Search topics...
Interrupts & PrioritiesISR Design & Basicsfoundational

Why should ISRs be kept short? What do you do if an interrupt requires heavy processing?

0 upvotes
Practice with AISoon
Study the fundamentals first — Interrupts & Priorities topic page

An ISR runs at an elevated hardware priority level, meaning it blocks all interrupts of equal or lower priority for its entire duration. A long-running ISR directly increases interrupt latency for every other interrupt in the system. For example, if a UART RX ISR takes 200 microseconds to process a received packet, and a motor control timer ISR fires during that window, the motor update is delayed by up to 200 microseconds — potentially causing a missed control loop deadline, audible motor noise, or even a safety hazard. In a real-time system, the worst-case latency of every ISR contributes to the worst-case response time of every other ISR at the same or lower priority level.

Beyond latency, long ISRs cause stack pressure (nested interrupts each consume 32+ bytes of stack), increase the probability of priority inversion scenarios, and make the system harder to reason about. A general rule: ISRs should complete in microseconds, not milliseconds. Do the minimum work necessary — acknowledge the interrupt source by clearing the flag, capture time-critical data (read a register, copy a DMA result, sample a pin state), set a flag or enqueue data, and return immediately.

For heavy processing, the standard pattern is deferred processing. In a bare-metal super-loop, the ISR sets a volatile flag and the main loop checks it, performing the expensive work at base priority level where it cannot block other interrupts. In an RTOS, the ISR posts to a semaphore or message queue that wakes a dedicated task — this is the "bottom half" pattern borrowed from Linux. For example, a UART ISR copies received bytes into a ring buffer and signals a semaphore; the parser task wakes up, processes the complete message, and goes back to sleep. FreeRTOS provides xSemaphoreGiveFromISR() and xQueueSendFromISR() specifically for this. The key discipline is separating the time-critical capture (ISR) from the time-tolerant processing (task or main loop).

Source: Interrupts & Priorities Q&A