Deterministic Real-Time Behavior

Deterministic here does not imply fixed-sequence polling. Although this is possible too, the RXF uses a different method to achieve a deterministic behavior. The RXF serves your generated application. It will provide services like sending and receiving events, handling timeout events and more.

How Events are processed.

When an event is sent, the RXF will store a pointer to that event in a queue for the appropriate task, where it will be handled in a FIFO manner. The handling of events is also done by the RXF. Handling events also means handling expired timers that are converted to events when they expire.

An event for a specific object will be given to the generated event handle function of that Objects Class. This function carries out all the associated actions (On Entry, On Exit, in State, in transitions) and will return the control to the RXF when finished.

This will guarantee a flawless handling of events in a deterministic way. Actions can be delayed by other actions but only for a time that can easily be calculated.

How Time-outs (tm(xx) ) are handled.

When the tm(xx) statement is used in a state-machine, the user wants a certain delay in the processing of states. tm(xx) in a transition means: Wait xx milliseconds and then take this transition (and execute all attached actions).

The timer ticks are processed by a callback function of the RXF, which is called at a regular interval of MS_PER_TICK ms.

The delay in the tm(Delay) statement should only be a multiple of MS_PER_TICK. Values that do not mach a multiple of the tick time get rounded up to the next matching multiple of ticks (e.g. if the tick time is 10ms and tm(1) is typed, the Delay will be 1 Tick (10ms) ) 

Due to the fact that the timer is derived from an external tick source, the granularity of the ticks is the minimum tick value. It is possible that a timeout request occurs just before a tick would happen or just after a tick has happened, what leads to an inaccuracy of timout transitions of 1 tick.

In general a timeout will expire between ( timeout-time - MS_PER_TICK ) and  timeout-time, or in other words in worst case 1 Tick (or the time defined in MS_PER_TICK) earlier than expected. 

If a MINIMUM time for tm(xx) to pass before the transition is taken needs to be guaranteed, the time of one tick ( value of MS_PER_TICK ) needs to be added to the desired time. This is done automatically by the simplifier for all timeout-transitions of a reactive class, if the property RXF::Class::TimeoutGuaranteeTime is set to true on this class. If this property should be applied to the whole model, it can also be overridden on project or component level.

It is a common problem for timeouts that they can expire 1 tick earlier than expected. See also:
https://www.ibm.com/support/pages/rhapsody-tm-function-not-precise
https://www.keil.com/support/docs/3766.htm


After the timout has expired, a timeout event is placed to the event queue. If a statechart is in the middle of processing an event, that event needs to complete before the timeout is handled. Also there can be other events in the queue that are processed first. This could cause a non-determinable extra delay.

When using the RXF with an RTOS Adapter, please note:
To prevent additional delay through suppression of timer management task by other tasks, the priority of the timer management task should be configured to be the highest.

The following timeout behavior can be observed with MS_PER_TICK = 10 miliseconds:

[tm(0)] - expires immediately - is put to queue without being scheduled.
[tm(1)] - expires after 0 to 10 ms (at the next tick).
[tm(10)] - expires after 10 to 20 ms. (Same behavieor as tm(1) to tm(9))
[tm(11)] - expires after 10 to 20 ms.
[tm(20)] - expires after 10 to 20 ms.
[tm(100)] - expires after 90 to 100 ms.
[tm(1000)] - expires after 990 to 1000 ms.

And so on. So the argument in tm(xx) indicates the time ( minus 1 Tick ) to pass before the transition is taken!

With RXF::Class::TimeoutGuaranteeTime = true the expected timeout values are:

[tm(0)] - expires at the next tick (0 to 10 ms later).
[tm(1)] - expires after 10 to 20 ms.
[tm(10)] - expires after 10 to 20 ms.
[tm(11)] - expires after 20 to 30 ms.
[tm(20)] - expires after 20 to 30 ms.
[tm(100)] - expires after 100 to 110 ms.
[tm(1000)] - expires after 1000 to 1010 ms.

The RXF prevents invalid values for the delay as far as possible:

Run-To-Completion (NULL-Transitions)

In a statechart it is possible to model state transitions that are directly to be taken, without waiting for an event as a trigger. These are so called NULL-transitions. The RXF includes a mechanism to detect endless loops of NULL-transitions (e.g. because of a design error in modeling a state machine) during runtime. An endless loop is detected, if more than a defined number of NULL-transitions occur in a row. This maximum number of directly following NULL-transitions can be configured.

NULL-transitions on Statechart Start Behavior

If the first transition of a statechart is a NULL transition (without trigger) the Framework handles the transition from the context, that calls the startBehavior() operation. From this context a runToCompletion() is executed. That means all following states that are connected with NULL transitions are executed from this startup context. The user should be aware of this when using initial NULL transitions.
If a context switch is required before executing initial behavior, a tm(0) can be used as trigger for a state containing this behavior. A tm(0) will put a timeout event in the event queue immediately and thereby trigger a context switch to the execution context of this statechart.