QP/C
Data Structures | Defines | Functions | Variables
qf.h File Reference

QF/C platform-independent public interface. More...

Go to the source code of this file.

Data Structures

struct  QActive
 Active Object structure. More...
struct  QTimeEvt
 Time Event structure. More...
struct  QSubscrList
 Subscriber-List structure. More...

Defines

#define QF_EVENT_SIZ_SIZE   2
 Default value of the macro configurable value in qf_port.h.
#define QF_MAX_EPOOL   3
 Default value of the macro configurable value in qf_port.h.
#define QACTIVE_POST(me_, e_, sender_)   QActive_postFIFO((me_), (e_), (sender_))
 Invoke the direct event posting facility QActive_postFIFO(). This macro is the recommended way of posting events, because it provides the vital information for software tracing and avoids any overhead when the tracing is disabled.
#define QActive_ctor(me_, initial_)   QF_ACTIVE_CTOR_(&(me_)->super, (initial_))
 protected "constructor" of an active object. Performs the first step of active object initialization by assigning the initial pseudostate to the currently active state of the state machine.
#define QF_TIMEEVT_CTR_SIZE   2
 macro to override the default QTimeEvtCtr size. Valid values 1, 2, or 4; default 2
#define QTimeEvt_postIn(me_, act_, nTicks_)
 Arm a one-shot time event for direct event posting.
#define QTimeEvt_postEvery(me_, act_, nTicks_)
 Arm a periodic time event for direct event posting.
#define QF_PUBLISH(e_, sender_)   QF_publish((e_), (sender_))
 Invoke the event publishing facility QF_publish(). 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.
#define QF_TICK(sender_)   QF_tick(sender_)
 Invoke the system clock tick processing QF_tick(). 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.
#define Q_NEW(evtT_, sig_)   ((evtT_ *)QF_new_((QEventSize)sizeof(evtT_), (QSignal)(sig_)))
 Allocate a dynamic event.

Functions

void QActive_start (QActive *me, uint8_t prio, QEvent const *qSto[], uint32_t qLen, void *stkSto, uint32_t stkSize, QEvent const *ie)
 Starts execution of an active object and registers the object with the framework.
void QActive_postFIFO (QActive *me, QEvent const *e, void const *sender)
 Posts an event e directly to the event queue of the acitve object me using the First-In-First-Out (FIFO) policy.
void QActive_postLIFO (QActive *me, QEvent const *e)
 Posts an event directly to the event queue of the active object me using the Last-In-First-Out (LIFO) policy.
void QActive_stop (QActive *me)
 Stops execution of an active object and removes it from the framework's supervision.
void QActive_subscribe (QActive const *me, QSignal sig)
 Subscribes for delivery of signal sig to the active object me.
void QActive_unsubscribe (QActive const *me, QSignal sig)
 Un-subscribes from the delivery of signal sig to the active object me.
void QActive_unsubscribeAll (QActive const *me)
 Un-subscribes from the delivery of all signals to the active object me.
void QActive_defer (QActive *me, QEQueue *eq, QEvent const *e)
 Defer an event to a given separate event queue.
uint8_t QActive_recall (QActive *me, QEQueue *eq)
 Recall a deferred event from a given event queue.
QEvent const * QActive_get_ (QActive *me)
 Get an event from the event queue of an active object.
void QTimeEvt_ctor (QTimeEvt *me, QSignal sig)
 The "constructor" to initialize a Time Event.
uint8_t QTimeEvt_disarm (QTimeEvt *me)
 Disarm a time event.
uint8_t QTimeEvt_rearm (QTimeEvt *me, QTimeEvtCtr nTicks)
 Rearm a time event.
QTimeEvtCtr QTimeEvt_ctr (QTimeEvt const *me)
 Get the current value of the down-counter of a time event.
void QTimeEvt_arm_ (QTimeEvt *me, QActive *act, QTimeEvtCtr nTicks)
 Arm a time event (internal function to be used through macros only).
void QF_init (void)
 QF initialization.
void QF_psInit (QSubscrList *subscrSto, QSignal maxSignal)
 Publish-subscribe initialization.
void QF_poolInit (void *poolSto, uint32_t poolSize, QEventSize evtSize)
 Event pool initialization for dynamic allocation of events.
void QF_run (void)
 Transfers control to QF to run the application.
void QF_stop (void)
 Function invoked by the application layer to stop the QF application and return control to the OS/Kernel.
void QF_onStartup (void)
 Startup QF callback.
void QF_onCleanup (void)
 Cleanup QF callback.
void QF_onIdle (void)
 QF idle callback (customized in BSPs for QF)
void QF_publish (QEvent const *e, void const *sender)
 Publish event to the framework.
void QF_tick (void const *sender)
 Processes all armed time events at every clock tick.
void QF_add_ (QActive *a)
 Register an active object to be managed by the framework.
void QF_remove_ (QActive const *a)
 Remove the active object from the framework.
char_t const Q_ROM *Q_ROM_VAR QF_getVersion (void)
 Returns the QF version.
char_t const Q_ROM *Q_ROM_VAR QF_getPortVersion (void)
 Returns the QF-port version.
uint32_t QF_getPoolMargin (uint8_t poolId)
 This function returns the margin of the given event pool.
uint32_t QF_getQueueMargin (uint8_t prio)
 This function returns the margin of the given event queue.
QEventQF_new_ (QEventSize evtSize, QSignal sig)
 Internal QF implementation of the dynamic event allocator.
void QF_gc (QEvent const *e)
 Recycle a dynamic event.

Variables

uint8_t const Q_ROM Q_ROM_VAR QF_log2Lkup [256]
 Lookup table for (log2(n) + 1), where n is the index into the table.
uint8_t const Q_ROM Q_ROM_VAR QF_pwr2Lkup [65]
 Lookup table for (1 << ((n-1) % 8)), where n is the index into the table.
