Click here to Skip to main content
Click here to Skip to main content

Develop embedded systems based on UML state machines

By , 1 Jun 2005
 

Sample Image

Figure 1: The State Tree of PowerUpDown Application in Running Mode

Introduction

This article discovers how to develop and simulate cross-platform embedded systems using UML State Machine Wizard.

Background

Embedded systems are some special purpose computers that are used inside of devices. Embedded systems generally use micro controllers that contain many functions of a computer on a single device.

Embedded systems have to tightly work together with special hardware. They have to respond to external interactions in a predetermined amount of time. Usually embedded systems are real time.

Many embedded system applications are natural candidates for being organized as a state machine. A program that must sequence a series of actions, or handle inputs differently depending on what state it's in, is often best implemented as a state machine.

Thus most embedded systems support state machine based design where multiple events can be received in a single state. The next state is determined by the contents of the received event. State machines provide a very flexible mechanism to handle asynchronous event interactions. The flexibility comes with its own complexities.

Visual C++ is a powerful software developing tool. However it aims at developing Windows-specific applications. UML State Machine Wizard acts as a Visual C++ add-in, which provides a UML (Unified Modeling Language) state machine programming mechanism in portable standard C for embedded systems developing and simulating in Visual C++ developer studio. After simulating and debugging, developer can move the program to a destination working environment with little or no extra investment or effort.

Using the code

There are a number of ways to show state machines, from simple tables through graphically animated illustrations. State Machine Wizard shows and organizes state machines in two ways: state tree and state chart. State Machine Wizard defines a set of specific macros as state machine mapping data. These macros map to state enumerations, event handler function declarations, event handler table for a state, state tree definition and application variable definition. In the following source file PowerUpDown.c, State Machine Wizard generates the following macros to define the PowerUpDown application:

SME_BEGIN_STATE_DEF(PowerUpDown,PowerUpDown)
    /*{{SME_STATE_DEF(PowerUpDown,PowerUpDown)*/
    SME_STATE_ENTRY_FUNC(PowerUpDownEntry)
    SME_STATE_EXIT_FUNC(PowerUpDownExit)
    SME_ON_EVENT(EVENT_KEY_LEFTSOFT, 
        OnPowerUpDownEVENT_KEY_LEFTSOFT,SME_INTERNAL_TRAN)
    SME_ON_EVENT(EVENT_KEY_RIGHTSOFT,
        OnPowerUpDownEVENT_KEY_RIGHTSOFT,SME_INTERNAL_TRAN)
    /*}}SME_STATE_DEF*/
SME_END_STATE_DEF

SME_BEGIN_STATE_DEF(PowerUpDown,PowerDown)
    /*{{SME_STATE_DEF(PowerUpDown,PowerDown)*/
    SME_STATE_ENTRY_FUNC(PowerDownEntry)
    SME_STATE_EXIT_FUNC(PowerDownExit)
    SME_ON_EVENT(EVENT_POWER_UP,NULL,PowerUp)
    /*}}SME_STATE_DEF*/
SME_END_STATE_DEF
SME_BEGIN_STATE_DEF(PowerUpDown,PowerUp)
    /*{{SME_STATE_DEF(PowerUpDown,PowerUp)*/
    SME_STATE_ENTRY_FUNC(PowerUpEntry)
    SME_STATE_EXIT_FUNC(PowerUpExit)
    SME_ON_EVENT(EVENT_KEY_POWER,NULL,PowerDown)
    /*}}SME_STATE_DEF*/
SME_END_STATE_DEF
SME_BEGIN_STATE_DEF(PowerUpDown,Idle)
    /*{{SME_STATE_DEF(PowerUpDown,Idle)*/
    SME_STATE_ENTRY_FUNC(IdleEntry)
    SME_STATE_EXIT_FUNC(IdleExit)
    SME_ON_EVENT(EVENT_OPEN_MENU_MAIN,OnIdleEVENT_OPEN_MENU_MAIN,ImageSurf)
    SME_ON_EVENT(EVENT_OPEN_MENU_LANG,OnIdleEVENT_OPEN_MENU_LANG,MenuSurf)
    SME_ON_EVENT(EVENT_KEY_0,OnIdleEVENT_KEY_0,DigitInput)
    SME_ON_EVENT(EVENT_KEY_1,OnIdleEVENT_KEY_1,DigitInput)
    SME_ON_EVENT(EVENT_KEY_2,OnIdleEVENT_KEY_2,DigitInput)
    SME_ON_EVENT(EVENT_KEY_3,OnIdleEVENT_KEY_3,DigitInput)
    SME_ON_EVENT(EVENT_KEY_4,OnIdleEVENT_KEY_4,DigitInput)
    SME_ON_EVENT(EVENT_KEY_5,OnIdleEVENT_KEY_5,DigitInput)
    SME_ON_EVENT(EVENT_KEY_6,OnIdleEVENT_KEY_6,DigitInput)
    SME_ON_EVENT(EVENT_KEY_7,OnIdleEVENT_KEY_7,DigitInput)
    SME_ON_EVENT(EVENT_KEY_8,OnIdleEVENT_KEY_8,DigitInput)
    SME_ON_EVENT(EVENT_KEY_9,OnIdleEVENT_KEY_9,DigitInput)
    SME_ON_EVENT(EVENT_ON_TIMER,OnIdleEVENT_ON_TIMER,SME_INTERNAL_TRAN)
    /*}}SME_STATE_DEF*/
SME_END_STATE_DEF
SME_BEGIN_STATE_DEF(PowerUpDown,MenuSurf)
    /*{{SME_STATE_DEF(PowerUpDown,MenuSurf)*/
    SME_STATE_ENTRY_FUNC(MenuSurfEntry)
    SME_STATE_EXIT_FUNC(MenuSurfExit)
    SME_ON_EVENT(EVENT_MENU_EXIT,NULL,Idle)
    SME_ON_EVENT(EVENT_MENU_SEL,OnMenuSurfEVENT_MENU_SEL,Function)
    /*}}SME_STATE_DEF*/
SME_END_STATE_DEF
SME_BEGIN_STATE_DEF(PowerUpDown,Function)
    /*{{SME_STATE_DEF(PowerUpDown,Function)*/
    SME_STATE_ENTRY_FUNC(FunctionEntry)
    SME_STATE_EXIT_FUNC(FunctionExit)
    SME_ON_EVENT(EVENT_DLG_OK,OnFunctionEVENT_DLG_OK,Idle)
    SME_ON_EVENT(EVENT_DLG_CANCEL,NULL,Idle)
    /*}}SME_STATE_DEF*/
SME_END_STATE_DEF
SME_BEGIN_STATE_DEF(PowerUpDown,DigitInput)
    /*{{SME_STATE_DEF(PowerUpDown,DigitInput)*/
    SME_STATE_ENTRY_FUNC(DigitInputEntry)
    SME_STATE_EXIT_FUNC(DigitInputExit)
    SME_ON_EVENT(EVENT_EDIT_OK,OnDigitInputEVENT_EDIT_OK,Function)
    /*}}SME_STATE_DEF*/
SME_END_STATE_DEF
SME_BEGIN_STATE_DEF(PowerUpDown,ImageSurf)
    /*{{SME_STATE_DEF(PowerUpDown,ImageSurf)*/
    SME_STATE_ENTRY_FUNC(ImageSurfEntry)
    SME_STATE_EXIT_FUNC(ImageSurfExit)
    SME_ON_EVENT(EVENT_IMAGE_EXIT,NULL,Idle)
    SME_ON_EVENT(EVENT_IMAGE_FUNC,OnImageSurfEVENT_IMAGE_FUNC,Function)
    SME_ON_EVENT(EVENT_IMAGE_OPEN,OnImageSurfEVENT_IMAGE_OPEN,MenuSurf)
    /*}}SME_STATE_DEF*/
