Embedded software architecture
Structure software so that responsibilities, control flow, data ownership and failure containment remain understandable as the product grows and changes.
After this module, you should be able to:
- Decompose software around stable responsibilities
- Describe structure and runtime behaviour using complementary views
- Control dependencies, state and shared resources
- Connect architectural decisions to verification evidence
Architecture makes the difficult software decisions visible.
Embedded software architecture defines the major elements, their responsibilities, the rules by which they interact and the constraints that protect important system qualities. It sits between system allocation and detailed implementation.
A useful architecture explains more than a source tree. It shows where behaviour lives, which component owns each state and item of data, how events flow, what may block, how faults are contained and which elements depend on hardware.
Separate policies from mechanisms and hardware detail.
| Area | Architectural decision | Questions to answer |
|---|---|---|
| Application behaviour | State machines, use-case controllers or event handlers. | Who owns the operational state and validates transitions? |
| Domain logic | Algorithms and decisions independent of device drivers. | Can core behaviour be tested without target hardware? |
| Hardware abstraction | Typed interfaces above registers, buses and vendor libraries. | Which hardware differences are hidden and which must remain visible? |
| Execution | Tasks, interrupts, priorities, queues and synchronisation. | Where may code block, pre-empt or share a resource? |
| Data | Ownership, lifetime, validity, persistence and configuration. | Who may change the value, and how does a consumer know it is current? |
| Fault management | Detection, reporting, containment, safe response and recovery. | Can failure in one element corrupt control elsewhere? |
| External interfaces | Protocol adaptation, validation and version boundaries. | Where is untrusted or malformed input converted into trusted internal data? |
Common patterns—layers, pipelines, publish/subscribe, active objects, supervisors and hardware-abstraction layers—are useful only when their trade-offs match the system. Combining patterns deliberately is normal; allowing accidental dependencies is not.
Use several views because no single diagram answers every question.
- Context and allocation. Show external interfaces and the system behaviours assigned to software.
- Static structure. Show components, responsibilities, provided interfaces and permitted dependencies.
- Runtime behaviour. Trace critical scenarios across interrupts, tasks, queues and state transitions.
- Data view. Define important data, ownership, units, validity, retention and concurrency controls.
- Deployment view. Map executables, boot stages and software elements to processors and memory regions.
- Safety and security view. Show trust boundaries, privilege, isolation, monitors and protection mechanisms.
- Decision records. Capture alternatives, rationale, assumptions and consequences for major choices.
Worked example: multi-channel thermal controller
Four channels share an MCU, but each channel must retain independent state, sensor validity and output limits.
Drivers publish typed observations rather than changing application state directly. Each channel service owns its state machine. A separate supervisor compares commanded and measured behaviour, while one output arbiter is the only component permitted to energise heaters. This makes authority explicit and enables algorithms and state logic to run in host-based tests.
Show that the implemented software preserves the architecture.
Complementary views, component responsibilities, interfaces, constraints and conventions.
Allocation of system and software requirements, hazards and security controls to elements.
Types, units, ownership, timing, errors, preconditions and postconditions.
Alternatives, rationale, assumptions, quality-attribute impact and approval.
Dependency rules, static analysis, code review and tests that detect architectural erosion.
Traces showing start-up, control, shutdown, update and fault behaviour across elements.
Common failure patterns
Any component can change shared data, so ownership and sequencing become unknowable.
Application decisions leak into hardware drivers and cannot be tested or changed independently.
Boxes look orderly, but nothing prevents forbidden calls, blocking or cross-layer access.
The description is not updated after learning from implementation, integration or risk analysis.
Further learning
- NASA Software Engineering Handbook: Software Design DescriptionArchitectural elements, interfaces, decisions, multiple views and quality attributes.
- Arm CMSIS documentationA practical example of standard interfaces between processor, peripherals, drivers and software frameworks.
Make ownership and dependency rules explicit.
A durable embedded software architecture shows who owns behaviour and data, how execution flows and which constraints protect timing, safety, security and testability.