Interrupt Handlers — volatile, reentrancy, critical sections - MarekBykowski/readme GitHub Wiki
// Variables shared between ISR and main must be volatile
volatile uint32_t tick_count = 0;
void SysTick_Handler(void) { // ISR — called by hardware
tick_count++; // write
}
void main(void) {
while (1) {
uint32_t t = tick_count; // volatile — reads fresh value
do_work(t);
}
}
Critical section — disable interrupts for atomic read-modify-write:
// ARM Cortex-M
uint32_t save = __get_PRIMASK();
__disable_irq(); // enter critical section
shared_var += 1; // safe — interrupts disabled
__set_PRIMASK(save); // restore (don't just re-enable blindly)
// Linux kernel equivalent
unsigned long flags;
spin_lock_irqsave(&lock, flags);
shared_var += 1;
spin_unlock_irqrestore(&lock, flags);
ISR rules:
| Rule | Why |
|---|---|
| Keep ISR short | interrupts blocked while ISR runs |
No malloc/free in ISR |
heap is not reentrant |
No blocking calls (printf, sleep) |
will deadlock or corrupt |
| Set a flag, process in main loop | standard pattern |
All shared vars must be volatile |
or compiler optimises reads away |