qf.h 74 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124
  1. /*$file${include::qf.h} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
  2. /*
  3. * Model: qpc.qm
  4. * File: ${include::qf.h}
  5. *
  6. * This code has been generated by QM 5.2.5 <www.state-machine.com/qm>.
  7. * DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost.
  8. *
  9. * This code is covered by the following QP license:
  10. * License # : LicenseRef-QL-dual
  11. * Issued to : Any user of the QP/C real-time embedded framework
  12. * Framework(s) : qpc
  13. * Support ends : 2023-12-31
  14. * License scope:
  15. *
  16. * Copyright (C) 2005 Quantum Leaps, LLC <state-machine.com>.
  17. *
  18. * SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
  19. *
  20. * This software is dual-licensed under the terms of the open source GNU
  21. * General Public License version 3 (or any later version), or alternatively,
  22. * under the terms of one of the closed source Quantum Leaps commercial
  23. * licenses.
  24. *
  25. * The terms of the open source GNU General Public License version 3
  26. * can be found at: <www.gnu.org/licenses/gpl-3.0>
  27. *
  28. * The terms of the closed source Quantum Leaps commercial licenses
  29. * can be found at: <www.state-machine.com/licensing>
  30. *
  31. * Redistributions in source code must retain this top-level comment block.
  32. * Plagiarizing this software to sidestep the license obligations is illegal.
  33. *
  34. * Contact information:
  35. * <www.state-machine.com/licensing>
  36. * <info@state-machine.com>
  37. */
  38. /*$endhead${include::qf.h} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
  39. /*! @file
  40. * @brief QF/C platform-independent public interface.
  41. */
  42. #ifndef QF_H_
  43. #define QF_H_
  44. /*==========================================================================*/
  45. /*$declare${QF-config} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
  46. /*${QF-config::QF_MAX_ACTIVE} ..............................................*/
  47. #ifndef QF_MAX_ACTIVE
  48. /*! Maximum number of active objects (configurable value in qf_port.h)
  49. * Valid values: [1U..64U]; default 32U
  50. */
  51. #define QF_MAX_ACTIVE 32U
  52. #endif /* ndef QF_MAX_ACTIVE */
  53. /*${QF-config::QF_MAX_ACTIVE exceeds the maximu~} ..........................*/
  54. #if (QF_MAX_ACTIVE > 64U)
  55. #error QF_MAX_ACTIVE exceeds the maximum of 64U;
  56. #endif /* (QF_MAX_ACTIVE > 64U) */
  57. /*${QF-config::QF_MAX_TICK_RATE} ...........................................*/
  58. #ifndef QF_MAX_TICK_RATE
  59. /*! Maximum number of clock rates (configurable value in qf_port.h)
  60. * Valid values: [0U..15U]; default 1U
  61. */
  62. #define QF_MAX_TICK_RATE 1U
  63. #endif /* ndef QF_MAX_TICK_RATE */
  64. /*${QF-config::QF_MAX_TICK_RATE exceeds the max~} ..........................*/
  65. #if (QF_MAX_TICK_RATE > 15U)
  66. #error QF_MAX_TICK_RATE exceeds the maximum of 15U;
  67. #endif /* (QF_MAX_TICK_RATE > 15U) */
  68. /*${QF-config::QF_MAX_EPOOL} ...............................................*/
  69. #ifndef QF_MAX_EPOOL
  70. /*! Maximum number of event pools (configurable value in qf_port.h)
  71. * Valid values: [0U..15U]; default 3U
  72. *
  73. * @note
  74. * #QF_MAX_EPOOL set to zero means that dynamic events are NOT configured
  75. * and should not be used in the application.
  76. */
  77. #define QF_MAX_EPOOL 3U
  78. #endif /* ndef QF_MAX_EPOOL */
  79. /*${QF-config::QF_MAX_EPOOL exceeds the maximum~} ..........................*/
  80. #if (QF_MAX_EPOOL > 15U)
  81. #error QF_MAX_EPOOL exceeds the maximum of 15U;
  82. #endif /* (QF_MAX_EPOOL > 15U) */
  83. /*${QF-config::QF_TIMEEVT_CTR_SIZE} ........................................*/
  84. #ifndef QF_TIMEEVT_CTR_SIZE
  85. /*! Size of the QTimeEvt counter (configurable value in qf_port.h)
  86. * Valid values: 1U, 2U, or 4U; default 4U
  87. */
  88. #define QF_TIMEEVT_CTR_SIZE 4U
  89. #endif /* ndef QF_TIMEEVT_CTR_SIZE */
  90. /*${QF-config::QF_TIMEEVT_CTR_SIZE defined inco~} ..........................*/
  91. #if (QF_TIMEEVT_CTR_SIZE != 1U) && (QF_TIMEEVT_CTR_SIZE != 2U) && (QF_TIMEEVT_CTR_SIZE != 4U)
  92. #error QF_TIMEEVT_CTR_SIZE defined incorrectly, expected 1U, 2U, or 4U;
  93. #endif /* (QF_TIMEEVT_CTR_SIZE != 1U) && (QF_TIMEEVT_CTR_SIZE != 2U) && (QF_TIMEEVT_CTR_SIZE != 4U) */
  94. /*${QF-config::QF_EVENT_SIZ_SIZE} ..........................................*/
  95. #ifndef QF_EVENT_SIZ_SIZE
  96. /*! Size of the event-size (configurable value in qf_port.h)
  97. * Valid values: 1U, 2U, or 4U; default 2U
  98. */
  99. #define QF_EVENT_SIZ_SIZE 2U
  100. #endif /* ndef QF_EVENT_SIZ_SIZE */
  101. /*${QF-config::QF_EVENT_SIZ_SIZE defined incorr~} ..........................*/
  102. #if (QF_EVENT_SIZ_SIZE != 1U) && (QF_EVENT_SIZ_SIZE != 2U) && (QF_EVENT_SIZ_SIZE != 4U)
  103. #error QF_EVENT_SIZ_SIZE defined incorrectly, expected 1U, 2U, or 4U;
  104. #endif /* (QF_EVENT_SIZ_SIZE != 1U) && (QF_EVENT_SIZ_SIZE != 2U) && (QF_EVENT_SIZ_SIZE != 4U) */
  105. /*$enddecl${QF-config} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
  106. /*==========================================================================*/
  107. /*$declare${QF-types} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
  108. /*${QF-types::QPSetBits} ...................................................*/
  109. #if (8U < QF_MAX_ACTIVE) && (QF_MAX_ACTIVE <= 16U)
  110. /*! bitmask for the internal representation of QPSet elements */
  111. typedef uint16_t QPSetBits;
  112. #endif /* (8U < QF_MAX_ACTIVE) && (QF_MAX_ACTIVE <= 16U) */
  113. /*${QF-types::QPSetBits} ...................................................*/
  114. #if (16 < QF_MAX_ACTIVE)
  115. typedef uint32_t QPSetBits;
  116. #endif /* (16 < QF_MAX_ACTIVE) */
  117. /*${QF-types::QPSetBits} ...................................................*/
  118. #if (QF_MAX_ACTIVE <= 8U)
  119. typedef uint8_t QPSetBits;
  120. #endif /* (QF_MAX_ACTIVE <= 8U) */
  121. /*${QF-types::QTimeEvtCtr} .................................................*/
  122. #if (QF_TIMEEVT_CTR_SIZE == 2U)
  123. /*! Data type to store the block-size defined based on the macro
  124. * #QF_TIMEEVT_CTR_SIZE.
  125. *
  126. * @details
  127. * The dynamic range of this data type determines the maximum block
  128. * size that can be managed by the pool.
  129. */
  130. typedef uint16_t QTimeEvtCtr;
  131. #endif /* (QF_TIMEEVT_CTR_SIZE == 2U) */
  132. /*${QF-types::QTimeEvtCtr} .................................................*/
  133. #if (QF_TIMEEVT_CTR_SIZE == 4U)
  134. typedef uint32_t QTimeEvtCtr;
  135. #endif /* (QF_TIMEEVT_CTR_SIZE == 4U) */
  136. /*${QF-types::QTimeEvtCtr} .................................................*/
  137. #if (QF_TIMEEVT_CTR_SIZE == 1U)
  138. typedef uint8_t QTimeEvtCtr;
  139. #endif /* (QF_TIMEEVT_CTR_SIZE == 1U) */
  140. /*${QF-types::QF_LOG2} .....................................................*/
  141. #ifndef QF_LOG2
  142. /*! Log-base-2 calculation when hardware acceleration
  143. * is NOT provided (#QF_LOG2 not defined).
  144. * @static @private @memberof QF
  145. */
  146. uint_fast8_t QF_LOG2(QPSetBits x);
  147. #endif /* ndef QF_LOG2 */
  148. /*${QF-types::QPrioSpec} ...................................................*/
  149. /*! Priority specification for Active Objects in QP
  150. *
  151. * @details
  152. * Active Object priorities in QP are integer numbers in the range
  153. * [1..#QF_MAX_ACTIVE], whereas the special priority number 0 is reserved
  154. * for the lowest-priority idle thread. The QP framework uses the *direct*
  155. * priority numbering, in which higher numerical values denote higher urgency.
  156. * For example, an AO with priority 32 has higher urgency than an AO with
  157. * priority 23.
  158. *
  159. * ::QPrioSpec allows an application developer to assign **two**
  160. * priorities to a given AO (see also Q_PRIO()):
  161. *
  162. * 1. The "QF-priority", which resides in the least-significant byte
  163. * of the ::QPrioSpec data type. The "QF-priority" must be **unique**
  164. * for each thread in the system and higher numerical values represent
  165. * higher urgency (direct pirority numbering).
  166. *
  167. * 2. The "preemption-threshold" priority, which resides in the most-
  168. * significant byte of the ::QPrioSpec data type. The second priority
  169. * cannot be lower than the "QF-priority", but does NOT need to be
  170. * unuque.
  171. *
  172. * In the QP native preemptive kernels, like QK and QXK, the "preemption-
  173. * threshold" priority is used as to implement the "preemption-threshold
  174. * scheduling" (PTS). It determines the conditions under which a given
  175. * thread can be *preempted* by other threads. Specifically, a given
  176. * thread can be preempted only by another thread with a *higher*
  177. * priority than the "preemption-threshold" of the original thread.
  178. *
  179. * ![QF-priority and preemption-threshold relations](qp-prio.png)
  180. *
  181. * @note
  182. * For backwards-compatibility, ::QPrioSpec data type might contain only
  183. * the "QF-priority" component (and the "preemption-threshold" component
  184. * left at zero). In that case, the "preemption-threshold" will be assumed
  185. * to be the same as the "QF-priority". This corresponds exactly to the
  186. * previous semantics of AO priority.
  187. *
  188. * @remark
  189. * When QP runs on top of 3rd-party kernels/RTOSes or general-purpose
  190. * operating systems, sthe second priority can have different meaning,
  191. * depending on the specific RTOS/GPOS used.
  192. */
  193. typedef uint16_t QPrioSpec;
  194. /*${QF-types::QSchedStatus} ................................................*/
  195. /*! The scheduler lock status used in some real-time kernels */
  196. typedef uint_fast16_t QSchedStatus;
  197. /*${QF-types::QPSet} .......................................................*/
  198. /*! @brief Priority Set of up to #QF_MAX_ACTIVE elements
  199. * @class QPSet
  200. *
  201. * @details
  202. * The priority set represents the set of active objects that are ready to
  203. * run and need to be considered by the scheduling algorithm. The set is
  204. * capable of storing up to #QF_MAX_ACTIVE priority levels, which can be
  205. * configured in the rage 1..64, inclusive.
  206. */
  207. typedef struct {
  208. /* public: */
  209. #if (QF_MAX_ACTIVE <= 32)
  210. /*! bitmask with a bit for each element */
  211. QPSetBits volatile bits;
  212. #endif /* (QF_MAX_ACTIVE <= 32) */
  213. #if (32 < QF_MAX_ACTIVE)
  214. /*! bitmasks with a bit for each element */
  215. QPSetBits volatile bits[2];
  216. #endif /* (32 < QF_MAX_ACTIVE) */
  217. } QPSet;
  218. /* public: */
  219. /*! Make the priority set empty */
  220. static inline void QPSet_setEmpty(QPSet * const me) {
  221. #if (QF_MAX_ACTIVE <= 32)
  222. me->bits = 0U;
  223. #else
  224. me->bits[0] = 0U;
  225. me->bits[1] = 0U;
  226. #endif
  227. }
  228. /*! Return 'true' if the priority set is empty */
  229. static inline bool QPSet_isEmpty(QPSet const * const me) {
  230. #if (QF_MAX_ACTIVE <= 32)
  231. return (me->bits == 0U);
  232. #else
  233. return (me->bits[0] == 0U) ? (me->bits[1] == 0U) : false;
  234. #endif
  235. }
  236. /*! Return 'true' if the priority set is NOT empty */
  237. static inline bool QPSet_notEmpty(QPSet const * const me) {
  238. #if (QF_MAX_ACTIVE <= 32)
  239. return (me->bits != 0U);
  240. #else
  241. return (me->bits[0] != 0U) ? true : (me->bits[1] != 0U);
  242. #endif
  243. }
  244. /*! Return 'true' if the priority set has the element n. */
  245. static inline bool QPSet_hasElement(QPSet const * const me,
  246. uint_fast8_t const n)
  247. {
  248. #if (QF_MAX_ACTIVE <= 32U)
  249. return (me->bits & (1U << (n - 1U))) != 0U;
  250. #else
  251. return (n <= 32U)
  252. ? ((me->bits[0] & ((uint32_t)1U << (n - 1U))) != 0U)
  253. : ((me->bits[1] & ((uint32_t)1U << (n - 33U))) != 0U);
  254. #endif
  255. }
  256. /*! insert element `n` into the set (n = 1..::QF_MAX_ACTIVE) */
  257. static inline void QPSet_insert(QPSet * const me,
  258. uint_fast8_t const n)
  259. {
  260. #if (QF_MAX_ACTIVE <= 32U)
  261. me->bits = (me->bits | (1U << (n - 1U)));
  262. #else
  263. if (n <= 32U) {
  264. me->bits[0] = (me->bits[0] | ((uint32_t)1U << (n - 1U)));
  265. }
  266. else {
  267. me->bits[1] = (me->bits[1] | ((uint32_t)1U << (n - 33U)));
  268. }
  269. #endif
  270. }
  271. /*! Remove element `n` from the set (n = 1U..::QF_MAX_ACTIVE) */
  272. static inline void QPSet_remove(QPSet * const me,
  273. uint_fast8_t const n)
  274. {
  275. #if (QF_MAX_ACTIVE <= 32U)
  276. me->bits = (me->bits &
  277. (QPSetBits)(~((QPSetBits)1U << (n - 1U))));
  278. #else
  279. if (n <= 32U) {
  280. (me->bits[0] = (me->bits[0] & ~((uint32_t)1U << (n - 1U))));
  281. }
  282. else {
  283. (me->bits[1] = (me->bits[1] & ~((uint32_t)1U << (n - 33U))));
  284. }
  285. #endif
  286. }
  287. /*! Find the maximum element in the set, returns zero if the set is empty */
  288. static inline uint_fast8_t QPSet_findMax(QPSet const * const me) {
  289. #if (QF_MAX_ACTIVE <= 32)
  290. return QF_LOG2(me->bits);
  291. #else
  292. return (me->bits[1] != 0U)
  293. ? (QF_LOG2(me->bits[1]) + 32U)
  294. : (QF_LOG2(me->bits[0]));
  295. #endif
  296. }
  297. /*${QF-types::QSubscrList} .................................................*/
  298. /*! Subscriber List (for publish-subscribe)
  299. *
  300. * @details
  301. * This data type represents a set of Active Objects that subscribe to
  302. * a given signal. The set is represented as priority-set, where each
  303. * bit corresponds to the unique QF-priority of an AO (see ::QPrioSpec).
  304. */
  305. typedef QPSet QSubscrList;
  306. /*$enddecl${QF-types} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
  307. /*$declare${QF::QActive} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
  308. /*${QF::QActive} ...........................................................*/
  309. /*! @brief Active object class (based on the QHsm implementation strategy)
  310. * @class QActive
  311. * @extends QHsm
  312. *
  313. * @details
  314. * Active objects are encapsulated tasks (each containing an event queue and
  315. * a state machine) that communicate with one another asynchronously by
  316. * sending and receiving events. Within an active object, events are
  317. * processed in a run-to-completion (RTC) fashion, while QF encapsulates
  318. * all the details of thread-safe event exchange and queuing.<br>
  319. *
  320. * QActive represents an active object that uses the QHsm-style
  321. * implementation strategy for state machines. This strategy is tailored
  322. * to manual coding, but it is also supported by the QM modeling tool.
  323. * The resulting code is slower than in the ::QMsm-style implementation
  324. * strategy.
  325. *
  326. * @note
  327. * QActive is not intended to be instantiated directly, but rather serves
  328. * as the abstract base class for derivation of active objects in the
  329. * applications.
  330. *
  331. * @sa QMActive
  332. *
  333. * @usage
  334. * The following example illustrates how to derive an active object from
  335. * QActive.
  336. * @include qf_qactive.c
  337. */
  338. typedef struct QActive {
  339. /* protected: */
  340. QHsm super;
  341. /* private: */
  342. #ifdef QF_EQUEUE_TYPE
  343. /*! OS-dependent event-queue type
  344. * @private @memberof QActive
  345. *
  346. * @details
  347. * The type of the queue depends on the underlying operating system or
  348. * a kernel. Many kernels support "message queues" that can be adapted
  349. * to deliver QF events to the active object. Alternatively, QF provides
  350. * a native event queue implementation that can be used as well.
  351. *
  352. * @note
  353. * The native QF event queue is configured by defining the macro
  354. * #QF_EQUEUE_TYPE as ::QEQueue.
  355. */
  356. QF_EQUEUE_TYPE eQueue;
  357. #endif /* def QF_EQUEUE_TYPE */
  358. #ifdef QF_OS_OBJECT_TYPE
  359. /*! OS-dependent per-thread object
  360. * @private @memberof QActive
  361. *
  362. * @details
  363. * This data might be used in various ways, depending on the QF port.
  364. * In some ports me->osObject is used to block the calling thread when
  365. * the native QF queue is empty. In other QF ports the OS-dependent
  366. * object might be used differently.
  367. */
  368. QF_OS_OBJECT_TYPE osObject;
  369. #endif /* def QF_OS_OBJECT_TYPE */
  370. #ifdef QF_THREAD_TYPE
  371. /*! OS-dependent representation of the thread of the active object
  372. * @private @memberof QActive
  373. *
  374. * @details
  375. * This data might be used in various ways, depending on the QF port.
  376. * In some ports me->thread is used store the thread handle. In other ports
  377. * me->thread can be a pointer to the Thread-Local-Storage (TLS).
  378. */
  379. QF_THREAD_TYPE thread;
  380. #endif /* def QF_THREAD_TYPE */
  381. /* public: */
  382. /*! QF-priority [1..#QF_MAX_ACTIVE] of this AO.
  383. * @private @memberof QActive
  384. * @sa ::QPrioSpec
  385. */
  386. uint8_t prio;
  387. /*! preemption-threshold [1..#QF_MAX_ACTIVE] of this AO.
  388. * @private @memberof QActive
  389. * @sa ::QPrioSpec
  390. */
  391. uint8_t pthre;
  392. /* private: */
  393. } QActive;
  394. /* protected: */
  395. /*! ::QActive constructor (abstract base class)
  396. * @protected @memberof QActive
  397. *
  398. * @param[in,out] me current instance pointer (see @ref oop)
  399. * @param[in] initial pointer to the top-most initial state-handler
  400. * function in the derived active object
  401. * @sa QHsm_ctor()
  402. */
  403. void QActive_ctor(QActive * const me,
  404. QStateHandler const initial);
  405. /* private: */
  406. /*! Starts execution of an active object and registers the object
  407. * with the framework
  408. * @private @memberof QActive
  409. *
  410. * @details
  411. * Starts execution of the AO and registers the AO with the framework.
  412. *
  413. * @param[in,out] me current instance pointer (see @ref oop)
  414. * @param[in] prioSpec priority specification for the AO (See ::QPrioSpec)
  415. * @param[in] qSto pointer to the storage for the ring buffer of the
  416. * event queue
  417. * @param[in] qLen length of the event queue [# ::QEvt* pointers]
  418. * @param[in] stkSto pointer to the stack storage (might be NULL)
  419. * @param[in] stkSize stack size [bytes]
  420. * @param[in] par pointer to an extra parameter (might be NULL)
  421. *
  422. * @usage
  423. * The following example shows starting an AO when a per-task stack
  424. * is needed:
  425. * @include qf_start.c
  426. */
  427. void QActive_start_(QActive * const me,
  428. QPrioSpec const prioSpec,
  429. QEvt const * * const qSto,
  430. uint_fast16_t const qLen,
  431. void * const stkSto,
  432. uint_fast16_t const stkSize,
  433. void const * const par);
  434. /* protected: */
  435. #ifdef QF_ACTIVE_STOP
  436. /*! Stops execution of an active object and removes it from the
  437. * framework's supervision
  438. * @protected @memberof QActive
  439. *
  440. * @param[in,out] me current instance pointer (see @ref oop)
  441. *
  442. * @attention
  443. * QActive_stop() must be called only from the AO that is about
  444. * to stop its execution. By that time, any pointers or references
  445. * to the AO are considered invalid (dangling) and it becomes
  446. * illegal for the rest of the application to post events to the AO.
  447. */
  448. void QActive_stop(QActive * const me);
  449. #endif /* def QF_ACTIVE_STOP */
  450. /* private: */
  451. /*! Posts an event `e` directly to the event queue of the active object
  452. * using the First-In-First-Out (FIFO) policy.
  453. * @private @memberof QActive
  454. *
  455. * @details
  456. * Direct event posting is the simplest asynchronous communication
  457. * method available in QF.
  458. *
  459. * @param[in,out] me current instance pointer (see @ref oop)
  460. * @param[in] e pointer to the event to be posted
  461. * @param[in] margin number of required free slots in the queue
  462. * after posting the event or ::QF_NO_MARGIN.
  463. * @param[in] sender pointer to a sender object (used in QS only)
  464. *
  465. * @returns
  466. * 'true' (success) if the posting succeeded (with the provided margin)
  467. * and 'false' (failure) when the posting fails.
  468. *
  469. * @precondition{qf_actq,100}
  470. * - event pointer must be valid
  471. *
  472. * @postcondition{qf_actq,190}
  473. * - the event must be posted if (`margin` == ::QF_NO_MARGIN)
  474. *
  475. * @attention
  476. * For `margin` == ::QF_NO_MARGIN, this function will assert internally
  477. * if the event posting fails. In that case, it is unnecessary to check
  478. * the retrun value from this function.
  479. *
  480. * @note
  481. * This function might be implemented differently in various QP/C++
  482. * ports. The provided implementation assumes that the ::QEQueue
  483. * class is used for the ::QActive event queue.
  484. *
  485. * @sa
  486. * QActive_postLIFO()
  487. *
  488. * @usage
  489. * @include qf_post.c
  490. */
  491. bool QActive_post_(QActive * const me,
  492. QEvt const * const e,
  493. uint_fast16_t const margin,
  494. void const * const sender);
  495. /*! Posts an event `e` directly to the event queue of the active object
  496. * using the Last-In-First-Out (LIFO) policy.
  497. * @private @memberof QActive
  498. *
  499. * @details
  500. * The LIFO policy should be used only for self-posting and with caution,
  501. * because it alters order of events in the queue.
  502. *
  503. * @param[in,out] me current instance pointer (see @ref oop)
  504. * @param[in] e pointer to the event to be posted
  505. *
  506. * @precondition{qf_actq,200}
  507. * - the queue must be able to accept the event (cannot overflow)
  508. *
  509. * @note
  510. * This function might be implemented differently in various QP/C++
  511. * ports. The provided implementation assumes that the ::QEQueue
  512. * class is used for the QActive event queue.
  513. *
  514. * @sa
  515. * QActive_post()
  516. */
  517. void QActive_postLIFO_(QActive * const me,
  518. QEvt const * const e);
  519. /*! Get an event from the event queue of an active object
  520. * @private @memberof QActive
  521. *
  522. * @details
  523. * The behavior of this function depends on the kernel used in the
  524. * QF port. For built-in kernels (Vanilla or QK) the function can be
  525. * called only when the queue is not empty, so it doesn't block. For
  526. * a blocking kernel/OS the function can block and wait for delivery
  527. * of an event.
  528. *
  529. * @param[in,out] me current instance pointer (see @ref oop)
  530. *
  531. * @returns
  532. * A pointer to the received event. The returned pointer is guaranteed
  533. * to be valid (can't be NULL).
  534. *
  535. * @note
  536. * This function might be implemented differently in various QP/C++
  537. * ports. The provided implementation assumes that the ::QEQueue
  538. * class is used for the QActive event queue.
  539. */
  540. QEvt const * QActive_get_(QActive * const me);
  541. /* public: */
  542. /*! Subscribes for delivery of signal `sig` to the active object
  543. * @public @memberof QActive
  544. *
  545. * @details
  546. * This function is part of the Publish-Subscribe event delivery
  547. * mechanism available in QF. Subscribing to an event means that the
  548. * framework will start posting all published events with a given signal
  549. * `sig` to the event queue of the active object.
  550. *
  551. * @param[in,out] me current instance pointer (see @ref oop)
  552. * @param[in] sig event signal to subscribe
  553. *
  554. * @precondition{qf_ps,300}
  555. * - signal must be in range of subscribe scignals
  556. * - subscriber AO priority must be in range
  557. * - the AO must be registered (started)
  558. *
  559. * The following example shows how the Table active object subscribes
  560. * to three signals in the initial transition:
  561. * @include qf_subscribe.cpp
  562. *
  563. * @sa
  564. * QActive_publish_(), QActive_unsubscribe(), and
  565. * QActive_unsubscribeAll()
  566. */
  567. void QActive_subscribe(QActive const * const me,
  568. enum_t const sig);
  569. /*! Unsubscribes from the delivery of signal `sig` to the active object
  570. * @public @memberof QActive
  571. *
  572. * @details
  573. * This function is part of the Publish-Subscribe event delivery
  574. * mechanism available in QF. Un-subscribing from an event means that
  575. * the framework will stop posting published events with a given signal
  576. * `sig` to the event queue of the active object.
  577. *
  578. * @param[in,out] me current instance pointer (see @ref oop)
  579. * @param[in] sig event signal to unsubscribe
  580. *
  581. * @precondition{qf_ps,400}
  582. * - signal must be in range of subscribe scignals
  583. * - subscriber AO priority must be in range
  584. * - the AO must be registered (started)
  585. *
  586. * @note
  587. * Due to the latency of event queues, an active object should NOT
  588. * assume that a given signal `sig` will never be dispatched to the
  589. * state machine of the active object after un-subscribing from that
  590. * signal. The event might be already in the queue, or just about to
  591. * be posted and the un-subscribe operation will not flush such events.
  592. *
  593. * @note
  594. * Un-subscribing from a signal that has never been subscribed in the
  595. * first place is considered an error and QF will raise an assertion.
  596. *
  597. * @sa
  598. * QActive_publish_(), QActive_subscribe(), and
  599. * QActive_unsubscribeAll()
  600. */
  601. void QActive_unsubscribe(QActive const * const me,
  602. enum_t const sig);
  603. /*! Unsubscribes from the delivery of all signals to the active object
  604. * @public @memberof QActive
  605. *
  606. * @details
  607. * This function is part of the Publish-Subscribe event delivery
  608. * mechanism available in QF. Un-subscribing from all events means that
  609. * the framework will stop posting any published events to the event
  610. * queue of the active object.
  611. *
  612. * @param[in,out] me current instance pointer (see @ref oop)
  613. *
  614. * @precondition{qf_ps,500}
  615. * - subscriber AO priority must be in range
  616. * - the AO must be registered (started)
  617. *
  618. * @note
  619. * Due to the latency of event queues, an active object should NOT
  620. * assume that no events will ever be dispatched to the state machine of
  621. * the active object after un-subscribing from all events.
  622. * The events might be already in the queue, or just about to be posted
  623. * and the un-subscribe operation will not flush such events. Also, the
  624. * alternative event-delivery mechanisms, such as direct event posting or
  625. * time events, can be still delivered to the event queue of the active
  626. * object.
  627. *
  628. * @sa
  629. * QActive_publish_(), QActive_subscribe(), and QActive_unsubscribe()
  630. */
  631. void QActive_unsubscribeAll(QActive const * const me);
  632. /*! Publish event to all subscribers of a given signal `e->sig`
  633. * @static @public @memberof QActive
  634. *
  635. * @details
  636. * This function posts (using the FIFO policy) the event @a e to **all**
  637. * active objects that have subscribed to the signal @a e->sig, which is
  638. * called _multicasting_. The multicasting performed in this function is
  639. * very efficient based on reference-counting inside the published event
  640. * ("zero-copy" event multicasting). This function is designed to be
  641. * callable from any part of the system, including ISRs, device drivers,
  642. * and active objects.
  643. *
  644. * @note
  645. * To avoid any unexpected re-ordering of events posted into AO queues,
  646. * the event multicasting is performed with scheduler **locked**.
  647. * However, the scheduler is locked only up to the priority level of
  648. * the highest-priority subscriber, so any AOs of even higher priority,
  649. * which did not subscribe to this event are *not* affected.
  650. */
  651. void QActive_psInit(
  652. QSubscrList * const subscrSto,
  653. enum_t const maxSignal);
  654. /* private: */
  655. /*! Publish event to all subscribers of a given signal `e->sig`
  656. * @static @private @memberof QActive
  657. *
  658. * @details
  659. * This function posts (using the FIFO policy) the event @a e to **all**
  660. * active objects that have subscribed to the signal @a e->sig, which is
  661. * called _multicasting_. The multicasting performed in this function is
  662. * very efficient based on reference-counting inside the published event
  663. * ("zero-copy" event multicasting). This function is designed to be
  664. * callable from any part of the system, including ISRs, device drivers,
  665. * and active objects.
  666. *
  667. * @precondition{qf_ps,200}
  668. * - the published signal must be within the configured range
  669. *
  670. * @note
  671. * To avoid any unexpected re-ordering of events posted into AO queues,
  672. * the event multicasting is performed with scheduler **locked**.
  673. * However, the scheduler is locked only up to the priority level of
  674. * the highest-priority subscriber, so any AOs of even higher priority,
  675. * which did not subscribe to this event are *not* affected.
  676. */
  677. void QActive_publish_(
  678. QEvt const * const e,
  679. void const * const sender,
  680. uint_fast8_t const qs_id);
  681. /* protected: */
  682. /*! Defer an event to a given separate event queue
  683. * @protected @memberof QActive
  684. *
  685. * @details
  686. * This function is part of the event deferral support. An active object
  687. * uses this function to defer an event `e` to the QF-supported native
  688. * event queue `eq`. QF correctly accounts for another outstanding
  689. * reference to the event and will not recycle the event at the end of
  690. * the RTC step. Later, the active object might recall one event at a
  691. * time from the event queue.
  692. *
  693. * @param[in] eq pointer to a "raw" thread-safe queue to recall
  694. * an event from.
  695. * @param[in] e pointer to the event to be deferred
  696. *
  697. * @returns
  698. * 'true' (success) when the event could be deferred and 'false'
  699. * (failure) if event deferral failed due to overflowing the queue.
  700. *
  701. * An active object can use multiple event queues to defer events of
  702. * different kinds.
  703. *
  704. * @sa
  705. * QActive_recall(), ::QEQueue, QActive_flushDeferred()
  706. */
  707. bool QActive_defer(QActive const * const me,
  708. QEQueue * const eq,
  709. QEvt const * const e);
  710. /*! Recall a deferred event from a given event queue
  711. * @protected @memberof QActive
  712. *
  713. * @details
  714. * This function is part of the event deferral support. An active object
  715. * uses this function to recall a deferred event from a given QF
  716. * event queue. Recalling an event means that it is removed from the
  717. * deferred event queue `eq` and posted (LIFO) to the event queue of
  718. * the active object.
  719. *
  720. * @param[in] eq pointer to a "raw" thread-safe queue to recall
  721. * an event from.
  722. *
  723. * @returns
  724. * 'true' if an event has been recalled and 'false' if not.
  725. *
  726. * @note
  727. * An active object can use multiple event queues to defer events of
  728. * different kinds.
  729. *
  730. * @sa
  731. * QActive_recall(), QActive_postLIFO_(), ::QEQueue
  732. */
  733. bool QActive_recall(QActive * const me,
  734. QEQueue * const eq);
  735. /*! Flush the specified deferred queue 'eq'
  736. * @protected @memberof QActive
  737. *
  738. * @details
  739. * This function is part of the event deferral support. An active object
  740. * can use this function to flush a given QF event queue. The function
  741. * makes sure that the events are not leaked.
  742. *
  743. * @param[in] eq pointer to a "raw" thread-safe queue to flush.
  744. *
  745. * @returns
  746. * the number of events actually flushed from the queue.
  747. *
  748. * @sa
  749. * QActive_defer(), QActive_recall(), ::QEQueue
  750. */
  751. uint_fast16_t QActive_flushDeferred(QActive const * const me,
  752. QEQueue * const eq);
  753. /* public: */
  754. /*! Generic setting of additional attributes (useful in QP ports)
  755. * @public @memberof QActive
  756. */
  757. void QActive_setAttr(QActive * const me,
  758. uint32_t attr1,
  759. void const * attr2);
  760. /* private: */
  761. /*! Thread routine for executing an active object `act`
  762. * @static @private @memberof QActive
  763. */
  764. void QActive_thread_(QActive * act);
  765. /* protected: */
  766. /*! Register this active object to be managed by the framework
  767. * @protected @memberof QActive
  768. *
  769. * @details
  770. * This function adds a given active object to the active objects
  771. * managed by the QF framework. It should not be called by the
  772. * application directly, only through the function QActive::start().
  773. *
  774. * @param[in,out] me current instance pointer (see @ref oop)
  775. *
  776. * @precondition{qf_qact,100}
  777. * - the "QF-priority" of the AO must be in range (must be set
  778. * before calling QActive_register_())
  779. * - the "QF-priority" must not be already in use (unique priority)
  780. * - the "QF-priority" must not exceed the "preemption-threshold"
  781. *
  782. * @postcondition{qf_qact,190}
  783. * - the preceding pre-thre must not exceed the preemption-threshold
  784. * - the preemption-threshold must not exceed the next pre-thre
  785. *
  786. * @sa QActive_unregister_()
  787. */
  788. void QActive_register_(QActive * const me);
  789. /*! Un-register the active object from the framework
  790. * @protected @memberof QActive
  791. *
  792. * @details
  793. * This function un-registers a given active object from the active objects
  794. * managed by the QF framework. It should not be called by the QP ports.
  795. *
  796. * @param[in] me pointer to the active object to remove from the
  797. * framework.
  798. *
  799. * @precondition{qf_qact,200}
  800. * - the priority of the active object must not be zero and cannot
  801. * exceed the maximum #QF_MAX_ACTIVE
  802. * - the priority of the AO must be already registered.
  803. *
  804. * @note
  805. * The active object that is removed from the framework can no longer
  806. * participate in any event exchange.
  807. *
  808. * @sa QActive_register_()
  809. */
  810. void QActive_unregister_(QActive * const me);
  811. /* private: */
  812. #ifdef QF_ISR_API
  813. /*! the "FromISR" variant used in the QP port to "FreeRTOS"
  814. * @private @memberof QActive
  815. */
  816. bool QActive_postFromISR_(QActive * const me,
  817. QEvt const * const e,
  818. uint_fast16_t const margin,
  819. void * par,
  820. void const * const sender);
  821. #endif /* def QF_ISR_API */
  822. /* public: */
  823. #ifdef QF_ISR_API
  824. /*! the "FromISR" variant used in the QP port to "FreeRTOS"
  825. * @static @private @memberof QActive
  826. */
  827. void QActive_publishFromISR_(
  828. QEvt const * e,
  829. void * par,
  830. void const * sender);
  831. #endif /* def QF_ISR_API */
  832. /*! Internal array of registered active objects
  833. * @static @private @memberof QActive
  834. */
  835. extern QActive * QActive_active_[QF_MAX_ACTIVE + 1U];
  836. /*! pointer to the array of all subscriber AOs for a given event signal.
  837. * @static @private @memberof QActive
  838. */
  839. extern QSubscrList * QActive_subscrList_;
  840. /*! The maximum published signal (the size of the subscrList_ array)
  841. * @static @private @memberof QActive
  842. */
  843. extern enum_t QActive_maxPubSignal_;
  844. /*! Internal array of registered active objects
  845. * @static @private @memberof QActive
  846. */
  847. extern QActive * QActive_registry_[QF_MAX_ACTIVE + 1U];
  848. /*$enddecl${QF::QActive} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
  849. /*$declare${QF::QActiveVtable} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
  850. /*${QF::QActiveVtable} .....................................................*/
  851. /*! @brief Virtual table for the QActive class */
  852. typedef struct QActiveVtable {
  853. struct QHsmVtable super; /*!< @protected inherits ::QHsmVtable */
  854. /*! @private virtual function to start the AO/thread
  855. * @sa QACTIVE_START()
  856. */
  857. void (*start)(QActive * const me, QPrioSpec prio,
  858. QEvt const * * const qSto, uint_fast16_t const qLen,
  859. void * const stkSto, uint_fast16_t const stkSize,
  860. void const * const par);
  861. /*! @private virtual function to asynchronously post (FIFO)
  862. * an event to the AO
  863. * @sa QACTIVE_POST() and QACTIVE_POST_X()
  864. */
  865. bool (*post)(QActive * const me, QEvt const * const e,
  866. uint_fast16_t const margin, void const * const sender);
  867. /*! @private virtual function to asynchronously post (LIFO)
  868. * an event to the AO
  869. * @sa QACTIVE_POST_LIFO()
  870. */
  871. void (*postLIFO)(QActive * const me, QEvt const * const e);
  872. } QActiveVtable;
  873. /*$enddecl${QF::QActiveVtable} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
  874. /*$declare${QF::QMActive} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
  875. /*${QF::QMActive} ..........................................................*/
  876. /*! @brief Active object class (based on QMsm implementation strategy)
  877. * @class QMActive
  878. * @extends QActive
  879. *
  880. * @details
  881. * ::QMActive represents an active object that uses the ::QMsm style state
  882. * machine implementation strategy. This strategy requires the use of the
  883. * QM modeling tool to generate state machine code automatically, but the
  884. * code is faster than in the ::QHsm style implementation strategy and needs
  885. * less run-time support (smaller event-processor).
  886. *
  887. * @note
  888. * ::QMActive is not intended to be instantiated directly, but rather serves
  889. * as the base class for derivation of active objects in the application.
  890. *
  891. * @trace
  892. * @tr{AQP214}
  893. *
  894. * @usage
  895. * The following example illustrates how to derive an active object from
  896. * ::QMActive. Please note that the ::QActive member @c super is defined as
  897. * the **first** member of the derived struct (see @ref oop).
  898. * @include qf_qmactive.c
  899. */
  900. typedef struct {
  901. /* protected: */
  902. QActive super;
  903. } QMActive;
  904. /* protected: */
  905. /*! Constructor of ::QMActive class.
  906. * @protected @memberof QMActive
  907. *
  908. * @details
  909. * Performs the first step of active object initialization by assigning
  910. * the virtual pointer and calling the superclass constructor.
  911. *
  912. * @param[in,out] me current instance pointer (see @ref oop)
  913. * @param[in] initial pointer to the event to be dispatched to the MSM
  914. *
  915. * @note Must be called only ONCE before QHSM_INIT().
  916. *
  917. * @sa QHsm_ctor()
  918. */
  919. void QMActive_ctor(QMActive * const me,
  920. QStateHandler const initial);
  921. /*$enddecl${QF::QMActive} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
  922. /*$declare${QF::QMActiveVtable} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
  923. /*${QF::QMActiveVtable} ....................................................*/
  924. /*! @brief Virtual Table for the ::QMActive class (inherited
  925. * from ::QActiveVtable)
  926. *
  927. * @note
  928. * ::QMActive inherits ::QActive exactly, without adding any new virtual
  929. * functions and therefore, ::QMActiveVtable is typedef'ed as ::QActiveVtable.
  930. */
  931. typedef QActiveVtable QMActiveVtable;
  932. /*$enddecl${QF::QMActiveVtable} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
  933. /*$declare${QF::QTimeEvt} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
  934. /*${QF::QTimeEvt} ..........................................................*/
  935. /*! @brief Time Event class
  936. * @class QTimeEvt
  937. * @extends QEvt
  938. *
  939. * @details
  940. * Time events are special QF events equipped with the notion of time passage.
  941. * The basic usage model of the time events is as follows. An active object
  942. * allocates one or more ::QTimeEvt objects (provides the storage for them).
  943. * When the active object needs to arrange for a timeout, it arms one of its
  944. * time events to fire either just once (one-shot) or periodically. Each time
  945. * event times out independently from the others, so a QF application can make
  946. * multiple parallel timeout requests (from the same or different active
  947. * objects). When QF detects that the appropriate moment has arrived, it
  948. * inserts the time event directly into the recipient's event queue. The
  949. * recipient then processes the time event just like any other event.
  950. *
  951. * Time events, as any other QF events derive from the ::QEvt base class.
  952. * Typically, you will use a time event as-is, but you can also further
  953. * derive more specialized time events from it by adding some more data
  954. * members and/or specialized functions that operate on the specialized
  955. * time events.
  956. *
  957. * Internally, the armed time events are organized into linked lists--one
  958. * list for every supported ticking rate. These linked lists are scanned in
  959. * every invocation of the QTIMEEVT_TICK_X() macro. Only armed (timing out)
  960. * time events are in the list, so only armed time events consume CPU cycles.
  961. *
  962. * @sa ::QTimeEvt for the description of the data members
  963. *
  964. * @trace
  965. * @tr{AQP215}
  966. *
  967. * @note
  968. * QF manages the time events in the QTIMEEVT_TICK_X() macro, which must
  969. * be called periodically, from the clock tick ISR or from other periodic
  970. * source. QTIMEEVT_TICK_X() caYou might also use the special ::QTicker
  971. * active object.
  972. *
  973. * @note
  974. * Even though ::QTimeEvt is a subclass of ::QEvt, ::QTimeEvt instances can NOT
  975. * be allocated dynamically from event pools. In other words, it is illegal to
  976. * allocate ::QTimeEvt instances with the Q_NEW() or Q_NEW_X() macros.
  977. */
  978. typedef struct QTimeEvt {
  979. /* protected: */
  980. QEvt super;
  981. /* private: */
  982. /*! link to the next time event in the list
  983. * @private @memberof QTimeEvt
  984. */
  985. struct QTimeEvt * volatile next;
  986. /*! The active object that receives the time events
  987. * @private @memberof QTimeEvt
  988. */
  989. void * volatile act;
  990. /*! Internal down-counter of the time event.
  991. * @private @memberof QTimeEvt
  992. *
  993. * @details
  994. * The down-counter is decremented by 1 in every QTimeEvt_tick_() call.
  995. * The time event fires (gets posted or published) when the down-counter
  996. * reaches zero.
  997. */
  998. QTimeEvtCtr volatile ctr;
  999. /*! Interval for periodic time event (zero for one-shot time event)
  1000. * @private @memberof QTimeEvt
  1001. *
  1002. * @details
  1003. * The value of the interval is re-loaded to the internal down-counter
  1004. * when the time event expires, so that the time event keeps timing out
  1005. * periodically.
  1006. */
  1007. QTimeEvtCtr interval;
  1008. /* public: */
  1009. } QTimeEvt;
  1010. /* public: */
  1011. /*! The "extended" constructor to initialize a Time Event.
  1012. * @public @memberof QTimeEvt
  1013. *
  1014. * @details
  1015. * When creating a time event, you must commit it to a specific active object
  1016. * `act`, tick rate `tickRate` and event signal `sig`. You cannot change
  1017. * these attributes later.
  1018. *
  1019. * @param[in,out] me current instance pointer (see @ref oop)
  1020. * @param[in] act pointer to the active object associated with this
  1021. * time event. The time event will post itself to this AO.
  1022. * @param[in] sig signal to associate with this time event.
  1023. * @param[in] tickRate system clock tick rate to associate with this
  1024. * time event in the range [0..15].
  1025. *
  1026. * @precondition{qf_time,300}
  1027. * - the signal `sig` must be valid
  1028. * - the tick rate `tickRate` must be in range
  1029. *
  1030. * @note
  1031. * You should call QTimeEvt_ctorX() exactly once for every Time Event
  1032. * object **before** arming the Time Event. The ideal place for calling
  1033. * QTimeEvt_ctorX() is the constructor of the associated AO.
  1034. */
  1035. void QTimeEvt_ctorX(QTimeEvt * const me,
  1036. QActive * const act,
  1037. enum_t const sig,
  1038. uint_fast8_t const tickRate);
  1039. /*! Arm a time event (one shot or periodic) for direct event posting.
  1040. * @public @memberof QTimeEvt
  1041. *
  1042. * @details
  1043. * Arms a time event to fire in a specified number of clock ticks and with
  1044. * a specified interval. If the interval is zero, the time event is armed for
  1045. * one shot ('one-shot' time event). When the timeout expires, the time event
  1046. * gets directly posted (using the FIFO policy) into the event queue of the
  1047. * host active object. After posting, a one-shot time event gets automatically
  1048. * disarmed while a periodic time event (interval != 0) is automatically
  1049. * re-armed.
  1050. *
  1051. * A time event can be disarmed at any time by calling QTimeEvt_disarm().
  1052. * Also, a time event can be re-armed to fire in a different number of clock
  1053. * ticks by calling the QTimeEvt_rearm().
  1054. *
  1055. * @param[in,out] me current instance pointer (see @ref oop)
  1056. * @param[in] nTicks number of clock ticks (at the associated rate)
  1057. * to rearm the time event with.
  1058. * @param[in] interval interval (in clock ticks) for periodic time event.
  1059. *
  1060. * @precondition{qf_time,400}
  1061. * - the host AO must be valid,
  1062. * - the time eveht must be disarmed,
  1063. * - the number of clock ticks cannot be zero,
  1064. * - the signal must be valid.
  1065. *
  1066. * @attention
  1067. * Arming an already armed time event is __not__ allowed and is considered
  1068. * a programming error. The QP/C framework will assert if it detects an
  1069. * attempt to arm an already armed time event.
  1070. *
  1071. * @usage
  1072. * The following example shows how to arm a periodic time event as well as
  1073. * one-shot time event from a state machine of an active object:
  1074. * @include qf_tevt.c
  1075. */
  1076. void QTimeEvt_armX(QTimeEvt * const me,
  1077. QTimeEvtCtr const nTicks,
  1078. QTimeEvtCtr const interval);
  1079. /*! Disarm a time event.
  1080. * @public @memberof QTimeEvt
  1081. *
  1082. * @details
  1083. * Disarm the time event so it can be safely reused.
  1084. *
  1085. * @param[in,out] me current instance pointer (see @ref oop)
  1086. *
  1087. * @returns
  1088. * 'true' if the time event was truly disarmed, that is, it was running.
  1089. * The return of 'false' means that the time event was not truly disarmed,
  1090. * because it was not running. The 'false' return is only possible for one-
  1091. * shot time events that have been automatically disarmed upon expiration.
  1092. * In this case the 'false' return means that the time event has already
  1093. * been posted or published and should be expected in the active object's
  1094. * state machine.
  1095. *
  1096. * @note
  1097. * there is no harm in disarming an already disarmed time event
  1098. */
  1099. bool QTimeEvt_disarm(QTimeEvt * const me);
  1100. /*! Rearm a time event.
  1101. * @public @memberof QTimeEvt
  1102. *
  1103. * @details
  1104. * Rearms a time event with a new number of clock ticks. This function can
  1105. * be used to adjust the current period of a periodic time event or to
  1106. * prevent a one-shot time event from expiring (e.g., a watchdog time event).
  1107. * Rearming a periodic timer leaves the interval unchanged and is a convenient
  1108. * method to adjust the phasing of a periodic time event.
  1109. *
  1110. * @param[in,out] me current instance pointer (see @ref oop)
  1111. * @param[in] nTicks number of clock ticks (at the associated rate)
  1112. * to rearm the time event with.
  1113. *
  1114. * @returns
  1115. * 'true' if the time event was running as it was re-armed. The 'false'
  1116. * return means that the time event was not truly rearmed because it was
  1117. * not running. The 'false' return is only possible for one-shot time events
  1118. * that have been automatically disarmed upon expiration. In this case the
  1119. * 'false' return means that the time event has already been posted or
  1120. * published and should be expected in the active object's state machine.
  1121. *
  1122. * @precondition{qf_time,600}
  1123. * - AO must be valid
  1124. * - tick rate must be in range
  1125. * - nTicks must not be zero,
  1126. * - the signal of this time event must be valid
  1127. */
  1128. bool QTimeEvt_rearm(QTimeEvt * const me,
  1129. QTimeEvtCtr const nTicks);
  1130. /*! Check the "was disarmed" status of a time event.
  1131. * @public @memberof QTimeEvt
  1132. *
  1133. * @details
  1134. * Useful for checking whether a one-shot time event was disarmed in the
  1135. * QTimeEvt_disarm() operation.
  1136. *
  1137. * @param[in,out] me current instance pointer (see @ref oop)
  1138. *
  1139. * @returns
  1140. * 'true' if the time event was truly disarmed in the last QTimeEvt_disarm()
  1141. * operation. The 'false' return means that the time event was not truly
  1142. * disarmed, because it was not running at that time. The 'false' return is
  1143. * only possible for one-shot time events that have been automatically disarmed
  1144. * upon expiration. In this case the 'false' return means that the time event
  1145. * has already been posted or published and should be expected in the active
  1146. * object's event queue.
  1147. *
  1148. * @note
  1149. * This function has a **side effect** of setting the "was disarmed" status,
  1150. * which means that the second and subsequent times this function is called
  1151. * the function will return 'true'.
  1152. */
  1153. bool QTimeEvt_wasDisarmed(QTimeEvt * const me);
  1154. /*! Get the current value of the down-counter of a time event.
  1155. * @public @memberof QTimeEvt
  1156. *
  1157. * @details
  1158. * Useful for checking how many clock ticks (at the tick rate associated
  1159. * with the time event) remain until the time event expires.
  1160. *
  1161. * @param[in,out] me current instance pointer (see @ref oop)
  1162. *
  1163. * @returns
  1164. * For an armed time event, the function returns the current value of the
  1165. * down-counter of the given time event. If the time event is not armed,
  1166. * the function returns 0.
  1167. *
  1168. * @note
  1169. * The function is thread-safe.
  1170. */
  1171. QTimeEvtCtr QTimeEvt_currCtr(QTimeEvt const * const me);
  1172. /*! Processes all armed time events at every clock tick.
  1173. * @static @private @memberof QTimeEvt
  1174. *
  1175. * @details
  1176. * This internal helper function processes all armed ::QTimeEvt objects
  1177. * associated wit the tick rate `tickRate`.
  1178. *
  1179. * This function must be called periodically from a time-tick ISR or from
  1180. * a task so that QF can manage the timeout events assigned to the given
  1181. * system clock tick rate.
  1182. *
  1183. * @param[in] tickRate clock tick rate serviced in this call [1..15].
  1184. * @param[in] sender pointer to a sender object (only for QS tracing)
  1185. *
  1186. * @note
  1187. * this function should be called only via the macro QTIMEEVT_TICK_X()
  1188. *
  1189. * @note
  1190. * the calls to QTimeEvt_tick_() with different `tickRate` parameter can
  1191. * preempt each other. For example, higher clock tick rates might be
  1192. * serviced from interrupts while others from tasks (active objects).
  1193. *
  1194. * @sa ::QTimeEvt.
  1195. */
  1196. void QTimeEvt_tick_(
  1197. uint_fast8_t const tickRate,
  1198. void const * const sender);
  1199. #ifdef Q_UTEST
  1200. /*! Processes one clock tick for QUTest
  1201. * @static @private @memberof QTimeEvt
  1202. */
  1203. void QTimeEvt_tick1_(
  1204. uint_fast8_t const tickRate,
  1205. void const * const sender);
  1206. #endif /* def Q_UTEST */
  1207. /*! Returns 'true' if there are no armed time events at a given tick rate.
  1208. * @static @public @memberof QTimeEvt
  1209. *
  1210. * @details
  1211. * Find out if any time events are armed at the given clock tick rate.
  1212. *
  1213. * @param[in] tickRate system clock tick rate to find out about.
  1214. *
  1215. * @returns
  1216. * 'true' if no time events are armed at the given tick rate and
  1217. * 'false' otherwise.
  1218. *
  1219. * @precondition{qf_time,800}
  1220. * - the tick rate must be in range
  1221. *
  1222. * @note
  1223. * This function should be called in critical section.
  1224. */
  1225. bool QTimeEvt_noActive(uint_fast8_t const tickRate);
  1226. /*! heads of linked lists of time events, one for every clock tick rate */
  1227. extern QTimeEvt QTimeEvt_timeEvtHead_[QF_MAX_TICK_RATE];
  1228. /*$enddecl${QF::QTimeEvt} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
  1229. /*$declare${QF::QTicker} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
  1230. /*${QF::QTicker} ...........................................................*/
  1231. /*! @brief "Ticker" Active Object class
  1232. * @class QTicker
  1233. * @extends QActive
  1234. *
  1235. * @details
  1236. * QTicker is an efficient active object specialized to process QF system
  1237. * clock tick at a specified tick rate [0..#QF_MAX_TICK_RATE].
  1238. * Placing system clock tick processing in an active object allows you
  1239. * to remove the non-deterministic QTIMEEVT_TICK_X() processing from the
  1240. * interrupt level and move it into the thread-level, where you can prioritize
  1241. * it as low as you wish.
  1242. *
  1243. * @usage
  1244. * The following example illustrates use of QTicker active objects:
  1245. * @include qf_ticker.c
  1246. */
  1247. typedef struct {
  1248. /* protected: */
  1249. QActive super;
  1250. } QTicker;
  1251. /* public: */
  1252. /*! Constructor of the QTicker Active Object class
  1253. * @public @memberof QTicker
  1254. */
  1255. void QTicker_ctor(QTicker * const me,
  1256. uint_fast8_t const tickRate);
  1257. /* private: */
  1258. /*! initialization (override)
  1259. * @private @memberof QTicker
  1260. */
  1261. void QTicker_init_(
  1262. QHsm * const me,
  1263. void const * const par,
  1264. uint_fast8_t const qs_id);
  1265. /*! dispatching (override)
  1266. * @private @memberof QTicker
  1267. */
  1268. void QTicker_dispatch_(
  1269. QHsm * const me,
  1270. QEvt const * const e,
  1271. uint_fast8_t const qs_id);
  1272. /* public: */
  1273. /*! post (override)
  1274. * @private @memberof QTicker
  1275. */
  1276. bool QTicker_post_(
  1277. QActive * const me,
  1278. QEvt const * const e,
  1279. uint_fast16_t const margin,
  1280. void const * const sender);
  1281. /*! post-LIFO (override)
  1282. * @private @memberof QTicker
  1283. */
  1284. void QTicker_postLIFO_(
  1285. QActive * const me,
  1286. QEvt const * const e);
  1287. /*$enddecl${QF::QTicker} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
  1288. /*$declare${QF::QF-base} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
  1289. /*${QF::QF-base::Attr} .....................................................*/
  1290. /*! @brief QF active object framework
  1291. * @class QF
  1292. */
  1293. typedef struct QF_Attr {
  1294. uint8_t dummy; /*< dummy attribute */
  1295. } QF;
  1296. /*${QF::QF-base::intLock_} .................................................*/
  1297. /*! Interrupt lock up-down counter (used in some QF ports )
  1298. * @static @private @memberof QF
  1299. */
  1300. extern uint_fast8_t volatile QF_intLock_;
  1301. /*${QF::QF-base::intNest_} .................................................*/
  1302. /*! Interrupt nesting up-down counter (used in some QF ports )
  1303. * @static @private @memberof QF
  1304. */
  1305. extern uint_fast8_t volatile QF_intNest_;
  1306. /*${QF::QF-base::init} .....................................................*/
  1307. /*! QF initialization
  1308. * @static @public @memberof QF
  1309. *
  1310. * @details
  1311. * Initializes QF and must be called exactly once before any other QF
  1312. * function. Typcially, QF_init() is called from main() even before
  1313. * initializing the Board Support Package (BSP).
  1314. *
  1315. * @note
  1316. * QF_init() clears the internal QF variables, so that the framework
  1317. * can start correctly even if the startup code fails to clear the
  1318. * uninitialized data (as is required by the C Standard).
  1319. */
  1320. void QF_init(void);
  1321. /*${QF::QF-base::stop} .....................................................*/
  1322. /*! Function invoked by the application layer to stop the QF
  1323. * application and return control to the OS/Kernel.
  1324. * @static @public @memberof QF
  1325. *
  1326. * @details
  1327. * This function stops the QF application. After calling this function,
  1328. * QF attempts to gracefully stop the application. This graceful shutdown
  1329. * might take some time to complete. The typical use of this function is
  1330. * for terminating the QF application to return back to the operating
  1331. * system or for handling fatal errors that require shutting down
  1332. * (and possibly re-setting) the system.
  1333. *
  1334. * @attention
  1335. * After calling QF_stop() the application must terminate and cannot
  1336. * continue. In particular, QF_stop() is **not** intended to be followed
  1337. * by a call to QF_init() to "resurrect" the application.
  1338. *
  1339. * @sa QF_onCleanup()
  1340. */
  1341. void QF_stop(void);
  1342. /*${QF::QF-base::run} ......................................................*/
  1343. /*! Transfers control to QF to run the application.
  1344. * @static @public @memberof QF
  1345. *
  1346. * @details
  1347. * QF_run() is typically called from your startup code after you initialize
  1348. * the QF and start at least one active object with QACTIVE_START().
  1349. *
  1350. * @returns
  1351. * In QK, the QF_run() does not return.
  1352. */
  1353. int_t QF_run(void);
  1354. /*${QF::QF-base::psInit} ...................................................*/
  1355. /*! initialization of publish-subscribe
  1356. *
  1357. * @deprecated
  1358. * @sa QActive_psInit()
  1359. */
  1360. static inline void QF_psInit(
  1361. QSubscrList * const subscrSto,
  1362. enum_t const maxSignal)
  1363. {
  1364. QActive_psInit(subscrSto, maxSignal);
  1365. }
  1366. /*${QF::QF-base::getQueueMin} ..............................................*/
  1367. /*! This function returns the minimum of free entries of
  1368. * the given event queue.
  1369. * @static @public @memberof QF
  1370. *
  1371. * @details
  1372. * Queries the minimum of free ever present in the given event queue of
  1373. * an active object with priority `prio`, since the active object
  1374. * was started.
  1375. *
  1376. * @note
  1377. * This function is available only when the native QF event queue
  1378. * implementation is used. Requesting the queue minimum of an unused
  1379. * priority level raises an assertion in the QF. (A priority level becomes
  1380. * used in QF after the call to the QActive_register_() function.)
  1381. *
  1382. * @param[in] prio Priority of the active object, whose queue is queried
  1383. *
  1384. * @returns
  1385. * the minimum of free ever present in the given event queue of an active
  1386. * object with priority `prio`, since the active object was started.
  1387. */
  1388. uint_fast16_t QF_getQueueMin(uint_fast8_t const prio);
  1389. /*${QF::QF-base::onStartup} ................................................*/
  1390. /*! Startup QF callback.
  1391. * @static @public @memberof QF
  1392. *
  1393. * @details
  1394. * The purpose of the QF_onStartup() callback is to configure and enable
  1395. * hardware interrupts. The callback is invoked from QF_run(), right before
  1396. * starting the underlying real-time kernel. By that time, the application
  1397. * is considered ready to receive and service interrupts.
  1398. *
  1399. * This function is application-specific and is not implemented in QF, but
  1400. * rather in the Board Support Package (BSP) for the given application.
  1401. */
  1402. void QF_onStartup(void);
  1403. /*${QF::QF-base::onCleanup} ................................................*/
  1404. /*! Cleanup QF callback.
  1405. * @static @public @memberof QF
  1406. *
  1407. * @details
  1408. * QF_onCleanup() is called in some QF ports before QF returns to the
  1409. * underlying real-time kernel or operating system.
  1410. *
  1411. * This function is strongly platform-specific and is not implemented in
  1412. * the QF, but either in the QF port or in the Board Support Package (BSP)
  1413. * for the given application. Some QF ports might not require implementing
  1414. * QF_onCleanup() at all, because many embedded applications don't have
  1415. * anything to exit to.
  1416. *
  1417. * @sa QF_stop()
  1418. */
  1419. void QF_onCleanup(void);
  1420. /*$enddecl${QF::QF-base} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
  1421. /*$declare${QF::QF-dyn} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
  1422. /*${QF::QF-dyn::poolInit} ..................................................*/
  1423. /*! Event pool initialization for dynamic allocation of events.
  1424. * @static @public @memberof QF
  1425. *
  1426. * @details
  1427. * This function initializes one event pool at a time and must be called
  1428. * exactly once for each event pool before the pool can be used.
  1429. *
  1430. * @param[in] poolSto pointer to the storage for the event pool
  1431. * @param[in] poolSize size of the storage for the pool in bytes
  1432. * @param[in] evtSize the block-size of the pool in bytes, which determines
  1433. * the maximum size of events that can be allocated from the pool.
  1434. *
  1435. * @attention
  1436. * You might initialize many event pools by making many consecutive calls
  1437. * to the QF_poolInit() function. However, for the simplicity of the internal
  1438. * implementation, you must initialize event pools in the **ascending order**
  1439. * of the event size.
  1440. *
  1441. * Many RTOSes provide fixed block-size heaps, a.k.a. memory pools that can
  1442. * be adapted for QF event pools. In case such support is missing, QF provides
  1443. * a native QF event pool implementation. The macro #QF_EPOOL_TYPE_ determines
  1444. * the type of event pool used by a particular QF port. See structure ::QMPool
  1445. * for more information.
  1446. *
  1447. * @note The actual number of events available in the pool might be actually
  1448. * less than (`poolSize` / `evtSize`) due to the internal alignment
  1449. * of the blocks that the pool might perform. You can always check the
  1450. * capacity of the pool by calling QF_getPoolMin().
  1451. *
  1452. * @note The dynamic allocation of events is optional, meaning that you
  1453. * might choose not to use dynamic events. In that case calling QF_poolInit()
  1454. * and using up memory for the memory blocks is unnecessary.
  1455. *
  1456. * @sa QF initialization example for QF_init()
  1457. */
  1458. void QF_poolInit(
  1459. void * const poolSto,
  1460. uint_fast32_t const poolSize,
  1461. uint_fast16_t const evtSize);
  1462. /*${QF::QF-dyn::poolGetMaxBlockSize} .......................................*/
  1463. /*! Obtain the block size of any registered event pools.
  1464. * @static @public @memberof QF
  1465. *
  1466. * @details
  1467. * Obtain the block size of any registered event pools
  1468. */
  1469. uint_fast16_t QF_poolGetMaxBlockSize(void);
  1470. /*${QF::QF-dyn::getPoolMin} ................................................*/
  1471. /*! Obtain the minimum of free entries of the given event pool.
  1472. * @static @public @memberof QF
  1473. *
  1474. * @details
  1475. * This function obtains the minimum number of free blocks in the given
  1476. * event pool since this pool has been initialized by a call to QF_poolInit().
  1477. *
  1478. * @param[in] poolId event pool ID in the range 1..QF_maxPool_, where
  1479. * QF_maxPool_ is the number of event pools initialized
  1480. * with the function QF_poolInit().
  1481. *
  1482. * @returns
  1483. * the minimum number of unused blocks in the given event pool.
  1484. */
  1485. uint_fast16_t QF_getPoolMin(uint_fast8_t const poolId);
  1486. /*${QF::QF-dyn::newX_} .....................................................*/
  1487. /*! Internal QF implementation of creating new dynamic event.
  1488. * @static @private @memberof QF
  1489. *
  1490. * @details
  1491. * Allocates an event dynamically from one of the QF event pools.
  1492. *
  1493. * @param[in] evtSize the size (in bytes) of the event to allocate
  1494. * @param[in] margin the number of un-allocated events still available
  1495. * in a given event pool after the allocation completes.
  1496. * The special value ::QF_NO_MARGIN means that this function
  1497. * will assert if allocation fails.
  1498. * @param[in] sig the signal to be assigned to the allocated event
  1499. *
  1500. * @returns
  1501. * pointer to the newly allocated event. This pointer can be NULL only if
  1502. * margin != #QF_NO_MARGIN and the event cannot be allocated with the
  1503. * specified margin still available in the given pool.
  1504. *
  1505. * @note
  1506. * The internal QF function QF_newX_() raises an assertion when the
  1507. * `margin` parameter is #QF_NO_MARGIN and allocation of the event turns
  1508. * out to be impossible due to event pool depletion, or incorrect (too big)
  1509. * size of the requested event.
  1510. *
  1511. * @note
  1512. * The application code should not call this function directly.
  1513. * The only allowed use is thorough the macros Q_NEW() or Q_NEW_X().
  1514. */
  1515. QEvt * QF_newX_(
  1516. uint_fast16_t const evtSize,
  1517. uint_fast16_t const margin,
  1518. enum_t const sig);
  1519. /*${QF::QF-dyn::gc} ........................................................*/
  1520. /*! Recycle a dynamic event
  1521. * @static @public @memberof QF
  1522. *
  1523. * @details
  1524. * This function implements a simple garbage collector for the dynamic events.
  1525. * Only dynamic events are candidates for recycling. (A dynamic event is one
  1526. * that is allocated from an event pool, which is determined as non-zero
  1527. * e->poolId_ attribute.) Next, the function decrements the reference counter
  1528. * of the event (e->refCtr_), and recycles the event only if the counter drops
  1529. * to zero (meaning that no more references are outstanding for this event).
  1530. * The dynamic event is recycled by returning it to the pool from which
  1531. * it was originally allocated.
  1532. *
  1533. * @param[in] e pointer to the event to recycle
  1534. *
  1535. * @note
  1536. * QF invokes the garbage collector at all appropriate contexts, when
  1537. * an event can become garbage (automatic garbage collection), so the
  1538. * application code should have no need to call QF_gc() directly. The QF_gc()
  1539. * function is exposed only for special cases when your application sends
  1540. * dynamic events to the "raw" thread-safe queues (see ::QEQueue). Such
  1541. * queues are processed outside of QF and the automatic garbage collection
  1542. * is **NOT** performed for these events. In this case you need to call
  1543. * QF_gc() explicitly.
  1544. */
  1545. void QF_gc(QEvt const * const e);
  1546. /*${QF::QF-dyn::newRef_} ...................................................*/
  1547. /*! Internal QF implementation of creating new event reference.
  1548. * @static @private @memberof QF
  1549. *
  1550. * @details
  1551. * Creates and returns a new reference to the current event e
  1552. *
  1553. * @param[in] e pointer to the current event
  1554. * @param[in] evtRef the event reference
  1555. *
  1556. * @returns
  1557. * the newly created reference to the event `e`
  1558. *
  1559. * @note
  1560. * The application code should not call this function directly.
  1561. * The only allowed use is thorough the macro Q_NEW_REF().
  1562. */
  1563. QEvt const * QF_newRef_(
  1564. QEvt const * const e,
  1565. void const * const evtRef);
  1566. /*${QF::QF-dyn::deleteRef_} ................................................*/
  1567. /*! Internal QF implementation of deleting event reference.
  1568. * @static @private @memberof QF
  1569. *
  1570. * @details
  1571. * Deletes an existing reference to the event e
  1572. *
  1573. * @param[in] evtRef the event reference
  1574. *
  1575. * @note
  1576. * The application code should not call this function directly.
  1577. * The only allowed use is thorough the macro Q_DELETE_REF().
  1578. */
  1579. void QF_deleteRef_(void const * const evtRef);
  1580. /*$enddecl${QF::QF-dyn} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
  1581. /*$declare${QF::QF-extern-C} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
  1582. /*${QF::QF-extern-C::onContextSw} ..........................................*/
  1583. #ifdef QF_ON_CONTEXT_SW
  1584. /*! QF context switch callback used in built-in kernels (QV, QK, QXK)
  1585. * @static @public @memberof QF
  1586. *
  1587. * @details
  1588. * This callback function provides a mechanism to perform additional
  1589. * custom operations when one of the built-in kernels switches context
  1590. * from one thread to another.
  1591. *
  1592. * @param[in] prev pointer to the previous thread (active object)
  1593. * (prev==0 means that `prev` was the idle loop)
  1594. * @param[in] next pointer to the next thread (active object)
  1595. * (next==0) means that `next` is the idle loop)
  1596. * @attention
  1597. * QF_onContextSw() is invoked with interrupts **disabled** and must also
  1598. * return with interrupts **disabled**.
  1599. *
  1600. * @note
  1601. * This callback is enabled by defining the macro #QF_ON_CONTEXT_SW.
  1602. *
  1603. * @include qf_oncontextsw.c
  1604. */
  1605. void QF_onContextSw(
  1606. QActive * prev,
  1607. QActive * next);
  1608. #endif /* def QF_ON_CONTEXT_SW */
  1609. /*$enddecl${QF::QF-extern-C} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
  1610. /*==========================================================================*/
  1611. /*$declare${QF-macros} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
  1612. /*${QF-macros::QF_NO_MARGIN} ...............................................*/
  1613. /*! Special value of margin that causes asserting failure in case
  1614. * event allocation or event posting fails
  1615. */
  1616. #define QF_NO_MARGIN ((uint_fast16_t)0xFFFFU)
  1617. /*${QF-macros::Q_PRIO} .....................................................*/
  1618. /*! Create a ::QPrioSpec object to specify priorty of an AO or a thread */
  1619. #define Q_PRIO(prio_, pthre_) ((QPrioSpec)((prio_) | ((pthre_) << 8U)))
  1620. /*${QF-macros::Q_NEW} ......................................................*/
  1621. #ifndef Q_EVT_CTOR
  1622. /*! Allocate a dynamic event (case when ::QEvt is a POD)
  1623. *
  1624. * @details
  1625. * The macro calls the internal QF function QF::newX_() with
  1626. * margin == ::QF_NO_MARGIN, which causes an assertion when the event
  1627. * cannot be successfully allocated.
  1628. *
  1629. * @param[in] evtT_ event type (class name) of the event to allocate
  1630. * @param[in] sig_ signal to assign to the newly allocated event
  1631. *
  1632. * @returns a valid event pointer cast to the type `evtT_`.
  1633. *
  1634. * @note
  1635. * If #Q_EVT_CTOR is defined, the Q_NEW() macro becomes variadic and
  1636. * takes all the arguments needed by the constructor of the event
  1637. * class being allocated. The constructor is then called by means
  1638. * of the placement-new operator.
  1639. *
  1640. * @usage
  1641. * The following example illustrates dynamic allocation of an event:
  1642. * @include qf_post.c
  1643. */
  1644. #define Q_NEW(evtT_, sig_) ((evtT_ *)QF_newX_((uint_fast16_t)sizeof(evtT_), \
  1645. QF_NO_MARGIN, (enum_t)(sig_)))
  1646. #endif /* ndef Q_EVT_CTOR */
  1647. /*${QF-macros::Q_NEW} ......................................................*/
  1648. #ifdef Q_EVT_CTOR
  1649. /*! Asserting allocate a dynamic event
  1650. * (case when ::QEvt is not a POD)
  1651. */
  1652. #define Q_NEW(evtT_, sig_, ...) \
  1653. (evtT_##_ctor((evtT_ *)QF_newX_((uint_fast16_t)sizeof(evtT_), \
  1654. QF_NO_MARGIN, (sig_)), (enum_t)(sig_), ##__VA_ARGS__))
  1655. #endif /* def Q_EVT_CTOR */
  1656. /*${QF-macros::Q_NEW_X} ....................................................*/
  1657. #ifndef Q_EVT_CTOR
  1658. /*! Non-asserting allocate a dynamic event (case when ::QEvt is a POD).
  1659. *
  1660. * @details
  1661. * This macro allocates a new event and sets the pointer `e_`, while
  1662. * leaving at least `margin_` of events still available in the pool
  1663. *
  1664. * @param[out] e_ pointer to the newly allocated event
  1665. * @param[in] evtT_ event type (class name) of the event to allocate
  1666. * @param[in] margin_ number of events that must remain available
  1667. * in the given pool after this allocation. The
  1668. * special value ::QF_NO_MARGIN causes asserting
  1669. * failure in case event allocation fails.
  1670. * @param[in] sig_ signal to assign to the newly allocated event
  1671. *
  1672. * @returns an event pointer cast to the type `evtT_` or NULL if the
  1673. * event cannot be allocated with the specified `margin`.
  1674. *
  1675. * @note
  1676. * If #Q_EVT_CTOR is defined, the Q_NEW_X() macro becomes variadic and
  1677. * takes all the arguments needed by the constructor of the event
  1678. * class being allocated. The constructor is then called by means
  1679. * of the placement-new operator.
  1680. *
  1681. * @usage
  1682. * The following example illustrates dynamic allocation of an event:
  1683. * @include qf_postx.c
  1684. */
  1685. #define Q_NEW_X(e_, evtT_, margin_, sig_) ((e_) = \
  1686. (evtT_ *)QF_newX_((uint_fast16_t)sizeof(evtT_), \
  1687. (margin_), (enum_t)(sig_)))
  1688. #endif /* ndef Q_EVT_CTOR */
  1689. /*${QF-macros::Q_NEW_X} ....................................................*/
  1690. #ifdef Q_EVT_CTOR
  1691. /*! Non-asserting allocate a dynamic event
  1692. * (case when ::QEvt is not a POD)
  1693. */
  1694. #define Q_NEW_X(e_, evtT_, margin_, sig_, ...) do { \
  1695. (e_) = (evtT_ *)QF_newX_((uint_fast16_t)sizeof(evtT_), \
  1696. (margin_), (enum_t)(sig_));\
  1697. if ((e_) != (evtT_ *)0) { \
  1698. evtT_##_ctor((e_), (enum_t)(sig_), ##__VA_ARGS__); \
  1699. } \
  1700. } while (false)
  1701. #endif /* def Q_EVT_CTOR */
  1702. /*${QF-macros::Q_NEW_REF} ..................................................*/
  1703. /*! Create a new reference of the current event `e`
  1704. *
  1705. * @details
  1706. * The current event processed by an active object is available only for
  1707. * the duration of the run-to-completion (RTC) step. After that step, the
  1708. * current event is no longer available and the framework might recycle
  1709. * (garbage-collect) the event. The macro Q_NEW_REF() explicitly creates
  1710. * a new reference to the current event that can be stored and used beyond
  1711. * the current RTC step, until the reference is explicitly recycled by
  1712. * means of the macro Q_DELETE_REF().
  1713. *
  1714. * @param[in,out] evtRef_ event reference to create
  1715. * @param[in] evtT_ event type (class name) of the event reference
  1716. *
  1717. * @usage
  1718. * The example **defer** in the directory `examples/win32/defer` illustrates
  1719. * the use of Q_NEW_REF()
  1720. *
  1721. * @sa Q_DELETE_REF()
  1722. */
  1723. #define Q_NEW_REF(evtRef_, evtT_) \
  1724. ((evtRef_) = (evtT_ const *)QF_newRef_(e, (evtRef_)))
  1725. /*${QF-macros::Q_DELETE_REF} ...............................................*/
  1726. /*! Delete the event reference
  1727. *
  1728. * @details
  1729. * Every event reference created with the macro Q_NEW_REF() needs to be
  1730. * eventually deleted by means of the macro Q_DELETE_REF() to avoid leaking
  1731. * the event.
  1732. *
  1733. * @param[in,out] evtRef_ event reference to delete
  1734. *
  1735. * @usage
  1736. * The example **defer** in the directory `examples/win32/defer` illustrates
  1737. * the use of Q_DELETE_REF()
  1738. *
  1739. * @sa Q_NEW_REF()
  1740. */
  1741. #define Q_DELETE_REF(evtRef_) do { \
  1742. QF_deleteRef_((evtRef_)); \
  1743. (evtRef_) = (void *)0; \
  1744. } while (false)
  1745. /*${QF-macros::QACTIVE_START} ..............................................*/
  1746. /*! Virtual call to start an active object.
  1747. *
  1748. * @details
  1749. * Starts execution of the AO and registers the AO with the framework.
  1750. *
  1751. * @param[in,out] me_ current instance pointer (see @ref oop)
  1752. * @param[in] prioSpec_ priority specification for the Active Object
  1753. * @param[in] qSto_ pointer to the storage for the ring buffer of the
  1754. * event queue (used only with the built-in ::QEQueue)
  1755. * @param[in] qLen_ length of the event queue (in events)
  1756. * @param[in] stkSto_ pointer to the stack storage (used only when
  1757. * per-AO stack is needed)
  1758. * @param[in] stkSize_ stack size (in bytes)
  1759. * @param[in] par_ pointer to the additional port-specific parameter(s)
  1760. * (might be NULL).
  1761. * @usage
  1762. * @include qf_start.c
  1763. */
  1764. #define QACTIVE_START(me_, prioSpec_, qSto_, qLen_, stkSto_, stkSize_, par_) do { \
  1765. Q_ASSERT((Q_HSM_UPCAST(me_))->vptr); \
  1766. (*((QActiveVtable const *)((Q_HSM_UPCAST(me_))->vptr))->start)( \
  1767. (QActive *)(me_), (prioSpec_), \
  1768. (qSto_), (qLen_), (stkSto_), (stkSize_), (par_)); \
  1769. } while (false)
  1770. /*${QF-macros::QACTIVE_POST} ...............................................*/
  1771. #ifdef Q_SPY
  1772. /*! Invoke the direct event posting facility QActive_post_()
  1773. *
  1774. * @details
  1775. * This macro asserts if the queue overflows and cannot accept the event.
  1776. *
  1777. * @param[in,out] me_ current instance pointer (see @ref oop)
  1778. * @param[in] e_ pointer to the event to post
  1779. * @param[in] sender_ pointer to the sender object.
  1780. *
  1781. * @note
  1782. * The `sendedr_` parameter is actually only used when QS tracing
  1783. * is enabled (macro #Q_SPY is defined). When QS software tracing is
  1784. * disenabled, the QACTIVE_POST() macro does not pass the `sender_`
  1785. * parameter, so the overhead of passing this extra parameter is entirely
  1786. * avoided.
  1787. *
  1788. * @note the pointer to the sender object is not necessarily a pointer
  1789. * to an active object. In fact, if QACTIVE_POST() is called from an
  1790. * interrupt or other context, you can create a unique object just to
  1791. * unambiguously identify the sender of the event.
  1792. *
  1793. * @sa QActive_post_()
  1794. */
  1795. #define QACTIVE_POST(me_, e_, sender_) \
  1796. ((void)(*((QActiveVtable const *)((Q_HSM_UPCAST(me_))->vptr))->post)(\
  1797. (me_), (e_), QF_NO_MARGIN, (sender_)))
  1798. #endif /* def Q_SPY */
  1799. /*${QF-macros::QACTIVE_POST} ...............................................*/
  1800. #ifndef Q_SPY
  1801. #define QACTIVE_POST(me_, e_, dummy) \
  1802. ((void)(*((QActiveVtable const *)((Q_HSM_UPCAST(me_))->vptr))->post)(\
  1803. (me_), (e_), QF_NO_MARGIN, (void *)0))
  1804. #endif /* ndef Q_SPY */
  1805. /*${QF-macros::QACTIVE_POST_X} .............................................*/
  1806. #ifdef Q_SPY
  1807. /*! Invoke the direct event posting facility QActive_post_()
  1808. * without delivery guarantee
  1809. *
  1810. * @details
  1811. * This macro does not assert if the queue overflows and cannot accept
  1812. * the event with the specified margin of free slots remaining.
  1813. *
  1814. * @param[in,out] me_ current instance pointer (see @ref oop)
  1815. * @param[in] e_ pointer to the event to post
  1816. * @param[in] margin_ the minimum free slots in the queue, which
  1817. * must still be available after posting the event.
  1818. * The special value ::QF_NO_MARGIN causes
  1819. * asserting failure in case event posting fails.
  1820. * @param[in] sender_ pointer to the sender object.
  1821. *
  1822. * @returns
  1823. * 'true' if the posting succeeded, and 'false' if the posting
  1824. * failed due to insufficient margin of free entries available in
  1825. * the queue.
  1826. *
  1827. * @note
  1828. * The `sender_` parameter is actually only used when QS tracing
  1829. * is enabled (macro #Q_SPY is defined). When QS software tracing is
  1830. * disabled, the POST_X() macro does not pass the `sender_` parameter,
  1831. * so the overhead of passing this extra parameter is entirely avoided.
  1832. *
  1833. * @note
  1834. * The pointer to the sender object is not necessarily a pointer
  1835. * to an active object. In fact, if POST_X() is called from an
  1836. * interrupt or other context, you can create a unique object just to
  1837. * unambiguously identify the sender of the event.
  1838. *
  1839. * @usage
  1840. * @include qf_postx.c
  1841. */
  1842. #define QACTIVE_POST_X(me_, e_, margin_, sender_) \
  1843. ((*((QActiveVtable const *)((Q_HSM_UPCAST(me_))->vptr))->post)((me_),\
  1844. (e_), (margin_), (sender_)))
  1845. #endif /* def Q_SPY */
  1846. /*${QF-macros::QACTIVE_POST_X} .............................................*/
  1847. #ifndef Q_SPY
  1848. #define QACTIVE_POST_X(me_, e_, margin_, dummy) \
  1849. ((*((QActiveVtable const *)((Q_HSM_UPCAST(me_))->vptr))->post)((me_),\
  1850. (e_), (margin_), (void *)0))
  1851. #endif /* ndef Q_SPY */
  1852. /*${QF-macros::QACTIVE_POST_LIFO} ..........................................*/
  1853. /*! Virtual call to post an event to an active object using the
  1854. * Last-In-First-Out (LIFO) policy.
  1855. *
  1856. * @param[in,out] me_ current instance pointer (see @ref oop)
  1857. * @param[in] e_ pointer to the event to post
  1858. */
  1859. #define QACTIVE_POST_LIFO(me_, e_) \
  1860. ((*((QActiveVtable const *)((Q_HSM_UPCAST(me_))->vptr))->postLIFO)( \
  1861. (me_), (e_)))
  1862. /*${QF-macros::QACTIVE_PUBLISH} ............................................*/
  1863. #ifdef Q_SPY
  1864. /*! Publish an event to all subscriber Active Objects.
  1865. *
  1866. * @details
  1867. * If #Q_SPY is defined, this macro calls QActive_publish_() with
  1868. * the `sender_` parameter to identify the publisher of the event.
  1869. * Otherwise, `sender_` is not used.
  1870. *
  1871. * @param[in] e_ pointer to the posted event
  1872. * @param[in] sender_ pointer to the sender object (actually used
  1873. * only when #Q_SPY is defined)
  1874. *
  1875. * @note
  1876. * The pointer to the `sender_` object is not necessarily a pointer
  1877. * to an active object. In fact, if QACTIVE_PUBLISH() is called from an
  1878. * interrupt or other context, you can create a unique object just to
  1879. * unambiguously identify the sender of the event.
  1880. *
  1881. * @sa QActive_publish_()
  1882. */
  1883. #define QACTIVE_PUBLISH(e_, sender_) \
  1884. (QActive_publish_((e_), (void const *)(sender_), (sender_)->prio))
  1885. #endif /* def Q_SPY */
  1886. /*${QF-macros::QACTIVE_PUBLISH} ............................................*/
  1887. #ifndef Q_SPY
  1888. #define QACTIVE_PUBLISH(e_, dummy) (QActive_publish_((e_), (void *)0, 0U))
  1889. #endif /* ndef Q_SPY */
  1890. /*${QF-macros::QTIMEEVT_TICK_X} ............................................*/
  1891. #ifdef Q_SPY
  1892. /*! Invoke the system clock tick processing QTimeEvt_tick_()
  1893. *
  1894. * @details
  1895. * This macro is the recommended way of invoking clock tick processing,
  1896. * because it provides the vital information for software tracing and
  1897. * avoids any overhead when the tracing is disabled.
  1898. *
  1899. * @param[in] tickRate_ clock tick rate to be serviced through this call
  1900. * @param[in] sender_ pointer to the sender object. This parameter
  1901. * is actually only used when QS software tracing is enabled
  1902. * (macro #Q_SPY is defined)
  1903. * @note
  1904. * When QS software tracing is disabled, the macro calls QTimeEvt_tick_()
  1905. * without the `sender` parameter, so the overhead of passing this
  1906. * extra parameter is entirely avoided.
  1907. *
  1908. * @note
  1909. * The pointer to the sender object is not necessarily a pointer
  1910. * to an active object. In fact, when QTIMEEVT_TICK_X() is called from
  1911. * an interrupt, you would create a unique object just to unambiguously
  1912. * identify the ISR as the sender of the time events.
  1913. *
  1914. * @sa QTimeEvt_tick_()
  1915. */
  1916. #define QTIMEEVT_TICK_X(tickRate_, sender_) \
  1917. (QTimeEvt_tick_((tickRate_), (sender_)))
  1918. #endif /* def Q_SPY */
  1919. /*${QF-macros::QTIMEEVT_TICK_X} ............................................*/
  1920. #ifndef Q_SPY
  1921. #define QTIMEEVT_TICK_X(tickRate_, dummy) \
  1922. (QTimeEvt_tick_((tickRate_), (void *)0))
  1923. #endif /* ndef Q_SPY */
  1924. /*${QF-macros::QTIMEEVT_TICK} ..............................................*/
  1925. /*! Invoke the system clock tick processing
  1926. * for tick rate 0
  1927. */
  1928. #define QTIMEEVT_TICK(sender_) QTIMEEVT_TICK_X(0U, (sender_))
  1929. /*${QF-macros::QF_CRIT_EXIT_NOP} ...........................................*/
  1930. #ifndef QF_CRIT_EXIT_NOP
  1931. /*! No-operation for exiting a critical section
  1932. *
  1933. * @details
  1934. * In some QF ports the critical section exit takes effect only on the
  1935. * next machine instruction. If this next instruction is another entry
  1936. * to a critical section, the critical section won't be really exited,
  1937. * but rather the two adjecent critical sections would be merged.
  1938. * The QF_CRIT_EXIT_NOP() macro contains minimal code required to
  1939. * prevent such merging of critical sections in such merging of
  1940. * critical sections in QF ports, in which it can occur.
  1941. */
  1942. #define QF_CRIT_EXIT_NOP() ((void)0)
  1943. #endif /* ndef QF_CRIT_EXIT_NOP */
  1944. /*${QF-macros::QF_TICK_X} ..................................................*/
  1945. /*! Invoke the system clock tick processing
  1946. *
  1947. * @deprecated
  1948. * superseded by QTIMEEVT_TICK_X()
  1949. */
  1950. #define QF_TICK_X(tickRate_, sender_) QTIMEEVT_TICK_X((tickRate_), (sender_))
  1951. /*${QF-macros::QF_TICK} ....................................................*/
  1952. /*! Invoke the system clock tick processing for tick rate 0
  1953. *
  1954. * @deprecated
  1955. * superseded by QTIMEEVT_TICK()
  1956. */
  1957. #define QF_TICK(sender_) QTIMEEVT_TICK(sender_)
  1958. /*${QF-macros::QF_PUBLISH} .................................................*/
  1959. /*! Publish an event to all subscriber Active Objects.
  1960. *
  1961. * @deprecated
  1962. * superseded by QACTIVE_PUBLISH()
  1963. */
  1964. #define QF_PUBLISH(e_, sender_) QACTIVE_PUBLISH((e_), (sender_))
  1965. /*$enddecl${QF-macros} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
  1966. #endif /* QF_H_ */