On an exception entry, a ARMv7-M processor will do below things as the last step of stack pushing.
if CurrentMode==Mode_Handler then
LR = Ones(28):'0001'; <=== This is not a valid address
else
LR = Ones(29):CONTROL.SPSEL:'01'; <=== This is not a valid address
On an exception return, according to this video, the BX LR
instruction is executed as the last step to return to interrupted code location.
According to the ARMv7-M ARM:
BX can also be used for an exception return.
And:
An exception return occurs when the processor is in Handler mode and one of the following instructions loads a value of 0xFXXXXXXX into the PC:
- POP/LDM that includes loading the PC.
- LDR with PC as a destination.
- BX with any register. <===== we are using this approach
And for the BX instruction, the ARMv7-M ARM says:
BX Specifies the register that contains the branch target address and instruction set selection bit.
So if we use LR
for the BX
instruction, the LR
should contain the branch target address.
But clearly the LR value prepared on the exception entry is not a valid branch target address (see the beginning of this question).
So how could the ISR return back to the interrupted location?
And since the cortex-M NVIC hardware automatically push/pop the context to/from the stack, which include the ReturnAddress
, why do we still need to branch to an invalid address with the BX
instruction?
OK maybe I can explain it now.
The ARMv7 ARM says this about the exception return:
An exception return occurs when the processor is in Handler mode and one of the following instructions loads a value of 0xFXXXXXXX into the PC:
POP/LDM that includes loading the PC.
LDR with PC as a destination.
BX with any register.
So the value writing to PC is just a 32-bit pattern beginning with 0xF
. According to spec:
Bits[31:28] 0xF. This value identifies the value in a PC load as an EXC_RETURN value.
And the LR after a exception entry contains below values:
if CurrentMode==Mode_Handler then
LR = Ones(28):'0001';
else
LR = Ones(29):CONTROL.SPSEL:'01';
It is 0xF1
, 0xF9
or 0xFD
, which correspond to below definitions in the spec:
The entry in the Return stack column is the stack that holds the information that the processor must restore as part of the exception return sequence. This is also the stack the processor will use after returning from the exception.
The 0xFXXXXXXX
address is a special:
If an EXC_RETURN value is loaded into the PC when in Thread mode, or from the vector table, or by any other instruction, the value is treated as an address, not as a special value. The 0xFXXXXXXX address range, that includes all possible EXC_RETURN values, has Execute Never (XN) permissions, and loading this value causes a MemManage exception, or an INVSTATE UsageFault exception, or escalation of the exception to a HardFault.
So basically, BX LR
is just a trigger of the stack poping.