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
如果我在IRQ模式下保存了lr_usr(返回时也恢复usr_ulr),那么代码现在就可以了。我之前发布的代码在任务调用某些func时不会生效,如果func被中断,而func尚未完成,并且时钟中断会更改当前的函数,中断返回后,LR不是正确的LR如果我在IRQ模式下保存了LR_usr,代码现在就可以了(返回时也恢复usr_LR)。如果任务调用某个func时中断了func,并且时钟中断更改了当前的func,那么我之前发布的代码将无法执行,在中断返回后,LR不是正确的LR。代码在我看来还行,但它完全取决于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。代码在我看来还行,但它完全取决
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