SME_END_STATE_DEF
/*{{SME_STATE_STATETREE_SEPARATOR}}*/
SME_BEGIN_STATE_TREE_DEF(PowerUpDown)
    /*{{SME_STATE_TREE_DEF(PowerUpDown)*/
    SME_STATE(PowerUpDown,PowerUpDown,SME_INVALID_STATE,PowerDown)
    SME_STATE(PowerUpDown,PowerDown,0,-1)
    SME_STATE(PowerUpDown,PowerUp,0,Idle)
    SME_STATE(PowerUpDown,Idle,PowerUp,-1)
    SME_STATE(PowerUpDown,MenuSurf,PowerUp,-1)
    SME_STATE(PowerUpDown,Function,PowerUp,-1)
    SME_STATE(PowerUpDown,DigitInput,PowerUp,-1)
    SME_STATE(PowerUpDown,ImageSurf,PowerUp,-1)
    /*}}SME_STATE_TREE_DEF*/
SME_END_STATE_TREE_DEF
/*{{SME_DEC_IMP_SEPARATOR}}*/
SME_APPLICATION_DEF(PowerUpDown, "PowerUpDown")


/* The follows are macro definitions for 
   state machine data mappings in header file. */

#define SME_BEGIN_STATE_DECLARE(_app) \
    enum _app##_state_enum_t \
    {

#define SME_STATE_DECLARE(_state) _state, 

#define SME_MAX_STATE(_app)    _app##_max_state

#define SME_END_STATE_DECLARE };

////////////////
#define SME_ENTRY_FUNC_IDX    0
#define SME_EXIT_FUNC_IDX     1
#define SME_EVENT_HANDLER_FUNC_IDX    2

#define SME_BEGIN_STATE_DEF(_app,_state) \
static const SME_EVENT_TABLE_T _app##_state##_event_hdl_tbl[] \
={

#define SME_STATE_ENTRY_FUNC( _EntryFunc) \
{  SME_INVALID_EVENT_ID, _EntryFunc, 0},

#define SME_STATE_EXIT_FUNC( _ExitFunc) \
{  SME_INVALID_EVENT_ID, _ExitFunc, 0},

#define SME_ON_EVENT(_EventID, _Handler, _NewState) \
{  _EventID, _Handler, _NewState},

#define SME_END_STATE_DEF { SME_INVALID_EVENT_ID, 0, SME_INVALID_STATE}};

#define SME_BEGIN_STATE_TREE_DEF(_app) \
extern const SME_STATE_TREE_TABLE_T _app##_state_tree[] = \
{

#define SME_STATE(_app,_state,_state_parent,_def_substate) \
    {(SME_EVENT_TABLE_T *)_app##_state##_event_hdl_tbl, 
      _state,_state_parent,_def_substate},

#define SME_END_STATE_TREE_DEF };

#define SME_APPLICATION_DEF(_app,_app_name) \
    struct SME_APP_T _app##App = { \
    _app_name, NULL, NULL, 0, NULL, NULL, 
    _app##_state_tree, SME_INVALID_STATE};

/* Get application variable name. */
#define SME_GET_APP_VAR(_app) _app##App

/* Declare application variable that has external linkage. */
#define SME_DEC_EXT_APP_VAR(_app) extern SME_APP_T _app##App;

//

The figure 1 shows the State Tree tab window in running mode. App project consists of the DialogCtrl, MenuCtrl and PowerUpDown applications. PowerUpDown application is comprised of (PowerUp (Idle, MenuSurf, Function), PowerDown) states.

The State Chart gives you a "birds'-eye view" of your application's logical structure and flow. It graphically constructs the state hierarchy, with child states nested within their parent state. Another of State Chart's major advantage over the State Tree is that it displays every state's transitions, in the form of arrows from one state to another state.

Sample Image

Figure 2:The State Chart of PowerUpDown Application

There are two threads in developing embedded system applications, one thread is application developing. The other thread is simulator developing. On each developing thread, we can divide it to the following three stages:

  • Modeling stage
  • Developing/coding stage
  • Simulating/debugging stage

Figure 3: The Developing Stages

After simulating and debugging on the Windows platform, the developer can move the program to a destination working environment with little or no extra investment or effort.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Jerome_D
Web Developer
China China
Member
Jerome. (Free to speak, free to use.)

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionPurchase a license from Intelliwizardmemberxwy12 Mar '12 - 17:50 
Since I want to purchase a license from Intelliwizard, I was trying to send email to info@intelliwizard.com for a long while. But I never get feedback. I would like to know the reason. Could anyone help me to fix the issue?
GeneralOpen engine source codememberJerome_D19 Apr '06 - 20:25 
Open the state machine engine source code at http://www.intelliwizard.com .
 
Jerome. An embedded system developer.
GeneralRe: Open engine source codememberxwy12 Mar '12 - 17:35 
Hi jerome,
I was trying to send email to info@intelliwizard.com for a long while. But I never get feedback. I would like to know the reason. Since I want to purchase a license from Intelliwizard.
GeneralMultiThreaded Operationmembersuperfrigee28 Dec '05 - 17:52 
Hello,
 
Really like this tool....
 
I have been playing with this add-in for a week or so and have found the multithreaded example on the intelliwizard.com website. My question is:
Is the mulithreaded version available for window ce systems?
 

Thanks
 
superfrigee
GeneralRe: MultiThreaded OperationmemberJerome_D30 Dec '05 - 2:14 
superfrigee:
 
Thanks for your remark.
 
Yes, the WinCE edition of StateWizard engine supports multi-thread based on Thread Local Storage.
 
Please download the StateWizard V7.0Beta or upper installation pack at the following url.
 
http://www.intelliwizard.com/down/StateMachineWiz.exe
 
Unzip the sample.exe. There are 2 samples as below. Each sample have 2 threads: one is main thread, the other one is child thread named MediaPlay.
 
1) VC6_PhoneDev
2) EVC_Player

 
Best Regards
Jerome
 
Jerome. An embedded system developer.
GeneralGood Add In!membercynew18 Sep '05 - 22:25 
Laugh | :laugh:
I think it is very useful when developing software on e0mbedded system.
Thanks to author.......
 
chainone
GeneralRe: Good Add In!membernorus.celler28 Sep '05 - 18:15 
Agree, so...nice!! Smile | :) I plan to use it for developing state machine based applications anyway.
GeneralLOST!!memberWREY17 Sep '05 - 7:25 
After downloading both the Wizard and the application source, I ran the wizard to a successful installation and activated it as an Add-In from Tool->Customize.
 
