/*$file${include::qep.h} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ /* * Model: qpc.qm * File: ${include::qep.h} * * This code has been generated by QM 5.2.4 . * 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 . * * 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: * * The terms of the closed source Quantum Leaps commercial licenses * can be found at: * * Redistributions in source code must retain this top-level comment block. * Plagiarizing this software to sidestep the license obligations is illegal. * * Contact information: * * */ /*$endhead${include::qep.h} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ /*! @file * @brief QEP/C platform-independent public interface. * * @tr{RQP001} @tr{RQP101} */ #ifndef QP_INC_QEP_H_ #define QP_INC_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 720U /*! 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.0" /*! Encrypted current QP release (7.2.0) and date (2023-01-06) */ #define QP_RELEASE 0x76D8998FU /*==========================================================================*/ /*$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. * * @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 * * @tr{RQP002} */ QSignal sig; /* private: */ /*! Pool ID (==0 for immutable event) * @private @memberof QEvt * * @tr{RQP003} */ uint8_t poolId_; /*! Reference counter (for mutable events) * @private @memberof QEvt * * @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 * @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. * * @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::QHSM_MAX_NEST_DEPTH_} .............................................*/ /*! maximum depth of state nesting in a HSM (including the top level), * must be >= 3 */ enum { QHSM_MAX_NEST_DEPTH_ = 6}; /*${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.
* * 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. * * @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 * * @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 * * @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. * * @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. * * @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 * * @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. * * @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) * * @note Must be called only ONCE after the QHsm_ctor(). * * @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) * * @note * This function should be called only via the virtual table (see * QHSM_DISPATCH()) and should NOT be called directly in the applications. * * @tr{RQP103} * @tr{RQP120A} @tr{RQP120B} @tr{RQP120C} @tr{RQP120D} @tr{RQP120E} */ 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). * @private @memberof QHsm * * @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. * * @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. * * @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. * * @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. * * @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) * * @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) * * @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". * * @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(). * * @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. * * @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. * * @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. * @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 * * @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. * * @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. * * @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 /* QP_INC_QEP_H_ */