Search code examples
assemblyarminterruptcortex-m

Cortex-M3: Changing Interrupt Return Address


I need to edit the return address of an ISR. The ISR should return to a specific address after the interrupt is handled, regardless of where it came from. This is to facilitate a fast system reset. This functionality can't be implemented in the normal firmware as timing is too tight to check a flag somewhere frequently.

I've tried editing the stack frame that is saved by the ISR upon exception entry, which seems to work for a few milliseconds, then it enters the micro's "Oh shit something went bad" state. In this state, the stack looks normal, and there are no signs that anything went wrong. This occurs even if I pop the stack and push exactly the same data back onto it. Also, using a stack-pointer-relative store causes this failure.

Info about exception handling can be found here, but I can't find enough info to tell me whats going wrong.

Ideas? I really just need to get the interrupt to return to the same label regardless of where the interrupt hits, and without the core getting all fussy.

Thanks, Stuart


Solution

  • A word of warning: this project was written in assembly with a lot of assumptions. This process is probably unsafe in C or assembly where you don't know exactly what the state of the CPU will be when the interrupt hits.

    After messing around with the stack frame for a while I realized that the saved status register (xPSR) had some bits set that I hadn't seen set during operation. It turns out that the interrupt was sometimes firing in the middle of a LDM or STM command. The Cortex-M3 has functionality to save the state of these commands so that they can be resumed properly. Teh problem arose when it would return from the interrupt to my specified location expecting to finish a LDM/STM command, but could not.

    In order to solve this problem, I merely had to clear the ICI bits in the saved status register in the stack frame. This made the Cortex-M3 "forget" that it was handling a LDM/STM command, and allowed the processor to return to an arbitrary location without consequence.