0% found this document useful (0 votes)
71 views50 pages

Design Patterns in Resource-Constrained Embedded Systems-2

The document discusses design patterns specifically tailored for resource-constrained embedded systems, emphasizing the need for performance, power efficiency, and code clarity. It covers various patterns such as Cooperative Scheduler, State Machine, Event Loop, and others, detailing their purposes, use cases, and best practices. The conclusion highlights the importance of understanding system limitations and the necessity of using these patterns to create reliable embedded firmware.

Uploaded by

neto.alceu
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
71 views50 pages

Design Patterns in Resource-Constrained Embedded Systems-2

The document discusses design patterns specifically tailored for resource-constrained embedded systems, emphasizing the need for performance, power efficiency, and code clarity. It covers various patterns such as Cooperative Scheduler, State Machine, Event Loop, and others, detailing their purposes, use cases, and best practices. The conclusion highlights the importance of understanding system limitations and the necessity of using these patterns to create reliable embedded firmware.

Uploaded by

neto.alceu
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 50

Design Patterns in

Resource-Constrained
Embedded Systems
Table of Contents
Table of Contents
1. Introduction
2. Cooperative Scheduler Pattern
3. State Machine Pattern
4. Event Loop Pattern
5. Singleton Pattern
6. Command Pattern
7. Observer Pattern
8. Strategy Pattern
9. Factory Pattern
10.Active Object Pattern
11.Hierarchical State Machine (HSM)
12.Object Pool Pattern
13.Proxy Pattern
14.Template Method Pattern
15.Conclusion
1. Introduction
1. Introduction
Designing embedded firmware for resource-
constrained systems is a delicate balance
between performance, power efficiency, and
code clarity. Unlike application-level
development on full-fledged operating systems,
these systems operate with limited SRAM (often
less than 2KB), single-core processors, and no
built-in support for multitasking. As such,
firmware engineers must architect software
with deterministic behavior, minimal stack
usage, and absolute control over timing.
1. Introduction
Design patterns, when properly applied,
become powerful tools to manage complexity
and reuse tested architectural principles.
However, not all patterns translate well to bare-
metal embedded systems. This article explores
patterns that have been adapted to low-level
environments such as AVR microcontrollers (e.g.,
ATtiny1616), where interrupts, non-blocking
execution, and low-power states are the rule,
not the exception.
2. Cooperative
Scheduler Pattern
2. Cooperative Scheduler
Pattern
Purpose
Implements multitasking in a non-preemptive
way by explicitly yielding control between tasks.

Use Case in Embedded


Enables simple task scheduling on single-core
MCUs without RTOS support. Tasks must
complete quickly or yield periodically to keep
the system responsive.

Best Practice Notes


• Avoid blocking delays (_delay_ms()).
• Design tasks to run for a bounded time.
• Use timer flags or counters to defer
execution.
2. Cooperative Scheduler
Pattern
Example
3. State Machine
Pattern
3. State Machine
Pattern
Purpose
Encapsulates system behavior into defined
states and transitions, promoting clear logic
separation.

Use Case in Embedded


Used for debouncing buttons, protocol parsing,
and user interface handling.

Best Practice Notes


• Use enums for states.
• Transition logic must remain non-blocking.
• Each state must do minimal work per call.
3. State Machine
Pattern
Example: Button Debounce FSM
3. State Machine
Pattern
4. Event Loop Pattern
4. Event Loop
Pattern
Purpose
Processes events in a loop, deferring action logic to
event handlers.

Use Case in Embedded


Ideal for communication stacks, central control
loops, or serial command processing.

Best Practice Notes


• Use event flags or queues.
• Keep handlers fast and deterministic.
4. Event Loop
Pattern
Example: Central Event Loop
5. Singleton Pattern
5. Singleton
Pattern
Purpose
Ensures a peripheral or manager is accessed
through a single instance.

Use Case in Embedded


Used to abstract hardware peripherals like
UART, ADC, or SPI, where duplicate access is
unsafe.

Best Practice Notes


