FW Profile - C1 Implementation
|
The C1 Implementation represents a state machine through a state machine descriptor (SMD).
A SMD is a data structure which holds all the information required to describe a state machine. Users do not normally manipulate the PRD directly. Instead, they manipulate the pointer to the PRD which is defined as an instance of type FwSmDesc_t
. Its internal structure is described in FwSmPrivate.h
. Most applications are not concerned with the internal structure of an SMD and can ignore this header file.
Applications manipulate a state machine by passing its SMD to the functions defined by the C1 Implementation. Thus, for instance, an application executes a state machine through the following function call: FwSmExecute(smDesc)
. Here, smDesc
is the SMD of the state machine to be executed.
The implementation of the state machine concept consists of several modules as described in the table:
Module | Description | Files |
---|---|---|
Core | Provides an interface to start and stop a state machine and to send a transition command to it. | FwSmCore.h , FwSmCore.c |
DCreate | Provides an interface to create a new SMD. The functions in this module are simple to use but rely on dynamic memory allocation. Applications which wish to avoid dynamic memory allocation can use the alternative SCreate module. | FwSmDCreate.h , FwSmDCreate.c |
SCreate | Provides macros to instantiate a new SMD (without using dynamic memory allocation) and functions to initialize it. This module is alternative to the DCreate module. | FwSmSCreate.h , FwSmSCreate.c |
Config | Provides an interface to configure a newly created SMD by defining its states and transitions. | FwSmConfig.h , FwSmConfig.c |
Aux | Provides an interface to auxiliary services which are useful during the application development phase. | FwSmAux.h , FwSmAux.c |
The Aux
module is not intended for inclusion in the final application. The DCreate
and SCreate
modules are normally alternative to each other (but deployment of both in the same application is possible). Applications which are severely constrained in memory can instantiate and configure the SMDs of their state machines by directly manipulating their internal fields. This requires a detailed understanding of the internal structure of the SMD but allows an application to dispense with both the DCreate
/SCreate
modules and with the Config
module. An example of direct instantiation and configuration of an SMD is provided in FwSmMakeTestSM5Dir
.
The state machine actions and guards are defined as function pointers of type, respectively, FwSmAction_t
and FwSmGuard_t
. Applications must provide functions of these two types to implement the actions and guards of their state machines. Both the guard and the action functions are called with the SMD as an argument.
Note that, if a state machine uses the same action or the same guard more than once, the associated function pointer is only stored once in the SMD.
The SMD includes a field holding a pointer to the state machine data. The state machine data are data which are manipulated by the state machine actions and guards. The exact type of the state machine data is defined by applications for each state machine. In most cases, it will take the form a struct
whose fields represents the inputs and outputs for the state machine actions and guards. The SMD treats the pointer to the state machine data as a pointer to void
. Functions FwSmSetData
and FwSmGetData
allow this pointer to be set in, and be retrieved from an SMD.
The state machine functions perform a limited amount of error checking. If they find an error, this is reported through the error code which stores the identifier of the last error encountered by the implementation. The value of the error code can be read with the FwSmGetErrCode
function. Nominally, the error code should be equal to smSuccess
. If this is not the case, the behaviour of the state machine is undefined.
The functions defined by the C1 Implementation do not use any global data. They operate exclusively on the data passed to them as arguments. They are therefore inherently thread-safe.
The basic usage of a state machine instance within an application is as follows:
FwSmDCreate.h
module but may also be done using the FwSmSCreate.h
module (if it is desired to avoid use of dynamic memory allocation).FwSmSetData
.add*
functions in the FwSmConfig.h
module which allow an application to define the states and the transitions of the state machine.FwSmCheck
and it may be printed with function FwSmPrintConfig
.FwSmStart
.FwSmExecute
and FwSmMakeTrans
.FwSmStop
.FwSmDCreate.h
module, the memory allocated to the state machine may be released with functions FwSmRelease
or FwSmReleaseRec
. Examples of creation and configuration of state machines can be found in file FwSmMakeTest.c
. Examples of operation of a state machine can be found in file FwSmTestCases.c
or in the Demo Application.
The C1 Implementation supports an extension mechanism for state machines which is similar to the inheritance-based extension mechanism of object-oriented languages.
A state machine (the base state machine) can be extended to create a new state machine (the derived state machine). A derived state machine can either be created dynamically with the FwSmCreateDer
function or else it can be instantiated statically with macro FW_SM_INST_DER
and initialized with function FwSmInitDer
.
After being created, a derived state machine is a clone of its base. It can then be configured by: overriding its actions (through function FwSmOverrideAction
), overriding its guards (through function FwSmOverrideGuard
), or embedding new state machines in its states (through function FwSmEmbed
).
The internal structure of the SMD is designed to minimize the memory requirements of derived state machines. An SMD is split into two parts: the Base Descriptor and the Extension Descriptor (see FwSmPrivate.h
module). The Base Descriptor holds the information about the state machine topology (its states, choice pseudo-states and their connections) whereas the Extension Descriptor holds the information about the state machine actions and guards and its embedded state machines. During the extension process, only the Extension Descriptor is duplicated whereas the Base Descriptor is shared between a state machine and its children. This significantly reduces memory occupation in a situation where a large number of state machines are derived from the same base state machine. The internal structure of a state machine descriptor is shown in the figure.