The key difference in exception handling between Cortex-M and Cortex-R processors is that Cortex-M uses the Nested Vectored Interrupt Controller (NVIC) while Cortex-R uses the Generic Interrupt Controller (GIC). The NVIC allows for tailored exception handling with a priority-based preemption model, while the GIC is more flexible and supports up to 1020 interrupt sources.
Cortex-M Exception Handling
The Cortex-M series of processors are designed for microcontroller applications and have a simplified exception model. When an exception occurs, the processor automatically saves context to the stack and branches to an exception handler routine. The NVIC controls dispatching exceptions and interrupts to the right handler routine.
There are several types of exceptions in Cortex-M processors:
- Resets – handled by boot code to initialize the system
- NMI – non-maskable interrupt with highest priority
- HardFault – for serious errors like bus faults
- MemManage – memory protection faults
- BusFault – memory/instruction bus errors
- UsageFault – undefined instructions, invalid state
- SVCall – supervisor call instructions
- DebugMonitor – for debugging breakpoints
- PendSV – pendable request for system service
- SysTick – system timer for operating system
- IRQ 0 to IRQ 239 – configurable external interrupts
The NVIC allows priorities to be assigned to each interrupt source, from 0 (highest priority) to 255 (lowest). Higher priority exceptions can preempt lower priority code. The NVIC has built-in registers for controlling interrupts like the Interrupt Set Enable Register (ISER), Interrupt Clear Enable Register (ICER), Interrupt Set Pending Register (ISPR), and Interrupt Clear Pending Register (ICPR).
Each exception type has a dedicated exception handler function. These are defined in a vector table which the processor reads on bootup. The vector table provides the memory addresses for each exception handler routine. When an exception occurs, the return address is pushed onto the current stack and the processor branches to the corresponding handler routine.
Inside the handler, software needs to clear the pending interrupt, handle the cause of the exception, and return from the handler which restores the original context. The simplified exception model reduces latency from interrupt detection to running the handler code.
Cortex-M Exception Priorities
The NVIC supports up to 240 interrupt channels with a default priority of 0 (low), 255 (high), or a configurable priority level for each channel. Higher priority interrupts preempt lower priority code.
However, Reset, HardFault, and NMI exceptions have fixed priorities that cannot be changed:
- Reset – Highest priority
- HardFault – 2nd highest priority
- NMI – 3rd highest priority
The Memory Management, Bus Fault, and Usage Fault exceptions have fixed priorities below NMI. PendSV, SysTick, and IRQ channels have configurable priorities below the fixed exceptions. SVCall has the lowest priority.
This prioritization ensures critical exceptions get handled immediately. The tailored priority levels allow flexibility in assigning importance to peripherals and external interrupts.
Context Saving on Exception Entry
When an exception occurs, the Cortex-M processor automatically saves context onto the current stack by pushing registers onto the stack. This includes saving the Program Counter, Link Register, Processor Status Register contents like interrupt masks, and general purpose register R0-R3, R12.
The exception handler can then freely use the registers while handling the exception. On exception exit, the registers are restored to continue normal execution.
For low latency entry into exception handlers, only a minimal set of registers are automatically saved. The exception handler needs to save any other registers it will use onto the stack. Any stack or structure restoration required is also handled in software.
The Cortex-M processors allow exception handlers to directly branch to a handler for a higher priority exception rather than returning first. This is known as tail-chaining and reduces the latency between related exceptions.
For example, a memory fault exception could tail-chain directly into the hard fault handler instead of returning from the memory handler first. This reduces the context restore time between the two related exceptions.
Cortex-R Exception Handling
The Cortex-R series targets more complex real-time applications which require an advanced exception handling model. The processor includes a configurable two-stage pipeline and optional MPU. Exceptions are handled using a common architecture called the Exception Handling Architecture (EHA).
The main components involved are:
- Generic Interrupt Controller (GIC) – manages interrupts
- Vector Table – points to handler routines
- Exception Handling Unit (EHU) – manages context saving
When an exception occurs, the EHU automatically saves context to banked registers rather than the stack. The processor then branches to the handler routine pointed to by the vector table. The return address is also saved by the EHU rather than on the stack.
Generic Interrupt Controller
Unlike the NVIC, the GIC is highly configurable for different numbers of interrupts. For example, the Cortex-R5 supports up to 224 interrupts while the Cortex-R52 supports 1020 interrupt sources.
The GIC supports 16 priority levels, with higher levels able to preempt lower priority exceptions. Priority grouping can be configured for binary, ternary or quaternary grouping of the 16 priority levels.
The GIC has registers for enabling, pending and active interrupts, as well as configuring targets and priorities. Multiple GIC interfaces extend the number of supported interrupts. The advanced GIC architecture suits more complex systems.
Banked Context Saving
Instead of using the stack, the Cortex-R processor uses banked registers to automatically save context on exception entry. The EHU manages saving to two register banks – the current bank for normal execution, and the exception bank used during exception processing.
On exception entry, the EHU switches to the exception bank and transfers context like the PC and PSR to reserved registers in the exception bank. This avoids stack operations for low latency branching to the vector table.
The handler routine can then freely use the current bank registers without corrupting the original context. On exception return, the EHU restores the original context from the exception bank registers.
The banked architecture reduces interrupt latency and overhead compared to stacking registers. The EHU also manages linking stacked exceptions through link registers.
Late Arrival and Tail-Chaining
The Cortex-R supports late arrival of higher priority exceptions. This means if a low priority exception is already being handled, and a higher priority exception arrives, the processor can pause handling the lower priority exception and context switch to the new higher priority exception.
Tail-chaining optimizations are also supported. A lower priority exception can directly branch to a higher priority handler using branch instructions rather than returning from the handler.
Together, these reduce context switching and interruption overhead to optimize real-time performance.
Summary of Key Differences
Some key differences between Cortex-M and Cortex-R exception handling include:
- Cortex-M uses NVIC, Cortex-R uses GIC
- Cortex-M uses stack for context saving, Cortex-R uses banked registers
- Cortex-M has simpler exceptions, Cortex-R has more advanced exceptions
- Cortex-M less flexible priorities, Cortex-R more priority levels
- Cortex-R supports late arrival and tail-chaining
In summary, Cortex-M favors low latency simple exception handling suitable for microcontrollers. Cortex-R has more advanced exception support optimized for complex real-time applications.
Exception handling on ARM’s Cortex-M and Cortex-R series processors differ significantly due to their differing use cases. The Cortex-M uses the Nested Vectored Interrupt Controller and stack-based context saving for low latency and a simple model suitable for microcontrollers. The Cortex-R has much more advanced support through the Generic Interrupt Controller, banked context saving, late arrival handling, and tail-chaining to optimize exception handling latency and flexibility for complex real-time systems.