In the ARM architecture, interrupts are handled by the processor’s interrupt controller and vectored interrupt controller. The interrupt controller receives interrupt requests from various sources and determines the priority of the interrupts. The vectored interrupt controller uses the priority to determine which interrupt should be handled first when multiple interrupts are pending.
ARM processors typically support up to 256 interrupt requests or IRQs numbered from 0 to 255. Lower numbered IRQs generally have higher priority than higher numbered IRQs. For example, IRQ 0 has the highest priority while IRQ 255 has the lowest priority. However, the exact priority levels can be configured by programming the priority registers in the interrupt controller.
Default Highest Priority Interrupt
By default, without any priority configuration, IRQ 0 has the highest priority in ARM processors. This IRQ is usually reserved for the system timer interrupt. The system timer generates periodic interrupts for task scheduling and timekeeping. Giving it the highest priority ensures timer events are handled promptly for real-time performance.
Other common high priority interrupts in ARM include:
- IRQ 1 – Keyboard interrupt
- IRQ 2 – Cascade interrupt for secondary interrupt controller
- IRQ 3 – UART interrupt for serial ports
- IRQ 4 – UART interrupt for serial ports
- IRQ 5 – GPIO interrupt for external signals
These interrupts need quick response which is why they are assigned priority levels near the top. On the other end, lower priority IRQs are used for interrupts that don’t require immediate service like network interfaces.
Changing Interrupt Priorities
The default interrupt priority levels can be changed by programming the interrupt controller registers. This allows flexibility in assigning interrupt priorities according to the needs of the system.
For example, in a real-time control system, the analog-to-digital converter (ADC) interrupts may need higher priority than the serial port interrupts. Or in a network router, the network interface interrupts might need priority over the timer interrupt.
To change priorities, the interrupt controller peripheral has priority level registers. Setting a lower value gives an interrupt higher priority. The processor checks these priority levels to pick the active interrupt with the highest priority.
As an example, the ARM Generic Interrupt Controller (GIC) has PRIORITYRn registers where n is the interrupt number. Writing a smaller value like 0xFF to PRIORITYR10 will assign IRQ10 higher priority than the default 0x80.
ARM processors also support nesting of interrupts. This allows high priority interrupts to preempt lower priority interrupts. For example, if IRQ10 is already being handled, and IRQ20 occurs with higher priority, then IRQ20 can become active and its interrupt service routine will run.
When IRQ20 finishes, IRQ10 can resume execution. This nested execution helps ensure critical interrupts get serviced immediately without waiting for lower priority interrupts to finish.
The interrupt controller automatically manages the stacking, prioritization and returning from nested interrupts. The processor simply executes the highest priority interrupt service routine presented to it.
Priority Level Groups
To allow flexibility in assigning priority levels, the GIC supports splitting interrupts into priority groups. For example, groups could be:
- Group 0: IRQs 0-31
- Group 1: IRQs 32-63
- Group 2: IRQs 64+
Each group has its own priority levels. So IRQ50 in group 1 could have higher priority than IRQ10 in group 0, even though 50 > 10. This enables logical grouping of interrupts for priority management.
Managing Interrupt Latency
A key aspect of assigning interrupt priorities is managing interrupt latency. Latency is the delay between an interrupt being asserted and its execution. High priority interrupts have lower latency because they get serviced faster.
Latency depends on:
- Interrupt priority grouping
- Priority levels assigned
- Code execution time of interrupt service routines
To guarantee low latency for critical interrupts, they need to be in the highest priority group. Their service routines must also be streamlined with minimal instructions. Checking and tuning interrupt priorities is a key step in achieving desired real-time performance.
Some example use cases for managing interrupt priorities in ARM systems are:
- Real-time control – Higher priority for ADC/DAC interrupts to sample data and update outputs with determinism.
- Sensor fusion – Lower priority for slower sensors, higher priority for critical sensors requiring fast response.
- Network switch – Highest priority for network interface and packet processing interrupts.
- User interfaces – Higher priority for display refresh and touchscreen interrupts for smooth UI.
- Automotive – Highest priority for engine/brake control systems with safety critical requirements.
Optimally configuring interrupt priorities is key to building responsive real-time embedded and IoT applications using ARM processors.
IRQ 0 has the highest default priority in ARM processors. But interrupt priorities are flexible and can be changed by programming the interrupt controller registers. Grouping interrupts into priority levels, assigning higher priority to time-critical interrupts, and reducing service routine latency allows meeting real-time performance requirements. Tuning interrupt priorities and latency is an important consideration when building ARM-based embedded systems.