当IRQ中断加载/存储多条指令时,我面临与中断返回相关的问题。
当IRQ中断加载/存储多条指令时,EPSR的ICI字段指示从中断返回时应继续执行LDM / STM指令。
在中断进入异常帧(包含调用者保存的上下文)上,硬件会自动将其存储在当前堆栈中。
在我的情况下,内核软件然后保存Callee保存的上下文并准备一个新的上下文,该上下文包括堆栈上的虚拟异常帧。 在准备了新的上下文之后,将执行BX LR指令,该指令弹出虚拟异常帧。由于伪异常帧包含返回地址(返回地址指向新的中断处理程序),因此执行转到新的中断处理程序。
在这种情况下,如果被中断的指令是LDM / STM指令,我会收到INVSTATE的USAGE-FAULT异常,因为从中断返回的硬件期望使用适当的LDM / STM指令,而返回地址是我的位置不同。
《 ARM体系结构参考手册》提到了可以为CortexM实现的三个设计选项。
在指令集属性寄存器2(ID_ISAR2)中,位[11:8]:
我的硬件通过选项3实现。
我无法理解的是,如果我将IPSR的ICI字段强制设为0, 我的LDM / STM指令会重新启动还是会出现异常?
即使重新启动(考虑到中断的STM指令),它也会推入已经部分推入的寄存器的顶部,在这种情况下最终会破坏堆栈,或者会在重新开始操作之前调整堆栈指针。
答案 0 :(得分:2)
“ ICI / IT”字段是EPSR的一部分,而不是IPSR,并不是与xPSR进行交互会产生巨大的差异。
如果STM或LDM指令被中断,则将EPSR设置为指示可以从其继续执行的点,然后触发 then 异常条目。因此,堆叠的PSR值包含此信息,就像它包含中断代码中的Thumb位一样。如果新上下文的堆栈式PSR的ISI位为零,则由于给出的原因,您不应看到使用错误异常。 (在没有任何代码的情况下,我真的不能比这更具体。)
如果LDM和STM被实现为可重新启动或可延续,则不会,堆栈不会被此过程破坏。 (这将是一场噩梦!)如果LDM和STM可重新启动,则将堆栈指针简单地重置为LDM / STM开始时的值,然后重新执行该指令;如果它们是连续的,则不修改堆栈指针,而是执行部分STM / LDM来完成指令。
您没有确切说明如何实现上下文切换,但我假设您是手动将r4-r11
推入进程堆栈,然后将PSP保存在某个位置并更新它以指向新的上下文一个不同的堆栈,然后弹出r4-r11
并触发异常返回-这当然是解决该问题的常用方法。