EmbeddedRelated.com

Finite State Machine

Category: Architecture | Also known as: state machine, FSM

A finite state machine (FSM) is a computational model in which a system exists in exactly one of a finite number of defined states at any given time, transitioning between states in response to defined inputs or events. FSMs are widely used in embedded firmware to manage control flow, protocol handling, and reactive behavior in a structured, maintainable way.

In practice

In embedded systems, FSMs replace deeply nested if/else or switch/case logic with an explicit model of system behavior. Each state captures what the system is doing right now, each transition defines when and why it moves to a different state, and optional entry/exit actions run code at the moment a state is entered or left. This separation of concerns makes behavior easier to reason about, test, and extend. Common embedded use cases include button debouncing, communication protocol parsers (UART framing, Modbus, USB protocol stages), motor control sequences, power management modes, and menu navigation on display-based devices.

Two dominant implementation patterns appear in C/C++ firmware. The flat FSM uses a single switch statement over a state enum inside a periodically called function -- simple to write and sufficient for small machines with few states and no hierarchy. The table-driven FSM stores states, events, actions, and next-states in a 2D array or array of structs, making transitions data rather than code and reducing the risk of forgetting a case; note that some table-driven designs use sparse tables or default handlers rather than enumerating every possible state-event combination. More advanced designs use function pointers or virtual methods so each state owns its own event-handling logic, which scales better as the number of states grows. The blog posts "Finite State Machines (FSM) in Embedded Systems (Part 1)" through "Part 3" cover these patterns in detail, including a C++ DSL approach for reducing boilerplate.

A common pitfall is conflating the current state with a mode flag or a set of boolean variables scattered across the codebase -- an informal, implicit FSM that is hard to audit. Making the FSM explicit forces every possible state and every valid transition to be named, which surfaces missing or unintended transitions early. Another frequent mistake is performing long blocking operations inside a state's action code; on bare-metal systems without an RTOS, this stalls the entire state machine and can miss events. Keeping actions short and deferring long work to background tasks or interrupts is the standard remedy.

Hierarchical state machines (HSMs), popularized by Miro Samek's Quantum Platform (QP) framework, extend flat FSMs by allowing states to nest inside parent states that share common behavior. This avoids duplicating transitions across many peer states. For most simple embedded control problems a flat FSM is sufficient; HSMs pay off when the number of states grows large or when many states share significant common behavior. The "Implementing State Machines" blog post discusses practical trade-offs between flat and hierarchical approaches.

Discussed on EmbeddedRelated

Frequently asked

What is the difference between a Mealy machine and a Moore machine?
In a Moore machine, outputs depend only on the current state. In a Mealy machine, outputs depend on both the current state and the current input or event. Many embedded FSM implementations are mixed Mealy/Moore in practice; those that trigger actions primarily on transitions lean Mealy, while those that produce outputs based on entry into a state lean Moore. The distinction rarely affects which implementation pattern you choose in practice.
When should I use a table-driven FSM instead of a switch/case FSM?
A switch/case FSM is quick to write and easy to debug for small machines (roughly under 10 states and 10 events). As the machine grows, the switch/case approach becomes hard to audit for missing transitions and invites copy-paste bugs. A table-driven approach makes state-event handling explicit in data, which is easier to review and to generate from a tool, at the cost of slightly more upfront structure.
How do FSMs interact with interrupts or an RTOS?
A common pattern is to have ISRs or RTOS tasks post events into a queue and have the FSM run in a dedicated task or in the main loop, consuming events one at a time. This decouples event production from state processing and keeps FSM transition logic outside of interrupt context, where long execution or blocking is problematic.
What is a hierarchical state machine (HSM) and when is it worth the complexity?
An HSM allows states to be nested inside parent states. A transition not handled by a child state can propagate up to the parent, so common behavior is defined once rather than duplicated across sibling states. HSMs are worth the added complexity when a flat FSM starts accumulating many states that share large amounts of transition logic. Miro Samek's QP framework is a well-known implementation used in embedded systems.
Can I generate FSM code from a diagram tool?
Yes. Tools such as Yakindu Statechart Tools, Miro Samek's QM modeler, and various UML tools can generate C or C++ FSM code from a statechart diagram. This is common in safety-related or larger projects where the diagram serves as documentation and the code is derived from it, reducing manual transcription errors. For small projects the overhead of a modeling tool often outweighs the benefit.

Differentiators vs similar concepts

FSM vs. HSM (hierarchical state machine): a flat FSM has no state nesting; every state is a peer. An HSM adds parent-child relationships between states so that unhandled events bubble up to a parent state. HSMs are a specialization of FSMs with hierarchy added; the two terms are sometimes used loosely and interchangeably, though they are technically distinct. HSM implementations such as QP/C and QP/C++ are distinct libraries from simple switch/case or table-driven flat FSMs.