interruptcortex-m

How does BX LR work on an exception return in cortex-M processor?


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.

enter image description here

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?

enter image description here


Solution

  • 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:

    enter image description here

    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.