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