The ARM Cortex-M0 is an ultra low power 32-bit RISC processor core designed for microcontroller applications. It implements the ARMv6-M architecture and includes built-in exception handling for faults and interrupts. The Cortex-M0 handles exceptions through the use of the Nested Vectored Interrupt Controller (NVIC) and the processor’s exception model.
ARMv6-M Exception Model
The ARMv6-M architecture defines several types of exceptions that can occur during program execution on a Cortex-M0 processor:
- Resets – Generated when the processor is reset
- NMI – Non-maskable interrupt triggered by hardware
- Hard fault – For severe errors such as illegal opcode or memory access violations
- SVCall – Supervisor call instruction to request a privileged function
- PendSV – Pendable request for system service from a unprivileged thread mode
- SysTick – System timer interrupt for task scheduling or timekeeping
- IRQ – Generic interrupts signaled from peripheral modules
When an exception occurs, the processor automatically saves context on the stack and enters Handler mode, the privileged exception handling state. The processor then reads the vector table to branch to the specific exception handler routine. After handling the exception, the handler returns to Handler mode to restore context and resume normal execution.
Nested Vectored Interrupt Controller (NVIC)
The NVIC is the key component of the Cortex-M0 that handles prioritized exception dispatching. It provides configurable interrupts with programmable priority levels and vector tables. The NVIC interfaces with the processor core to manage interrupts as follows:
- Reads the exception vector table to determine the entry point for each exception handler
- Sets the priority levels for exceptions and determines which has highest priority
- Triggers the appropriate exception on the core based on priority
- Contains registers for configuring and enabling interrupts
The NVIC vector table occupies the first 1KB of memory and defines the address for each exception handler. Vectors can be read-only in flash memory or writable when located in SRAM. The NVIC prioritizes exceptions using configurable priority levels and preemption groups. Higher priority interrupts preempt lower priority ones. Within the same priority level, preemption groups can be used to prevent preemption during critical handling routines.
Cortex-M0 Vector Table
The Cortex-M0 vector table defines 16 exception vectors plus up to 32 external interrupts. The table is located at memory address 0x00000000 on reset. Each vector is a 32-bit word holding the address of the exception handler for that exception. The vectors include:
- Position 1 – Initial stack pointer value
- Position 2 – Reset handler for processor restart
- Position 3 – NMI handler for non-maskable interrupts
- Position 4 – HardFault handler for critical errors
- Position 5-10 – Reserved exception handlers
- Position 11 – SVCall handler for supervisor calls
- Position 12-13 – Reserved exception handlers
- Position 14 – PendSV handler for pending system requests
- Position 15 – SysTick timer system handler
- Position 16+ – IRQ external interrupt handler vectors
Unimplemented handlers can point to a default handler routine. External interrupts are enabled by configuring the NVIC to set priorities and enable masking/clearing of specific IRQ vectors. Startup code initializes the stack pointer and branch to the reset handler on boot.
Cortex-M0 Exception Priority Levels
The NVIC supports up to 32 priority levels for interrupts, with 0 being the highest priority level. Exceptions have the following default priority levels:
- Reset – -3
- NMI – -2
- HardFault – -1
- SVCall, PendSV – 0 (lowest)
- SysTick – 3
- External Interrupts – configurable priority 0-31
The priority scheme ensures critical exceptions like hard faults and NMIs are handled before lower priority interrupts. PendSV and SVCall have low priority to allow masking during interrupt handling. SysTick has above average priority for task scheduling. Interrupts defaults to priority 0 but can be lowered if needed.
Cortex-M0 Hard Fault Exception
The hard fault exception is triggered for critical errors during execution, such as:
- Invalid memory access
- Illegal unaligned memory access
- Faulting instruction execution, such as invalid opcode
- Dividing by 0
- Corruption of stack pointer
When a hard fault occurs, the NVIC forces an exception – all lower priority exceptions and interrupts are temporarily disabled. The processor switches to Handler mode and sets the hard fault active bit. The hard fault handler at vector 4 is invoked to process the fault. The fault information and context state at the time of the error are available for inspection and debugging purposes.
Typical hard fault handling involves recording the fault cause and location, then performing tasks like halting further execution or rebooting. Hard faults are severe errors indicating a bug or unhandled problem in the program code itself, rather than normal exceptions that can be recovered from.
Cortex-M0 Bus Fault Exception
The bus fault exception is a special type of hard fault triggered by memory related errors during an instruction fetch or data access. Typical causes include:
- Illegal address access
- Unaligned address on word or halfword access
- Double word access to an odd address
- Fault on normal, privileged, or stack memory access
As a subclass of hard fault, bus faults have the same priority level and handling. The processor enters Handler mode and invokes the hard fault handler. Additional bus fault status registers provide insight into the specific error, such as the failing address and access type. Debugging features like breakpoints on access violations are useful for diagnosing complex memory related bugs.
Cortex-M0 Usage Fault Exception
Usage faults represent a special category of hard fault related to incorrect use of instructions or resources on the processor. Potential causes include:
- Unaligned memory access on halfword or word instructions
- Division by zero
- Invalid or undefined opcode
- Coprocessor instruction in invalid context
- Attempt to switch to invalid stack pointer
Like other hard faults, usage faults invoke the fault handler at priority -1. Usage fault status registers indicate the specific type of fault and where it occurred. Debugging is needed to resolve issues in program logic, memory, or register usage that led to the faulty operation.
Cortex-M0 Debug Exception
The debug exception is triggered when halting debugger code execution for inspection, such as on a breakpoint. Debug events have lower priority than even SVCall/PendSV so as not to interfere with critical exception handling. Debug exception causes include:
- Halting on a breakpoint opcode (BKPT instruction)
- Halting on externally set breakpoint signal
- Halting through debugger command
- Halting on a watchpoint data match
- Starting exception execution via debugger
The handler saves context then enters Debug state waiting for the debugger. After debugging, the handler restores context and resumes normal execution. The debug exception provides powerful insight into program execution without interfering with operation until halted.
Cortex-M0 NMI Exception
The non-maskable interrupt (NMI) exception cannot be ignored or preempted by normal interrupts in the system. NMIs have the highest exception priority of -2. Typical NMI causes include:
- External NMI pin assertion
- Parity or ECC errors
- Wakeup on system resume from low power mode
The NMI handler forces all other exceptions to be temporarily ignored regardless of state or priority level. This ensures critical and time-sensitive NMIs can provide handling for severe errors and wakeup scenarios. After handling, the NMI return backs to previous context before the NMI assertion.
Cortex-M0 SVCall Exception
The supervisor call (SVCall) exception is triggered by SVCall instructions in Thread mode to request privileged system functions accessible from Handler mode only. Typical SVCall uses include:
- Requesting protected OS kernel services
- Entering a critical section to access shared resources
- Inter-process communication and synchronization
The SVCall handler first saves context, then performs the privileged function before returning to resume Thread mode operation. SVCalls allow for clean layering between privilege levels in software architectures.
Cortex-M0 PendSV Exception
The PendSV exception implements flexible context switching and tail-chaining for low priority service requests from multiple sources. Typical causes include:
- Pending thread switch at next opportunity
- Pending request for OS kernel management function
- Pending peripheral driver action
- Start of new timed processing phase
The PendSV handler efficiently saves just enough context to resume the thread later. This is faster than saving full context. Handler code then performs tailored system service functions requested by sources before return. PendSV enables rapid deferred handling of asynchronous system events.
Cortex-M0 SysTick Exception
The SysTick exception is triggered by the core’s internal 24-bit SysTick counter/timer for consistent timing and clocking. Typical uses include:
- Real-time OS tick for task scheduling and switching
- Providing a periodic timebase and software timers
- Instruction trace timestamps
- Datawatchpoint timestamp tagging
- Polling driver and system functions for periodic update
The SysTick handler acts on elapsed time to drive time-based service routines. It can increment global time values, update peripheral registers or devices, trigger thread switches, and more. The programmable timer rate provides highly flexible consistent timing.
Cortex-M0 IRQ Interrupt Handling
IRQ interrupts represent asynchronous external signals from on-chip peripherals or devices. IRQ causes include:
- SPI, UART, I2C peripheral data transfer events
- ADC conversion complete interrupts
- Sensor measurement thresholds met
- Touch interface events
- GPIO pin waveform events
IRQ handlers run with tail-chaining so that back to back interrupts can be efficiently serviced without context saving/restoring. The NVIC sets interrupt priorities 0-31, with 0 being highest priority. Higher priority IRQs can preempt lower priority handlers. Within the same priority, IRQ preemption groups can be configured to manage contention.
Exception Handler Design
When designing Cortex-M0 exception handlers, key considerations include:
- Minimize context saving to only the registers needed
- Keep handlers short, focused, and atomic when possible
- Return to resume previous execution quickly
- Prioritize and structure handlers based on frequency and criticality
- Use stacked exception handling to contain errors
- Layer privilege levels between Thread/Handler modes cleanly
These practices enable lean interrupt-driven designs to make optimal use of the Cortex-M0’s exception handling capabilities. The end result is responsive real-time application execution with robust handling of complex fault conditions.
In summary, the Cortex-M0 provides comprehensive exception handling for interrupts, faults, system calls, and debugger events. The NVIC and vector table structures enable configurable prioritized exception management. Exception mechanisms like tail-chaining provide low latency deferred handling of asynchronous events. Overall the Cortex-M0 exception capabilities facilitate efficient embedded software architectures for real-time application use cases.