我正在尝试使用CodeSourcery GCC工具链为Cortex-M编写一个准系统循环调度程序。我的调度程序使用SysTick在时间片到期后触发中断,并且上下文切换发生在ISR内部。为了简单起见,我只使用主堆栈指针(MSP)来处理所有事情。
我一直在决定如何处理在Cortex-M3上加载新上下文。根据Cortex-M3技术参考手册(TRM),该过程将PC,LR和状态寄存器推送到ISR条目上的当前堆栈。
如果我推动其余的寄存器来保存当前任务的上下文并从下一个任务的控制块加载一个新的SP值,我将如何恢复其余的上下文?
根据我的理解,我需要弹出我推送的寄存器(比如{r4-r11}),处理器将推出其余的(包括新任务(LR)和状态寄存器的返回地址) ISR返回时自动执行。所以我假设我只是在完成切换任务后才需要执行BX
?
以下是TRM上的内容:
当下列指令之一将值0xFFFFFFFX加载到PC时发生异常返回1)POP / LDM包括加载PC 2)LDR与PC作为目的地3)BX与任何寄存器。
如何加载EXC_RETURN值?我应该把它推到堆栈上(因为它应该是here)?假设我已经弹出了我通过软件推送的寄存器,那么Cortex如何弹出已保存的寄存器呢?一般来说,如何恢复任务的上下文?
我已经尝试过阅读TRM和其他ARM参考文献,但它们似乎不清楚。
答案 0 :(得分:13)
答案 1 :(得分:2)
稍后在#ARM IRC频道上阅读了一些内容和一些帮助,我能够理解异常返回机制。这是我的理解。
如CM3 TRM中所述,当注册异常时,内核将寄存器r0-r3,r12以及状态LR和PC一起打开到当前进程堆栈。因此,在异常进入时,堆栈包含8个单词,其中包括包含要返回的地址的LR。硬件弹出机制基本上反转相同的动作,即它弹出最后8个字,在此期间它将LR加载到PC中以返回到被中断的功能。
因此,可以简单地通过将堆栈指针移动到适当的位置来切换上下文,使得当前堆栈帧类似于刚被中断的任务的堆栈帧,即包含相同顺序的确切单词。在异常进入时以及将寄存器保存到堆栈之后,LR将加载EXC_RETURN值。该值包含指示返回条件的特殊状态标志。这也用于指示中断的结束。也就是说,如果ISR需要返回任务并将堆栈指针从当前(MSP)切换到PSP,则可以使用适当的EXC_VALUE(在TRM中指示)加载LR并简单地执行BX LR
切换状态。
答案 2 :(得分:2)
这是一个代码片段,可以完全满足您的需求 - https://github.com/DISTORTEC/distortos/blob/master/source/architecture/ARM/ARMv7-M/ARMv7-M-PendSV_Handler.cpp - 它的工作方式与您所描述的相同: