Deploying the Application on the Toolstick
Deploying the application on the Toolstick requires only providing the board-specific initialization and the time-tick interrupt, which must call the QP-nano function
QF_tick() to generate the
TIMEOUT events. The PELICAN example contains a small board support package (bsp.c) for the Toolstick, which has been modeled largely after the standard PWM_demo application that comes on the Toolstick CD.
The code accompanying this article contains an extensive README file explaining all the examples included and the usual workarounds for minor bugs in the demo tools and their incompatibilities. I just wanted to mention here that I ended up using the 4-KB KickStart(tm) 8051 compiler from IAR Systems, instead of the 2-KB demo version of the Keil 8051 compiler that comes with the Toolstick. Finally, because the memory footprint is of primary interest in this article, here are the numbers I've obtained with the IAR 8051 compiler optimized for size: QP-nano: 1254 bytes of CODE, 1 byte of DATA; application totals: 2712 bytes of CODE, 16 bytes of DATA, 88 bytes of IDATA (including 64 bytes of stack), 1 byte of BIT memory.
Reuse of Behavior in UML Statecharts
Statecharts achieve reuse of actions and transitions through a combination of hierarchy and "programming-by-difference" semantics. States may have substates that inherit the actions and transitions of their superstates, just as classes have subclasses that inherit the attributes and operations of their superclasses.
For example, a state diagram of a pocket calculator can be vastly simplified by introducing an abstract superstate "on" that contains most of the calculator states inside (see Figure 4).
To understand how the high-level transitions apply, assume that the user presses the
CANCEL button while the calculator state machine is in the
result state. The state
result does not pre-scribe how to handle the
CANCEL event. However, the
CANCEL event is not silently discarded, as it would be the case in the traditional FSM. Rather, because
result is now nested inside the
on superstate, the state machine attempts to handle the event at the higher level of state hierarchy of the
on state. Because UML statecharts support entry and exit actions on states, the self-transition
CANCEL in the
on state requires in this case exiting the
result state, exiting the
on state, en-tering the
on state again, taking the initial transition within the
on state, and finally entering the
In summary, the transition
CANCEL took the state machine from state
result to state
begin, properly exiting and entering all the states on the way. Identical argumentation can be made for every substate of the
on superstate, so the single
CANCEL transition in the
on superstate replaces all low-level transitions that would be necessary in the traditional "flat" FSM without hierarchy.
As you can see, the semantics of hierarchical state nesting is based on the "programming-by-difference" principle. All substates of the
on superstate need only define the differences from the superstate, and otherwise can reuse the behavior by simply ignoring the commonly handled events, such as
UML-style state machines can help you produce efficient, maintainable, testable systems with well understood behavior, rather than creating the usual "spaghetti" code littered with convoluted ifs and elses. In this article I've demonstrated that the technique is applicable to quite small systems, starting from about 4KB of ROM, and some 128 bytes of RAM.
Contrary to widespread misconceptions, you don't need big UML tools to take full advantage of the hierarchical state nesting and the guaranteed initialization and cleanup of states, which are the most important features of UML statecharts. In fact, manual coding of a nontrivial PELICAN crossing statechart turned out to be a rather simple exercise in following just a few straightforward rules. The implementation technique based on an "event processor", such as QP-nano, results in concise, highly maintainable code that truly reflects the statechart structure without any repetitions. The resulting state machine representation in C is flexible, allowing even sweeping changes in the state machine structure to be accomplished quite easily, at any stage of the project.
Once you design a system with UML statecharts, you will not want to go back to the "spaghetti" code or even to the traditional RTOS. Welcome to the 21st century.
Miro Samek is the Founder and President of Quantum Leaps, a provider of real-time, state machine-based application frameworks for embedded real-time systems, and author of "Practical Statecharts in C/C++" (CMP Books, 2002).