I am using STM32F746, an ARM cortex-M7 based processor. I am trying to do something hacky, which requires me to return to the program from a MemManage Fault handler.
When entering MemManage Fault handler, the PC before the fault and everything I need is stored on the stack. So I thought I can simply recover those to return to the previous execution point.
However, I cannot properly restore the xPSR
.
The previous CPSR
before the fault handler is saved in the stack, so I tried restoring it using MSR instruction.
I tried both MSR, xpsr, r12
and MSR, apsr, r12
However, it would only restore the flags and not the other parts of the CPSR
, such as the GE
or the system mode bits.
(and my mode bits seems also weird.. my xPSR
shows as: 0x61070004
, but this tells me that the last 5 bits cannot be 0x04
)
How can I go back to the program point before the fault handler? I also tried popping the pc but it does not work and I think the problem is CPSR not getting properly restored.
When a Cortex M7 enters an exception handler, the execution context is saved as follows and of course restored when exiting the handler (from ARM Cortex M7 Programming Manual):
As you see, the xPSR is restored after the return from exception.
Furthermore
faults are a subset of the exceptions.
You can do a simple test: dereference on purpose an unvalid pointer. It will trigger a HardFault. Modify your HardFault handler to just return and do nothing. You can check that the context is restored. I tried on STM32H753, it works fine, xPSR latest bits (ISR_NUMBER) are indeed 0 (thread mode).
Be careful though: I don't know for MemManage but HardFault returns to the very same instruction that triggered the fault (and not to the following instruction like a regular exception). It means you will execute again the same instruction after the Hardfault.