RKH
Quick reference

Prev: Home
Next: Installation

The main objective of this section is to show and also illustrate the most important concepts to apply when dealing with RKH and the event-driven applications.

This section includes:



Defining a state machine


Prev: Quick reference
A state machine application is defined with the RKH_SMA_CREATE() macro and declared with the RKH_SMA_DCLR() macro. Frequently, each state machine is encapsulated inside a dedicated source file (.c file), from which the RKH_SMA_CREATE() macro is used, thus the structure definition is in fact entirely encapsulated in its module and is inaccessible to the rest of the application. However, as a general rule, the state machine application must be declared inside a header file (.h file) by means of RKH_SMA_DCLR() macro. We will develop one example of state machine creation to illustrate the use of this macro. Also, we will give our hierarchical state machine the name my. If you wanted to create a "flat" state machine, you would use the FLAT parameter rather than the HCAL parameter.

This section includes:

Defining the state machine application


(1) // my.c: state machine application's module
(2) typedef struct
{
RKH_SMA_T sm; // base structure
rui8_t x; // private member
rui8_t y; // private member
} MYSM_T;
(3) static RKH_ROM_STATIC_EVENT( turnon, TURNON );
(4) RKH_SMA_CREATE( MYSM_T, // state machine application data type
(6) my, // name
(7) 2, // priority number
(8) HCAL, // hierarchical state machine
(9) &S1, // initial state
(10) my_init, // initial action
(11) &turnon ); // initial event
#define RKH_ROM_STATIC_EVENT(ev_obj, ev_sig)
This macro declares and initializes the event structure ev_ob with ev_sig signal number and establish...
@ HCAL
Definition: rkhsm.h:1611
#define RKH_SMA_CREATE(type, name, prio, ppty, initialState, initialAction, initialEvt)
Declare and allocate a SMA (active object) derived from RKH_SMA_T. Also, initializes and assigns a st...
Definition: rkhsma.h:348
Describes the SMA (active object in UML).
Definition: rkhsma.h:772

Declaring the state machine

// my.h: state-machine application's header file
#define RKH_SMA_DCLR(me_)
This macro declares a opaque pointer to previously created state machine application (SMA aka active ...
Definition: rkhsma.h:139

Explanation

  • (1) Frequently, each state machine application is encapsulated inside a dedicated source file (.c file), from which the RKH_SMA_CREATE() macro is used.
  • (2) The MYSM_T defines the my state machine application structure. Almost every state machine applications must also store other "extended-state" information. You supply this additional information by means of data members enlisted after the base structure member sm. This illustrates how to derive an state machine application from RKH_SMA_T. Please note that the RKH_SMA_T member sm is defined as the FIRST member of the derived struct. RKH_SMA_T is not intended to be instantiated directly, but rather serves as the base structure for derivation of state machines in the application code.
  • (3) Declares and initializes the event structure turnon with TURNON
    signal and establishes it as one static event. The created event object is explicitly placed in ROM..
  • (4) As said below, the MYSM_T defines the my state machine application structure.
  • (6) my is the state machine application. Represents the top state of state diagram.
  • (7) 2 is the state machine application priority.
  • (8) the my state machine is defined as a hierarchical state machine. The available property options are enumerated in RKH_HPPTY_T enumeration in the rkh.h file.
  • (9) S1 is the initial state.
  • (10) my_init() function defines the topmost initial transition in the my state machine. The function prototype is defined as RKH_TRN_ACT_T. This argument is (optional), thus it could be declared as NULL. The application code must trigger the initial transition explicitly by invoking rkh_sma_activate() function.
  • (11) turnon is a pointer to an event that will be passed to state machine application when it starts. Could be used to pass arguments to the state machine like an argc/argv. This argument is optional, thus it could be declared as NULL or eliminated in compile-time with RKH_CFG_SMA_INIT_EVT_EN = 0.

Customization

Each RKH application must have its own configuration file, called rkhcfg.h. This file adapts and configures RKH by means of compiler definitions and macros allowing to restrict the resources consumed by RKH. Adjusting this definitions allows to reduce the ROM and RAM consumption, and to enhance the system performance in a substantial manner. The rkhcfg.h shows the general layout of the configuration file.

Use the following macros to reduce the memory taken by state machine structure: RKH_CFG_SMA_INIT_EVT_EN. See Configuration section for more information.

Prev: Quick reference


Defining a composite state


Prev: Quick reference

A superstate or composite state is defined with the RKH_CREATE_COMP_STATE() macro and declared with the RKH_DCLR_COMP_STATE macro. Frequently, each state machine and its states (composite and basic) are encapsulated inside a dedicated source file (.c file), from which the RKH_CREATE_COMP_STATE() macro is used. We will develop one example of composite state definition to illustrate the use of this macro. We will give our composite state the name S1.

This section includes:

Defining a composite state

(1) // my.c: state-machine's module
(4) turn_on,
(5) turn_off,
(6) &SA,
(7) &S11,
(8) &H );
#define RKH_CREATE_COMP_STATE(name, en, ex, parent, defchild, history)
This macro creates a composite state.
Definition: rkhsm.h:191

Declaring a composite state

// my.h: state-machine's header file
...
RKH_DCLR_COMP_STATE S1;

Explanation

  • (1) Frequently, each state machine and its states are encapsulated inside a dedicated source file (.c file), from which the RKH_CREATE_COMP_STATE() macro is used.
  • (2) S1 is the state name. Represents a composite state structure.
  • (4) turn_on() defines the entry action to be executed unconditionally upon the entry to the S1 state. This argument is optional, thus it could be declared as NULL. The RKH_ENT_ACT_T defines the function prototype.
  • (5) turn_off() defines the exit action, which is executed upon exit from the S1 state. This argument is optional, thus it could be declared as NULL. The RKH_EXT_ACT_T defines the function prototype.
  • (6) SA is the parent state of S1. If a state has no explicit superstate means that it is implicitly nested in the "top" state, and the parent state is defined by means of RKH_ROOT macro. The "top" state is a UML concept that denotes the ultimate root of the state hierarchy in a hierarchical state machine.
  • (7) S11 is the default state of S1 state machine. At each level of nesting, a superstate can have a private initial transition that designates the active substate after the superstate is entered directly. Here the initial transition of state S1 designates the state S11 as the initial active substate.
  • (8) H is the history pseudostate. This argument is optional, thus it could be declared as NULL. See RKH_CREATE_SHALLOW_HISTORY_STATE() macro and RKH_CREATE_DEEP_HISTORY_STATE().

Customization

Each RKH application must have its own configuration file, called rkhcfg.h. This file adapts and configures RKH by means of compiler definitions and macros allowing to restrict the resources consumed by RKH. Adjusting this definitions allows to reduce the ROM and RAM consumption, and to enhance the system performance in a substantial manner. The rkhcfg.h shows the general layout of the configuration file.

Use the following macros to reduce the memory taken by state machine structure: RKH_CFG_SMA_HCAL_EN. See Configuration section for more information.

Prev: Quick reference


Defining a basic state


Prev: Quick reference

A basic state (also called substate) is defined with the RKH_CREATE_BASIC_STATE() macro and declared with the RKH_DCLR_BASIC_STATE macro. Frequently, each state machine and its states (composite and basic) are encapsulated inside a dedicated source file (.c file), from which the RKH_CREATE_BASIC_STATE() macro is used. We will develop one example of basic state definition to illustrate the use of this macro. We will give our basic state the name S11. As will demostrates the use of RKH_CREATE_BASIC_STATE() macro and its arguments is very similar to RKH_CREATE_COMP_STATE() macro.

Defining a basic state

(1) // my.c: state-machine's module
(4) start_process,
(5) stop_process,
(6) &S1,
(7) in_keyb );
#define RKH_CREATE_BASIC_STATE(name, en, ex, parent, prepro)
This macro creates a basic state.
Definition: rkhsm.h:277

Declaring a basic state