uint8_t const Q_ROM Q_ROM_VAR QF_invPwr2Lkup [65]
 Lookup table for ~(1 << ((n-1) % 8)), where n is the index into the table.
uint8_t const Q_ROM Q_ROM_VAR QF_div8Lkup [65]
 Lookup table for (n-1)/8.
QActiveQF_active_ []
 array of registered active objects

Detailed Description

QF/C platform-independent public interface.

This header file must be included directly or indirectly in all modules (*.c files) that use QF or QK.

Definition in file qf.h.


Define Documentation

#define Q_NEW (   evtT_,
  sig_ 
)    ((evtT_ *)QF_new_((QEventSize)sizeof(evtT_), (QSignal)(sig_)))

Allocate a dynamic event.

This macro returns an event pointer cast to the type evtT_. The event is initialized with the signal sig_. Internally, the macro calls the internal QF function QF_new_(), which always returns a valid event pointer.

Note:
The internal QF function QF_new_() raises an assertion when the allocation of the event turns out to be impossible due to event pool depletion, or incorrect (too big) size of the requested event.

The following example illustrates dynamic allocation of an event:

extern QActive *AO_Table;

QState Philosopher_hungry(Philosopher *me, QEvent const *e) {
    TableEvt *pe;
    switch (e->sig) {
        case Q_ENTRY_SIG: {
            pe = Q_NEW(TableEvt, HUNGRY_SIG); /* dynamically allocate event */
            pe->philNum = me->num;
            QActive_postFIFO(AO_Table, (QEvent *)pe);     /* direct posting */
            return Q_HANDLED();
        }
        . . .
    }
    return Q_SUPER(&QHsm_top);
}

Definition at line 1024 of file qf.h.

#define QActive_ctor (   me_,
  initial_ 
)    QF_ACTIVE_CTOR_(&(me_)->super, (initial_))

protected "constructor" of an active object. Performs the first step of active object initialization by assigning the initial pseudostate to the currently active state of the state machine.

Note:
Must be called only by the "constructors" of the derived active objects, as shown in the following example:
void Philosopher_ctor(Philosopher *me) {
    QActive_ctor(&me->super, (QStateHandler)&Philosopher_initial);
    QTimeEvt_ctor(&me->timeEvt, TIMEOUT_SIG);
}
Must be called before QActive_start().

The following example illustrates how to invoke QFsm_ctor() in the "constructor" of a derived state machine:

void QCalc_ctor(QCalc *me) {
    QHsm_ctor(&me->super, (QStateHandler)&QCalc_initial);
}
See also:
QHsm_ctor and QFsm_ctor

Definition at line 313 of file qf.h.

#define QACTIVE_POST (   me_,
  e_,
  sender_ 
)    QActive_postFIFO((me_), (e_), (sender_))

Invoke the direct event posting facility QActive_postFIFO(). This macro is the recommended way of posting events, because it provides the vital information for software tracing and avoids any overhead when the tracing is disabled.

This macro takes the last argument sender_, which is a pointer to the sender object. This argument is actually only used when QS software tracing is disabled (macro #Q_SPY is defined). When QS software tracing is not enabled, the macro calls QF_publish() without the sender_ argument, so the overhead of passing this extra argument is entirely avoided.

Note:
the pointer to the sender object is not necessarily a poiner to an active object. In fact, if QACTIVE_POST() is called from an interrupt or other context, you can create a unique object just to unambiguously identify the publisher of the event.
See also:
QActive_postFIFO().

Definition at line 275 of file qf.h.

Referenced by QF_publish(), and QF_tick().

#define QF_PUBLISH (   e_,
  sender_ 
)    QF_publish((e_), (sender_))

Invoke the event publishing facility QF_publish(). 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.

This macro takes the last argument sender_, which is a pointer to the sender object. This argument is 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 sender_ argument, so the overhead of passing this extra argument is entirely avoided.

Note:
the pointer to the sender object is not necessarily a poiner 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.
See also:
QF_publish().

Definition at line 869 of file qf.h.

#define QF_TICK (   sender_)    QF_tick(sender_)

Invoke the system clock tick processing QF_tick(). 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.

This macro takes the argument sender_, which is a pointer to the sender object. This argument is actually only used when QS software tracing is enabled (macro #Q_SPY is defined). When QS software tracing is disabled, the macro calls QF_tick() without any arguments, so the overhead of passing this extra argument is entirely avoided.

Note:
the pointer to the sender object is not necessarily a poiner to an active object. In fact, typically QF_TICK() will be called from an interrupt, in which case you would create a unique object just to unambiguously identify the ISR as the sender of the time events.
See also:
QF_tick().

Definition at line 915 of file qf.h.

#define QTimeEvt_postEvery (   me_,
  act_,
  nTicks_ 
)
Value:
do { \
    (me_)->interval = (nTicks_); \
    QTimeEvt_arm_((me_), (act_), (nTicks_)); \
} while (0)

Arm a periodic time event for direct event posting.

Arms a time event me_ to fire every nTicks_ clock ticks (periodic time event). The time event gets directly posted (using the FIFO policy) into the event queue of the active object act_.

After posting, the time event gets automatically re-armed to fire again in the specified nTicks_ clock ticks.

A periodic time event can be disarmed only by calling the QTimeEvt_disarm() function. After disarming, the time event can be reused for a one-shot or periodic timeout requests.

Note:
An attempt to reuse (arm again) a running periodic time event raises an assertion.

Also, a periodic time event can be re-armed to shorten or extend the current period by calling the QTimeEvt_rearm() function. After adjusting the current period, the periodic time event goes back timing out at the original rate.

Definition at line 590 of file qf.h.

#define QTimeEvt_postIn (   me_,
  act_,
  nTicks_ 
)
Value:
do { \
    (me_)->interval = (QTimeEvtCtr)0; \
    QTimeEvt_arm_((me_), (act_), (nTicks_)); \
} while (0)

