1. A Message Based
C++ Object Oriented Hierarchial
State Machine Architecture for
Embedded Systems
Manuel Sardinha
ATSystems Inc.
mSardinha@ATSystemsInc.com
12/9/2003
2. Introduction to Software State
Machines
• Advantages of a state machine
implementation
• State machine components
3. Advantages of a State Machine
Implementation
• Easier to manage the design and
debugging of mission critical and complex
software.
• A structured framework for managing
every possible event for every possible
condition or state.
• Efficient debugging using centralized base
class logic, for tracking all processed and
generated events and state transitions.
4. State Machine Components
• Run Loop
• State table implementation
• State function implementation
• State Transitions
5. Run Loop
• A run loop is the main driving function of the
state machine, which calls a state function with
the event as a parameter.
• Each iteration of the run loop processes an
event within the context of the current state.
• The next event to be processed can be retrieved
from message queue, or it could be returned
from the function called for the current state.
6. State Table Implementation
• In this implementation, each row
represents a state and each column
represents an event, and each cell
contains a pointer to a function to handle
one event for a specific state.
• The disadvantage of this approach is that
the state table sometimes becomes
sparsely populated, since many events
make no sense within a given state.
7. State Function Implementation
• In this implementation, each state is
implemented with a single function, in which the
event is passed as an argument. Within this
state function, each event becomes a case
within a switch statement.
• The disadvantage is that each state function is
unique to a specific state, which limits reuse by
another state. However, internal logic can be
consolidated with common functions.
8. State Transitions
• A transition from one state to another involves:
– one or more exit events
– one or more entry events
– one start event along with a start event.
– Note: A state transition is not allowed while processing an exit or
an entry event.
• The exit event is the last event processed by a state.
Exit events are normally used for resource cleanup.
• The entry event is the first event processed by the state
being entered. Entry events are normally used for
resource allocation.
• The start event will follow an entry event for only the
destination state.
9. Hierarchical Versus Flat State
Machine Design
• In a flat state machine
design, all states
have equal status
• In a hierarchical state
machine, all states
except the top state
are child states of a
parent state
State1
State2
State3
Flat State Machine
Top
1.0
1.1 1.2
2.0
2.1 2.2
Hierarchical State
Machine
10. Hierarchical State Machine
Advantages
• Code re-use
– If an event is not handled by the current state,
then it is passed up to the parent state –
which is a form of object oriented inheritance
• Encapsulation
– A parent state and all of its child states
represent an encapsulation of an activity or
operational mode, which embodies a sub
state or UML use case object.
12. Hierarchical State Machine
Template
• The design chosen at AT Systems Inc.
was based on the following article in
Embedded Systems Programming
Magazine
• “State Oriented Programming by Miro
Samek and Paul Montgomery (August
2000)
• http://www.state-
machine.com/resources/samek0008.pdf
13. AT Systems Customization
• The run loop was integrated into the state
machine’s base class.
• Events became messages stored in a message
queue.
• Support for deferred events and history was
added to the base state machine class.
• The state transition macro was replaced with a
function.
• A message controller was added for inter object
routing and delivery of messages (i.e. events)
14. Modeling Architecture
• Each controlled device is
modeled with an instance
of a hierarchical state
machine (Hsm).
• PLC modules translate
device data to and from
messages.
• Each software object runs
as a separate task with a
single input message
queue.
Control
HSM A HSM B HSM C
Communications Link
User Interface
PLC A PLC B PLC C
Device A Device B Device C
Serial, TTL, etc. Serial, TTL, etc. Serial, TTL, etc.
15. Message Routing
• A flexible message routing scheme allows for the flexible relocation
of software objects.
• Our solution:
– Each message queue entry is a 32 bit pointer to a message base class,
from which all messages are derived. The overridden MsgId() function
returns the ID of the message queued, and this ID is used within a state
function’s event switch statement.
– We created a Message Controller object that holds and manages the
message queues for all software objects. Initially we embedded the
message queues within each object, but startup messages were
lost when the destination object had not yet been created.
– Message routing is simplified by embedding the source and destination
object ID within the bit fields of each unique message ID.
– Message Controllers in different network nodes can collaborate by
forwarding messages meant for a specific device which may not exist
locally.
16. Design Challenges
• Message latency (i.e. stale messages)
– Stale watchdog timer messages
– Avoiding the use of stale data
• Deferring message processing
• Full input message queue conditions
• Internal State Messages.
17. Stale Watchdog Messages
• Watchdog timer event messages present a special latency problem.
If a watchdog timer fires and the corresponding message is queued,
the processing of previously queued messages may result in the
cancellation of this watchdog. If this occurs, then the stale watchdog
message should not be processed.
• Our solution:
– Wrap the watchdog in a class, and record the current system tick value
when the watchdog is set or reset.
– When the watchdog fires, the current system tick value is embedded in
the queued watchdog event message.
– When the watchdog message is retrieved, the triggered tick value in the
message should be greater than the start tick value in the watchdog
wrapper – otherwise, the message should not be processed (i.e. if it is
stale).
– Note: the VxWorks 64 bit SYSCLOCKTICK “vxAbsTicks” value is used
with overloaded comparison operators to utilize both the “upper” and
“lower” 32 bit elements.
18. Avoiding the Use of Stale Data
• Sometimes the state of a switch or solenoid may change
multiple times before the first such event message can
be processed.
• To avoid making decisions on out of date information due
to message latency, the current state of all switches and
solenoids are maintained in global variables. These
global variables are used to validate each of the “switch
change” event messages.
• For instance, if a message indicates that a switch was
opened, but the corresponding global variable indicates
that the switch is currently closed – then we can assume
that one or more corresponding “switch was closed”
event messages have already been queued.
19. Deferred Message Processing
• Sometimes a state is not able to process an event. In
this case the event is deferred or saved for later
processing when a transition to another state occurs.
• Our solution:
– Create a link list of deferred events in the Hsm base class.
– Pass the deferred events to the new state in FIFO order until all
have been passed – or until another state change occurs as a
result of one of these deferred events.
– If a deferred event is deferred again, put it back on the deferred
list – otherwise delete it.
– If a deferred event results in a state change, restart the list of
deferred events from the beginning for the new state.
• Deferred message processing is mentioned in the UML
State Chart standard.
20. Full Input Message Queue
Conditions
• VxWorks message queues must be created with a fixed
size, which prevents a logic error from filling a queue
with messages that represent all available heap space.
• If a message queue is full, the architect must decide if
the message should be thrown away – or if the object
processing the event message should lock while waiting
for a response message to be queued.
• Care must be taken to avoid a deadly embrace
condition, where 2 objects are queuing message for
each other – and the message queues of both objects
are full.
21. Internal State Messages
• The processing of an event message is atomic, which is
another way of saying that events are handled one at a
time without interruption from other events.
• If the response to an event requires one or more
uninterrupted functions to be executed, then a state can
send one or more event messages to itself to invoke
these atomic functions.
• Messages sent internally can be preallocated as
member elements of an object, which avoids memory
allocation failures. Since the pointer to the message is
all that is placed in the queue – one or more instances of
this same event message can exist in the message
queue simultaneously.
22. Resources for Further Study
• http://www.ddjembedded.com/resources/articles/200
2/0212h/0212h.htm Review of Miro Samek’s
“Practical Statecharts in C/C++”
• http://www.programming-
reviews.com/Practical_Statecharts_in_CC_Quantum_Pr
ogramming_for_Embedded_Systems_with_CDROM_15
78201101.html Review of Miro Samek’s “Practical
Statecharts in C/C++”
• http://www.eventhelix.com/RealtimeMantra/HierarchicalS
tateMachine.htm
• http://www.usecasemaps.org/pub/isorc2000.pdf
• http://www.ee.uts.edu.au/~drowe/PhD/publish/cotar_
ws/cotar_ws.htm