Hi,
I think I am just getting confused with this even if (or because of) I read the book and manuals again and again.
At exception entry, the processor saves R0-R3, R12, LR, PC and PSR on the stack. Saving PC means that the address of the instruction to be executed next after return from the exception handler is saved on the stack. However, the documentation also says that LR is updated with EXC_RETURN and that when the EXC_RETURN value is loaded to the PC, the exception return sequence begins.
So, the confusion is - it is the stacked PC value which should be loaded to the PC to return to the place where it left to attend the exception handler. If the PC is loaded with EXC_RETURN value, it is not a valid address but that only the lower 5 bits indicate which stack was used and the return mode (thread/handler) etc.
Or is it that the loading of PC with EXC_RETURN is then followed up by loading of the PC with the stacked PC value?
Can someone please help clearing this confusion?
Thanks,
Gopal
To me, it looks like you've understood almost all of it correctly.
Loading PC with the value of LR is sufficient. LR already holds EXC_RETURN, and you do not have to worry about which stack you need to use; the EXC_RETURN in LR is pre-encoded with the correct value.
Normally you only have to change the EXC_RETURN value when you're writing a context-switcher.
This is what more or less happens:
The EXC_RETURN is actually one real cool feature of the Cortex architecture. It means that you do not have to have a RFI instruction (Return From Interrupt), as you use the standard "return-instruction" to return from an interrupt. So there's no real difference in writing an interrupt-routine and a normal subroutine for a Cortex-M based microcontroller.
I remember in the 80's (speaking about the M68xxx in particular), you would have to unstack some 'info-words', depending on which kind of interrupt occurred, and you'd have to make sure that the stack-frame had the correct format. Sometimes you'd have to modify the values on the stack, before returning, and if that wasn't enough, you had great chances that your interrupt would crash the entire system if you made a minor mistake.
It's not like that with an ARM Cortex-M microcontroller. The architecture makes your interrupt and exception handling much more robust; you don't have to worry too much about reentrancy, and if you're writing a context-switcher from scratch, ARM did most of it for you in hardware in advance.
Yes being able to write the interrupt routines as straightforward C functions is as you say real cool. And it explains the choice of registers which are stored, they are the ones the calling standard says a program is allowed to change without restoring on return. A good instance of the software and hardware working together.
View all questions in Cortex-M / M-Profile forum