2013-03-03 79 views
2

我在ARM926的先发制人操作系统(极简主义)中结束了,但我遇到了一些困难。恢复用户堆栈/寄存器

今天,我可以启动操作系统,切换到用户模式(使用它自己的stask)并在定时器中断后返回操作系统模式(SVC)。

但今天我试图在定时器中断之前的上下文中返回用户函数。

我做了什么: 我的初始化任务功能:

init_task(taskstruct * task, unsigned int* stack, void (*function)(void)){ 



    stack += STACK_SIZE;// - 16; /* End of stack, minus what we're about to push */ 
    //stack[0] = 0x10; /* User mode, interrupts on */ 
    //stack[1] = (unsigned int)function; 

    task->sp = stack; 

    task->sp[0] = task->registers[0]; // r0 
    task->sp[1] = task->registers[1];// = task->sp[3];//0; // r1 
    task->sp[2] = task->registers[2];// = task->sp[4];//0; // r2 
    task->sp[3] = task->registers[3];// = task->sp[5];//0; // r3 
    task->sp[4] = task->registers[4];// = task->sp[6];//0; // r4 
    task->sp[5] = task->registers[5];// = task->sp[7];//0; // r5 
    task->sp[6] = task->registers[6];// = task->sp[8];//0; // r6 
    task->sp[7] = task->registers[7];// = task->sp[9];//0; // r7 
    task->sp[8] = task->registers[8];// = task->sp[10];//0; // r8 
    task->sp[9] = task->registers[9];// = task->sp[11];//0; // r9 
    task->sp[10] = task->registers[10];// = task->sp[12];//0; // r10 
    task->sp[11] = task->registers[11];// = task->sp[13];//0; // r11 
    task->sp[12] = task->registers[12];// = task->sp[14];//0; // r12 
    task->sp[13] = (unsigned int)function; 
} 

的激活功能:

.global activate 
activate: 
    /* Save kernel state */ 
    STMFD sp!,{r1-r12,lr} 
    NOP 
    msr CPSR_c, SYS_MODE /* Sys mode with IRQ enabled and FIQ disabled*/ 
    mov sp, r0 /* MOVE TO THE STACK USER 
    /* LOAD THE TASK'S CONTEXT */ 
    mov ip, r0 
    LDMFD sp!, {r0-ip,lr} 
    NOP 
    mov pc, lr 

呼吁:

activate(task[0].sp); 
print_uart0("Kernel gets back control ! \n"); 
print_uart0("Load the next task ! \n"); 
activate(task[0].sp); 

我在irq_handler做什么:

irq_handler: 
/* Save the return value */ 
SUB ip,lr,#4 
BL event_irq_handler 

/* Save the user task context */ 
MSR CPSR_c, #INT_OFF|SYS_MODE 
MOV lr, ip 
STMFD sp!,{r0-ip,lr} 
NOP 
MOV r0, sp 
BL saveTaskContext 


/* Load kernel state */ 
MSR CPSR_c,SVC_MODE 
LDMFD sp!,{r1-r12,pc} 
NOP 

的savcontext功能:

int i = 0; 
//char printable = 0x00; 
/* UPDATE THE STACK TASK */ 
for (i = 0 ; i <= 13 ; i++){ 
    task[0].sp[i] = *(ptr+i); 
} 

但我的问题是,当我要求第二次激活(任务[0] .SP),其分支机构的任何地方,我的主要程序重新启动。

我在哪里错了?

问候,VincentB

+0

研究如何这样做... – vonbrand 2013-03-03 19:40:01

回答

0

我只是觉得在你的

for (i = 0 ; i <= 13 ; i++){ 
    task[0].sp[i] = *(ptr+i); 
} 

应该做这样?

for (i = 0 ; i <= 13 ; i++){ 
    task[0].sp[i] = (*ptr+i); 
} 

我想...你追加的ptr地址与i价值,但真的不知道

+0

(* ptr + 1)将返回ptr的值+ 1的值。*(ptr + 1)将通过ptr返回下一个值点 – deletMe 2013-03-03 15:09:17

1

这是确定的,长期艰苦的劳动后,我已经完成了找到解决方案!

最后的代码比原来很简单:

我只是改变代码的irq_handler,该代码的其余部分是一样的,我以前的帖子:其他操作系统

irq_handler: 
/* Save the return value */ 
SUB lr,lr,#4 
STMFD sp!, {r0-ip, lr}^ /* Save the user task context */ 
MOV r0, sp 
BL saveTaskContext 

BL event_irq_handler 


/* Load kernel state */ 
MSR CPSR_c,SVC_MODE 
LDMFD sp!,{r1-r12,pc} 
NOP 
相关问题