// my.h: state-machine's header file
...
RKH_DCLR_BASIC_STATE S11;

Explanation

  • (1) Frequently, each state machine and its states are encapsulated inside a dedicated source file (.c file), from which the RKH_CREATE_BASIC_STATE() macro is used.
  • (2) S11 is the state name. Represents a substate structure.
  • (4) start_process() defines the entry action to be executed unconditionally upon the entry to the S11 state. This argument is optional, thus it could be declared as NULL. The RKH_ENT_ACT_T defines the function prototype.
  • (5) stop_process() defines the exit action, which is executed upon exit from the S11 state. This argument is optional, thus it could be declared as NULL. The RKH_EXT_ACT_T defines the function prototype.
  • (6) S1 is the parent state of S11. If a state has no explicit superstate means that it is implicitly nested in the "top" state, and the parent state is defined by means of RKH_ROOT macro. The "top" state is a UML concept that denotes the ultimate root of the state hierarchy in a hierarchical state machine.
  • (7) in_keyb() defines the event preprocessor action. Before sending the arrived event to state machine, it can be previously processed using the event preprocessor function. An action function takes the state machine pointer and the event pointer as arguments. The first parameter is optional in compile-time according to RKH_EN_PPRO_HSM_ARG macro. Example:
    static
    in_keyb( RKH_EVT_T *pe )
    {
    if( pe->e >= 0 && pe->e <= 9 )
    return DECIMAL;
    if( pe->e == '.' )
    return POINT;
    else
    return pe->e;
    }
    rui8_t RKH_SIG_T
    Definition: rkhevt.h:100
    Represents events without parameters.
    Definition: rkhevt.h:170
    RKH_SIG_T e
    Signal of the event instance.
    Definition: rkhevt.h:175
  • (7) Aditionally, by means of single inheritance in C it could be used to supply additional information to state. Implementing the single inheritance in C is very simply by literally embedding the base type, RKH_PPRO_T in this case, as the first member of the derived structure. This argument is optional, thus it could be declared as NULL. Example:
    typedef struct
    {
    RKH_PPRO_T prepro; // extend the RKH_PPRO_T class
    unsigned min:4; // addtional information...
    unsigned max:4;
    char *buff;
    } SDATA_T; // this data type will be used in S12 context
    static const SDATA_T option = { preprocessor, 4, 8, token };
    /* Define S11 state as a substate of S1 */
    RKH_CREATE_BASIC_STATE( S11, start_process, start_process, &S1, in_keyb );
    /* Define S12 state as a substate of S1 */
    RKH_CREATE_BASIC_STATE( S12, NULL, NULL, &S1, (RKH_PPRO_T*)&option );
    RKH_SIG_T(* RKH_PPRO_T)(const RKH_SM_T *sma, RKH_EVT_T *pe)
    Event preprocessor.
    Definition: rkhsm.h:1726

Customization

Each RKH application must have its own configuration file, called rkhcfg.h. This file adapts and configures RKH by means of compiler definitions and macros allowing to restrict the resources consumed by RKH. Adjusting this definitions allows to reduce the ROM and RAM consumption, and to enhance the system performance in a substantial manner. The rkhcfg.h shows the general layout of the configuration file.

Use the following macros to reduce the memory taken by state machine structure: RKH_CFG_SMA_PPRO_EN. See Configuration section for more information.

Prev: Quick reference


Defining a submachine state


Prev: Quick reference

A submachine state is a kind of a state that actually refers to another defined state machine. The diagram in following figure shows a fragment from a state machine diagram in which a submachine state (the SB) is referenced.

Submachine state

In the above example, the transition triggered by event TWO will terminate on entry point ENS12 of the SB state machine. The ONE transition implies taking of the default transition of the SB and executes the act5() action. The transition emanating from the EX1S12 exit point of the submachine will execute the act1() behavior in addition to what is executed within the SB state machine. Idem transition emanating from the EX2S12. This transition must have been triggered within the SB state machine. Finally, the transition emanating from the edge of the submachine state is triggered by event THREE.

The following figure is an example of a state machine SB defined with two exit points, EXPNT1 and EXPNT2, and one entry point ENPNT.

State machine with two exit points and one entry point

In the following figure the state machine shown above is referenced twice in a submachine state S12 and S2.

Submachine state with usage of exit and entry points

This section includes:

Defining a submachine state

A submachine state is defined with the RKH_CREATE_SUBMACHINE_STATE() macro and declared with the RKH_DCLR_SUBM_STATE macro. Frequently, each state machine and its states (composites, basic, and submachine states) are encapsulated inside a dedicated source file (.c file), from which the RKH_CREATE_SUBMACHINE_STATE() macro is used. We will develop one example of submachine state definition to illustrate the usage and its related macros. We will give our submachine state the name S12.

(1) // my.c: state-machine's module
(4) NULL,
(5) NULL,
(6) &S1,
(7) &SB );
#define RKH_CREATE_SUBMACHINE_STATE(name, en, ex, parent, sbm)
This macro creates a submachine state.
Definition: rkhsm.h:493

Explanation

  • (1) Frequently, each state machine and its states are encapsulated inside a dedicated source file (.c file), from which the RKH_CREATE_SUBMACHINE_STATE() macro is used.
  • (2) S12 is the state name. Represents a submachine state structure.
  • (4) the entry action is not used.
  • (5) the exit action is not used.
  • (6) S1 is the parent state of S12. If a state has no explicit superstate means that it is implicitly nested in the "top" state, and the parent state is defined by means of RKH_ROOT macro. The "top" state is a UML concept that denotes the ultimate root of the state hierarchy in a hierarchical state machine.
  • (7) SB is the defined submachine state machine, which is referenced by S12 submachine state.

On the other hand, in RKH every submachine state is associated with a transition table, which is composed of a well-defined set of transitions. See Defining a state transition table for defining a state transition table.

RKH_TRINT( TERM, NULL, terminate ),
RKH_TRREG( THREE, NULL, NULL, &S1 ),
#define RKH_CREATE_TRANS_TABLE(name)
This macro creates a state transition table.
Definition: rkhsm.h:777
#define RKH_END_TRANS_TABLE
This macro is used to terminate a state transition table. This table have the general structure shown...
Definition: rkhsm.h:894
#define RKH_TRREG(evt_, guard_, effect_, target_)
This macro defines a regular state transition.
Definition: rkhsm.h:811
#define RKH_TRINT(e, g, a)
This macro defines an internal state transition. Internal transitions are simple reactions to events ...
Definition: rkhsm.h:835

Declaring a submachine state

// my.h: state-machine's header file
...
RKH_DCLR_SUBM_STATE S12;

Defining the exit connection references

Connection point references are sources/targets of transitions implying exits out of/entries into the submachine state machine referenced by a submachine state. In RKH every submachine state is associated with a exit point connection point reference table, which is composed of a well-defined set of exit point connection references. Thus, in RKH each row in a exit point table references an exit point pseudostate as defined in the submachine of the submachine state that has the exit point connection point defined. Note that each row number matches with the index number of the exit point pseudostate that it represent.

// --- exit point pseudostates of SB submachine ---
0, // index of exit point connection table
&SB );
1, // index of exit point connection table
&SB );
...
// --- exit point connection references of S12 submachine state ---
(2) RKH_EX_CNNPNT( EX1S12, &EXPNT1, act1, &S13 ), // table index = 0 (EXPNT1)
(3) RKH_EX_CNNPNT( EX2S12, &EXPNT2, act2, &S3 ), // table index = 1 (EXPNT2)
#define RKH_CREATE_REF_EXPNT(name, ix, subm)
This macro creates an exit point.
Definition: rkhsm.h:708
#define RKH_CREATE_EX_CNNPNT_TABLE(name)
This macro creates a exit point connection point reference table.
Definition: rkhsm.h:529
#define RKH_END_EX_CNNPNT_TABLE
This macro is used to terminate a exit point connection reference table.
Definition: rkhsm.h:599
#define RKH_EX_CNNPNT(name, expnt, act, ts)
This macro creates an exit point connection point reference.
Definition: rkhsm.h:575

