| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124 |
- /*$file${include::qf.h} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
- /*
- * Model: qpc.qm
- * File: ${include::qf.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::qf.h} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
- /*! @file
- * @brief QF/C platform-independent public interface.
- */
- #ifndef QF_H_
- #define QF_H_
- /*==========================================================================*/
- /*$declare${QF-config} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
- /*${QF-config::QF_MAX_ACTIVE} ..............................................*/
- #ifndef QF_MAX_ACTIVE
- /*! Maximum number of active objects (configurable value in qf_port.h)
- * Valid values: [1U..64U]; default 32U
- */
- #define QF_MAX_ACTIVE 32U
- #endif /* ndef QF_MAX_ACTIVE */
- /*${QF-config::QF_MAX_ACTIVE exceeds the maximu~} ..........................*/
- #if (QF_MAX_ACTIVE > 64U)
- #error QF_MAX_ACTIVE exceeds the maximum of 64U;
- #endif /* (QF_MAX_ACTIVE > 64U) */
- /*${QF-config::QF_MAX_TICK_RATE} ...........................................*/
- #ifndef QF_MAX_TICK_RATE
- /*! Maximum number of clock rates (configurable value in qf_port.h)
- * Valid values: [0U..15U]; default 1U
- */
- #define QF_MAX_TICK_RATE 1U
- #endif /* ndef QF_MAX_TICK_RATE */
- /*${QF-config::QF_MAX_TICK_RATE exceeds the max~} ..........................*/
- #if (QF_MAX_TICK_RATE > 15U)
- #error QF_MAX_TICK_RATE exceeds the maximum of 15U;
- #endif /* (QF_MAX_TICK_RATE > 15U) */
- /*${QF-config::QF_MAX_EPOOL} ...............................................*/
- #ifndef QF_MAX_EPOOL
- /*! Maximum number of event pools (configurable value in qf_port.h)
- * Valid values: [0U..15U]; default 3U
- *
- * @note
- * #QF_MAX_EPOOL set to zero means that dynamic events are NOT configured
- * and should not be used in the application.
- */
- #define QF_MAX_EPOOL 3U
- #endif /* ndef QF_MAX_EPOOL */
- /*${QF-config::QF_MAX_EPOOL exceeds the maximum~} ..........................*/
- #if (QF_MAX_EPOOL > 15U)
- #error QF_MAX_EPOOL exceeds the maximum of 15U;
- #endif /* (QF_MAX_EPOOL > 15U) */
- /*${QF-config::QF_TIMEEVT_CTR_SIZE} ........................................*/
- #ifndef QF_TIMEEVT_CTR_SIZE
- /*! Size of the QTimeEvt counter (configurable value in qf_port.h)
- * Valid values: 1U, 2U, or 4U; default 4U
- */
- #define QF_TIMEEVT_CTR_SIZE 4U
- #endif /* ndef QF_TIMEEVT_CTR_SIZE */
- /*${QF-config::QF_TIMEEVT_CTR_SIZE defined inco~} ..........................*/
- #if (QF_TIMEEVT_CTR_SIZE != 1U) && (QF_TIMEEVT_CTR_SIZE != 2U) && (QF_TIMEEVT_CTR_SIZE != 4U)
- #error QF_TIMEEVT_CTR_SIZE defined incorrectly, expected 1U, 2U, or 4U;
- #endif /* (QF_TIMEEVT_CTR_SIZE != 1U) && (QF_TIMEEVT_CTR_SIZE != 2U) && (QF_TIMEEVT_CTR_SIZE != 4U) */
- /*${QF-config::QF_EVENT_SIZ_SIZE} ..........................................*/
- #ifndef QF_EVENT_SIZ_SIZE
- /*! Size of the event-size (configurable value in qf_port.h)
- * Valid values: 1U, 2U, or 4U; default 2U
- */
- #define QF_EVENT_SIZ_SIZE 2U
- #endif /* ndef QF_EVENT_SIZ_SIZE */
- /*${QF-config::QF_EVENT_SIZ_SIZE defined incorr~} ..........................*/
- #if (QF_EVENT_SIZ_SIZE != 1U) && (QF_EVENT_SIZ_SIZE != 2U) && (QF_EVENT_SIZ_SIZE != 4U)
- #error QF_EVENT_SIZ_SIZE defined incorrectly, expected 1U, 2U, or 4U;
- #endif /* (QF_EVENT_SIZ_SIZE != 1U) && (QF_EVENT_SIZ_SIZE != 2U) && (QF_EVENT_SIZ_SIZE != 4U) */
- /*$enddecl${QF-config} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
- /*==========================================================================*/
- /*$declare${QF-types} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
- /*${QF-types::QPSetBits} ...................................................*/
- #if (8U < QF_MAX_ACTIVE) && (QF_MAX_ACTIVE <= 16U)
- /*! bitmask for the internal representation of QPSet elements */
- typedef uint16_t QPSetBits;
- #endif /* (8U < QF_MAX_ACTIVE) && (QF_MAX_ACTIVE <= 16U) */
- /*${QF-types::QPSetBits} ...................................................*/
- #if (16 < QF_MAX_ACTIVE)
- typedef uint32_t QPSetBits;
- #endif /* (16 < QF_MAX_ACTIVE) */
- /*${QF-types::QPSetBits} ...................................................*/
- #if (QF_MAX_ACTIVE <= 8U)
- typedef uint8_t QPSetBits;
- #endif /* (QF_MAX_ACTIVE <= 8U) */
- /*${QF-types::QTimeEvtCtr} .................................................*/
- #if (QF_TIMEEVT_CTR_SIZE == 2U)
- /*! Data type to store the block-size defined based on the macro
- * #QF_TIMEEVT_CTR_SIZE.
- *
- * @details
- * The dynamic range of this data type determines the maximum block
- * size that can be managed by the pool.
- */
- typedef uint16_t QTimeEvtCtr;
- #endif /* (QF_TIMEEVT_CTR_SIZE == 2U) */
- /*${QF-types::QTimeEvtCtr} .................................................*/
- #if (QF_TIMEEVT_CTR_SIZE == 4U)
- typedef uint32_t QTimeEvtCtr;
- #endif /* (QF_TIMEEVT_CTR_SIZE == 4U) */
- /*${QF-types::QTimeEvtCtr} .................................................*/
- #if (QF_TIMEEVT_CTR_SIZE == 1U)
- typedef uint8_t QTimeEvtCtr;
- #endif /* (QF_TIMEEVT_CTR_SIZE == 1U) */
- /*${QF-types::QF_LOG2} .....................................................*/
- #ifndef QF_LOG2
- /*! Log-base-2 calculation when hardware acceleration
- * is NOT provided (#QF_LOG2 not defined).
- * @static @private @memberof QF
- */
- uint_fast8_t QF_LOG2(QPSetBits x);
- #endif /* ndef QF_LOG2 */
- /*${QF-types::QPrioSpec} ...................................................*/
- /*! Priority specification for Active Objects in QP
- *
- * @details
- * Active Object priorities in QP are integer numbers in the range
- * [1..#QF_MAX_ACTIVE], whereas the special priority number 0 is reserved
- * for the lowest-priority idle thread. The QP framework uses the *direct*
- * priority numbering, in which higher numerical values denote higher urgency.
- * For example, an AO with priority 32 has higher urgency than an AO with
- * priority 23.
- *
- * ::QPrioSpec allows an application developer to assign **two**
- * priorities to a given AO (see also Q_PRIO()):
- *
- * 1. The "QF-priority", which resides in the least-significant byte
- * of the ::QPrioSpec data type. The "QF-priority" must be **unique**
- * for each thread in the system and higher numerical values represent
- * higher urgency (direct pirority numbering).
- *
- * 2. The "preemption-threshold" priority, which resides in the most-
- * significant byte of the ::QPrioSpec data type. The second priority
- * cannot be lower than the "QF-priority", but does NOT need to be
- * unuque.
- *
- * In the QP native preemptive kernels, like QK and QXK, the "preemption-
- * threshold" priority is used as to implement the "preemption-threshold
- * scheduling" (PTS). It determines the conditions under which a given
- * thread can be *preempted* by other threads. Specifically, a given
- * thread can be preempted only by another thread with a *higher*
- * priority than the "preemption-threshold" of the original thread.
- *
- * 
- *
- * @note
- * For backwards-compatibility, ::QPrioSpec data type might contain only
- * the "QF-priority" component (and the "preemption-threshold" component
- * left at zero). In that case, the "preemption-threshold" will be assumed
- * to be the same as the "QF-priority". This corresponds exactly to the
- * previous semantics of AO priority.
- *
- * @remark
- * When QP runs on top of 3rd-party kernels/RTOSes or general-purpose
- * operating systems, sthe second priority can have different meaning,
- * depending on the specific RTOS/GPOS used.
- */
- typedef uint16_t QPrioSpec;
- /*${QF-types::QSchedStatus} ................................................*/
- /*! The scheduler lock status used in some real-time kernels */
- typedef uint_fast16_t QSchedStatus;
- /*${QF-types::QPSet} .......................................................*/
- /*! @brief Priority Set of up to #QF_MAX_ACTIVE elements
- * @class QPSet
- *
- * @details
- * The priority set represents the set of active objects that are ready to
- * run and need to be considered by the scheduling algorithm. The set is
- * capable of storing up to #QF_MAX_ACTIVE priority levels, which can be
- * configured in the rage 1..64, inclusive.
- */
- typedef struct {
- /* public: */
- #if (QF_MAX_ACTIVE <= 32)
- /*! bitmask with a bit for each element */
- QPSetBits volatile bits;
- #endif /* (QF_MAX_ACTIVE <= 32) */
- #if (32 < QF_MAX_ACTIVE)
- /*! bitmasks with a bit for each element */
- QPSetBits volatile bits[2];
- #endif /* (32 < QF_MAX_ACTIVE) */
- } QPSet;
- /* public: */
- /*! Make the priority set empty */
- static inline void QPSet_setEmpty(QPSet * const me) {
- #if (QF_MAX_ACTIVE <= 32)
- me->bits = 0U;
- #else
- me->bits[0] = 0U;
- me->bits[1] = 0U;
- #endif
- }
- /*! Return 'true' if the priority set is empty */
- static inline bool QPSet_isEmpty(QPSet const * const me) {
- #if (QF_MAX_ACTIVE <= 32)
- return (me->bits == 0U);
- #else
- return (me->bits[0] == 0U) ? (me->bits[1] == 0U) : false;
- #endif
- }
- /*! Return 'true' if the priority set is NOT empty */
- static inline bool QPSet_notEmpty(QPSet const * const me) {
- #if (QF_MAX_ACTIVE <= 32)
- return (me->bits != 0U);
- #else
- return (me->bits[0] != 0U) ? true : (me->bits[1] != 0U);
- #endif
- }
- /*! Return 'true' if the priority set has the element n. */
- static inline bool QPSet_hasElement(QPSet const * const me,
- uint_fast8_t const n)
- {
- #if (QF_MAX_ACTIVE <= 32U)
- return (me->bits & (1U << (n - 1U))) != 0U;
- #else
- return (n <= 32U)
- ? ((me->bits[0] & ((uint32_t)1U << (n - 1U))) != 0U)
- : ((me->bits[1] & ((uint32_t)1U << (n - 33U))) != 0U);
- #endif
- }
- /*! insert element `n` into the set (n = 1..::QF_MAX_ACTIVE) */
- static inline void QPSet_insert(QPSet * const me,
- uint_fast8_t const n)
- {
- #if (QF_MAX_ACTIVE <= 32U)
- me->bits = (me->bits | (1U << (n - 1U)));
- #else
- if (n <= 32U) {
- me->bits[0] = (me->bits[0] | ((uint32_t)1U << (n - 1U)));
- }
- else {
- me->bits[1] = (me->bits[1] | ((uint32_t)1U << (n - 33U)));
- }
- #endif
- }
- /*! Remove element `n` from the set (n = 1U..::QF_MAX_ACTIVE) */
- static inline void QPSet_remove(QPSet * const me,
- uint_fast8_t const n)
- {
- #if (QF_MAX_ACTIVE <= 32U)
- me->bits = (me->bits &
- (QPSetBits)(~((QPSetBits)1U << (n - 1U))));
- #else
- if (n <= 32U) {
- (me->bits[0] = (me->bits[0] & ~((uint32_t)1U << (n - 1U))));
- }
- else {
- (me->bits[1] = (me->bits[1] & ~((uint32_t)1U << (n - 33U))));
- }
- #endif
- }
- /*! Find the maximum element in the set, returns zero if the set is empty */
- static inline uint_fast8_t QPSet_findMax(QPSet const * const me) {
- #if (QF_MAX_ACTIVE <= 32)
- return QF_LOG2(me->bits);
- #else
- return (me->bits[1] != 0U)
- ? (QF_LOG2(me->bits[1]) + 32U)
- : (QF_LOG2(me->bits[0]));
- #endif
- }
- /*${QF-types::QSubscrList} .................................................*/
- /*! Subscriber List (for publish-subscribe)
- *
- * @details
- * This data type represents a set of Active Objects that subscribe to
- * a given signal. The set is represented as priority-set, where each
- * bit corresponds to the unique QF-priority of an AO (see ::QPrioSpec).
- */
- typedef QPSet QSubscrList;
- /*$enddecl${QF-types} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
- /*$declare${QF::QActive} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
- /*${QF::QActive} ...........................................................*/
- /*! @brief Active object class (based on the QHsm implementation strategy)
- * @class QActive
- * @extends QHsm
- *
- * @details
- * Active objects are encapsulated tasks (each containing an event queue and
- * a state machine) that communicate with one another asynchronously by
- * sending and receiving events. Within an active object, events are
- * processed in a run-to-completion (RTC) fashion, while QF encapsulates
- * all the details of thread-safe event exchange and queuing.<br>
- *
- * QActive represents an active object that uses the QHsm-style
- * implementation strategy for state machines. This strategy is tailored
- * to manual coding, but it is also supported by the QM modeling tool.
- * The resulting code is slower than in the ::QMsm-style implementation
- * strategy.
- *
- * @note
- * QActive is not intended to be instantiated directly, but rather serves
- * as the abstract base class for derivation of active objects in the
- * applications.
- *
- * @sa QMActive
- *
- * @usage
- * The following example illustrates how to derive an active object from
- * QActive.
- * @include qf_qactive.c
- */
- typedef struct QActive {
- /* protected: */
- QHsm super;
- /* private: */
- #ifdef QF_EQUEUE_TYPE
- /*! OS-dependent event-queue type
- * @private @memberof QActive
- *
- * @details
- * The type of the queue depends on the underlying operating system or
- * a kernel. Many kernels support "message queues" that can be adapted
- * to deliver QF events to the active object. Alternatively, QF provides
- * a native event queue implementation that can be used as well.
- *
- * @note
- * The native QF event queue is configured by defining the macro
- * #QF_EQUEUE_TYPE as ::QEQueue.
- */
- QF_EQUEUE_TYPE eQueue;
- #endif /* def QF_EQUEUE_TYPE */
- #ifdef QF_OS_OBJECT_TYPE
- /*! OS-dependent per-thread object
- * @private @memberof QActive
- *
- * @details
- * This data might be used in various ways, depending on the QF port.
- * In some ports me->osObject is used to block the calling thread when
- * the native QF queue is empty. In other QF ports the OS-dependent
- * object might be used differently.
- */
- QF_OS_OBJECT_TYPE osObject;
- #endif /* def QF_OS_OBJECT_TYPE */
- #ifdef QF_THREAD_TYPE
- /*! OS-dependent representation of the thread of the active object
- * @private @memberof QActive
- *
- * @details
- * This data might be used in various ways, depending on the QF port.
- * In some ports me->thread is used store the thread handle. In other ports
- * me->thread can be a pointer to the Thread-Local-Storage (TLS).
- */
- QF_THREAD_TYPE thread;
- #endif /* def QF_THREAD_TYPE */
- /* public: */
- /*! QF-priority [1..#QF_MAX_ACTIVE] of this AO.
- * @private @memberof QActive
- * @sa ::QPrioSpec
- */
- uint8_t prio;
- /*! preemption-threshold [1..#QF_MAX_ACTIVE] of this AO.
- * @private @memberof QActive
- * @sa ::QPrioSpec
- */
- uint8_t pthre;
- /* private: */
- } QActive;
- /* protected: */
- /*! ::QActive constructor (abstract base class)
- * @protected @memberof QActive
- *
- * @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 active object
- * @sa QHsm_ctor()
- */
- void QActive_ctor(QActive * const me,
- QStateHandler const initial);
- /* private: */
- /*! Starts execution of an active object and registers the object
- * with the framework
- * @private @memberof QActive
- *
- * @details
- * Starts execution of the AO and registers the AO with the framework.
- *
- * @param[in,out] me current instance pointer (see @ref oop)
- * @param[in] prioSpec priority specification for the AO (See ::QPrioSpec)
- * @param[in] qSto pointer to the storage for the ring buffer of the
- * event queue
- * @param[in] qLen length of the event queue [# ::QEvt* pointers]
- * @param[in] stkSto pointer to the stack storage (might be NULL)
- * @param[in] stkSize stack size [bytes]
- * @param[in] par pointer to an extra parameter (might be NULL)
- *
- * @usage
- * The following example shows starting an AO when a per-task stack
- * is needed:
- * @include qf_start.c
- */
- void QActive_start_(QActive * const me,
- QPrioSpec const prioSpec,
- QEvt const * * const qSto,
- uint_fast16_t const qLen,
- void * const stkSto,
- uint_fast16_t const stkSize,
- void const * const par);
- /* protected: */
- #ifdef QF_ACTIVE_STOP
- /*! Stops execution of an active object and removes it from the
- * framework's supervision
- * @protected @memberof QActive
- *
- * @param[in,out] me current instance pointer (see @ref oop)
- *
- * @attention
- * QActive_stop() must be called only from the AO that is about
- * to stop its execution. By that time, any pointers or references
- * to the AO are considered invalid (dangling) and it becomes
- * illegal for the rest of the application to post events to the AO.
- */
- void QActive_stop(QActive * const me);
- #endif /* def QF_ACTIVE_STOP */
- /* private: */
- /*! Posts an event `e` directly to the event queue of the active object
- * using the First-In-First-Out (FIFO) policy.
- * @private @memberof QActive
- *
- * @details
- * Direct event posting is the simplest asynchronous communication
- * method available in QF.
- *
- * @param[in,out] me current instance pointer (see @ref oop)
- * @param[in] e pointer to the event to be posted
- * @param[in] margin number of required free slots in the queue
- * after posting the event or ::QF_NO_MARGIN.
- * @param[in] sender pointer to a sender object (used in QS only)
- *
- * @returns
- * 'true' (success) if the posting succeeded (with the provided margin)
- * and 'false' (failure) when the posting fails.
- *
- * @precondition{qf_actq,100}
- * - event pointer must be valid
- *
- * @postcondition{qf_actq,190}
- * - the event must be posted if (`margin` == ::QF_NO_MARGIN)
- *
- * @attention
- * For `margin` == ::QF_NO_MARGIN, this function will assert internally
- * if the event posting fails. In that case, it is unnecessary to check
- * the retrun value from this function.
- *
- * @note
- * This function might be implemented differently in various QP/C++
- * ports. The provided implementation assumes that the ::QEQueue
- * class is used for the ::QActive event queue.
- *
- * @sa
- * QActive_postLIFO()
- *
- * @usage
- * @include qf_post.c
- */
- bool QActive_post_(QActive * const me,
- QEvt const * const e,
- uint_fast16_t const margin,
- void const * const sender);
- /*! Posts an event `e` directly to the event queue of the active object
- * using the Last-In-First-Out (LIFO) policy.
- * @private @memberof QActive
- *
- * @details
- * The LIFO policy should be used only for self-posting and with caution,
- * because it alters order of events in the queue.
- *
- * @param[in,out] me current instance pointer (see @ref oop)
- * @param[in] e pointer to the event to be posted
- *
- * @precondition{qf_actq,200}
- * - the queue must be able to accept the event (cannot overflow)
- *
- * @note
- * This function might be implemented differently in various QP/C++
- * ports. The provided implementation assumes that the ::QEQueue
- * class is used for the QActive event queue.
- *
- * @sa
- * QActive_post()
- */
- void QActive_postLIFO_(QActive * const me,
- QEvt const * const e);
- /*! Get an event from the event queue of an active object
- * @private @memberof QActive
- *
- * @details
- * The behavior of this function depends on the kernel used in the
- * QF port. For built-in kernels (Vanilla or QK) the function can be
- * called only when the queue is not empty, so it doesn't block. For
- * a blocking kernel/OS the function can block and wait for delivery
- * of an event.
- *
- * @param[in,out] me current instance pointer (see @ref oop)
- *
- * @returns
- * A pointer to the received event. The returned pointer is guaranteed
- * to be valid (can't be NULL).
- *
- * @note
- * This function might be implemented differently in various QP/C++
- * ports. The provided implementation assumes that the ::QEQueue
- * class is used for the QActive event queue.
- */
- QEvt const * QActive_get_(QActive * const me);
- /* public: */
- /*! Subscribes for delivery of signal `sig` to the active object
- * @public @memberof QActive
- *
- * @details
- * This function is part of the Publish-Subscribe event delivery
- * mechanism available in QF. Subscribing to an event means that the
- * framework will start posting all published events with a given signal
- * `sig` to the event queue of the active object.
- *
- * @param[in,out] me current instance pointer (see @ref oop)
- * @param[in] sig event signal to subscribe
- *
- * @precondition{qf_ps,300}
- * - signal must be in range of subscribe scignals
- * - subscriber AO priority must be in range
- * - the AO must be registered (started)
- *
- * The following example shows how the Table active object subscribes
- * to three signals in the initial transition:
- * @include qf_subscribe.cpp
- *
- * @sa
- * QActive_publish_(), QActive_unsubscribe(), and
- * QActive_unsubscribeAll()
- */
- void QActive_subscribe(QActive const * const me,
- enum_t const sig);
- /*! Unsubscribes from the delivery of signal `sig` to the active object
- * @public @memberof QActive
- *
- * @details
- * This function is part of the Publish-Subscribe event delivery
- * mechanism available in QF. Un-subscribing from an event means that
- * the framework will stop posting published events with a given signal
- * `sig` to the event queue of the active object.
- *
- * @param[in,out] me current instance pointer (see @ref oop)
- * @param[in] sig event signal to unsubscribe
- *
- * @precondition{qf_ps,400}
- * - signal must be in range of subscribe scignals
- * - subscriber AO priority must be in range
- * - the AO must be registered (started)
- *
- * @note
- * Due to the latency of event queues, an active object should NOT
- * assume that a given signal `sig` will never be dispatched to the
- * state machine of the active object after un-subscribing from that
- * signal. The event might be already in the queue, or just about to
- * be posted and the un-subscribe operation will not flush such events.
- *
- * @note
- * Un-subscribing from a signal that has never been subscribed in the
- * first place is considered an error and QF will raise an assertion.
- *
- * @sa
- * QActive_publish_(), QActive_subscribe(), and
- * QActive_unsubscribeAll()
- */
- void QActive_unsubscribe(QActive const * const me,
- enum_t const sig);
- /*! Unsubscribes from the delivery of all signals to the active object
- * @public @memberof QActive
- *
- * @details
- * This function is part of the Publish-Subscribe event delivery
- * mechanism available in QF. Un-subscribing from all events means that
- * the framework will stop posting any published events to the event
- * queue of the active object.
- *
- * @param[in,out] me current instance pointer (see @ref oop)
- *
- * @precondition{qf_ps,500}
- * - subscriber AO priority must be in range
- * - the AO must be registered (started)
- *
- * @note
- * Due to the latency of event queues, an active object should NOT
- * assume that no events will ever be dispatched to the state machine of
- * the active object after un-subscribing from all events.
- * The events might be already in the queue, or just about to be posted
- * and the un-subscribe operation will not flush such events. Also, the
- * alternative event-delivery mechanisms, such as direct event posting or
- * time events, can be still delivered to the event queue of the active
- * object.
- *
- * @sa
- * QActive_publish_(), QActive_subscribe(), and QActive_unsubscribe()
- */
- void QActive_unsubscribeAll(QActive const * const me);
- /*! Publish event to all subscribers of a given signal `e->sig`
- * @static @public @memberof QActive
- *
- * @details
- * This function posts (using the FIFO policy) the event @a e to **all**
- * active objects that have subscribed to the signal @a e->sig, which is
- * called _multicasting_. The multicasting performed in this function is
- * very efficient based on reference-counting inside the published event
- * ("zero-copy" event multicasting). This function is designed to be
- * callable from any part of the system, including ISRs, device drivers,
- * and active objects.
- *
- * @note
- * To avoid any unexpected re-ordering of events posted into AO queues,
- * the event multicasting is performed with scheduler **locked**.
- * However, the scheduler is locked only up to the priority level of
- * the highest-priority subscriber, so any AOs of even higher priority,
- * which did not subscribe to this event are *not* affected.
- */
- void QActive_psInit(
- QSubscrList * const subscrSto,
- enum_t const maxSignal);
- /* private: */
- /*! Publish event to all subscribers of a given signal `e->sig`
- * @static @private @memberof QActive
- *
- * @details
- * This function posts (using the FIFO policy) the event @a e to **all**
- * active objects that have subscribed to the signal @a e->sig, which is
- * called _multicasting_. The multicasting performed in this function is
- * very efficient based on reference-counting inside the published event
- * ("zero-copy" event multicasting). This function is designed to be
- * callable from any part of the system, including ISRs, device drivers,
- * and active objects.
- *
- * @precondition{qf_ps,200}
- * - the published signal must be within the configured range
- *
- * @note
- * To avoid any unexpected re-ordering of events posted into AO queues,
- * the event multicasting is performed with scheduler **locked**.
- * However, the scheduler is locked only up to the priority level of
- * the highest-priority subscriber, so any AOs of even higher priority,
- * which did not subscribe to this event are *not* affected.
- */
- void QActive_publish_(
- QEvt const * const e,
- void const * const sender,
- uint_fast8_t const qs_id);
- /* protected: */
- /*! Defer an event to a given separate event queue
- * @protected @memberof QActive
- *
- * @details
- * This function is part of the event deferral support. An active object
- * uses this function to defer an event `e` to the QF-supported native
- * event queue `eq`. QF correctly accounts for another outstanding
- * reference to the event and will not recycle the event at the end of
- * the RTC step. Later, the active object might recall one event at a
- * time from the event queue.
- *
- * @param[in] eq pointer to a "raw" thread-safe queue to recall
- * an event from.
- * @param[in] e pointer to the event to be deferred
- *
- * @returns
- * 'true' (success) when the event could be deferred and 'false'
- * (failure) if event deferral failed due to overflowing the queue.
- *
- * An active object can use multiple event queues to defer events of
- * different kinds.
- *
- * @sa
- * QActive_recall(), ::QEQueue, QActive_flushDeferred()
- */
- bool QActive_defer(QActive const * const me,
- QEQueue * const eq,
- QEvt const * const e);
- /*! Recall a deferred event from a given event queue
- * @protected @memberof QActive
- *
- * @details
- * This function is part of the event deferral support. An active object
- * uses this function to recall a deferred event from a given QF
- * event queue. Recalling an event means that it is removed from the
- * deferred event queue `eq` and posted (LIFO) to the event queue of
- * the active object.
- *
- * @param[in] eq pointer to a "raw" thread-safe queue to recall
- * an event from.
- *
- * @returns
- * 'true' if an event has been recalled and 'false' if not.
- *
- * @note
- * An active object can use multiple event queues to defer events of
- * different kinds.
- *
- * @sa
- * QActive_recall(), QActive_postLIFO_(), ::QEQueue
- */
- bool QActive_recall(QActive * const me,
- QEQueue * const eq);
- /*! Flush the specified deferred queue 'eq'
- * @protected @memberof QActive
- *
- * @details
- * This function is part of the event deferral support. An active object
- * can use this function to flush a given QF event queue. The function
- * makes sure that the events are not leaked.
- *
- * @param[in] eq pointer to a "raw" thread-safe queue to flush.
- *
- * @returns
- * the number of events actually flushed from the queue.
- *
- * @sa
- * QActive_defer(), QActive_recall(), ::QEQueue
- */
- uint_fast16_t QActive_flushDeferred(QActive const * const me,
- QEQueue * const eq);
- /* public: */
- /*! Generic setting of additional attributes (useful in QP ports)
- * @public @memberof QActive
- */
- void QActive_setAttr(QActive * const me,
- uint32_t attr1,
- void const * attr2);
- /* private: */
- /*! Thread routine for executing an active object `act`
- * @static @private @memberof QActive
- */
- void QActive_thread_(QActive * act);
- /* protected: */
- /*! Register this active object to be managed by the framework
- * @protected @memberof QActive
- *
- * @details
- * This function adds a given active object to the active objects
- * managed by the QF framework. It should not be called by the
- * application directly, only through the function QActive::start().
- *
- * @param[in,out] me current instance pointer (see @ref oop)
- *
- * @precondition{qf_qact,100}
- * - the "QF-priority" of the AO must be in range (must be set
- * before calling QActive_register_())
- * - the "QF-priority" must not be already in use (unique priority)
- * - the "QF-priority" must not exceed the "preemption-threshold"
- *
- * @postcondition{qf_qact,190}
- * - the preceding pre-thre must not exceed the preemption-threshold
- * - the preemption-threshold must not exceed the next pre-thre
- *
- * @sa QActive_unregister_()
- */
- void QActive_register_(QActive * const me);
- /*! Un-register the active object from the framework
- * @protected @memberof QActive
- *
- * @details
- * This function un-registers a given active object from the active objects
- * managed by the QF framework. It should not be called by the QP ports.
- *
- * @param[in] me pointer to the active object to remove from the
- * framework.
- *
- * @precondition{qf_qact,200}
- * - the priority of the active object must not be zero and cannot
- * exceed the maximum #QF_MAX_ACTIVE
- * - the priority of the AO must be already registered.
- *
- * @note
- * The active object that is removed from the framework can no longer
- * participate in any event exchange.
- *
- * @sa QActive_register_()
- */
- void QActive_unregister_(QActive * const me);
- /* private: */
- #ifdef QF_ISR_API
- /*! the "FromISR" variant used in the QP port to "FreeRTOS"
- * @private @memberof QActive
- */
- bool QActive_postFromISR_(QActive * const me,
- QEvt const * const e,
- uint_fast16_t const margin,
- void * par,
- void const * const sender);
- #endif /* def QF_ISR_API */
- /* public: */
- #ifdef QF_ISR_API
- /*! the "FromISR" variant used in the QP port to "FreeRTOS"
- * @static @private @memberof QActive
- */
- void QActive_publishFromISR_(
- QEvt const * e,
- void * par,
- void const * sender);
- #endif /* def QF_ISR_API */
- /*! Internal array of registered active objects
- * @static @private @memberof QActive
- */
- extern QActive * QActive_active_[QF_MAX_ACTIVE + 1U];
- /*! pointer to the array of all subscriber AOs for a given event signal.
- * @static @private @memberof QActive
- */
- extern QSubscrList * QActive_subscrList_;
- /*! The maximum published signal (the size of the subscrList_ array)
- * @static @private @memberof QActive
- */
- extern enum_t QActive_maxPubSignal_;
- /*! Internal array of registered active objects
- * @static @private @memberof QActive
- */
- extern QActive * QActive_registry_[QF_MAX_ACTIVE + 1U];
- /*$enddecl${QF::QActive} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
- /*$declare${QF::QActiveVtable} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
- /*${QF::QActiveVtable} .....................................................*/
- /*! @brief Virtual table for the QActive class */
- typedef struct QActiveVtable {
- struct QHsmVtable super; /*!< @protected inherits ::QHsmVtable */
- /*! @private virtual function to start the AO/thread
- * @sa QACTIVE_START()
- */
- void (*start)(QActive * const me, QPrioSpec prio,
- QEvt const * * const qSto, uint_fast16_t const qLen,
- void * const stkSto, uint_fast16_t const stkSize,
- void const * const par);
- /*! @private virtual function to asynchronously post (FIFO)
- * an event to the AO
- * @sa QACTIVE_POST() and QACTIVE_POST_X()
- */
- bool (*post)(QActive * const me, QEvt const * const e,
- uint_fast16_t const margin, void const * const sender);
- /*! @private virtual function to asynchronously post (LIFO)
- * an event to the AO
- * @sa QACTIVE_POST_LIFO()
- */
- void (*postLIFO)(QActive * const me, QEvt const * const e);
- } QActiveVtable;
- /*$enddecl${QF::QActiveVtable} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
- /*$declare${QF::QMActive} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
- /*${QF::QMActive} ..........................................................*/
- /*! @brief Active object class (based on QMsm implementation strategy)
- * @class QMActive
- * @extends QActive
- *
- * @details
- * ::QMActive represents an active object that uses the ::QMsm style state
- * machine implementation strategy. This strategy requires the use of the
- * QM modeling tool to generate state machine code automatically, but the
- * code is faster than in the ::QHsm style implementation strategy and needs
- * less run-time support (smaller event-processor).
- *
- * @note
- * ::QMActive is not intended to be instantiated directly, but rather serves
- * as the base class for derivation of active objects in the application.
- *
- * @trace
- * @tr{AQP214}
- *
- * @usage
- * The following example illustrates how to derive an active object from
- * ::QMActive. Please note that the ::QActive member @c super is defined as
- * the **first** member of the derived struct (see @ref oop).
- * @include qf_qmactive.c
- */
- typedef struct {
- /* protected: */
- QActive super;
- } QMActive;
- /* protected: */
- /*! Constructor of ::QMActive class.
- * @protected @memberof QMActive
- *
- * @details
- * Performs the first step of active object initialization by assigning
- * the virtual pointer and calling the superclass constructor.
- *
- * @param[in,out] me current instance pointer (see @ref oop)
- * @param[in] initial pointer to the event to be dispatched to the MSM
- *
- * @note Must be called only ONCE before QHSM_INIT().
- *
- * @sa QHsm_ctor()
- */
- void QMActive_ctor(QMActive * const me,
- QStateHandler const initial);
- /*$enddecl${QF::QMActive} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
- /*$declare${QF::QMActiveVtable} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
- /*${QF::QMActiveVtable} ....................................................*/
- /*! @brief Virtual Table for the ::QMActive class (inherited
- * from ::QActiveVtable)
- *
- * @note
- * ::QMActive inherits ::QActive exactly, without adding any new virtual
- * functions and therefore, ::QMActiveVtable is typedef'ed as ::QActiveVtable.
- */
- typedef QActiveVtable QMActiveVtable;
- /*$enddecl${QF::QMActiveVtable} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
- /*$declare${QF::QTimeEvt} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
- /*${QF::QTimeEvt} ..........................................................*/
- /*! @brief Time Event class
- * @class QTimeEvt
- * @extends QEvt
- *
- * @details
- * Time events are special QF events equipped with the notion of time passage.
- * The basic usage model of the time events is as follows. An active object
- * allocates one or more ::QTimeEvt objects (provides the storage for them).
- * When the active object needs to arrange for a timeout, it arms one of its
- * time events to fire either just once (one-shot) or periodically. Each time
- * event times out independently from the others, so a QF application can make
- * multiple parallel timeout requests (from the same or different active
- * objects). When QF detects that the appropriate moment has arrived, it
- * inserts the time event directly into the recipient's event queue. The
- * recipient then processes the time event just like any other event.
- *
- * Time events, as any other QF events derive from the ::QEvt base class.
- * Typically, you will use a time event as-is, but you can also further
- * derive more specialized time events from it by adding some more data
- * members and/or specialized functions that operate on the specialized
- * time events.
- *
- * Internally, the armed time events are organized into linked lists--one
- * list for every supported ticking rate. These linked lists are scanned in
- * every invocation of the QTIMEEVT_TICK_X() macro. Only armed (timing out)
- * time events are in the list, so only armed time events consume CPU cycles.
- *
- * @sa ::QTimeEvt for the description of the data members
- *
- * @trace
- * @tr{AQP215}
- *
- * @note
- * QF manages the time events in the QTIMEEVT_TICK_X() macro, which must
- * be called periodically, from the clock tick ISR or from other periodic
- * source. QTIMEEVT_TICK_X() caYou might also use the special ::QTicker
- * active object.
- *
- * @note
- * Even though ::QTimeEvt is a subclass of ::QEvt, ::QTimeEvt instances can NOT
- * be allocated dynamically from event pools. In other words, it is illegal to
- * allocate ::QTimeEvt instances with the Q_NEW() or Q_NEW_X() macros.
- */
- typedef struct QTimeEvt {
- /* protected: */
- QEvt super;
- /* private: */
- /*! link to the next time event in the list
- * @private @memberof QTimeEvt
- */
- struct QTimeEvt * volatile next;
- /*! The active object that receives the time events
- * @private @memberof QTimeEvt
- */
- void * volatile act;
- /*! Internal down-counter of the time event.
- * @private @memberof QTimeEvt
- *
- * @details
- * The down-counter is decremented by 1 in every QTimeEvt_tick_() call.
- * The time event fires (gets posted or published) when the down-counter
- * reaches zero.
- */
- QTimeEvtCtr volatile ctr;
- /*! Interval for periodic time event (zero for one-shot time event)
- * @private @memberof QTimeEvt
- *
- * @details
- * The value of the interval is re-loaded to the internal down-counter
- * when the time event expires, so that the time event keeps timing out
- * periodically.
- */
- QTimeEvtCtr interval;
- /* public: */
- } QTimeEvt;
- /* public: */
- /*! The "extended" constructor to initialize a Time Event.
- * @public @memberof QTimeEvt
- *
- * @details
- * When creating a time event, you must commit it to a specific active object
- * `act`, tick rate `tickRate` and event signal `sig`. You cannot change
- * these attributes later.
- *
- * @param[in,out] me current instance pointer (see @ref oop)
- * @param[in] act pointer to the active object associated with this
- * time event. The time event will post itself to this AO.
- * @param[in] sig signal to associate with this time event.
- * @param[in] tickRate system clock tick rate to associate with this
- * time event in the range [0..15].
- *
- * @precondition{qf_time,300}
- * - the signal `sig` must be valid
- * - the tick rate `tickRate` must be in range
- *
- * @note
- * You should call QTimeEvt_ctorX() exactly once for every Time Event
- * object **before** arming the Time Event. The ideal place for calling
- * QTimeEvt_ctorX() is the constructor of the associated AO.
- */
- void QTimeEvt_ctorX(QTimeEvt * const me,
- QActive * const act,
- enum_t const sig,
- uint_fast8_t const tickRate);
- /*! Arm a time event (one shot or periodic) for direct event posting.
- * @public @memberof QTimeEvt
- *
- * @details
- * Arms a time event to fire in a specified number of clock ticks and with
- * a specified interval. If the interval is zero, the time event is armed for
- * one shot ('one-shot' time event). When the timeout expires, the time event
- * gets directly posted (using the FIFO policy) into the event queue of the
- * host active object. After posting, a one-shot time event gets automatically
- * disarmed while a periodic time event (interval != 0) is automatically
- * re-armed.
- *
- * A time event can be disarmed at any time by calling QTimeEvt_disarm().
- * Also, a time event can be re-armed to fire in a different number of clock
- * ticks by calling the QTimeEvt_rearm().
- *
- * @param[in,out] me current instance pointer (see @ref oop)
- * @param[in] nTicks number of clock ticks (at the associated rate)
- * to rearm the time event with.
- * @param[in] interval interval (in clock ticks) for periodic time event.
- *
- * @precondition{qf_time,400}
- * - the host AO must be valid,
- * - the time eveht must be disarmed,
- * - the number of clock ticks cannot be zero,
- * - the signal must be valid.
- *
- * @attention
- * Arming an already armed time event is __not__ allowed and is considered
- * a programming error. The QP/C framework will assert if it detects an
- * attempt to arm an already armed time event.
- *
- * @usage
- * The following example shows how to arm a periodic time event as well as
- * one-shot time event from a state machine of an active object:
- * @include qf_tevt.c
- */
- void QTimeEvt_armX(QTimeEvt * const me,
- QTimeEvtCtr const nTicks,
- QTimeEvtCtr const interval);
- /*! Disarm a time event.
- * @public @memberof QTimeEvt
- *
- * @details
- * Disarm the time event so it can be safely reused.
- *
- * @param[in,out] me current instance pointer (see @ref oop)
- *
- * @returns
- * 'true' if the time event was truly disarmed, that is, it was running.
- * The return of 'false' means that the time event was not truly disarmed,
- * because it was not running. The 'false' return is only possible for one-
- * shot time events that have been automatically disarmed upon expiration.
- * In this case the 'false' return means that the time event has already
- * been posted or published and should be expected in the active object's
- * state machine.
- *
- * @note
- * there is no harm in disarming an already disarmed time event
- */
- bool QTimeEvt_disarm(QTimeEvt * const me);
- /*! Rearm a time event.
- * @public @memberof QTimeEvt
- *
- * @details
- * Rearms a time event with a new number of clock ticks. This function can
- * be used to adjust the current period of a periodic time event or to
- * prevent a one-shot time event from expiring (e.g., a watchdog time event).
- * Rearming a periodic timer leaves the interval unchanged and is a convenient
- * method to adjust the phasing of a periodic time event.
- *
- * @param[in,out] me current instance pointer (see @ref oop)
- * @param[in] nTicks number of clock ticks (at the associated rate)
- * to rearm the time event with.
- *
- * @returns
- * 'true' if the time event was running as it was re-armed. The 'false'
- * return means that the time event was not truly rearmed because it was
- * not running. The 'false' return is only possible for one-shot time events
- * that have been automatically disarmed upon expiration. In this case the
- * 'false' return means that the time event has already been posted or
- * published and should be expected in the active object's state machine.
- *
- * @precondition{qf_time,600}
- * - AO must be valid
- * - tick rate must be in range
- * - nTicks must not be zero,
- * - the signal of this time event must be valid
- */
- bool QTimeEvt_rearm(QTimeEvt * const me,
- QTimeEvtCtr const nTicks);
- /*! Check the "was disarmed" status of a time event.
- * @public @memberof QTimeEvt
- *
- * @details
- * Useful for checking whether a one-shot time event was disarmed in the
- * QTimeEvt_disarm() operation.
- *
- * @param[in,out] me current instance pointer (see @ref oop)
- *
- * @returns
- * 'true' if the time event was truly disarmed in the last QTimeEvt_disarm()
- * operation. The 'false' return means that the time event was not truly
- * disarmed, because it was not running at that time. The 'false' return is
- * only possible for one-shot time events that have been automatically disarmed
- * upon expiration. In this case the 'false' return means that the time event
- * has already been posted or published and should be expected in the active
- * object's event queue.
- *
- * @note
- * This function has a **side effect** of setting the "was disarmed" status,
- * which means that the second and subsequent times this function is called
- * the function will return 'true'.
- */
- bool QTimeEvt_wasDisarmed(QTimeEvt * const me);
- /*! Get the current value of the down-counter of a time event.
- * @public @memberof QTimeEvt
- *
- * @details
- * Useful for checking how many clock ticks (at the tick rate associated
- * with the time event) remain until the time event expires.
- *
- * @param[in,out] me current instance pointer (see @ref oop)
- *
- * @returns
- * For an armed time event, the function returns the current value of the
- * down-counter of the given time event. If the time event is not armed,
- * the function returns 0.
- *
- * @note
- * The function is thread-safe.
- */
- QTimeEvtCtr QTimeEvt_currCtr(QTimeEvt const * const me);
- /*! Processes all armed time events at every clock tick.
- * @static @private @memberof QTimeEvt
- *
- * @details
- * This internal helper function processes all armed ::QTimeEvt objects
- * associated wit the tick rate `tickRate`.
- *
- * This function must be called periodically from a time-tick ISR or from
- * a task so that QF can manage the timeout events assigned to the given
- * system clock tick rate.
- *
- * @param[in] tickRate clock tick rate serviced in this call [1..15].
- * @param[in] sender pointer to a sender object (only for QS tracing)
- *
- * @note
- * this function should be called only via the macro QTIMEEVT_TICK_X()
- *
- * @note
- * the calls to QTimeEvt_tick_() with different `tickRate` parameter can
- * preempt each other. For example, higher clock tick rates might be
- * serviced from interrupts while others from tasks (active objects).
- *
- * @sa ::QTimeEvt.
- */
- void QTimeEvt_tick_(
- uint_fast8_t const tickRate,
- void const * const sender);
- #ifdef Q_UTEST
- /*! Processes one clock tick for QUTest
- * @static @private @memberof QTimeEvt
- */
- void QTimeEvt_tick1_(
- uint_fast8_t const tickRate,
- void const * const sender);
- #endif /* def Q_UTEST */
- /*! Returns 'true' if there are no armed time events at a given tick rate.
- * @static @public @memberof QTimeEvt
- *
- * @details
- * Find out if any time events are armed at the given clock tick rate.
- *
- * @param[in] tickRate system clock tick rate to find out about.
- *
- * @returns
- * 'true' if no time events are armed at the given tick rate and
- * 'false' otherwise.
- *
- * @precondition{qf_time,800}
- * - the tick rate must be in range
- *
- * @note
- * This function should be called in critical section.
- */
- bool QTimeEvt_noActive(uint_fast8_t const tickRate);
- /*! heads of linked lists of time events, one for every clock tick rate */
- extern QTimeEvt QTimeEvt_timeEvtHead_[QF_MAX_TICK_RATE];
- /*$enddecl${QF::QTimeEvt} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
- /*$declare${QF::QTicker} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
- /*${QF::QTicker} ...........................................................*/
- /*! @brief "Ticker" Active Object class
- * @class QTicker
- * @extends QActive
- *
- * @details
- * QTicker is an efficient active object specialized to process QF system
- * clock tick at a specified tick rate [0..#QF_MAX_TICK_RATE].
- * Placing system clock tick processing in an active object allows you
- * to remove the non-deterministic QTIMEEVT_TICK_X() processing from the
- * interrupt level and move it into the thread-level, where you can prioritize
- * it as low as you wish.
- *
- * @usage
- * The following example illustrates use of QTicker active objects:
- * @include qf_ticker.c
- */
- typedef struct {
- /* protected: */
- QActive super;
- } QTicker;
- /* public: */
- /*! Constructor of the QTicker Active Object class
- * @public @memberof QTicker
- */
- void QTicker_ctor(QTicker * const me,
- uint_fast8_t const tickRate);
- /* private: */
- /*! initialization (override)
- * @private @memberof QTicker
- */
- void QTicker_init_(
- QHsm * const me,
- void const * const par,
- uint_fast8_t const qs_id);
- /*! dispatching (override)
- * @private @memberof QTicker
- */
- void QTicker_dispatch_(
- QHsm * const me,
- QEvt const * const e,
- uint_fast8_t const qs_id);
- /* public: */
- /*! post (override)
- * @private @memberof QTicker
- */
- bool QTicker_post_(
- QActive * const me,
- QEvt const * const e,
- uint_fast16_t const margin,
- void const * const sender);
- /*! post-LIFO (override)
- * @private @memberof QTicker
- */
- void QTicker_postLIFO_(
- QActive * const me,
- QEvt const * const e);
- /*$enddecl${QF::QTicker} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
- /*$declare${QF::QF-base} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
- /*${QF::QF-base::Attr} .....................................................*/
- /*! @brief QF active object framework
- * @class QF
- */
- typedef struct QF_Attr {
- uint8_t dummy; /*< dummy attribute */
- } QF;
- /*${QF::QF-base::intLock_} .................................................*/
- /*! Interrupt lock up-down counter (used in some QF ports )
- * @static @private @memberof QF
- */
- extern uint_fast8_t volatile QF_intLock_;
- /*${QF::QF-base::intNest_} .................................................*/
- /*! Interrupt nesting up-down counter (used in some QF ports )
- * @static @private @memberof QF
- */
- extern uint_fast8_t volatile QF_intNest_;
- /*${QF::QF-base::init} .....................................................*/
- /*! QF initialization
- * @static @public @memberof QF
- *
- * @details
- * Initializes QF and must be called exactly once before any other QF
- * function. Typcially, QF_init() is called from main() even before
- * initializing the Board Support Package (BSP).
- *
- * @note
- * QF_init() clears the internal QF variables, so that the framework
- * can start correctly even if the startup code fails to clear the
- * uninitialized data (as is required by the C Standard).
- */
- void QF_init(void);
- /*${QF::QF-base::stop} .....................................................*/
- /*! Function invoked by the application layer to stop the QF
- * application and return control to the OS/Kernel.
- * @static @public @memberof QF
- *
- * @details
- * This function stops the QF application. After calling this function,
- * QF attempts to gracefully stop the application. This graceful shutdown
- * might take some time to complete. The typical use of this function is
- * for terminating the QF application to return back to the operating
- * system or for handling fatal errors that require shutting down
- * (and possibly re-setting) the system.
- *
- * @attention
- * After calling QF_stop() the application must terminate and cannot
- * continue. In particular, QF_stop() is **not** intended to be followed
- * by a call to QF_init() to "resurrect" the application.
- *
- * @sa QF_onCleanup()
- */
- void QF_stop(void);
- /*${QF::QF-base::run} ......................................................*/
- /*! Transfers control to QF to run the application.
- * @static @public @memberof QF
- *
- * @details
- * QF_run() is typically called from your startup code after you initialize
- * the QF and start at least one active object with QACTIVE_START().
- *
- * @returns
- * In QK, the QF_run() does not return.
- */
- int_t QF_run(void);
- /*${QF::QF-base::psInit} ...................................................*/
- /*! initialization of publish-subscribe
- *
- * @deprecated
- * @sa QActive_psInit()
- */
- static inline void QF_psInit(
- QSubscrList * const subscrSto,
- enum_t const maxSignal)
- {
- QActive_psInit(subscrSto, maxSignal);
- }
- /*${QF::QF-base::getQueueMin} ..............................................*/
- /*! This function returns the minimum of free entries of
- * the given event queue.
- * @static @public @memberof QF
- *
- * @details
- * Queries the minimum of free ever present in the given event queue of
- * an active object with priority `prio`, since the active object
- * was started.
- *
- * @note
- * This function is available only when the native QF event queue
- * implementation is used. Requesting the queue minimum of an unused
- * priority level raises an assertion in the QF. (A priority level becomes
- * used in QF after the call to the QActive_register_() function.)
- *
- * @param[in] prio Priority of the active object, whose queue is queried
- *
- * @returns
- * the minimum of free ever present in the given event queue of an active
- * object with priority `prio`, since the active object was started.
- */
- uint_fast16_t QF_getQueueMin(uint_fast8_t const prio);
- /*${QF::QF-base::onStartup} ................................................*/
- /*! Startup QF callback.
- * @static @public @memberof QF
- *
- * @details
- * The purpose of the QF_onStartup() callback is to configure and enable
- * hardware interrupts. The callback is invoked from QF_run(), right before
- * starting the underlying real-time kernel. By that time, the application
- * is considered ready to receive and service interrupts.
- *
- * This function is application-specific and is not implemented in QF, but
- * rather in the Board Support Package (BSP) for the given application.
- */
- void QF_onStartup(void);
- /*${QF::QF-base::onCleanup} ................................................*/
- /*! Cleanup QF callback.
- * @static @public @memberof QF
- *
- * @details
- * QF_onCleanup() is called in some QF ports before QF returns to the
- * underlying real-time kernel or operating system.
- *
- * This function is strongly platform-specific and is not implemented in
- * the QF, but either in the QF port or in the Board Support Package (BSP)
- * for the given application. Some QF ports might not require implementing
- * QF_onCleanup() at all, because many embedded applications don't have
- * anything to exit to.
- *
- * @sa QF_stop()
- */
- void QF_onCleanup(void);
- /*$enddecl${QF::QF-base} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
- /*$declare${QF::QF-dyn} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
- /*${QF::QF-dyn::poolInit} ..................................................*/
- /*! Event pool initialization for dynamic allocation of events.
- * @static @public @memberof QF
- *
- * @details
- * 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.
- *
- * @param[in] poolSto pointer to the storage for the event pool
- * @param[in] poolSize size of the storage for the pool in bytes
- * @param[in] evtSize the block-size of the pool in bytes, which determines
- * the maximum size of events that can be allocated from the pool.
- *
- * @attention
- * You might initialize many event pools by making many consecutive calls
- * to the QF_poolInit() function. However, for the simplicity of the internal
- * implementation, you must initialize event pools in the **ascending order**
- * of the event size.
- *
- * Many RTOSes provide fixed block-size heaps, a.k.a. memory pools that can
- * be adapted for QF event pools. In case such support is missing, QF provides
- * a native QF event pool implementation. The macro #QF_EPOOL_TYPE_ determines
- * the type of event pool used by a particular QF port. See structure ::QMPool
- * for more information.
- *
- * @note The actual number of events available in the pool might be actually
- * less than (`poolSize` / `evtSize`) due to the internal alignment
- * of the blocks that the pool might perform. You can always check the
- * capacity of the pool by calling QF_getPoolMin().
- *
- * @note The dynamic allocation of events is optional, meaning that you
- * might choose not to use dynamic events. In that case calling QF_poolInit()
- * and using up memory for the memory blocks is unnecessary.
- *
- * @sa QF initialization example for QF_init()
- */
- void QF_poolInit(
- void * const poolSto,
- uint_fast32_t const poolSize,
- uint_fast16_t const evtSize);
- /*${QF::QF-dyn::poolGetMaxBlockSize} .......................................*/
- /*! Obtain the block size of any registered event pools.
- * @static @public @memberof QF
- *
- * @details
- * Obtain the block size of any registered event pools
- */
- uint_fast16_t QF_poolGetMaxBlockSize(void);
- /*${QF::QF-dyn::getPoolMin} ................................................*/
- /*! Obtain the minimum of free entries of the given event pool.
- * @static @public @memberof QF
- *
- * @details
- * This function obtains the minimum number of free blocks in the given
- * event pool since this pool has been initialized by a call to QF_poolInit().
- *
- * @param[in] poolId event pool ID in the range 1..QF_maxPool_, where
- * QF_maxPool_ is the number of event pools initialized
- * with the function QF_poolInit().
- *
- * @returns
- * the minimum number of unused blocks in the given event pool.
- */
- uint_fast16_t QF_getPoolMin(uint_fast8_t const poolId);
- /*${QF::QF-dyn::newX_} .....................................................*/
- /*! Internal QF implementation of creating new dynamic event.
- * @static @private @memberof QF
- *
- * @details
- * Allocates an event dynamically from one of the QF event pools.
- *
- * @param[in] evtSize the size (in bytes) of the event to allocate
- * @param[in] margin the number of un-allocated events still available
- * in a given event pool after the allocation completes.
- * The special value ::QF_NO_MARGIN means that this function
- * will assert if allocation fails.
- * @param[in] sig the signal to be assigned to the allocated event
- *
- * @returns
- * pointer to the newly allocated event. This pointer can be NULL only if
- * margin != #QF_NO_MARGIN and the event cannot be allocated with the
- * specified margin still available in the given pool.
- *
- * @note
- * The internal QF function QF_newX_() raises an assertion when the
- * `margin` parameter is #QF_NO_MARGIN and allocation of the event turns
- * out to be impossible due to event pool depletion, or incorrect (too big)
- * size of the requested event.
- *
- * @note
- * The application code should not call this function directly.
- * The only allowed use is thorough the macros Q_NEW() or Q_NEW_X().
- */
- QEvt * QF_newX_(
- uint_fast16_t const evtSize,
- uint_fast16_t const margin,
- enum_t const sig);
- /*${QF::QF-dyn::gc} ........................................................*/
- /*! Recycle a dynamic event
- * @static @public @memberof QF
- *
- * @details
- * This function implements a simple garbage collector for the dynamic events.
- * Only dynamic events are candidates for recycling. (A dynamic event is one
- * that is allocated from an event pool, which is determined as non-zero
- * e->poolId_ attribute.) Next, the function decrements the reference counter
- * of the event (e->refCtr_), and recycles the event only if the counter drops
- * to zero (meaning that no more references are outstanding for this event).
- * The dynamic event is recycled by returning it to the pool from which
- * it was originally allocated.
- *
- * @param[in] e pointer to the event to recycle
- *
- * @note
- * QF invokes the garbage collector at all appropriate contexts, when
- * an event can become garbage (automatic garbage collection), so the
- * application code should have no need to call QF_gc() directly. The QF_gc()
- * function is exposed only for special cases when your application sends
- * dynamic events to the "raw" thread-safe queues (see ::QEQueue). Such
- * queues are processed outside of QF and the automatic garbage collection
- * is **NOT** performed for these events. In this case you need to call
- * QF_gc() explicitly.
- */
- void QF_gc(QEvt const * const e);
- /*${QF::QF-dyn::newRef_} ...................................................*/
- /*! Internal QF implementation of creating new event reference.
- * @static @private @memberof QF
- *
- * @details
- * Creates and returns a new reference to the current event e
- *
- * @param[in] e pointer to the current event
- * @param[in] evtRef the event reference
- *
- * @returns
- * the newly created reference to the event `e`
- *
- * @note
- * The application code should not call this function directly.
- * The only allowed use is thorough the macro Q_NEW_REF().
- */
- QEvt const * QF_newRef_(
- QEvt const * const e,
- void const * const evtRef);
- /*${QF::QF-dyn::deleteRef_} ................................................*/
- /*! Internal QF implementation of deleting event reference.
- * @static @private @memberof QF
- *
- * @details
- * Deletes an existing reference to the event e
- *
- * @param[in] evtRef the event reference
- *
- * @note
- * The application code should not call this function directly.
- * The only allowed use is thorough the macro Q_DELETE_REF().
- */
- void QF_deleteRef_(void const * const evtRef);
- /*$enddecl${QF::QF-dyn} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
- /*$declare${QF::QF-extern-C} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
- /*${QF::QF-extern-C::onContextSw} ..........................................*/
- #ifdef QF_ON_CONTEXT_SW
- /*! QF context switch callback used in built-in kernels (QV, QK, QXK)
- * @static @public @memberof QF
- *
- * @details
- * This callback function provides a mechanism to perform additional
- * custom operations when one of the built-in kernels switches context
- * from one thread to another.
- *
- * @param[in] prev pointer to the previous thread (active object)
- * (prev==0 means that `prev` was the idle loop)
- * @param[in] next pointer to the next thread (active object)
- * (next==0) means that `next` is the idle loop)
- * @attention
- * QF_onContextSw() is invoked with interrupts **disabled** and must also
- * return with interrupts **disabled**.
- *
- * @note
- * This callback is enabled by defining the macro #QF_ON_CONTEXT_SW.
- *
- * @include qf_oncontextsw.c
- */
- void QF_onContextSw(
- QActive * prev,
- QActive * next);
- #endif /* def QF_ON_CONTEXT_SW */
- /*$enddecl${QF::QF-extern-C} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
- /*==========================================================================*/
- /*$declare${QF-macros} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
- /*${QF-macros::QF_NO_MARGIN} ...............................................*/
- /*! Special value of margin that causes asserting failure in case
- * event allocation or event posting fails
- */
- #define QF_NO_MARGIN ((uint_fast16_t)0xFFFFU)
- /*${QF-macros::Q_PRIO} .....................................................*/
- /*! Create a ::QPrioSpec object to specify priorty of an AO or a thread */
- #define Q_PRIO(prio_, pthre_) ((QPrioSpec)((prio_) | ((pthre_) << 8U)))
- /*${QF-macros::Q_NEW} ......................................................*/
- #ifndef Q_EVT_CTOR
- /*! Allocate a dynamic event (case when ::QEvt is a POD)
- *
- * @details
- * The macro calls the internal QF function QF::newX_() with
- * margin == ::QF_NO_MARGIN, which causes an assertion when the event
- * cannot be successfully allocated.
- *
- * @param[in] evtT_ event type (class name) of the event to allocate
- * @param[in] sig_ signal to assign to the newly allocated event
- *
- * @returns a valid event pointer cast to the type `evtT_`.
- *
- * @note
- * If #Q_EVT_CTOR is defined, the Q_NEW() macro becomes variadic and
- * takes all the arguments needed by the constructor of the event
- * class being allocated. The constructor is then called by means
- * of the placement-new operator.
- *
- * @usage
- * The following example illustrates dynamic allocation of an event:
- * @include qf_post.c
- */
- #define Q_NEW(evtT_, sig_) ((evtT_ *)QF_newX_((uint_fast16_t)sizeof(evtT_), \
- QF_NO_MARGIN, (enum_t)(sig_)))
- #endif /* ndef Q_EVT_CTOR */
- /*${QF-macros::Q_NEW} ......................................................*/
- #ifdef Q_EVT_CTOR
- /*! Asserting allocate a dynamic event
- * (case when ::QEvt is not a POD)
- */
- #define Q_NEW(evtT_, sig_, ...) \
- (evtT_##_ctor((evtT_ *)QF_newX_((uint_fast16_t)sizeof(evtT_), \
- QF_NO_MARGIN, (sig_)), (enum_t)(sig_), ##__VA_ARGS__))
- #endif /* def Q_EVT_CTOR */
- /*${QF-macros::Q_NEW_X} ....................................................*/
- #ifndef Q_EVT_CTOR
- /*! Non-asserting allocate a dynamic event (case when ::QEvt is a POD).
- *
- * @details
- * This macro allocates a new event and sets the pointer `e_`, while
- * leaving at least `margin_` of events still available in the pool
- *
- * @param[out] e_ pointer to the newly allocated event
- * @param[in] evtT_ event type (class name) of the event to allocate
- * @param[in] margin_ number of events that must remain available
- * in the given pool after this allocation. The
- * special value ::QF_NO_MARGIN causes asserting
- * failure in case event allocation fails.
- * @param[in] sig_ signal to assign to the newly allocated event
- *
- * @returns an event pointer cast to the type `evtT_` or NULL if the
- * event cannot be allocated with the specified `margin`.
- *
- * @note
- * If #Q_EVT_CTOR is defined, the Q_NEW_X() macro becomes variadic and
- * takes all the arguments needed by the constructor of the event
- * class being allocated. The constructor is then called by means
- * of the placement-new operator.
- *
- * @usage
- * The following example illustrates dynamic allocation of an event:
- * @include qf_postx.c
- */
- #define Q_NEW_X(e_, evtT_, margin_, sig_) ((e_) = \
- (evtT_ *)QF_newX_((uint_fast16_t)sizeof(evtT_), \
- (margin_), (enum_t)(sig_)))
- #endif /* ndef Q_EVT_CTOR */
- /*${QF-macros::Q_NEW_X} ....................................................*/
- #ifdef Q_EVT_CTOR
- /*! Non-asserting allocate a dynamic event
- * (case when ::QEvt is not a POD)
- */
- #define Q_NEW_X(e_, evtT_, margin_, sig_, ...) do { \
- (e_) = (evtT_ *)QF_newX_((uint_fast16_t)sizeof(evtT_), \
- (margin_), (enum_t)(sig_));\
- if ((e_) != (evtT_ *)0) { \
- evtT_##_ctor((e_), (enum_t)(sig_), ##__VA_ARGS__); \
- } \
- } while (false)
- #endif /* def Q_EVT_CTOR */
- /*${QF-macros::Q_NEW_REF} ..................................................*/
- /*! Create a new reference of the current event `e`
- *
- * @details
- * The current event processed by an active object is available only for
- * the duration of the run-to-completion (RTC) step. After that step, the
- * current event is no longer available and the framework might recycle
- * (garbage-collect) the event. The macro Q_NEW_REF() explicitly creates
- * a new reference to the current event that can be stored and used beyond
- * the current RTC step, until the reference is explicitly recycled by
- * means of the macro Q_DELETE_REF().
- *
- * @param[in,out] evtRef_ event reference to create
- * @param[in] evtT_ event type (class name) of the event reference
- *
- * @usage
- * The example **defer** in the directory `examples/win32/defer` illustrates
- * the use of Q_NEW_REF()
- *
- * @sa Q_DELETE_REF()
- */
- #define Q_NEW_REF(evtRef_, evtT_) \
- ((evtRef_) = (evtT_ const *)QF_newRef_(e, (evtRef_)))
- /*${QF-macros::Q_DELETE_REF} ...............................................*/
- /*! Delete the event reference
- *
- * @details
- * Every event reference created with the macro Q_NEW_REF() needs to be
- * eventually deleted by means of the macro Q_DELETE_REF() to avoid leaking
- * the event.
- *
- * @param[in,out] evtRef_ event reference to delete
- *
- * @usage
- * The example **defer** in the directory `examples/win32/defer` illustrates
- * the use of Q_DELETE_REF()
- *
- * @sa Q_NEW_REF()
- */
- #define Q_DELETE_REF(evtRef_) do { \
- QF_deleteRef_((evtRef_)); \
- (evtRef_) = (void *)0; \
- } while (false)
- /*${QF-macros::QACTIVE_START} ..............................................*/
- /*! Virtual call to start an active object.
- *
- * @details
- * Starts execution of the AO and registers the AO with the framework.
- *
- * @param[in,out] me_ current instance pointer (see @ref oop)
- * @param[in] prioSpec_ priority specification for the Active Object
- * @param[in] qSto_ pointer to the storage for the ring buffer of the
- * event queue (used only with the built-in ::QEQueue)
- * @param[in] qLen_ length of the event queue (in events)
- * @param[in] stkSto_ pointer to the stack storage (used only when
- * per-AO stack is needed)
- * @param[in] stkSize_ stack size (in bytes)
- * @param[in] par_ pointer to the additional port-specific parameter(s)
- * (might be NULL).
- * @usage
- * @include qf_start.c
- */
- #define QACTIVE_START(me_, prioSpec_, qSto_, qLen_, stkSto_, stkSize_, par_) do { \
- Q_ASSERT((Q_HSM_UPCAST(me_))->vptr); \
- (*((QActiveVtable const *)((Q_HSM_UPCAST(me_))->vptr))->start)( \
- (QActive *)(me_), (prioSpec_), \
- (qSto_), (qLen_), (stkSto_), (stkSize_), (par_)); \
- } while (false)
- /*${QF-macros::QACTIVE_POST} ...............................................*/
- #ifdef Q_SPY
- /*! Invoke the direct event posting facility QActive_post_()
- *
- * @details
- * This macro asserts if the queue overflows and cannot accept the event.
- *
- * @param[in,out] me_ current instance pointer (see @ref oop)
- * @param[in] e_ pointer to the event to post
- * @param[in] sender_ pointer to the sender object.
- *
- * @note
- * The `sendedr_` parameter is actually only used when QS tracing
- * is enabled (macro #Q_SPY is defined). When QS software tracing is
- * disenabled, the QACTIVE_POST() macro does not pass the `sender_`
- * parameter, so the overhead of passing this extra parameter is entirely
- * avoided.
- *
- * @note the pointer to the sender object is not necessarily a pointer
- * to an active object. In fact, if QACTIVE_POST() is called from an
- * interrupt or other context, you can create a unique object just to
- * unambiguously identify the sender of the event.
- *
- * @sa QActive_post_()
- */
- #define QACTIVE_POST(me_, e_, sender_) \
- ((void)(*((QActiveVtable const *)((Q_HSM_UPCAST(me_))->vptr))->post)(\
- (me_), (e_), QF_NO_MARGIN, (sender_)))
- #endif /* def Q_SPY */
- /*${QF-macros::QACTIVE_POST} ...............................................*/
- #ifndef Q_SPY
- #define QACTIVE_POST(me_, e_, dummy) \
- ((void)(*((QActiveVtable const *)((Q_HSM_UPCAST(me_))->vptr))->post)(\
- (me_), (e_), QF_NO_MARGIN, (void *)0))
- #endif /* ndef Q_SPY */
- /*${QF-macros::QACTIVE_POST_X} .............................................*/
- #ifdef Q_SPY
- /*! Invoke the direct event posting facility QActive_post_()
- * without delivery guarantee
- *
- * @details
- * This macro does not assert if the queue overflows and cannot accept
- * the event with the specified margin of free slots remaining.
- *
- * @param[in,out] me_ current instance pointer (see @ref oop)
- * @param[in] e_ pointer to the event to post
- * @param[in] margin_ the minimum free slots in the queue, which
- * must still be available after posting the event.
- * The special value ::QF_NO_MARGIN causes
- * asserting failure in case event posting fails.
- * @param[in] sender_ pointer to the sender object.
- *
- * @returns
- * 'true' if the posting succeeded, and 'false' if the posting
- * failed due to insufficient margin of free entries available in
- * the queue.
- *
- * @note
- * The `sender_` parameter is actually only used when QS tracing
- * is enabled (macro #Q_SPY is defined). When QS software tracing is
- * disabled, the POST_X() macro does not pass the `sender_` parameter,
- * so the overhead of passing this extra parameter is entirely avoided.
- *
- * @note
- * The pointer to the sender object is not necessarily a pointer
- * to an active object. In fact, if POST_X() is called from an
- * interrupt or other context, you can create a unique object just to
- * unambiguously identify the sender of the event.
- *
- * @usage
- * @include qf_postx.c
- */
- #define QACTIVE_POST_X(me_, e_, margin_, sender_) \
- ((*((QActiveVtable const *)((Q_HSM_UPCAST(me_))->vptr))->post)((me_),\
- (e_), (margin_), (sender_)))
- #endif /* def Q_SPY */
- /*${QF-macros::QACTIVE_POST_X} .............................................*/
- #ifndef Q_SPY
- #define QACTIVE_POST_X(me_, e_, margin_, dummy) \
- ((*((QActiveVtable const *)((Q_HSM_UPCAST(me_))->vptr))->post)((me_),\
- (e_), (margin_), (void *)0))
- #endif /* ndef Q_SPY */
- /*${QF-macros::QACTIVE_POST_LIFO} ..........................................*/
- /*! Virtual call to post an event to an active object using the
- * Last-In-First-Out (LIFO) policy.
- *
- * @param[in,out] me_ current instance pointer (see @ref oop)
- * @param[in] e_ pointer to the event to post
- */
- #define QACTIVE_POST_LIFO(me_, e_) \
- ((*((QActiveVtable const *)((Q_HSM_UPCAST(me_))->vptr))->postLIFO)( \
- (me_), (e_)))
- /*${QF-macros::QACTIVE_PUBLISH} ............................................*/
- #ifdef Q_SPY
- /*! Publish an event to all subscriber Active Objects.
- *
- * @details
- * If #Q_SPY is defined, this macro calls QActive_publish_() with
- * the `sender_` parameter to identify the publisher of the event.
- * Otherwise, `sender_` is not used.
- *
- * @param[in] e_ pointer to the posted event
- * @param[in] sender_ pointer to the sender object (actually used
- * only when #Q_SPY is defined)
- *
- * @note
- * The pointer to the `sender_` object is not necessarily a pointer
- * to an active object. In fact, if QACTIVE_PUBLISH() is called from an
- * interrupt or other context, you can create a unique object just to
- * unambiguously identify the sender of the event.
- *
- * @sa QActive_publish_()
- */
- #define QACTIVE_PUBLISH(e_, sender_) \
- (QActive_publish_((e_), (void const *)(sender_), (sender_)->prio))
- #endif /* def Q_SPY */
- /*${QF-macros::QACTIVE_PUBLISH} ............................................*/
- #ifndef Q_SPY
- #define QACTIVE_PUBLISH(e_, dummy) (QActive_publish_((e_), (void *)0, 0U))
- #endif /* ndef Q_SPY */
- /*${QF-macros::QTIMEEVT_TICK_X} ............................................*/
- #ifdef Q_SPY
- /*! Invoke the system clock tick processing QTimeEvt_tick_()
- *
- * @details
- * This macro is the recommended way of invoking clock tick processing,
- * because it provides the vital information for software tracing and
- * avoids any overhead when the tracing is disabled.
- *
- * @param[in] tickRate_ clock tick rate to be serviced through this call
- * @param[in] sender_ pointer to the sender object. This parameter
- * is actually only used when QS software tracing is enabled
- * (macro #Q_SPY is defined)
- * @note
- * When QS software tracing is disabled, the macro calls QTimeEvt_tick_()
- * without the `sender` parameter, so the overhead of passing this
- * extra parameter is entirely avoided.
- *
- * @note
- * The pointer to the sender object is not necessarily a pointer
- * to an active object. In fact, when QTIMEEVT_TICK_X() is called from
- * an interrupt, you would create a unique object just to unambiguously
- * identify the ISR as the sender of the time events.
- *
- * @sa QTimeEvt_tick_()
- */
- #define QTIMEEVT_TICK_X(tickRate_, sender_) \
- (QTimeEvt_tick_((tickRate_), (sender_)))
- #endif /* def Q_SPY */
- /*${QF-macros::QTIMEEVT_TICK_X} ............................................*/
- #ifndef Q_SPY
- #define QTIMEEVT_TICK_X(tickRate_, dummy) \
- (QTimeEvt_tick_((tickRate_), (void *)0))
- #endif /* ndef Q_SPY */
- /*${QF-macros::QTIMEEVT_TICK} ..............................................*/
- /*! Invoke the system clock tick processing
- * for tick rate 0
- */
- #define QTIMEEVT_TICK(sender_) QTIMEEVT_TICK_X(0U, (sender_))
- /*${QF-macros::QF_CRIT_EXIT_NOP} ...........................................*/
- #ifndef QF_CRIT_EXIT_NOP
- /*! No-operation for exiting a critical section
- *
- * @details
- * In some QF ports the critical section exit takes effect only on the
- * next machine instruction. If this next instruction is another entry
- * to a critical section, the critical section won't be really exited,
- * but rather the two adjecent critical sections would be merged.
- * The QF_CRIT_EXIT_NOP() macro contains minimal code required to
- * prevent such merging of critical sections in such merging of
- * critical sections in QF ports, in which it can occur.
- */
- #define QF_CRIT_EXIT_NOP() ((void)0)
- #endif /* ndef QF_CRIT_EXIT_NOP */
- /*${QF-macros::QF_TICK_X} ..................................................*/
- /*! Invoke the system clock tick processing
- *
- * @deprecated
- * superseded by QTIMEEVT_TICK_X()
- */
- #define QF_TICK_X(tickRate_, sender_) QTIMEEVT_TICK_X((tickRate_), (sender_))
- /*${QF-macros::QF_TICK} ....................................................*/
- /*! Invoke the system clock tick processing for tick rate 0
- *
- * @deprecated
- * superseded by QTIMEEVT_TICK()
- */
- #define QF_TICK(sender_) QTIMEEVT_TICK(sender_)
- /*${QF-macros::QF_PUBLISH} .................................................*/
- /*! Publish an event to all subscriber Active Objects.
- *
- * @deprecated
- * superseded by QACTIVE_PUBLISH()
- */
- #define QF_PUBLISH(e_, sender_) QACTIVE_PUBLISH((e_), (sender_))
- /*$enddecl${QF-macros} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
- #endif /* QF_H_ */
|