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

Develop embedded systems based on UML state machines

, 1 Jun 2005
Rate this:
Please Sign up or sign in to vote.
This article discovers how to develop and simulate cross-platform embedded systems using the UML State Machine Wizard.

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)

Share

About the Author

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

Comments and Discussions

 
GeneralOpen engine source code PinmemberJerome_D19-Apr-06 20:25 
GeneralRe: Open engine source code Pinmemberxwy12-Mar-12 17:35 

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

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140827.1 | Last Updated 2 Jun 2005
Article Copyright 2005 by Jerome_D
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid