I am developing an embedded application on an STM32F427. This MCU is using the ARM Cortex M4F core.
I am currently working on a debug tool, where it keeps a snapshot of the CPU state during a crash for later analysis. Specifically I am interested on what was the last instuction executed, before the error handler was called.
Initially I though that I can just log the value of the LR, as after the handler returns this is going to be the new PC. But I realized that this is not always the case.
I found out that in some cases indeed my handler works. The compiler calls the function with:
bl 0x60238
And then, the function returns with:
bx lr
Just as I was expecting.
However, in some other cases the compiler calls the function with:
bl 0x60250
Then the function performs:
push {r7, lr}
And then it returns with:
pop {r7, pc}
In the later case, since the LR may be used for another nested function call, the contents are overwritten and I lose the needed information.
Why is GCC producing such code, and why isn't code generated for a function call always the same? Taking the above into consideration, is there any other way to achieve what I want?
EDIT In my case a "system crash" may have numerous causes. This is why I am trying to read the actual register contents, providing a generic solution in my problem. Same cases may be:
- Call to hardfault handler, or any other exception.
- Failed assertion.
- Error condition detected during normal execution. A specific function called to restore the system.