ARM Cortex-M3 Programming: Understanding NVIC and Interrupt Handling
Modern embedded systems must react instantly to external events such as sensor inputs, communication requests, timer expirations, and safety-critical conditions. Instead of continuously checking every peripheral, microcontrollers rely on interrupts to notify the processor whenever immediate attention is required.
In ARM Cortex-M3 programming, interrupt management is performed by a dedicated hardware component known as the Nested Vectored Interrupt Controller (NVIC). This controller is integrated directly into the Cortex-M3 core, allowing the processor to respond to events with minimal delay while maintaining deterministic real-time performance.
Whether you’re developing industrial automation systems, automotive controllers, IoT devices, robotics applications, or medical equipment, understanding the NVIC is essential for writing efficient embedded software.
In this article, we’ll explore how the NVIC works, how interrupt priorities are assigned, and why the ARM Cortex-M3 architecture is widely recognized for its excellent interrupt performance.
What is the NVIC in ARM Cortex-M3 Programming?
The Nested Vectored Interrupt Controller (NVIC) is the hardware module responsible for managing interrupts and exceptions in the ARM Cortex-M3 processor.
Unlike older microcontrollers that relied on external interrupt controllers or software-driven interrupt management, the Cortex-M3 integrates the NVIC directly into the processor core. This hardware integration significantly reduces interrupt latency while simplifying firmware development.
The NVIC performs several important tasks:
- Detects interrupt requests.
- Prioritizes multiple interrupts.
- Executes the correct Interrupt Service Routine (ISR).
- Supports nested interrupts.
- Automatically saves and restores processor context.
- Reduces software overhead.
Because these operations are handled by dedicated hardware, developers can focus on application logic rather than complex interrupt management.

Why Interrupts Are Important in ARM Cortex-M3 Programming
Interrupts allow the processor to respond immediately when an event occurs.
Without interrupts, the processor would continuously poll every peripheral, wasting valuable CPU cycles.
For example, imagine a system containing:
- UART communication
- ADC sensor readings
- Motor control timers
- CAN communication
- External push buttons
Instead of checking each peripheral thousands of times every second, the processor simply waits until one of them generates an interrupt.
When an interrupt occurs, execution temporarily pauses, the interrupt is serviced, and the processor resumes its previous task.
This approach improves:
- CPU efficiency
- Response time
- Power consumption
- Real-time performance
- Overall system reliability
Types of Interrupts in ARM Cortex-M3
The Cortex-M3 processor handles two primary categories of events.
1. System Exceptions
These exceptions are generated internally by the processor itself.
Common examples include:
- Reset
- Non-Maskable Interrupt (NMI)
- Hard Fault
- Memory Management Fault
- Bus Fault
- Usage Fault
- SVCall
- Debug Monitor
- PendSV
- SysTick
These exceptions are essential for processor operation and system-level control.
2. External Interrupts
External interrupts originate from on-chip peripherals or external hardware.
Typical interrupt sources include:
- GPIO Pins
- UART
- SPI
- I2C
- CAN
- USB
- Timers
- PWM
- ADC
- Watchdog Timer
- Ethernet Controller
- RTC
For example, in the LPC1768 microcontroller, peripherals such as Timer0, UART0, ADC, CAN, Ethernet, USB, and external interrupt pins all generate NVIC interrupts.
How the NVIC Works
Whenever an interrupt occurs, the NVIC follows a well-defined sequence.
Step 1: Interrupt Request
A peripheral generates an interrupt request.
Examples include:
- UART receives new data.
- Timer reaches its compare value.
- ADC completes conversion.
- GPIO detects a rising edge.
Step 2: NVIC Detects the Interrupt
The NVIC continuously monitors all interrupt sources.
As soon as a request arrives, it checks:
- Whether the interrupt is enabled.
- Whether its priority is higher than the currently executing task.
- Whether it should execute immediately.
Step 3: Automatic Context Saving
Before executing the ISR, the Cortex-M3 automatically saves the processor context.
The following registers are pushed onto the stack:
- R0
- R1
- R2
- R3
- R12
- Link Register (LR)
- Program Counter (PC)
- Program Status Register (xPSR)
This hardware stacking eliminates the need for manual register saving, reducing ISR overhead and improving execution speed.
Step 4: Vector Table Lookup
Every interrupt has a unique entry in the Interrupt Vector Table.
The NVIC reads the ISR address directly from this table and immediately jumps to the correct interrupt service routine, significantly reducing interrupt latency.
Step 5: Interrupt Service Routine (ISR) Execution
The ISR performs the required task associated with the interrupt.
Typical examples include:
- Reading UART data.
- Clearing timer interrupt flags.
- Processing ADC conversion results.
- Updating motor control outputs.
- Handling communication packets.
Interrupt Service Routines should remain short and efficient so that the processor can quickly return to the interrupted program.
Step 6: Automatic Context Restoration
After the ISR finishes execution, the Cortex-M3 automatically restores the saved registers.
The interrupted program resumes from the exact instruction where execution was paused.
This automatic context restoration is one of the major advantages of ARM Cortex-M3 programming, reducing software complexity while improving interrupt performance.
Interrupt Vector Table
The Interrupt Vector Table is a memory table that stores the starting addresses of all exception handlers and interrupt service routines.
Each vector corresponds to a unique interrupt source.
| Vector | Interrupt |
|---|
| 0 | Initial Stack Pointer |
| 1 | Reset Handler |
| 2 | NMI Handler |
| 3 | Hard Fault Handler |
| 4 | Memory Management Fault |
| 5 | Bus Fault |
| 6 | Usage Fault |
| 15 | SysTick |
| 16 onwards | External Peripheral Interrupts |
Because every interrupt has its own vector, the processor immediately begins executing the appropriate interrupt service routine without additional software processing.