Arm a one-shot time event for direct event posting.

Arms a time event me_ to fire in nTicks_ clock ticks (one-shot time event). The time event gets directly posted (using the FIFO policy) into the event queue of the active object act_.

After posting, the time event gets automatically disarmed and can be reused for a one-shot or periodic timeout requests.

A one-shot time event can be disarmed at any time by calling the QTimeEvt_disarm() function. Also, a one-shot time event can be re-armed to fire in a different number of clock ticks by calling the QTimeEvt_rearm() function.

The following example shows how to arm a one-shot time event from a state machine of an active object:

QState Philosopher_eating(Philosopher *me, QEvent const *e) {
    TableEvt *pe;
    switch (e->sig) {
        case Q_ENTRY_SIG: {
            QTimeEvt_postIn(&me->timeEvt, (QActive *)me, EAT_TIME);
            return Q_HANDLED();
        }
        case TIMEOUT_SIG: {
            return Q_TRAN(&Philosopher_thinking);
        }
        case Q_EXIT_SIG: {
            pe = Q_NEW(TableEvt, DONE_SIG);
            pe->philNum = me->num;
            QF_publish((QEvent *)pe);
            return Q_HANDLED();
        }
    }
    return Q_SUPER(&QHsm_top);
}

Definition at line 564 of file qf.h.


Function Documentation

void QActive_defer ( QActive me,
QEQueue eq,
QEvent const *  e 
)

Defer an event to a given separate event queue.

This function is part of the event deferral support. An active object uses this function to defer an event e to the QF-supported native event queue eq. QF correctly accounts for another outstanding reference to the event and will not recycle the event at the end of the RTC step. Later, the active object might recall one event at a time from the event queue.

An active object can use multiple event queues to defer events of different kinds.

See also:
QActive_recall(), QEQueue

Definition at line 40 of file qa_defer.c.

References QEQueue_postFIFO().

QEvent const* QActive_get_ ( QActive me)

Get an event from the event queue of an active object.

This function is used internally by a QF port to extract events from the event queue of an active object. This function depends on the event queue implementation and is sometimes implemented in the QF port (qf_port.c file). Depending on the underlying OS or kernel, the function might block the calling thread when no events are available.

See also:
QActive_postFIFO(), QActive_postLIFO()

Definition at line 43 of file qa_get_.c.

References QACTIVE_EQUEUE_ONEMPTY_, QACTIVE_EQUEUE_WAIT_, QF_EVT_POOL_ID_, QF_EVT_REF_CTR_, QF_PTR_AT_, QS_aoObj_, QS_BEGIN_NOCRIT_, QS_END_NOCRIT_, QS_EQC_, QS_OBJ_, QS_QF_ACTIVE_GET, QS_QF_ACTIVE_GET_LAST, QS_TIME_, QS_U8_, and QEvent::sig.

Referenced by QF_run(), QK_sched_(), and QK_schedExt_().

void QActive_postFIFO ( QActive me,
QEvent const *  e,
void const *  sender 
)

Posts an event e directly to the event queue of the acitve object me using the First-In-First-Out (FIFO) policy.

Note:
this function should be called only via the macro QACTIVE_POST

Direct event posting is the simplest asynchronous communication method available in QF. The following example illustrates how the Philo active object posts directly the HUNGRY event to the Table active object.

extern QActive *AO_Table;

QState Philosopher_hungry(Philosopher *me, QEvent const *e) {
    TableEvt *pe;
    switch (e->sig) {
        case Q_ENTRY_SIG: {
            pe = Q_NEW(TableEvt, HUNGRY_SIG); /* dynamically allocate event */
            pe->philNum = me->num;
            QActive_postFIFO(AO_Table, (QEvent *)pe);     /* direct posting */
            return Q_HANDLED();
        }
        . . .
    }
    return Q_SUPER(&QHsm_top);
}
Note:
The producer of the event (Philo in this case) must only "know" the recipient (Table) by a generic (QActive *AO_Table) pointer, but the specific definition of the Table structure is not required.
Direct event posting should not be confused with direct event dispatching. In contrast to asynchronous event posting through event queues, direct event dispatching is synchronous. Direct event dispatching occurs when you call QHsm_dispatch(), or QFsm_dispatch() function.

Definition at line 46 of file qa_fifo.c.

References QActive::eQueue, Q_ASSERT, QACTIVE_EQUEUE_SIGNAL_, QF_EVT_POOL_ID_, QF_EVT_REF_CTR_, QF_EVT_REF_CTR_INC_, QF_PTR_AT_, QS_aoObj_, QS_BEGIN_NOCRIT_, QS_END_NOCRIT_, QS_EQC_, QS_OBJ_, QS_QF_ACTIVE_POST_FIFO, QS_TIME_, QS_U8_, and QEvent::sig.

void QActive_postLIFO ( QActive me,
QEvent const *  e 
)

Posts an event directly to the event queue of the active object me using the Last-In-First-Out (LIFO) policy.

Note:
The LIFO policy should be used only for self-posting and with caution because it alters order of events in the queue.
See also:
QActive_postFIFO()

Definition at line 43 of file qa_lifo.c.

References Q_ASSERT, QACTIVE_EQUEUE_SIGNAL_, QF_EVT_POOL_ID_, QF_EVT_REF_CTR_, QF_EVT_REF_CTR_INC_, QF_PTR_AT_, QS_aoObj_, QS_BEGIN_NOCRIT_, QS_END_NOCRIT_, QS_EQC_, QS_OBJ_, QS_QF_ACTIVE_POST_LIFO, QS_TIME_, and QS_U8_.

Referenced by QActive_recall().

uint8_t QActive_recall ( QActive me,
QEQueue eq 
)

Recall a deferred event from a given event queue.