Then I compiled and linked the source application for both 'App' and 'Simulator', and ran the sample.
 
After spending about 20 minutes familiarizing myself with the toolbar icons, reading and rereading your article, experimenting around with different things, I could not get any of the diagrams your article showed, to appear. I played around with both the 'Simulator' sample and the toolbar icons to see what would happen, and NOTHING HAPPENED!!!
 
I uninstalled and reinstalled the wizard and reread your article again and still couldn't make any of the diagrams the article showed, come to life.
 
I checked with the Wizard Help file and received a message that the file was created for a version of windows I don't have, which I can't understand since I have BOTH VC6 and VC7 on my machine, and I was running VC6.
 
Bottom line: After spending about 30 minutes and made no headway, I gave up, uninstalled the wizard, and deleted the sample files.
 
I am very familiar with StateCharts and have been looking around for such a tool to start working with, which is why I was willing to spend the time to see if what you offered would work.
 
Unless you can point out to me what I may have done wrong, what you have posted is totally useless.
 
Poke tongue | ;-P
 
William
 
Fortes in fide et opere!
GeneralYou have to click Add-in CHECKBOX to load WizardmemberJerome_18 Sep '05 - 17:38 
Hi, William
 
No, after you automatic install Wizard you have to follow the below action to load addin:
 
On the Add-ins and Macro Files dialog, choose the Add-ins and Macro Files tab. Click on the CHECKBOX next to UML State Machine Wizard.
 
The installation have no error that I told you before.
 
Best Regards
Jerome
 
Jerome. An embedded system developer.
GeneralRe: You have to click Add-in CHECKBOX to load WizardmemberWREY18 Sep '05 - 18:16 
Did you not read the first sentence of my message? It states, "I ran the wizard to a successful installation and activated it as an Add-In from Tool->Customize."
 
I had already loaded and activated it as an 'Add-in'. That was done. OK! Done!
 