Interrupt Priorities in ARM Cortex-M3 Programming
One of the most important features of the NVIC is its priority-based interrupt handling mechanism.
Each interrupt can be assigned a configurable priority. In ARM Cortex-M3, lower numerical values indicate higher priorities.
| Priority | Importance |
|---|
| 0 | Highest |
| 1 | Very High |
| 3 | High |
| 6 | Medium |
| 15 | Lowest |
Suppose three interrupts occur simultaneously:
| Interrupt | Priority |
|---|
| External Emergency | 1 |
| Timer | 3 |
| UART | 6 |
The NVIC services the interrupts in the following order:
- External Emergency
- Timer
- UART
This priority-based mechanism ensures that safety-critical events receive immediate processor attention.
Nested Interrupts in ARM Cortex-M3 Programming
One of the standout features of the ARM Cortex-M3 processor is its support for nested interrupts. This capability allows a higher-priority interrupt to temporarily interrupt the execution of a lower-priority Interrupt Service Routine (ISR). As a result, critical events are handled immediately without waiting for less important tasks to finish.
Example of Nested Interrupts
Imagine the following scenario:
- A UART interrupt is currently executing.
- While the UART ISR is running, a Timer interrupt occurs.
- The Timer interrupt has a higher priority than the UART interrupt.
The NVIC automatically performs the following steps:
- Suspends the UART ISR.
- Saves the processor state.
- Executes the Timer ISR.
- Restores the UART ISR after the Timer ISR finishes.
- Continues execution from the exact instruction where it was interrupted.
This mechanism ensures that high-priority events are never delayed by lower-priority interrupt routines.
Automatic Context Saving and Restoration
In traditional microcontrollers, developers often manually save processor registers before entering an Interrupt Service Routine and restore them before returning. This increases software complexity and execution time.
The ARM Cortex-M3 simplifies this process through hardware-managed context saving.
Whenever an interrupt occurs, the processor automatically stores the following registers on the stack:
- R0
- R1
- R2
- R3
- R12
- Link Register (LR)
- Program Counter (PC)
- Program Status Register (xPSR)
After the ISR completes, these registers are automatically restored.
Benefits
- Faster interrupt response
- Reduced software overhead
- Simpler firmware development
- Consistent interrupt execution
- Improved system reliability
This hardware feature is one of the reasons why ARM Cortex-M3 programming is widely used in real-time embedded applications.
Interrupt States in the NVIC
Each interrupt managed by the NVIC can exist in one of four different states.
1. Inactive
The interrupt has not been requested and is waiting for an event.
2. Pending
The interrupt request has been received but has not yet been serviced because:
- A higher-priority interrupt is currently running.
- Interrupts are temporarily disabled.
- The processor is servicing another exception.
3. Active
The processor is currently executing the Interrupt Service Routine associated with the interrupt.
4. Active and Pending
This state occurs when:
- An interrupt is already executing.
- The same interrupt is triggered again before the current ISR completes.
The second interrupt request remains pending until the first ISR finishes.
Understanding these interrupt states is valuable when debugging interrupt-driven embedded applications.
Enabling and Disabling Interrupts
The NVIC allows software to enable or disable individual interrupts according to application requirements.
Enabling Interrupts
When enabled, the processor responds immediately whenever the interrupt occurs.
Typical interrupt sources include:
- UART communication
- Timer events
- ADC conversion completion
- External GPIO interrupts
Disabling Interrupts
Sometimes the processor must execute a critical section of code without interruption.
In such situations, specific interrupts can be temporarily disabled.
Examples include:
- Updating shared variables
- Flash memory programming
- Bootloader execution
- Critical communication sequences
Once the critical operation is complete, the interrupt is re-enabled.
Proper interrupt management helps prevent race conditions and data corruption.
Interrupt Latency
Interrupt latency is the time between the occurrence of an interrupt and the execution of its corresponding Interrupt Service Routine.
Lower interrupt latency is essential in real-time systems because it enables faster responses to critical events.
The ARM Cortex-M3 achieves very low interrupt latency through several hardware optimizations:
- Integrated NVIC
- Direct vector table access
- Automatic context saving
- Hardware priority comparison
- Optimized exception entry and exit
These features allow Cortex-M3-based systems to meet strict timing requirements in industrial and safety-critical applications.
Tail-Chaining
Tail-chaining is an advanced optimization built into the NVIC that reduces interrupt overhead.
Without Tail-Chaining
Normally, after one ISR completes:
- The processor restores the saved context.
- Returns to the interrupted program.
- Saves the context again for the next interrupt.
- Executes the next ISR.
This process requires unnecessary stack operations.
With Tail-Chaining
Suppose:
- Timer0 ISR is finishing.
- UART0 interrupt is already pending.
Instead of restoring and saving the processor context again, the NVIC immediately switches from the Timer ISR to the UART ISR.
Advantages
- Faster interrupt processing
- Reduced stack operations
- Lower processor overhead
- Better real-time performance
Tail-chaining is one of the reasons ARM Cortex-M3 processors deliver excellent interrupt efficiency.
Late Arrival
Another intelligent optimization in ARM Cortex-M3 programming is Late Arrival.
Consider the following situation:
- A low-priority interrupt begins its exception entry.
- Before its ISR starts executing, a higher-priority interrupt occurs.
Instead of completing the low-priority interrupt entry first, the NVIC immediately redirects execution to the higher-priority interrupt.
Benefits
- Faster response to urgent events
- Reduced interrupt latency
- Improved deterministic behavior
- Better real-time performance
This optimization is particularly valuable in automotive, aerospace, robotics, and industrial control systems.
Advantages of the NVIC in ARM Cortex-M3 Programming
The Nested Vectored Interrupt Controller provides numerous benefits that improve embedded system performance.
- Very fast interrupt response
- Integrated hardware interrupt controller
- Automatic context saving and restoration
- Support for nested interrupts
- Configurable interrupt priorities
- Reduced interrupt latency
- Efficient handling of simultaneous interrupts
- Lower software complexity
- Improved CPU utilization
- Better real-time performance
- Deterministic interrupt execution
- Power-efficient processing
These capabilities make ARM Cortex-M3 an excellent choice for high-performance embedded applications.
le lower-priority tasks wait until higher-priority interrupts have been serviced.
Best Practices for ARM Cortex-M3 Programming
Writing efficient interrupt-driven firmware is an essential part of ARM Cortex-M3 programming. Following proven best practices helps improve system reliability, maintainability, and overall performance.
Consider the following recommendations when developing applications that use the NVIC:
- Keep Interrupt Service Routines (ISRs) as short as possible.
- Avoid blocking functions inside interrupt routines.
- Do not perform lengthy calculations inside an ISR.
- Assign interrupt priorities carefully based on application requirements.
- Protect shared resources using appropriate synchronization techniques.
- Always clear interrupt flags before exiting an ISR.
- Minimize nested interrupts unless absolutely necessary.
- Test interrupt timing under heavy system load.
- Document interrupt priorities for easier debugging and maintenance.
Following these practices ensures responsive and stable embedded applications while reducing unexpected interrupt-related issues.
Applications of ARM Cortex-M3 Interrupt Programming
The ARM Cortex-M3 processor and its NVIC are widely used in applications that require fast, deterministic interrupt handling.
Industrial Automation
- Programmable Logic Controllers (PLCs)
- Motor control systems
- Sensor monitoring
- Factory automation equipment
Automotive Electronics
- Engine Control Units (ECUs)
- Anti-lock Braking Systems (ABS)
- Airbag controllers
- Battery Management Systems (BMS)
Consumer Electronics
- Smart home devices
- Wearable electronics
- Digital cameras
- Gaming peripherals
Medical Devices
- Patient monitoring systems
- Infusion pumps
- Diagnostic equipment
- Portable healthcare devices
Internet of Things (IoT)
- Wireless sensor nodes
- Smart energy meters
- Environmental monitoring systems
- Edge computing devices
Robotics
- Autonomous robots
- Robotic arms
- Drone flight controllers
- Motion control systems
Common Mistakes in ARM Cortex-M3 Programming
Interrupt-related issues often occur because of poor firmware design. Avoiding these common mistakes can significantly improve application stability and performance.
- Assigning incorrect interrupt priorities.
- Writing lengthy Interrupt Service Routines.
- Forgetting to clear interrupt flags.
- Sharing variables between ISRs and the main program without proper synchronization.
- Disabling interrupts for extended periods.
- Ignoring nested interrupt behavior.
- Using blocking delays inside interrupt routines.
Following good coding practices and thoroughly testing interrupt behavior helps build reliable embedded systems.
Conclusion
Efficient interrupt management is fundamental to successful ARM Cortex-M3 programming, and the Nested Vectored Interrupt Controller (NVIC) plays a central role in achieving this goal. By integrating interrupt control directly into the processor core, the Cortex-M3 delivers fast response times, automatic context management, configurable priorities, nested interrupt support, and advanced optimizations such as tail-chaining and late arrival.
These features simplify firmware development while ensuring deterministic behavior in real-time systems. Whether you’re building industrial controllers, automotive ECUs, IoT devices, robotics platforms, or medical equipment, understanding the NVIC will help you create reliable, high-performance embedded applications.
Mastering interrupt handling is an essential step toward becoming proficient in ARM Cortex-M3 programming and designing efficient embedded systems.
Key Takeaways
- ARM Cortex-M3 programming includes an integrated NVIC for efficient interrupt management.
- The NVIC prioritizes interrupts and supports nested interrupt execution.
- Automatic context saving simplifies firmware development and reduces interrupt latency.
- Tail-chaining and late arrival improve interrupt efficiency and system responsiveness.
- Proper interrupt handling is essential for reliable real-time embedded applications.
- Keeping ISRs short and assigning priorities correctly improves overall system performance.
- ARM Cortex-M3 processors are widely used in industrial, automotive, IoT, robotics, and medical applications.