This function is part of the event deferral support. An active object uses this function to recall a deferred event from a given QF event queue. Recalling an event means that it is removed from the deferred event queue eq and posted (LIFO) to the event queue of the active object.

QActive_recall() returns 1 (TRUE) if an event has been recalled. Otherwise the function returns 0.

An active object can use multiple event queues to defer events of different kinds.

See also:
QActive_recall(), QEQueue, QActive_postLIFO()

Definition at line 45 of file qa_defer.c.

References Q_ASSERT, QActive_postLIFO(), QEQueue_get(), QF_EVT_POOL_ID_, QF_EVT_REF_CTR_, and QF_EVT_REF_CTR_DEC_.

void QActive_start ( QActive me,
uint8_t  prio,
QEvent const *  qSto[],
uint32_t  qLen,
void *  stkSto,
uint32_t  stkSize,
QEvent const *  ie 
)

Starts execution of an active object and registers the object with the framework.

The function takes seven arguments. me is a pointer to the active object structure. prio is the priority of the active object. QF allows you to start up to 63 active objects, each one having a unique priority number between 1 and 63 inclusive, where higher numerical values correspond to higher priority (urgency) of the active object relative to the others. qSto[] and qLen arguments are the storage and size of the event queue used by this active object. stkSto and stkSize are the stack storage and size in bytes. Please note that a per-active object stack is used only when the underlying OS requies it. If the stack is not required, or the underlying OS allocates the stack internally, the stkSto should be NULL and/or stkSize should be 0. ie is an optional initialization event that can be used to pass additional startup data to the active object. (Pass NULL if your active object does not expect the initialization event).

Note:
This function is strongly OS-dependent and must be defined in the QF port to a particular platform.

The following example shows starting of the Philosopher object when a per-task stack is required:

static Philosopher l_philo[N];              /* N Philosopher active objects */
static QEvent const *l_philQueueSto[N][N];/* storage for Philo event queues */
static int l_philoStk[N][256]; /* stacks for the Philosopher active objects */

main() {
    . . .
    for (n = 0; n < N; ++n) {
        TableEvt ie;        /* initialization event for the Philosopher HSM */
        ie.philNum = n;
        Philosopher_ctor(&l_philo[n]);
        QActive_start((QActive *)&l_philo[n],       /* Philosopher number n */
                      (uint8_t)(n*10 + 1),                      /* priority */
                      l_philoQueueSto[n], Q_DIM(l_philoQueueSto[n]),/*queue */
                      l_philoStk[n], sizeof(l_philoStk[n]),/*uC/OS-II stack */
                      (QEvent const *)&ie);         /* initialization event */
    }
    . . .
} 

Definition at line 88 of file qvanilla.c.

References QActive::eQueue, QActive::prio, Q_ASSERT, Q_REQUIRE, QEQueue_init(), QF_add_(), QF_MAX_ACTIVE, QS_FLUSH, and QActive::super.

void QActive_stop ( QActive me)

Stops execution of an active object and removes it from the framework's supervision.

The preferred way of calling this function is from within the active object that needs to stop. In other words, an active object should stop itself rather than being stopped by some other entity. This policy works best, because only the active object itself "knows" when it has reached the appropriate state for the shutdown.

Note:
This function is strongly OS-dependent and should be defined in the QF port to a particular platform. This function is optional in embedded systems where active objects never need to be stopped.

Definition at line 105 of file qvanilla.c.

References QF_remove_().

void QActive_subscribe ( QActive const *  me,
QSignal  sig 
)

Subscribes for delivery of signal sig to the active object me.

This function is part of the Publish-Subscribe event delivery mechanism available in QF. Subscribing to an event means that the framework will start posting all published events with a given signal sig to the event queue of the active object me.

The following example shows how the Table active object subscribes to three signals in the initial transition:

QState Table_initial(Table *me, QEvent const *e) {
    uint8_t n;
    (void)e;                               /* suppress the compiler warning */

    QActive_subscribe((QActive *)me, HUNGRY_SIG);   /* subscribe to HUNGRY */
    QActive_subscribe((QActive *)me, DONE_SIG);              /*... to DONE */
    QActive_subscribe((QActive *)me, TERMINATE_SIG); /*...and to TERMINATE */
    for (n = 0; n < N; ++n) {
        me->fork[n] = FREE;
        me->isHungry[n] = 0;
    }
    return Q_TRAN(&Table_serving);
}
See also:
QF_publish(), QActive_unsubscribe(), and QActive_unsubscribeAll()

Definition at line 40 of file qa_sub.c.

References Q_REQUIRE, Q_USER_SIG, QF_active_, QF_div8Lkup, QF_MAX_ACTIVE, QF_maxSignal_, QF_PTR_AT_, QF_pwr2Lkup, QF_subscrList_, QS_aoObj_, QS_BEGIN_NOCRIT_, QS_END_NOCRIT_, QS_OBJ_, QS_QF_ACTIVE_SUBSCRIBE, and QS_TIME_.

void QActive_unsubscribe ( QActive const *  me,
QSignal  sig 
)

Un-subscribes from the delivery of signal sig to the active object me.

This function is part of the Publish-Subscribe event delivery mechanism available in QF. Un-subscribing from an event means that the framework will stop posting published events with a given signal sig to the event queue of the active object me.

Note:
Due to the latency of event queues, an active object should NOT assume that a given signal sig will never be dispatched to the state machine of the active object after un-subscribing from that signal. The event might be already in the queue, or just about to be posted and the un-subscribe operation will not flush such events.
Un-subscribing from a signal that has never been subscribed in the first place is considered an error and QF will rise an assertion.
See also:
QF_publish(), QActive_subscribe(), and QActive_unsubscribeAll()

Definition at line 40 of file qa_usub.c.

