SinelaboreRT Header Logo

SinelaboreRT

It's better when it's simple!

User Tools

Site Tools


Sidebar

UML-Tool specific Intro

Language Backends

Getting started

How-To

Examples

Designers Toolbox

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:backends:c_lang

Generating C code

Sinelabore creates compact and clearly readable C code from UML state charts. State hierarchies are mapped to nested switch/case code. Event handling code to if/else if/else structures. There are various configuration options to adjust the generated code:

  • usage as interrupt handler without any parameters
  • having only the event as parameter of the handler
  • having an instance pointer and event as parameter (for running multiple instances of the same machine)
  • having an own defined parameter containing the event which allow to easily send data with the event
  • Support for externally defined events (i.e. outside the UML diagram) to better support reuse of legacy code
  • Support for conditional events (i.e. boolean expressions)
  • the C backend has features for high-availability applications where it is desirable to detect serious errors happening outside the state machine code but effecting the correct execution of the state machine. Such errors might come from a runaway pointer overwriting key variables, power brownout corrupting a bit or a bad ram cell losing a bit to name a few. To detect and handle such situations is an overall system design task. But the code generator can help you to detect inconsistencies of the state machine offering different mechanisms described in the manual.

The code generator supports code generation from models with regions. A region is an orthogonal part of a state. Regions allow to express parallelism within a state. A state can have two or more regions. Region contains states and transitions. To add a region in astah* right click to a state and select Add region from the context menu.

An example state diagram with regions is shown below. Imagine how much effort it would be to manually write the code for this machine. And even worse how difficult it would be to maintain it over time when new states/events are added.

This allows to generate code that is optimal for your system. See the manual for a list of all available options. To generate C code call the code generator with the command line flag -l cx.

This results in the following files:

  • C-file with the state machine implementation
  • H-file of the state machine
  • H-file with the events that can be sent to the machine
  • A file with some code that supports debugging

Example code generated from the oven example in the handbook:

#include "oven_ext.h"
#include "oven_hlp.h"
#include "oven.h"
#include <stdio.h>
 
extern unsigned char msg;
extern T_PWR pwr;
 
void  oven(OVEN_INSTANCEDATA_T *instanceVar){
 
	OVEN_EV_CONSUMED_FLAG_T evConsumed = 0U;
 
	/* Create a copy of the instance data.
	   Changes during the machine execution are done on the copy 
	   while tests (e.g. isIn) must use the unmodified instance data */
	OVEN_INSTANCEDATA_T instanceVarCopy = *instanceVar;
 
 
	switch (instanceVar->stateVar) {
 
		case Active:
			/* calling region code */
			evConsumed |= ovenLight(instanceVar, &instanceVarCopy, msg);
			evConsumed |= ovenPower(instanceVar, &instanceVarCopy, msg);
			evConsumed |= ovenRadioator(instanceVar, &instanceVarCopy, msg);
 
			/* Check if event was already processed  */
			if(evConsumed==0U){
 
				if(msg==(OVEN_EVENT_T)evDec){
					/* Transition from Active to Active */
 
					/* Exit code for regions in state Active */
 
					/* Action code for transition  */
					timer_dec();
 
 
 
					/* Entry code for regions in state Active */
					/* entry chain  */
					/* entry chain  */
					/* entry chain  */
 
 
					/* adjust state variables  */
					(&instanceVarCopy)->stateVar = Active;
				}else if(msg==(OVEN_EVENT_T)evInc){
					/* Transition from Active to Active */
 
					/* Exit code for regions in state Active */
 
					/* Action code for transition  */
					timer_inc();
 
 
 
					/* Entry code for regions in state Active */
					/* entry chain  */
					/* entry chain  */
					/* entry chain  */
 
 
					/* adjust state variables  */
					(&instanceVarCopy)->stateVar = Active;
				}else{
					/* Intentionally left blank */
				} /*end of event selection */
			}
		break; /* end of case Active  */
 
		case Inactive:
			if(1){
				/* Transition from Inactive to Active */
 
 
				/* Entry code for regions in state Active */
				/* entry chain  */
				/* entry chain  */
				/* entry chain  */
 
 
				/* adjust state variables  */
				(&instanceVarCopy)->stateVar = Active;
			}else{
				/* Intentionally left blank */
			} /*end of event selection */
		break; /* end of case Inactive  */
 
		default:
			/* Intentionally left blank */
		break;
	} /* end switch stateVar_root */
 
	/* Save the modified instance data */
	*instanceVar = instanceVarCopy;
}

For more details read section “Generating C Code” of the manual.

How do you like this article?
 stars  from 0 votes

Leave your comments

Enter your comment:
 
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/backends/c_lang.txt · Last modified: 2020/08/28 11:22 by pmueller