QP is an event-driven, RTOS-like, active object framework for microcontrollers, such as mbed. The QP framework provides thread-safe execution of active objects (concurrent state machines) and support both manual and automatic coding of UML statecharts in readable, production-quality C or C++. Automatic code generation of QP code is supported by the free QM modeling tool.

Dependents:   qp_hangman qp_dpp qp_blinky

QP/C++ (Quantum Platform in C++) is a lightweight, open source active object (actor) framework for building responsive and modular real-time embedded applications as systems of asynchronous event-driven active objects (actors). The QP/C++ framework is a member of a larger family consisting of QP/C++, QP/C, and QP-nano frameworks, which are all strictly quality controlled, thoroughly documented, and available under GPLv3 with a special Exception for mbed (see http://www.state-machine.com/licensing/QP-mbed_GPL_Exception.txt).

The behavior of active objects is specified in QP/C++ by means of hierarchical state machines (UML statecharts). The framework supports manual coding of UML state machines in C++ as well as automatic code generation by means of the free QM modeling tool (http://www.state-machine.com/qm).

Please see the "QP/C++ Reference Manual" (http://www.state-machine.com/qpcpp) for more information.

Files at this revision

API Documentation at this revision

Comitter:
QL
Date:
Mon Sep 26 01:42:32 2011 +0000
Parent:
5:949864ba515c
Child:
7:bf92d3a6625e
Commit message:
4.2.04

Changed in this revision

qp.cpp Show annotated file Show diff for this revision Revisions of this file
qp.h Show annotated file Show diff for this revision Revisions of this file
--- a/qp.cpp	Sun Sep 25 18:10:41 2011 +0000
+++ b/qp.cpp	Mon Sep 26 01:42:32 2011 +0000
@@ -1,7 +1,7 @@
 //////////////////////////////////////////////////////////////////////////////
 // Product: QP/C++, selectabel Vanilla/QK kernels
-// Last Updated for QP ver: 4.1.06 (modified to fit in one file)
-// Date of the Last Update: Feb 08, 2011
+// Last Updated for QP ver: 4.2.04 (modified to fit in one file)
+// Date of the Last Update: Sep 25, 2011
 //
 //                    Q u a n t u m     L e a P s
 //                    ---------------------------
@@ -27,6 +27,10 @@
 //////////////////////////////////////////////////////////////////////////////
 #include "qp_port.h"                                                // QP port
 
+#ifdef Q_USE_NAMESPACE
+namespace QP {
+#endif
+
 Q_DEFINE_THIS_MODULE(qp)
 
 // "qep_pkg.h" ===============================================================
@@ -42,7 +46,7 @@
 #define QEP_TRIG_(state_, sig_) \
     ((*(state_))(this, &QEP_reservedEvt_[sig_]))
 
-/// helper macro to trigger entry action in an HSM
+/// helper macro to trigger exit action in an HSM
 #define QEP_EXIT_(state_) \
     if (QEP_TRIG_(state_, Q_EXIT_SIG) == Q_RET_HANDLED) { \
         QS_BEGIN_(QS_QEP_STATE_EXIT, QS::smObj_, this) \
@@ -51,7 +55,7 @@
         QS_END_() \
     }
 
-/// helper macro to trigger exit action in an HSM
+/// helper macro to trigger entry action in an HSM
 #define QEP_ENTER_(state_) \
     if (QEP_TRIG_(state_, Q_ENTRY_SIG) == Q_RET_HANDLED) { \
         QS_BEGIN_(QS_QEP_STATE_ENTRY, QS::smObj_, this) \
@@ -63,21 +67,28 @@
 // "qep.cpp" =================================================================
 // Package-scope objects -----------------------------------------------------
 QEvent const QEP_reservedEvt_[] = {
-    { (QSignal)QEP_EMPTY_SIG_, (uint8_t)0 },
-    { (QSignal)Q_ENTRY_SIG,    (uint8_t)0 },
-    { (QSignal)Q_EXIT_SIG,     (uint8_t)0 },
-    { (QSignal)Q_INIT_SIG,     (uint8_t)0 }
+#ifdef Q_EVT_CTOR
+    (QSignal)QEP_EMPTY_SIG_,
+    (QSignal)Q_ENTRY_SIG,
+    (QSignal)Q_EXIT_SIG,
+    (QSignal)Q_INIT_SIG
+#else
+    {(QSignal)QEP_EMPTY_SIG_, (uint8_t)0, (uint8_t)0},
+    {(QSignal)Q_ENTRY_SIG,    (uint8_t)0, (uint8_t)0},
+    {(QSignal)Q_EXIT_SIG,     (uint8_t)0, (uint8_t)0},
+    {(QSignal)Q_INIT_SIG,     (uint8_t)0, (uint8_t)0}
+#endif
 };
 //............................................................................
-//lint -e970 -e971               ignore MISRA rules 13 and 14 in this function
+//lint -e970 -e971 -e778         ignore MISRA rules 13 and 14 in this function
 char const Q_ROM * Q_ROM_VAR QEP::getVersion(void) {
     static char const Q_ROM Q_ROM_VAR version[] = {
-        ((QP_VERSION >> 12) & 0xF) + '0',
+        (char)(((QP_VERSION >> 12U) & 0xFU) + (uint8_t)'0'),
         '.',
-        ((QP_VERSION >>  8) & 0xF) + '0',
+        (char)(((QP_VERSION >>  8U) & 0xFU) + (uint8_t)'0'),
         '.',
-        ((QP_VERSION >>  4) & 0xF) + '0',
-        (QP_VERSION         & 0xF) + '0',
+        (char)(((QP_VERSION >>  4U) & 0xFU) + (uint8_t)'0'),
+        (char)((QP_VERSION          & 0xFU) + (uint8_t)'0'),
         '\0'
     };
     return version;
@@ -402,7 +413,7 @@
 
 // package-scope objects -----------------------------------------------------
 extern QTimeEvt *QF_timeEvtListHead_;  ///< head of linked list of time events
-extern QF_EPOOL_TYPE_ QF_pool_[3];                 ///< allocate 3 event pools
+extern QF_EPOOL_TYPE_ QF_pool_[QF_MAX_EPOOL];        ///< allocate event pools
 extern uint8_t QF_maxPool_;                  ///< # of initialized event pools
 extern QSubscrList *QF_subscrList_;             ///< the subscriber list array
 extern QSignal QF_maxSignal_;                ///< the maximum published signal
@@ -414,12 +425,25 @@
     QFreeBlock *m_next;
 };
 
+/// \brief access to the poolId of an event \a e_
+#define EVT_POOL_ID(e_)     ((e_)->poolId_)
+
+/// \brief access to the refCtr of an event \a e_
+#define EVT_REF_CTR(e_)     ((e_)->refCtr_)
+
+/// \brief increment the refCtr of an event \a e_
+#define EVT_INC_REF_CTR(e_) (++((QEvent *)(e_))->refCtr_)
+
+/// \brief decrement the refCtr of an event \a e_
+#define EVT_DEC_REF_CTR(e_) (--((QEvent *)(e_))->refCtr_)
+
 // "qa_defer.cpp" ============================================================
+//............................................................................
 void QActive::defer(QEQueue *eq, QEvent const *e) {
     eq->postFIFO(e);
 }
 //............................................................................
-QEvent const *QActive::recall(QEQueue *eq) {
+uint8_t QActive::recall(QEQueue *eq) {
     QEvent const *e = eq->get();    // try to get an event from deferred queue
     if (e != (QEvent *)0) {                                // event available?
 
@@ -428,48 +452,53 @@
         QF_INT_LOCK_KEY_
         QF_INT_LOCK_();
 
-        if (e->dynamic_ != (uint8_t)0) {             // is it a dynamic event?
+        if (EVT_POOL_ID(e) != (uint8_t)0) {          // is it a dynamic event?
 
             // after posting to the AO's queue the event must be referenced
             // at least twice: once in the deferred event queue (eq->get()
             // did NOT decrement the reference counter) and once in the
             // AO's event queue.
-            Q_ASSERT((e->dynamic_ & 0x3F) > 1);
+            Q_ASSERT(EVT_REF_CTR(e) > (uint8_t)1);
 
             // we need to decrement the reference counter once, to account
             // for removing the event from the deferred event queue.
             //
-            //lint -e1773                           Attempt to cast away const
-            --((QEvent *)e)->dynamic_;      // decrement the reference counter
-                   // NOTE: cast the 'const' away, which is legitimate because
-                   // it's a dynamic event
+            EVT_DEC_REF_CTR(e);             // decrement the reference counter
         }
 
         QF_INT_UNLOCK_();
 
+        return (uint8_t)1;                                   // event recalled
     }
-    return e;  // pass the recalled event to the caller (NULL if not recalled)
+    else {
+        return (uint8_t)0;                               // event not recalled
+    }
 }
 
 // "qa_fifo.cpp" =============================================================
+//............................................................................
+#ifndef Q_SPY
 void QActive::postFIFO(QEvent const *e) {
+#else
+void QActive::postFIFO(QEvent const *e, void const *sender) {
+#endif
+
     QF_INT_LOCK_KEY_
     QF_INT_LOCK_();
 
     QS_BEGIN_NOLOCK_(QS_QF_ACTIVE_POST_FIFO, QS::aoObj_, this)
         QS_TIME_();                                               // timestamp
+        QS_OBJ_(sender);                                  // the sender object
         QS_SIG_(e->sig);                            // the signal of the event
         QS_OBJ_(this);                                   // this active object
-        QS_U8_(e->dynamic_);                  // the QF attribute of the event
+        QS_U8_(EVT_POOL_ID(e));                    // the pool Id of the event
+        QS_U8_(EVT_REF_CTR(e));                  // the ref count of the event
         QS_EQC_(m_eQueue.m_nFree);                   // number of free entries
         QS_EQC_(m_eQueue.m_nMin);                // min number of free entries
     QS_END_NOLOCK_()
 
-    if (e->dynamic_ != (uint8_t)0) {                 // is it a dynamic event?
-        //lint -e1773                               Attempt to cast away const
-        ++((QEvent *)e)->dynamic_;          // increment the reference counter
-                   // NOTE: cast the 'const' away, which is legitimate because
-                   // it's a dynamic event
+    if (EVT_POOL_ID(e) != (uint8_t)0) {              // is it a dynamic event?
+        EVT_INC_REF_CTR(e);                 // increment the reference counter
     }
 
     if (m_eQueue.m_frontEvt == (QEvent *)0) {           // is the queue empty?
@@ -516,7 +545,8 @@
             QS_TIME_();                                           // timestamp
             QS_SIG_(e->sig);                       // the signal of this event
             QS_OBJ_(this);                               // this active object
-            QS_U8_(e->dynamic_);        // the dynamic attributes of the event
+            QS_U8_(EVT_POOL_ID(e));                // the pool Id of the event
+            QS_U8_(EVT_REF_CTR(e));              // the ref count of the event
             QS_EQC_(m_eQueue.m_nFree);               // number of free entries
         QS_END_NOLOCK_()
     }
@@ -528,7 +558,8 @@
             QS_TIME_();                                           // timestamp
             QS_SIG_(e->sig);                       // the signal of this event
             QS_OBJ_(this);                               // this active object
-            QS_U8_(e->dynamic_);        // the dynamic attributes of the event
+            QS_U8_(EVT_POOL_ID(e));                // the pool Id of the event
+            QS_U8_(EVT_REF_CTR(e));              // the ref count of the event
         QS_END_NOLOCK_()
     }
     QF_INT_UNLOCK_();
@@ -556,16 +587,14 @@
         QS_TIME_();                                               // timestamp
         QS_SIG_(e->sig);                           // the signal of this event
         QS_OBJ_(this);                                   // this active object
-        QS_U8_(e->dynamic_);            // the dynamic attributes of the event
+        QS_U8_(EVT_POOL_ID(e));                    // the pool Id of the event
+        QS_U8_(EVT_REF_CTR(e));                  // the ref count of the event
         QS_EQC_(m_eQueue.m_nFree);                   // number of free entries
         QS_EQC_(m_eQueue.m_nMin);                // min number of free entries
     QS_END_NOLOCK_()
 
-    if (e->dynamic_ != (uint8_t)0) {                    // is it a pool event?
-        //lint -e1773                               Attempt to cast away const
-        ++((QEvent *)e)->dynamic_;          // increment the reference counter
-                   // NOTE: cast the 'const' away, which is legitimate because
-                   // it's a dynamic event
+    if (EVT_POOL_ID(e) != (uint8_t)0) {              // is it a dynamic event?
+        EVT_INC_REF_CTR(e);                 // increment the reference counter
     }
 
     if (m_eQueue.m_frontEvt == (QEvent *)0) {           // is the queue empty?
@@ -675,16 +704,14 @@
         QS_TIME_();                                               // timestamp
         QS_SIG_(e->sig);                           // the signal of this event
         QS_OBJ_(this);                                    // this queue object
-        QS_U8_(e->dynamic_);            // the dynamic attributes of the event
+        QS_U8_(EVT_POOL_ID(e));                    // the pool Id of the event
+        QS_U8_(EVT_REF_CTR(e));                  // the ref count of the event
         QS_EQC_(m_nFree);                            // number of free entries
         QS_EQC_(m_nMin);                         // min number of free entries
     QS_END_NOLOCK_()
 
-    if (e->dynamic_ != (uint8_t)0) {                    // is it a pool event?
-        //lint -e1773                               Attempt to cast away const
-        ++((QEvent *)e)->dynamic_;          // increment the reference counter
-                   // NOTE: cast the 'const' away, which is legitimate because
-                   // it's a dynamic event
+    if (EVT_POOL_ID(e) != (uint8_t)0) {              // is it a dynamic event?
+        EVT_INC_REF_CTR(e);                 // increment the reference counter
     }
 
     if (m_frontEvt == (QEvent *)0) {                    // is the queue empty?
@@ -733,7 +760,8 @@
                 QS_TIME_();                                       // timestamp
                 QS_SIG_(e->sig);                   // the signal of this event
                 QS_OBJ_(this);                            // this queue object
-                QS_U8_(e->dynamic_);    // the dynamic attributes of the event
+                QS_U8_(EVT_POOL_ID(e));            // the pool Id of the event
+                QS_U8_(EVT_REF_CTR(e));          // the ref count of the event
                 QS_EQC_(m_nFree);                    // number of free entries
             QS_END_NOLOCK_()
         }
@@ -744,7 +772,8 @@
                 QS_TIME_();                                       // timestamp
                 QS_SIG_(e->sig);                   // the signal of this event
                 QS_OBJ_(this);                            // this queue object
-                QS_U8_(e->dynamic_);     // the dynamic attribute of the event
+                QS_U8_(EVT_POOL_ID(e));            // the pool Id of the event
+                QS_U8_(EVT_REF_CTR(e));          // the ref count of the event
             QS_END_NOLOCK_()
         }
     }
@@ -778,16 +807,14 @@
         QS_TIME_();                                               // timestamp
         QS_SIG_(e->sig);                           // the signal of this event
         QS_OBJ_(this);                                    // this queue object
-        QS_U8_(e->dynamic_);             // the dynamic attribute of the event
+        QS_U8_(EVT_POOL_ID(e));                    // the pool Id of the event
+        QS_U8_(EVT_REF_CTR(e));                  // the ref count of the event
         QS_EQC_(m_nFree);                            // number of free entries
         QS_EQC_(m_nMin);                         // min number of free entries
     QS_END_NOLOCK_()
 
-    if (e->dynamic_ != (uint8_t)0) {                 // is it a dynamic event?
-        //lint -e1773                               Attempt to cast away const
-        ++((QEvent *)e)->dynamic_;          // increment the reference counter
-                   // NOTE: cast the 'const' away, which is legitimate because
-                   // it's a dynamic event
+    if (EVT_POOL_ID(e) != (uint8_t)0) {              // is it a dynamic event?
+        EVT_INC_REF_CTR(e);                 // increment the reference counter
     }
 
     if (m_frontEvt != (QEvent *)0) {                // is the queue not empty?
@@ -821,12 +848,12 @@
 //lint -e970 -e971               ignore MISRA rules 13 and 14 in this function
 const char Q_ROM * Q_ROM_VAR QF::getVersion(void) {
     static char const Q_ROM Q_ROM_VAR version[] = {
-        ((QP_VERSION >> 12) & 0xF) + '0',
+        (char)(((QP_VERSION >> 12U) & 0xFU) + (uint8_t)'0'),
         '.',
-        ((QP_VERSION >>  8) & 0xF) + '0',
+        (char)(((QP_VERSION >>  8U) & 0xFU) + (uint8_t)'0'),
         '.',
-        ((QP_VERSION >>  4) & 0xF) + '0',
-        (QP_VERSION         & 0xF) + '0',
+        (char)(((QP_VERSION >>  4U) & 0xFU) + (uint8_t)'0'),
+        (char)((QP_VERSION          & 0xFU) + (uint8_t)'0'),
         '\0'
     };
     return version;
@@ -874,38 +901,41 @@
 
 // "qf_gc.cpp" ===============================================================
 void QF::gc(QEvent const *e) {
-    if (e->dynamic_ != (uint8_t)0) {                 // is it a dynamic event?
+    if (EVT_POOL_ID(e) != (uint8_t)0) {              // is it a dynamic event?
         QF_INT_LOCK_KEY_
         QF_INT_LOCK_();
 
-        if ((e->dynamic_ & 0x3F) > 1) {      // isn't this the last reference?
-
-            //lint -e1773                           Attempt to cast away const
-            --((QEvent *)e)->dynamic_;      // decrement the reference counter
-                   // NOTE: cast the 'const' away, which is legitimate because
-                   // it's a dynamic event
+        if (EVT_REF_CTR(e) > (uint8_t)1) {   // isn't this the last reference?
+            EVT_DEC_REF_CTR(e);                   // decrement the ref counter
 
             QS_BEGIN_NOLOCK_(QS_QF_GC_ATTEMPT, (void *)0, (void *)0)
                 QS_TIME_();                                       // timestamp
                 QS_SIG_(e->sig);                    // the signal of the event
-                QS_U8_(e->dynamic_);    // the dynamic attributes of the event
+                QS_U8_(EVT_POOL_ID(e));            // the pool Id of the event
+                QS_U8_(EVT_REF_CTR(e));          // the ref count of the event
             QS_END_NOLOCK_()
 
             QF_INT_UNLOCK_();
         }
         else {         // this is the last reference to this event, recycle it
-            uint8_t idx = (uint8_t)((e->dynamic_ >> 6) - 1);
+            uint8_t idx = (uint8_t)(EVT_POOL_ID(e) - 1);
 
             QS_BEGIN_NOLOCK_(QS_QF_GC, (void *)0, (void *)0)
                 QS_TIME_();                                       // timestamp
                 QS_SIG_(e->sig);                    // the signal of the event
-                QS_U8_(e->dynamic_);    // the dynamic attributes of the event
+                QS_U8_(EVT_POOL_ID(e));            // the pool Id of the event
+                QS_U8_(EVT_REF_CTR(e));          // the ref count of the event
             QS_END_NOLOCK_()
 
             QF_INT_UNLOCK_();
 
             Q_ASSERT(idx < QF_maxPool_);
 
+#ifdef Q_EVT_CTOR
+            //lint -e1773                           Attempt to cast away const
+            ((QEvent *)e)->~QEvent();     // call the xtor, cast 'const' away,
+                             // which is legitimate, because it's a pool event
+#endif
             //lint -e1773                           Attempt to cast away const
             QF_EPOOL_PUT_(QF_pool_[idx], (QEvent *)e);   // cast 'const' away,
                              // which is legitimate, because it's a pool event
@@ -936,10 +966,10 @@
 // "qf_new.cpp" ==============================================================
 QEvent *QF::new_(uint16_t evtSize, QSignal sig) {
                     // find the pool id that fits the requested event size ...
-    uint8_t id = (uint8_t)0;
-    while (evtSize > QF_EPOOL_EVENT_SIZE_(QF_pool_[id])) {
-        ++id;
-        Q_ASSERT(id < QF_maxPool_);      // cannot run out of registered pools
+    uint8_t idx = (uint8_t)0;
+    while (evtSize > QF_EPOOL_EVENT_SIZE_(QF_pool_[idx])) {
+        ++idx;
+        Q_ASSERT(idx < QF_maxPool_);     // cannot run out of registered pools
     }
 
     QS_INT_LOCK_KEY_
@@ -950,20 +980,19 @@
     QS_END_()
 
     QEvent *e;
-    QF_EPOOL_GET_(QF_pool_[id], e);
+    QF_EPOOL_GET_(QF_pool_[idx], e);
     Q_ASSERT(e != (QEvent *)0);             // pool must not run out of events
 
     e->sig = sig;                                 // set signal for this event
+    EVT_POOL_ID(e) = (uint8_t)(idx + 1);     // store the pool ID in the event
+    EVT_REF_CTR(e) = (uint8_t)0;             // set the reference counter to 0
 
-                                 // store the dynamic attributes of the event:
-                                 // the pool ID and the reference counter == 0
-    e->dynamic_ = (uint8_t)((id + 1) << 6);
     return e;
 }
 
 // "qf_pool.cpp" =============================================================
 // Package-scope objects -----------------------------------------------------
-QF_EPOOL_TYPE_ QF_pool_[3];                          // allocate 3 event pools
+QF_EPOOL_TYPE_ QF_pool_[QF_MAX_EPOOL];             // allocate the event pools
 uint8_t QF_maxPool_;                      // number of initialized event pools
 
 //............................................................................
@@ -989,7 +1018,11 @@
 }
 
 // "qf_pspub.cpp" ============================================================
+#ifndef Q_SPY
 void QF::publish(QEvent const *e) {
+#else
+void QF::publish(QEvent const *e, void const *sender) {
+#endif
          // make sure that the published signal is within the configured range
     Q_REQUIRE(e->sig < QF_maxSignal_);
 
@@ -998,15 +1031,14 @@
 
     QS_BEGIN_NOLOCK_(QS_QF_PUBLISH, (void *)0, (void *)0)
         QS_TIME_();                                           // the timestamp
+        QS_OBJ_(sender);                                  // the sender object
         QS_SIG_(e->sig);                            // the signal of the event
-        QS_U8_(e->dynamic_);            // the dynamic attributes of the event
+        QS_U8_(EVT_POOL_ID(e));                    // the pool Id of the event
+        QS_U8_(EVT_REF_CTR(e));                  // the ref count of the event
     QS_END_NOLOCK_()
 
-    if (e->dynamic_ != (uint8_t)0) {                 // is it a dynamic event?
-        //lint -e1773                               Attempt to cast away const
-        ++((QEvent *)e)->dynamic_;      // increment reference counter, NOTE01
-                   // NOTE: cast the 'const' away, which is legitimate because
-                   // it's a dynamic event */
+    if (EVT_POOL_ID(e) != (uint8_t)0) {              // is it a dynamic event?
+        EVT_INC_REF_CTR(e);         // increment the reference counter, NOTE01
     }
     QF_INT_UNLOCK_();
 
@@ -1017,7 +1049,8 @@
         tmp &= Q_ROM_BYTE(QF_invPwr2Lkup[p]);      // clear the subscriber bit
         Q_ASSERT(active_[p] != (QActive *)0);            // must be registered
 
-        active_[p]->postFIFO(e);  // internally asserts if the queue overflows
+                           // POST() asserts internally if the queue overflows
+        active_[p]->POST(e, sender);
     }
 #else
     uint8_t i = Q_DIM(QF_subscrList_[0].m_bits);// number of bytes in the list
@@ -1030,8 +1063,8 @@
             p = (uint8_t)(p + (i << 3));                // adjust the priority
             Q_ASSERT(active_[p] != (QActive *)0);        // must be registered
 
-                       // postFIFO() internally asserts if the queue overflows
-            active_[p]->postFIFO(e);
+                           // POST() asserts internally if the queue overflows
+            active_[p]->POST(e, sender);
         }
     } while (i != (uint8_t)0);
 #endif
@@ -1078,7 +1111,12 @@
 };
 
 // "qf_tick.cpp" =============================================================
+#ifndef Q_SPY
 void QF::tick(void) {                                            // see NOTE01
+#else
+void QF::tick(void const *sender) {
+#endif
+
     QF_INT_LOCK_KEY_
     QF_INT_LOCK_();
 
@@ -1120,8 +1158,8 @@
 
             QF_INT_UNLOCK_();   // unlock interrupts before calling QF service
 
-                  // postFIFO() asserts internally that the event was accepted
-            t->m_act->postFIFO(t);
+                           // POST() asserts internally if the queue overflows
+            t->m_act->POST(t, sender);
         }
         else {
             QF_INT_UNLOCK_();
@@ -1181,15 +1219,7 @@
               && ((QMPoolSize)(blockSize + (QMPoolSize)sizeof(QFreeBlock))
                     > blockSize));
 
-    //lint -e923                       ignore MISRA Rule 45 in this expression
-    uint32_t corr = ((uint32_t)poolSto
-                      & ((uint32_t)sizeof(QFreeBlock) - (uint32_t)1));
-    if (corr != (uint32_t)0) {                            // alignment needed?
-        corr = (uint32_t)sizeof(QFreeBlock) - corr; // amount to align poolSto
-        poolSize -= corr;                    // reduce the available pool size
-    }
-    //lint -e826   align the head of free list at the free block-size boundary
-    m_free = (void *)((uint8_t *)poolSto + corr);
+    m_free = poolSto;
 
                 // round up the blockSize to fit an integer number of pointers
     m_blockSize = (QMPoolSize)sizeof(QFreeBlock);       // start with just one
@@ -1283,15 +1313,43 @@
 
 // "qte_ctor.cpp" ============================================================
 QTimeEvt::QTimeEvt(QSignal s)
-    : m_prev((QTimeEvt *)0),
-      m_next((QTimeEvt *)0),
-      m_act((QActive *)0),
-      m_ctr((QTimeEvtCtr)0),
-      m_interval((QTimeEvtCtr)0)
+  :
+#ifdef Q_EVT_CTOR
+    QEvent(s),
+#endif
+    m_prev((QTimeEvt *)0),
+    m_next((QTimeEvt *)0),
+    m_act((QActive *)0),
+    m_ctr((QTimeEvtCtr)0),
+    m_interval((QTimeEvtCtr)0)
 {
     Q_REQUIRE(s >= (QSignal)Q_USER_SIG);                       // valid signal
     sig = s;
-    dynamic_ = (uint8_t)0;            // time event must be static, see NOTE01
+    EVT_POOL_ID(this) = (uint8_t)0;   // time event must be static, see NOTE01
+}
+
+// "qte_ctr.cpp" =============================================================
+QTimeEvtCtr QTimeEvt::ctr(void) {
+    QTimeEvtCtr ctr;
+    QF_INT_LOCK_KEY_
+    QF_INT_LOCK_();
+    if (m_prev != (QTimeEvt *)0) {        // is the time event actually armed?
+        ctr = m_ctr;
+    }
+    else {                                     // the time event was not armed
+        ctr = (QTimeEvtCtr)0;
+    }
+
+    QS_BEGIN_NOLOCK_(QS_QF_TIMEEVT_CTR, QS::teObj_, this)
+        QS_TIME_();                                               // timestamp
+        QS_OBJ_(this);                               // this time event object
+        QS_OBJ_(m_act);                                   // the active object
+        QS_TEC_(ctr);                                   // the current counter
+        QS_TEC_(m_interval);                                   // the interval
+    QS_END_NOLOCK_()
+
+    QF_INT_UNLOCK_();
+    return ctr;
 }
 
 // "qte_darm.cpp" ============================================================
@@ -1418,27 +1476,45 @@
 #endif
 
 // "qk.cpp" ==================================================================
+#ifdef Q_USE_NAMESPACE
+}                                                              // namespace QP
+#endif
+
 // Public-scope objects ------------------------------------------------------
-#if (QF_MAX_ACTIVE <= 8)
+extern "C" {
+#if (QF_MAX_ACTIVE <= 8U)
+#ifdef Q_USE_NAMESPACE
+    QP::QPSet8  volatile QK_readySet_;                      // ready set of QK
+#else
     QPSet8  volatile QK_readySet_;                          // ready set of QK
+#endif
+#else
+#ifdef Q_USE_NAMESPACE
+    QP::QPSet64 volatile QK_readySet_;                      // ready set of QK
 #else
     QPSet64 volatile QK_readySet_;                          // ready set of QK
 #endif
+#endif
                                          // start with the QK scheduler locked
 uint8_t volatile QK_currPrio_ = (uint8_t)(QF_MAX_ACTIVE + 1);
 uint8_t volatile QK_intNest_;                 // start with nesting level of 0
 
+}                                                                // extern "C"
+
+#ifdef Q_USE_NAMESPACE
+namespace QP {
+#endif
 
 //............................................................................
 //lint -e970 -e971               ignore MISRA rules 13 and 14 in this function
 char const Q_ROM * Q_ROM_VAR QK::getVersion(void) {
     static char const Q_ROM Q_ROM_VAR version[] = {
-        ((QP_VERSION >> 12) & 0xF) + '0',
+        (char)(((QP_VERSION >> 12U) & 0xFU) + (uint8_t)'0'),
         '.',
-        ((QP_VERSION >>  8) & 0xF) + '0',
+        (char)(((QP_VERSION >>  8U) & 0xFU) + (uint8_t)'0'),
         '.',
-        ((QP_VERSION >>  4) & 0xF) + '0',
-        (QP_VERSION         & 0xF) + '0',
+        (char)(((QP_VERSION >>  4U) & 0xFU) + (uint8_t)'0'),
+        (char)((QP_VERSION          & 0xFU) + (uint8_t)'0'),
         '\0'
     };
     return version;
@@ -1496,13 +1572,26 @@
 }
 
 // "qk_sched" ================================================================
+
+#ifdef Q_USE_NAMESPACE
+}                                                              // namespace QP
+#endif
+
 //............................................................................
-// NOTE: the QK scheduler is entered and exited with interrupts LOCKED
+// NOTE: the QK scheduler is entered and exited with interrupts LOCKED.
+// QK_schedule_() is extern "C", so it does not belong to the QP namespace.
+//
+extern "C" {
+
 #ifndef QF_INT_KEY_TYPE
 void QK_schedule_(void) {
 #else
 void QK_schedule_(QF_INT_KEY_TYPE intLockKey_) {
 #endif
+
+#ifdef Q_USE_NAMESPACE
+    using namespace QP;
+#endif
                          // the QK scheduler must be called at task level only
     Q_REQUIRE(QK_intNest_ == (uint8_t)0);
 
@@ -1566,6 +1655,12 @@
     }
 }
 
+}                                                                // extern "C"
+
+#ifdef Q_USE_NAMESPACE
+namespace QP {
+#endif
+
 // "qk_mutex.cpp" ============================================================
 #ifndef QK_NO_MUTEX
 
@@ -1790,12 +1885,12 @@
 //lint -e970 -e971               ignore MISRA rules 13 and 14 in this function
 char const Q_ROM * Q_ROM_VAR QS::getVersion(void) {
     static char const Q_ROM Q_ROM_VAR version[] = {
-        ((QP_VERSION >> 12) & 0xF) + '0',
+        (char)(((QP_VERSION >> 12U) & 0xFU) + (uint8_t)'0'),
         '.',
-        ((QP_VERSION >>  8) & 0xF) + '0',
+        (char)(((QP_VERSION >>  8U) & 0xFU) + (uint8_t)'0'),
         '.',
-        ((QP_VERSION >>  4) & 0xF) + '0',
-        (QP_VERSION         & 0xF) + '0',
+        (char)(((QP_VERSION >>  4U) & 0xFU) + (uint8_t)'0'),
+        (char)((QP_VERSION          & 0xFU) + (uint8_t)'0'),
         '\0'
     };
     return version;
@@ -2062,6 +2157,37 @@
     QS_INSERT_BYTE((uint8_t)0)
 }
 
+// "qs_u64.cpp" ==============================================================
+#if (QS_OBJ_PTR_SIZE == 8) || (QS_FUN_PTR_SIZE == 8)
+
+//............................................................................
+void QS::u64_(uint64_t d) {
+    QS_INSERT_ESC_BYTE((uint8_t)d)
+    d >>= 8;
+    QS_INSERT_ESC_BYTE((uint8_t)d)
+    d >>= 8;
+    QS_INSERT_ESC_BYTE((uint8_t)d)
+    d >>= 8;
+    QS_INSERT_ESC_BYTE((uint8_t)d)
+    d >>= 8;
+    QS_INSERT_ESC_BYTE((uint8_t)d)
+    d >>= 8;
+    QS_INSERT_ESC_BYTE((uint8_t)d)
+    d >>= 8;
+    QS_INSERT_ESC_BYTE((uint8_t)d)
+    d >>= 8;
+    QS_INSERT_ESC_BYTE((uint8_t)d)
+}
+//............................................................................
+void QS::u64(uint8_t format, uint64_t d) {
+    QS_INSERT_ESC_BYTE(format)
+    u64_(d);
+}
+
+#endif
+
 #endif                                                                // Q_SPY
 
-
+#ifdef Q_USE_NAMESPACE
+}                                                              // namespace QP
+#endif
--- a/qp.h	Sun Sep 25 18:10:41 2011 +0000
+++ b/qp.h	Mon Sep 26 01:42:32 2011 +0000
@@ -1,7 +1,7 @@
 //////////////////////////////////////////////////////////////////////////////
 // Product: QP/C++
-// Last Updated for QP ver: 4.1.06 (modified to fit in one file)
-// Date of the Last Update: Jan 26, 2011
+// Last Updated for QP ver: 4.2.04 (modified to fit in one file)
+// Date of the Last Update: Sep 25, 2011
 //
 //                    Q u a n t u m     L e a P s
 //                    ---------------------------
@@ -28,6 +28,10 @@
 #ifndef qp_h
 #define qp_h
 
+#ifdef Q_USE_NAMESPACE
+namespace QP {
+#endif
+
 // "qevent.h" ================================================================
 /// \brief QEvent class and basic macros used by all QP components.
 ///
@@ -40,7 +44,7 @@
 /// \return version of the QP as a hex constant constant 0xXYZZ, where X is
 /// a 1-digit major version number, Y is a 1-digit minor version number, and
 /// ZZ is a 2-digit release number.
-#define QP_VERSION      0x4106
+#define QP_VERSION      0x4204U
 
 #ifndef Q_ROM
     /// \brief Macro to specify compiler-specific directive for placing a
@@ -97,9 +101,11 @@
     /// This macro can be defined in the QEP port file (qep_port.h) to
     /// configure the ::QSignal type. When the macro is not defined, the
     /// default of 1 byte is chosen.
-    #define Q_SIGNAL_SIZE 1
+    #define Q_SIGNAL_SIZE 2
 #endif
 #if (Q_SIGNAL_SIZE == 1)
+    typedef uint8_t QSignal;
+#elif (Q_SIGNAL_SIZE == 2)
     /// \brief QSignal represents the signal of an event.
     ///
     /// The relationship between an event and a signal is as follows. A signal
@@ -109,12 +115,6 @@
     /// event. (The signal conveys the type of the occurrence-what happened?)
     /// However, an event can also contain additional quantitative information
     /// about the occurrence in form of event parameters. Please refer to the
-    /// document
-    /// <A HREF="http://www.quantum-leaps.com/devzone/Recipe_IntroHSM.pdf">
-    /// Brief Introduction to UML State Machines</A>) for more information
-    /// about state machine concepts.
-    typedef uint8_t QSignal;
-#elif (Q_SIGNAL_SIZE == 2)
     typedef uint16_t QSignal;
 #elif (Q_SIGNAL_SIZE == 4)
     typedef uint32_t QSignal;
@@ -137,7 +137,13 @@
 /// \include qep_qevent.cpp
 struct QEvent {
     QSignal sig;                             ///< signal of the event instance
-    uint8_t dynamic_;  ///< attributes of a dynamic event (0 for static event)
+    uint8_t poolId_;                         ///< pool ID (0 for static event)
+    uint8_t refCtr_;                                    ///< reference counter
+
+#ifdef Q_EVT_CTOR
+    QEvent(QSignal s) : sig(s) {}
+    virtual ~QEvent() {}                                 // virtual destructor
+#endif
 };
 
 //////////////////////////////////////////////////////////////////////////////
@@ -1179,6 +1185,11 @@
     #error "QF_EVENT_SIZ_SIZE defined incorrectly, expected 1, 2, or 4"
 #endif
 
+//////////////////////////////////////////////////////////////////////////////
+#ifndef QF_MAX_EPOOL
+    /// \brief Default value of the macro configurable value in qf_port.h
+    #define QF_MAX_EPOOL 3
+#endif
 
 //////////////////////////////////////////////////////////////////////////////
 #ifndef QF_ACTIVE_SUPER_
@@ -1306,7 +1317,7 @@
     /// \include qf_start.cpp
     void start(uint8_t prio,
                QEvent const *qSto[], uint32_t qLen,
-               void *stkSto = (void *)0, uint32_t stkSize = 0,
+               void *stkSto, uint32_t stkSize,
                QEvent const *ie = (QEvent *)0);
 
     /// \brief Posts an event \a e directly to the event queue of the acitve
@@ -1327,13 +1338,18 @@
     /// queues, direct event dispatching is synchronous. Direct event
     /// dispatching occurs when you call QHsm::dispatch(), or QFsm::dispatch()
     /// function.
+#ifndef Q_SPY
     void postFIFO(QEvent const *e);
+#else
+    void postFIFO(QEvent const *e, void const *sender);
+#endif
 
     /// \brief Posts an event directly to the event queue of the active object
     /// \a me using the Last-In-First-Out (LIFO) policy.
     ///
-    /// \note The LIFO policy should be used only with great caution because
-    /// it alters order of events in the queue.
+    /// \note The LIFO policy should be used only for self-posting and with
+    /// great caution because it alters order of events in the queue.
+    ///
     /// \sa QActive::postFIFO()
     void postLIFO(QEvent const *e);
 
@@ -1451,14 +1467,14 @@
     /// deferred event queue \a eq and posted (LIFO) to the event queue of
     /// the active object.
     ///
-    /// QActive::recall() returns the pointer to the recalled event to the
-    /// caller. The function returns NULL if no event has been recalled.
+    /// 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.
     ///
     /// \sa QActive::defer(), QEQueue, QActive::postLIFO()
-    QEvent const *recall(QEQueue *eq);
+    uint8_t recall(QEQueue *eq);
 
 public:
     /// \brief Un-subscribes from the delivery of all signals to the active
@@ -1667,21 +1683,14 @@
     /// expected in the active object's state machine.
     uint8_t rearm(QTimeEvtCtr nTicks);
 
-    // for backwards compatibility
-
-    /// \brief Arm a one-shot time event for direct event posting (obsolete).
+    /// \brief Get the current value of the down-counter of a time event.
     ///
-    /// This facility is now obsolete, please use \sa QTimeEvt::postIn().
-    void fireIn(QActive *act, QTimeEvtCtr nTicks) {
-        postIn(act, nTicks);
-    }
-
-    /// \brief Arm a periodic time event for direct event posting (obsolete).
+    /// 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.
     ///
-    /// This facility is now obsolete, please use \sa QTimeEvt::postEvery().
-    void fireEvery(QActive *act, QTimeEvtCtr nTicks) {
-        postEvery(act, nTicks);
-    }
+    /// /note The function is thread-safe.
+    QTimeEvtCtr ctr(void);
 
 private:
 
@@ -1905,7 +1914,11 @@
     /// 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.)
+#ifndef Q_SPY
     static void publish(QEvent const *e);
+#else
+    static void publish(QEvent const *e, void const *sender);
+#endif
 
     /// \brief Processes all armed time events at every clock tick.
     ///
@@ -1921,7 +1934,11 @@
     ///
     /// The following example illustrates the call to QF::tick():
     /// \include qf_tick.cpp
+#ifndef Q_SPY
     static void tick(void);
+#else
+    static void tick(void const *sender);
+#endif
 
     /// \brief Returns the QF version.
     ///
@@ -1977,6 +1994,10 @@
     /// Please use the macro #Q_NEW.
     static QEvent *new_(uint16_t evtSize, QSignal sig);
 
+#ifdef Q_EVT_CTOR
+    #define Q_NEW(evtT_, sig_, ...) \
+        (new(QF::new_(sizeof(evtT_), sig_)) evtT_((sig_), ##__VA_ARGS__))
+#else
     /// \brief Allocate a dynamic event.
     ///
     /// This macro returns an event pointer cast to the type \a evtT_. The
@@ -1991,6 +2012,7 @@
     /// The following example illustrates dynamic allocation of an event:
     /// \include qf_post.cpp
     #define Q_NEW(evtT_, sig_) ((evtT_ *)QF::new_(sizeof(evtT_), (sig_)))
+#endif
 
     /// \brief Recycle a dynamic event.
     ///
@@ -2086,6 +2108,157 @@
 extern uint8_t const Q_ROM Q_ROM_VAR QF_div8Lkup[65];
 
 //////////////////////////////////////////////////////////////////////////////
+#ifdef Q_EVT_CTOR
+#include <new>                                            // for placement new
+#endif
+
+// from qf.h -----------------------------------------------------------------
+//////////////////////////////////////////////////////////////////////////////
+// QS software tracing integration, only if enabled
+#ifdef Q_SPY                                   // QS software tracing enabled?
+    #define QS_TIME_SIZE            4
+    #define QS_OBJ_PTR_SIZE         4
+    #define QS_FUN_PTR_SIZE         4
+
+    /// \brief 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 \a 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.
+    ///
+    /// \sa QF::tick()
+    #define TICK(sender_)                  tick(sender_)
+
+    /// \brief 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 \a 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
+    /// \a 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.
+    ///
+    /// \sa QF::publish()
+    #define PUBLISH(e_, sender_)           publish((e_), (sender_))
+
+    /// \brief 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 \a 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
+    /// \a 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 ao->POST() is called from an
+    /// interrupt or other context, you can create a unique object just to
+    /// unambiguously identify the publisher of the event.
+    ///
+    /// \sa QActive::postFIFO()
+    #define POST(e_, sender_)              postFIFO((e_), (sender_))
+
+    #if (QF_EQUEUE_CTR_SIZE == 1)
+
+        /// \brief Internal QS macro to output an unformatted event queue
+        /// counter data element
+        /// \note the counter size depends on the macro #QF_EQUEUE_CTR_SIZE.
+        #define QS_EQC_(ctr_)       QS::u8_(ctr_)
+    #elif (QF_EQUEUE_CTR_SIZE == 2)
+        #define QS_EQC_(ctr_)       QS::u16_(ctr_)
+    #elif (QF_EQUEUE_CTR_SIZE == 4)
+        #define QS_EQC_(ctr_)       QS::u32_(ctr_)
+    #else
+        #error "QF_EQUEUE_CTR_SIZE not defined"
+    #endif
+
+
+    #if (QF_EVENT_SIZ_SIZE == 1)
+
+        /// \brief Internal QS macro to output an unformatted event size
+        /// data element
+        /// \note the event size depends on the macro #QF_EVENT_SIZ_SIZE.
+        #define QS_EVS_(size_)      QS::u8_(size_)
+    #elif (QF_EVENT_SIZ_SIZE == 2)
+        #define QS_EVS_(size_)      QS::u16_(size_)
+    #elif (QF_EVENT_SIZ_SIZE == 4)
+        #define QS_EVS_(size_)      QS::u32_(size_)
+    #endif
+
+
+    #if (QF_MPOOL_SIZ_SIZE == 1)
+
+        /// \brief Internal QS macro to output an unformatted memory pool
+        /// block-size data element
+        /// \note the block-size depends on the macro #QF_MPOOL_SIZ_SIZE.
+        #define QS_MPS_(size_)      QS::u8_(size_)
+    #elif (QF_MPOOL_SIZ_SIZE == 2)
+        #define QS_MPS_(size_)      QS::u16_(size_)
+    #elif (QF_MPOOL_SIZ_SIZE == 4)
+        #define QS_MPS_(size_)      QS::u32_(size_)
+    #endif
+
+    #if (QF_MPOOL_CTR_SIZE == 1)
+
+        /// \brief Internal QS macro to output an unformatted memory pool
+        /// block-counter data element
+        /// \note the counter size depends on the macro #QF_MPOOL_CTR_SIZE.
+        #define QS_MPC_(ctr_)       QS::u8_(ctr_)
+    #elif (QF_MPOOL_CTR_SIZE == 2)
+        #define QS_MPC_(ctr_)       QS::u16_(ctr_)
+    #elif (QF_MPOOL_CTR_SIZE == 4)
+        #define QS_MPC_(ctr_)       QS::u32_(ctr_)
+    #endif
+
+
+    #if (QF_TIMEEVT_CTR_SIZE == 1)
+
+        /// \brief Internal QS macro to output an unformatted time event
+        /// tick-counter data element
+        /// \note the counter size depends on the macro #QF_TIMEEVT_CTR_SIZE.
+        #define QS_TEC_(ctr_)       QS::u8_(ctr_)
+    #elif (QF_TIMEEVT_CTR_SIZE == 2)
+        #define QS_TEC_(ctr_)       QS::u16_(ctr_)
+    #elif (QF_TIMEEVT_CTR_SIZE == 4)
+        #define QS_TEC_(ctr_)       QS::u32_(ctr_)
+    #endif
+
+#else
+    #ifndef qs_dummy_h
+    #include "qs_dummy.h"                   // disable the QS software tracing
+    #endif
+
+    #define TICK(dummy_)                   tick()
+    #define PUBLISH(e_, dummy_)            publish((e_))
+    #define POST(e_, dummy_)               postFIFO((e_))
+
+#endif                                                                // Q_SPY
+
+//////////////////////////////////////////////////////////////////////////////
 // QS software tracing
 #ifdef Q_SPY
 
@@ -2140,7 +2313,7 @@
     QS_QF_TIMEEVT_DISARM,           ///< true disarming of an armed time event
     QS_QF_TIMEEVT_REARM,                         ///< rearming of a time event
     QS_QF_TIMEEVT_POST,      ///< a time event posted itself directly to an AO
-    QS_QF_RESERVED7,
+    QS_QF_TIMEEVT_CTR,                 ///< a time event counter was requested
     QS_QF_INT_LOCK,                                ///< interrupts were locked
     QS_QF_INT_UNLOCK,                            ///< interrupts were unlocked
     QS_QF_ISR_ENTRY,                                   ///< an ISR was entered
@@ -2384,6 +2557,18 @@
     /// client code directly.
     static void mem(uint8_t const *blk, uint8_t size);
 
+#if (QS_OBJ_PTR_SIZE == 8) || (QS_FUN_PTR_SIZE == 8)
+    /// \brief Output uint64_t data element without format information
+    /// \note This function is only to be used through macros, never in the
+    /// client code directly.
+    static void u64_(uint64_t d);
+
+    /// \brief Output uint64_t data element with format information
+    /// \note This function is only to be used through macros, never in the
+    /// client code directly.
+    static void u64(uint8_t format, uint64_t d);
+#endif
+
     // QS buffer access ......................................................
 
     /// \brief Byte-oriented interface to the QS data buffer.
@@ -2633,7 +2818,7 @@
 /// to NULL.
 ///
 /// \sa Example of using QS filters in #QS_FILTER_ON documentation
-#define QS_FILTER_AP_OBJ(obj_)  (QS_apObj_ = (obj_))
+#define QS_FILTER_AP_OBJ(obj_)  (QS::apObj_ = (obj_))
 
 
 //////////////////////////////////////////////////////////////////////////////
@@ -2769,6 +2954,8 @@
     #define QS_OBJ_(obj_)       QS::u16_((uint16_t)(obj_))
 #elif (QS_OBJ_PTR_SIZE == 4)
     #define QS_OBJ_(obj_)       QS::u32_((uint32_t)(obj_))
+#elif (QS_OBJ_PTR_SIZE == 8)
+    #define QS_OBJ_(obj_)       QS::u64_((uint64_t)(obj_))
 #else
 
     /// \brief Internal QS macro to output an unformatted object pointer
@@ -2785,6 +2972,8 @@
     #define QS_FUN_(fun_)       QS::u16_((uint16_t)(fun_))
 #elif (QS_FUN_PTR_SIZE == 4)
     #define QS_FUN_(fun_)       QS::u32_((uint32_t)(fun_))
+#elif (QS_FUN_PTR_SIZE == 8)
+    #define QS_FUN_(fun_)       QS::u64_((uint64_t)(fun_))
 #else
 
     /// \brief Internal QS macro to output an unformatted function pointer
@@ -2822,7 +3011,10 @@
     QS_MEM_T,                         ///< up to 255-bytes memory block format
     QS_SIG_T,                                         ///< event signal format
     QS_OBJ_T,                                       ///< object pointer format
-    QS_FUN_T                                      ///< function pointer format
+    QS_FUN_T,                                     ///< function pointer format
+    QS_I64_T,                                ///< signed 64-bit integer format
+    QS_U64_T,                              ///< unsigned 64-bit integer format
+    QS_U32_HEX_T                    ///< unsigned 32-bit integer in hex format
 };
 
 /// \brief Output formatted int8_t to the QS record
@@ -2857,6 +3049,18 @@
 #define QS_F64(width_, data_) \
     QS::f64((uint8_t)(((width_) << 4)) | QS_F64_T, (data_))
 
+/// \brief Output formatted int64_t to the QS record
+#define QS_I64(width_, data_) \
+    QS::u64((uint8_t)(((width_) << 4)) | QS_I64_T, (data_))
+
+/// \brief Output formatted uint64_t to the QS record
+#define QS_U64(width_, data_) \
+    QS::u64((uint8_t)(((width_) << 4)) | QS_U64_T, (data_))
+
+/// \brief Output formatted uint32_t to the QS record
+#define QS_U32_HEX(width_, data_) \
+    QS::u32((uint8_t)(((width_) << 4)) | QS_U32_HEX_T, (data_))
+
 /// \brief Output formatted zero-terminated ASCII string to the QS record
 #define QS_STR(str_)            QS::str(str_)
 
@@ -2875,6 +3079,8 @@
     #define QS_OBJ(obj_)        QS::u16(QS_OBJ_T, (uint16_t)(obj_))
 #elif (QS_OBJ_PTR_SIZE == 4)
     #define QS_OBJ(obj_)        QS::u32(QS_OBJ_T, (uint32_t)(obj_))
+#elif (QS_OBJ_PTR_SIZE == 8)
+    #define QS_OBJ(obj_)        QS::u64(QS_OBJ_T, (uint64_t)(obj_))
 #else
     /// \brief Output formatted object pointer to the QS record
     #define QS_OBJ(obj_)        QS::u32(QS_OBJ_T, (uint32_t)(obj_))
@@ -2887,6 +3093,8 @@
     #define QS_FUN(fun_)        QS::u16(QS_FUN_T, (uint16_t)(fun_))
 #elif (QS_FUN_PTR_SIZE == 4)
     #define QS_FUN(fun_)        QS::u32(QS_FUN_T, (uint32_t)(fun_))
+#elif (QS_FUN_PTR_SIZE == 8)
+    #define QS_FUN(fun_)        QS::u64(QS_FUN_T, (uint64_t)(fun_))
 #else
     /// \brief Output formatted function pointer to the QS record
     #define QS_FUN(fun_)        QS::u32(QS_FUN_T, (uint32_t)(fun_))
@@ -3159,7 +3367,9 @@
 #define QS_U32(width_, data_)           ((void)0)
 #define QS_F32(width_, data_)           ((void)0)
 #define QS_F64(width_, data_)           ((void)0)
+#define QS_U64(width_, data_)           ((void)0)
 #define QS_STR(str_)                    ((void)0)
+#define QS_U32_HEX(width_, data_)       ((void)0)
 #define QS_STR_ROM(str_)                ((void)0)
 #define QS_MEM(mem_, size_)             ((void)0)
 #define QS_SIG(sig_, obj_)              ((void)0)
@@ -3180,6 +3390,7 @@
 #define QS_U8_(data_)                   ((void)0)
 #define QS_U16_(data_)                  ((void)0)
 #define QS_U32_(data_)                  ((void)0)
+#define QS_U64_(data_)                  ((void)0)
 #define QS_TIME_()                      ((void)0)
 #define QS_SIG_(sig_)                   ((void)0)
 #define QS_EVS_(size_)                  ((void)0)
@@ -3198,6 +3409,10 @@
 
 #endif                                                                // Q_SPY
 
+#ifdef Q_USE_NAMESPACE
+}                                                              // namespace QP
+#endif
+
 //////////////////////////////////////////////////////////////////////////////
 /**
 * \brief Customizable QP assertions.
@@ -3207,19 +3422,23 @@
 * programs.
 *
 * \note The preprocessor switch Q_NASSERT disables checking assertions.
-* In particular macros \ref Q_ASSERT, \ref Q_REQUIRE, \ref Q_ENSURE,
-* \ref Q_INVARIANT, and \ref Q_ERROR do NOT evaluate the test condition
+* In particular macros #Q_ASSERT, #Q_REQUIRE, #Q_ENSURE, #Q_INVARIANT,
+* #Q_ERROR as well as  #Q_ASSERT_ID, #Q_REQUIRE_ID, #Q_ENSURE_ID,
+* #Q_INVARIANT_ID, and #Q_ERROR_ID do NOT evaluate the test condition
 * passed as the argument to these macros. One notable exception is the
-* macro \ref Q_ALLEGE, that still evaluates the test condition, but does
+* macro #Q_ALLEGE, that still evaluates the test condition, but does
 * not report assertion failures when the switch Q_NASSERT is defined.
 */
 #ifdef Q_NASSERT          /* Q_NASSERT defined--assertion checking disabled */
 
     #define Q_DEFINE_THIS_FILE
     #define Q_DEFINE_THIS_MODULE(name_)
-    #define Q_ASSERT(test_)    ((void)0)
-    #define Q_ALLEGE(test_)    ((void)(test_))
-    #define Q_ERROR()          ((void)0)
+    #define Q_ASSERT(test_)             ((void)0)
+    #define Q_ASSERT_ID(id_, test_)     ((void)0)
+    #define Q_ALLEGE(test_)             ((void)(test_))
+    #define Q_ALLEGE_ID(id_, test_)     ((void)(test_))
+    #define Q_ERROR()                   ((void)0)
+    #define Q_ERROR_ID(id_)             ((void)0)
 
 #else                  /* Q_NASSERT not defined--assertion checking enabled */
 
@@ -3227,9 +3446,10 @@
         extern "C" {
     #endif
 
-    /** callback invoked in case the condition passed to \ref Q_ASSERT,
-    * \ref Q_REQUIRE, \ref Q_ENSURE, \ref Q_ERROR, or \ref Q_ALLEGE
-    * evaluates to FALSE.
+    /** callback invoked in case the condition passed to #Q_ASSERT,
+    * #Q_REQUIRE, #Q_ENSURE, #Q_ERROR, #Q_ALLEGE as well as #Q_ASSERT_ID,
+    * #Q_REQUIRE_ID, #Q_ENSURE_ID, #Q_ERROR_ID, and #Q_ALLEGE_ID evaluates
+    * to FALSE.
     *
     * \param file file name where the assertion failed
     * \param line line number at which the assertion failed
@@ -3258,50 +3478,116 @@
     /** General purpose assertion that makes sure the \a test_ argument is
     * TRUE. Calls the Q_onAssert() callback if the \a test_ evaluates
     * to FALSE.
-    * \note the \a test_ is NOT evaluated if assertions are
-    * disabled with the Q_NASSERT switch.
+    * \note the \a test_ is NOT evaluated if assertions are disabled with
+    * the Q_NASSERT switch.
+    * \sa #Q_ASSERT_ID
     */
     #define Q_ASSERT(test_) \
         if (test_) { \
         } \
-        else (Q_onAssert(l_this_file, __LINE__))
+        else (Q_onAssert(&l_this_file[0], __LINE__))
+
+    /** General purpose assertion that makes sure the \a test_ argument is
+    * TRUE. Calls the Q_onAssert() callback if the \a test_ evaluates
+    * to FALSE. The argument \a id_ is the ID number (unique within
+    * the file) of the assertion. This assertion style is better suited
+    * for unit testig, because it avoids the volatility of line numbers
+    * for indentifying assertions.
+    * \note the \a test_ is NOT evaluated if assertions are disabled with
+    * the Q_NASSERT switch.
+    * \sa #Q_ASSERT
+    */
+    #define Q_ASSERT_ID(id_, test_) \
+        if (test_) { \
+        } \
+        else (Q_onAssert(&l_this_file[0], (id_)))
 
     /** General purpose assertion that ALWAYS evaluates the \a test_
     * argument and calls the Q_onAssert() callback if the \a test_
     * evaluates to FALSE.
-    * \note the \a test_ argument IS always evaluated even when assertions are
-    * disabled with the Q_NASSERT macro. When the Q_NASSERT macro is
+    * \note the \a test_ argument IS always evaluated even when assertions
+    * are disabled with the Q_NASSERT macro. When the Q_NASSERT macro is
     * defined, the Q_onAssert() callback is NOT called, even if the
     * \a test_ evaluates to FALSE.
+    * \sa #Q_ALLEGE_ID
     */
     #define Q_ALLEGE(test_)    Q_ASSERT(test_)
 
+    /** General purpose assertion that ALWAYS evaluates the \a test_
+    * argument and calls the Q_onAssert() callback if the \a test_
+    * evaluates to FALSE. This assertion style is better suited
+    * for unit testig, because it avoids the volatility of line numbers
+    * for indentifying assertions.
+    * \note the \a test_ argument IS always evaluated even when assertions
+    * are disabled with the Q_NASSERT macro. When the Q_NASSERT macro is
+    * defined, the Q_onAssert() callback is NOT called, even if the
+    * \a test_ evaluates to FALSE.
+    * \sa #Q_ALLEGE
+    */
+    #define Q_ALLEGE_ID(id_, test_) Q_ASSERT_ID(id_, test_)
+
     /** Assertion that always calls the Q_onAssert() callback if
     * ever executed.
     * \note can be disabled with the Q_NASSERT switch.
+    * \sa #Q_ERROR_ID
     */
     #define Q_ERROR() \
         (Q_onAssert(l_this_file, __LINE__))
 
+    /** Assertion that always calls the Q_onAssert() callback if
+    * ever executed. This assertion style is better suited for unit
+    * testig, because it avoids the volatility of line numbers for
+    * indentifying assertions.
+    * \note can be disabled with the Q_NASSERT switch.
+    * \sa #Q_ERROR
+    */
+    #define Q_ERROR_ID(id_) \
+        (Q_onAssert(l_this_file, (id_)))
+
+
 #endif                                                         /* Q_NASSERT */
 
 /** Assertion that checks for a precondition. This macro is equivalent to
-* \ref Q_ASSERT, except the name provides a better documentation of the
+* #Q_ASSERT, except the name provides a better documentation of the
 * intention of this assertion.
+* \sa #Q_REQUIRE_ID
 */
-#define Q_REQUIRE(test_)   Q_ASSERT(test_)
+#define Q_REQUIRE(test_)         Q_ASSERT(test_)
+
+/** Assertion that checks for a precondition. This macro is equivalent to
+* #Q_ASSERT_ID, except the name provides a better documentation of the
+* intention of this assertion.
+* \sa #Q_REQUIRE
+*/
+#define Q_REQUIRE_ID(id_, test_) Q_ASSERT_ID(id_, test_)
 
 /** Assertion that checks for a postcondition. This macro is equivalent to
-* \ref Q_ASSERT, except the name provides a better documentation of the
+* #Q_ASSERT, except the name provides a better documentation of the
 * intention of this assertion.
+* \sa #Q_ENSURE_ID
 */
-#define Q_ENSURE(test_)    Q_ASSERT(test_)
+#define Q_ENSURE(test_)          Q_ASSERT(test_)
+
+/** Assertion that checks for a postcondition. This macro is equivalent to
+* #Q_ASSERT_ID, except the name provides a better documentation of the
+* intention of this assertion.
+* \sa #Q_ENSURE
+*/
+#define Q_ENSURE_ID(id_, test_)  Q_ASSERT_ID(id_, test_)
 
 /** Assertion that checks for an invariant. This macro is equivalent to
-* \ref Q_ASSERT, except the name provides a better documentation of the
+* #Q_ASSERT, except the name provides a better documentation of the
 * intention of this assertion.
+* \sa #Q_INVARIANT_ID
 */
-#define Q_INVARIANT(test_) Q_ASSERT(test_)
+#define Q_INVARIANT(test_)       Q_ASSERT(test_)
+
+/** Assertion that checks for an invariant. This macro is equivalent to
+* #Q_ASSERT_ID, except the name provides a better documentation of the
+* intention of this assertion.
+* \sa #Q_INVARIANT
+*/
+#define Q_INVARIANT_ID(id_, test_) Q_ASSERT_ID(id_, test_)
 
 /** Compile-time assertion exploits the fact that in C/C++ a dimension of
 * an array cannot be negative. The following declaration causes a compilation