Arm 任务切换没有';不行 .macro保存上下文开关 ldr sp,=当前_p/*切换到pcb*/ ldr sp,[sp]/*获取pcb ptr*/ 将sp、sp、#68/*点添加到堆栈顶部*/ .if(\SWI_F==0)/*如果不是SWI宏*/ 子lr,lr,#0x04/*返回地址*/ .endif/*lr-=4(如果不是swi)*/ stmdb sp!,{lr} stmdb sp!,{r0-r12,lr}/*准备返回*/ mrs r1,spsr/*r1

Arm 任务切换没有';不行 .macro保存上下文开关 ldr sp,=当前_p/*切换到pcb*/ ldr sp,[sp]/*获取pcb ptr*/ 将sp、sp、#68/*点添加到堆栈顶部*/ .if(\SWI_F==0)/*如果不是SWI宏*/ 子lr,lr,#0x04/*返回地址*/ .endif/*lr-=4(如果不是swi)*/ stmdb sp!,{lr} stmdb sp!,{r0-r12,lr}/*准备返回*/ mrs r1,spsr/*r1,arm,task-switching,Arm,Task Switching,如果我在IRQ模式下保存了lr_usr(返回时也恢复usr_ulr),那么代码现在就可以了。我之前发布的代码在任务调用某些func时不会生效,如果func被中断,而func尚未完成,并且时钟中断会更改当前的函数,中断返回后,LR不是正确的LR如果我在IRQ模式下保存了LR_usr,代码现在就可以了(返回时也恢复usr_LR)。如果任务调用某个func时中断了func,并且时钟中断更改了当前的func,那么我之前发布的代码将无法执行,在中断返回后,LR不是正确的LR。代码在我看来还行,但它完全取决

如果我在IRQ模式下保存了lr_usr(返回时也恢复usr_ulr),那么代码现在就可以了。我之前发布的代码在任务调用某些func时不会生效,如果func被中断,而func尚未完成,并且时钟中断会更改当前的函数,中断返回后,LR不是正确的LR

如果我在IRQ模式下保存了LR_usr,代码现在就可以了(返回时也恢复usr_LR)。如果任务调用某个func时中断了func,并且时钟中断更改了当前的func,那么我之前发布的代码将无法执行,在中断返回后,LR不是正确的LR。代码在我看来还行,但它完全取决于
current\u p
中存储的内容,因此我会在那里查看。您有一个全局
current\u p
,并使用
ldr sp,=内核堆栈
,因此代码不是可重入的。更正常的方法是在上下文开关上切换SVC堆栈。然后可以使用
sp\u svc&0xfffffc00
来获取当前值。也就是说,每个进程的主管堆栈是独立的,它还保存任务还原信息。对于标准ARM MMU页面大小,stack plus任务结构保持在4k;如果您在没有MMU的情况下运行,则可以使用任何尺寸。您还可以使用小页面、多页面等。您可以使用
sp_irq
作为暂存寄存器。在所有条目例外情况下,切换到svc模式。+1我看到有人投了反对票。但是,至少您标记了一个实际上是ARM代码的ARM问题。我想有人希望多做点工作来说明你做了什么/没有做什么。您应该查看和/或其他许多开源项目,以获得一些想法。ARM参考手册中的第9.6.5章上下文切换也可能有用。显然,用常量重新加载堆栈会破坏堆栈的用途。最终,您会遇到多个异常,需要几个帧。如果我在IRQ模式下保存了lr_usr(返回时也恢复usr_lr),代码现在就可以了。如果函数被中断,且函数尚未完成,并且时钟中断更改了当前的函数,那么我之前发布的代码在任务调用某些函数时将无法运行,LR不是中断后返回的正确LR。谢谢你给我这么好的建议。代码在我看来还行,但这一切都取决于
current\u p
中存储的内容,所以我会在那里查看。你有一个全局
current\u p
并使用
ldr sp,=内核堆栈
,因此代码不是可重入的。更正常的方法是在上下文开关上切换SVC堆栈。然后可以使用
sp\u svc&0xfffffc00
来获取当前值。也就是说,每个进程的主管堆栈是独立的,它还保存任务还原信息。对于标准ARM MMU页面大小,stack plus任务结构保持在4k;如果您在没有MMU的情况下运行,则可以使用任何尺寸。您还可以使用小页面、多页面等。您可以使用
sp_irq
作为暂存寄存器。在所有条目例外情况下,切换到svc模式。+1我看到有人投了反对票。但是,至少您标记了一个实际上是ARM代码的ARM问题。我想有人希望多做点工作来说明你做了什么/没有做什么。您应该查看和/或其他许多开源项目,以获得一些想法。ARM参考手册中的第9.6.5章上下文切换也可能有用。显然,用常量重新加载堆栈会破坏堆栈的用途。最终,您会遇到多个异常,需要几个帧。如果我在IRQ模式下保存了lr_usr(返回时也恢复usr_lr),代码现在就可以了。如果函数被中断,且函数尚未完成,并且时钟中断更改了当前的函数,那么我之前发布的代码在任务调用某些函数时将无法运行,在中断返回后,LR不是正确的LR。谢谢你给我这么好的建议^_^
.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