Explanation

  • (2) The RKH_EX_CNNPNT() macro defines the exit point connection EX1S12, where EXPNT1 is the referenced exit point pseudostate, act1() is the transition action function to be taken, and S13 is the transition target state. The place in the table matches with the EXPNT1's index field.
  • (3) Idem (2).

Defining the entry connection references

Connection point references are sources/targets of transitions implying exits out of/entries into the submachine state machine referenced by a submachine state.

A entry point connection reference is defined with the RKH_EN_CNNPNT() macro and declared with the RKH_DCLR_ENPNT macro. Frequently, each state machine and its states and pseudostates are encapsulated inside a dedicated source file (.c file), from which the RKH_EN_CNNPNT() macro is used. We will develop one example of entry point connection definition to illustrate the use of this macro. We will give our entry connection the name ENS12.

(1) // my.c: state-machine's module
(2) RKH_EN_CNNPNT( ENS12,
&ENPNT,
&S12 );
#define RKH_EN_CNNPNT(name, enpnt, subm)
This macro creates an entry point connection point reference.
Definition: rkhsm.h:623

Explanation

  • (1) Frequently, each state machine and its states are encapsulated inside a dedicated source file (.c file), from which the RKH_EN_CNNPNT() macro is used.
  • (2) The RKH_EN_CNNPNT() macro defines the exit point connection ENS12, where ENPNT is the referenced entry point pseudostate, and S12 is the transition target state.

Declaring entry connection references

// my.h: state-machine's header file
...
RKH_DCLR_ENPNT ENS12;

Defining a submachine

A submachine is defined with the RKH_CREATE_REF_SUBMACHINE() macro and declared with the RKH_DCLR_REF_SUBM macro. Frequently, each state machine and its states (composites, basic, and submachine states) are encapsulated inside a dedicated source file (.c file), from which the RKH_CREATE_REF_SUBMACHINE() macro is used. We will develop one example of submachine definition to illustrate the usage and its related macros. We will give our submachine the name SB.

(1) // my.c: state-machine's module
(4) &SB1,
(5) NULL );
#define RKH_CREATE_REF_SUBMACHINE(name, defchild, iact)
This macro creates a submachine state machine, which is to be inserted in place of the (submachine) s...
Definition: rkhsm.h:654

Explanation

  • (1) Frequently, each state machine and its states are encapsulated inside a dedicated source file (.c file), from which the RKH_CREATE_REF_SUBMACHINE() macro is used.
  • (2) SB is the submachine name. Represents a submachine structure.
  • (4) SB1 is the default state of SB submachine. At each level of nesting, a submachine can have a private initial transition that designates the active substate after the submachine is entered directly. Here the initial transition of state SB designates the state SB1 as the initial active substate.
  • (5) the initialization action is not used.

Declaring a submachine

// my.h: state-machine's header file
...
RKH_DCLR_REF_SUBM SB;

Defining the exit point

A exit point pseudostate is defined with the RKH_CREATE_REF_EXPNT() macro and declared with the RKH_DCLR_REF_EXPNT macro. Frequently, each state machine and its states and pseudostates are encapsulated inside a dedicated source file (.c file), from which the RKH_CREATE_REF_EXPNT() macro is used. We will develop one example of exit point definition to illustrate the use of this macro. We will give our exit points the name EXPNT1 and EXPNT2.

(1) // my.c: state-machine's module
(2) RKH_CREATE_REF_EXPNT( EXPNT1,
0,
&SB );
1,
&SB );

Explanation

  • (1) Frequently, each state machine and its states are encapsulated inside a dedicated source file (.c file), from which the RKH_EN_CNNPNT() macro is used.
  • (2) The RKH_CREATE_REF_EXPNT() macro defines the exit point EXPNT1, where 0 is the index of the exit point connection table, and SB is the containing submachine. See Declaring entry connection references for referencing a submachine exit point from a submachine state.

Declaring a submachine

// my.h: state-machine's header file
...
RKH_DCLR_REF_EXPNT EXPNT1, EXPNT2;

Defining the entry point

A entry point pseudostate is defined with the RKH_CREATE_REF_ENPNT() macro and declared with the RKH_DCLR_REF_ENPNT macro. Frequently, each state machine and its states and pseudostates are encapsulated inside a dedicated source file (.c file), from which the RKH_CREATE_REF_ENPNT() macro is used. We will develop one example of entry point definition to illustrate the use of this macro. We will give our entry point the name ENPNT.

(1) // my.c: state-machine's module
act8,
&SB1,
&SB );
#define RKH_CREATE_REF_ENPNT(name, act, ts, subm)
This macro creates a entry point.
Definition: rkhsm.h:745

Explanation

  • (1) Frequently, each state machine and its states are encapsulated inside a dedicated source file (.c file), from which the RKH_CREATE_REF_ENPNT() macro is used.
  • (2) The RKH_CREATE_REF_ENPNT() macro defines the entry point ENPNT, where activate() is the transition action to be taken, SB1 is the transition target state, and SB is the containing submachine.

Declaring a entry point

// my.h: state-machine's header file
...
RKH_DCLR_REF_ENPNT ENPNT;

Customization

Each RKH application must have its own configuration file, called rkhcfg.h. This file adapts and configures RKH by means of compiler definitions and macros allowing to restrict the resources consumed by RKH. Adjusting this definitions allows to reduce the ROM and RAM consumption, and to enhance the system performance in a substantial manner. The rkhcfg.h shows the general layout of the configuration file.

Use the following macros to reduce the memory taken by state machine structure: RKH_CFG_SMA_HCAL_EN, RKH_CFG_SMA_PSEUDOSTATE_EN, and RKH_CFG_SMA_SUBMACHINE_EN. See Configuration section for more information.

Prev: Quick reference


Defining a state transition table


Prev: Quick reference

In RKH every state is associated with a transition table, which is composed of a well-defined set of transitions. The general syntax of an expression labelling a transition in a statechart is "i[c]/a" where i is the input that triggers the transition, c is a condition that guards the transition from being taken unless it is true when i occurs, and a is an action that is carried out if and when the transition is taken. All of these parts are optional. Thus, in RKH each row in a table represents a transition, which is well-defined by an event, a guard, an action, and target state (or pseudostate). The Transition table figure shows a demostrative example of that.

Transition table
  • (1) Expressing this transition as said above:

    RCV_DATA[ data == SYNC ]/store_data( data )

    The data == SYNC expression guards the transition from being taken unless it is true. The store_data() function is the action to be taken. Note that in RKH the guard condition is evaluated invoking to a function.
  • (2) Expressing this transition as said above:

    TOUT0/drop_frame()

    This transition is not conditioned by a guard.
  • (3) Expressing this transition as said above:

    DISABLE/disable()

    Similar to prior transition.

Now, is time to represent IN_DATA's transition table by means of RKH framework:

(1) RKH_CREATE_TRANS_TABLE( IN_DATA )
(2) RKH_TRINT( RCV_DATA, is_sync, store_data ),
(3) RKH_TRREG( TOUT0, NULL, drop_frame, &WAIT_SYNC ),
RKH_TRREG( DISABLE, NULL, disable, &IDLE )

Explanation

  • (2) The RKH_TRINT() macro defines a internal transition, where RCV_DATA is the triggering event, is_sync is the guard function, and store_data() is the action function to be taken.
  • (3) The RKH_TRREG() macro defines a regular state transition, where TOUT0 is the triggering event, drop_frame() is the action function to be taken, and WAIT_SYNC is the target state. Note that it is not guarded.

As said above, the actions and guards in RKH framework are represented by functions. Thus, is_sync() could be declared as:

rbool_t
is_sync( RKH_EVT_T *pe )
{
return pe->e == SYNC;
}


Prev: Quick reference


Defining a conditional pseudostate


