Embedded

Interrupts in embedded systems

By CourseTron Team ·  9 min read ·  Updated Oct 2026 💬 𝕏 in f
Table of Contents
    🖨  Download / Print this guide (PDF)

    In short: An interrupt is a hardware or software signal that pauses the CPU's normal flow to run a short handler called an ISR. Mastering interrupts in embedded systems means understanding the NVIC, interrupt latency, priority levels, nesting, and the discipline of keeping ISRs tiny and deterministic.

    What Is interrupts in embedded systems?

    At its core, an interrupt is an asynchronous event that tells the processor "stop what you are doing and attend to me." Instead of the CPU repeatedly polling a peripheral to ask "are you ready yet?", the peripheral raises a signal when it genuinely needs service. The processor finishes the current instruction, saves enough context to resume later, and jumps to a dedicated routine. Understanding interrupts in embedded systems is fundamental because almost every responsive, low-power, real-time device depends on them rather than on wasteful busy-wait loops.

    The routine that services the event is the Interrupt Service Routine (ISR), sometimes called an interrupt handler. Each interrupt source — a timer overflow, a UART byte received, a GPIO edge, an ADC conversion complete — maps to an entry in the vector table, a list of handler addresses the hardware consults to find the right ISR. When the event fires, the CPU looks up the vector, pushes state, and begins executing the handler.

    Key fact: On an ARM Cortex-M core, the processor automatically stacks eight registers (R0–R3, R12, LR, PC, xPSR) on interrupt entry. This hardware stacking is why a C function can be used directly as an ISR with no special assembly prologue.

    Why Interrupts Matter and How They Work

    Polling wastes CPU cycles and energy, and it reacts only as often as the loop revisits a check. Interrupts invert the model: the CPU sleeps or does useful work until an event demands attention, then responds within microseconds. This makes interrupts the backbone of real-time behaviour, power management, and clean software architecture.

    The mechanism on a Cortex-M follows a precise sequence. A peripheral asserts its interrupt line, which reaches the NVIC (Nested Vectored Interrupt Controller). The NVIC checks whether the interrupt is enabled and whether its priority is high enough to preempt whatever is running. If so, it signals the core, which completes the current instruction, pushes the register frame, loads the handler address from the vector table, and executes the ISR. On return, a special exception-return value in the Link Register triggers automatic unstacking, and the interrupted code resumes exactly where it left off.

    Polling versus interruptsPollingCPU keeps checking a status register, even when idleInterruptCPU works or sleeps until an eventISR: short serviceevent arrivesCourseTron · coursetron.com
    Animated: the polling CPU spends the whole time checking, while the interrupt-driven CPU is free until the event arrives and a short ISR runs.

    Interrupt latency

    Interrupt latency is the time between the event asserting and the first useful instruction of the ISR running. It is the sum of several contributions: the time to finish the current instruction, hardware stacking cycles, vector fetch, and any higher-priority activity or critical sections that temporarily mask interrupts. On Cortex-M this is famously deterministic — typically 12 cycles to enter — and features like tail-chaining skip redundant unstack/restack when a second interrupt is already pending, cutting latency between back-to-back ISRs.

    Priorities, Preemption, and Nesting

    Not all events are equally urgent. A motor fault must be handled before a routine housekeeping timer. Priorities let the system express this ranking. On Cortex-M the NVIC gives each interrupt a configurable priority number, where a lower numeric value means higher urgency — a common source of confusion for beginners.

    Priority is split into two fields: preemption priority (group priority) and sub-priority. A running ISR can be interrupted only by another whose preemption priority is higher. This is nesting: an ISR runs, a more urgent event arrives, its handler preempts and runs to completion, then control returns to the first ISR. Sub-priority does not cause preemption; it only decides the order when two interrupts of equal preemption level are pending at the same instant.

    Nesting: a more urgent ISR preempts a running oneISR B (urgent)ISR AMain codemainISR AISR BISR AmainB preempts A only if its preemption priority is higher (lower number).A then resumes, and main code continues where it stopped.CourseTron · coursetron.com
    Nesting timeline: main code is interrupted by ISR A, ISR A is preempted by the higher-priority ISR B, then A resumes and main code continues.
    • Maskable interrupts — the vast majority, which software can disable via the NVIC or the PRIMASK/BASEPRI registers.
    • Non-maskable interrupt (NMI) — cannot be disabled; reserved for critical events like a clock failure.
    • Faults and exceptions — HardFault, MemManage, BusFault, and SysTick are handled through the same vectored mechanism.

    A frequent bug is a priority inversion or an unintended lockup where a low-priority ISR holds a resource a high-priority path needs. Careful priority assignment and short critical sections keep the system predictable.

    ISR Best Practices in Practice

    The single most important rule: keep ISRs short and bounded. An ISR runs with other interrupts possibly masked and steals time from the whole system, so it should do the minimum — clear the hardware flag, grab the data, and defer the heavy work.

    1. Do the least possible. Read the byte, timestamp the event, set a flag or post to a queue, then return. Push parsing, filtering, and printing to the main loop or an RTOS task.
    2. Share data safely. Mark variables shared with the main context as volatile so the compiler does not cache stale values, and protect multi-byte updates with a short critical section or atomic access.
    3. Always clear the interrupt flag. Forgetting to acknowledge the source re-triggers the ISR immediately, producing an interrupt storm that starves the main program.
    4. Never block. No delays, no busy-waits, no calls that spin or can sleep. An ISR must have a bounded, short execution time.
    5. Use a deferred model. The classic pattern is "top half / bottom half": the ISR is the top half; a task, work queue, or main-loop flag is the bottom half that does the real processing.

    In an RTOS such as FreeRTOS, ISRs communicate with tasks using the FromISR API variants (for example xQueueSendFromISR) and may request a context switch on exit so a freshly-unblocked high-priority task runs immediately.

    Interrupt flow on a Cortex-MPeripheraltimer, UART...NVICenable + priorityCPU corestack + vectorISR runsclear flag, deferMain coderesumesCourseTron · coursetron.com
    Interrupt flow: a peripheral raises its line, the NVIC checks enable and priority, the core stacks state and fetches the vector, the ISR runs, and main code resumes.

    How Industry Tools Handle Interrupts

    Vendor tooling makes interrupt configuration far less error-prone than hand-writing register values. STMicroelectronics' STM32CubeMX and HAL generate the NVIC enable calls, priority-group settings, and weak ISR stubs for you, so you fill in only the handler body. Silicon Labs, NXP, and Microchip ship equivalent configurators. The CMSIS standard from Arm provides a uniform API — NVIC_EnableIRQ(), NVIC_SetPriority() — so code ports across Cortex-M vendors.

    On the debugging side, tools like SEGGER SystemView and Percepio Tracealyzer visualise exactly when each ISR fired and how long it ran, exposing latency spikes and overlong handlers. Logic analysers with GPIO toggling at ISR entry and exit remain a cheap, precise way to measure real latency and execution time on the bench. RTOS kernels add interrupt-safe primitives and a documented maximum priority at which their API may be called.

    Learn this hands-on

    Real projects and industry tool flows, with certification.

    Explore CourseTron Courses →

    interrupts in embedded systems — Interview FAQ

    What is the difference between an interrupt and polling?

    Polling has the CPU actively and repeatedly check a status register, consuming cycles even when nothing changes. An interrupt is event-driven: the peripheral signals the CPU only when service is needed, giving lower latency, lower power, and better CPU utilisation. Polling can be simpler and more deterministic for very fast, tightly bounded loops, but interrupts scale far better across many sources.

    Why should an ISR be kept as short as possible?

    While an ISR runs it can block equal- or lower-priority interrupts and steals time from the main program, hurting overall responsiveness and worst-case latency. A long ISR risks missing other time-critical events. Best practice is to do only the urgent minimum — clear the flag, capture data, signal a task — and defer heavy processing to the main loop or a dedicated task.

    What does the volatile keyword do for interrupt-shared variables?

    volatile tells the compiler the variable can change outside the normal program flow, so it must read it from memory each time rather than caching it in a register or optimising the access away. Without it, a flag set inside an ISR might never appear to change in the main loop. Note that volatile guarantees visibility, not atomicity — multi-byte values still need a critical section or atomic access.

    What is interrupt nesting and how does the NVIC support it?

    Nesting means a higher-priority interrupt can preempt an ISR that is already executing, run to completion, and then return to the original ISR. The Cortex-M NVIC supports this natively through configurable preemption-priority levels: an interrupt preempts only if its preemption priority is higher (numerically lower) than the one currently running. Sub-priority merely orders simultaneously-pending interrupts of equal preemption level.

    Related: a related topic · the VLSI Glossary · all courses.

    Advertisement