QP/C
qk.c
Go to the documentation of this file.
00001 /*****************************************************************************
00002 * Product: QK/C
00003 * Last Updated for Version: 4.4.00
00004 * Date of the Last Update:  Jan 05, 2012
00005 *
00006 *                    Q u a n t u m     L e a P s
00007 *                    ---------------------------
00008 *                    innovating embedded systems
00009 *
00010 * Copyright (C) 2002-2012 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 #include "qk_pkg.h"
00029 #include "qassert.h"
00030 
00031 Q_DEFINE_THIS_MODULE("qk")
00032 
00033 
00041 /* Public-scope objects ----------------------------------------------------*/
00042 #if (QF_MAX_ACTIVE <= 8)
00043     QPSet8  QK_readySet_;                                   /* QK ready-set */
00044 #else
00045     QPSet64 QK_readySet_;                                   /* QK ready-set */
00046 #endif
00047                                       /* start with the QK scheduler locked */
00048 uint8_t QK_currPrio_ = (uint8_t)(QF_MAX_ACTIVE + 1);
00049 uint8_t QK_intNest_;                       /* start with nesting level of 0 */
00050 
00051 /*..........................................................................*/
00052 char_t const Q_ROM * Q_ROM_VAR QK_getVersion(void) {
00053     return QF_getVersion();
00054 }
00055 /*..........................................................................*/
00056 void QF_init(void) {
00057     QK_init();                              /* might be defined in assembly */
00058 }
00059 /*..........................................................................*/
00060 void QF_stop(void) {
00061     QF_onCleanup();                                     /* cleanup callback */
00062     /* nothing else to do for the QK preemptive kernel */
00063 }
00064 /*..........................................................................*/
00065 static void initialize(void) {
00066     uint8_t p;
00067 
00068     QK_currPrio_ = (uint8_t)0;     /* set the priority for the QK idle loop */
00069     p = QK_schedPrio_();
00070     if (p != (uint8_t)0) {
00071         QK_sched_(p);                 /* process all events produced so far */
00072     }
00073 }
00074 /*..........................................................................*/
00075 void QF_run(void) {
00076     QF_INT_DISABLE();
00077     initialize();
00078     QF_onStartup();                                     /* startup callback */
00079     QF_INT_ENABLE();
00080 
00081     for (;;) {                                          /* the QK idle loop */
00082         QK_onIdle();                      /* invoke the QK on-idle callback */
00083     }
00084 }
00085 /*..........................................................................*/
00086 void QActive_start(QActive *me, uint8_t prio,
00087                    QEvent const *qSto[], uint32_t qLen,
00088                    void *stkSto, uint32_t stkSize,
00089                    QEvent const *ie)
00090 {
00091     Q_REQUIRE(((uint8_t)0 < prio) && (prio <= (uint8_t)QF_MAX_ACTIVE));
00092 
00093     QEQueue_init(&me->eQueue, qSto, (QEQueueCtr)qLen);
00094     me->prio = prio;
00095     QF_add_(me);                     /* make QF aware of this active object */
00096 
00097 #if defined(QK_TLS) || defined(QK_EXT_SAVE)
00098     me->osObject = (uint8_t)stkSize;  /* osObject contains the thread flags */
00099     me->thread = stkSto;/* contains the pointer to the thread-local storage */
00100 #else
00101     Q_ASSERT((stkSto == (void *)0) && (stkSize == (uint32_t)0));
00102 #endif
00103 
00104     QF_ACTIVE_INIT_(&me->super, ie);          /* execute initial transition */
00105 
00106     QS_FLUSH();                       /* flush the trace buffer to the host */
00107 }
00108 /*..........................................................................*/
00109 void QActive_stop(QActive *me) {
00110     QF_remove_(me);                /* remove this active object from the QF */
00111 }
00112 /*..........................................................................*/
00113 /* NOTE: QK schedPrio_() is entered and exited with interrupts DISABLED     */
00114 uint8_t QK_schedPrio_(void) {
00115     uint8_t p;               /* highest-priority active object ready to run */
00116 
00117 #if (QF_MAX_ACTIVE <= 8)
00118         /* determine the priority of the highest-priority task ready to run */
00119     QPSet8_findMax(&QK_readySet_, p);
00120 #else
00121         /* determine the priority of the highest-priority task ready to run */
00122     QPSet64_findMax(&QK_readySet_, p);
00123 #endif
00124 
00125 #ifdef QK_NO_MUTEX
00126     if (p <= QK_currPrio_) {                    /* do we have a preemption? */
00127 #else                                /* QK priority-ceiling mutexes allowed */
00128     if ((p <= QK_currPrio_) || (p <= QK_ceilingPrio_)) {
00129 #endif
00130         p = (uint8_t)0;
00131     }
00132     return p;
00133 }