References Q_REQUIRE, Q_USER_SIG, QF_active_, QF_div8Lkup, QF_invPwr2Lkup, QF_MAX_ACTIVE, QF_maxSignal_, QF_PTR_AT_, QF_subscrList_, QS_aoObj_, QS_BEGIN_NOCRIT_, QS_END_NOCRIT_, QS_OBJ_, QS_QF_ACTIVE_UNSUBSCRIBE, and QS_TIME_.

void QActive_unsubscribeAll ( QActive const *  me)

Un-subscribes from the delivery of all signals to the active object me.

This function is part of the Publish-Subscribe event delivery mechanism available in QF. Un-subscribing from all events means that the framework will stop posting any published events to the event queue of the active object me.

Note:
Due to the latency of event queues, an active object should NOT assume that no events will ever be dispatched to the state machine of the active object after un-subscribing from all events. The events might be already in the queue, or just about to be posted and the un-subscribe operation will not flush such events. Also, the alternative event-delivery mechanisms, such as direct event posting or time events, can be still delivered to the event queue of the active object.
See also:
QF_publish(), QActive_subscribe(), and QActive_unsubscribe()

Definition at line 40 of file qa_usuba.c.

References Q_REQUIRE, Q_USER_SIG, QF_active_, QF_div8Lkup, QF_invPwr2Lkup, QF_MAX_ACTIVE, QF_maxSignal_, QF_PTR_AT_, QF_pwr2Lkup, QF_subscrList_, QS_aoObj_, QS_BEGIN_NOCRIT_, QS_END_NOCRIT_, QS_OBJ_, QS_QF_ACTIVE_UNSUBSCRIBE, and QS_TIME_.

void QF_add_ ( QActive a)

Register an active object to be managed by the framework.

This function should not be called by the application directly, only through the function QActive_start(). The priority of the active object a should be set before calling this function.

Note:
This function raises an assertion if the priority of the active object exceeds the maximum value QF_MAX_ACTIVE. Also, this function raises an assertion if the priority of the active object is already in use. (QF requires each active object to have a UNIQUE priority.)

Definition at line 58 of file qf_act.c.

References QActive::prio, Q_REQUIRE, QF_active_, QF_MAX_ACTIVE, QS_aoObj_, QS_BEGIN_NOCRIT_, QS_END_NOCRIT_, QS_OBJ_, QS_QF_ACTIVE_ADD, QS_TIME_, and QS_U8_.

Referenced by QActive_start().

void QF_gc ( QEvent const *  e)

Recycle a dynamic event.

This function implements a simple garbage collector for the dynamic events. Only dynamic events are candidates for recycling. (A dynamic event is one that is allocated from an event pool, which is determined as non-zero e->attrQF__ attribute.) Next, the function decrements the reference counter of the event, and recycles the event only if the counter drops to zero (meaning that no more references are outstanding for this event). The dynamic event is recycled by returning it to the pool from which it was originally allocated. The pool-of-origin information is stored in the upper 2-MSBs of the e->attrQF__ attribute.)

Note:
QF invokes the garbage collector at all appropriate contexts, when an event can become garbage (automatic garbage collection), so the application code should have no need to call QF_gc() directly. The QF_gc() function is exposed only for special cases when your application sends dynamic events to the "raw" thread-safe queues (see QEQueue). Such queues are processed outside of QF and the automatic garbage collection is CANNOT be performed for these events. In this case you need to call QF_gc() explicitly.

Definition at line 40 of file qf_gc.c.

References Q_ASSERT, QF_EPOOL_PUT_, QF_EVT_POOL_ID_, QF_EVT_REF_CTR_, QF_EVT_REF_CTR_DEC_, QF_maxPool_, QF_pool_, QS_BEGIN_NOCRIT_, QS_END_NOCRIT_, QS_QF_GC, QS_QF_GC_ATTEMPT, QS_TIME_, and QS_U8_.

Referenced by QF_publish(), QF_run(), QK_sched_(), and QK_schedExt_().

uint32_t QF_getPoolMargin ( uint8_t  poolId)

This function returns the margin of the given event pool.

This function returns the margin of the given event pool poolId, where poolId is the ID of the pool initialized by the call to QF_poolInit(). The poolId of the first initialized pool is 1, the second 2, and so on.

The returned pool margin is the minimal number of free blocks encountered in the given pool since system startup.

Note:
Requesting the margin of an un-initialized pool raises an assertion in the QF.

Definition at line 65 of file qmp_get.c.

References Q_REQUIRE, QF_maxPool_, and QF_pool_.

char_t const Q_ROM* Q_ROM_VAR QF_getPortVersion ( void  )

Returns the QF-port version.

This function returns constant version string in the format x.y.zz, where x (one digit) is the major version, y (one digit) is the minor version, and zz (two digits) is the maintenance release version. An example of the QF-port version string is "1.1.03".

See also:
QF_getVersion()
uint32_t QF_getQueueMargin ( uint8_t  prio)

This function returns the margin of the given event queue.

This function returns the margin of the given event queue of an active object with priority prio. (QF priorities start with 1 and go up to QF_MAX_ACTIVE.) The margin is the minimal number of free events encountered in the given queue since system startup.

Note:
QF_getQueueMargin() is available only when the native QF event queue implementation is used. Requesting the queue margin of an unused priority level raises an assertion in the QF. (A priority level becomes used in QF after the call to the QF_add_() function.)

Definition at line 87 of file qa_get_.c.

References Q_REQUIRE, QF_active_, and QF_MAX_ACTIVE.

char_t const Q_ROM* Q_ROM_VAR QF_getVersion ( void  )

Returns the QF version.

This function returns constant version string in the format x.y.zz, where x (one digit) is the major version, y (one digit) is the minor version, and zz (two digits) is the maintenance release version. An example of the version string is "3.1.03".

