State Machines in Embedded C

Model device behaviour as explicit states and events instead of nested flags and delays.

Most firmware is reactive: wait for an event, act, wait again. Expressing that with boolean flags and nested ifs quickly becomes unreadable. A finite state machine (FSM) makes every state and every allowed transition explicit — and it never blocks.

Design guidelines

while (!timer_done) { } // inside a state Return from fsm_step and wait for the EV_TIMER event

Blocking inside a state freezes every other part of the system; the FSM should only react to events.

Why give the switch a default branch even when all enum values are handled?

Memory corruption or a bit flip can put an invalid value into the state variable; the default branch drives the system back to a known safe state.