SinelaboreRT Header Logo

SinelaboreRT

It's better when it's simple!

User Tools

Site Tools


Sidebar

UML-Tool specific Intro

How-To

Examples

Designers Toolbox

Integrated state-chart editor with auto-layout

Focus on modeling and not on moving states around to create a nice looking diagram! Syntax aware text fields offer a comfortable way to specify actions, guards etc. When the diagram passed the model checker it can be directly simulated. Connect the diagram to the real hardware to monitor the state machine in action.

There are better ways to model state machines than using spread sheets!

In the past different μC manufacturers have published application notes about the benefit of using state machines for the design of embedded software. An example is the application note SLAA402 from Texas Instruments (TI). It suggests to generate source code based on a spread sheet table. Nowadays several affordable UML modeling tools are available supporting the efficient design of state machines in a graphical way. SinelaboreRT generates production quality source code from state diagrams created with many different UML tools. Give it a try!

Latest Changes

wiki:news:27okt2012

Generate code from state machines with regions

In state diagrams usually only one state is active at a time. In UML state diagrams regions also allow to model concurrency - i.e. more than one state is active at a time (AND states).

The latest beta now supports the modeling of parallel regions with the following constraints:

  • Transitions must not cross region boarders. Why this is important is discussed further down
  • No regions in regions
  • No support for fork
  • Join can be realized with transitions using guards like isInS221 && isInS222 as an example
  • UModel and EnterpriseArchitect as modeling tools
  • Only C/C++ code generation. No simulation etc.

The remainder of this article explains how to use regions based on the microwave oven example also used in the manual. It also discusses why it can be tricky to use regions.

Notation

A UML state may be divided into regions. Each region contains sub-states. Regions are executed in parallel. You can think of regions as independent state machines displayed in one diagram. The state machine below (Fig. 1) shows several regions each running in parallel in the state Active. Dashed lines are used to divide a state into regions.

Using multiple regions

Consider a microwave oven. The power setting, light and microwave radiator are be considered as independent (concurrent) parts of the oven, each with its own states. The door and timer as the main external trigger are used in the regions to trigger state transitions. For example the radiator is switched on if the door gets closed and the timer is > zero.

As you can see multiple concurrent regions can be used to explicitly visualize different parts of a device. And all the states in the one diagram.

The model and the generated code thereof is provided in the examples folder of the latest beta.

 Oven model with regions Figure 1a: State machine model of a microwave oven using regions (created with UModel).

 Oven model with regions Figure 1b: State machine model of a microwave oven using regions (created with EA).

Alternative design without using regions

The microwave oven can also be modelled in a different way as shown below (the example is taken from the manual and code is available in the examples folder of the SinelaboreRT download). This model was created from an outside perspective not showing the state of different parts explicitly. It might be easier to follow the state flow during debugging and simulation because there is no parallelism. On the other hand the status of some parts of the oven are not a visible as in the model with regions.

 Oven model without regions Figure 2: Oven model not using regions.

How regions are implemented

The following brief descriptions explains how regions are implemented.

  • For each region an own function is generated. Its name is automatically derived from the region name.
  • If a state contains several regions they are called one after the other (in alphabetical order). If the event sent to the state machine was processed in one of the regions no further event handling happens. Otherwise the event is processed in the parent state. This is similar to the event handling of normal hierarchical state machines.
  • To maintain consistency during execution of machine code a copy of the instance data is created at the beginning of the state machine code. All tests are performed on the original instance data. All changes are done on the copy. This ensures that all regions “see” the same situation when running. At the end of the machine code the modified instance data is copied back to the original data. Note: this is not yet available in the C++ backend.

Here is the simplified C-code example of the oven state machine.

