Linux Face / QPFramework
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers qf.h Source File

qf.h

Go to the documentation of this file.
00001 //////////////////////////////////////////////////////////////////////////////
00002 // Product: QF/C++ platform-independent public interface
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 06, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00027 //////////////////////////////////////////////////////////////////////////////
00028 #ifndef qf_h
00029 #define qf_h
00030 
00031 /// \file
00032 /// \ingroup qf qk
00033 /// \brief QF/C++ platform-independent public interface.
00034 ///
00035 /// This header file must be included directly or indirectly
00036 /// in all modules (*.cpp files) that use QF/C++.
00037 
00038 //////////////////////////////////////////////////////////////////////////////
00039 #if (QF_MAX_ACTIVE < 1) || (63 < QF_MAX_ACTIVE)
00040     #error "QF_MAX_ACTIVE not defined or out of range. Valid range is 1..63"
00041 #endif
00042 
00043 //////////////////////////////////////////////////////////////////////////////
00044 #ifndef QF_EVENT_SIZ_SIZE
00045 
00046     /// \brief Default value of the macro configurable value in qf_port.h
00047     #define QF_EVENT_SIZ_SIZE 2
00048 #endif
00049 #if (QF_EVENT_SIZ_SIZE == 1)
00050 
00051     /// \brief The data type to store the block-size defined based on
00052     /// the macro #QF_EVENT_SIZ_SIZE.
00053     ///
00054     /// The dynamic range of this data type determines the maximum block
00055     /// size that can be managed by the pool.
00056     typedef uint8_t QEventSize;
00057 #elif (QF_EVENT_SIZ_SIZE == 2)
00058     typedef uint16_t QEventSize;
00059 #elif (QF_EVENT_SIZ_SIZE == 4)
00060     typedef uint32_t QEventSize;
00061 #else
00062     #error "QF_EVENT_SIZ_SIZE defined incorrectly, expected 1, 2, or 4"
00063 #endif
00064 
00065 
00066 //////////////////////////////////////////////////////////////////////////////
00067 #ifndef QF_ACTIVE_SUPER_
00068 
00069     //////////////////////////////////////////////////////////////////////////
00070     /// \brief The macro defining the base class for QActive.
00071     ///
00072     /// By default, the ::QActive class is derived from ::QHsm. However,
00073     /// if the macro QF_ACTIVE_SUPER_ is defined, QActive is derived from
00074     /// QF_ACTIVE_SUPER_.
00075     ///
00076     /// Clients might choose, for example, to define QF_ACTIVE_SUPER_ as QFsm
00077     /// to avoid the 1-2KB overhead of the hierarchical event processor.
00078     ///
00079     /// Clients might also choose to define QF_ACTIVE_SUPER_ as their own
00080     /// completely customized class that has nothing to do with QHsm or QFsm.
00081     /// The QF_ACTIVE_SUPER_ class must provide member functions init() and
00082     /// dispatch(), consistent with the signatures of QHsm and QFsm. But
00083     /// the implementatin of these functions is completely open.
00084     #define QF_ACTIVE_SUPER_  QHsm
00085 
00086     /// \brief The argument of the base class' constructor.
00087     #define QF_ACTIVE_STATE_  QStateHandler
00088 
00089 #endif
00090 
00091 class QEQueue;                                          // forward declaration
00092 
00093 
00094 /// \brief Base class for derivation of application-level active object
00095 /// classes.
00096 ///
00097 /// QActive is the base class for derivation of active objects. Active objects
00098 /// in QF are encapsulated tasks (each embedding a state machine and an event
00099 /// queue) that communicate with one another asynchronously by sending and
00100 /// receiving events. Within an active object, events are processed
00101 /// sequentially in a run-to-completion (RTC) fashion, while QF encapsulates
00102 /// all the details of thread-safe event exchange and queuing.
00103 ///
00104 /// \note QActive is not intended to be instantiated directly, but rather
00105 /// serves as the base class for derivation of active objects in the
00106 /// application code.
00107 ///
00108 /// The following example illustrates how to derive an active object from
00109 /// QActive.
00110 /// \include qf_qactive.cpp
00111 ///
00112 /// \sa #QF_ACTIVE_SUPER_ defines the base class for QActive
00113 class QActive : public QF_ACTIVE_SUPER_ {
00114 private:
00115 
00116     /// \brief OS-dependent event-queue type.
00117     ///
00118     /// The type of the queue depends on the underlying operating system or
00119     /// a kernel. Many kernels support "message queues" that can be adapted
00120     /// to deliver QF events to the active object. Alternatively, QF provides
00121     /// a native event queue implementation that can be used as well.
00122     ///
00123     /// The native QF event queue is configured by defining the macro
00124     /// #QF_EQUEUE_TYPE as ::QEQueue.
00125     QF_EQUEUE_TYPE m_eQueue;
00126 
00127 public:
00128 #ifdef QF_OS_OBJECT_TYPE
00129     /// \brief OS-dependent per-thread object.
00130     ///
00131     /// This data might be used in various ways, depending on the QF port.
00132     /// In some ports m_osObject is used to block the calling thread when
00133     /// the native QF queue is empty. In other QF ports the OS-dependent
00134     /// object might be used differently.
00135     QF_OS_OBJECT_TYPE m_osObject;
00136 #endif
00137 
00138 #ifdef QF_THREAD_TYPE
00139     /// \brief OS-dependent representation of the thread of the active
00140     /// object.
00141     ///
00142     /// This data might be used in various ways, depending on the QF port.
00143     /// In some ports m_thread is used store the thread handle. In other ports
00144     /// m_thread can be the pointer to the Thread-Local-Storage (TLS).
00145     QF_THREAD_TYPE m_thread;
00146 #endif
00147 
00148     /// \brief QF priority associated with the active object.
00149     /// \sa QActive::start()
00150     uint8_t m_prio;
00151 
00152     /// \brief The Boolean loop variable determining if the thread routine
00153     /// of the active object is running.
00154     ///
00155     /// This flag is only used with the traditional loop-structured thread
00156     /// routines. Clearing this flag breaks out of the thread loop, which is
00157     /// often the cleanest way to terminate the thread. The following example
00158     /// illustrates the thread routine for Win32:
00159     /// \include qf_run.cpp
00160     uint8_t m_running;
00161 
00162 public:
00163 
00164     /// \brief Starts execution of an active object and registers the object
00165     /// with the framework.
00166     ///
00167     /// The function takes six arguments.
00168     /// \a prio is the priority of the active object. QF allows you to start
00169     /// up to 63 active objects, each one having a unique priority number
00170     /// between 1 and 63 inclusive, where higher numerical values correspond
00171     /// to higher priority (urgency) of the active object relative to the
00172     /// others.
00173     /// \a qSto[] and \a qLen arguments are the storage and size of the event
00174     /// queue used by this active object.
00175     /// \a stkSto and \a stkSize are the stack storage and size in bytes.
00176     /// Please note that a per-active object stack is used only when the
00177     /// underlying OS requies it. If the stack is not required, or the
00178     /// underlying OS allocates the stack internally, the \a stkSto should be
00179     /// NULL and/or \a stkSize should be 0.
00180     /// \a ie is an optional initialization event that can be used to pass
00181     /// additional startup data to the active object. (Pass NULL if your
00182     /// active object does not expect the initialization event).
00183     ///
00184     /// \note This function is strongly OS-dependent and must be defined in
00185     /// the QF port to a particular platform.
00186     ///
00187     /// The following example shows starting of the Philosopher object when a
00188     /// per-task stack is required:
00189     /// \include qf_start.cpp
00190     void start(uint8_t prio,
00191                QEvent const *qSto[], uint32_t qLen,
00192                void *stkSto, uint32_t stkSize,
00193                QEvent const *ie = (QEvent *)0);
00194 
00195     /// \brief Posts an event \a e directly to the event queue of the acitve
00196     /// object \a me using the First-In-First-Out (FIFO) policy.
00197     ///
00198     /// Direct event posting is the simplest asynchronous communication method
00199     /// available in QF. The following example illustrates how the Philosopher
00200     /// active obejct posts directly the HUNGRY event to the Table active
00201     /// object. \include qf_post.cpp
00202     ///
00203     /// \note The producer of the event (Philosopher in this case) must only
00204     /// "know" the recipient (Table) by a generic (QActive *QDPP_table)
00205     /// pointer, but the specific definition of the Table class is not
00206     /// required.
00207     ///
00208     /// \note Direct event posting should not be confused with direct event
00209     /// dispatching. In contrast to asynchronous event posting through event
00210     /// queues, direct event dispatching is synchronous. Direct event
00211     /// dispatching occurs when you call QHsm::dispatch(), or QFsm::dispatch()
00212     /// function.
00213     void postFIFO(QEvent const *e);
00214 
00215     /// \brief Posts an event directly to the event queue of the active object
00216     /// \a me using the Last-In-First-Out (LIFO) policy.
00217     ///
00218     /// \note The LIFO policy should be used only with great caution because
00219     /// it alters order of events in the queue.
00220     /// \sa QActive::postFIFO()
00221     void postLIFO(QEvent const *e);
00222 
00223     /// \brief Traditional loop-structured thread routine for an active object
00224     ///
00225     /// This function is only used when QF is ported to a traditional
00226     /// RTOS/Kernel. QActive::run() is structured as a typical endless loop,
00227     /// which blocks on the event queue get() operation of an active object.
00228     /// When an event becomes available, it's dispatched to the active
00229     /// object's state machine and after this recycled with QF::gc().
00230     /// The loop might optionally use the QActive::m_running flag to terminate
00231     /// and cause QActive::run() to return which is often the cleanest way to
00232     /// terminate the thread.
00233     void run(void);
00234 
00235     /// \brief Get an event from the event queue of an active object.
00236     ///
00237     /// This function is used internally by a QF port to extract events from
00238     /// the event queue of an active object. This function depends on the
00239     /// event queue implementation and is sometimes implemented in the QF port
00240     /// (qf_port.cpp file). Depending on the underlying OS or kernel, the
00241     /// function might block the calling thread when no events are available.
00242     ///
00243     /// \note QActive::get_() is public because it often needs to be called
00244     /// from thread-run routines with difficult to foresee signature (so
00245     /// declaring friendship with such function(s) is not possible.)
00246     ///
00247     /// \sa QActive::postFIFO(), QActive::postLIFO()
00248     QEvent const *get_(void);
00249 
00250 protected:
00251 
00252     /// \brief protected constructor
00253     ///
00254     /// Performs the first step of active object initialization by assigning
00255     /// the initial pseudostate to the currently active state of the state
00256     /// machine.
00257     ///
00258     /// \note The constructor is protected to prevent direct instantiation
00259     /// of QActive objects. This class is intended only for derivation
00260     /// (abstract class).
00261     QActive(QF_ACTIVE_STATE_ initial) : QF_ACTIVE_SUPER_(initial) {
00262     }
00263 
00264     /// \brief Stops execution of an active object and removes it from the
00265     /// framework's supervision.
00266     ///
00267     /// The preferred way of calling this function is from within the active
00268     /// object that needs to stop (that's why this function is protected).
00269     /// In other words, an active object should stop itself rather than being
00270     /// stopped by some other entity. This policy works best, because only
00271     /// the active object itself "knows" when it has reached the appropriate
00272     /// state for the shutdown.
00273     ///
00274     /// \note This function is strongly OS-dependent and should be defined in
00275     /// the QF port to a particular platform. This function is optional in
00276     /// embedded systems where active objects never need to be stopped.
00277     void stop(void);
00278 
00279     /// \brief Subscribes for delivery of signal \a sig to the active object
00280     ///
00281     /// This function is part of the Publish-Subscribe event delivery
00282     /// mechanism available in QF. Subscribing to an event means that the
00283     /// framework will start posting all published events with a given signal
00284     /// \a sig to the event queue of the active object.
00285     ///
00286     /// The following example shows how the Table active object subscribes
00287     /// to three signals in the initial transition:
00288     /// \include qf_subscribe.cpp
00289     ///
00290     /// \sa QF::publish(), QActive::unsubscribe(), and
00291     /// QActive::unsubscribeAll()
00292     void subscribe(QSignal sig) const;
00293 
00294     /// \brief Un-subscribes from the delivery of signal \a sig to the
00295     /// active object.
00296     ///
00297     /// This function is part of the Publish-Subscribe event delivery
00298     /// mechanism available in QF. Un-subscribing from an event means that
00299     /// the framework will stop posting published events with a given signal
00300     /// \a sig to the event queue of the active object.
00301     ///
00302     /// \note Due to the latency of event queues, an active object should NOT
00303     /// assume that a given signal \a sig will never be dispatched to the
00304     /// state machine of the active object after un-subscribing from that
00305     /// signal. The event might be already in the queue, or just about to be
00306     /// posted and the un-subscribe operation will not flush such events.
00307     ///
00308     /// \note Un-subscribing from a signal that has never been subscribed in
00309     /// the first place is considered an error and QF will rise an assertion.
00310     ///
00311     /// \sa QF::publish(), QActive::subscribe(), and QActive::unsubscribeAll()
00312     void unsubscribe(QSignal sig) const;
00313 
00314     /// \brief Defer an event to a given separate event queue.
00315     ///
00316     /// This function is part of the event deferral support. An active object
00317     /// uses this function to defer an event \a e to the QF-supported native
00318     /// event queue \a eq. QF correctly accounts for another outstanding
00319     /// reference to the event and will not recycle the event at the end of
00320     /// the RTC step. Later, the active object might recall one event at a
00321     /// time from the event queue.
00322     ///
00323     /// An active object can use multiple event queues to defer events of
00324     /// different kinds.
00325     ///
00326     /// \sa QActive::recall(), QEQueue
00327     void defer(QEQueue *eq, QEvent const *e);
00328 
00329     /// \brief Recall a deferred event from a given event queue.
00330     ///
00331     /// This function is part of the event deferral support. An active object
00332     /// uses this function to recall a deferred event from a given QF
00333     /// event queue. Recalling an event means that it is removed from the
00334     /// deferred event queue \a eq and posted (LIFO) to the event queue of
00335     /// the active object.
00336     ///
00337     /// QActive::recall() returns the pointer to the recalled event to the
00338     /// caller. The function returns NULL if no event has been recalled.
00339     ///
00340     /// An active object can use multiple event queues to defer events of
00341     /// different kinds.
00342     ///
00343     /// \sa QActive::defer(), QEQueue, QActive::postLIFO()
00344     QEvent const *recall(QEQueue *eq);
00345 
00346 public:
00347     /// \brief Un-subscribes from the delivery of all signals to the active
00348     /// object.
00349     ///
00350     /// This function is part of the Publish-Subscribe event delivery
00351     /// mechanism available in QF. Un-subscribing from all events means that
00352     /// the framework will stop posting any published events to the event
00353     /// queue of the active object.
00354     ///
00355     /// \note Due to the latency of event queues, an active object should NOT
00356     /// assume that no events will ever be dispatched to the state machine of
00357     /// the active object after un-subscribing from all events.
00358     /// The events might be already in the queue, or just about to be posted
00359     /// and the un-subscribe operation will not flush such events. Also, the
00360     /// alternative event-delivery mechanisms, such as direct event posting or
00361     /// time events, can be still delivered to the event queue of the active
00362     /// object.
00363     ///
00364     /// \sa QF::publish(), QActive::subscribe(), and QActive::unsubscribe()
00365     void unsubscribeAll(void) const;
00366 
00367 private:
00368 
00369     friend class QF;
00370     friend class QTimeEvt;
00371     #ifndef QF_INT_KEY_TYPE
00372         friend void QK_schedule_(void);
00373         friend void QK_scheduleExt_(void);
00374     #else
00375         friend void QK_schedule_(QF_INT_KEY_TYPE intLockKey);
00376         friend void QK_scheduleExt_(QF_INT_KEY_TYPE intLockKey);
00377     #endif
00378 };
00379 
00380 
00381 //////////////////////////////////////////////////////////////////////////////
00382 #ifndef QF_TIMEEVT_CTR_SIZE
00383     /// \brief macro to override the default QTimeEvtCtr size.
00384     /// Valid values 1, 2, or 4; default 2
00385     #define QF_TIMEEVT_CTR_SIZE 2
00386 #endif
00387 #if (QF_TIMEEVT_CTR_SIZE == 1)
00388 
00389     /// \brief type of the Time Event counter, which determines the dynamic
00390     /// range of the time delays measured in clock ticks.
00391     ///
00392     /// This typedef is configurable via the preprocessor switch
00393     /// #QF_TIMEEVT_CTR_SIZE. The other possible values of this type are
00394     /// as follows: \n
00395     /// uint8_t when (QF_TIMEEVT_CTR_SIZE == 1), and \n
00396     /// uint32_t when (QF_TIMEEVT_CTR_SIZE == 4).
00397     typedef uint8_t QTimeEvtCtr;
00398 #elif (QF_TIMEEVT_CTR_SIZE == 2)
00399     typedef uint16_t QTimeEvtCtr;
00400 #elif (QF_TIMEEVT_CTR_SIZE == 4)
00401     typedef uint32_t QTimeEvtCtr;
00402 #else
00403     #error "QF_TIMEEVT_CTR_SIZE defined incorrectly, expected 1, 2, or 4"
00404 #endif
00405 
00406 //////////////////////////////////////////////////////////////////////////////
00407 /// \brief Time Event class
00408 ///
00409 /// Time events are special QF events equipped with the notion of time
00410 /// passage. The basic usage model of the time events is as follows. An
00411 /// active object allocates one or more QTimeEvt objects (provides the
00412 /// storage for them). When the active object needs to arrange for a timeout,
00413 /// it arms one of its time events to fire either just once (one-shot) or
00414 /// periodically. Each time event times out independently from the others,
00415 /// so a QF application can make multiple parallel timeout requests (from the
00416 /// same or different active objects). When QF detects that the appropriate
00417 /// moment has arrived, it inserts the time event directly into the
00418 /// recipient's event queue. The recipient then processes the time event just
00419 /// like any other event.
00420 ///
00421 /// Time events, as any other QF events derive from the ::QEvent base
00422 /// class. Typically, you will use a time event as-is, but you can also
00423 /// further derive more specialized time events from it by adding some more
00424 /// data members and/or specialized functions that operate on the specialized
00425 /// time events.
00426 ///
00427 /// Internally, the armed time events are organized into a bi-directional
00428 /// linked list. This linked list is scanned in every invocation of the
00429 /// QF::tick() function. Only armed (timing out) time events are in the list,
00430 /// so only armed time events consume CPU cycles.
00431 ///
00432 /// \note QF manages the time events in the function QF::tick(), which
00433 /// must be called periodically, preferably from the clock tick ISR.
00434 /// \note In this version of QF QTimeEvt objects should be allocated
00435 /// statically rather than dynamically from event pools. Currently, QF will
00436 /// not correctly recycle the dynamically allocated Time Events.
00437 class QTimeEvt : public QEvent {
00438 private:
00439 
00440     //// link to the previous time event in the list
00441     QTimeEvt *m_prev;
00442 
00443     /// link to the next time event in the list
00444     QTimeEvt *m_next;
00445 
00446     /// the active object that receives the time events.
00447     QActive *m_act;
00448 
00449     /// the internal down-counter of the time event. The down-counter
00450     /// is decremented by 1 in every QF_tick() invocation. The time event
00451     /// fires (gets posted or published) when the down-counter reaches zero.
00452     QTimeEvtCtr m_ctr;
00453 
00454     /// the interval for the periodic time event (zero for the one-shot
00455     /// time event). The value of the interval is re-loaded to the internal
00456     /// down-counter when the time event expires, so that the time event
00457     /// keeps timing out periodically.
00458     QTimeEvtCtr m_interval;
00459 
00460 public:
00461 
00462     /// \brief The Time Event constructor.
00463     ///
00464     /// The most important initialization performed in  the constructor is
00465     /// assigning a signal to the Time Event. You can reuse the Time Event
00466     /// any number of times, but you cannot change the signal.
00467     /// This is because pointers to Time Events might still be held in event
00468     /// queues and changing signal could to hard-to-detect errors.
00469     ///
00470     /// The following example shows the use of QTimeEvt::QTimeEvt()
00471     /// constructor in the constructor initializer list of the Philosopher
00472     /// active object constructor that owns the time event
00473     /// \include qf_ctor.cpp
00474     QTimeEvt(QSignal s);
00475 
00476     /// \brief Arm a one-shot time event for direct event posting.
00477     ///
00478     /// Arms a time event to fire in \a nTicks clock ticks (one-shot time
00479     /// event). The time event gets directly posted (using the FIFO policy)
00480     /// into the event queue of the active object \a act.
00481     ///
00482     /// After posting, the time event gets automatically disarmed and can be
00483     /// reused for a one-shot or periodic timeout requests.
00484     ///
00485     /// A one-shot time event can be disarmed at any time by calling the
00486     /// QTimeEvt::disarm() function. Also, a one-shot time event can be
00487     /// re-armed to fire in a different number of clock ticks by calling the
00488     /// QTimeEvt::rearm() function.
00489     ///
00490     /// The following example shows how to arm a one-shot time event from a
00491     /// state machine of an active object:
00492     /// \include qf_state.cpp
00493     void postIn(QActive *act, QTimeEvtCtr nTicks) {
00494         m_interval = (uint16_t)0;
00495         arm_(act, nTicks);
00496     }
00497 
00498     /// \brief Arm a periodic time event for direct event posting.
00499     ///
00500     /// Arms a time event to fire every \a nTicks clock ticks (periodic time
00501     /// event). The time event gets directly posted (using the FIFO policy)
00502     /// into the event queue of the active object \a act.
00503     ///
00504     /// After posting, the time event gets automatically re-armed to fire
00505     /// again in the specified \a nTicks clock ticks.
00506     ///
00507     /// A periodic time event can be disarmed only by calling the
00508     /// QTimeEvt::disarm() function. After disarming, the time event can be
00509     /// reused for a one-shot or periodic timeout requests.
00510     ///
00511     /// \note An attempt to reuse (arm again) a running periodic time event
00512     /// raises an assertion.
00513     ///
00514     /// Also, a periodic time event can be re-armed to shorten or extend the
00515     /// current period by calling the QTimeEvt_rearm() function. After
00516     /// adjusting the current period, the periodic time event goes back
00517     /// timing out at the original rate.
00518     void postEvery(QActive *act, QTimeEvtCtr nTicks) {
00519         m_interval = nTicks;
00520         arm_(act, nTicks);
00521     }
00522 
00523     /// \brief Disarm a time event.
00524     ///
00525     /// The time event gets disarmed and can be reused. The function
00526     /// returns 1 (TRUE) if the time event was truly disarmed, that is, it
00527     /// was running. The return of 0 (FALSE) means that the time event was
00528     /// not truly disarmed because it was not running. The FALSE return is
00529     /// only possible for one-shot time events that have been automatically
00530     /// disarmed upon expiration. In this case the FALSE return means that
00531     /// the time event has already been posted or published and should be
00532     /// expected in the active object's state machine.
00533     uint8_t disarm(void);
00534 
00535     /// \brief Rearm a time event.
00536     ///
00537     /// The time event gets rearmed with a new number of clock ticks
00538     /// \a nTicks. This facility can be used to prevent a one-shot time event
00539     /// from expiring (e.g., a watchdog time event), or to adjusts the
00540     /// current period of a periodic time event. Rearming a periodic timer
00541     /// leaves the interval unchanged and is a convenient method to adjust the
00542     /// phasing of the periodic time event.
00543     ///
00544     /// The function returns 1 (TRUE) if the time event was running as it
00545     /// was re-armed. The return of 0 (FALSE) means that the time event was
00546     /// not truly rearmed because it was not running. The FALSE return is only
00547     /// possible for one-shot time events that have been automatically
00548     /// disarmed upon expiration. In this case the FALSE return means that
00549     /// the time event has already been posted or published and should be
00550     /// expected in the active object's state machine.
00551     uint8_t rearm(QTimeEvtCtr nTicks);
00552 
00553     // for backwards compatibility
00554 
00555     /// \brief Arm a one-shot time event for direct event posting (obsolete).
00556     ///
00557     /// This facility is now obsolete, please use \sa QTimeEvt::postIn().
00558     void fireIn(QActive *act, QTimeEvtCtr nTicks) {
00559         postIn(act, nTicks);
00560     }
00561 
00562     /// \brief Arm a periodic time event for direct event posting (obsolete).
00563     ///
00564     /// This facility is now obsolete, please use \sa QTimeEvt::postEvery().
00565     void fireEvery(QActive *act, QTimeEvtCtr nTicks) {
00566         postEvery(act, nTicks);
00567     }
00568 
00569 private:
00570 
00571     /// \brief Arm a time event (internal function to be used through macros
00572     /// only).
00573     ///
00574     /// \sa QTimeEvt::postIn(), QTimeEvt::postEvery(),
00575     /// \sa QTimeEvt::publishIn(), QTimeEvt::publishEvery()
00576     void arm_(QActive *act, QTimeEvtCtr nTicks);
00577 
00578     friend class QF;
00579 };
00580 
00581 
00582 #if (QF_MAX_ACTIVE > 63)
00583     #error "QF_MAX_ACTIVE exceeds 63"
00584 #endif
00585 
00586 //////////////////////////////////////////////////////////////////////////////
00587 /// \brief Subscriber List class
00588 ///
00589 /// This data type represents a set of active objects that subscribe to
00590 /// a given signal. The set is represented as an array of bits, where each
00591 /// bit corresponds to the unique priority of an active object.
00592 class QSubscrList {
00593 private:
00594 
00595     /// An array of bits representing subscriber active objects. Each bit
00596     /// in the array corresponds to the unique priority of the active object.
00597     /// The size of the array is determined of the maximum number of active
00598     /// objects in the application configured by the #QF_MAX_ACTIVE macro.
00599     /// For example, an active object of priority p is a subscriber if the
00600     /// following is true: ((m_bits[QF_div8Lkup[p]] & QF_pwr2Lkup[p]) != 0)
00601     ///
00602     /// \sa QF::psInit(), QF_div8Lkup, QF_pwr2Lkup, #QF_MAX_ACTIVE
00603     uint8_t m_bits[((QF_MAX_ACTIVE - 1) / 8) + 1];
00604 
00605     friend class QF;
00606     friend class QActive;
00607 };
00608 
00609 //////////////////////////////////////////////////////////////////////////////
00610 /// \brief QF services.
00611 ///
00612 /// This class groups together QF services. It has only static members and
00613 /// should not be instantiated.
00614 class QF {
00615 public:
00616 
00617     /// \brief QF initialization.
00618     ///
00619     /// This function initializes QF and must be called exactly once before
00620     /// any other QF function.
00621     static void init(void);
00622 
00623     /// \brief Publish-subscribe initialization.
00624     ///
00625     /// This function initializes the publish-subscribe facilities of QF and
00626     /// must be called exactly once before any subscriptions/publications
00627     /// occur in the application. The arguments are as follows: \a subscrSto
00628     /// is a pointer to the array of subscriber-lists. \a maxSignal is the
00629     /// dimension of this array and at the same time the maximum signal that
00630     /// can be published or subscribed.
00631     ///
00632     /// The array of subscriber-lists is indexed by signals and provides
00633     /// mapping between the signals and subscirber-lists. The subscriber-
00634     /// lists are bitmasks of type ::QSubscrList, each bit in the bitmask
00635     /// corresponding to the unique priority of an active object. The size
00636     /// of the ::QSubscrList bitmask depends on the value of the
00637     /// #QF_MAX_ACTIVE macro.
00638     ///
00639     /// \note The publish-subscribe facilities are optional, meaning that
00640     /// you might choose not to use publish-subscribe. In that case calling
00641     /// QF::psInit() and using up memory for the subscriber-lists is
00642     /// unnecessary.
00643     ///
00644     /// \sa ::QSubscrList
00645     ///
00646     /// The following example shows the typical initialization sequence of
00647     /// QF: \include qf_main.cpp
00648     static void psInit(QSubscrList *subscrSto, QSignal maxSignal);
00649 
00650     /// \brief Event pool initialization for dynamic allocation of events.
00651     ///
00652     /// This function initializes one event pool at a time and must be called
00653     /// exactly once for each event pool before the pool can be used.
00654     /// The arguments are as follows: \a poolSto is a pointer to the memory
00655     /// block for the events. \a poolSize is the size of the memory block in
00656     /// bytes. \a evtSize is the block-size of the pool in bytes, which
00657     /// determines the maximum size of events that can be allocated from the
00658     /// pool.
00659     ///
00660     /// You might initialize one, two, and up to three event pools by making
00661     /// one, two, or three calls to the QF_poolInit() function. However,
00662     /// for the simplicity of the internal implementation, you must initialize
00663     /// event pools in the ascending order of the event size.
00664     ///
00665     /// Many RTOSes provide fixed block-size heaps, a.k.a. memory pools that
00666     /// can be used for QF event pools. In case such support is missing, QF
00667     /// provides a native QF event pool implementation. The macro
00668     /// #QF_EPOOL_TYPE_ determines the type of event pool used by a
00669     /// particular QF port. See class ::QMPool for more information.
00670     ///
00671     /// \note The actual number of events available in the pool might be
00672     /// actually less than (\a poolSize / \a evtSize) due to the internal
00673     /// alignment of the blocks that the pool might perform. You can always
00674     /// check the capacity of the pool by calling QF::getPoolMargin().
00675     ///
00676     /// \note The dynamic allocation of events is optional, meaning that you
00677     /// might choose not to use dynamic events. In that case calling
00678     /// QF::poolInit() and using up memory for the memory blocks is
00679     /// unnecessary.
00680     ///
00681     /// \sa QF initialization example for QF::init()
00682     static void poolInit(void *poolSto, uint32_t poolSize,
00683                          QEventSize evtSize);
00684 
00685     /// \brief Transfers control to QF to run the application.
00686     ///
00687     /// QF::run() is typically called from your startup code after you
00688     /// initialize the QF and start at least one active object with
00689     /// QActive::start(). Also, QF::start() call must precede the transfer
00690     /// of control to QF::run(), but some QF ports might call QF::start()
00691     /// from QF::run(). QF::run() typically never returns to the caller.
00692     ///
00693     /// \note This function is strongly platform-dependent and is not
00694     /// implemented in the QF, but either in the QF port or in the
00695     /// Board Support Package (BSP) for the given application. All QF ports
00696     /// must implement QF::run().
00697     ///
00698     /// \note When the Quantum Kernel (QK) is used as the underlying real-time
00699     /// kernel for the QF, all platfrom dependencies are handled in the QK, so
00700     /// no porting of QF is necessary. In other words, you only need to
00701     /// recompile the QF platform-independent code with the compiler for your
00702     /// platform, but you don't need to provide any platform-specific
00703     /// implementation (so, no qf_port.cpp file is necessary). Moreover, QK
00704     /// implements the function QF::run() in a platform-independent way,
00705     /// in the modile qk.cpp.
00706     static void run(void);
00707 
00708     /// \brief Startup QF callback.
00709     ///
00710     /// The timeline for calling QF::onStartup() depends on the particular
00711     /// QF port. In most cases, QF::onStartup() is called from QF::run(),
00712     /// right before starting any multitasking kernel or the background loop.
00713     static void onStartup(void);
00714 
00715     /// \brief Cleanup QF callback.
00716     ///
00717     /// QF::onCleanup() is called in some QF ports before QF returns to the
00718     /// underlying operating system or RTOS.
00719     ///
00720     /// This function is strongly platform-specific and is not implemented in
00721     /// the QF but either in the QF port or in the Board Support Package (BSP)
00722     /// for the given application. Some QF ports might not require
00723     /// implementing QF::onCleanup() at all, because many embedded
00724     /// applications don't have anything to exit to.
00725     ///
00726     /// \sa QF::init() and QF::stop()
00727     static void onCleanup(void);
00728 
00729 #ifndef QF_INT_KEY_TYPE
00730     static void onIdle(void);                // interrupt lock key NOT defined
00731 
00732 #else
00733 
00734     /// \brief QF idle callback (customized in BSPs for QF)
00735     ///
00736     /// QF::onIdle() is called by the non-preemptive scheduler built into QF
00737     /// when the framework detects that no events are available for active
00738     /// objects (the idle condition). This callback gives the application an
00739     /// opportunity to enter a power-saving CPU mode, or perform some other
00740     /// idle processing (such as Q-Spy output).
00741     ///
00742     /// \note QF::onIdle() is invoked with interrupts LOCKED because the idle
00743     /// condition can be asynchronously changed at any time by an interrupt.
00744     /// QF::onIdle() MUST unlock the interrupts internally, but not before
00745     /// putting the CPU into the low-power mode. (Ideally, unlocking
00746     /// interrupts and low-power mode should happen atomically). At the very
00747     /// least, the function MUST unlock interrupts, otherwise interrups will
00748     /// be locked permanently.
00749     ///
00750     /// \note QF::onIdle() is only used by the non-preemptive scheduler built
00751     /// into QF in the "bare metal" port, and is NOT used in any other ports.
00752     /// When QF is combined with QK, the QK idle loop calls a different
00753     /// function QK::onIdle(), with different semantics than QF::onIdle().
00754     /// When QF is combined with a 3rd-party RTOS or kernel, the idle
00755     /// processing mechanism of the RTOS or kernal is used instead of
00756     /// QF::onIdle().
00757     static void onIdle(QF_INT_KEY_TYPE intLockKey);   // int. lock key defined
00758 
00759 #endif                                                      // QF_INT_KEY_TYPE
00760 
00761     /// \brief Function invoked by the application layer to stop the QF
00762     /// application and return control to the OS/Kernel.
00763     ///
00764     /// This function stops the QF application. After calling this function,
00765     /// QF attempts to gracefully stop the  application. This graceful
00766     /// shutdown might take some time to complete. The typical use of this
00767     /// funcition is for terminating the QF application to return back to the
00768     /// operating system or for handling fatal errors that require shutting
00769     /// down (and possibly re-setting) the system.
00770     ///
00771     /// This function is strongly platform-specific and is not implemented in
00772     /// the QF but either in the QF port or in the Board Support Package (BSP)
00773     /// for the given application. Some QF ports might not require
00774     /// implementing QF::stop() at all, because many embedded application
00775     /// don't have anything to exit to.
00776     ///
00777     /// \sa QF::stop() and QF::onCleanup()
00778     static void stop(void);
00779 
00780     /// \brief Publish event to the framework.
00781     ///
00782     /// This function posts (using the FIFO policy) the event \a e it to ALL
00783     /// active object that have subscribed to the signal \a e->sig.
00784     /// This function is designed to be callable from any part of the system,
00785     /// including ISRs, device drivers, and active objects.
00786     ///
00787     /// In the general case, event publishing requires multi-casting the
00788     /// event to multiple subscribers. This happens in the caller's thread
00789     /// with the scheduler locked to prevent preemptions during the multi-
00790     /// casting process. (Please note that the interrupts are not locked.)
00791     static void publish(QEvent const *e);
00792 
00793     /// \brief Processes all armed time events at every clock tick.
00794     ///
00795     /// This function must be called periodically from a time-tick ISR or from
00796     /// the highest-priority task so that QF can manage the timeout events.
00797     ///
00798     /// \note The QF::tick() function is not reentrant meaning that it must
00799     /// run to completion before it is called again. Also, QF::tick() assumes
00800     /// that it never will get preempted by a task, which is always the case
00801     /// when it is called from an ISR or the highest-priority task.
00802     ///
00803     /// \sa ::QTimeEvt.
00804     ///
00805     /// The following example illustrates the call to QF::tick():
00806     /// \include qf_tick.cpp
00807     static void tick(void);
00808 
00809     /// \brief Returns the QF version.
00810     ///
00811     /// This function returns constant version string in the format x.y.zz,
00812     /// where x (one digit) is the major version, y (one digit) is the minor
00813     /// version, and zz (two digits) is the maintenance release version.
00814     /// An example of the version string is "3.1.03".
00815     ///
00816     /// The following example illustrates the usage of this function:
00817     /// \include qf_version.cpp
00818     static char const Q_ROM * Q_ROM_VAR getVersion(void);
00819 
00820     /// \brief Returns the QF-port version.
00821     ///
00822     /// This function returns constant version string in the format x.y.zz,
00823     /// where x (one digit) is the major version, y (one digit) is the minor
00824     /// version, and zz (two digits) is the maintenance release version.
00825     /// An example of the QF-port version string is "1.1.03".
00826     ///
00827     /// \sa QF::getVersion()
00828     static char const Q_ROM * Q_ROM_VAR getPortVersion(void);
00829 
00830     /// \brief This function returns the margin of the given event pool.
00831     ///
00832     /// This function returns the margin of the given event pool \a poolId,
00833     /// where poolId is the ID of the pool initialized by the call to
00834     /// QF::poolInit(). The poolId of the first initialized pool is 1, the
00835     /// second 2, and so on.
00836     ///
00837     /// The returned pool margin is the minimal number of free blocks
00838     /// encountered in the given pool since system startup.
00839     ///
00840     /// \note Requesting the margin of an un-initialized pool raises an
00841     /// assertion in the QF.
00842     static uint32_t getPoolMargin(uint8_t poolId);
00843 
00844     /// \brief This function returns the margin of the given event queue.
00845     ///
00846     /// This function returns the margin of the given event queue of an active
00847     /// object with priority \a prio. (QF priorities start with 1 and go up to
00848     /// #QF_MAX_ACTIVE.) The margin is the minimal number of free events
00849     /// encountered in the given queue since system startup.
00850     ///
00851     /// \note QF::getQueueMargin() is available only when the native QF event
00852     /// queue implementation is used. Requesting the queue margin of an unused
00853     /// priority level raises an assertion in the QF. (A priority level
00854     /// becomes used in QF after the call to the QF::add_() function.)
00855     static uint32_t getQueueMargin(uint8_t prio);
00856 
00857     /// \brief Internal QF implementation of the dynamic event allocator.
00858     ///
00859     /// \note The application code should not call this function directly.
00860     /// Please use the macro #Q_NEW.
00861     static QEvent *new_(uint16_t evtSize, QSignal sig);
00862 
00863     /// \brief Allocate a dynamic event.
00864     ///
00865     /// This macro returns an event pointer cast to the type \a evtT_. The
00866     /// event is initialized with the signal \a sig. Internally, the macro
00867     /// calls the internal QF function QF::new_(), which always returns a
00868     /// valid event pointer.
00869     ///
00870     /// \note The internal QF function QF::new_() raises an assertion when
00871     /// the allocation of the event turns out to be impossible due to event
00872     /// pool depletion, or incorrect (too big) size of the requested event.
00873     ///
00874     /// The following example illustrates dynamic allocation of an event:
00875     /// \include qf_post.cpp
00876     #define Q_NEW(evtT_, sig_) ((evtT_ *)QF::new_(sizeof(evtT_), (sig_)))
00877 
00878     /// \brief Recycle a dynamic event.
00879     ///
00880     /// This function implements a simple garbage collector for the dynamic
00881     /// events. Only dynamic events are candidates for recycling. (A dynamic
00882     /// event is one that is allocated from an event pool, which is
00883     /// determined as non-zero e->attrQF__ attribute.) Next, the function
00884     /// decrements the reference counter of the event, and recycles the event
00885     /// only if the counter drops to zero (meaning that no more references
00886     /// are outstanding for this event). The dynamic event is recycled by
00887     /// returning it to the pool from which it was originally allocated.
00888     /// The pool-of-origin information is stored in the upper 2-MSBs of the
00889     /// e->attrQF__ attribute.)
00890     ///
00891     /// \note QF invokes the garbage collector at all appropriate contexts,
00892     /// when an event can become garbage (automatic garbage collection),
00893     /// so the application code should have NO need to call QF::gc() directly.
00894     /// The QF::gc() function is exposed only for special cases when your
00895     /// application sends dynamic events to the "raw" thread-safe queues
00896     /// (see ::QEQueue). Such queues are processed outside of QF and the
00897     /// automatic garbage collection CANNOT be performed for these events.
00898     /// In this case you need to call QF::gc() explicitly.
00899     static void gc(QEvent const *e);
00900 
00901     /// \brief array of registered active objects
00902     ///
00903     /// \note Not to be used by Clients directly, only in ports of QF
00904     static QActive *active_[];
00905 
00906 private:                              // functions to be used in QF ports only
00907 
00908     /// \brief Register an active object to be managed by the framework
00909     ///
00910     /// This function should not be called by the application directly, only
00911     /// through the function QActive::start(). The priority of the active
00912     /// object \a a should be set before calling this function.
00913     ///
00914     /// \note This function raises an assertion if the priority of the active
00915     /// object exceeds the maximum value #QF_MAX_ACTIVE. Also, this function
00916     /// raises an assertion if the priority of the active object is already in
00917     /// use. (QF requires each active object to have a UNIQUE priority.)
00918     static void add_(QActive *a);
00919 
00920 public:
00921     /// \brief Remove the active object from the framework.
00922     ///
00923     /// This function should not be called by the application directly, only
00924     /// inside the QF port. The priority level occupied by the active object
00925     /// is freed-up and can be reused for another active object.
00926     ///
00927     /// The active object that is removed from the framework can no longer
00928     /// participate in the publish-subscribe event exchange.
00929     ///
00930     /// \note This function raises an assertion if the priority of the active
00931     /// object exceeds the maximum value #QF_MAX_ACTIVE or is not used.
00932     static void remove_(QActive const *a);
00933 
00934     friend class QActive;
00935 };
00936 
00937 //////////////////////////////////////////////////////////////////////////////
00938 // useful lookup tables
00939 
00940 /// \brief Lookup table for (log2(n) + 1), where n is the index
00941 /// into the table.
00942 ///
00943 /// This lookup delivers the 1-based number of the most significant 1-bit
00944 /// of a byte.
00945 ///
00946 /// \note Index range n = 0..255. The first index (n == 0) should never
00947 /// be used.
00948 ///
00949 extern uint8_t const Q_ROM Q_ROM_VAR QF_log2Lkup[256];
00950 
00951 /// \brief Lookup table for (1 << ((n-1) % 8)), where n is the index
00952 /// into the table.
00953 ///
00954 /// \note Index range n = 0..64. The first index (n == 0) should never
00955 /// be used.
00956 extern uint8_t const Q_ROM Q_ROM_VAR QF_pwr2Lkup[65];
00957 
00958 /// \brief Lookup table for ~(1 << ((n-1) % 8)), where n is the index
00959 /// into the table.
00960 ///
00961 /// \note Index range n = 0..64. The first index (n == 0) should never
00962 /// be used.
00963 extern uint8_t const Q_ROM Q_ROM_VAR QF_invPwr2Lkup[65];
00964 
00965 /// \brief Lookup table for (n-1)/8
00966 ///
00967 /// \note Index range n = 0..64. The first index (n == 0) should never
00968 /// be used.
00969 extern uint8_t const Q_ROM Q_ROM_VAR QF_div8Lkup[65];
00970 
00971 
00972 //////////////////////////////////////////////////////////////////////////////
00973 // QS software tracing integration, only if enabled
00974 #ifdef Q_SPY                                   // QS software tracing enabled?
00975     #ifndef qs_h
00976     #include "qs_port.h"                                    // include QS port
00977     #endif                                                             // qs_h
00978 
00979     #if (QF_EQUEUE_CTR_SIZE == 1)
00980 
00981         /// \brief Internal QS macro to output an unformatted event queue
00982         /// counter data element
00983         /// \note the counter size depends on the macro #QF_EQUEUE_CTR_SIZE.
00984         #define QS_EQC_(ctr_)       QS::u8_(ctr_)
00985     #elif (QF_EQUEUE_CTR_SIZE == 2)
00986         #define QS_EQC_(ctr_)       QS::u16_(ctr_)
00987     #elif (QF_EQUEUE_CTR_SIZE == 4)
00988         #define QS_EQC_(ctr_)       QS::u32_(ctr_)
00989     #else
00990         #error "QF_EQUEUE_CTR_SIZE not defined"
00991     #endif
00992 
00993 
00994     #if (QF_EVENT_SIZ_SIZE == 1)
00995 
00996         /// \brief Internal QS macro to output an unformatted event size
00997         /// data element
00998         /// \note the event size depends on the macro #QF_EVENT_SIZ_SIZE.
00999         #define QS_EVS_(size_)      QS::u8_(size_)
01000     #elif (QF_EVENT_SIZ_SIZE == 2)
01001         #define QS_EVS_(size_)      QS::u16_(size_)
01002     #elif (QF_EVENT_SIZ_SIZE == 4)
01003         #define QS_EVS_(size_)      QS::u32_(size_)
01004     #endif
01005 
01006 
01007     #if (QF_MPOOL_SIZ_SIZE == 1)
01008 
01009         /// \brief Internal QS macro to output an unformatted memory pool
01010         /// block-size data element
01011         /// \note the block-size depends on the macro #QF_MPOOL_SIZ_SIZE.
01012         #define QS_MPS_(size_)      QS::u8_(size_)
01013     #elif (QF_MPOOL_SIZ_SIZE == 2)
01014         #define QS_MPS_(size_)      QS::u16_(size_)
01015     #elif (QF_MPOOL_SIZ_SIZE == 4)
01016         #define QS_MPS_(size_)      QS::u32_(size_)
01017     #endif
01018 
01019     #if (QF_MPOOL_CTR_SIZE == 1)
01020 
01021         /// \brief Internal QS macro to output an unformatted memory pool
01022         /// block-counter data element
01023         /// \note the counter size depends on the macro #QF_MPOOL_CTR_SIZE.
01024         #define QS_MPC_(ctr_)       QS::u8_(ctr_)
01025     #elif (QF_MPOOL_CTR_SIZE == 2)
01026         #define QS_MPC_(ctr_)       QS::u16_(ctr_)
01027     #elif (QF_MPOOL_CTR_SIZE == 4)
01028         #define QS_MPC_(ctr_)       QS::u32_(ctr_)
01029     #endif
01030 
01031 
01032     #if (QF_TIMEEVT_CTR_SIZE == 1)
01033 
01034         /// \brief Internal QS macro to output an unformatted time event
01035         /// tick-counter data element
01036         /// \note the counter size depends on the macro #QF_TIMEEVT_CTR_SIZE.
01037         #define QS_TEC_(ctr_)       QS::u8_(ctr_)
01038     #elif (QF_TIMEEVT_CTR_SIZE == 2)
01039         #define QS_TEC_(ctr_)       QS::u16_(ctr_)
01040     #elif (QF_TIMEEVT_CTR_SIZE == 4)
01041         #define QS_TEC_(ctr_)       QS::u32_(ctr_)
01042     #endif
01043 
01044 #else
01045     #ifndef qs_dummy_h
01046     #include "qs_dummy.h"                   // disable the QS software tracing
01047     #endif
01048 #endif                                                                // Q_SPY
01049 
01050 #endif                                                                 // qf_h