The following example illustrates the usage of this function:

    printf("Quantum DPP\nQEP %s\nQF  %s, QF port %s\n"
           "Press ESC to quit...\n",
           QEP_getVersion(),
           QF_getVersion(), QF_getPortVersion());

Definition at line 45 of file qf_act.c.

References QP_VERSION.

Referenced by QK_getVersion().

void QF_init ( void  )

QF initialization.

This function initializes QF and must be called exactly once before any other QF function.

Definition at line 48 of file qvanilla.c.

References QK_init().

QEvent* QF_new_ ( QEventSize  evtSize,
QSignal  sig 
)

Internal QF implementation of the dynamic event allocator.

Note:
The application code should not call this function directly. Please use the macro Q_NEW.

Definition at line 40 of file qf_new.c.

References Q_ASSERT, QF_EPOOL_EVENT_SIZE_, QF_EPOOL_GET_, QF_EVT_POOL_ID_, QF_EVT_REF_CTR_, QF_maxPool_, QF_pool_, QS_BEGIN_, QS_CRIT_STAT_, QS_END_, QS_QF_NEW, QS_TIME_, and QEvent::sig.

void QF_onCleanup ( void  )

Cleanup QF callback.

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.

See also:
QF_stop()

Referenced by QF_stop().

void QF_onIdle ( void  )

QF idle callback (customized in BSPs for QF)

QF_onIdle() is called by the non-preemptive "Vanilla" scheduler built into QF when the framework detects that no events are available for active objects (the idle condition). This callback gives the application an opportunity to enter a power-saving CPU mode, or perform some other idle processing (such as Q-Spy output).

Note:
QF_onIdle() is invoked with interrupts DISABLED because the idle condition can be asynchronously changed at any time by an interrupt. QF_onIdle() MUST enable the interrupts internally, but not before putting the CPU into the low-power mode. (Ideally, enabling interrupts and low-power mode should happen atomically). At the very least, the function MUST enable interrupts, otherwise interrups will remain disabled permanently.
QF_onIdle() is only used by the non-preemptive "Vanilla" scheduler in the "bare metal" QF port, and is NOT used in any other QF ports. When QF is combined with QK, the QK idle loop calls a different function QK_onIdle(), with different semantics than QF_onIdle(). When QF is combined with a 3rd-party RTOS or kernel, the idle processing mechanism of the RTOS or kernal is used instead of QF_onIdle().

Referenced by QF_run().

void QF_onStartup ( void  )

Startup QF callback.

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.

Referenced by QF_run().

void QF_poolInit ( void *  poolSto,
uint32_t  poolSize,
QEventSize  evtSize 
)

Event pool initialization for dynamic allocation of events.

This function initializes one event pool at a time and must be called exactly once for each event pool before the pool can be used. The arguments are as follows: poolSto is a pointer to the memory block for the events. poolSize is the size of the memory block in bytes. evtSize is the block-size of the pool in bytes, which determines the maximum size of events that can be allocated from the pool.

You might initialize one, two, and up to three event pools by making one, two, or three calls to the QF_poolInit() function. However, for the simplicity of the internal implementation, you must initialize event pools in the ascending order of the event size.

Many RTOSes provide fixed block-size heaps, a.k.a. memory pools that can be adapted for QF event pools. In case such support is missing, QF provides a native QF event pool implementation. The macro QF_EPOOL_TYPE_ determines the type of event pool used by a particular QF port. See structure QMPool for more information.

Note:
The actual number of events available in the pool might be actually less than (poolSize / evtSize) due to the internal alignment of the blocks that the pool might perform. You can always check the capacity of the pool by calling QF_getPoolMargin().
The dynamic allocation of events is optional, meaning that you might choose not to use dynamic events. In that case calling QF_poolInit() and using up memory for the memory blocks is unnecessary.
See also:
QF initialization example for QF_init()

Definition at line 44 of file qf_pool.c.

References Q_DIM, Q_REQUIRE, QF_EPOOL_EVENT_SIZE_, QF_EPOOL_INIT_, QF_maxPool_, and QF_pool_.

void QF_psInit ( QSubscrList subscrSto,
QSignal  maxSignal 
)

Publish-subscribe initialization.

This function initializes the publish-subscribe facilities of QF and must be called exactly once before any subscriptions/publications occur in the application. The arguments are as follows: subscrSto is a pointer to the array of subscriber-lists. maxSignal is the dimension of this array and at the same time the maximum signal that can be published or subscribed.

The array of subscriber-lists is indexed by signals and provides mapping between the signals and subscriber-lists. The subscriber-lists are bitmasks of type QSubscrList, each bit in the bitmask corresponding to the unique priority of an active object. The size of the QSubscrList bitmask depends on the value of the QF_MAX_ACTIVE macro.

Note:
The publish-subscribe facilities are optional, meaning that you might choose not to use publish-subscribe. In that case calling QF_psInit() and using up memory for the subscriber-lists is unnecessary.
See also:
QSubscrList

The following example shows the typical initialization sequence of QF:

/* allocate storage for active objects, event queues, event pools,
* subscriber lists, and stacks.
*/
static QEvent const *l_tableQueueSto[N_PHILO];
static QEvent const *l_philoQueueSto[N_PHILO][N_PHILO];
static QSubscrList   l_subscrSto[MAX_PUB_SIG];

static union SmallEvent {
    void *min_size;
    TableEvt te;
    /* other event types to go into this pool */
} l_smlPoolSto[2*N_PHILO];              /* storage for the small event pool */

