|
QP-nano
|
00001 /***************************************************************************** 00002 * Product: QF-nano implemenation 00003 * Last Updated for Version: 4.3.00 00004 * Date of the Last Update: Oct 29, 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 00027 *****************************************************************************/ 00028 #include "qpn_port.h" /* QP-nano port */ 00029 00030 Q_DEFINE_THIS_MODULE(qfn) 00031 00032 00038 /* Global-scope objects ----------------------------------------------------*/ 00039 uint8_t volatile QF_readySet_; /* ready-set of QF-nano */ 00040 00041 /* local objects -----------------------------------------------------------*/ 00042 static uint8_t const Q_ROM Q_ROM_VAR l_pow2Lkup[] = { 00043 0x00U, 0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U 00044 }; 00045 00046 /*..........................................................................*/ 00047 #if (Q_PARAM_SIZE != 0) 00048 void QActive_post(QActive *me, QSignal sig, QParam par) 00049 #else 00050 void QActive_post(QActive *me, QSignal sig) 00051 #endif 00052 { 00053 QActiveCB const Q_ROM *ao = &QF_active[me->prio]; 00054 00055 /* the queue must be able to accept the event (cannot overflow) */ 00056 Q_ASSERT(me->nUsed < Q_ROM_BYTE(ao->end)); 00057 00058 QF_INT_LOCK(); 00059 /* insert event into the ring buffer (FIFO) */ 00060 ((QEvent *)Q_ROM_PTR(ao->queue))[me->head].sig = sig; 00061 #if (Q_PARAM_SIZE != 0) 00062 ((QEvent *)Q_ROM_PTR(ao->queue))[me->head].par = par; 00063 #endif 00064 if (me->head == (uint8_t)0) { 00065 me->head = Q_ROM_BYTE(ao->end); /* wrap the head */ 00066 } 00067 --me->head; 00068 ++me->nUsed; 00069 if (me->nUsed == (uint8_t)1) { /* is this the first event? */ 00070 QF_readySet_ |= Q_ROM_BYTE(l_pow2Lkup[me->prio]); /* set the bit */ 00071 #ifdef QK_PREEMPTIVE 00072 sig = QK_schedPrio_(); /* reuse 'sig' to hold the priority */ 00073 if (sig != 0) { 00074 QK_sched_(sig); /* check for synchronous preemption */ 00075 } 00076 #endif 00077 } 00078 QF_INT_UNLOCK(); 00079 } 00080 /*..........................................................................*/ 00081 #if (Q_PARAM_SIZE != 0) 00082 void QActive_postISR(QActive *me, QSignal sig, QParam par) 00083 #else 00084 void QActive_postISR(QActive *me, QSignal sig) 00085 #endif 00086 { 00087 #ifdef QF_ISR_NEST 00088 #ifdef QF_ISR_KEY_TYPE 00089 QF_ISR_KEY_TYPE key; 00090 #endif 00091 #endif 00092 QActiveCB const Q_ROM *ao = &QF_active[me->prio]; 00093 00094 /* the queue must be able to accept the event (cannot overflow) */ 00095 Q_ASSERT(me->nUsed < Q_ROM_BYTE(ao->end)); 00096 00097 #ifdef QF_ISR_NEST 00098 #ifdef QF_ISR_KEY_TYPE 00099 QF_ISR_LOCK(key); 00100 #else 00101 QF_INT_LOCK(); 00102 #endif 00103 #endif 00104 /* insert event into the ring buffer (FIFO) */ 00105 ((QEvent *)Q_ROM_PTR(ao->queue))[me->head].sig = sig; 00106 #if (Q_PARAM_SIZE != 0) 00107 ((QEvent *)Q_ROM_PTR(ao->queue))[me->head].par = par; 00108 #endif 00109 if (me->head == (uint8_t)0) { 00110 me->head = Q_ROM_BYTE(ao->end); /* wrap the head */ 00111 } 00112 --me->head; 00113 ++me->nUsed; 00114 if (me->nUsed == (uint8_t)1) { /* is this the first event? */ 00115 QF_readySet_ |= Q_ROM_BYTE(l_pow2Lkup[me->prio]); /* set the bit */ 00116 } 00117 00118 #ifdef QF_ISR_NEST 00119 #ifdef QF_ISR_KEY_TYPE 00120 QF_ISR_UNLOCK(key); 00121 #else 00122 QF_INT_UNLOCK(); 00123 #endif 00124 #endif 00125 } 00126 00127 /*--------------------------------------------------------------------------*/ 00128 #if (QF_TIMEEVT_CTR_SIZE != 0) 00129 00130 /*..........................................................................*/ 00131 void QF_tickISR(void) { 00132 uint8_t p = (uint8_t)QF_MAX_ACTIVE; 00133 QActiveCB const Q_ROM *ao = &QF_active[(uint8_t)QF_MAX_ACTIVE]; 00134 do { 00135 QActive *a = (QActive *)Q_ROM_PTR(ao->act); 00136 if (a->tickCtr != (QTimeEvtCtr)0) { 00137 --a->tickCtr; 00138 if (a->tickCtr == (QTimeEvtCtr)0) { 00139 #if (Q_PARAM_SIZE != 0) 00140 QActive_postISR(a, (QSignal)Q_TIMEOUT_SIG, (QParam)0); 00141 #else 00142 QActive_postISR(a, (QSignal)Q_TIMEOUT_SIG); 00143 #endif 00144 } 00145 } 00146 --ao; 00147 --p; 00148 } while (p != (uint8_t)0); 00149 } 00150 00151 #if (QF_TIMEEVT_CTR_SIZE > 1) 00152 /*..........................................................................*/ 00153 void QActive_arm(QActive *me, QTimeEvtCtr tout) { 00154 QF_INT_LOCK(); 00155 me->tickCtr = tout; 00156 QF_INT_UNLOCK(); 00157 } 00158 /*..........................................................................*/ 00159 void QActive_disarm(QActive *me) { 00160 QF_INT_LOCK(); 00161 me->tickCtr = (QTimeEvtCtr)0; 00162 QF_INT_UNLOCK(); 00163 } 00164 #endif /* #if (QF_TIMEEVT_CTR_SIZE > 1) */ 00165 00166 #endif /* #if (QF_TIMEEVT_CTR_SIZE != 0) */ 00167 00168 /*--------------------------------------------------------------------------*/ 00169 #ifndef QK_PREEMPTIVE 00170 00171 void QF_run(void) { 00172 static uint8_t const Q_ROM Q_ROM_VAR log2Lkup[] = { 00173 0U, 1U, 2U, 2U, 3U, 3U, 3U, 3U, 4U, 4U, 4U, 4U, 4U, 4U, 4U, 4U 00174 }; 00175 static uint8_t const Q_ROM Q_ROM_VAR invPow2Lkup[] = { 00176 0xFFU, 0xFEU, 0xFDU, 0xFBU, 0xF7U, 0xEFU, 0xDFU, 0xBFU, 0x7FU 00177 }; 00178 uint8_t p; 00179 QActive *a; 00180 QActiveCB const Q_ROM *ao; 00181 00182 /* set priorities all registered active objects... */ 00183 for (p = (uint8_t)1; p <= (uint8_t)QF_MAX_ACTIVE; ++p) { 00184 a = (QActive *)Q_ROM_PTR(QF_active[p].act); 00185 Q_ASSERT(a != (QActive *)0); /* QF_active[p] must be initialized */ 00186 a->prio = p; /* set the priority of the active object */ 00187 } 00188 /* trigger initial transitions in all registered active objects... */ 00189 for (p = (uint8_t)1; p <= (uint8_t)QF_MAX_ACTIVE; ++p) { 00190 a = (QActive *)Q_ROM_PTR(QF_active[p].act); 00191 #ifndef QF_FSM_ACTIVE 00192 QHsm_init((QHsm *)a); /* take the initial transition in HSM */ 00193 #else 00194 QFsm_init((QFsm *)a); /* take the initial transition in FSM */ 00195 #endif 00196 } 00197 00198 QF_onStartup(); /* invoke startup callback */ 00199 00200 for (;;) { /* the event loop of the vanilla kernel */ 00201 QF_INT_LOCK(); 00202 if (QF_readySet_ != (uint8_t)0) { 00203 #if (QF_MAX_ACTIVE > 4) 00204 if ((QF_readySet_ & 0xF0) != 0U) { /* upper nibble used? */ 00205 p = (uint8_t)(Q_ROM_BYTE(log2Lkup[QF_readySet_ >> 4]) + 4); 00206 } 00207 else /* upper nibble of QF_readySet_ is zero */ 00208 #endif 00209 { 00210 p = Q_ROM_BYTE(log2Lkup[QF_readySet_]); 00211 } 00212 ao = &QF_active[p]; 00213 a = (QActive *)Q_ROM_PTR(ao->act); 00214 Q_ASSERT(a->nUsed > 0); /* some events must be available */ 00215 --a->nUsed; 00216 if (a->nUsed == (uint8_t)0) { /* queue becoming empty? */ 00217 QF_readySet_ &= Q_ROM_BYTE(invPow2Lkup[p]);/* clear the bit */ 00218 } 00219 Q_SIG(a) = 00220 ((QEvent *)Q_ROM_PTR(ao->queue))[a->tail].sig; 00221 #if (Q_PARAM_SIZE != 0) 00222 Q_PAR(a) = 00223 ((QEvent *)Q_ROM_PTR(ao->queue))[a->tail].par; 00224 #endif 00225 if (a->tail == (uint8_t)0) { /* wrap around? */ 00226 a->tail = Q_ROM_BYTE(ao->end); 00227 } 00228 --a->tail; 00229 QF_INT_UNLOCK(); 00230 00231 #ifndef QF_FSM_ACTIVE 00232 QHsm_dispatch((QHsm *)a); /* dispatch to HSM */ 00233 #else 00234 QFsm_dispatch((QFsm *)a); /* dispatch to FSM */ 00235 #endif 00236 } 00237 else { 00238 QF_onIdle(); /* see NOTE01 */ 00239 } 00240 } 00241 } 00242 00243 #endif /* #ifndef QK_PREEMPTIVE */ 00244 00245 /***************************************************************************** 00246 * NOTE01: 00247 * QF_onIdle() must be called with interrupts locked because the determination 00248 * of the idle condition (no events in the queues) can be changed by any 00249 * interrupt. The QF_onIdle() MUST enable interrups internally, ideally 00250 * atomically with putting the CPU into a low-power mode. 00251 */
1.7.5.1