Chapter2 Details of the Exception Handling
In the last chapter, I have covered a little about stack, in this chapter, I’ll focus on the details of the exception handling sequences, expecially the stacking and unstacking operations, details about the EXC_RETURN code, which is used for switching task. And I won’t mention how to set up NVIC and the types of exceptions available, if you are interested in it, please search it online. All the information I’ll mention in this blog will focus on Embedded Operating Systems.
Normaly, when we develop a code which don’t base on OS, we don’t pay attention to the stacking and unstacking. However, it is a important part for OS or debugging when a corruption happened. So let’s started by introducing the mechanism.
Information about Stacking and Unstacking when Exception Handlers
A C function can modify R0 to R3(which is used for passing input parameter, R0 also can be used for passing return result, If the return value is 64 bits, R1 will also be used as the return result), R12, R14 (LR), and PSR.The program code that calls a subroutine needs to save these register contents into memory before the function call if these values will still be needed after the function call. Register values that are not required after the function call don’t have to be saved. If the C function needs to use R4 to R11, it should save these registers on to the stack memory and restore them before the end of the function.
But why the programmer don’t pay attention to stacking and unstacking when they develop a code which don’t base on OS, it beacuse the exception mechanism save R0 to R3, R12, LR, and PSR at exception entrance automatically, and restore them at exception exit under the control of the processor’s hardware. It makes the register is the same between interrupt return and entry.
The block of data that are pushed to the stack memory at exception entrance is called
a stack frame. As I said, stacking and unstacking deal by processor’s automatically, but what do the Stack frames look like? When programmer get the stack, how can they analyse the data? The follow figure show what the stack frames look like. So when debug, we can get the start address of stack memory by the MSP or PSP, and then we can get where the last sentence which is pointed by LR, and get whether the parameter is right or not.
But for storing and restoring stack frame, paying attention to double-word aligned or exit boundary is necessary. To achieve this, processors can insert an additional word of padding space in the stack automatically if the stack pointer was not aligned to double-word location when the interrupt happened. The bit 9 of the stacked xPSR is used to indicate if the value of the stack pointer has been adjusted.
How the function return
Here, I just introduce how the exception handlers return.
As the processor enters the exception handler or Interrupt Service Routine (ISR), the
value of the Link Register (LR) is updated to a code called EXC_RETURN. The
value of this code is used to trigger the exception return mechanism when it is loaded
into the Program Counter (PC) using BX, POP, or memory load instructions (LDR or
LDM).
Stacking
The processor stacks the PC and xPSR first, this can make sure we can store the real secne, or store other register can broke the PC and xPSR.
There are two situation when stack: Using MSP and Using PSP.
For MSP(bit 1 of the CONTROL register is 0, as in the default setting), the stacking operation is carried out in the main stack with MSP. After entering Handler mode, the processor must be using the MSP, so the stacking operation of all nested interrupts are carried out with the main stack with MSP.
For PSP(bit 1 of the CONTROL register is 1),the stacking operation is carried out in the main stack with PSP.
Unstacking
When stacking, we can get which SP we can use by CONTROL regiser. But for unstacking, how can we know which SP can we use?
At the end of an exception handler, the bit 2 of the EXC_RETURN value generated
at the exception entrance is used to decide which stack pointer should be used to
extract the stack frame. If bit 2 is 0, the processor knows that the main stack was
used for stacking. If bit 2 is 1, the processor knows that the process stack was used for stacking, as shown in the second unstacking operation.
Reference: The Definitive Guide to ARM Cortex-M3 and Cortex-M4 Processors, 3rd Edition