qpc/include/qf.h

885 lines
32 KiB
C
Raw Normal View History

2014-04-06 11:43:13 -04:00
/**
2015-04-28 13:45:35 -04:00
* @file
* @brief QF/C platform-independent public interface.
* @ingroup qf
* @cond
2014-04-06 11:43:13 -04:00
******************************************************************************
2020-07-18 17:56:40 -04:00
* Last updated for version 6.8.2
* Last updated on 2020-07-14
2012-08-14 18:07:04 -04:00
*
2018-11-22 11:35:21 -05:00
* Q u a n t u m L e a P s
* ------------------------
* Modern Embedded Software
2012-08-14 18:07:04 -04:00
*
2019-02-10 21:00:39 -05:00
* Copyright (C) 2005-2019 Quantum Leaps, LLC. All rights reserved.
2012-08-14 18:07:04 -04:00
*
* This program is open source software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
2012-08-14 18:07:04 -04:00
* (at your option) any later version.
*
* Alternatively, this program may be distributed and modified under the
* terms of Quantum Leaps commercial licenses, which expressly supersede
* the GNU General Public License and are specifically designed for
* licensees interested in retaining the proprietary status of their code.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
2019-10-27 11:57:33 -04:00
* along with this program. If not, see <www.gnu.org/licenses>.
2012-08-14 18:07:04 -04:00
*
* Contact information:
2019-12-31 15:55:08 -05:00
* <www.state-machine.com/licensing>
2019-10-27 11:57:33 -04:00
* <info@state-machine.com>
2014-04-06 11:43:13 -04:00
******************************************************************************
2015-04-28 13:45:35 -04:00
* @endcond
2014-04-06 11:43:13 -04:00
*/
2019-10-27 11:57:33 -04:00
#ifndef QF_H
#define QF_H
2012-08-14 18:07:04 -04:00
2019-10-27 11:57:33 -04:00
#ifndef QPSET_H
2016-09-29 18:08:33 -04:00
#include "qpset.h"
2012-08-14 18:07:04 -04:00
#endif
2016-09-29 18:08:33 -04:00
/****************************************************************************/
2012-08-14 18:07:04 -04:00
#ifndef QF_EVENT_SIZ_SIZE
2014-04-06 11:43:13 -04:00
/*! Default value of the macro configurable value in qf_port.h */
2020-03-17 21:33:20 -04:00
#define QF_EVENT_SIZ_SIZE 2U
2012-08-14 18:07:04 -04:00
#endif
2020-03-17 21:33:20 -04:00
#if (QF_EVENT_SIZ_SIZE == 1U)
2013-09-23 14:34:35 -04:00
typedef uint8_t QEvtSize;
2020-03-17 21:33:20 -04:00
#elif (QF_EVENT_SIZ_SIZE == 2U)
2014-04-06 11:43:13 -04:00
/*! The data type to store the block-size defined based on
* the macro #QF_EVENT_SIZ_SIZE. */
/**
2012-08-14 18:07:04 -04:00
* The dynamic range of this data type determines the maximum block
* size that can be managed by the pool.
*/
typedef uint16_t QEvtSize;
2020-03-17 21:33:20 -04:00
#elif (QF_EVENT_SIZ_SIZE == 4U)
2012-08-14 18:07:04 -04:00
typedef uint32_t QEvtSize;
#else
#error "QF_EVENT_SIZ_SIZE defined incorrectly, expected 1, 2, or 4"
#endif
#ifndef QF_MAX_EPOOL
2014-04-06 11:43:13 -04:00
/*! Default value of the macro configurable value in qf_port.h */
2020-03-17 21:33:20 -04:00
#define QF_MAX_EPOOL 3U
2012-08-14 18:07:04 -04:00
#endif
2013-09-23 14:34:35 -04:00
#ifndef QF_MAX_TICK_RATE
2018-08-13 11:30:18 -04:00
/*! Default value of the macro configurable value in qf_port.h.
2020-03-17 21:33:20 -04:00
* Valid values: [0U..15U]; default 1
2018-08-13 11:30:18 -04:00
*/
2020-03-17 21:33:20 -04:00
#define QF_MAX_TICK_RATE 1U
#elif (QF_MAX_TICK_RATE > 15U)
2018-08-13 11:30:18 -04:00
#error "QF_MAX_TICK_RATE exceeds the maximum of 15"
2013-09-23 14:34:35 -04:00
#endif
2012-08-14 18:07:04 -04:00
2013-09-23 14:34:35 -04:00
#ifndef QF_TIMEEVT_CTR_SIZE
2018-08-13 11:30:18 -04:00
/*! macro to override the default ::QTimeEvtCtr size.
* Valid values: 1, 2, or 4; default 2
2012-08-14 18:07:04 -04:00
*/
2020-10-01 12:48:48 -04:00
#define QF_TIMEEVT_CTR_SIZE 2U
2012-08-14 18:07:04 -04:00
#endif
/****************************************************************************/
2014-04-06 11:43:13 -04:00
struct QEQueue; /* forward declaration */
2016-11-30 18:14:20 -05:00
/****************************************************************************/
2020-07-18 17:56:40 -04:00
/*! Active Object base class (based on ::QHsm implementation)
* @extends QHsm
*/
2014-04-06 11:43:13 -04:00
/**
2015-04-28 13:45:35 -04:00
* @description
2014-04-06 11:43:13 -04:00
* Active objects in QP are encapsulated state machines (each embedding an
2013-09-23 14:34:35 -04:00
* event queue and a thread) that communicate with one another asynchronously
* by sending and receiving events. Within an active object, events are
2012-08-14 18:07:04 -04:00
* processed sequentially in a run-to-completion (RTC) fashion, while QF
* encapsulates all the details of thread-safe event exchange and queuing.
2015-05-01 08:40:16 -04:00
* @n@n
2016-11-30 18:14:20 -05:00
* ::QActive represents an active object that uses the QHsm-style
* implementation strategy for state machines. This strategy is tailored
* to manual coding, but it is also supported by the QM modeling tool.
* The resulting code is slower than in the ::QMsm style implementation
* strategy.
2012-08-14 18:07:04 -04:00
*
2015-04-28 13:45:35 -04:00
* @usage
2012-08-14 18:07:04 -04:00
* The following example illustrates how to derive an active object from
2016-11-30 18:14:20 -05:00
* ::QActive. Please note that the ::QActive member @c super is defined as the
2015-04-28 13:45:35 -04:00
* __first__ member of the derived struct (see @ref oop).
2016-11-30 18:14:20 -05:00
* @include qf_qactive.c
2012-08-14 18:07:04 -04:00
*/
2017-07-06 13:30:17 -04:00
typedef struct QActive {
2016-11-30 18:14:20 -05:00
QHsm super; /*!< inherits ::QHsm */
2012-08-14 18:07:04 -04:00
#ifdef QF_EQUEUE_TYPE
2014-04-06 11:43:13 -04:00
/*! OS-dependent event-queue type. */
/**
2015-04-28 13:45:35 -04:00
* @description
2012-08-14 18:07:04 -04:00
* The type of the queue depends on the underlying operating system or
* a kernel. Many kernels support "message queues" that can be adapted
* to deliver QF events to the active object. Alternatively, QF provides
* a native event queue implementation that can be used as well.
*
2017-08-21 18:20:16 -04:00
* @note
* The native QF event queue is configured by defining the macro
2012-08-14 18:07:04 -04:00
* #QF_EQUEUE_TYPE as ::QEQueue.
*/
QF_EQUEUE_TYPE eQueue;
#endif
#ifdef QF_OS_OBJECT_TYPE
2014-04-06 11:43:13 -04:00
/*! OS-dependent per-thread object. */
/**
2015-04-28 13:45:35 -04:00
* @description
2012-08-14 18:07:04 -04:00
* This data might be used in various ways, depending on the QF port.
* In some ports osObject is used to block the calling thread when
* the native QF queue is empty. In other QF ports the OS-dependent
* object might be used differently.
*/
QF_OS_OBJECT_TYPE osObject;
#endif
#ifdef QF_THREAD_TYPE
2014-04-06 11:43:13 -04:00
/*! OS-dependent representation of the thread of the active object. */
/**
2015-04-28 13:45:35 -04:00
* @description
2012-08-14 18:07:04 -04:00
* This data might be used in various ways, depending on the QF port.
* In some ports thread is used to store the thread handle. In other
* ports thread can be the pointer to the Thread-Local-Storage (TLS).
*/
QF_THREAD_TYPE thread;
#endif
2019-10-27 11:57:33 -04:00
#ifdef QXK_H /* QXK kernel used? */
2020-10-01 12:48:48 -04:00
/*! QXK dynamic priority (1..#QF_MAX_ACTIVE) of this AO/thread */
uint8_t dynPrio;
2017-08-21 18:20:16 -04:00
#endif
2020-10-01 12:48:48 -04:00
/*! QF priority (1..#QF_MAX_ACTIVE) of this active object. */
uint8_t prio;
2016-11-30 18:14:20 -05:00
} QActive;
2012-08-14 18:07:04 -04:00
2016-11-30 18:14:20 -05:00
/*! Virtual table for the ::QActive class */
2014-04-06 11:43:13 -04:00
typedef struct {
2019-10-27 11:57:33 -04:00
struct QHsmVtable super; /*!< inherits ::QHsmVtable */
2013-09-23 14:34:35 -04:00
2014-04-06 11:43:13 -04:00
/*! virtual function to start the active object (thread) */
2015-04-28 13:45:35 -04:00
/** @sa QACTIVE_START() */
2016-11-30 18:14:20 -05:00
void (*start)(QActive * const me, uint_fast8_t prio,
2020-03-17 21:33:20 -04:00
QEvt const * * const qSto, uint_fast16_t const qLen,
void * const stkSto, uint_fast16_t const stkSize,
2019-12-31 15:55:08 -05:00
void const * const par);
2013-09-23 14:34:35 -04:00
#ifdef Q_SPY
2014-04-06 11:43:13 -04:00
/*! virtual function to asynchronously post (FIFO) an event to an AO */
2015-04-28 13:45:35 -04:00
/** @sa QACTIVE_POST() and QACTIVE_POST_X() */
2016-11-30 18:14:20 -05:00
bool (*post)(QActive * const me, QEvt const * const e,
2014-04-06 11:43:13 -04:00
uint_fast16_t const margin, void const * const sender);
2013-09-23 14:34:35 -04:00
#else
2016-11-30 18:14:20 -05:00
bool (*post)(QActive * const me, QEvt const * const e,
2014-04-06 11:43:13 -04:00
uint_fast16_t const margin);
2013-09-23 14:34:35 -04:00
#endif
2014-04-06 11:43:13 -04:00
/*! virtual function to asynchronously post (LIFO) an event to an AO */
2015-04-28 13:45:35 -04:00
/** @sa QACTIVE_POST_LIFO() */
2016-11-30 18:14:20 -05:00
void (*postLIFO)(QActive * const me, QEvt const * const e);
2013-09-23 14:34:35 -04:00
2019-10-27 11:57:33 -04:00
} QActiveVtable;
2013-09-23 14:34:35 -04:00
2020-07-18 17:56:40 -04:00
/* QActive public operations... */
/*! Polymorphically start an active object.
* @public @memberof QActive
*/
2014-04-06 11:43:13 -04:00
/**
2015-04-28 13:45:35 -04:00
* @description
* Starts execution of the AO and registers the AO with the framework.
2014-04-06 11:43:13 -04:00
*
2015-04-28 13:45:35 -04:00
* @param[in,out] me_ pointer (see @ref oop)
* @param[in] prio_ priority at which to start the active object
* @param[in] qSto_ pointer to the storage for the ring buffer of the
* event queue (used only with the built-in ::QEQueue)
* @param[in] qLen_ length of the event queue (in events)
* @param[in] stkSto_ pointer to the stack storage (used only when
* per-AO stack is needed)
* @param[in] stkSize_ stack size (in bytes)
2019-02-10 21:00:39 -05:00
* @param[in] par_ pointer to the additional port-specific parameter(s)
2015-04-28 13:45:35 -04:00
* (might be NULL).
2015-12-24 14:33:20 -05:00
* @usage
* @include qf_start.c
2013-09-23 14:34:35 -04:00
*/
2019-02-10 21:00:39 -05:00
#define QACTIVE_START(me_, prio_, qSto_, qLen_, stkSto_, stkLen_, par_) do { \
2020-07-18 17:56:40 -04:00
Q_ASSERT((Q_HSM_UPCAST(me_))->vptr); \
(*((QActiveVtable const *)((Q_HSM_UPCAST(me_))->vptr))->start)( \
(QActive *)(me_), (prio_), \
(qSto_), (qLen_), (stkSto_), (stkLen_), (par_)); \
2019-12-31 15:55:08 -05:00
} while (false)
2012-08-14 18:07:04 -04:00
2013-09-23 14:34:35 -04:00
#ifdef Q_SPY
2014-04-06 11:43:13 -04:00
/*! Polymorphically posts an event to an active object (FIFO)
2020-07-18 17:56:40 -04:00
* with delivery guarantee.
* @public @memberof QActive
*/
2014-04-06 11:43:13 -04:00
/**
2015-04-28 13:45:35 -04:00
* @description
2013-09-23 14:34:35 -04:00
* This macro asserts if the queue overflows and cannot accept the event.
2012-08-14 18:07:04 -04:00
*
2015-04-28 13:45:35 -04:00
* @param[in,out] me_ pointer (see @ref oop)
* @param[in] e_ pointer to the event to post
* @param[in] sender_ pointer to the sender object.
2014-04-06 11:43:13 -04:00
*
2017-08-21 18:20:16 -04:00
* @note
* The @p sendedr_ parameter is actually only used when QS tracing
2014-04-06 11:43:13 -04:00
* is enabled (macro #Q_SPY is defined). When QS software tracing is
2015-04-28 13:45:35 -04:00
* disenabled, the QACTIVE_POST() macro does not pass the @p sender_
2014-04-06 11:43:13 -04:00
* argument, so the overhead of passing this extra argument is entirely
* avoided.
2012-08-14 18:07:04 -04:00
*
2017-08-21 18:20:16 -04:00
* @note
* The pointer to the sender object is not necessarily a pointer
2012-08-14 18:07:04 -04:00
* to an active object. In fact, if QACTIVE_POST() is called from an
* interrupt or other context, you can create a unique object just to
2013-09-23 14:34:35 -04:00
* unambiguously identify the sender of the event.
2012-08-14 18:07:04 -04:00
*
2015-04-28 13:45:35 -04:00
* @sa #QACTIVE_POST_X, QActive_post_().
2012-08-14 18:07:04 -04:00
*/
2020-07-18 17:56:40 -04:00
#define QACTIVE_POST(me_, e_, sender_) \
((void)(*((QActiveVtable const *)((Q_HSM_UPCAST(me_))->vptr))->post)(\
(me_), (e_), QF_NO_MARGIN, (sender_)))
2014-04-06 11:43:13 -04:00
/*! Polymorphically posts an event to an active object (FIFO)
2020-07-18 17:56:40 -04:00
* without delivery guarantee.
* @public @memberof QActive
*/
2014-04-06 11:43:13 -04:00
/**
2015-04-28 13:45:35 -04:00
* @description
2014-04-06 11:43:13 -04:00
* This macro does not assert if the queue overflows and cannot accept
* the event with the specified margin of free slots remaining.
*
2015-04-28 13:45:35 -04:00
* @param[in,out] me_ pointer (see @ref oop)
* @param[in] e_ pointer to the event to post
* @param[in] margin_ the minimum free slots in the queue, which
2017-06-19 11:45:15 -04:00
* must still be available after posting the event.
* The special value #QF_NO_MARGIN causes asserting failure
* in case event allocation fails.
2015-04-28 13:45:35 -04:00
* @param[in] sender_ pointer to the sender object.
2014-04-06 11:43:13 -04:00
*
2015-04-28 13:45:35 -04:00
* @returns 'true' if the posting succeeded, and 'false' if the posting
2014-04-06 11:43:13 -04:00
* failed due to insufficient margin of free slots available in the queue.
*
2017-08-21 18:20:16 -04:00
* @note
* The @p sender_ parameter is actually only used when QS tracing
2014-04-06 11:43:13 -04:00
* is enabled (macro #Q_SPY is defined). When QS software tracing is
2015-04-28 13:45:35 -04:00
* disabled, the QACTIVE_POST() macro does not pass the @p sender_
2014-04-06 11:43:13 -04:00
* argument, so the overhead of passing this extra argument is entirely
* avoided.
2013-09-23 14:34:35 -04:00
*
2017-08-21 18:20:16 -04:00
* @note
* The pointer to the sender object is not necessarily a pointer
2017-06-19 11:45:15 -04:00
* to an active object. In fact, if QACTIVE_POST_X() is called from an
2013-09-23 14:34:35 -04:00
* interrupt or other context, you can create a unique object just to
* unambiguously identify the sender of the event.
*
2015-04-28 13:45:35 -04:00
* @usage
* @include qf_postx.c
2013-09-23 14:34:35 -04:00
*/
2020-07-18 17:56:40 -04:00
#define QACTIVE_POST_X(me_, e_, margin_, sender_) \
((*((QActiveVtable const *)((Q_HSM_UPCAST(me_))->vptr))->post)((me_),\
2013-09-23 14:34:35 -04:00
(e_), (margin_), (sender_)))
2012-08-14 18:07:04 -04:00
#else
2020-07-18 17:56:40 -04:00
#define QACTIVE_POST(me_, e_, sender_) \
((void)(*((QActiveVtable const *)((Q_HSM_UPCAST(me_))->vptr))->post)(\
(me_), (e_), QF_NO_MARGIN))
2013-09-23 14:34:35 -04:00
2020-07-18 17:56:40 -04:00
#define QACTIVE_POST_X(me_, e_, margin_, sender_) \
((*((QActiveVtable const *)((Q_HSM_UPCAST(me_))->vptr))->post)( \
(me_), (e_), (margin_)))
2013-09-23 14:34:35 -04:00
2012-08-14 18:07:04 -04:00
#endif
2014-04-06 11:43:13 -04:00
/*! Polymorphically posts an event to an active object using the
2020-07-18 17:56:40 -04:00
* Last-In-First-Out (LIFO) policy.
* @public @memberof QActive
*/
2014-04-06 11:43:13 -04:00
/**
2015-04-28 13:45:35 -04:00
* @param[in,out] me_ pointer (see @ref oop)
* @param[in] e_ pointer to the event to post
2013-09-23 14:34:35 -04:00
*/
2020-07-18 17:56:40 -04:00
#define QACTIVE_POST_LIFO(me_, e_) \
((*((QActiveVtable const *)((Q_HSM_UPCAST(me_))->vptr))->postLIFO)( \
(me_), (e_)))
2013-09-23 14:34:35 -04:00
2020-07-18 17:56:40 -04:00
/* QActive protected operations... */
/*! protected "constructor" of an ::QActive active object
* @protected @memberof QActive
*/
void QActive_ctor(QActive * const me, QStateHandler initial);
2012-08-14 18:07:04 -04:00
2019-03-28 11:58:16 -04:00
#ifdef QF_ACTIVE_STOP
/*! Stops execution of an active object and removes it from the
2020-07-18 17:56:40 -04:00
* framework's supervision.
* @protected @memberof QActive
*/
/** @attention
* QActive_stop() must be called only from the AO that is about
* to stop its execution. By that time, any pointers or references
* to the AO are considered invalid (dangling) and it becomes
* illegal for the rest of the application to post events to the AO.
*/
2019-03-28 11:58:16 -04:00
void QActive_stop(QActive * const me);
#endif
2020-07-18 17:56:40 -04:00
/*! Subscribes for delivery of signal @p sig to the active object @p me.
* @protected @memberof QActive
*/
2012-08-14 18:07:04 -04:00
void QActive_subscribe(QActive const * const me, enum_t const sig);
2020-07-18 17:56:40 -04:00
/*! Un-subscribes from the delivery of signal @p sig to the AO @p me.
* @protected @memberof QActive
*/
2012-08-14 18:07:04 -04:00
void QActive_unsubscribe(QActive const * const me, enum_t const sig);
2020-07-18 17:56:40 -04:00
/*! Un-subscribes from the delivery of all signals to the AO @p me.
* @protected @memberof QActive
*/
2012-08-14 18:07:04 -04:00
void QActive_unsubscribeAll(QActive const * const me);
2020-07-18 17:56:40 -04:00
/*! Defer an event @p e to a given event queue @p eq.
* @protected @memberof QActive
*/
2016-11-30 18:14:20 -05:00
bool QActive_defer(QActive const * const me,
2014-04-06 11:43:13 -04:00
QEQueue * const eq, QEvt const * const e);
2012-08-14 18:07:04 -04:00
2020-07-18 17:56:40 -04:00
/*! Recall a deferred event from a given event queue @p eq.
* @protected @memberof QActive
*/
2016-11-30 18:14:20 -05:00
bool QActive_recall(QActive * const me, QEQueue * const eq);
2012-08-14 18:07:04 -04:00
2020-07-18 17:56:40 -04:00
/*! Flush the specified deferred queue @p eq.
* @protected @memberof QActive
*/
2016-11-30 18:14:20 -05:00
uint_fast16_t QActive_flushDeferred(QActive const * const me,
2016-02-10 16:50:22 -05:00
QEQueue * const eq);
2020-07-18 17:56:40 -04:00
/*! Generic setting of additional attributes (useful in QP ports)
* @protected @memberof QActive
*/
2018-01-10 18:27:33 -05:00
void QActive_setAttr(QActive *const me, uint32_t attr1, void const *attr2);
2016-11-30 18:14:20 -05:00
/****************************************************************************/
2020-07-18 17:56:40 -04:00
/*! QMActive active object base class (based on ::QMsm implementation)
* @extends QActvie
*/
2016-11-30 18:14:20 -05:00
/**
* @description
* QMActive represents an active object that uses the ::QMsm style state
* machine implementation strategy. This strategy requires the use of the
* QM modeling tool to generate state machine code automatically, but the
* code is faster than in the ::QHsm style implementation strategy and needs
* less run-time support (smaller event-processor).
*
* @note
* ::QMActive is not intended to be instantiated directly, but rather serves
* as the base class for derivation of active objects in the application.
*
* @sa ::QActive
*
* @usage
* The following example illustrates how to derive an active object from
* ::QMActive. Please note that the ::QActive member @c super is defined as
* the __first__ member of the derived struct (see @ref oop).
* @include qf_qmactive.c
*/
2020-07-18 17:56:40 -04:00
typedef struct {
QActive super; /*!< inherits ::QActive */
} QMActive;
2016-11-30 18:14:20 -05:00
2019-10-27 11:57:33 -04:00
/*! Virtual Table for the ::QMActive class (inherited from ::QActiveVtable */
2016-11-30 18:14:20 -05:00
/**
* @note
* ::QMActive inherits ::QActive exactly, without adding any new virtual
2019-10-27 11:57:33 -04:00
* functions and therefore, ::QMActiveVtable is typedef'ed as ::QActiveVtable.
2016-11-30 18:14:20 -05:00
*/
2019-10-27 11:57:33 -04:00
typedef QActiveVtable QMActiveVtable;
2016-11-30 18:14:20 -05:00
2020-07-18 17:56:40 -04:00
/* QMActive protected operations... */
/*! protected "constructor" of an ::QMActive active object.
* @protected @memberof QMActive
*/
2016-11-30 18:14:20 -05:00
void QMActive_ctor(QMActive * const me, QStateHandler initial);
2012-08-14 18:07:04 -04:00
2013-09-23 14:34:35 -04:00
/****************************************************************************/
2020-03-17 21:33:20 -04:00
#if (QF_TIMEEVT_CTR_SIZE == 1U)
2013-09-23 14:34:35 -04:00
typedef uint8_t QTimeEvtCtr;
2020-03-17 21:33:20 -04:00
#elif (QF_TIMEEVT_CTR_SIZE == 2U)
2012-08-14 18:07:04 -04:00
2014-04-06 11:43:13 -04:00
/*! type of the Time Event counter, which determines the dynamic
* range of the time delays measured in clock ticks. */
/**
2015-04-28 13:45:35 -04:00
* @description
2012-08-14 18:07:04 -04:00
* This typedef is configurable via the preprocessor switch
* #QF_TIMEEVT_CTR_SIZE. The other possible values of this type are
2015-04-28 13:45:35 -04:00
* as follows: @n
2020-03-17 21:33:20 -04:00
* uint8_t when (QF_TIMEEVT_CTR_SIZE == 1U), and @n
* uint32_t when (QF_TIMEEVT_CTR_SIZE == 4U).
2012-08-14 18:07:04 -04:00
*/
typedef uint16_t QTimeEvtCtr;
2020-03-17 21:33:20 -04:00
#elif (QF_TIMEEVT_CTR_SIZE == 4U)
2012-08-14 18:07:04 -04:00
typedef uint32_t QTimeEvtCtr;
#else
#error "QF_TIMEEVT_CTR_SIZE defined incorrectly, expected 1, 2, or 4"
#endif
2020-07-18 17:56:40 -04:00
/*! Time Event class
* @extends QEvt
*/
2014-04-06 11:43:13 -04:00
/**
2015-04-28 13:45:35 -04:00
* @description
2012-08-14 18:07:04 -04:00
* Time events are special QF events equipped with the notion of time passage.
* The basic usage model of the time events is as follows. An active object
2016-11-30 18:14:20 -05:00
* allocates one or more ::QTimeEvt objects (provides the storage for them).
2012-08-14 18:07:04 -04:00
* When the active object needs to arrange for a timeout, it arms one of its
* time events to fire either just once (one-shot) or periodically. Each time
* event times out independently from the others, so a QF application can make
* multiple parallel timeout requests (from the same or different active
* objects). When QF detects that the appropriate moment has arrived, it
* inserts the time event directly into the recipient's event queue. The
* recipient then processes the time event just like any other event.
*
* Time events, as any other QF events derive from the ::QEvt base structure.
2012-08-14 18:07:04 -04:00
* Typically, you will use a time event as-is, but you can also further
* derive more specialized time events from it by adding some more data
* members and/or specialized functions that operate on the specialized
* time events.
*
2013-09-23 14:34:35 -04:00
* Internally, the armed time events are organized into linked lists--one list
* for every supported ticking rate. These linked lists are scanned in every
2013-12-30 17:37:40 -05:00
* invocation of the QF_tickX_() function. Only armed (timing out) time events
2013-09-23 14:34:35 -04:00
* are in the list, so only armed time events consume CPU cycles.
2012-08-14 18:07:04 -04:00
*
2015-04-28 13:45:35 -04:00
* @sa ::QTimeEvt for the description of the data members @n @ref oop
2012-08-14 18:07:04 -04:00
*
2017-08-21 18:20:16 -04:00
* @note
* QF manages the time events in the function QF_tickX_(), which must be called
* periodically, from the clock tick ISR or from the special ::QTicker
* active object.
2012-08-14 18:07:04 -04:00
*
2017-08-21 18:20:16 -04:00
* @note
* Even though ::QTimeEvt is a subclass of ::QEvt, ::QTimeEvt instances can NOT
* be allocated dynamically from event pools. In other words, it is illegal to
* allocate ::QTimeEvt instances with the Q_NEW() or Q_NEW_X() macros.
2012-08-14 18:07:04 -04:00
*/
2014-04-06 11:43:13 -04:00
typedef struct QTimeEvt {
2016-11-30 18:14:20 -05:00
QEvt super; /*<! inherits ::QEvt */
2012-08-14 18:07:04 -04:00
2014-04-06 11:43:13 -04:00
/*! link to the next time event in the list */
struct QTimeEvt * volatile next;
2012-08-14 18:07:04 -04:00
2014-04-06 11:43:13 -04:00
/*! the active object that receives the time events */
2013-09-23 14:34:35 -04:00
void * volatile act;
2012-08-14 18:07:04 -04:00
2014-04-06 11:43:13 -04:00
/*! the internal down-counter of the time event. */
/**
2015-04-28 13:45:35 -04:00
* @description
2014-04-06 11:43:13 -04:00
* The down-counter is decremented by 1 in every QF_tickX_() invocation.
* The time event fires (gets posted or published) when the down-counter
* reaches zero.
2012-08-14 18:07:04 -04:00
*/
2013-09-23 14:34:35 -04:00
QTimeEvtCtr volatile ctr;
2012-08-14 18:07:04 -04:00
2014-04-06 11:43:13 -04:00
/*! the interval for periodic time event (zero for one-shot time event) */
/**
2015-04-28 13:45:35 -04:00
* @description
2014-04-06 11:43:13 -04:00
* The value of the interval is re-loaded to the internal down-counter
* when the time event expires, so that the time event keeps timing out
* periodically.
2012-08-14 18:07:04 -04:00
*/
QTimeEvtCtr interval;
} QTimeEvt;
2020-07-18 17:56:40 -04:00
/* QTimeEvt public operations... */
2012-08-14 18:07:04 -04:00
2020-07-18 17:56:40 -04:00
/*! The extended "constructor" to initialize a Time Event.
* @public @memberof QTimeEvt
*/
2016-11-30 18:14:20 -05:00
void QTimeEvt_ctorX(QTimeEvt * const me, QActive * const act,
2014-04-06 11:43:13 -04:00
enum_t const sig, uint_fast8_t tickRate);
2012-08-14 18:07:04 -04:00
2020-07-18 17:56:40 -04:00
/*! Arm a time event (one shot or periodic) for direct event posting.
* @public @memberof QTimeEvt
*/
2013-09-23 14:34:35 -04:00
void QTimeEvt_armX(QTimeEvt * const me,
QTimeEvtCtr const nTicks, QTimeEvtCtr const interval);
2012-08-14 18:07:04 -04:00
2020-07-18 17:56:40 -04:00
/*! Rearm a time event.
* @public @memberof QTimeEvt
*/
2014-04-06 11:43:13 -04:00
bool QTimeEvt_rearm(QTimeEvt * const me, QTimeEvtCtr const nTicks);
2012-08-14 18:07:04 -04:00
2020-07-18 17:56:40 -04:00
/*! Disarm a time event.
* @public @memberof QTimeEvt
*/
2014-04-06 11:43:13 -04:00
bool QTimeEvt_disarm(QTimeEvt * const me);
2012-08-14 18:07:04 -04:00
2020-07-18 17:56:40 -04:00
/*! Check the "was disarmed" status of a time event.
* @public @memberof QTimeEvt
*/
2018-08-13 11:30:18 -04:00
bool QTimeEvt_wasDisarmed(QTimeEvt * const me);
2020-07-18 17:56:40 -04:00
/*! Get the current value of the down-counter of a time event.
* @public @memberof QTimeEvt
*/
2019-03-28 11:58:16 -04:00
QTimeEvtCtr QTimeEvt_currCtr(QTimeEvt const * const me);
2012-08-14 18:07:04 -04:00
2016-09-23 12:08:21 -04:00
2014-04-06 11:43:13 -04:00
/****************************************************************************/
/* QF facilities */
2012-08-14 18:07:04 -04:00
2014-04-06 11:43:13 -04:00
/*! Subscriber-List structure */
/**
2015-04-28 13:45:35 -04:00
* @description
2012-08-14 18:07:04 -04:00
* This data type represents a set of active objects that subscribe to
2016-09-29 18:08:33 -04:00
* a given signal. The set is represented as a priority-set, where each
2012-08-14 18:07:04 -04:00
* bit corresponds to the unique priority of an active object.
*
2015-04-28 13:45:35 -04:00
* @sa ::QSubscrList for the description of the data members
2012-08-14 18:07:04 -04:00
*/
2016-09-23 12:08:21 -04:00
typedef QPSet QSubscrList;
2012-08-14 18:07:04 -04:00
/* public functions */
2014-04-06 11:43:13 -04:00
/*! QF initialization. */
2012-08-14 18:07:04 -04:00
void QF_init(void);
2014-04-06 11:43:13 -04:00
/*! Publish-subscribe initialization. */
2013-12-30 17:37:40 -05:00
void QF_psInit(QSubscrList * const subscrSto, enum_t const maxSignal);
2012-08-14 18:07:04 -04:00
2014-04-06 11:43:13 -04:00
/*! Event pool initialization for dynamic allocation of events. */
2015-04-28 13:45:35 -04:00
void QF_poolInit(void * const poolSto, uint_fast32_t const poolSize,
2014-04-06 11:43:13 -04:00
uint_fast16_t const evtSize);
2012-08-14 18:07:04 -04:00
2015-09-04 12:08:22 -04:00
/*! Obtain the block size of any registered event pools */
uint_fast16_t QF_poolGetMaxBlockSize(void);
2014-04-06 11:43:13 -04:00
/*! Transfers control to QF to run the application. */
2013-12-30 17:37:40 -05:00
int_t QF_run(void);
2012-08-14 18:07:04 -04:00
2014-04-06 11:43:13 -04:00
/*! Function invoked by the application layer to stop the QF
* application and return control to the OS/Kernel. */
2012-08-14 18:07:04 -04:00
void QF_stop(void);
2014-04-06 11:43:13 -04:00
/*! Startup QF callback. */
/**
2015-04-28 13:45:35 -04:00
* @description
2012-08-14 18:07:04 -04:00
* The timeline for calling QF_onStartup() depends on the particular
* QF port. In most cases, QF_onStartup() is called from QF_run(), right
* before starting any multitasking kernel or the background loop.
*/
void QF_onStartup(void);
2014-04-06 11:43:13 -04:00
/*! Cleanup QF callback. */
/**
2015-04-28 13:45:35 -04:00
* @description
2012-08-14 18:07:04 -04:00
* QF_onCleanup() is called in some QF ports before QF returns to the
* underlying operating system or RTOS.
*
* This function is strongly platform-specific and is not implemented in
* the QF, but either in the QF port or in the Board Support Package (BSP)
* for the given application. Some QF ports might not require implementing
* QF_onCleanup() at all, because many embedded applications don't have
* anything to exit to.
*
2015-04-28 13:45:35 -04:00
* @sa QF_stop()
2012-08-14 18:07:04 -04:00
*/
void QF_onCleanup(void);
#ifdef Q_SPY
2014-04-06 11:43:13 -04:00
/*! Publish event to the framework. */
2013-12-30 17:37:40 -05:00
void QF_publish_(QEvt const * const e, void const * const sender);
2012-08-14 18:07:04 -04:00
2014-04-06 11:43:13 -04:00
/*! Invoke the event publishing facility QF_publish_(). */
/**
2015-04-28 13:45:35 -04:00
* @description
2014-04-06 11:43:13 -04:00
* This macro is the recommended way of publishing events, because it
* provides the vital information for software tracing and avoids any
* overhead when the tracing is disabled.
2012-08-14 18:07:04 -04:00
*
2015-04-28 13:45:35 -04:00
* @param[in] e_ pointer to the posted event
* @param[in] sender_ pointer to the sender object. This argument is
2014-04-06 11:43:13 -04:00
* actually only used when QS software tracing is enabled
* (macro #Q_SPY is defined). When QS software tracing is
* disabled, the macro calls QF_publish_() without the
2015-04-28 13:45:35 -04:00
* @p sender_ parameter, so the overhead of passing this
2014-04-06 11:43:13 -04:00
* extra argument is entirely avoided.
2012-08-14 18:07:04 -04:00
*
2017-08-21 18:20:16 -04:00
* @note
* the pointer to the sender object is not necessarily a pointer
2012-08-14 18:07:04 -04:00
* to an active object. In fact, if QF_PUBLISH() is called from an
* interrupt or other context, you can create a unique object just to
* unambiguously identify the publisher of the event.
*
2015-04-28 13:45:35 -04:00
* @sa QF_publish_().
2012-08-14 18:07:04 -04:00
*/
2013-02-12 10:04:39 -05:00
#define QF_PUBLISH(e_, sender_) \
2013-12-30 17:37:40 -05:00
(QF_publish_((e_), (void const *)(sender_)))
2012-08-14 18:07:04 -04:00
#else
2013-12-30 17:37:40 -05:00
void QF_publish_(QEvt const * const e);
#define QF_PUBLISH(e_, dummy_) (QF_publish_(e_))
2012-08-14 18:07:04 -04:00
#endif
#ifdef Q_SPY
2014-04-06 11:43:13 -04:00
/*! Processes all armed time events at every clock tick. */
void QF_tickX_(uint_fast8_t const tickRate, void const * const sender);
/*! Invoke the system clock tick processing QF_tickX_(). */
/**
2015-04-28 13:45:35 -04:00
* @description
2014-04-06 11:43:13 -04:00
* This macro is the recommended way of invoking clock tick processing,
* because it provides the vital information for software tracing and
* avoids any overhead when the tracing is disabled.
*
2020-07-18 17:56:40 -04:00
* @param[in] tickRate_ clock tick rate to be serviced through this call
* @param[in] sender_ pointer to the sender object. This argument
2014-04-06 11:43:13 -04:00
* is actually only used when QS software tracing is enabled
* (macro #Q_SPY is defined)
2015-04-28 13:45:35 -04:00
* @note
2014-04-06 11:43:13 -04:00
* When QS software tracing is disabled, the macro calls QF_tickX_()
2015-04-28 13:45:35 -04:00
* without the @p sender parameter, so the overhead of passing this
2014-04-06 11:43:13 -04:00
* extra argument is entirely avoided.
2012-08-14 18:07:04 -04:00
*
2015-04-28 13:45:35 -04:00
* @note
* The pointer to the sender object is not necessarily a pointer
2013-09-23 14:34:35 -04:00
* to an active object. In fact, when #QF_TICK_X() is called from
* an interrupt, you would create a unique object just to unambiguously
* identify the ISR as the sender of the time events.
2012-08-14 18:07:04 -04:00
*
2015-12-24 14:33:20 -05:00
* @usage
* The following example shows how to invoke QF_TICK_X() for different
* system tick rates:
* @include qf_tickx.c
*
2015-04-28 13:45:35 -04:00
* @sa QF_tickX_().
2012-08-14 18:07:04 -04:00
*/
2013-12-30 17:37:40 -05:00
#define QF_TICK_X(tickRate_, sender_) (QF_tickX_((tickRate_), (sender_)))
2012-08-14 18:07:04 -04:00
#else
2014-04-06 11:43:13 -04:00
void QF_tickX_(uint_fast8_t const tickRate);
2013-12-30 17:37:40 -05:00
#define QF_TICK_X(tickRate_, dummy) (QF_tickX_(tickRate_))
2012-08-14 18:07:04 -04:00
#endif
2017-06-19 11:45:15 -04:00
/*! special value of margin that causes asserting failure in case
* event allocation or event posting fails
*/
2020-03-17 21:33:20 -04:00
#define QF_NO_MARGIN ((uint_fast16_t)0xFFFFU)
2017-06-19 11:45:15 -04:00
2014-04-06 11:43:13 -04:00
/*! Invoke the system clock tick processing for rate 0 */
2020-03-17 21:33:20 -04:00
#define QF_TICK(sender_) QF_TICK_X(0U, (sender_))
2013-12-30 17:37:40 -05:00
2014-04-06 11:43:13 -04:00
/*! Returns 'true' if there are no armed time events at a given tick rate */
bool QF_noTimeEvtsActiveX(uint_fast8_t const tickRate);
2012-08-14 18:07:04 -04:00
2014-04-06 11:43:13 -04:00
/*! Register an active object to be managed by the framework */
2016-11-30 18:14:20 -05:00
void QF_add_(QActive * const a);
2012-08-14 18:07:04 -04:00
2014-04-06 11:43:13 -04:00
/*! Remove the active object from the framework. */
2016-11-30 18:14:20 -05:00
void QF_remove_(QActive * const a);
2012-08-14 18:07:04 -04:00
2014-04-06 11:43:13 -04:00
/*! Obtain the minimum of free entries of the given event pool. */
uint_fast16_t QF_getPoolMin(uint_fast8_t const poolId);
2012-08-14 18:07:04 -04:00
2014-04-06 11:43:13 -04:00
/*! This function returns the minimum of free entries of
* the given event queue. */
uint_fast16_t QF_getQueueMin(uint_fast8_t const prio);
2012-08-14 18:07:04 -04:00
2018-03-19 14:49:36 -04:00
/*! Internal QF implementation of creating new dynamic event. */
2014-04-06 11:43:13 -04:00
QEvt *QF_newX_(uint_fast16_t const evtSize,
uint_fast16_t const margin, enum_t const sig);
2012-08-14 18:07:04 -04:00
2018-03-19 14:49:36 -04:00
/*! Internal QF implementation of creating new event reference. */
QEvt const *QF_newRef_(QEvt const * const e, void const * const evtRef);
/*! Internal QF implementation of deleting event reference. */
void QF_deleteRef_(void const * const evtRef);
2015-09-04 12:08:22 -04:00
2016-11-30 18:14:20 -05:00
#ifdef Q_EVT_CTOR /* Shall the ctor for the ::QEvt class be provided? */
2012-08-14 18:07:04 -04:00
2019-02-10 21:00:39 -05:00
#define Q_NEW(evtT_, sig_, ...) \
2014-04-06 11:43:13 -04:00
(evtT_##_ctor((evtT_ *)QF_newX_((uint_fast16_t)sizeof(evtT_), \
2020-03-17 21:33:20 -04:00
QF_NO_MARGIN, 0), (sig_), ##__VA_ARGS__))
2012-08-14 18:07:04 -04:00
2019-02-10 21:00:39 -05:00
#define Q_NEW_X(e_, evtT_, margin_, sig_, ...) do { \
2014-04-06 11:43:13 -04:00
(e_) = (evtT_ *)QF_newX_((uint_fast16_t)sizeof(evtT_), \
2020-07-18 17:56:40 -04:00
(margin_), 0); \
2019-02-10 21:00:39 -05:00
if ((e_) != (evtT_ *)0) { \
evtT_##_ctor((e_), (sig_), ##__VA_ARGS__); \
2019-10-27 11:57:33 -04:00
} \
2019-12-31 15:55:08 -05:00
} while (false)
2012-08-14 18:07:04 -04:00
2013-09-23 14:34:35 -04:00
#else
2012-08-14 18:07:04 -04:00
2014-04-06 11:43:13 -04:00
/*! Allocate a dynamic event. */
/**
2015-04-28 13:45:35 -04:00
* @description
2015-09-04 12:08:22 -04:00
* The macro calls the internal QF function QF_newX_() with
2017-06-19 11:45:15 -04:00
* margin == #QF_NO_MARGIN, which causes an assertion when the event
* cannot be successfully allocated.
*
2015-04-28 13:45:35 -04:00
* @param[in] evtT_ event type (class name) of the event to allocate
* @param[in] sig_ signal to assign to the newly allocated event
*
2015-04-28 13:45:35 -04:00
* @returns a valid event pointer cast to the type @p evtT_.
*
2015-04-28 13:45:35 -04:00
* @note
2020-07-18 17:56:40 -04:00
* If Q_EVT_CTOR is defined, the Q_NEW() macro becomes variadic and
* takes all the arguments needed by the constructor of the event
* class being allocated. The constructor is then called by means
* of the placement-new operator.
2012-08-14 18:07:04 -04:00
*
2015-04-28 13:45:35 -04:00
* @usage
2012-08-14 18:07:04 -04:00
* The following example illustrates dynamic allocation of an event:
2015-04-28 13:45:35 -04:00
* @include qf_post.c
2012-08-14 18:07:04 -04:00
*/
2019-02-10 21:00:39 -05:00
#define Q_NEW(evtT_, sig_) \
2014-04-06 11:43:13 -04:00
((evtT_ *)QF_newX_((uint_fast16_t)sizeof(evtT_), \
2017-06-19 11:45:15 -04:00
QF_NO_MARGIN, (sig_)))
2013-09-23 14:34:35 -04:00
2014-04-06 11:43:13 -04:00
/*! Allocate a dynamic event (non-asserting version). */
/**
2015-04-28 13:45:35 -04:00
* @description
* This macro allocates a new event and sets the pointer @p e_, while
* leaving at least @p margin_ of events still available in the pool
*
2020-07-18 17:56:40 -04:00
* @param[in,out] e_ pointer to the newly allocated event
2015-04-28 13:45:35 -04:00
* @param[in] evtT_ event type (class name) of the event to allocate
* @param[in] margin_ number of events that must remain available
2017-06-19 11:45:15 -04:00
* in the given pool after this allocation. The special
* value #QF_NO_MARGIN causes asserting failure in case
* event allocation or event posting fails.
2015-04-28 13:45:35 -04:00
* @param[in] sig_ signal to assign to the newly allocated event
2013-09-23 14:34:35 -04:00
*
2015-04-28 13:45:35 -04:00
* @returns an event pointer cast to the type @p evtT_ or NULL if the
* event cannot be allocated with the specified @p margin.
*
2015-04-28 13:45:35 -04:00
* @note
2020-07-18 17:56:40 -04:00
* If Q_EVT_CTOR is defined, the Q_NEW_X() macro becomes variadic and
* takes all the arguments needed by the constructor of the event
* class being allocated. The constructor is then called and all the
* extra arguments are passed to it.
*
2015-04-28 13:45:35 -04:00
* @usage
2013-09-23 14:34:35 -04:00
* The following example illustrates dynamic allocation of an event:
2015-04-28 13:45:35 -04:00
* @include qf_postx.c
2013-09-23 14:34:35 -04:00
*/
#define Q_NEW_X(e_, evtT_, margin_, sig_) ((e_) = \
2014-04-06 11:43:13 -04:00
(evtT_ *)QF_newX_((uint_fast16_t)sizeof(evtT_), (margin_), (sig_)))
2012-08-14 18:07:04 -04:00
2014-04-06 11:43:13 -04:00
#endif /* Q_EVT_CTOR */
2012-08-14 18:07:04 -04:00
2015-09-04 12:08:22 -04:00
/*! Create a new reference of the current event `e` */
/**
* @description
* The current event processed by an active object is available only for
* the duration of the run-to-completion (RTC) step. After that step, the
* current event is no longer available and the framework might recycle
* (garbage-collect) the event. The macro Q_NEW_REF() explicitly creates
* a new reference to the current event that can be stored and used beyond
* the current RTC step, until the reference is explicitly recycled by
* means of the macro Q_DELETE_REF().
*
* @param[in,out] evtRef_ event reference to create
2016-11-30 18:14:20 -05:00
* @param[in] evtT_ event type (class name) of the event reference
2015-09-04 12:08:22 -04:00
*
* @usage
* The example **defer** in the directory `examples/win32/defer` illustrates
* the use of Q_NEW_REF()
*
* @sa Q_DELETE_REF()
*/
#define Q_NEW_REF(evtRef_, evtT_) \
2018-03-19 14:49:36 -04:00
((evtRef_) = (evtT_ const *)QF_newRef_(e, (evtRef_)))
2015-09-04 12:08:22 -04:00
/*! Delete the event reference */
/**
* @description
* Every event reference created with the macro Q_NEW_REF() needs to be
* eventually deleted by means of the macro Q_DELETE_REF() to avoid leaking
* the event.
*
* @param[in,out] evtRef_ event reference to delete
*
* @usage
* The example **defer** in the directory `examples/win32/defer` illustrates
* the use of Q_DELETE_REF()
*
* @sa Q_NEW_REF()
*/
#define Q_DELETE_REF(evtRef_) do { \
2019-10-27 11:57:33 -04:00
QF_deleteRef_((evtRef_)); \
(evtRef_) = (void *)0; \
2019-12-31 15:55:08 -05:00
} while (false)
2012-08-14 18:07:04 -04:00
2014-04-06 11:43:13 -04:00
/*! Recycle a dynamic event. */
2012-08-14 18:07:04 -04:00
void QF_gc(QEvt const * const e);
2014-04-06 11:43:13 -04:00
/*! Clear a specified region of memory to zero. */
void QF_bzero(void * const start, uint_fast16_t len);
2013-12-30 17:37:40 -05:00
2013-09-23 14:34:35 -04:00
#ifndef QF_CRIT_EXIT_NOP
2014-04-06 11:43:13 -04:00
/*! No-operation for exiting a critical section */
/**
2015-04-28 13:45:35 -04:00
* @description
2013-09-23 14:34:35 -04:00
* In some QF ports the critical section exit takes effect only on the
* next machine instruction. If this next instruction is another entry
* to a critical section, the critical section won't be really exited,
* but rather the two adjacent critical sections would be merged.
* The #QF_CRIT_EXIT_NOP() macro contains minimal code required to
* prevent such merging of critical sections in QF ports, in which it
* can occur.
*/
#define QF_CRIT_EXIT_NOP() ((void)0)
#endif
2012-08-14 18:07:04 -04:00
2014-04-06 11:43:13 -04:00
/*! array of registered active objects */
/**
2015-04-28 13:45:35 -04:00
* @note Not to be used by Clients directly, only in ports of QF
2012-08-14 18:07:04 -04:00
*/
2020-03-17 21:33:20 -04:00
extern QActive *QF_active_[QF_MAX_ACTIVE + 1U];
2012-08-14 18:07:04 -04:00
2016-12-16 10:34:09 -05:00
/****************************************************************************/
2020-07-18 17:56:40 -04:00
/*! QTicker Active Object class
* @extends QActive
*/
2016-12-16 10:34:09 -05:00
/**
* @description
* The QTicker is an efficient active object specialized to process
2020-07-18 17:56:40 -04:00
* QF system clock tick at a specified tick frequency [0..::QF_MAX_TICK_RATE].
2016-12-16 10:34:09 -05:00
* Placing system clock tick processing in an active object allows you
* to remove the non-deterministic QF::TICK_X() processing from the interrupt
* level and move it into the thread-level, where you can prioritize it
* as low as you wish.
*/
2020-07-18 17:56:40 -04:00
typedef struct {
QActive super; /*!< inherits ::QActive */
} QTicker;
2016-12-16 10:34:09 -05:00
/*! Constructor of the QTicker Active Object class */
2020-07-18 17:56:40 -04:00
void QTicker_ctor(QTicker * const me, uint_fast8_t tickRate);
2016-12-16 10:34:09 -05:00
2019-10-27 11:57:33 -04:00
#endif /* QF_H */
2013-09-23 14:34:35 -04:00