/*..........................................................................*/
int main(int argc, char *argv[]) {
    uint8_t n;

    Philo_ctor();             /* instantiate all Philosopher active objects */
    Table_ctor();                    /* instantiate the Table active object */

    BSP_init(argc, argv);           /* initialize the Board Support Package */

    QF_init();     /* initialize the framework and the underlying RT kernel */

    QF_psInit(l_subscrSto, Q_DIM(l_subscrSto));   /* init publish-subscribe */

                                               /* initialize event pools... */
    QF_poolInit(l_smlPoolSto, sizeof(l_smlPoolSto), sizeof(l_smlPoolSto[0]));

    for (n = 0; n < N_PHILO; ++n) {          /* start the active objects... */
        QActive_start(AO_Philo[n], (uint8_t)(n + 1),
                      l_philoQueueSto[n], Q_DIM(l_philoQueueSto[n]),
                      (void *)0, 0, (QEvent *)0);
    }
    QActive_start(AO_Table, (uint8_t)(N_PHILO + 1),
                  l_tableQueueSto, Q_DIM(l_tableQueueSto),
                  (void *)0, 0, (QEvent *)0);
    QF_run();                                     /* run the QF application */

    return 0;
}

Definition at line 42 of file qf_psini.c.

References QF_maxSignal_.

void QF_publish ( QEvent const *  e,
void const *  sender 
)

Publish event to the framework.

This function posts (using the FIFO policy) the event e to ALL active objects that have subscribed to the signal e->sig. This function is designed to be callable from any part of the system, including ISRs, device drivers, and active objects.

In the general case, event publishing requires multi-casting the event to multiple subscribers. This happens in the caller's thread with the scheduler locked to prevent preemptions during the multi-casting process. (Please note that the interrupts are not locked.)

Note:
this function should be called only via the macro QF_PUBLISH

Definition at line 43 of file qf_pspub.c.

References QSubscrList::bits, Q_ASSERT, Q_DIM, Q_REQUIRE, QACTIVE_POST, QF_active_, QF_EVT_POOL_ID_, QF_EVT_REF_CTR_, QF_EVT_REF_CTR_INC_, QF_gc(), QF_invPwr2Lkup, QF_log2Lkup, QF_maxSignal_, QF_PTR_AT_, QF_subscrList_, QS_BEGIN_NOCRIT_, QS_END_NOCRIT_, QS_OBJ_, QS_QF_PUBLISH, QS_TIME_, QS_U8_, and QEvent::sig.

void QF_remove_ ( QActive const *  a)

Remove the active object from the framework.

This function should not be called by the application directly, only inside the QF port. The priority level occupied by the active object is freed-up and can be reused for another active object.

The active object that is removed from the framework can no longer participate in the publish-subscribe event exchange.

Note:
This function raises an assertion if the priority of the active object exceeds the maximum value QF_MAX_ACTIVE or is not used.

Definition at line 78 of file qf_act.c.

References QActive::prio, Q_REQUIRE, QF_active_, QF_MAX_ACTIVE, QS_aoObj_, QS_BEGIN_NOCRIT_, QS_END_NOCRIT_, QS_OBJ_, QS_QF_ACTIVE_REMOVE, QS_TIME_, and QS_U8_.

Referenced by QActive_stop().

void QF_run ( void  )

Transfers control to QF to run the application.

QF_run() is typically called from your startup code after you initialize the QF and start at least one active object with QActive_start(). Also, QF_start() call must precede the transfer of control to QF_run(), but some QF ports might call QF_start() from QF_run(). QF_run() typically never returns to the caller.

Note:
This function is strongly platform-dependent and is not implemented in the QF, but either in the QF port or in the Board Support Package (BSP) for the given application. All QF ports must implement QF_run().
When the Quantum Kernel (QK) is used as the underlying real-time kernel for the QF, all platfrom dependencies are handled in the QK, so no porting of QF is necessary. In other words, you only need to recompile the QF platform-independent code with the compiler for your platform, but you don't need to provide any platform-specific implementation (so, no qf_port.c file is necessary). Moreover, QK implements the function QF_run() in a platform-independent way, in the modile qk.c.

Definition at line 57 of file qvanilla.c.

References QActive_get_(), QF_active_, QF_gc(), QF_INT_DISABLE, QF_INT_ENABLE, QF_onIdle(), QF_onStartup(), QK_onIdle(), QPSet64_findMax, QPSet64_notEmpty, QPSet8_findMax, QPSet8_notEmpty, and QActive::super.

void QF_stop ( void  )

Function invoked by the application layer to stop the QF application and return control to the OS/Kernel.

This function stops the QF application. After calling this function, QF attempts to gracefully stop the application. This graceful shutdown might take some time to complete. The typical use of this funcition is for terminating the QF application to return back to the operating system or for handling fatal errors that require shutting down (and possibly re-setting) the system.

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_stop() at all, because many embedded applications don't have anything to exit to.

See also:
QF_onCleanup()

Definition at line 52 of file qvanilla.c.

References QF_onCleanup().

void QF_tick ( void const *  sender)

Processes all armed time events at every clock tick.

This function must be called periodically from a time-tick ISR or from the highest-priority task so that QF can manage the timeout events.

Note:
The QF_tick() function is not reentrant meaning that it must run to completion before it is called again. Also, QF_tick() assumes that it never will get preempted by a task, which is always the case when it is called from an ISR or the highest-priority task.
this function should be called only via the macro QF_TICK
See also:
QTimeEvt.

Definition at line 43 of file qf_tick.c.

References QTimeEvt::act, QTimeEvt::ctr, QTimeEvt::interval, QTimeEvt::next, QTimeEvt::prev, QACTIVE_POST, QF_timeEvtListHead_, QS_BEGIN_NOCRIT_, QS_END_NOCRIT_, QS_OBJ_, QS_QF_TICK, QS_QF_TIMEEVT_AUTO_DISARM, QS_QF_TIMEEVT_POST, QS_teObj_, QS_tickCtr_, QS_TIME_, QEvent::sig, and QTimeEvt::super.

void QTimeEvt_arm_ ( QTimeEvt me,
QActive act,
QTimeEvtCtr  nTicks 
)

Arm a time event (internal function to be used through macros only).

See also:
QTimeEvt_postIn, QTimeEvt_postEvery,

