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