0
votes

I am facing an issue related to Return-From-Interrupt when the IRQ interrupted a load/store multiple instruction.

When the IRQ interrupts a load/store multiple instruction, the ICI field of EPSR indicates that the LDM/STM instruction should be continued on the return from interrupt.

On interrupt entry exception frame(containing caller saved context) is stored on the current stack automatically by the hardware.

In my case, Kernel Software then saves the Callee saved context and prepares a new context, which includes a dummy exception frame on the stack. After preparing the new context the BX LR instruction is executed which pops the dummy exception frame. As the dummy exception frame contains the return-address(return address is pointing to new interrupt handler), execution goes to new interrupt handler.

In this case, if the interrupted instruction was an LDM/STM instruction I get a USAGE-FAULT exception with INVSTATE, because hardware on return-from-interrupt is expecting the appropriate LDM/STM instruction, while the return address is a different location in my case.

The ARM-Architecture Reference Manual mentions three design options that can be implemented for CortexM.

In the Instruction Set Attribute Register 2(ID_ISAR2), bits[11:8]:

  1. None supported. This means the LDM and STM instructions are not interruptible. ARMv7-M reserved.
  2. LDM and STM instructions are restartable.
  3. LDM and STM instructions are continuable.

My hardware is implemented with option 3.

What I am unable to understand is, if I force the ICI field of IPSR to 0, will my LDM/STM instruction be restarted or will I still get an exception?

And even if it gets restarted(considering the interrupted STM instruction) will it push on top of already partially pushed registers, corrupting the stack eventually in this case or will it adjust the stack pointer before restarting the operation.

1

1 Answers

2
votes

The ICI/IT field is part of EPSR, not IPSR, not that it makes a huge amount of difference if you're interacting with xPSR.

If an STM or LDM instruction is interrupted, EPSR is set to indicate the point from which the execution can continue, and then exception entry is triggered. It is therefore the stacked PSR value that contains this information, just as it contains the Thumb bit from the interrupted code. If your new context has zero in the ISI bits of the stacked PSR, you should not see a usage fault exception for the reasons you give. (In the absence of any code, I can't really be more specific than this.)

If LDM and STM are implemented as restartable or continuable, then no, the stack will not be corrupted by this process. (That would be a nightmare!) If LDM and STM are restartable then the stack pointer is simply reset to the value it had at the start of the LDM/STM and the instruction is executed anew; if they are continuable then the stack pointer is not modified but a partial STM/LDM is performed to complete the instruction.

You don't mention exactly how you're achieving a context switch, but I assume you are manually pushing r4-r11 to the process stack, then saving the PSP somewhere and updating it to point to the new context on a different stack, before popping r4-r11 and triggering an exception return - that's certainly the usual way to go about it.