QP/C++
qk.cpp
Go to the documentation of this file.
00001 
00002 // Product: QK/C++
00003 // Last Updated for Version: 4.3.00
00004 // Date of the Last Update:  Nov 02, 2011
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2011 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
00028 #include "qk_pkg.h"
00029 #include "qassert.h"
00030 
00036 
00037 // Public-scope objects ------------------------------------------------------
00038 extern "C" {
00039 #if (QF_MAX_ACTIVE <= 8U)
00040 #ifdef Q_USE_NAMESPACE
00041     QP::QPSet8  volatile QK_readySet_;                      // ready set of QK
00042 #else
00043     QPSet8  volatile QK_readySet_;                          // ready set of QK
00044 #endif
00045 #else
00046 #ifdef Q_USE_NAMESPACE
00047     QP::QPSet64 volatile QK_readySet_;                      // ready set of QK
00048 #else
00049     QPSet64 volatile QK_readySet_;                          // ready set of QK
00050 #endif
00051 #endif
00052                                          // start with the QK scheduler locked
00053 uint8_t volatile QK_currPrio_ = (uint8_t)(QF_MAX_ACTIVE + 1);
00054 uint8_t volatile QK_intNest_;                 // start with nesting level of 0
00055 
00056 }                                                                // extern "C"
00057 
00058 #ifdef Q_USE_NAMESPACE
00059 namespace QP {
00060 #endif
00061 
00062 Q_DEFINE_THIS_MODULE(qk)
00063 
00064 //............................................................................
00065 //lint -e970 -e971               ignore MISRA rules 13 and 14 in this function
00066 char const Q_ROM * Q_ROM_VAR QK::getVersion(void) {
00067     static char const Q_ROM Q_ROM_VAR version[] = {
00068         (char)(((QP_VERSION >> 12U) & 0xFU) + (uint8_t)'0'),
00069         '.',
00070         (char)(((QP_VERSION >>  8U) & 0xFU) + (uint8_t)'0'),
00071         '.',
00072         (char)(((QP_VERSION >>  4U) & 0xFU) + (uint8_t)'0'),
00073         (char)((QP_VERSION          & 0xFU) + (uint8_t)'0'),
00074         '\0'
00075     };
00076     return version;
00077 }
00078 //............................................................................
00079 void QF::init(void) {
00080     QK_init();           // QK initialization ("C" linkage, might be assembly)
00081 }
00082 //............................................................................
00083 void QF::stop(void) {
00084     QF::onCleanup();                                       // cleanup callback
00085     // nothing else to do for the QK preemptive kernel
00086 }
00087 //............................................................................
00088 static void initialize(void) {
00089     QK_currPrio_ = (uint8_t)0;        // set the priority for the QK idle loop
00090     uint8_t p = QK_schedPrio_();
00091     if (p != (uint8_t)0) {
00092         QK_sched_(p);                    // process all events produced so far
00093     }
00094 }
00095 //............................................................................
00096 void QF::run(void) {
00097     QF_INT_DISABLE();
00098     initialize();
00099     onStartup();                                           // startup callback
00100     QF_INT_ENABLE();
00101 
00102     for (;;) {                                             // the QK idle loop
00103         QK::onIdle();                        // invoke the QK on-idle callback
00104     }
00105 }
00106 //............................................................................
00107 void QActive::start(uint8_t prio,
00108                     QEvent const *qSto[], uint32_t qLen,
00109                     void *tls, uint32_t flags,
00110                     QEvent const *ie)
00111 {
00112     Q_REQUIRE(((uint8_t)0 < prio) && (prio <= (uint8_t)QF_MAX_ACTIVE));
00113 
00114     m_eQueue.init(qSto, (QEQueueCtr)qLen);       // initialize the event queue
00115     m_prio = prio;
00116     QF::add_(this);                     // make QF aware of this active object
00117 
00118 #if defined(QK_TLS) || defined(QK_EXT_SAVE)
00119     m_osObject = (uint8_t)flags;       // m_osObject contains the thread flags
00120     m_thread   = tls;      // contains the pointer to the thread-local-storage
00121 #else
00122     Q_ASSERT((tls == (void *)0) && (flags == (uint32_t)0));
00123 #endif
00124 
00125     init(ie);                                    // execute initial transition
00126 
00127     QS_FLUSH();                          // flush the trace buffer to the host
00128 }
00129 //............................................................................
00130 void QActive::stop(void) {
00131     QF::remove_(this);                // remove this active object from the QF
00132 }
00133 
00134 #ifdef Q_USE_NAMESPACE
00135 }                                                              // namespace QP
00136 #endif
00137 
00138 //............................................................................
00139 extern "C" {
00140 
00141 // NOTE: QK schedPrio_() is entered and exited with interrupts DISABLED
00142 uint8_t QK_schedPrio_(void) {
00143 
00144 #ifdef Q_USE_NAMESPACE
00145     using namespace QP;
00146 #endif
00147 
00148     uint8_t p = QK_readySet_.findMax();
00149 
00150 #ifdef QK_NO_MUTEX
00151     if (p > QK_currPrio_) {                        // do we have a preemption?
00152 #else                                   // QK priority-ceiling mutexes allowed
00153     if ((p > QK_currPrio_) && (p > QK_ceilingPrio_)) {
00154 #endif
00155         return p;
00156     }
00157     else {
00158         return (uint8_t)0;
00159     }
00160 }
00161 
00162 }                                                                // extern "C"