• Implement as a static function-scoped
instance.
• Avoid dynamic memory.
5. Singleton
Pattern
Example: UART Singleton
6. Command Pattern
6. Command
Pattern
Purpose
Encapsulates actions as objects to decouple
command issuance from execution.

Use Case in Embedded


Used in CLI interpreters, menu systems, or
motor control logic.

Best Practice Notes


• Define command structs or enums.
• Use function pointers to execute commands.
6. Command
Pattern
Example: CLI Command Handler
7. Observer Pattern
7. Observer
Pattern
Purpose
Allows multiple modules to react to state changes
in another module.

Use Case in Embedded


Used in sensor threshold alerting or decoupled
UI updates.

Best Practice Notes


• Use function pointers or callback registries.
• Limit callback duration.
7. Observer
Pattern
Example: Temperature Observer
8. Strategy Pattern
8. Strategy
Pattern
Purpose
Allows runtime selection of behavior among
multiple algorithms.

Use Case in Embedded


Used for selecting communication methods,
power modes, or filtering techniques.

Best Practice Notes


• Define interfaces via function pointers.
• Keep strategy structs static.
8. Strategy
Pattern
Example: Power Mode Strategy
9. Factory Pattern
9. Factory
Pattern
Purpose
Provides a way to create objects without exposing
the instantiation logic.

Use Case in Embedded


Used for abstracting different driver backends.

Best Practice Notes


• Use config constants or init structs to drive
instantiation.
• Avoid malloc—use statically allocated
buffers.
9. Factory
Pattern
Example: Sensor Factory
10. Active Object
Pattern
10. Active Object
Pattern
Purpose
Separates method execution into its own context
(thread or task).

Use Case in Embedded


Used with queues in RTOS environments or ISR-
to-task communication.

Best Practice Notes


• Use FreeRTOS queues or ring buffers.
• Decouple ISR logic from heavy processing.
10. Active Object
Pattern
Example: Logger Task
11. Hierarchical State
Machine (HSM)
11. Hierarchical State
Machine (HSM)
Purpose
Extends FSMs by supporting state nesting and
reuse.

Use Case in Embedded


Used in communication stacks, display logic, or
robotic behaviors.

Best Practice Notes


• Model common substates (e.g., Error, Idle).
• Manage transitions cleanly with events.
11. Hierarchical State
Machine (HSM)
Example: BT State Tree
11. Hierarchical State
Machine (HSM)
12. Object Pool
Pattern
12. Object Pool
Pattern
Purpose
Avoids fragmentation and allocation overhead by
reusing pre-allocated objects.

Use Case in Embedded


Used for packet buffers, command structs, or
job queues.

Best Practice Notes


• Use circular buffers or free lists.
• Never use malloc/free in ISR or runtime.
12. Object Pool
Pattern
Example: UART Packet Pool
13. Proxy
Pattern
13. Proxy
Pattern
Purpose
Acts as a controlled interface to access complex or
sensitive resources.

Use Case in Embedded


Used for EEPROM, Flash, or I2C abstraction with
added safety or caching.

Best Practice Notes


• Use static structs and clear boundaries.
• Implement protection for concurrent or
unsafe access.
13. Proxy
Pattern
Example: EEPROM Proxy
14. Template
Method Pattern
14. Template
Method Pattern
Purpose
Defines the skeleton of an operation, deferring
specific steps to subclasses.

Use Case in Embedded


Used to standardize interface behavior across
hardware-specific drivers.

Best Practice Notes


• Use function pointers in base structs.
• Keep the "template" flow centralized.
14. Template
Method Pattern
Example: Sensor Read Template
14. Template
Method Pattern
15. Conclusion
15. Conclusion
Design patterns offer powerful abstractions
and reusable structures for embedded software
development, especially under tight memory,
power, and performance constraints. When
adapted correctly, they provide maintainable
and scalable architectures even for bare-metal
microcontrollers like the ATtiny1616.

However, using them effectively requires a deep


understanding of the system's limitations. Avoid
dynamic memory, keep execution non-blocking,
and prioritize deterministic behavior. These
patterns are not just academic concepts—
they’re essential tools for delivering reliable
embedded firmware in the real world.

You might also like