Processor Architecture & CPU Internalsfoundational
Explain how interrupts work. What are some things that you should never do in an interrupt function?
0 upvotes
Practice with AISoon
How interrupts work
An interrupt is an asynchronous (hardware) or synchronous (software/exception) event that diverts the CPU from its current instruction stream to run a dedicated handler (ISR). The typical sequence:
- Request: A peripheral asserts an interrupt line (or a software event raises an exception). The signal is routed through an interrupt controller (e.g., the ARM NVIC on Cortex-M, or a GIC on Cortex-A, or the legacy PIC/APIC on x86).
- Prioritization / masking: The controller checks whether the interrupt is enabled and whether its priority is high enough to preempt the current execution level. Globally maskable interrupts can be disabled (e.g.,
PRIMASK/BASEPRIon Cortex-M,cli/stion x86). Some interrupts are non-maskable (NMI). - Acknowledge & vector: The CPU finishes/abandons the current instruction to a safe point, then looks up the handler address in the interrupt vector table and branches to it.
- Context save: Enough state is saved to resume later. On Cortex-M the hardware automatically stacks a subset of registers (xPSR, PC, LR, R0–R3, R12) onto the active stack; the rest is preserved by the handler/ABI. On other architectures more is done in software.
- Execute ISR: The handler runs, typically: read the peripheral status, clear the interrupt source/flag (otherwise it re-fires), do the minimal work, and signal the rest of the system (set a flag, post to a queue, give a semaphore).
- Return: An interrupt-return (e.g.,
BX LRwith the specialEXC_RETURNvalue on Cortex-M,ireton x86) restores context and resumes the interrupted code (or, in an RTOS, may trigger a context switch to a now-ready higher-priority task, e.g., viaPendSV).
Related concepts worth mentioning: interrupt latency (time from assertion to first ISR instruction), nesting/preemption (higher-priority IRQs interrupting lower-priority ISRs), tail-chaining (Cortex-M optimization that skips redundant unstack/stack between back-to-back IRQs), edge vs. level triggering, and shared interrupt lines.
Things you should never (or rarely) do in an ISR
- Block or wait: No busy-wait loops, no blocking I/O, no waiting on a mutex/semaphore that another task holds, no
sleep/delay. ISRs must run to completion quickly. - Run long / heavy work: Keep ISRs short and deterministic. Defer heavy processing to a bottom half — a task, work queue, or DPC. (Top-half/bottom-half or "deferred procedure" pattern.)
- Call non-reentrant / non-ISR-safe APIs: Avoid
printf,malloc/free, most of the C standard library, and any function not documented as ISR-safe. In an RTOS, only call the "FromISR" variants (e.g., FreeRTOSxQueueSendFromISR). - Take ordinary blocking locks: Acquiring a mutex meant for thread context can deadlock or cause priority issues. Use lock-free signaling or ISR-safe primitives.
- Forget to clear the interrupt source: If you don't acknowledge/clear the flag in the peripheral (and sometimes in the controller), the ISR re-enters immediately — an interrupt storm.
- Ignore
volatile/ memory ordering: Shared variables between ISR and main code must bevolatile(and access must be atomic or protected), or the compiler may cache/reorder them. Also insert memory/peripheral barriers where required (e.g.,DSB/ISB, or clearing an NVIC pending flag before returning). - Do floating-point unsafely: If the FPU context isn't saved (or lazy stacking is misconfigured), using FP in an ISR can corrupt a task's FP state. Know your platform's rules.
- Assume a big stack: ISRs may run on a limited interrupt stack; avoid large local arrays and deep recursion.
- Re-enable interrupts carelessly or leave them disabled too long: Long critical sections inflate interrupt latency for the whole system.
- Throw exceptions / use constructs with unbounded runtime (in C++ contexts).
The guiding principle: do the minimum to service the hardware and hand off the rest — read/clear the source, capture data, signal a task, and return.
