qkn.c

Go to the documentation of this file.
00001 /*****************************************************************************
00002 * Product: QK-nano implemenation
00003 * Last Updated for Version: 4.0.02
00004 * Date of the Last Update:  Jul 11, 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 #include "qpn_port.h"                                       /* QP-nano port */
00029 
00030 Q_DEFINE_THIS_MODULE(qkn)
00031 
00032 
00038 #ifndef QK_PREEMPTIVE
00039     #error "The required header file qkn.h is not included in qpn_port.h"
00040 #endif
00041 
00042 /* Global-scope objects ----------------------------------------------------*/
00043                                       /* start with the QK scheduler locked */
00044 uint8_t volatile QK_currPrio_ = (uint8_t)(QF_MAX_ACTIVE + 1);
00045 
00046 #ifdef QF_ISR_NEST
00047 uint8_t volatile QK_intNest_;              /* start with nesting level of 0 */
00048 #endif
00049 
00050 /* local objects -----------------------------------------------------------*/
00051 static QActive *l_act;                                         /* ptr to AO */
00052 
00053 /*..........................................................................*/
00054 void QF_run(void) {
00055     static uint8_t p;                /* declared static to save stack space */
00056 
00057                          /* set priorities all registered active objects... */
00058     for (p = (uint8_t)1; p <= (uint8_t)QF_MAX_ACTIVE; ++p) {
00059         l_act = (QActive *)Q_ROM_PTR(QF_active[p].act);
00060         Q_ASSERT(l_act != (QActive *)0);/* QF_active[p] must be initialized */
00061         l_act->prio = p;           /* set the priority of the active object */
00062     }
00063          /* trigger initial transitions in all registered active objects... */
00064     for (p = (uint8_t)1; p <= (uint8_t)QF_MAX_ACTIVE; ++p) {
00065         l_act = (QActive *)Q_ROM_PTR(QF_active[p].act);
00066 #ifndef QF_FSM_ACTIVE
00067         QHsm_init((QHsm *)l_act);                          /* initial tran. */
00068 #else
00069         QFsm_init((QFsm *)l_act);                          /* initial tran. */
00070 #endif
00071     }
00072 
00073     QF_INT_LOCK();
00074     QK_currPrio_ = (uint8_t)0;     /* set the priority for the QK idle loop */
00075     QK_SCHEDULE_();                   /* process all events produced so far */
00076     QF_INT_UNLOCK();
00077 
00078     QF_onStartup();                             /* invoke startup callback  */
00079 
00080     for (;;) {                                    /* enter the QK idle loop */
00081         QK_onIdle();                         /* invoke the on-idle callback */
00082     }
00083 }
00084 /*..........................................................................*/
00085 /* NOTE: the QK scheduler is entered and exited with interrupts LOCKED */
00086 void QK_schedule_(void) Q_REENTRANT {
00087     static uint8_t const Q_ROM Q_ROM_VAR log2Lkup[] = {
00088         0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4
00089     };
00090     static uint8_t const Q_ROM Q_ROM_VAR invPow2Lkup[] = {
00091         0xFF, 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F
00092     };
00093 
00094     uint8_t pin;                            /* the initial QK-nano priority */
00095     uint8_t p;           /* new highest-priority active object ready to run */
00096 
00097           /* determine the priority of the highest-priority AO ready to run */
00098 #if (QF_MAX_ACTIVE > 4)
00099     if ((QF_readySet_ & 0xF0) != 0) {                 /* upper nibble used? */
00100         p = (uint8_t)(Q_ROM_BYTE(log2Lkup[QF_readySet_ >> 4]) + 4);
00101     }
00102     else                            /* upper nibble of QF_readySet_ is zero */
00103 #endif
00104     {
00105         p = Q_ROM_BYTE(log2Lkup[QF_readySet_]);
00106     }
00107 
00108     if (p > QK_currPrio_) {                  /* is the new priority higher? */
00109         pin = QK_currPrio_;                    /* save the initial priority */
00110         do {
00111             QK_currPrio_ = p;  /* new priority becomes the current priority */
00112             QF_INT_UNLOCK();          /* unlock interrupts to launch a task */
00113 
00114                                       /* dispatch to HSM (execute RTC step) */
00115 #ifndef QF_FSM_ACTIVE
00116             QHsm_dispatch((QHsm *)Q_ROM_PTR(QF_active[p].act));
00117 #else
00118             QFsm_dispatch((QFsm *)Q_ROM_PTR(QF_active[p].act));
00119 #endif
00120 
00121             QF_INT_LOCK();
00122                /* set cb and a again, in case they change over the RTC step */
00123             l_act = (QActive *)Q_ROM_PTR(QF_active[p].act);
00124 
00125             if ((--l_act->nUsed) == (uint8_t)0) {/*is queue becoming empty? */
00126                                                      /* clear the ready bit */
00127                 QF_readySet_ &= Q_ROM_BYTE(invPow2Lkup[p]);
00128             }
00129             else {
00130                 Q_SIG(l_act) = ((QEvent *)Q_ROM_PTR(QF_active[p].queue))
00131                                    [l_act->tail].sig;
00132 #if (Q_PARAM_SIZE != 0)
00133                 Q_PAR(l_act) = ((QEvent *)Q_ROM_PTR(QF_active[p].queue))
00134                                    [l_act->tail].par;
00135 #endif
00136                 if (l_act->tail == (uint8_t)0) {            /* wrap around? */
00137                     l_act->tail = Q_ROM_BYTE(QF_active[p].end);/* wrap tail */
00138                 }
00139                 --l_act->tail;
00140             }
00141                           /* determine the highest-priority AO ready to run */
00142             if (QF_readySet_ != (uint8_t)0) {
00143 #if (QF_MAX_ACTIVE > 4)
00144                 if ((QF_readySet_ & 0xF0) != 0) {     /* upper nibble used? */
00145                     p = (uint8_t)(Q_ROM_BYTE(log2Lkup[QF_readySet_ >> 4])+ 4);
00146                 }
00147                 else                /* upper nibble of QF_readySet_ is zero */
00148 #endif
00149                 {
00150                     p = Q_ROM_BYTE(log2Lkup[QF_readySet_]);
00151                 }
00152             }
00153             else {
00154                 p = (uint8_t)0;                    /* break out of the loop */
00155             }
00156 
00157         } while (p > pin);      /* is the new priority higher than initial? */
00158         QK_currPrio_ = pin;                 /* restore the initial priority */
00159     }
00160 }
00161 
00162 #ifdef QK_MUTEX
00163 /*..........................................................................*/
00164 QMutex QK_mutexLock(uint8_t prioCeiling) {
00165     uint8_t mutex;
00166     QF_INT_LOCK();
00167     mutex = QK_currPrio_;             /* the original QK priority to return */
00168     if (QK_currPrio_ < prioCeiling) {
00169         QK_currPrio_ = prioCeiling;                /* raise the QK priority */
00170     }
00171     QF_INT_UNLOCK();
00172     return mutex;
00173 }
00174 /*..........................................................................*/
00175 void QK_mutexUnlock(QMutex mutex) {
00176     QF_INT_LOCK();
00177     if (QK_currPrio_ > mutex) {
00178         QK_currPrio_ = mutex;                 /* restore the saved priority */
00179         QK_SCHEDULE_();
00180     }
00181     QF_INT_UNLOCK();
00182 }
00183 #endif                                                   /* #ifdef QK_MUTEX */

Generated on Sat Nov 15 13:56:09 2008 for QP-nano by  doxygen 1.5.4