Definition at line 43 of file qte_arm.c.

References QTimeEvt::prev, Q_REQUIRE, Q_USER_SIG, QF_timeEvtListHead_, QS_BEGIN_NOCRIT_, QS_END_NOCRIT_, QS_OBJ_, QS_QF_TIMEEVT_ARM, QS_teObj_, and QS_TIME_.

void QTimeEvt_ctor ( QTimeEvt me,
QSignal  sig 
)

The "constructor" to initialize a Time Event.

You should call this function exactly once for every Time Event object BEFORE arming the Time Event. The most important action performed in this function is assigning a signal to the Time Event. You can reuse the Time Event any number of times, but you should not change the signal. This is because pointers to Time Events might still be held in event queues and changing signal could to hard-to-detect errors.

The following example shows the invocation of QTimeEvt_ctor() from the "constructor" of the Philosopher active object that owns the time event

void Philosopher_ctor(Philosopher *me) {
    QActive_ctor(&me->super, (QStateHandler)&Philosopher_initial);
    QTimeEvt_ctor(&me->timeEvt, TIMEOUT_SIG);
}

Definition at line 40 of file qte_ctor.c.

References Q_REQUIRE, Q_USER_SIG, and QF_EVT_POOL_ID_.

QTimeEvtCtr QTimeEvt_ctr ( QTimeEvt const *  me)

Get the current value of the down-counter of a time event.

If the time event is armed, the function returns the current value of the down-counter of the given time event. If the time event is not armed, the function returns 0.

/note The function is thread-safe.

Definition at line 37 of file qte_ctr.c.

References QTimeEvt::act, QTimeEvt::ctr, QTimeEvt::interval, QTimeEvt::prev, QS_BEGIN_NOCRIT_, QS_END_NOCRIT_, QS_OBJ_, QS_QF_TIMEEVT_CTR, QS_teObj_, and QS_TIME_.

uint8_t QTimeEvt_disarm ( QTimeEvt me)

Disarm a time event.

The time event me gets disarmed and can be reused. The function returns 1 (TRUE) if the time event was truly disarmed, that is, it was running. The return of 0 (FALSE) means that the time event was not truly disarmed because it was not running. The FALSE return is only possible for one-shot time events that have been automatically disarmed upon expiration. In this case the FALSE return means that the time event has already been posted or published and should be expected in the active object's state machine.

Definition at line 38 of file qte_darm.c.

References QTimeEvt::act, QTimeEvt::ctr, QTimeEvt::interval, QTimeEvt::next, QTimeEvt::prev, QF_timeEvtListHead_, QS_BEGIN_NOCRIT_, QS_END_NOCRIT_, QS_OBJ_, QS_QF_TIMEEVT_DISARM, QS_QF_TIMEEVT_DISARM_ATTEMPT, QS_teObj_, and QS_TIME_.

uint8_t QTimeEvt_rearm ( QTimeEvt me,
QTimeEvtCtr  nTicks 
)

Rearm a time event.

The time event me gets rearmed with a new number of clock ticks nTicks. This facility can be used to prevent a one-shot time event from expiring (e.g., a watchdog time event), or to adjusts the current period of a periodic time event. Rearming a periodic timer leaves the interval unchanged and is a convenient method to adjust the phasing of the periodic time event.

The function returns 1 (TRUE) if the time event was running as it was re-armed. The return of 0 (FALSE) means that the time event was not truly rearmed because it was not running. The FALSE return is only possible for one-shot time events that have been automatically disarmed upon expiration. In this case the FALSE return means that the time event has already been posted or published and should be expected in the active object's state machine.

Definition at line 40 of file qte_rarm.c.

References QTimeEvt::prev, Q_REQUIRE, Q_USER_SIG, QF_timeEvtListHead_, QS_BEGIN_NOCRIT_, QS_END_NOCRIT_, QS_OBJ_, QS_QF_TIMEEVT_REARM, QS_teObj_, QS_TIME_, and QS_U8_.


Variable Documentation

array of registered active objects

Note:
Not to be used by Clients directly, only in ports of QF

Definition at line 41 of file qf_act.c.

Referenced by QActive_subscribe(), QActive_unsubscribe(), QActive_unsubscribeAll(), QF_add_(), QF_getQueueMargin(), QF_publish(), QF_remove_(), QF_run(), QK_sched_(), and QK_schedExt_().

uint8_t const Q_ROM Q_ROM_VAR QF_div8Lkup[65]

Lookup table for (n-1)/8.

Note:
Index range n = 0..64. The first index (n == 0) should never be used.

Definition at line 77 of file qf_pwr2.c.

Referenced by QActive_subscribe(), QActive_unsubscribe(), and QActive_unsubscribeAll().

uint8_t const Q_ROM Q_ROM_VAR QF_invPwr2Lkup[65]

Lookup table for ~(1 << ((n-1) % 8)), where n is the index into the table.

Note:
Index range n = 0..64. The first index (n == 0) should never be used.

Definition at line 57 of file qf_pwr2.c.

Referenced by QActive_unsubscribe(), QActive_unsubscribeAll(), and QF_publish().

uint8_t const Q_ROM Q_ROM_VAR QF_log2Lkup[256]

Lookup table for (log2(n) + 1), where n is the index into the table.

This lookup delivers the 1-based number of the most significant 1-bit of a byte.

Note:
Index range n = 0..255. The first index (n == 0) should never be used.

Definition at line 37 of file qf_log2.c.

Referenced by QF_publish().

uint8_t const Q_ROM Q_ROM_VAR QF_pwr2Lkup[65]

Lookup table for (1 << ((n-1) % 8)), where n is the index into the table.

Note:
Index range n = 0..64. The first index (n == 0) should never be used.

Definition at line 37 of file qf_pwr2.c.

Referenced by QActive_subscribe(), and QActive_unsubscribeAll().