Prev: Quick reference

A conditional pseudostate (also called juncton pseudostate) is defined with the RKH_CREATE_COND_STATE() macro and declared with the RKH_DCLR_COND_STATE macro. Frequently, each state machine and its states and pseudostates are encapsulated inside a dedicated source file (.c file), from which the RKH_CREATE_COND_STATE() macro is used. We will develop one example of conditional pseudostate (aka junction pseudostate) definition to illustrate the use of this macro. We will give our junction pseudostate the name C1. As will demostrates the use of RKH_CREATE_COND_STATE() macro and its arguments is very similar to RKH_CREATE_BASIC_STATE() macro.

Defining a conditional pseudostate

(1) // my.c: state-machine's module
#define RKH_CREATE_COND_STATE(name)
This macro creates a conditional pseudostate (a.k.a. junction).
Definition: rkhsm.h:313

Declaring a conditional pseudostate

// my.h: state-machine's header file
...
RKH_DCLR_COND_STATE C1;

Explanation

  • (1) Frequently, each state machine and its states are encapsulated inside a dedicated source file (.c file), from which the RKH_CREATE_COND_STATE() macro is used.
  • (2) C1 is the pseudostate name. Represents a conditional pseudostate structure.

Customization

Each RKH application must have its own configuration file, called rkhcfg.h. This file adapts and configures RKH by means of compiler definitions and macros allowing to restrict the resources consumed by RKH. Adjusting this definitions allows to reduce the ROM and RAM consumption, and to enhance the system performance in a substantial manner. The rkhcfg.h shows the general layout of the configuration file.

Use the following macros to reduce the memory taken by state machine structure: RKH_CFG_SMA_HCAL_EN, RKH_CFG_SMA_PSEUDOSTATE_EN, RKH_CFG_SMA_CONDITIONAL_EN, RKH_SMA_MAX_TR_SEGS. See Configuration section for more information.

Prev: Quick reference


Defining a branch table


Prev: Quick reference

A condition connector has one incoming transition and can have several outgoing transition segments called branches. Branches are labeled with guards that determine which one is to be actually taken. Since the condition connector is an OR connector, only one of the branches can be taken. Each condition connector can have one special branch with a guard labeled rkh_sm_else, which is taken if all the guards on the other branches are false. Branches cannot contain triggers, but in addition to a guard they may contain actions. A branch can enter another condition connector, thus providing for the nesting of branches. In RKH branches are defined by the macro RKH_BRANCH(). The general syntax of an expression labelling a branch in a statechart is "[c]/a" where c is a condition that guards the transition from being taken unless it is true, and a is an action that is carried out if and when the transition is taken. All of these parts are optional. Example:

(2) RKH_BRANCH( power_ok, enable_process, &S22 ),
(3) RKH_BRANCH( ELSE, abort, &S4 ),
#define RKH_CREATE_BRANCH_TABLE(name)
Definition: rkhsm.h:920
#define ELSE
Each condition connector can have one special branch with a guard labeled ELSE, which is taken if all...
Definition: rkhsm.h:81
#define RKH_END_BRANCH_TABLE
This macro is used to terminate a state transition table. This table have the general structure shown...
Definition: rkhsm.h:1013
#define RKH_BRANCH(guard_, effect_, target_)
This macro defines a branch in the branch table.
Definition: rkhsm.h:956

Explanation

  • (2) The RKH_BRANCH() macro defines a branch segment, where power_ok() is the guard function, enable_process is the action function to be taken, and S22 is the target state.
  • (3) If all the guards on the other branches are false abort() function will be invoked, and S4 will be the next state.

As said above, the actions and guards in RKH framework are represented by functions.


Prev: Quick reference


Defining a shallow history pseudostate


Prev: Quick reference

A shallow history pseudostate is defined with the RKH_CREATE_SHALLOW_HISTORY_STATE() macro and declared with the RKH_DCLR_SHIST_STATE macro. Frequently, each state machine and its states and pseudostates are encapsulated inside a dedicated source file (.c file), from which the RKH_CREATE_SHALLOW_HISTORY_STATE() macro is used. We will develop one example of shallow history pseudostate definition to illustrate the use of this macro. We will give our history pseudostate the name H1. As will demostrates the use of RKH_CREATE_SHALLOW_HISTORY_STATE() macro and its arguments is very similar to RKH_CREATE_COND_STATE() macro.

Defining a shallow history pseudostate

(1) // my.c: state-machine's module
(3) 6,
(4) &S1 );
#define RKH_CREATE_SHALLOW_HISTORY_STATE(name, parent, dftTrnGuard, dftTrnAction, dftTarget)
Definition: rkhsm.h:436

Declaring a shallow history pseudostate

// my.h: state-machine's header file
...
RKH_DCLR_DHIST_STATE H1;

Explanation

  • (1) Frequently, each state machine and its states are encapsulated inside a dedicated source file (.c file), from which the RKH_CREATE_SHALLOW_HISTORY_STATE() macro is used.
  • (2) H1 is the pseudostate name. Represents a shallow history pseudostate structure.
  • (3) 6 is the value of pseudostate ID.
  • (6) S1 is the parent state of H1.

Customization

Each RKH application must have its own configuration file, called rkhcfg.h. This file adapts and configures RKH by means of compiler definitions and macros allowing to restrict the resources consumed by RKH. Adjusting this definitions allows to reduce the ROM and RAM consumption, and to enhance the system performance in a substantial manner. The rkhcfg.h shows the general layout of the configuration file. Use the following macros to reduce the memory taken by state machine structure: RKH_CFG_SMA_HCAL_EN, RKH_CFG_SMA_PSEUDOSTATE_EN, RKH_SMA_MAX_TR_SEGS, RKH_EN_SHALLOW_HISTORY. See Configuration section for more information.

Prev: Quick reference


Defining a deep history pseudostate


Prev: Quick reference

A deep history pseudostate is defined with the RKH_CREATE_DEEP_HISTORY_STATE() macro and declared with the RKH_DCLR_DHIST_STATE macro. Frequently, each state machine and its states and pseudostates are encapsulated inside a dedicated source file (.c file), from which the RKH_CREATE_DEEP_HISTORY_STATE() macro is used. We will develop one example of deep history pseudostate definition to illustrate the use of this macro. We will give our history pseudostate the name H2. As will demostrates the use of RKH_CREATE_DEEP_HISTORY_STATE() macro and its arguments is very similar to RKH_CREATE_SHALLOW_HISTORY_STATE() macro.

Defining a deep history pseudostate

(1) // my.c: state-machine's module
(4) &S21 );
#define RKH_CREATE_DEEP_HISTORY_STATE(name, parent, dftTrnGuard, dftTrnAction, dftTarget)
Definition: rkhsm.h:393

Declaring a shallow history pseudostate

// my.h: state-machine's header file
...
RKH_DCLR_DHIST_STATE H1;

Explanation

  • (1) Frequently, each state machine and its states are encapsulated inside a dedicated source file (.c file), from which the RKH_CREATE_DEEP_HISTORY_STATE() macro is used.
  • (2) H2 is the pseudostate name. Represents a deep history pseudostate structure.
  • (6) S21 is the parent state of H2.

Customization

Each RKH application must have its own configuration file, called rkhcfg.h. This file adapts and configures RKH by means of compiler definitions and macros allowing to restrict the resources consumed by RKH. Adjusting this definitions allows to reduce the ROM and RAM consumption, and to enhance the system performance in a substantial manner. The rkhcfg.h shows the general layout of the configuration file. Use the following macros to reduce the memory taken by state machine structure: RKH_CFG_SMA_HCAL_EN, RKH_CFG_SMA_PSEUDOSTATE_EN, RKH_SMA_MAX_TR_SEGS, RKH_EN_DEEP_HISTORY. See Configuration section for more information.

Prev: Quick reference


Defining a choice pseudostate


Prev: Quick reference

