The Cortex-M is a family of ARM processor cores designed specifically for microcontroller applications. One of the key features of Cortex-M cores is their support for exceptions and interrupts.
An exception is an unexpected event that disrupts the normal flow of instruction execution in a processor. When an exception occurs, the processor immediately stops what it is currently doing and jumps to an exception handler routine to deal with the exception. This allows the processor to respond quickly to events that require urgent attention without having to poll for them constantly.
Types of Exceptions in Cortex-M
The Cortex-M processors support several types of exceptions:
- Reset: This occurs when the processor is reset, such as at power up. The processor will jump to the reset handler routine.
- NMI: The non-maskable interrupt (NMI) is the highest priority exception. It cannot be disabled by software and is used for critical events like memory errors.
- Hard fault: Generated for serious errors like a bus error or invalid instruction. This indicates a fatal problem.
- SVC: Triggered by the SVC instruction. Used to make secure supervisor calls to privileged software services.
- PendSV: The pending service call (PendSV) exception allows low priority tasks to preempt a running task without waiting.
- SysTick: The system tick timer generates this regularly to trigger OS task scheduling and timekeeping.
- IRQs: Interrupt requests (IRQs) signal external asynchronous events. The processor has multiple IRQ lines for peripherals.
Exception Handling Process
When an exception event occurs, the following sequence of actions happens in the Cortex-M processor:
- The processor finishes executing the current instruction.
- It saves its state by pushing register contents onto the stack.
- The return address is pushed onto the stack.
- The exception handler address is loaded from the vector table.
- The processor jumps to and executes the exception handler routine.
- The handler runs to completion and executes a return instruction.
- The stacked state is restored by popping register contents.
- Execution resumes from the return address after the point of exception.
This structured mechanism allows the processor to neatly context switch to the exception handler and back. The software just needs to provide the handler routines for each exception type.
Configuring Exception Handling
Several Cortex-M processor registers are used to configure exceptions and priorities:
- IPSR: Holds the exception number of the current executing handler.
- SHPR1-3: Set handler priorities for exceptions.
- SCR: Configures the secure state for exception handling.
- AIRCR: Manages priority grouping, NMI, and reset handling.
The vector table also needs to be set up correctly. This is an array of exception handler addresses stored in the initial boot memory region. The processor fetches the relevant handler address from the vector table when an exception occurs.
Priorities and priority grouping allow flexibility in organizing the order in which nested exceptions are handled. Higher priority exceptions can preempt lower priority ones.
Uses of Exceptions
Here are some examples of how exceptions are used in Cortex-M processors:
- Interrupts: Peripherals trigger IRQ exceptions to indicate events like data received, transmission complete, ADC done, timer elapsed, etc. The handlers process each peripheral event.
- OS Scheduling: The PendSV and SysTick exceptions allow an RTOS to preempt tasks and trigger scheduling at precisely controlled intervals.
- Errors: Hard fault and NMI exceptions allow fast responses to critical errors and crashes to log diagnostic data.
- Supervisor Calls: Code in unprivileged threads can make SVC calls to kernel services for resource access, I/O, etc.
Exception Handling Tips
Here are some tips for working effectively with exceptions on Cortex-M processors:
- Use stacking on exception entry and exit to keep the handler isolated.
- Minimize stack usage within handlers to prevent overflow.
- Store context data in registers rather than on the stack if possible.
- Keep exception handlers short, focused, atomic, and fast.
- Use compiler intrinsics rather than instructions for exception triggering.
- Utilize priority grouping and nesting to structure complex applications.
- Leverage assets like CMSIS headers and peripheral libraries.
- Test exception handling thoroughly during development.
Some common issues with exception handling on Cortex-M processors include:
- Vector table errors – check alignments, mappings, and handler addresses.
- Faulty stacks – use stack overflow protection and monitoring.
- Undesired nesting – double check handler priorities.
- Clobbered registers – review context saving conventions.
- Endless exceptions – look for stuck handlers or priorities.
- Spurious interrupts – filter noise with de-bouncing.
- Broken return flow – verify the handler exit mechanism.
A debug probe is invaluable for inspecting stack frames, registers, and exception vectors during crashes. Many SoCs also provide debug exception triggering modules to thoroughly validate handling.
Exception handling on the Cortex-M enables real-time, deterministic, and crash-safe response to events. Configuring the vector table, handlers, priorities, and stacks correctly is key to creating robust embedded applications. As microcontroller projects grow more complex, flexible exception architectures like the Cortex-M’s become highly valuable for managing concurrency and simplifying logic flow.