Entry and Exit of Exception for ARM Cortex-M4 : The ARM Cortex-M4 processor is a popular microcontroller core used in embedded systems. One of its powerful features is how it handles exceptions—events that disrupt the normal flow of a program, such as interrupts, faults, or system calls.
Understanding how the Cortex-M4 enters and exits exceptions is crucial for writing reliable embedded software. This guide will walk you through the basics in a simple way.
Entry and Exit of Exception for ARM Cortex-M4
What Is an Exception?
An exception is a special event that temporarily interrupts the normal execution of a program to handle something urgent or important. Examples include:
- Interrupts (external signals, like a button press or sensor input)
- Faults (like memory access errors)
- System calls (requests for OS services)
When an exception occurs, the processor needs to:
- Save the current program state
- Jump to the exception handler code
- Run the handler
- Restore the saved state and resume normal execution
Cortex-M4 Exception Entry: What Happens When an Exception Occurs?
When an exception is triggered, the Cortex-M4 does the following steps automatically in hardware:
1. Complete the Current Instruction
The processor finishes executing the current instruction before responding to the exception.
2. Save Context on the Stack (Automatic Stacking)
To safely pause your program, the processor saves some important registers on the current stack (either Main Stack Pointer (MSP) or Process Stack Pointer (PSP)):
R0
toR3
(general-purpose registers)R12
LR
(Link Register)PC
(Program Counter)xPSR
(Program Status Register)
This saved context is called the Exception Stack Frame. Saving these registers means the processor remembers exactly where it left off.
3. Load the Exception Handler Address
The processor reads the address of the exception handler (from the Vector Table) and jumps to it. The handler is just a special function in your code that deals with the exception.
4. Change Processor State
The processor sets some internal flags to indicate it’s now running in Handler Mode (instead of Thread Mode).
Cortex-M4 Exception Exit: Returning to Normal Execution
When the exception handler finishes, it needs to return control back to the original program. This happens by executing the BX LR
or returning from the handler function.
Here’s what happens during exit:
1. Restore Context (Automatic Unstacking)
The processor automatically restores the saved registers (R0-R3
, R12
, LR
, PC
, xPSR
) from the stack. This means the program state is back exactly as it was before the exception.
2. Return to Thread Mode
The processor switches back from Handler Mode to Thread Mode, resuming normal program execution.
Key Points to Remember
Step | What Happens | Cortex-M4 Feature |
---|---|---|
Exception Entry | Save CPU registers on stack | Automatic stacking mechanism |
Jump to exception handler address | Vector Table lookup | |
Switch to Handler Mode | Hardware-controlled | |
Exception Handler Run | Execute the exception service routine | Software-defined |
Exception Exit | Restore CPU registers from stack | Automatic unstacking |
Return to the exact instruction in program | Resume Thread Mode |
Visual Overview
Normal Program Execution
↓
Exception Occurs
↓
[Automatic save registers on stack]
[Jump to Handler]
Exception Handler runs
↓
[Automatic restore registers from stack]
[Return to Normal Execution]
Why Is This Important?
- Automatic stacking/unstacking saves you from writing complex assembly code.
- You can rely on hardware to preserve the state of your program.
- Understanding this flow helps you write safe and efficient interrupt handlers.
- Helps in debugging exceptions and faults by knowing what the processor does internally.
Complete basic example of handling an external interrupt on an STM32F4
- GPIO configuration for a button input
- EXTI (external interrupt) setup on that GPIO pin
- NVIC interrupt enabling
- The actual interrupt handler code
Complete Example: GPIO Button Interrupt on STM32F4 (Cortex-M4)
Assumptions:
- You have STM32Cube HAL library or similar to handle low-level register operations (for simplicity).
- Button connected to GPIOA Pin 0.
- LED connected to GPIOG Pin 13 (just for indication).
1. Include headers and define pins:
#include "stm32f4xx.h" // Device header, adjust for your MCU
#include "stm32f4xx_hal.h" // HAL header for STM32
2. GPIO and EXTI Initialization:
void GPIO_EXTI_Init(void)
{
// Enable GPIOA and GPIOG clocks
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE();
// Configure PA0 as input with pull-up (Button pin)
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING; // Interrupt on rising edge (button press)
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// Configure PG13 as output (LED pin)
GPIO_InitStruct.Pin = GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // Push-pull output
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
// Enable and set EXTI line 0 Interrupt to the lowest priority
HAL_NVIC_SetPriority(EXTI0_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(EXTI0_IRQn);
}
3. Interrupt Handler Function
void EXTI0_IRQHandler(void)
{
// Check if EXTI line 0 caused the interrupt
if(__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_0) != RESET)
{
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_0); // Clear the interrupt flag
// Toggle LED on PG13
HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_13);
}
}
4. Main Function Example
int main(void)
{
HAL_Init(); // Initialize HAL Library
SystemClock_Config(); // Configure system clock (user-defined, MCU specific)
GPIO_EXTI_Init(); // Initialize GPIO and EXTI
while(1)
{
// Main loop can do other stuff
}
}
Explanation:
GPIO_EXTI_Init()
configures the button pin as an input interrupt source and sets up the LED pin as output.HAL_NVIC_EnableIRQ(EXTI0_IRQn)
enables the EXTI0 interrupt in the Nested Vector Interrupt Controller.- When the button connected to PA0 is pressed (rising edge), the Cortex-M4 automatically:
- Pushes registers on the stack (exception entry)
- Jumps to
EXTI0_IRQHandler
- The handler clears the interrupt flag and toggles the LED.
- On return, the processor restores the registers and resumes normal execution.
What is EXC_RETURN
?
In ARM Cortex-M (e.g., Cortex-M4), when an exception (like an interrupt or fault) occurs, the processor automatically saves some registers and branches to an exception handler.
When the handler finishes, the processor restores context using a special magic value called EXC_RETURN, which is loaded into the Program Counter (PC). This value tells the processor how to restore context and return to the previous state.
Breakdown of EXC_RETURN
Values (from the image)
Value | Meaning |
---|---|
0xFFFFFFF1 | Return to Handler Mode, use Main Stack Pointer (MSP), no FPU context |
0xFFFFFFF9 | Return to Thread Mode, use MSP, no FPU context |
0xFFFFFFFD | Return to Thread Mode, use Process Stack Pointer (PSP), no FPU context |
0xFFFFFFE1 | Return to Handler Mode, use MSP, with FPU context |
0xFFFFFFE9 | Return to Thread Mode, use MSP, with FPU context |
0xFFFFFFED | Return to Thread Mode, use PSP, with FPU context |
Bitwise Meaning (EXC_RETURN is 32-bit value)
Only the lower 5 bits are meaningful:
Bit | Meaning |
---|---|
0 | Always 1 |
2 | 1 = Return to Thread mode, 0 = Handler mode |
3 | 1 = Use PSP, 0 = Use MSP |
4 | 1 = FPU context present, 0 = No FPU context |
Example
If EXC_RETURN
= 0xFFFFFFFD
(binary ends in 11111111111111111111111111111101
):
- Bit 2 = 1 → Return to Thread mode
- Bit 3 = 1 → Use PSP
- Bit 4 = 0 → No FPU context
Why is this important?
When writing custom context switchers, RTOS code, or exception handlers (like SVC
or PendSV), the correct EXC_RETURN
value ensures the system:
- Restores the right registers
- Returns to the correct mode
- Uses the correct stack
- Handles FPU state (if available and used)
What is EXC_RETURN
?
EXC_RETURN
is a special constant value loaded into Link Register (LR) during exception entry.- This value tells the processor how to restore the previous context when returning from the exception (which stack to use, which mode to return to, whether FPU state is involved).
When is EXC_RETURN
Generated?
It is not stored in the LR by your C code—it is done automatically by the processor.
🔹 During exception entry, the processor puts an
EXC_RETURN
value into LR instead of the return address (like normal function calls do).
So, when the handler finishes, and you do BX LR
, the processor interprets LR as EXC_RETURN
and uses that info to exit the exception properly.
Full Exception Entry Sequence (Step-by-Step)
1. Pending Bit is Set
- An interrupt/exception is pending (from NVIC or system fault).
2. Stacking and Vector Fetch
- Processor automatically saves the current execution context (R0–R3, R12, LR, PC, xPSR) onto the current stack (MSP or PSP).
- Then, it fetches the exception vector from the vector table.
3. Entry into the Handler and Active Bit Set
- Processor enters the exception handler.
- The corresponding Active bit is set (in the Interrupt Control State Register, ICSR).
4. EXC_RETURN
Value is Placed in LR
- Instead of storing the normal return address, the processor stores a special
EXC_RETURN
value in LR to indicate how to resume execution. For example:LR = 0xFFFFFFFD // Return to Thread mode, use PSP, no FPU
🔸 5. Pending Bit is Cleared Automatically
- As soon as the processor starts executing the exception handler, the Pending bit is cleared (except for some faults like NMI).
🔸 6. Processor Mode is Now Handler Mode
- The CPU switches from Thread mode to Handler mode.
- Execution privileges may change (Handler is usually in privileged mode).
🔸 7. MSP is Used
- The Main Stack Pointer (MSP) is automatically selected and used for stack operations during the handler, unless you manually configured to use PSP.
🔚 What Happens at Exception Return?
- The handler ends by executing:
BX LR
- The processor checks the
EXC_RETURN
value in LR and:- Determines which mode to return to (Thread or Handler)
- Decides which stack to use (MSP or PSP)
- Checks whether to restore FPU state (if applicable)
- The processor pops the stack to restore R0-R3, R12, LR, PC, and xPSR.
Summary Table: Common EXC_RETURN
Values
Value | Mode Return | Stack Used | FPU Context |
---|---|---|---|
0xFFFFFFF1 | Handler | MSP | No |
0xFFFFFFF9 | Thread | MSP | No |
0xFFFFFFFD | Thread | PSP | No |
0xFFFFFFE1 | Handler | MSP | Yes |
0xFFFFFFE9 | Thread | MSP | Yes |
0xFFFFFFED | Thread | PSP | Yes |
Leave a Reply