Conslabs
Embedded Firmware Basics
intermediateMarch 5, 2025 · 3 min read

Timers & Interrupts

How hardware timers generate precise timing without CPU polling, and how interrupts let firmware react to events in real time.

GPIO, serial protocols, and analog I/O cover how firmware moves data. Timers and interrupts are what let firmware time things precisely and react to events without burning CPU cycles on polling.

Timers

A hardware timer is a register that increments on every clock tick (or every Nth tick, via a prescaler) and can trigger an event when it reaches a target value. This offloads precise timing from software loops, which are at the mercy of compiler optimization and interrupt jitter, onto dedicated silicon.

timer_frequency = clock_frequency / (prescaler + 1)
overflow_period = (auto_reload_value + 1) / timer_frequency

Worked example: a 16 MHz clock, prescaler of 15999, and auto-reload value of 999 gives:

timer_frequency = 16,000,000 / 16,000 = 1,000 Hz
overflow_period = 1,000 / 1,000 = 1 second

This is the standard pattern for generating a precise 1 Hz tick without any CPU polling — the timer counts independently of whatever the main program is doing.

Interrupts

An interrupt lets a peripheral suspend normal program execution and jump to a dedicated handler the instant an event occurs — a timer overflow, an incoming UART byte, a GPIO edge — instead of the CPU repeatedly polling a status flag.

volatile uint32_t tick_count = 0;
 
void TIM2_IRQHandler(void) {
    if (TIM2_SR & TIM_SR_UIF) {   // overflow flag set
        TIM2_SR &= ~TIM_SR_UIF;   // clear it
        tick_count++;
    }
}

Two rules matter once interrupts are involved:

  • Any variable shared between an interrupt handler and main-line code must be volatile — and for anything wider than the platform's atomic access width, it needs explicit protection (disabling interrupts briefly, or a hardware atomic instruction).
  • Keep interrupt handlers short. A handler that runs too long delays every lower-priority interrupt and can blow timing budgets elsewhere in the system. The common pattern is to do the minimum in the handler (clear the flag, capture data, set a flag) and defer the rest to the main loop or a task.

Polling vs. interrupts vs. DMA

ApproachCPU involvementBest for
PollingContinuous, blocks other workSimple, latency-insensitive bare-metal loops
InterruptBrief, only on eventSporadic events: button press, UART byte
DMANone — peripheral writes memory directlyHigh-throughput streams: ADC sampling, audio

Understanding when to escalate from polling to interrupts to DMA is one of the more practical judgment calls in embedded firmware. It's also exactly where bare-metal loops start to strain under multiple competing timing demands — which is what the next lesson, Real-Time Systems & RTOS, is built to handle.