Search topics...
Operating Systems & RTOSInterruptsintermediate

What are the design rules for writing an Interrupt Service Routine (ISR)?

0 upvotes
Practice with AISoon
Study the fundamentals first — Operating Systems & RTOS topic page

ISR design rules are among the most frequently tested topics in embedded interviews. The core principle is: keep ISRs short and fast.

Key rules: (1) Do not block — never call functions that can block (e.g., xSemaphoreTake, malloc, printf). ISRs run outside the context of any task and cannot be suspended. Most RTOS APIs have separate ISR-safe versions (e.g., xSemaphoreGiveFromISR in FreeRTOS). (2) Minimize execution time — long ISRs increase interrupt latency for all lower-priority interrupts. Do the minimum work: acknowledge the hardware, read/write hardware registers, set a flag or give a semaphore, then exit. Defer complex processing to a task. (3) Do not call non-reentrant functions — functions like printf, malloc, or strtok use global state and are not safe from ISR context. (4) Be aware of stack usage — ISRs typically run on a separate interrupt stack (on Cortex-M, the MSP), which is often small. Deep call chains or large local variables can overflow it. (5) Use volatile for shared variables — any variable shared between an ISR and a task must be declared volatile so the compiler does not optimize away reads/writes.

The top-half / bottom-half pattern (common in Linux) splits interrupt handling: the top half (ISR) does minimal hardware interaction and schedules a bottom half (tasklet, workqueue, or deferred procedure call) that runs later in a context where blocking is allowed. In an RTOS, the equivalent is to give a semaphore from the ISR and have a dedicated task waiting on that semaphore to do the actual processing.

Source: Operating Systems & RTOS Q&A