Disabling interrupts on an ARM processor can be useful in certain situations where real-time performance and determinism are critical. However, doing so requires careful planning and an understanding of the potential side effects. The key is managing workflow in such a way that time-critical code executes without interruption, while less time-sensitive operations occur around the edges.
Overview of Interrupts
Interrupts allow an ARM processor to react to events and requests from peripherals in real-time. When an interrupt is triggered, the processor pauses its current activity, saves its state, runs an interrupt handler routine, then returns to where it left off. This provides very fast response times, but can also cause problems for code that requires deterministic execution times.
Disabling interrupts prevents these asynchronous jumps, ensuring a block of code runs to completion without interruption. This is essential for operations like multi-stage calculations that require intermediate results. The tradeoff is that background processing halts, peripherals are ignored, and system responsiveness suffers overall.
When planning an ARM workflow with interrupts disabled, the first priority is identifying sections of code where deterministic execution is truly required. These time-critical blocks should be as short and efficient as possible. Long loops, complex calculations, and unnecessary branching increase the risks associated with an extended no-interrupt period.
Time-critical code must also be structured so it does not rely on interrupts itself. This means not having dependencies on data from interrupt-driven peripherals, and avoiding operations that could trigger nested interrupts. Stack usage should be conservative as well.
Less time-sensitive work should be arranged to occur in the gaps between critical sections. This includes background processes like communications protocols, display updates, non-urgent sensor readings, etc. Planning is required to ensure these operations are paused and resumed cleanly around interrupt-disabled regions.
On ARM processors, interrupts are disabled by setting the I bit in the CPSR processor status register. This masks incoming interrupt requests across the system. Code can then execute without asynchronous jumps.
A typical pattern is to disable interrupts at the start of a time-critical routine, perform the required work, then re-enable interrupts at the end: /* Disable Interrupts */ MRS R0, CPSR @ Read CPSR ORR R0, R0, #0x80 @ Set I bit MSR CPSR_c, R0 @ Write back /* Critical code here */ /* Re-enable Interrupts */ BIC R0, R0, #0x80 @ Clear I bit MSR CPSR_c, R0 @ Write back
The CPSR can also be manipulated via CPS instructions rather than register access. Other considerations around disabling interrupts include:
- Saving interrupt state if nesting is required
- Assigning priority levels to peripherals
- Stack overflow risks due to unserviced interrupts
- Impacts on code that relies on interrupt timing
With interrupts disabled, any peripheral that requires timely servicing will be impacted. Steps must be taken to avoid data loss and other issues:
- Buffer input data (e.g. ADC samples) to prevent overrun
- Flash inputs manually if needed during critical sections
- Handle pending peripheral flags after re-enabling interrupts
- Initialize peripherals to not generate interrupts
- Queue lower priority tasks to service peripherals later
In some cases, peripherals may need their own enable/disable controls to work cleanly with disabled global interrupts. Watchdog timers are also commonly used to catch hangs from unforeseen issues.
Fully deterministic real-time operation requires more than just disabled interrupts. Additional considerations include:
- Kernel preemption controls for RTOS threads
- Locking out DMA transfers
- Loop unroll counts, instruction scheduling
- Memory wait state configurations
- Cache control for predictable access
Some ARM cores provide architectural options to help optimize worst-case timing, such as scratchpad RAM, hardware semaphores, and mechanisms to manage pipeline flushes on exception return.
Debugging code with interrupts disabled requires special care. Issues like infinite loops will hang the system completely with no way for the debugger to break in. Options to consider include:
- Debug timer to trigger periodic interrupts
- Monitor mode for external debug control
- ITM / SWO for printf-style messaging
- Debug trigger points around critical sections
- Simulator trace captures
Toolchain configurations related to unwinding stacks and handling faults may need adjustment as well. The goal is to strike a balance between debugability and determinism.
On multiprocessing ARM systems, workflow with interrupts disabled has implications across cores. While a particular core executes critical code, the system must ensure other cores do not interrupt it unexpectedly.
This requires coordination to control which cores disable interrupts when, and mechanisms to trigger context switches safely. For example, a spinlock could force other cores to busy-wait until the critical section completes. Core 0 might also play a supervisory role.
Message passing schemes must likewise operate cleanly with independent interrupt control per core. Overall, multiprocessing adds significant complexity when attempting deterministic execution.
Interrupt disabling techniques are commonly employed in applications such as:
- Motor control ISRs for electric vehicles
- Industrial servo positioning
- Precision sensor measurements
- High-speed telemetry processing
- Machine vision analysis
In these cases, the ARM workflow is architected such that data capture, actuation, complex math, and other time-critical operations occur in deterministic interrupt-disabled segments. Less critical functionality happens in the background during other phases.
The exact approach depends on the application requirements. A balance must be struck between real-time performance and overall responsiveness. Thorough testing is also crucial to ensure stability.
Disabling interrupts provides ARM processors with deterministic execution at the cost of reduced responsiveness. The workflow must be planned carefully to minimize the disabled periods and handle peripherals and background tasks properly. Additional techniques may also be required for fully predictable real-time operation. When applied judiciously, disabling interrupts can enable ARM cores to meet stringent timing demands in performance-critical applications.