void  oven(OVEN_INSTANCEDATA_T *instanceVar){
 
  OVEN_EV_CONSUMED_FLAG_T evConsumed = 0U;
  OVEN_INSTANCEDATA_T instanceVarCopy = *instanceVar;
 
  switch (instanceVar->stateVar) {
 
    case Active:
      /* calling region code */
      evConsumed |= ovenActiveLight(instanceVar, &instanceVarCopy, msg);
      evConsumed |= ovenActivePower(instanceVar, &instanceVarCopy, msg);
      evConsumed |= ovenActiveRadioator(instanceVar, &instanceVarCopy, msg);
 
      /* Check if event was already processed  */
      if(evConsumed==0U){
        .... /* handle event on parent level */
 
 
    break;
   } /* end switch stateVar_root */
 
   /* Save the modified instance data */
   *instanceVar = instanceVarCopy;
}
 
OVEN_EV_CONSUMED_FLAG_T ovenActiveLight(OVEN_INSTANCEDATA_T *instanceVar, OVEN_INSTANCEDATA_T *instanceVarCopy, OVEN_EVENT_T msg){
  ...
}
 
OVEN_EV_CONSUMED_FLAG_T ovenActivePower(OVEN_INSTANCEDATA_T *instanceVar, OVEN_INSTANCEDATA_T *instanceVarCopy, OVEN_EVENT_T msg){
  ...
}
 
OVEN_EV_CONSUMED_FLAG_T ovenActiveRadioator(OVEN_INSTANCEDATA_T *instanceVar, OVEN_INSTANCEDATA_T *instanceVarCopy, OVEN_EVENT_T msg){
  ...
}

And the same example for C++:

// State machine event handler
int oven::processEvent(OVEN_EVENT_T msg){
 
  int evConsumed = 0;
 
  OVEN_INSTANCEDATA_T instanceVarCopy = *instanceVar;
 
  if(m_initialized==false) return 0;
 
  switch (stateVar) {
 
    case Active:
	/* calling region code */
	evConsumed |= ovenActiveLight(msg);
	evConsumed |= ovenActivePower(msg);
	evConsumed |= ovenActiveRadioator(msg);
 
	/* Check if event was already processed  */
	if(evConsumed==0){
           .... /* handle event on parent level */
 
  ...
  return evConsumed;
}
 
/* Region code for state Active */
 
int oven::ovenActiveLight(OVEN_EVENT_T msg){
  ...
}
 
int oven::ovenActivePower(OVEN_EVENT_T msg){
  ...
}
 
int oven::ovenActiveRadioator(OVEN_EVENT_T msg){
  ...
}

Points to consider with regions

Transitions must not cross region boundaries

In the first diagram state transitions do not cross region boundaries and therefore the modeller’s intension is quite clear. But look at the next diagram which is a valid diagram too. Now it is not clear anymore what the modeller had in mind. And it is also not very obvious what a code generator would/should generate. For that reason it is necessary that a code generator defines some limits here.

 Problems with regions

Regions must work on the same instance data

State diagrams follow the run-to-completion concept: Transitions that fire are fully executed and the state machine reaches a stable state configuration until it returns and can respond to the next event. To ensure this a copy of the instance data is kept and state changes are only performed on that copy. In practice this means that changes in one region does not influence other regions. Look into the following figure below.

  • If the event evClosed is sent region ValveA and ValveB change state.
  • But there is no state change in region Motor at the same time. The reason is that the transition from StopRun was not triggered at the beginning of the machine execution.
  • This behavior ensures that the result of a machine execution step is 100% predictable and e.g. not dependent of the execution order of the regions.
  • But on the other side it means that a second run of the machine is required to reach state MachineRun. I.e. the region Motor is always one cycle behind the Valve regions.

 Problems with regions II

And the conclusions?

Usually there is a way to model a problem with regions and without regions. The solution with regions allows to model a kind of parallelism and allows to explicitly display independent parts of a system.

On the other side exactly this parallelism is responsible that models with regions looks a bit more complex at first view.

If you have comments and suggestions please let me know! If you are interested to test this version download the latest beta following this download link.


Leave your comments

, 2012/11/19 19:01

Beta 5 maintains a copy of the instance data if regions are used in the state diagram. This ensures that all regions work on the same instance data set.

, 2012/11/05 18:50, 2012/11/05 19:14

The latest beta download is beta4 now which adds support for C++. The examples folder contains the oven example designed with UModel / EA9 in C and in EA9 in C++.

Enter your comment. Wiki syntax is allowed:
211 -0 = 
 
This website uses cookies. By using the website, you agree with storing cookies on your computer. Also you acknowledge that you have read and understand our Privacy Policy. If you do not agree leave the website.More information about cookies
wiki/news/27okt2012.txt · Last modified: 2013/08/12 15:11 by pmueller