A choice pseudostate is defined with the RKH_CREATE_CHOICE_STATE() macro and declared with the RKH_DCLR_CHOICE_STATE macro. Frequently, each state machine and its states and pseudostates are encapsulated inside a dedicated source file (.c file), from which the RKH_CREATE_CHOICE_STATE() macro is used. We will develop one example of choice pseudostate definition to illustrate the use of this macro. We will give our choice pseudostate the name CH. As will demostrates the use of RKH_CREATE_CHOICE_STATE() macro and its arguments is very similar to RKH_CREATE_COND_STATE() macro.

Defining a choice pseudostate

(1) // my.c: state-machine's module
#define RKH_CREATE_CHOICE_STATE(name)
This macro creates a choice pseudostate.
Definition: rkhsm.h:349

Declaring a choice pseudostate

// my.h: state-machine's header file
...
RKH_DCLR_CHOICE_STATE CH;

Explanation

  • (1) Frequently, each state machine and its states are encapsulated inside a dedicated source file (.c file), from which the RKH_CREATE_CHOICE_STATE() macro is used.
  • (2) CH is the pseudostate name. Represents a choice pseudostate structure.

Customization

Each RKH application must have its own configuration file, called rkhcfg.h. This file adapts and configures RKH by means of compiler definitions and macros allowing to restrict the resources consumed by RKH. Adjusting this definitions allows to reduce the ROM and RAM consumption, and to enhance the system performance in a substantial manner. The rkhcfg.h shows the general layout of the configuration file.

Use the following macros to reduce the memory taken by state machine structure: RKH_CFG_SMA_HCAL_EN, RKH_CFG_SMA_PSEUDOSTATE_EN, RKH_CFG_SMA_CHOICE_EN, RKH_SMA_MAX_TR_SEGS. See Configuration section for more information.

Prev: Quick reference


Defining entry, exit, and transition actions


Prev: Quick reference

This section summarize the functions and its prototypes used by RKH framework. As mentioned before, the framework make use the callbacks, i.e. pointer to functions, in most of its data structures by means of RKH_SMA_CREATE(), RKH_CREATE_COMP_STATE(), RKH_CREATE_BASIC_STATE(), RKH_TRINT(), RKH_TRREG(), RKH_BRANCH(), RKH_CREATE_SHALLOW_HISTORY_STATE(), RKH_CREATE_DEEP_HISTORY_STATE(), and RKH_CREATE_CHOICE_STATE() macros. Obviously, the set of available functions and its configurations is mandatory to known for properly using the framework.

Initialization action

Transition actions are small atomic behaviors executed at specified points in a state machine. This actions are assumed to take an insignificant amount of time to execute and are noninterruptible. UML statecharts are extended state machines with characteristics of both Mealy and Moore automata. In statecharts, actions generally depend on both the state of the system and the triggering event, as in a Mealy automaton. Additionally, UML statecharts provide optional entry and exit actions, which are associated with states rather than transitions, as in a Moore automaton. An action function takes the state machine pointer and the event pointer as arguments. These arguments are optional, thus they could be eliminated in compile-time by means of RKH_CFG_SMA_ACT_ARG_EVT_EN and RKH_CFG_SMA_ACT_ARG_SMA_EN.

The RKH implementation preserves the transition sequence imposed by Harel's Statechart and UML. Specifically, the implemented transition sequence is as follows:

  • Execute exit actions of the source state.
  • Execute the transition actions.
  • Execute entry actions of the target state.
Note
This callback is referenced from RKH_TRREG() and RKH_TRINT()macro.

As said above, the application must explicitly trigger initial transitions in all state machines. The following listing shows the use of rkh_sma_activate() function, when it's is called the initial action is invoked and the state machine start. The rkh_sma_activate() is a platform-dependent function. All RKH ports must be defined in the RKH port file to a particular platform. However, only the ports to the external OS/RTOS usually need some code to bolt the framework to the external OS/RTOS.

// start the manager state machine application
rkh_sma_activate( manager, // state machine application (SMA)
qmgr, // event storage area for manager SMA
QMGR_SIZE, // size of the storage area
( void * )0, // not used
0 ); // not used
void rkh_sma_activate(RKH_SMA_T *me, const RKH_EVT_T **qSto, RKH_QUENE_T qSize, void *stkSto, rui32_t stkSize)
Initializes and activates a previously created state machine application (SMA) as known as active obj...

The next listing shows an example of the initial action implementation.

void
manager_init( const struct rkh_t *sma, RKH_EVT_T *pe )
{
dprint( "Init \"manager\" state machine\n" );
manager_turnon();
}

Exit action

The actions that are always execute when a state is exited should be exit actions. UML statecharts provide optional entry and exit actions, which are associated with states rather than transitions, as in a Moore automaton. An exit function takes the state machine pointer as argument. This argument is optional, thus it could be eliminated in compile-time by means of RKH_CFG_SMA_EXT_ARG_SMA_EN.

The RKH implementation preserves the transition sequence imposed by Harel's Statechart and UML. Specifically, the implemented transition sequence is as follows:

  • Execute exit actions of the source state.
  • Execute the transition actions.
  • Execute entry actions of the target state.
Note
This callback is referenced from RKH_CREATE_COMP_STATE() and RKH_CREATE_BASIC_STATE() macros.

The next listing shows an example of the exit action implementation.

void
idle_exit( const struct rkh_t *sma )
{
dprint( "Exit from \"IDLE\" state\n" );
manager_restore();
}

Entry action

The actions that are always executed when a state is entered should be specified as entry actions. UML statecharts provide optional entry and exit actions, which are associated with states rather than transitions, as in a Moore automaton. An entry function takes the state machine pointer as argument. This argument is optional, thus it could be eliminated in compile-time by means of RKH_CFG_SMA_ENT_ARG_SMA_EN.

The RKH implementation preserves the transition sequence imposed by Harel's Statechart and UML. Specifically, the implemented transition sequence is as follows:

  • Execute exit actions of the source state.
  • Execute the transition actions.
  • Execute entry actions of the target state.
Note
This callback is referenced from RKH_CREATE_COMP_STATE() and RKH_CREATE_BASIC_STATE() macros. RKH_CFG_SMA_ENT_ARG_SMA_EN macro.

The next listing shows an example of the entry action implementation.

void
wait_process_entry( const struct rkh_t *sma )
{
dprint( "Entry to \"WAIT_PROCESS\" state\n" );
manager_deactivate();
}

Transition action

Transition actions are small atomic behaviors executed at specified points in a state machine. This actions are assumed to take an insignificant amount of time to execute and are noninterruptible. UML statecharts are extended state machines with characteristics of both Mealy and Moore automata. In statecharts, actions generally depend on both the state of the system and the triggering event, as in a Mealy automaton. Additionally, UML statecharts provide optional entry and exit actions, which are associated with states rather than transitions, as in a Moore automaton. An action function takes the state machine pointer and the event pointer as arguments. These arguments are optional, thus they could be eliminated in compile-time by means of RKH_CFG_SMA_ACT_ARG_EVT_EN and RKH_CFG_SMA_ACT_ARG_SMA_EN.

The RKH implementation preserves the transition sequence imposed by Harel's Statechart and UML. Specifically, the implemented transition sequence is as follows:

  • Execute exit actions of the source state.
  • Execute the transition actions.
  • Execute entry actions of the target state.
Note
This callback is referenced from RKH_TRREG() and RKH_TRINT()macro.

The next listing shows an example of the transition action implementation.

void
set_config( const struct rkh_t *sma, RKH_EVT_T *pe )
{
MYEVT_T *e;
(void)sma; /* argument not used */
(void)pe; /* argument not used */
e = RKH_ALLOC_EVT( MYEVT_T, SIX, sma );
e->ts = ( rui16_t )rand();
RKH_TMR_ONESHOT( &my_timer, sma, MY_TICK );
}
#define RKH_ALLOC_EVT(et, e, sender_)
This macro dynamically creates a new event of type et with its signal.
#define RKH_TMR_ONESHOT(t, sma, itick)
Start a timer as one-shot timer.
Definition: rkhtmr.h:187

Event preprocessor

Before sending the arrived event to state machine, it can be previously processed using the event preprocessor function. The RKH framework provides optional event preprocessor action, which are associated with states rather than transitions, as in a Moore automaton. This action takes the state machine pointer and the event pointer as arguments. This argument is optional, thus it could be eliminated in compile-time by means of RKH_CFG_SMA_PPRO_ARG_SMA_EN.

Note
This callback is referenced from RKH_CREATE_COMP_STATE() and RKH_CREATE_BASIC_STATE() macros.

The next listing shows an example of the event preprocessor action implementation.

preprocess_keys( const struct rkh_t *sma, RKH_EVT_T *pe )
{
if( pe->e >= 0 && pe->e <= 9 )
return DECIMAL;
if( pe->e == '.' )
return POINT;
else
return pe->e;
}

Guard

A guard is a boolean condition that returns a true (RKH_GTRUE) or false (RKH_GFALSE) value that controls whether or not a transition is taken following the receipt of a triggering event. A transition with a guard is only take if the triggering event occurs and the guard evaluates to true. As long as the guard evaluated to false, the triggering event would be discarded and the transition would not be taken. Each condition connector can have one special branch with a guard labeled rkh_sm_else, which is taken if all the guards on the other branches are false. A guard function takes the state machine pointer and the event pointer as arguments. These arguments are optional, thus they could be eliminated in compile-time by means of RKH_CFG_SMA_GRD_ARG_EVT_EN and RKH_CFG_SMA_GRD_ARG_SMA_EN.

Note
This callback is referenced from RKH_BRANCH() macro.

The next listing shows an example of the guard function implementation.

rbool_t
is_zero( const struct rkh_t *sma, RKH_EVT_T *pe )
{
return get_water_level( CHANNEL( (( CHEVT_T* )pe)->ch ) ) == 0;
}


Prev: Quick reference


Using events with parameters


Prev: Quick reference

An event can have associated parameters, allowing the event instance to convey not only the occurrence of some interesting incident but also quantitative information regarding that occurrence. Implementing the single inheritance in C is very simply by literally embedding the base structure, RKH_EVT_T in this case, as the first member of the derived structure. For example, the structure MYEVT_T derived from the base structure RKH_EVT_T by embedding the RKH_EVT_T instance as the first member of MYEVT_T. See also, Using dynamic and static events section for more information.

typedef struct
{
RKH_EVT_T evt; // base structure
int x; // parameter 'x'
int y; // parameter 'y'
} MYEVT_T;

Such nesting of structures always aligns the data member 'evt' at the beginning of every instance of the derived structure. In particular, this alignment lets you treat a pointer to the derived MYEVT_T structure as a pointer to the RKH_EVT_T base structure. Consequently, you can always safely pass a pointer to MYEVT_T to any C function that expects a pointer to RKH_EVT_T. (To be strictly correct in C, you should explicitly cast this pointer. In OOP such casting is called upcasting and is always safe.) Therefore, all functions designed for the RKH_EVT_T structure are automatically available to the MYEVT_T structure as well as other structures derived from RKH_EVT_T.

The RKH takes the 'e' member of RKH_EVT_T structure for triggering a state transition.

See also rkh_sma_put_fifo(), rkh_sma_put_lifo(), RKH_ALLOC_EVT(), RKH_SET_STATIC_EVENT(), and RKH_FWK_GC().


Prev: Quick reference


Using dynamic and static events


Prev: Quick reference

In RKH as other frameworks, the actual event instances are either constant events (or static events) statically allocated at compile time or dynamic events allocated at runtime from one of the event pools that the framework manages.

This section includes:

Registering the event pool

Before using dynamic events (or event with arguments) the application code must register the proper event pools, which stores the events as a fixed-sized memory block. Each event pool must be registered with the RKH framework, by means of the rkh_fwk_epool_register() function. This function initializes one event pool at a time and must be called exactly once for each event pool before the pool can be used.

The application code might initialize the event pools by making calls to the rkh_fwk_epool_register() function. However, for the simplicity of the internal implementation, the application code initialize event pools in the ascending order of the event size.

#define SIZEOF_EP0STO 64
#define SIZEOF_EP0_BLOCK sizeof( TOUT_T )
#define SIZEOF_EP1STO 32
#define SIZEOF_EP1_BLOCK sizeof( DIAL_T )
#define SIZEOF_EP2STO 32
#define SIZEOF_EP2_BLOCK sizeof( SETUP_T )
typedef struct
{
RKH_EVT_T evt; // base structure
int timerno; // parameter 'timerno'
} TOUT_T;
typedef struct
{
RKH_EVT_T evt; // base structure
char dial[ MAX_SIZE_DIAL ]; // parameter 'dial'
int qty; // parameter 'qty'
} DIAL_T;
typedef struct
{
RKH_EVT_T evt; // base structure
int volume; // parameter 'volume'
int baud_rate; // parameter 'baud_rate'
char name[ MAX_SIZE_NAME ]; // parameter 'name'
int iloop; // parameter 'iloop'
} SETUP_T;
// declares the storage memory of event pool
static rui8_t ep0sto[ SIZEOF_EP0STO ],
ep1sto[ SIZEOF_EP1STO ],
ep2sto[ SIZEOF_EP2STO ];
...
rkh_fwk_epool_register( ep0sto, SIZEOF_EP0STO, SIZEOF_EP0_BLOCK );
rkh_fwk_epool_register( ep1sto, SIZEOF_EP1STO, SIZEOF_EP1_BLOCK );
rkh_fwk_epool_register( ep2sto, SIZEOF_EP2STO, SIZEOF_EP2_BLOCK );
...

Allocating events

(1) typedef struct
{
RKH_EVT_T evt; // base structure
char dial[ MAX_SIZE_DIAL ]; // parameter 'dial'
int qty; // parameter 'qty'
} DIAL_T;
(2) typedef struct
{
RKH_EVT_T evt; // base structure
int volume; // parameter 'volume'
int baud_rate; // parameter 'baud_rate'
char name[ MAX_SIZE_NAME ]; // parameter 'name'
int iloop; // parameter 'iloop'
} SETUP_T;
typedef struct
{
RKH_EVT_T evt;
int timerno;
} TOUT_T;
(3) static RKH_ROM_STATIC_EVENT( offh, OFFHOOK );
(4) static TOUT_T tout;
...
(5) RKH_SET_STATIC_EVENT( &tout, TIMEOUT );
(6) DIAL_T *de = RKH_ALLOC_EVT( DIAL_T, DIALED, me );
(7) SETUP_T *se = RKH_ALLOC_EVT( SETUP_T, SET_CONFIG, me );
(8) se->volume = 0;
se->baud_rate = DEFAULT_BAUD_RATE;
se->iloop = 2;
#define RKH_SET_STATIC_EVENT(ev_obj, ev_sig)
This macro initialize an event e with es signal and establishes it as one static event.

Explanation

  • (1-2) As mentioned before, implementing the single inheritance in C is very simply by literally embedding the base structure, RKH_EVT_T in this case, as the first member of the derived structure, DIAL_T and SETUP_T.
  • (3) The OFFHOOK event never changes, so it can be statically allocated just once. This event is declared as const, which means that it can be placed in ROM. The initializer list for this event consists of the signal OFFHOOK followed by zero. This zero informs the RKH framework that this event is static and should never be recycled to an event pool.
  • (4) The TIMEOUT( timerno ) event is an example of an event with changing parameters. In general, such an event cannot be allocated in ROM like the OFFHOOK event because it can change.
  • (5) This macro set the event TIMEOUT( timerno ) with TIMEOUT signal and establishes it as one static event.
  • (6-7) The RKH_ALLOC_EVT() macro dynamically creates a new instances events of type DIAL_T and SETUP_T with DIALED and SET_CONFIG signals. These events are represented like this: DIALED( dial, qty ) and SET_CONFIG( volume, baud_rate, name, iloop ) This macro returns a pointer to the event already cast to the required event type.
  • (8) The volume, baud_rate, and iloop parameters of the event are assigned.

