| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204 |
- /*$file${include::qep.h} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
- /*
- * Model: qpc.qm
- * File: ${include::qep.h}
- *
- * This code has been generated by QM 5.2.5 <www.state-machine.com/qm>.
- * DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
- *
- * This code is covered by the following QP license:
- * License # : LicenseRef-QL-dual
- * Issued to : Any user of the QP/C real-time embedded framework
- * Framework(s) : qpc
- * Support ends : 2023-12-31
- * License scope:
- *
- * Copyright (C) 2005 Quantum Leaps, LLC <state-machine.com>.
- *
- * SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
- *
- * This software is dual-licensed under the terms of the open source GNU
- * General Public License version 3 (or any later version), or alternatively,
- * under the terms of one of the closed source Quantum Leaps commercial
- * licenses.
- *
- * The terms of the open source GNU General Public License version 3
- * can be found at: <www.gnu.org/licenses/gpl-3.0>
- *
- * The terms of the closed source Quantum Leaps commercial licenses
- * can be found at: <www.state-machine.com/licensing>
- *
- * Redistributions in source code must retain this top-level comment block.
- * Plagiarizing this software to sidestep the license obligations is illegal.
- *
- * Contact information:
- * <www.state-machine.com/licensing>
- * <info@state-machine.com>
- */
- /*$endhead${include::qep.h} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
- /*! @file
- * @brief QEP/C platform-independent public interface.
- *
- * @trace
- * @tr{RQP001}, @tr{RQP101}
- */
- #ifndef QEP_H_
- #define QEP_H_
- /*==========================================================================*/
- /*! The current QP version as an unsigned number
- *
- * @details
- * ::QP_VERSION is a decimal constant, where XX is a 1-digit or 2-digit
- * major version number, Y is a 1-digit minor version number, and Z is
- * a 1-digit release number.
- */
- #define QP_VERSION 722U
- /*! The current QP version as a zero terminated string literal.
- *
- * @details
- * ::QP_VERSION_STR is of the form "XX.Y.Z", where XX is a 1-or 2-digit
- * major version number, Y is a 1-digit minor version number, and Z is
- * a 1-digit release number.
- */
- #define QP_VERSION_STR "7.2.2"
- /*! Encrypted current QP release (7.2.2) and date (2023-03-01) */
- #define QP_RELEASE 0x76BAD85DU
- /*==========================================================================*/
- /*$declare${glob-types} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
- /*${glob-types::int_t} .....................................................*/
- /*! alias for line numbers in assertions and return from QF_run() */
- typedef int int_t;
- /*${glob-types::enum_t} ....................................................*/
- /*! alias for enumerations used for event signals */
- typedef int enum_t;
- /*${glob-types::float32_t} .................................................*/
- /*! alias for IEEE 754 32-bit floating point number,
- * MISRA-C 2012 Dir 4.6(A)
- *
- * @note
- * QP does not use floating-point types anywhere in the internal
- * implementation, except in QS software tracing, where utilities for
- * output of floating-point numbers are provided for application-specific
- * trace records.
- */
- typedef float float32_t;
- /*${glob-types::float64_t} .................................................*/
- /*! alias for IEEE 754 64-bit floating point number,
- * MISRA-C 2012 Dir 4.6(A)
- *
- * @note
- * QP does not use floating-point types anywhere in the internal
- * implementation, except in QS software tracing, where utilities for
- * output of floating-point numbers are provided for application-specific
- * trace records.
- */
- typedef double float64_t;
- /*$enddecl${glob-types} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
- /*$declare${QEP-config} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
- /*${QEP-config::Q_SIGNAL_SIZE} .............................................*/
- #ifndef Q_SIGNAL_SIZE
- /*! The size (in bytes) of the signal of an event. Valid values:
- * 1U, 2U, or 4U; default 2U
- *
- * @details
- * This macro can be defined in the QEP port file (qep_port.h) to
- * configure the ::QSignal type. When the macro is not defined, the
- * default of 2 bytes is applied.
- */
- #define Q_SIGNAL_SIZE 2U
- #endif /* ndef Q_SIGNAL_SIZE */
- /*$enddecl${QEP-config} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
- /*==========================================================================*/
- /*$declare${QEP} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
- /*${QEP::QP_versionStr[8]} .................................................*/
- /*! the current QP version number string in ROM, based on #QP_VERSION_STR */
- extern char const QP_versionStr[8];
- /*${QEP::QSignal} ..........................................................*/
- #if (Q_SIGNAL_SIZE == 2U)
- /*! ::QSignal represents the signal of an event
- *
- * @details
- * The relationship between an event and a signal is as follows. A signal
- * in UML is the specification of an asynchronous stimulus that triggers
- * reactions, and as such is an essential part of an event. (The signal
- * conveys the type of the occurrence--what happened?) However, an event
- * can also contain additional quantitative information about the
- * occurrence in form of event parameters.
- */
- typedef uint16_t QSignal;
- #endif /* (Q_SIGNAL_SIZE == 2U) */
- /*${QEP::QSignal} ..........................................................*/
- #if (Q_SIGNAL_SIZE == 1U)
- typedef uint8_t QSignal;
- #endif /* (Q_SIGNAL_SIZE == 1U) */
- /*${QEP::QSignal} ..........................................................*/
- #if (Q_SIGNAL_SIZE == 4U)
- typedef uint32_t QSignal;
- #endif /* (Q_SIGNAL_SIZE == 4U) */
- /*${QEP::QEvt} .............................................................*/
- /*! @brief Event class
- * @class QEvt
- *
- * @details
- * ::QEvt represents events without parameters and serves as the base class
- * for derivation of events with parameters.
- *
- * @trace
- * @tr{RQP001}, @tr{RQP004}, @tr{AQP210}
- *
- * @usage
- * The following example illustrates how to add an event parameter by
- * derivation of the ::QEvt class. Please note that the ::QEvt member
- * super is defined as the FIRST member of the derived struct.
- * @include qep_qevt.c
- */
- typedef struct {
- /* public: */
- /*! Signal of the event.
- * @public @memberof QEvt
- *
- * @trace
- * @tr{RQP002}
- */
- QSignal sig;
- /* private: */
- /*! Pool ID (==0 for immutable event)
- * @private @memberof QEvt
- *
- * @trace
- * @tr{RQP003}
- */
- uint8_t poolId_;
- /*! Reference counter (for mutable events)
- * @private @memberof QEvt
- *
- * @trace
- * @tr{RQP003}
- */
- uint8_t volatile refCtr_;
- } QEvt;
- /* public: */
- #ifdef Q_EVT_CTOR
- /*! Custom event constructor
- * @public @memberof QEvt
- *
- * @note
- * Available only when the macro #Q_EVT_CTOR is defined
- *
- * @trace
- * @tr{RQP005}
- */
- void QEvt_ctor(QEvt * const me,
- enum_t const sig);
- #endif /* def Q_EVT_CTOR */
- /*${QEP::QStateRet} ........................................................*/
- /*! All possible values returned from state/action handlers
- *
- * @note
- * The order matters for algorithmic correctness.
- */
- enum QStateRet {
- /* unhandled and need to "bubble up" */
- Q_RET_SUPER, /*!< event passed to superstate to handle */
- Q_RET_SUPER_SUB, /*!< event passed to submachine superstate */
- Q_RET_UNHANDLED, /*!< event unhandled due to a guard */
- /* handled and do not need to "bubble up" */
- Q_RET_HANDLED, /*!< event handled (internal transition) */
- Q_RET_IGNORED, /*!< event silently ignored (bubbled up to top) */
- /* entry/exit */
- Q_RET_ENTRY, /*!< state entry action executed */
- Q_RET_EXIT, /*!< state exit action executed */
- /* no side effects */
- Q_RET_NULL, /*!< return value without any effect */
- /* transitions need to execute transition-action table in ::QMsm */
- Q_RET_TRAN, /*!< regular transition */
- Q_RET_TRAN_INIT, /*!< initial transition in a state or submachine */
- Q_RET_TRAN_EP, /*!< entry-point transition into a submachine */
- /* transitions that additionally clobber me->state */
- Q_RET_TRAN_HIST, /*!< transition to history of a given state */
- Q_RET_TRAN_XP /*!< exit-point transition out of a submachine */
- };
- /*${QEP::QState} ...........................................................*/
- /*! Type returned from state-handler functions */
- typedef enum QStateRet QState;
- /*${QEP::QStateHandler} ....................................................*/
- /*! Pointer to a state-handler function. */
- typedef QState (* QStateHandler )(void * const me, QEvt const * const e);
- /*${QEP::QActionHandler} ...................................................*/
- /*! Pointer to an action-handler function. */
- typedef QState (* QActionHandler )(void * const me);
- /*${QEP::QXThread} .........................................................*/
- /* forward declaration */
- struct QXThread;
- /*${QEP::QXThreadHandler} ..................................................*/
- /*! Pointer to an eXthended thread handler function */
- typedef void (* QXThreadHandler )(struct QXThread * const me);
- /*${QEP::QMState} ..........................................................*/
- /*! @brief State object for the ::QMsm class (QM State Machine).
- *
- * @details
- * This class groups together the attributes of a ::QMsm state, such as the
- * parent state (state nesting), the associated state handler function and
- * the exit action handler function. These attributes are used inside the
- * QMsm_dispatch() and QMsm_init() functions.
- *
- * @trace
- * @tr{RQP104}
- *
- * @attention
- * The ::QMState class is only intended for the QM code generator and should
- * not be used in hand-crafted code.
- */
- typedef struct QMState {
- struct QMState const *superstate; /*!< superstate of this state */
- QStateHandler const stateHandler; /*!< state handler function */
- QActionHandler const entryAction; /*!< entry action handler function */
- QActionHandler const exitAction; /*!< exit action handler function */
- QActionHandler const initAction; /*!< init action handler function */
- } QMState;
- /*${QEP::QMTranActTable} ...................................................*/
- /*! @brief Transition-Action Table for the ::QMsm State Machine. */
- typedef struct QMTranActTable {
- QMState const *target; /*!< target of the transition */
- QActionHandler const act[1]; /*!< array of actions */
- } QMTranActTable;
- /*${QEP::QHsmAttr} .........................................................*/
- /*! @brief Attribute of for the ::QHsm class (Hierarchical State Machine).
- *
- * @details
- * This union represents possible values stored in the 'state' and 'temp'
- * attributes of the ::QHsm class.
- */
- union QHsmAttr {
- QStateHandler fun; /*!< @private pointer to a state-handler */
- QActionHandler act; /*!< @private pointer to an action-handler */
- QXThreadHandler thr; /*!< @private pointer to an thread-handler */
- QMTranActTable const *tatbl; /*!< @private transition-action table */
- struct QMState const *obj; /*!< @private pointer to QMState object */
- };
- /*${QEP::QReservedSig} .....................................................*/
- /*! Reserved signals by the HSM-style state machine
- * implementation strategy.
- */
- enum QReservedSig {
- Q_EMPTY_SIG, /*!< signal to execute the default case */
- Q_ENTRY_SIG, /*!< signal for coding entry actions */
- Q_EXIT_SIG, /*!< signal for coding exit actions */
- Q_INIT_SIG, /*!< signal for coding initial transitions */
- Q_USER_SIG /*!< offset for the user signals (QP Application) */
- };
- /*${QEP::QHsm} .............................................................*/
- /*! @brief Hierarchical State Machine class
- * @class QHsm
- *
- * @details
- * ::QHsm represents a Hierarchical State Machine (HSM) with full support for
- * hierarchical nesting of states, entry/exit actions, initial transitions,
- * and transitions to history in any composite state. This class is designed
- * for ease of manual coding of HSMs in C, but it is also supported by the
- * QM modeling tool.<br>
- *
- * ::QHsm is also the base class for the QMsm state machine, which provides
- * a superior efficiency, but requires the use of the QM modeling tool to
- * generate code.
- *
- * @note
- * ::QHsm is not intended to be instantiated directly, but rather serves as the
- * abstract base class for derivation of state machines in the QP application.
- *
- * @trace
- * @tr{RQP103}, @tr{AQP211}
- *
- * @usage
- * The following example illustrates how to derive a state machine class
- * from QHsm. Please note that the QHsm member `super` is defined as the
- * FIRST member of the derived class.
- * @include qep_qhsm.c
- */
- typedef struct {
- /* private: */
- /*! Virtual pointer
- * @private @memberof QHsm
- *
- * @trace
- * @tr{RQP102}
- */
- struct QHsmVtable const * vptr;
- /* protected: */
- /*! Current active state (state-variable).
- * @private @memberof QHsm
- */
- union QHsmAttr state;
- /*! Temporary: target/act-table, etc.
- * @private @memberof QHsm
- */
- union QHsmAttr temp;
- } QHsm;
- /* public: */
- /*! Tests if a given state is part of the current active state
- * configuration in ::QHsm subclasses.
- * @public @memberof QHsm
- *
- * @details
- * Tests if a state machine derived from QHsm is-in a given state.
- *
- * @note For a HSM, to "be in a state" means also to be in a superstate of
- * of the state.
- *
- * @param[in] me current instance pointer (see @ref oop)
- * @param[in] state pointer to the state-handler function to be tested
- *
- * @returns
- *'true' if the HSM "is in" the `state` and 'false' otherwise
- *
- * @precondition{qep_hsm,600}
- * - the state configuration must be stable
- *
- * @trace
- * @tr{RQP103}, @tr{RQP120S}
- */
- bool QHsm_isIn(QHsm * const me,
- QStateHandler const state);
- /*! Obtain the current active state from a HSM (read only).
- * @public @memberof QHsm
- *
- * @param[in] me current instance pointer (see @ref oop)
- *
- * @returns the current active state of the QHsm class
- *
- * @note
- * This function is used in QM for auto-generating code for state history.
- */
- static inline QStateHandler QHsm_state(QHsm * const me) {
- return me->state.fun;
- }
- /*! Obtain the current active child state of a given parent in ::QHsm
- * @public @memberof QHsm
- *
- * @details
- * Finds the child state of the given `parent`, such that this child state
- * is an ancestor of the currently active state. The main purpose of this
- * function is to support **shallow history** transitions in state machines
- * derived from QHsm.
- *
- * @param[in] me current instance pointer (see @ref oop)
- * @param[in] parent pointer to the state-handler function
- *
- * @returns
- * the child of a given `parent` state, which is an ancestor of the current
- * active state. For the corner case when the currently active state is the
- * given `parent` state, function returns the `parent` state.
- *
- * @postcondition{qep_hsm,890}
- * - the child must be found
- *
- * @note
- * this function is designed to be called during state transitions, so it
- * does not necessarily start in a stable state configuration.
- * However, the function establishes stable state configuration upon exit.
- *
- * @trace
- * @tr{RQP103}, @tr{RQP120H}
- */
- QStateHandler QHsm_childState(QHsm * const me,
- QStateHandler const parent);
- /* protected: */
- /*! Protected "constructor" of ::QHsm
- * @protected @memberof QHsm
- *
- * @details
- * Performs the first step of HSM initialization by assigning the initial
- * pseudostate to the currently active state of the state machine.
- *
- * @param[in,out] me current instance pointer (see @ref oop)
- * @param[in] initial pointer to the top-most initial state-handler
- * function in the derived state machine
- *
- * @note Must be called only by the constructors of the derived state
- * machines.
- *
- * @note Must be called only ONCE before QHSM_INIT().
- *
- * @usage
- * The following example illustrates how to invoke QHsm_ctor() in the
- * "constructor" of a derived state machine:
- * @include qep_qhsm_ctor.c
- *
- * @trace
- * @tr{RQP103}
- */
- void QHsm_ctor(QHsm * const me,
- QStateHandler const initial);
- /*! The top-state of QHsm.
- * @protected @memberof QHsm
- *
- * @details
- * QHsm_top() is the ultimate root of state hierarchy in all HSMs derived
- * from ::QHsm.
- *
- * @param[in] me current instance pointer (see @ref oop)
- * @param[in] e pointer to the event to be dispatched to the FSM
- *
- * @returns
- * Always returns ::Q_RET_IGNORED, which means that the top state ignores
- * all events.
- *
- * @note The parameters to this state handler are not used. They are provided
- * for conformance with the state-handler function signature ::QStateHandler.
- *
- * @trace
- * @tr{RQP103}, @tr{RQP120T}
- */
- QState QHsm_top(QHsm const * const me,
- QEvt const * const e);
- /*! Implementation of the top-most initial tran. in ::QHsm.
- * @protected @memberof QHsm
- *
- * @details
- * Executes the top-most initial transition in a HSM.
- *
- * @param[in,out] me current instance pointer (see @ref oop)
- * @param[in] e pointer to an extra parameter (might be NULL)
- * @param[in] qs_id QS-id of this state machine (for QS local filter)
- *
- * @precondition{qep_hsm,200}
- * - the virtual pointer must be initialized,
- * - the top-most initial transition must be initialized,
- * - the initial transition must not be taken yet.
- *
- * @note Must be called only ONCE after the QHsm_ctor().
- *
- * @trace
- * @tr{RQP103}, @tr{RQP120I}, @tr{RQP120D}
- */
- void QHsm_init_(QHsm * const me,
- void const * const e,
- uint_fast8_t const qs_id);
- /*! Implementation of dispatching events to a ::QHsm
- * @protected @memberof QHsm
- *
- * @details
- * Dispatches an event for processing to a hierarchical state machine (HSM).
- * The processing of an event represents one run-to-completion (RTC) step.
- *
- * @param[in,out] me current instance pointer (see @ref oop)
- * @param[in] e pointer to the event to be dispatched to the HSM
- * @param[in] qs_id QS-id of this state machine (for QS local filter)
- *
- * @precondition{qep_hsm,400}
- * - the current state must be initialized and
- * - the state configuration must be stable
- *
- * @note
- * This function should be called only via the virtual table (see
- * QHSM_DISPATCH()) and should NOT be called directly in the applications.
- *
- * @trace
- * @tr{RQP103}, @tr{RQP120A}, @tr{RQP120B}, @tr{RQP120C},
- * @tr{RQP120D}, @tr{RQP120E}, @tr{RQP120E}, @tr{RQP120C},
- * @tr{RQP120B}
- */
- void QHsm_dispatch_(QHsm * const me,
- QEvt const * const e,
- uint_fast8_t const qs_id);
- /* private: */
- #ifdef Q_SPY
- /*! Implementation of getting the state handler in a ::QHsm subclass
- * @private @memberof QHsm
- */
- QStateHandler QHsm_getStateHandler_(QHsm * const me);
- #endif /* def Q_SPY */
- /*! Helper function to execute transition sequence in a hierarchical state
- * machine (HSM).
- *
- * @param[in,out] path array of pointers to state-handler functions
- * to execute the entry actions
- * @param[in] qs_id QS-id of this state machine (for QS local filter)
- *
- * @returns
- * the depth of the entry path stored in the `path` parameter.
- *
- * @trace
- * @tr{RQP103}, @tr{RQP120E}, @tr{RQP120F}
- */
- int_fast8_t QHsm_tran_(QHsm * const me,
- QStateHandler * const path,
- uint_fast8_t const qs_id);
- /*! Helper function to execute entry into a given state in a
- * hierarchical state machine (HSM).
- * @private @memberof QHsm
- *
- * @param[in] state state handler function
- * @param[in] qs_id QS-id of this state machine (for QS local filter)
- */
- void QHsm_state_entry_(QHsm * const me,
- QStateHandler const state,
- uint_fast8_t const qs_id);
- /*! Helper function to execute exit from a given state in a
- * hierarchical state machine (HSM).
- * @private @memberof QHsm
- *
- * @param[in] state state handler function
- * @param[in] qs_id QS-id of this state machine (for QS local filter)
- *
- * @returns
- * 'true' if the exit action has been found in the state and
- * 'flase' otherwise.
- */
- bool QHsm_state_exit_(QHsm * const me,
- QStateHandler const state,
- uint_fast8_t const qs_id);
- /*${QEP::QHsmVtable} .......................................................*/
- /*! @brief Virtual table for the ::QHsm class.
- *
- * @trace
- * @tr{RQP102}
- */
- struct QHsmVtable {
- /*! Triggers the top-most initial transition in the HSM. */
- void (*init)(QHsm * const me, void const * const e,
- uint_fast8_t const qs_id);
- /*! Dispatches an event to the HSM. */
- void (*dispatch)(QHsm * const me, QEvt const * const e,
- uint_fast8_t const qs_id);
- #ifdef Q_SPY
- /*! Get the current state handler of the HSM. */
- QStateHandler (*getStateHandler)(QHsm * const me);
- #endif /* Q_SPY */
- };
- /*${QEP::QMsm} .............................................................*/
- /*! @brief QM state machine implementation strategy
- * @class QMsm
- * @extends QHsm
- *
- * @details
- * QMsm (QM State Machine) provides a more efficient state machine
- * implementation strategy than ::QHsm, but requires the use of the QM
- * modeling tool, but are the fastest and need the least run-time
- * support (the smallest event-processor taking up the least code space).
- *
- * @note
- * QMsm is not intended to be instantiated directly, but rather serves
- * as the abstrace base class for derivation of state machines in the
- * application code.
- *
- * @trace
- * @tr{RQP104}
- *
- * @usage
- * The following example illustrates how to derive a state machine class
- * from QMsm. Please note that the QMsm member `super` is defined
- * as the *first* member of the derived struct.
- * @include qep_qmsm.c
- */
- typedef struct {
- /* protected: */
- QHsm super;
- } QMsm;
- /* public: */
- /*! Tests if a given state is part of the current active state
- * configuration in a MSM.
- * @public @memberof QMsm
- *
- * @details
- * Tests if a state machine derived from QMsm is-in a given state.
- *
- * @note
- * For a MSM, to "be-in" a state means also to "be-in" a superstate of
- * of the state.
- *
- * @param[in] me current instance pointer (see @ref oop)
- * @param[in] state pointer to the QMState object that corresponds to the
- * tested state.
- * @returns
- * 'true' if the MSM "is in" the `state` and 'false' otherwise
- */
- bool QMsm_isInState(QMsm const * const me,
- QMState const * const state);
- /*! Obtain the current active state from a MSM (read only)
- * @public @memberof QMsm
- *
- * @param[in] me current instance pointer (see @ref oop)
- *
- * @returns the current active state-object
- *
- * @note
- * This function is used in QM for auto-generating code for state history
- */
- QMState const * QMsm_stateObj(QHsm const * const me);
- /*! Obtain the current active child state of a given parent in ::QMsm
- * @public @memberof QMsm
- *
- * @details
- * Finds the child state of the given @c parent, such that this child state
- * is an ancestor of the currently active state. The main purpose of this
- * function is to support **shallow history** transitions in state machines
- * derived from QMsm.
- *
- * @param[in] me current instance pointer (see @ref oop)
- * @param[in] parent pointer to the state-handler object
- *
- * @returns
- * the child of a given @c parent state, which is an ancestor of
- * the currently active state. For the corner case when the currently active
- * state is the given @c parent state, function returns the @c parent state.
- *
- * @postcondition{qep_msm,890}
- * - the child must be found
- *
- * @sa QMsm_childStateObj()
- */
- QMState const * QMsm_childStateObj(
- QHsm const * const me,
- QMState const * const parent);
- /* protected: */
- /*! Constructor of ::QMsm
- * @protected @memberof QMsm
- *
- * @details
- * Performs the first step of QMsm initialization by assigning the initial
- * pseudostate to the currently active state of the state machine.
- *
- * @param[in,out] me current instance pointer (see @ref oop)
- * @param[in] initial the top-most initial transition for the MSM.
- *
- * @note
- * Must be called only ONCE before QHSM_INIT().
- *
- * @note
- * QMsm inherits QHsm, so by the @ref oop convention it should call the
- * constructor of the superclass, i.e., QHsm_ctor(). However, this would pull
- * in the QHsmVtable, which in turn will pull in the code for QHsm_init_() and
- * QHsm_dispatch_() implemetations. To avoid this code size penalty, in case
- * ::QHsm is not used in a given project, the QMsm_ctor() performs direct
- * intitialization of the Vtable, which avoids pulling in the code for QMsm.
- *
- * @usage
- * The following example illustrates how to invoke QMsm_ctor() in the
- * "constructor" of a derived state machine:
- * @include qep_qmsm_ctor.c
- */
- void QMsm_ctor(QMsm * const me,
- QStateHandler const initial);
- /* public: */
- /*! Implementation of the top-most initial tran. in ::QMsm.
- * @private @memberof QMsm
- *
- * @details
- * Executes the top-most initial transition in a MSM.
- *
- * @param[in,out] me current instance pointer (see @ref oop)
- * @param[in] e pointer to an extra parameter (might be NULL)
- * @param[in] qs_id QS-id of this state machine (for QS local filter)
- *
- * @precondition{qep_msm,200}
- * - the virtual pointer must be initialized,
- * - the top-most initial transition must be initialized,
- * - the initial transition must not be taken yet.
- *
- * @note
- * This function should be called only via the virtual table (see
- * QHSM_INIT()) and should NOT be called directly in the applications.
- */
- void QMsm_init_(
- QHsm * const me,
- void const * const e,
- uint_fast8_t const qs_id);
- /* private: */
- /*! Implementation of dispatching events to a ::QMsm
- * @private @memberof QMsm
- *
- * @details
- * Dispatches an event for processing to a meta state machine (MSM).
- * The processing of an event represents one run-to-completion (RTC) step.
- *
- * @param[in,out] me current instance pointer (see @ref oop)
- * @param[in] e pointer to the event to be dispatched to the MSM
- * @param[in] qs_id QS-id of this state machine (for QS local filter)
- *
- * @precondition{qep_msm,300}
- * - current state must be initialized
- *
- * @note
- * This function should be called only via the virtual table (see
- * QHSM_DISPATCH()) and should NOT be called directly in the applications.
- */
- void QMsm_dispatch_(
- QHsm * const me,
- QEvt const * const e,
- uint_fast8_t const qs_id);
- /* public: */
- #ifdef Q_SPY
- /*! Implementation of getting the state handler in a ::QMsm subclass
- * @public @memberof QMsm
- */
- QStateHandler QMsm_getStateHandler_(QHsm * const me);
- #endif /* def Q_SPY */
- /* private: */
- /*! Execute transition-action table
- * @private @memberof QMsm
- *
- * @details
- * Helper function to execute transition sequence in a transition-action table.
- *
- * @param[in,out] me current instance pointer (see @ref oop)
- * @param[in] tatbl pointer to the transition-action table
- * @param[in] qs_id QS-id of this state machine (for QS local filter)
- *
- * @returns
- * status of the last action from the transition-action table.
- *
- * @note
- * This function is for internal use inside the QEP event processor and
- * should **not** be called directly from the applications.
- */
- QState QMsm_execTatbl_(
- QHsm * const me,
- QMTranActTable const * const tatbl,
- uint_fast8_t const qs_id);
- /*! Exit the current state up to the explicit transition source
- * @private @memberof QMsm
- *
- * @details
- * Static helper function to exit the current state configuration to the
- * transition source, which in a hierarchical state machine might be a
- * superstate of the current state.
- *
- * @param[in,out] me current instance pointer (see @ref oop)
- * @param[in] cs pointer to the current state
- * @param[in] ts pointer to the transition source state
- * @param[in] qs_id QS-id of this state machine (for QS local filter)
- */
- void QMsm_exitToTranSource_(
- QHsm * const me,
- QMState const * const cs,
- QMState const * const ts,
- uint_fast8_t const qs_id);
- /*! Enter history of a composite state
- * @private @memberof QMsm
- *
- * @details
- * Static helper function to execute the segment of transition to history
- * after entering the composite state and
- *
- * @param[in,out] me current instance pointer (see @ref oop)
- * @param[in] hist pointer to the history substate
- * @param[in] qs_id QS-id of this state machine (for QS local filter)
- *
- * @returns
- * #Q_RET_TRAN_INIT, if an initial transition has been executed in the last
- * entered state or #Q_RET_NULL if no such transition was taken.
- */
- QState QMsm_enterHistory_(
- QHsm * const me,
- QMState const *const hist,
- uint_fast8_t const qs_id);
- /*$enddecl${QEP} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
- /*==========================================================================*/
- /*$declare${QEP-macros} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
- /*${QEP-macros::QHSM_INIT} .................................................*/
- #ifdef Q_SPY
- /*! Virtual call to the top-most initial transition in a HSM.
- *
- * @param[in,out] me_ current instance pointer (see @ref oop)
- * @param[in] par_ pointer the optional initialization parameter
- * @param[in] qs_id_ QS local filter ID (used only when Q_SPY is defined)
- *
- * @note Must be called only ONCE after the SM "constructor".
- *
- * @trace
- * @tr{RQP102}
- *
- * @usage
- * The following example illustrates how to initialize a SM, and dispatch
- * events to it:
- * @include qep_qhsm_use.c
- */
- #define QHSM_INIT(me_, par_, qs_id_) do { \
- Q_ASSERT((me_)->vptr); \
- (*(me_)->vptr->init)((me_), (par_), (qs_id_)); \
- } while (false)
- #endif /* def Q_SPY */
- /*${QEP-macros::QHSM_INIT} .................................................*/
- #ifndef Q_SPY
- #define QHSM_INIT(me_, par_, dummy) do { \
- Q_ASSERT((me_)->vptr); \
- (*(me_)->vptr->init)((me_), (par_), 0U); \
- } while (false)
- #endif /* ndef Q_SPY */
- /*${QEP-macros::QHSM_DISPATCH} .............................................*/
- #ifdef Q_SPY
- /*! Virtual call to dispatch an event to a HSM
- *
- * @details
- * Processes one event at a time in Run-to-Completion fashion.
- *
- * @param[in,out] me_ current instance pointer (see @ref oop)
- * @param[in] e_ constant pointer the ::QEvt or a class
- * derived from ::QEvt (see @ref oop)
- * @param[in] qs_id_ QS local filter ID (used only when Q_SPY is defined)
- *
- * @note Must be called after the "constructor" and after QHSM_INIT().
- *
- * @trace
- * @tr{RQP102}
- */
- #define QHSM_DISPATCH(me_, e_, qs_id_) \
- ((*(me_)->vptr->dispatch)((me_), (e_), (qs_id_)))
- #endif /* def Q_SPY */
- /*${QEP-macros::QHSM_DISPATCH} .............................................*/
- #ifndef Q_SPY
- #define QHSM_DISPATCH(me_, e_, dummy) \
- ((*(me_)->vptr->dispatch)((me_), (e_), 0U))
- #endif /* ndef Q_SPY */
- /*${QEP-macros::Q_HSM_UPCAST} ..............................................*/
- /*! Perform upcast from a subclass of ::QHsm to the base class ::QHsm
- *
- * @details
- * Upcasting from a subclass to superclass is a very frequent and **safe**
- * operation in object-oriented programming and object-oriented languages
- * (such as C++) perform such upcasting automatically. However, OOP is
- * implemented in C just as a set of coding conventions (see @ref oop),
- * and the C compiler does not "know" that certain types are related by
- * inheritance. Therefore for C, the upcast must be performed explicitly.
- * Unfortunately, pointer casting violates the advisory MISRA-C 2012
- * Rule 11.3(req) "A cast shall not be performed between a pointer to object
- * type and a pointer to a different object type". This macro encapsulates
- * this deviation and provides a descriptive name for the reason of this cast.
- */
- #define Q_HSM_UPCAST(ptr_) ((QHsm *)(ptr_))
- /*${QEP-macros::Q_TRAN} ....................................................*/
- /*! Perform upcast from a subclass of ::QHsm to the base class ::QHsm
- *
- * @details
- * Upcasting from a subclass to superclass is a very frequent and **safe**
- * operation in object-oriented programming and object-oriented languages
- * (such as C++) perform such upcasting automatically. However, OOP is
- * implemented in C just as a set of coding conventions (see @ref oop),
- * and the C compiler does not "know" that certain types are related by
- * inheritance. Therefore for C, the upcast must be performed explicitly.
- * Unfortunately, pointer casting violates the advisory MISRA-C 2012
- * Rule 11.3(req) "A cast shall not be performed between a pointer to object
- * type and a pointer to a different object type". This macro encapsulates
- * this deviation and provides a descriptive name for the reason of this cast.
- */
- #define Q_TRAN(target_) \
- ((Q_HSM_UPCAST(me))->temp.fun = Q_STATE_CAST(target_), Q_RET_TRAN)
- /*${QEP-macros::Q_TRAN_HIST} ...............................................*/
- /*! Macro to call in a state-handler when it executes a transition
- * to history. Applicable only to HSMs.
- *
- * @trace
- * @tr{RQP103}, @tr{RQP120H}
- *
- * @usage
- * @include qep_qhist.c
- */
- #define Q_TRAN_HIST(hist_) \
- ((Q_HSM_UPCAST(me))->temp.fun = (hist_), Q_RET_TRAN_HIST)
- /*${QEP-macros::Q_SUPER} ...................................................*/
- /*! Macro to call in a state-handler when it designates the superstate
- * of a given state. Applicable only to ::QHsm subclasses.
- *
- * @trace
- * @tr{RQP103}
- *
- * @usage
- * @include qep_qsuper.c
- */
- #define Q_SUPER(super_) \
- ((Q_HSM_UPCAST(me))->temp.fun = Q_STATE_CAST(super_), Q_RET_SUPER)
- /*${QEP-macros::Q_HANDLED} .................................................*/
- /*! Macro to call in a state-handler when it handles an event.
- *
- * @trace
- * @tr{RQP103}, @tr{RQP120B}, @tr{RQP120C}
- */
- #define Q_HANDLED() (Q_RET_HANDLED)
- /*${QEP-macros::Q_UNHANDLED} ...............................................*/
- /*! Macro to call in a state-handler when it attempts to handle
- * an event but a guard condition evaluates to 'false' and there is no other
- * explicit way of handling the event. Applicable only to ::QHsm subclasses.
- */
- #define Q_UNHANDLED() (Q_RET_UNHANDLED)
- /*${QEP-macros::Q_ACTION_NULL} .............................................*/
- /*! Macro to provide strictly-typed zero-action to terminate action lists
- *! in the transition-action-tables
- */
- #define Q_ACTION_NULL ((QActionHandler)0)
- /*${QEP-macros::Q_EVT_CAST} ................................................*/
- /*! Perform downcast of an event onto a subclass of ::QEvt `class_`
- *
- * @details
- * This macro encapsulates the downcast of ::QEvt pointers, which violates
- * MISRA-C 2012 Rule 11.3(R) "A cast shall not be performed between a
- * pointer to object type and a pointer to a different object type". This
- * macro helps to localize this deviation.
- *
- * @param class_ a subclass of ::QEvt
- *
- * @trace
- * @tr{RQP003}, @tr{PQA11_3}
- */
- #define Q_EVT_CAST(class_) ((class_ const *)(e))
- /*${QEP-macros::Q_STATE_CAST} ..............................................*/
- /*! Perform cast to ::QStateHandler.
- * @details
- * This macro encapsulates the cast of a specific state handler function
- * pointer to ::QStateHandler, which violates MISRA:C-2012 Rule 11.1(req)
- * "Conversions shall not be performed between a pointer to function and
- * any other type". This macro helps to localize this deviation.
- *
- * @trace
- * @tr{PQP11_1}, @tr{PQA11_1}
- *
- * @usage
- * @include qep_qhsm_ctor.c
- */
- #define Q_STATE_CAST(handler_) ((QStateHandler)(handler_))
- /*${QEP-macros::Q_ACTION_CAST} .............................................*/
- /*! Perform cast to ::QActionHandler.
- * @details
- * This macro encapsulates the cast of a specific action handler function
- * pointer to ::QActionHandler, which violates MISRA:C-2012 Rule 11.1(R)
- * "Conversions shall not be performed between a pointer to function and
- * any other type". This macro helps to localize this deviation.
- *
- * @trace
- * @tr{PQP11_1}, @tr{PQA11_1}
- */
- #define Q_ACTION_CAST(action_) ((QActionHandler)(action_))
- /*${QEP-macros::Q_UNUSED_PAR} ..............................................*/
- /*! Helper macro to clearly mark unused parameters of functions. */
- #define Q_UNUSED_PAR(par_) ((void)(par_))
- /*${QEP-macros::Q_DIM} .....................................................*/
- /*! Helper macro to calculate static dimension of a 1-dim `array_`
- *
- * @param array_ 1-dimensional array
- * @returns the length of the array (number of elements it can hold)
- */
- #define Q_DIM(array_) (sizeof(array_) / sizeof((array_)[0U]))
- /*${QEP-macros::Q_UINT2PTR_CAST} ...........................................*/
- /*! Perform cast from unsigned integer `uint_` to pointer of type `type_`
- *
- * @details
- * This macro encapsulates the cast to (type_ *), which QP ports or
- * application might use to access embedded hardware registers.
- * Such uses can trigger PC-Lint "Note 923: cast from int to pointer"
- * and this macro helps to encapsulate this deviation.
- */
- #define Q_UINT2PTR_CAST(type_, uint_) ((type_ *)(uint_))
- /*${QEP-macros::QEVT_INITIALIZER} ..........................................*/
- /*! Initializer of static constant QEvt instances
- *
- * @details
- * This macro encapsulates the ugly casting of enumerated signals
- * to QSignal and constants for QEvt.poolID and QEvt.refCtr_.
- */
- #define QEVT_INITIALIZER(sig_) { (QSignal)(sig_), 0U, 0U }
- /*${QEP-macros::QM_ENTRY} ..................................................*/
- #ifdef Q_SPY
- /*! Macro to call in a QM action-handler when it executes
- * an entry action. Applicable only to ::QMsm subclasses.
- */
- #define QM_ENTRY(state_) \
- ((Q_HSM_UPCAST(me))->temp.obj = (state_), Q_RET_ENTRY)
- #endif /* def Q_SPY */
- /*${QEP-macros::QM_ENTRY} ..................................................*/
- #ifndef Q_SPY
- #define QM_ENTRY(dummy) (Q_RET_ENTRY)
- #endif /* ndef Q_SPY */
- /*${QEP-macros::QM_EXIT} ...................................................*/
- #ifdef Q_SPY
- /*! Macro to call in a QM action-handler when it executes
- * an exit action. Applicable only to ::QMsm subclasses.
- */
- #define QM_EXIT(state_) \
- ((Q_HSM_UPCAST(me))->temp.obj = (state_), Q_RET_EXIT)
- #endif /* def Q_SPY */
- /*${QEP-macros::QM_EXIT} ...................................................*/
- #ifndef Q_SPY
- #define QM_EXIT(dummy) (Q_RET_EXIT)
- #endif /* ndef Q_SPY */
- /*${QEP-macros::QM_SM_EXIT} ................................................*/
- /*! Macro to call in a QM submachine exit-handler.
- * Applicable only to subclasses of ::QMsm.
- */
- #define QM_SM_EXIT(state_) \
- ((Q_HSM_UPCAST(me))->temp.obj = (state_), Q_RET_EXIT)
- /*${QEP-macros::QM_TRAN} ...................................................*/
- /*! Macro to call in a QM state-handler when it executes a regular
- * transition. Applicable only to ::QMsm subclasses.
- */
- #define QM_TRAN(tatbl_) ((Q_HSM_UPCAST(me))->temp.tatbl \
- = (struct QMTranActTable const *)(tatbl_), Q_RET_TRAN)
- /*${QEP-macros::QM_TRAN_INIT} ..............................................*/
- /*! Macro to call in a QM state-handler when it executes an initial
- * transition. Applicable only to ::QMsm subclasses.
- */
- #define QM_TRAN_INIT(tatbl_) ((Q_HSM_UPCAST(me))->temp.tatbl \
- = (struct QMTranActTable const *)(tatbl_), Q_RET_TRAN_INIT)
- /*${QEP-macros::QM_TRAN_HIST} ..............................................*/
- /*! Macro to call in a QM state-handler when it executes a transition
- * to history. Applicable only to ::QMsm subclasses.
- */
- #define QM_TRAN_HIST(history_, tatbl_) \
- ((((Q_HSM_UPCAST(me))->state.obj = (history_)), \
- ((Q_HSM_UPCAST(me))->temp.tatbl = \
- (struct QMTranActTable const *)(tatbl_))), \
- Q_RET_TRAN_HIST)
- /*${QEP-macros::QM_TRAN_EP} ................................................*/
- /*! Macro to call in a QM state-handler when it executes a transition
- * to the submachine via an entry point.
- */
- #define QM_TRAN_EP(tatbl_) ((Q_HSM_UPCAST(me))->temp.tatbl \
- = (struct QMTranActTable const *)(tatbl_), Q_RET_TRAN_EP)
- /*${QEP-macros::QM_TRAN_XP} ................................................*/
- /*! Macro to call in a QM state-handler when it executes a transition
- * to exit point. Applicable only to ::QMsm subclasses.
- */
- #define QM_TRAN_XP(xp_, tatbl_) \
- ((((Q_HSM_UPCAST(me))->state.act = (xp_)), \
- ((Q_HSM_UPCAST(me))->temp.tatbl = \
- (struct QMTranActTable const *)(tatbl_))), \
- Q_RET_TRAN_XP)
- /*${QEP-macros::QM_HANDLED} ................................................*/
- /*! Macro to call in a QM state-handler when it handled an event.
- * Applicable only to ::QMsm subclasses.
- */
- #define QM_HANDLED() (Q_RET_HANDLED)
- /*${QEP-macros::QM_UNHANDLED} ..............................................*/
- /*! Macro to call in a QM state-handler when when it attempts to
- * handle an event but a guard condition evaluates to 'false' and there is
- * no other explicit way of handling the event. Applicable only to
- * ::QMsm subclasses.
- */
- #define QM_UNHANDLED() (Q_RET_UNHANDLED)
- /*${QEP-macros::QM_SUPER} ..................................................*/
- /*! Macro to call in a QM state-handler when it designates the
- * superstate to handle an event. Applicable only to QMSMs.
- */
- #define QM_SUPER() (Q_RET_SUPER)
- /*${QEP-macros::QM_SUPER_SUB} ..............................................*/
- /*! Macro to call in a QM submachine-handler when it designates the
- * host state to handle an event. Applicable only to subclasses of ::QMsm.
- */
- #define QM_SUPER_SUB(host_) \
- ((Q_HSM_UPCAST(me))->temp.obj = (host_), Q_RET_SUPER_SUB)
- /*${QEP-macros::QM_STATE_NULL} .............................................*/
- /*! Macro to provide strictly-typed zero-state to use for submachines.
- *! Applicable to subclasses of ::QMsm.
- */
- #define QM_STATE_NULL ((QMState *)0)
- /*$enddecl${QEP-macros} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
- #endif /* QEP_H_ */
|