1
.macro      SAVE_CONTEXT      SWI_F
    ldr     sp,=current_p               /* switch to pcb */
    ldr     sp,[sp]                     /* get pcb ptr */
    add     sp,sp,#68                   /* point to top of stack */
.if (\SWI_F == 0)                       /* if it is not swi macro */
    sub     lr,lr,#0x04                 /* return addr */
.endif                                  /* lr -= 4 if not swi */
    stmdb   sp!,{lr}
    stmdb   sp!,{r0-r12,lr}             /* prepare to return */ 
    mrs     r1,spsr                     /* r1 <- spsr_usr */
    mrs     r2,cpsr                     /* r2 <- cpsr */
    push    {r1}                        /* save spsr_usr */
    msr     cpsr_c,#SYS_MODE|NO_INTR    /* switch to sys mode */
    mov     r3,sp                       /* r3 <- sp_usr */
    msr     cpsr,r2                     /* switch back */
    push    {r3}                        /* save sp_usr */
    mov     r0,lr                       /* r0 <-- lr */
    msr     cpsr_c,#SVC_MODE|NO_INTR    /* switch back to SVC mode */
    ldr     sp,=KERNEL_STACK            /* switch to SVC stack */
.endm

.macro      SET_ISR_PROC     ISR_PROC   /* */
    ldr     lr,=__restart               /* set return address */
    ldr     pc,=\ISR_PROC               /* call ISR */
.endm

__restart:                              /* restore context */
    ldr     sp,=current_p               /* get pcb */
    ldr     sp,[sp]                     /* adjust back to pcb */
re_restart:                             /* ret from kernel */
    pop     {r3}                        /* r3 <- sp_usr */
    mrs     r2,cpsr                     /* r2 <- cpsr */
    msr     cpsr_c,SYS_MODE|NO_INTR     /* switch to sys mode*/
    mov     sp,r3                       /* sp_usr <-- r3 */
    msr     cpsr,r2                     /* switch back */
    pop     {r1}                        /* r1 <- spsr_usr */
    msr     spsr,r1                     /* restore spsr */
    ldmia   sp!,{r0-r12,lr,pc}^         /* intr ret */

_do_irq:
    SAVE_CONTEXT    0                   /* not swi */
    SET_ISR_PROC    do_irq

当我只有一个任务时,这个任务切换代码在我的 s3c2440 板上运行良好,但是当创建两个或更多任务时,task0 将执行 task1 代码或 task 1 执行 task0 代码,我不知道为什么,任何帮助是需要 !

4

1 回答 1

1

现在代码没问题,因为我在 IRQ 模式下保存了 lr_usr(返回时也恢复 usr_lr)。我之前发布的代码在任务调用某些 func 时将不起作用,如果 func 被中断而 func 尚未完成,并且时钟中断改变current_p,中断返回后LR不是正确的lr

于 2013-05-09T01:56:25.080 回答