Just one another example that it could be used to easily debug an application with static events.

typedef struct
{
RKH_EVT_T evt;
#if SYSEVT_DEBUG == 1
char *name;
#endif
} SYSEVT_T;
#if SYSEVT_DEBUG == 1
#define mkse( e, n ) { { (e), 0, 0 }, (n) }
#else
#define mkse( e, n ) { { (e), 0, 0 } }
#endif
static const SYSEVT_T sysevts[] =
{
mkse( OFFHOOK, "offhook" ),
mkse( ONHOOK, "onhook" ),
mkse( POLREV, "polarity reversal" ),
mkse( BTONE, "billing tone" ),
...
};

Posting events

The RKH framework supports one type of asynchronous event exchange: the simple mechanism of direct event posting supported through the functions rkh_sma_post_fifo() and rkh_sma_post_lifo(), when the producer of an event directly posts the event to the event queue of the consumer SMA (active object).

(1) static RKH_ROM_STATIC_EVENT( eterm, TERM );
...
(2) rkh_sma_post_fifo( manager, &eterm );
void rkh_sma_post_fifo(RKH_SMA_T *me, const RKH_EVT_T *e, const void *const sender)
Send an event to a state machine application (SMA) as known as active object through a queue using th...
  • (1) Declares and initializes the event eterm with TERM signal and establishes it as one static event.
  • (2) The eterm event is sent directly to the manager SMA.
...
(1) mye = RKH_ALLOC_EVT( MYEVT_T, kbmap( c ), me );
(2) mye->ts = ( rui16_t )rand();
(3) rkh_sma_post_fifo( my, ( RKH_EVT_T* )mye );
  • (1) Dynamically creates a new event mye of type MYEVT_T with the signal returned from the kbmap() function.
  • (2) Use the extended members of the event mye.
  • (3) The mye event is sent directly to the my SMA.

Recycling dynamic events

If the system make use of dynamic events facility after the processing, you must not forget to call the RKH garbage collector, because now RKH is no longer in charge of event processing and you are solely responsible for not leaking the event. The garbage collector actually recycles the event only when it determines that the event is no longer referenced. The following listing illustrates how and when to invoke RKH_FWK_GC() macro to recycle "dynamic" events.

void
rkh_fwk_enter( void )
{
rui8_t prio;
RKH_SMA_T *sma;
FOREVER
{
if( RKH_RDY_ISNOT_EMPTY( rkhrg ) )
{
RKH_RDY_FIND_HIGHEST( rkhrg, prio );
sma = rkh_sptbl[ prio ];
(1) e = rkh_sma_get( sma );
(2) rkh_sm_dispatch( (RKH_SM_T *)sma, e );
(3) RKH_FWK_GC( e );
}
else
//
// rkh_hook_idle() must be called with interrupts DISABLED because the
// determination of the idle condition (no events in the queues) can
// change at any time by an interrupt posting events to a queue. The
// rkh_hook_idle() MUST enable interrups internally, perhaps at the
// same time as putting the CPU into a power-saving mode.
//
}
}
void rkh_hook_start(void)
This hook function is called just before the RKH takes over control of the application.
void rkh_hook_idle(void)
An idle hook function will only get executed (with interrupts LOCKED) when there are no SMAs of highe...
#define RKH_FWK_GC(e, sender_)
Recycle a dynamic event.
RKH_EVT_T * rkh_sma_get(RKH_SMA_T *me)
Get an event from the event queue of an state machine application (SMA) as known as active object....
void rkh_fwk_enter(void)
RKH framework is started.
ruint rkh_sm_dispatch(RKH_SM_T *me, RKH_EVT_T *e)
Executes a state machine in a run-to-completation (RTC) model.
RKH_SMA_T * rkh_sptbl[RKH_CFG_FWK_MAX_SMA]
Priority arranged table of registered SMA.
#define RKH_TR_FWK_EN()
Initializes the RKH framework.
#define RKH_DIS_INTERRUPT()
RKH need to disable interrupts in order to access critical sections of code, and re-enable interrupts...
Definition: rkhitl.h:1998
#define RKH_ENA_INTERRUPT()
RKH need to disable interrupts in order to access critical sections of code, and re-enable interrupts...
Definition: rkhitl.h:1999
Describes the state machine.
Definition: rkhsm.h:1905
  • (1) An event e is get from the SMA queue with the highest priority.
  • (2) The event e is dispatched to the current SMA.
  • (2) Thus, the event e is passed to the RKH garbage collector for recycling. As described above, the RKH_FWK_GC() macro actually recycles the wvent only when it determines that the event is no longer referenced.

Customization

Each RKH application must have its own configuration file, called rkhcfg.h. This file adapts and configures RKH by means of compiler definitions and macros allowing to restrict the resources consumed by RKH. Adjusting this definitions allows to reduce the ROM and RAM consumption, and to enhance the system performance in a substantial manner. The rkhcfg.h shows the general layout of the configuration file. Use the following macros to reduce the memory taken by state machine structure: RKH_CFG_FWK_DYN_EVT_EN, RKH_CFG_FWK_MAX_EVT_POOL, RKH_CFG_FWK_SIZEOF_EVT, RKH_CFG_FWK_SIZEOF_EVT_SIZE, RKH_CFGPORT_NATIVE_DYN_EVT_EN, RKH_DYNE_TYPE, RKH_DYNE_INIT, RKH_DYNE_GET_ESIZE, RKH_DYNE_GET, RKH_DYNE_PUT, RKH_DYNE_GET_NFREE, RKH_DYNE_GET_NMIN, RKH_DYNE_GET_PSIZE. See Configuration section for more information.

Prev: Quick reference


Preprocessing events before of dispatch it


Prev: Quick reference

Before sending the arrived event to state machine, it can be previously processed using the event preprocessor function. The RKH framework provides optional event preprocessor action, which are associated with states rather than transitions, as in a Moore automaton. This action takes the state machine pointer and the event pointer as arguments. This argument is optional, thus it could be eliminated in compile-time by means of RKH_CFG_SMA_PPRO_ARG_SMA_EN.

Note
This callback is referenced from RKH_CREATE_COMP_STATE() and RKH_CREATE_BASIC_STATE() macros.

The next listing shows an example of the event preprocessor action implementation.

preprocess_keys( const struct rkh_t *sma, RKH_EVT_T *pe )
{
printf( "From state machine \"%s\"\n", rkh_get_sm_name( sma ) );
if( pe->e >= 0 && pe->e <= 9 )
return DECIMAL;
if( pe->e == '.' )
return POINT;
else
return pe->e;
}


Prev: Quick reference


Deferring and recalling events


Prev: Quick reference

Event deferral comes in very handy when an event arrives in a particularly inconvenient moment but can be deferred for some later time, when the system is in a much better position to handle the event. RKH supports very efficient event deferring and recalling mechanisms. This function is part of the event deferral mechanism. An SMA uses this function to defer an event e to the event queue q. RKH correctly accounts for another outstanding reference to the event and will not recycle the event at the end of the RTC step. Later, the SMA might recall one event at a time from the event queue by means of rkh_sma_recall(sma,q) function. Recalling an event means that it is removed from the deferred event queue q and posted (LIFO) to the event queue of the sma state machine application.

This section includes:

Deferring an event

static RKH_QUEUE_T qurc;
static RKH_EVT_T *qurc_sto[ MAX_SIZEOF_QURC ];
(1) rkh_queue_init( &qurc, (const void **)qurc_sto, MAX_SIZEOF_QURC, NULL );
...
void
ring( const struct rkh_t *sma, RKH_EVT_T *pe )
{
(void)sma; // argument not used
(2) rkh_sma_defer( &qurc, pe );
}
void rkh_queue_init(RKH_QUEUE_T *q, const void **sstart, RKH_QUENE_T ssize, void *sma)
Initializes the previously allocated queue data structure RKH_QUEUE_T.
void rkh_sma_defer(RKH_QUEUE_T *q, const RKH_EVT_T *e)
Defer an event to a given separate event queue.
Defines the data structure used to maintain information about the queue.
Definition: rkhqueue.h:170

Explanation

  • (1) Initialize the qurc queue to be used as deferred queue.
  • (1) Defers the event pe to the previously created event queue qurc.

Recalling an event

void
exit_rx_manager( const struct rkh_t *sma )
{
(1) rkh_sma_defer( sma, &qurc );
}

Explanation

  • (1) Removes an event from the deferred event queue qurc and posts (LIFO) to the event queue of the sma state machine application.


Prev: Quick reference


Using assertions


Prev: Quick reference

The assertions (RKH_ASSERT() macro) are used to check expressions that ought to be true as long as the program is running correctly. It is a convenient way to insert sanity checks.

A number of philosophies can be employed when deciding where to use an RKH_ASSERT() macro. Broadly speaking, the assertions only serve the purposes of catching bugs and helping documentation. Helping to document the code means that the statements inside the assertion tell the reader something he might not already know.


Prev: Quick reference


Debugging an application based on RKH's state machines


Prev: Quick reference

Please refer to Tracing tool section.


Prev: Quick reference


Initializing a state machine and dispatching events


Prev: Quick reference

The following listing shows an very simple example of the main() function implementation and demostrates how to use the RKH API.

Note
See Getting started with RKH section for more information about this.
...
typedef struct
{
RKH_EVT_T event;
rkhuint16 ts;
} MYEVT_T;
static MYEVT_T mye;
...
int
main( int argc, char *argv[] )
{
int c;
srand( ( unsigned )time( NULL ) );
(3) rkh_sm_init( (RKH_SM_T *)my );
(4) FOREVER
{
(5) c = mygetch();
if( c == 'p' )
else if ( c == ESC )
{
(7) rkh_sm_dispatch( (RKH_SM_T *)my, &term );
break;
}
else
{
(8) mye = RKH_ALLOC_EVT( MYEVT_T, kbmap( c ), 0 );
(9) mye->ts = ( rui16_t )rand();
(10) rkh_sm_dispatch( (RKH_SM_T *)my, ( RKH_EVT_T* )mye );
}
}
(12) rkh_fwk_exit();
}
void rkh_trc_open(void)
Open the tracing session.
void rkh_trc_flush(void)
Platform-dependent macro flushing the trace stream.
void rkh_trc_close(void)
Close the tracing session.
void rkh_fwk_exit(void)
Exit the RKH framework.
void rkh_fwk_init(void)
Initializes the RKH framework.
void rkh_sm_init(RKH_SM_T *me)
Inits a previously created state machine calling its initializing action.
  • (1) Open the trace session.
  • (2) Initialize the framework RKH.
  • (3) Initialize the my state machine. RKH invokes the defined init action.
  • (4) This is the event loop of the framework RKH.
  • (5) Gets key pressed from the standard input.
  • (6) Flush the trace stream.
  • (7) Send the term event to my state machine to terminate. After that, terminates the program.
  • (8) Allocates an event of MYEVT_T type (derived from RKH_EVT_T) to store the key pressed.
  • (9) The event has associated parameters that convey a random number.
  • (10) The mye event is dispatched to my state machine. Events with parameters, such as the MYEVT_T, require explicit casting from the generic base structure RKH_EVT_T to the specific derived structure MYEVT_T.
  • (11-12) Close the trace session and terminates the program.

Using software timers


Prev: Quick reference

This section includes:

Declaring, and initializing a timer

#define SYNC_TIME RKH_TIME_MS(100)
...
(1) static RKHTmEvt tmSync;
...
void
powerOn(ActiveObject *const me)
{
(2) RKH_SET_STATIC_EVENT(&tmSync, Sync);
RKH_TMR_INIT(&tmSync.tmr,
RKH_UPCAST(RKH_EVT_T, &tmSync),
NULL);
(3) RKH_TMR_ONESHOT(&tmSync.tmr,
SYNC_TIME);
}
#define RKH_UPCAST(BaseType_, me_)
Convert a pointer to a base-class.
Definition: rkhfwk_cast.h:74
#define RKH_TMR_INIT(t_, e_, th_)
Initializes the previously allocated timer structure RKH_TMR_T.
Definition: rkhtmr.h:143
It defines a time event that occurs at a specific duration.
Definition: rkhtmr.h:409
RKH_TMR_T tmr
Definition: rkhtmr.h:411

Explanation

  • (1) Declares and allocates the tmSync time event.
  • (2) Initializes tmSync like a static time event with signal Sync. It should be used like a transition's trigger to support the UML's time event 'after SYNC_TIME':
    RKH_CREATE_BASIC_STATE(s1, powerOn, powerOff, RKH_ROOT, NULL);
    RKH_TRREG(Sync, NULL, NULL, &s0), /* 'Sync' signal enables this */
    /* transition to 's0' state */
    /* It is equivalent to */
    /* 'after SYNC_TIME' UML's TimeEvent */
    #define RKH_ROOT
    This macro indicates the root state of a state machine.
    Definition: rkhsm.h:1019
  • (3) Initializes the tmSync timer as oneshot. When it expires the me active object will receive an event with Sync signal. The tmSync will expire after SYNC_TIME ticks.

Start and stop timers

(1) #define TPWROFF_TIME RKH_TIME_MS(100)
(2) #define TKEY_TIME RKH_TIME_MS(100)
#define TKEYSTART_TIME RKH_TIME_MS(300)
...
(3) static RKHTmEvt tPwrOff,
(4) tKey;
...
void
start(PowerMonitor *const me)
{
(5) RKH_TMR_ONESHOT(&tPwrOff.tmr,
TPWROFF_TIME);
}
...
void
close(PowerMonitor *const me)
{
(6) RKH_TMR_PERIODIC(&tKey.tmr,
TKEYSTART_TIME,
TKEY_TIME);
}
...
void
detect(PowerMonitor *const me)
{
(7) rkh_tmr_stop(&tKey);
(8) rkh_tmr_stop(&tPwrOff);
}
rbool_t rkh_tmr_stop(RKH_TMR_T *t)
Stops a running timer.
#define RKH_TMR_PERIODIC(t, sma, itick, per)
Start a timer as periodic timer.
Definition: rkhtmr.h:234
#define RKH_TIME_MS(ms_)
It can be used to convert ticks to time.
Definition: rkhitl.h:1618

Explanation

  • (1-2) Defines the number of millisencods for timer expiration using the macro RKH_TIME_MS(), which converts ticks to time.
  • (3-4) Declares and allocates the tPwrOff, and tKey event timers.
  • (5) Starts the previously initialized tPwrOff event timer as oneshot timer, which posts the evPwrOff signal to PowerMonitor active object after TPWROFF_TIME ticks.
  • (6) Starts the previously initialized tKey event timer as periodic timer, which posts the evKey signal to PowerMonitor active object after TKEYSTART_TIME ticks initially and then after every TKEY_TIME ticks.
  • (7-8) Stops both event timers.

Customization

Each RKH application must have its own configuration file, called rkhcfg.h. This file adapts and configures RKH by means of compiler definitions and macros allowing to restrict the resources consumed by RKH. Adjusting this definitions allows to reduce the ROM and RAM consumption, and to enhance the system performance in a substantial manner. The rkhcfg.h shows the general layout of the configuration file. Use the following macros to reduce the memory taken by state machine structure: RKH_CFG_TMR_EN, RKH_CFG_TMR_SIZEOF_NTIMER, RKH_CFG_TMR_HOOK_EN, RKH_CFG_TMR_GET_INFO_EN. See Configuration section for more information.

Prev: Home