首页 > 解决方案 > CortexM 上的中断加载倍增/存储倍增

问题描述

当 IRQ 中断加载/存储多条指令时,我面临与 Return-From-Interrupt 相关的问题。

当 IRQ 中断一条加载/存储多条指令时,EPSR 的 ICI 字段指示 LDM/STM 指令应在中断返回时继续执行。

在中断入口异常帧(包含调用者保存的上下文)由硬件自动存储在当前堆栈中。

在我的例子中,内核软件然后保存被调用者保存的上下文并准备一个新的上下文,其中包括堆栈上的一个虚拟异常帧。准备好新上下文后,执行 BX LR 指令,弹出虚拟异常帧。由于虚拟异常帧包含返回地址(返回地址指向新的中断处理程序),执行转到新的中断处理程序。

在这种情况下,如果被中断的指令是 LDM/STM 指令,我会得到一个带有 INVSTATE 的 USAGE-FAULT 异常,因为从中断返回的硬件需要适当的 LDM/STM 指令,而返回地址是不同的位置我的情况。

ARM-Architecture Reference Manual 提到了可以为 CortexM 实现的三个设计选项。

在指令集属性寄存器 2(ID_ISAR2) 中,位 [11:8]:

  1. 不支持。这意味着 LDM 和 STM 指令不可中断。ARMv7-M 保留。
  2. LDM 和 STM 指令是可重新启动的。
  3. LDM 和 STM 指令是可连续的。

我的硬件是使用选项 3 实现的。

我无法理解的是,如果我将 IPSR 的 ICI 字段强制为 0,我的 LDM/STM 指令会重新启动还是会出现异常?

即使它重新启动(考虑到中断的 STM 指令),它也会压入已经部分压入的寄存器之上,在这种情况下最终会破坏堆栈,或者它会在重新启动操作之前调整堆栈指针。

标签: exceptioninterrupt-handlingcortex-marmv7

解决方案


ICI/IT 字段是 EPSR 的一部分,而不是 IPSR,并不是说如果您与 xPSR 交互,它会产生巨大的差异。

如果 STM 或 LDM 指令被中断,EPSR 被设置为指示可以继续执行的点,然后触发异常进入。因此,堆栈的 PSR 值包含此信息,就像它包含中断代码中的 Thumb 位一样。如果您的新上下文在堆叠 PSR 的 ISI 位中为零,则由于您给出的原因,您不应该看到使用错误异常。(在没有任何代码的情况下,我真的不能比这更具体了。)

如果 LDM 和 STM 实现为可重新启动或可继续,则否,堆栈不会被此进程破坏。(那将是一场噩梦!)如果 LDM 和 STM 是可重新启动的,那么堆栈指针会简单地重置为它在 LDM/STM 开始时的值,然后重新执行指令;如果它们是可连续的,则堆栈指针不会被修改,但会执行部分 STM/LDM 以完成指令。

您没有确切提及如何实现上下文切换,但我假设您正在手动推r4-r11送到进程堆栈,然后将 PSP 保存在某处并更新它以指向不同堆栈上的新上下文,然后再弹出r4-r11和触发异常返回 - 这当然是通常的方法。


推荐阅读