Then the first sentence of the third paragraph said, "After spending about 20 minutes familiarizing myself with the toolbar icons," you can clearly see that I had already done and gotten passed what you are talking about. I would not have been able to use the icons if I had not done the same things you are now talking about.
 
Give me credit for the 30 minutes I spent trying different things.
 
I don't mind your offering suggestions, but read all that I had already tried rather than keep mentioning the same things.
 
D'Oh! | :doh:
 
William
 
Fortes in fide et opere!
 
-- modified at 0:18 Monday 19th September, 2005
GeneralWay to show state tree and state chartmemberjerome_19 Sep '05 - 4:28 
Hi, William
 
If you already activated the Wizard. You may unzip the sample: phone develop in the pack, which is a VC6 project. Open it with VC6, there will be a new StateTree tab window in the Workspace window. In the sample, there are some state machine applications. You may click the application item to show application's state tree. Note that an application is organized by a state machine.
 
Select one state item or application item and right click, there will be a pop menu. Click the "Draw State Chart" command, Wizard will show the selected state's state chart with state transitions. You may construct state machine using StateChart or StatTree.
 
Jerome

 
Jerome. An embedded system developer.
GeneralRe: LOST!!memberiloverockbest7 Oct '05 - 15:51 
Smile | :) Hi, there:
I tried every step in my vc6.0 and see it runs all well. After rereading your message, I really doubt whether you have clicked the "Enable/Disable State machine wizard" button on the toolbar by mistaken. If you disable the wizard accidently, it will remember the last setting automatically. Hence, when you close the workspace and reopen it, you will not see the state tree tab until you click the button again to enable it.
 
If cause is that, what you have to do is just another click to view this wizard. Good luck Smile | :)

 
we 'll rock & we 'll roll
QuestionCan this class show several curve at the same time?memberOilieLuo7 Aug '05 - 21:37 
I have to use this class to display 2 or 3 curves and the values update every minute.
When I set a group of data the previous curve disappeared.
Can the Class set several datagroup at the same time?Confused | :confused:
What can I do about this?
AnswerRe: Can this class show several curve at the same time?memberOilieLuo7 Aug '05 - 21:39 
Sorry everyone...
Wrong Post Dead | X|
GeneralDoesn't work with German VC6 Sp5memberGunnar Bolle1 Jun '05 - 2:36 
The State tree won't show up. Any ideas ?
GeneralRe: Doesn't work with German VC6 Sp5memberJerome_1 Jun '05 - 15:27 
As what we describe in the document "Install Manual.rtf", you have to follow the instruction after run installer application:
 
4) On the Add-ins and Macro Files dialog, choose the Add-ins and Macro Files tab. Click on the checkbox next to UML State Machine Wizard.
 
Best regards
Jerome.
 

 
Jerome. An embedded system developer.
GeneralInterestingsussjuggler1 Jun '05 - 0:48 
This is nice stuff, but the article that goes with the code is a bit short to explain what you are trying to do. More information about the code the wizard generates would be nice.
 
It's worth noting that
(a) there is no support here for asynchronous state machines and
(b) the code is C
(c) the boost equivalent for C++ is boost::fsm, originally in the boost::mpl example from release 1_32_0 but now rather extended & improved, if still a bit of a git to use.
GeneralRe: InterestingmemberJerome_1 Jun '05 - 15:44 
Hi, Juggler
 
Thank you for your comment. I answer your question blow your questions:
 
(a) there is no support here for asynchronous state machines and
This wizard does support asynchronous service call / events. You could get more information about the following functions in Help file.
 
SmePostEvent()
AgtPostExtEvent()
AgtPostServiceCall()
AgtSendServiceCall()
 

(b) the code is C
Yes. Portable (Cross-platform) standard C is good for embedded systems.
 
(c) the boost equivalent for C++ is boost::fsm, originally in the boost::mpl example from release 1_32_0 but now rather extended & improved, if still a bit of a git to use.
 
The entry function of state machine engine is
SmeRun()
 
You could get more detail information by www.intelliwizard.com.
 

Jerome
 
Jerome. An embedded system developer.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130516.1 | Last Updated 2 Jun 2005
Article Copyright 2005 by Jerome_D
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid