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.cpp
00001 ////////////////////////////////////////////////////////////////////////////// 00002 // Product: QP/C++ 00003 // Last Updated for QP ver: 4.5.02 (modified to fit in one file) 00004 // Date of the Last Update: Aug 24, 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 program is open source software: you can redistribute it and/or 00013 // modify it under the terms of the GNU General Public License as published 00014 // by the Free Software Foundation, either version 2 of the License, or 00015 // (at your option) any later version. 00016 // 00017 // Alternatively, this program may be distributed and modified under the 00018 // terms of Quantum Leaps commercial licenses, which expressly supersede 00019 // the GNU General Public License and are specifically designed for 00020 // licensees interested in retaining the proprietary status of their code. 00021 // 00022 // This program is distributed in the hope that it will be useful, 00023 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00024 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00025 // GNU General Public License for more details. 00026 // 00027 // You should have received a copy of the GNU General Public License 00028 // along with this program. If not, see <http://www.gnu.org/licenses/>. 00029 // 00030 // Contact information: 00031 // Quantum Leaps Web sites: http://www.quantum-leaps.com 00032 // http://www.state-machine.com 00033 // e-mail: info@quantum-leaps.com 00034 ////////////////////////////////////////////////////////////////////////////// 00035 #include "qp_port.h" // QP port 00036 00037 // "qep_pkg.h" =============================================================== 00038 QP_BEGIN_ 00039 00040 Q_DEFINE_THIS_MODULE("qp") 00041 00042 ////////////////////////////////////////////////////////////////////////////// 00043 /// preallocated reserved events 00044 extern QEvt const QEP_reservedEvt_[]; 00045 00046 /// empty signal for internal use only 00047 QSignal const QEP_EMPTY_SIG_ = static_cast<QSignal>(0); 00048 00049 /// maximum depth of state nesting (including the top level), must be >= 3 00050 int8_t const QEP_MAX_NEST_DEPTH_ = static_cast<int8_t>(6); 00051 00052 uint8_t const u8_0 = static_cast<uint8_t>(0); ///< \brief constant (uint8_t)0 00053 uint8_t const u8_1 = static_cast<uint8_t>(1); ///< \brief constant (uint8_t)1 00054 int8_t const s8_0 = static_cast<int8_t>(0); ///< \brief constant (int8_t)0 00055 int8_t const s8_1 = static_cast<int8_t>(1); ///< \brief constant (int8_t)1 00056 int8_t const s8_n1 = static_cast<int8_t>(-1); ///< \brief constant (int8_t)-1 00057 00058 QP_END_ 00059 00060 /// helper macro to trigger internal event in an HSM 00061 #define QEP_TRIG_(state_, sig_) \ 00062 ((*(state_))(this, &QEP_reservedEvt_[sig_])) 00063 00064 /// helper macro to trigger exit action in an HSM 00065 #define QEP_EXIT_(state_) do { \ 00066 if (QEP_TRIG_(state_, Q_EXIT_SIG) == Q_RET_HANDLED) { \ 00067 QS_BEGIN_(QS_QEP_STATE_EXIT, QS::smObj_, this) \ 00068 QS_OBJ_(this); \ 00069 QS_FUN_(state_); \ 00070 QS_END_() \ 00071 } \ 00072 } while (false) 00073 00074 /// helper macro to trigger entry action in an HSM 00075 #define QEP_ENTER_(state_) do { \ 00076 if (QEP_TRIG_(state_, Q_ENTRY_SIG) == Q_RET_HANDLED) { \ 00077 QS_BEGIN_(QS_QEP_STATE_ENTRY, QS::smObj_, this) \ 00078 QS_OBJ_(this); \ 00079 QS_FUN_(state_); \ 00080 QS_END_() \ 00081 } \ 00082 } while (false) 00083 00084 // "qep.cpp" ================================================================= 00085 /// \brief ::QEP_reservedEvt_ definition and QEP::getVersion() implementation. 00086 00087 QP_BEGIN_ 00088 00089 // Package-scope objects ----------------------------------------------------- 00090 QEvt const QEP_reservedEvt_[] = { 00091 #ifdef Q_EVT_CTOR // Is the QEvt constructor provided? 00092 static_cast<QSignal>(0), 00093 static_cast<QSignal>(1), 00094 static_cast<QSignal>(2), 00095 static_cast<QSignal>(3) 00096 #else // QEvt is a POD (Plain Old Datatype) 00097 { static_cast<QSignal>(0), u8_0, u8_0 }, 00098 { static_cast<QSignal>(1), u8_0, u8_0 }, 00099 { static_cast<QSignal>(2), u8_0, u8_0 }, 00100 { static_cast<QSignal>(3), u8_0, u8_0 } 00101 #endif 00102 }; 00103 //............................................................................ 00104 char_t const Q_ROM * Q_ROM_VAR QEP::getVersion(void) { 00105 uint8_t const u8_zero = static_cast<uint8_t>('0'); 00106 static char_t const Q_ROM Q_ROM_VAR version[] = { 00107 static_cast<char_t>(((QP_VERSION >> 12) & 0xFU) + u8_zero), 00108 static_cast<char_t>('.'), 00109 static_cast<char_t>(((QP_VERSION >> 8) & 0xFU) + u8_zero), 00110 static_cast<char_t>('.'), 00111 static_cast<char_t>(((QP_VERSION >> 4) & 0xFU) + u8_zero), 00112 static_cast<char_t>((QP_VERSION & 0xFU) + u8_zero), 00113 static_cast<char_t>('\0') 00114 }; 00115 return version; 00116 } 00117 00118 QP_END_ 00119 00120 // "qhsm_top.cpp" ============================================================ 00121 /// \brief QHsm::top() implementation. 00122 00123 QP_BEGIN_ 00124 00125 //............................................................................ 00126 QState QHsm::top(void * const, QEvt const * const) { 00127 return Q_RET_IGNORED; // the top state ignores all events 00128 } 00129 00130 QP_END_ 00131 00132 // "qhsm_ini.cpp" ============================================================ 00133 /// \brief QHsm::init() implementation. 00134 00135 QP_BEGIN_ 00136 00137 //............................................................................ 00138 QHsm::~QHsm() { 00139 } 00140 //............................................................................ 00141 void QHsm::init(QEvt const * const e) { 00142 QStateHandler t = m_state; 00143 00144 Q_REQUIRE((m_temp != Q_STATE_CAST(0)) // ctor must be executed 00145 && (t == Q_STATE_CAST(&QHsm::top))); // initial tran. NOT taken 00146 00147 // the top-most initial transition must be taken 00148 Q_ALLEGE((*m_temp)(this, e) == Q_RET_TRAN); 00149 00150 QS_CRIT_STAT_ 00151 do { // drill into the target... 00152 QStateHandler path[QEP_MAX_NEST_DEPTH_]; 00153 int8_t ip = s8_0; // transition entry path index 00154 00155 QS_BEGIN_(QS_QEP_STATE_INIT, QS::smObj_, this) 00156 QS_OBJ_(this); // this state machine object 00157 QS_FUN_(t); // the source state 00158 QS_FUN_(m_temp); // the target of the initial transition 00159 QS_END_() 00160 00161 path[0] = m_temp; 00162 (void)QEP_TRIG_(m_temp, QEP_EMPTY_SIG_); 00163 while (m_temp != t) { 00164 ++ip; 00165 path[ip] = m_temp; 00166 (void)QEP_TRIG_(m_temp, QEP_EMPTY_SIG_); 00167 } 00168 m_temp = path[0]; 00169 // entry path must not overflow 00170 Q_ASSERT(ip < QEP_MAX_NEST_DEPTH_); 00171 00172 do { // retrace the entry path in reverse (desired) order... 00173 QEP_ENTER_(path[ip]); // enter path[ip] 00174 --ip; 00175 } while (ip >= s8_0); 00176 00177 t = path[0]; // current state becomes the new source 00178 } while (QEP_TRIG_(t, Q_INIT_SIG) == Q_RET_TRAN); 00179 00180 QS_BEGIN_(QS_QEP_INIT_TRAN, QS::smObj_, this) 00181 QS_TIME_(); // time stamp 00182 QS_OBJ_(this); // this state machine object 00183 QS_FUN_(t); // the new active state 00184 QS_END_() 00185 00186 m_state = t; // change the current active state 00187 m_temp = t; // mark the configuration as stable 00188 } 00189 00190 QP_END_ 00191 00192 // "qhsm_dis.cpp" ============================================================ 00193 /// \brief QHsm::dispatch() implementation. 00194 00195 QP_BEGIN_ 00196 00197 //............................................................................ 00198 void QHsm::dispatch(QEvt const * const e) { 00199 QStateHandler t = m_state; 00200 00201 Q_REQUIRE(t == m_temp); // the state configuration must be stable 00202 00203 QStateHandler s; 00204 QState r; 00205 QS_CRIT_STAT_ 00206 00207 QS_BEGIN_(QS_QEP_DISPATCH, QS::smObj_, this) 00208 QS_TIME_(); // time stamp 00209 QS_SIG_(e->sig); // the signal of the event 00210 QS_OBJ_(this); // this state machine object 00211 QS_FUN_(t); // the current state 00212 QS_END_() 00213 00214 do { // process the event hierarchically... 00215 s = m_temp; 00216 r = (*s)(this, e); // invoke state handler s 00217 00218 if (r == Q_RET_UNHANDLED) { // unhandled due to a guard? 00219 00220 QS_BEGIN_(QS_QEP_UNHANDLED, QS::smObj_, this) 00221 QS_SIG_(e->sig); // the signal of the event 00222 QS_OBJ_(this); // this state machine object 00223 QS_FUN_(s); // the current state 00224 QS_END_() 00225 00226 r = QEP_TRIG_(s, QEP_EMPTY_SIG_); // find superstate of s 00227 } 00228 } while (r == Q_RET_SUPER); 00229 00230 if (r == Q_RET_TRAN) { // transition taken? 00231 QStateHandler path[QEP_MAX_NEST_DEPTH_]; 00232 int8_t ip = s8_n1; // transition entry path index 00233 int8_t iq; // helper transition entry path index 00234 #ifdef Q_SPY 00235 QStateHandler src = s; // save the transition source for tracing 00236 #endif 00237 00238 path[0] = m_temp; // save the target of the transition 00239 path[1] = t; 00240 00241 while (t != s) { // exit current state to transition source s... 00242 if (QEP_TRIG_(t, Q_EXIT_SIG) == Q_RET_HANDLED) { //exit handled? 00243 QS_BEGIN_(QS_QEP_STATE_EXIT, QS::smObj_, this) 00244 QS_OBJ_(this); // this state machine object 00245 QS_FUN_(t); // the exited state 00246 QS_END_() 00247 00248 (void)QEP_TRIG_(t, QEP_EMPTY_SIG_); // find superstate of t 00249 } 00250 t = m_temp; // m_temp holds the superstate 00251 } 00252 00253 t = path[0]; // target of the transition 00254 00255 if (s == t) { // (a) check source==target (transition to self) 00256 QEP_EXIT_(s); // exit the source 00257 ip = s8_0; // enter the target 00258 } 00259 else { 00260 (void)QEP_TRIG_(t, QEP_EMPTY_SIG_); // superstate of target 00261 t = m_temp; 00262 if (s == t) { // (b) check source==target->super 00263 ip = s8_0; // enter the target 00264 } 00265 else { 00266 (void)QEP_TRIG_(s, QEP_EMPTY_SIG_); // superstate of src 00267 // (c) check source->super==target->super 00268 if (m_temp == t) { 00269 QEP_EXIT_(s); // exit the source 00270 ip = s8_0; // enter the target 00271 } 00272 else { 00273 // (d) check source->super==target 00274 if (m_temp == path[0]) { 00275 QEP_EXIT_(s); // exit the source 00276 } 00277 else { // (e) check rest of source==target->super->super.. 00278 // and store the entry path along the way 00279 // 00280 iq = s8_0; // indicate LCA not found 00281 ip = s8_1; // enter target's superst 00282 path[1] = t; // save the superstate of target 00283 t = m_temp; // save source->super 00284 // find target->super->super 00285 r = QEP_TRIG_(path[1], QEP_EMPTY_SIG_); 00286 while (r == Q_RET_SUPER) { 00287 ++ip; 00288 path[ip] = m_temp; // store the entry path 00289 if (m_temp == s) { // is it the source? 00290 // indicate that LCA found 00291 iq = s8_1; 00292 // entry path must not overflow 00293 Q_ASSERT(ip < QEP_MAX_NEST_DEPTH_); 00294 --ip; // do not enter the source 00295 r = Q_RET_HANDLED; // terminate the loop 00296 } 00297 else { // it is not the source, keep going up 00298 r = QEP_TRIG_(m_temp, QEP_EMPTY_SIG_); 00299 } 00300 } 00301 if (iq == s8_0) { // LCA found yet? 00302 00303 // entry path must not overflow 00304 Q_ASSERT(ip < QEP_MAX_NEST_DEPTH_); 00305 00306 QEP_EXIT_(s); // exit the source 00307 00308 // (f) check the rest of source->super 00309 // == target->super->super... 00310 // 00311 iq = ip; 00312 r = Q_RET_IGNORED; // indicate LCA NOT found 00313 do { 00314 if (t == path[iq]) { // is this the LCA? 00315 r = Q_RET_HANDLED; // indicate LCA found 00316 // do not enter LCA 00317 ip = static_cast<int8_t>(iq - s8_1); 00318 // terminate the loop 00319 iq = s8_n1; 00320 } 00321 else { 00322 --iq; // try lower superstate of target 00323 } 00324 } while (iq >= s8_0); 00325 00326 if (r != Q_RET_HANDLED) { // LCA not found yet? 00327 // (g) check each source->super->... 00328 // for each target->super... 00329 // 00330 r = Q_RET_IGNORED; // keep looping 00331 do { 00332 // exit t unhandled? 00333 if (QEP_TRIG_(t, Q_EXIT_SIG) 00334 == Q_RET_HANDLED) 00335 { 00336 QS_BEGIN_(QS_QEP_STATE_EXIT, 00337 QS::smObj_, this) 00338 QS_OBJ_(this); 00339 QS_FUN_(t); 00340 QS_END_() 00341 00342 (void)QEP_TRIG_(t, QEP_EMPTY_SIG_); 00343 } 00344 t = m_temp; // set to super of t 00345 iq = ip; 00346 do { 00347 if (t == path[iq]) { // is this LCA? 00348 // do not enter LCA 00349 ip = static_cast<int8_t>(iq-s8_1); 00350 // break out of the inner loop 00351 iq = s8_n1; 00352 r = Q_RET_HANDLED; // break outer 00353 } 00354 else { 00355 --iq; 00356 } 00357 } while (iq >= s8_0); 00358 } while (r != Q_RET_HANDLED); 00359 } 00360 } 00361 } 00362 } 00363 } 00364 } 00365 // retrace the entry path in reverse (desired) order... 00366 for (; ip >= s8_0; --ip) { 00367 QEP_ENTER_(path[ip]); // enter path[ip] 00368 } 00369 t = path[0]; // stick the target into register 00370 m_temp = t; // update the next state 00371 00372 // drill into the target hierarchy... 00373 while (QEP_TRIG_(t, Q_INIT_SIG) == Q_RET_TRAN) { 00374 00375 QS_BEGIN_(QS_QEP_STATE_INIT, QS::smObj_, this) 00376 QS_OBJ_(this); // this state machine object 00377 QS_FUN_(t); // the source (pseudo)state 00378 QS_FUN_(m_temp); // the target of the transition 00379 QS_END_() 00380 00381 ip = s8_0; 00382 path[0] = m_temp; 00383 (void)QEP_TRIG_(m_temp, QEP_EMPTY_SIG_); // find superstate 00384 while (m_temp != t) { 00385 ++ip; 00386 path[ip] = m_temp; 00387 (void)QEP_TRIG_(m_temp, QEP_EMPTY_SIG_); // find superstate 00388 } 00389 m_temp = path[0]; 00390 // entry path must not overflow 00391 Q_ASSERT(ip < QEP_MAX_NEST_DEPTH_); 00392 00393 do { // retrace the entry path in reverse (correct) order... 00394 QEP_ENTER_(path[ip]); // enter path[ip] 00395 --ip; 00396 } while (ip >= s8_0); 00397 00398 t = path[0]; 00399 } 00400 00401 QS_BEGIN_(QS_QEP_TRAN, QS::smObj_, this) 00402 QS_TIME_(); // time stamp 00403 QS_SIG_(e->sig); // the signal of the event 00404 QS_OBJ_(this); // this state machine object 00405 QS_FUN_(src); // the source of the transition 00406 QS_FUN_(t); // the new active state 00407 QS_END_() 00408 00409 } 00410 else { // transition not taken 00411 #ifdef Q_SPY 00412 if (r == Q_RET_HANDLED) { 00413 00414 QS_BEGIN_(QS_QEP_INTERN_TRAN, QS::smObj_, this) 00415 QS_TIME_(); // time stamp 00416 QS_SIG_(e->sig); // the signal of the event 00417 QS_OBJ_(this); // this state machine object 00418 QS_FUN_(m_state); // the state that handled the event 00419 QS_END_() 00420 00421 } 00422 else { 00423 00424 QS_BEGIN_(QS_QEP_IGNORED, QS::smObj_, this) 00425 QS_TIME_(); // time stamp 00426 QS_SIG_(e->sig); // the signal of the event 00427 QS_OBJ_(this); // this state machine object 00428 QS_FUN_(m_state); // the current state 00429 QS_END_() 00430 00431 } 00432 #endif 00433 } 00434 00435 m_state = t; // change the current active state 00436 m_temp = t; // mark the configuration as stable 00437 } 00438 00439 QP_END_ 00440 00441 // "qf_pkg.h" ================================================================ 00442 /// \brief Internal (package scope) QF/C++ interface. 00443 00444 /// \brief helper macro to cast const away from an event pointer \a e_ 00445 #define QF_EVT_CONST_CAST_(e_) const_cast<QEvt *>(e_) 00446 00447 QP_BEGIN_ 00448 // QF-specific critical section 00449 #ifndef QF_CRIT_STAT_TYPE 00450 /// \brief This is an internal macro for defining the critical section 00451 /// status type. 00452 /// 00453 /// The purpose of this macro is to enable writing the same code for the 00454 /// case when critical sectgion status type is defined and when it is not. 00455 /// If the macro #QF_CRIT_STAT_TYPE is defined, this internal macro 00456 /// provides the definition of the critical section status varaible. 00457 /// Otherwise this macro is empty. 00458 /// \sa #QF_CRIT_STAT_TYPE 00459 /// 00460 #define QF_CRIT_STAT_ 00461 00462 /// \brief This is an internal macro for entering a critical section. 00463 /// 00464 /// The purpose of this macro is to enable writing the same code for the 00465 /// case when critical sectgion status type is defined and when it is not. 00466 /// If the macro #QF_CRIT_STAT_TYPE is defined, this internal macro 00467 /// invokes #QF_CRIT_ENTRY passing the key variable as the parameter. 00468 /// Otherwise #QF_CRIT_ENTRY is invoked with a dummy parameter. 00469 /// \sa #QF_CRIT_ENTRY 00470 /// 00471 #define QF_CRIT_ENTRY_() QF_CRIT_ENTRY(dummy) 00472 00473 /// \brief This is an internal macro for exiting a cricial section. 00474 /// 00475 /// The purpose of this macro is to enable writing the same code for the 00476 /// case when critical sectgion status type is defined and when it is not. 00477 /// If the macro #QF_CRIT_STAT_TYPE is defined, this internal macro 00478 /// invokes #QF_CRIT_EXIT passing the key variable as the parameter. 00479 /// Otherwise #QF_CRIT_EXIT is invoked with a dummy parameter. 00480 /// \sa #QF_CRIT_EXIT 00481 /// 00482 #define QF_CRIT_EXIT_() QF_CRIT_EXIT(dummy) 00483 00484 #else 00485 #define QF_CRIT_STAT_ QF_CRIT_STAT_TYPE critStat_; 00486 #define QF_CRIT_ENTRY_() QF_CRIT_ENTRY(critStat_) 00487 #define QF_CRIT_EXIT_() QF_CRIT_EXIT(critStat_) 00488 #endif 00489 00490 // package-scope objects ----------------------------------------------------- 00491 extern QTimeEvt *QF_timeEvtListHead_; ///< head of linked list of time events 00492 extern QF_EPOOL_TYPE_ QF_pool_[QF_MAX_EPOOL]; ///< allocate event pools 00493 extern uint8_t QF_maxPool_; ///< # of initialized event pools 00494 extern QSubscrList *QF_subscrList_; ///< the subscriber list array 00495 extern enum_t QF_maxSignal_; ///< the maximum published signal 00496 00497 //............................................................................ 00498 /// \brief Structure representing a free block in the Native QF Memory Pool 00499 /// \sa ::QMPool 00500 struct QFreeBlock { 00501 QFreeBlock *m_next; 00502 }; 00503 00504 ////////////////////////////////////////////////////////////////////////////// 00505 // internal helper inline functions 00506 00507 /// \brief access to the poolId_ of an event \a e 00508 inline uint8_t QF_EVT_POOL_ID_(QEvt const * const e) { return e->poolId_; } 00509 00510 /// \brief access to the refCtr_ of an event \a e 00511 inline uint8_t QF_EVT_REF_CTR_(QEvt const * const e) { return e->refCtr_; } 00512 00513 /// \brief increment the refCtr_ of an event \a e 00514 inline void QF_EVT_REF_CTR_INC_(QEvt const * const e) { 00515 ++(QF_EVT_CONST_CAST_(e))->refCtr_; 00516 } 00517 00518 /// \brief decrement the refCtr_ of an event \a e 00519 inline void QF_EVT_REF_CTR_DEC_(QEvt const * const e) { 00520 --(QF_EVT_CONST_CAST_(e))->refCtr_; 00521 } 00522 00523 ////////////////////////////////////////////////////////////////////////////// 00524 // internal frequently used srongly-typed constants 00525 00526 QTimeEvtCtr const tc_0 = static_cast<QTimeEvtCtr>(0); 00527 00528 void * const null_void = static_cast<void *>(0); 00529 QEvt const * const null_evt = static_cast<QEvt const *>(0); 00530 QTimeEvt * const null_tevt = static_cast<QTimeEvt *>(0); 00531 QActive * const null_act = static_cast<QActive *>(0); 00532 00533 QP_END_ 00534 00535 /// \brief access element at index \a i_ from the base pointer \a base_ 00536 #define QF_PTR_AT_(base_, i_) (base_[i_]) 00537 00538 ////////////////////////////////////////////////////////////////////////////// 00539 #ifdef Q_SPY // QS software tracing enabled? 00540 00541 #if (QF_EQUEUE_CTR_SIZE == 1) 00542 00543 /// \brief Internal QS macro to output an unformatted event queue 00544 /// counter data element 00545 /// \note the counter size depends on the macro #QF_EQUEUE_CTR_SIZE. 00546 #define QS_EQC_(ctr_) QS::u8_(ctr_) 00547 #elif (QF_EQUEUE_CTR_SIZE == 2) 00548 #define QS_EQC_(ctr_) QS::u16_(ctr_) 00549 #elif (QF_EQUEUE_CTR_SIZE == 4) 00550 #define QS_EQC_(ctr_) QS::u32_(ctr_) 00551 #else 00552 #error "QF_EQUEUE_CTR_SIZE not defined" 00553 #endif 00554 00555 00556 #if (QF_EVENT_SIZ_SIZE == 1) 00557 00558 /// \brief Internal QS macro to output an unformatted event size 00559 /// data element 00560 /// \note the event size depends on the macro #QF_EVENT_SIZ_SIZE. 00561 #define QS_EVS_(size_) QS::u8_(size_) 00562 #elif (QF_EVENT_SIZ_SIZE == 2) 00563 #define QS_EVS_(size_) QS::u16_(size_) 00564 #elif (QF_EVENT_SIZ_SIZE == 4) 00565 #define QS_EVS_(size_) QS::u32_(size_) 00566 #endif 00567 00568 00569 #if (QF_MPOOL_SIZ_SIZE == 1) 00570 00571 /// \brief Internal QS macro to output an unformatted memory pool 00572 /// block-size data element 00573 /// \note the block-size depends on the macro #QF_MPOOL_SIZ_SIZE. 00574 #define QS_MPS_(size_) QS::u8_(size_) 00575 #elif (QF_MPOOL_SIZ_SIZE == 2) 00576 #define QS_MPS_(size_) QS::u16_(size_) 00577 #elif (QF_MPOOL_SIZ_SIZE == 4) 00578 #define QS_MPS_(size_) QS::u32_(size_) 00579 #endif 00580 00581 #if (QF_MPOOL_CTR_SIZE == 1) 00582 00583 /// \brief Internal QS macro to output an unformatted memory pool 00584 /// block-counter data element 00585 /// \note the counter size depends on the macro #QF_MPOOL_CTR_SIZE. 00586 #define QS_MPC_(ctr_) QS::u8_(ctr_) 00587 #elif (QF_MPOOL_CTR_SIZE == 2) 00588 #define QS_MPC_(ctr_) QS::u16_(ctr_) 00589 #elif (QF_MPOOL_CTR_SIZE == 4) 00590 #define QS_MPC_(ctr_) QS::u32_(ctr_) 00591 #endif 00592 00593 00594 #if (QF_TIMEEVT_CTR_SIZE == 1) 00595 00596 /// \brief Internal QS macro to output an unformatted time event 00597 /// tick-counter data element 00598 /// \note the counter size depends on the macro #QF_TIMEEVT_CTR_SIZE. 00599 #define QS_TEC_(ctr_) QS::u8_(ctr_) 00600 #elif (QF_TIMEEVT_CTR_SIZE == 2) 00601 #define QS_TEC_(ctr_) QS::u16_(ctr_) 00602 #elif (QF_TIMEEVT_CTR_SIZE == 4) 00603 #define QS_TEC_(ctr_) QS::u32_(ctr_) 00604 #endif 00605 00606 #endif // Q_SPY 00607 00608 // "qa_defer.cpp" ============================================================ 00609 /// \brief QActive::defer() and QActive::recall() implementation. 00610 /// 00611 00612 QP_BEGIN_ 00613 00614 //............................................................................ 00615 void QActive::defer(QEQueue * const eq, QEvt const * const e) const { 00616 eq->postFIFO(e); 00617 } 00618 //............................................................................ 00619 bool QActive::recall(QEQueue * const eq) { 00620 QEvt const * const e = eq->get(); // try to get evt from deferred queue 00621 bool const recalled = (e != null_evt); // event available? 00622 if (recalled) { 00623 postLIFO(e); // post it to the front of the Active Object's queue 00624 00625 QF_CRIT_STAT_ 00626 QF_CRIT_ENTRY_(); 00627 00628 if (QF_EVT_POOL_ID_(e) != u8_0) { // is it a dynamic event? 00629 00630 // after posting to the AO's queue the event must be referenced 00631 // at least twice: once in the deferred event queue (eq->get() 00632 // did NOT decrement the reference counter) and once in the 00633 // AO's event queue. 00634 Q_ASSERT(QF_EVT_REF_CTR_(e) > u8_1); 00635 00636 // we need to decrement the reference counter once, to account 00637 // for removing the event from the deferred event queue. 00638 // 00639 QF_EVT_REF_CTR_DEC_(e); // decrement the reference counter 00640 } 00641 00642 QF_CRIT_EXIT_(); 00643 } 00644 return recalled; // event not recalled 00645 } 00646 00647 QP_END_ 00648 00649 00650 // "qa_fifo.cpp" ============================================================= 00651 /// \brief QActive::postFIFO() implementation. 00652 /// 00653 /// \note this source file is only included in the QF library when the native 00654 /// QF active object queue is used (instead of a message queue of an RTOS). 00655 00656 QP_BEGIN_ 00657 00658 //............................................................................ 00659 #ifndef Q_SPY 00660 void QActive::postFIFO(QEvt const * const e) { 00661 #else 00662 void QActive::postFIFO(QEvt const * const e, void const * const sender) { 00663 #endif 00664 00665 QF_CRIT_STAT_ 00666 QF_CRIT_ENTRY_(); 00667 00668 QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_POST_FIFO, QS::aoObj_, this) 00669 QS_TIME_(); // timestamp 00670 QS_OBJ_(sender); // the sender object 00671 QS_SIG_(e->sig); // the signal of the event 00672 QS_OBJ_(this); // this active object 00673 QS_U8_(QF_EVT_POOL_ID_(e)); // the pool Id of the event 00674 QS_U8_(QF_EVT_REF_CTR_(e)); // the ref count of the event 00675 QS_EQC_(m_eQueue.m_nFree); // number of free entries 00676 QS_EQC_(m_eQueue.m_nMin); // min number of free entries 00677 QS_END_NOCRIT_() 00678 00679 if (QF_EVT_POOL_ID_(e) != u8_0) { // is it a dynamic event? 00680 QF_EVT_REF_CTR_INC_(e); // increment the reference counter 00681 } 00682 00683 if (m_eQueue.m_frontEvt == null_evt) { // is the queue empty? 00684 m_eQueue.m_frontEvt = e; // deliver event directly 00685 QACTIVE_EQUEUE_SIGNAL_(this); // signal the event queue 00686 } 00687 else { // queue is not empty, leave event in the ring-buffer 00688 // queue must accept all posted events 00689 Q_ASSERT(m_eQueue.m_nFree != static_cast<QEQueueCtr>(0)); 00690 // insert event pointer e into the buffer (FIFO) 00691 QF_PTR_AT_(m_eQueue.m_ring, m_eQueue.m_head) = e; 00692 if (m_eQueue.m_head == static_cast<QEQueueCtr>(0)) { // need to wrap? 00693 m_eQueue.m_head = m_eQueue.m_end; // wrap around 00694 } 00695 --m_eQueue.m_head; 00696 00697 --m_eQueue.m_nFree; // update number of free events 00698 if (m_eQueue.m_nMin > m_eQueue.m_nFree) { 00699 m_eQueue.m_nMin = m_eQueue.m_nFree; // update minimum so far 00700 } 00701 } 00702 QF_CRIT_EXIT_(); 00703 } 00704 00705 QP_END_ 00706 00707 // "qa_get_.cpp" ============================================================= 00708 /// \brief QActive::get_() and QF::getQueueMargin() definitions. 00709 /// 00710 /// \note this source file is only included in the QF library when the native 00711 /// QF active object queue is used (instead of a message queue of an RTOS). 00712 00713 QP_BEGIN_ 00714 00715 //............................................................................ 00716 QEvt const *QActive::get_(void) { 00717 QF_CRIT_STAT_ 00718 QF_CRIT_ENTRY_(); 00719 00720 QACTIVE_EQUEUE_WAIT_(this); // wait for event to arrive directly 00721 00722 QEvt const *e = m_eQueue.m_frontEvt; 00723 00724 if (m_eQueue.m_nFree != m_eQueue.m_end) { //any events in the ring buffer? 00725 // remove event from the tail 00726 m_eQueue.m_frontEvt = QF_PTR_AT_(m_eQueue.m_ring, m_eQueue.m_tail); 00727 if (m_eQueue.m_tail == static_cast<QEQueueCtr>(0)) { // need to wrap? 00728 m_eQueue.m_tail = m_eQueue.m_end; // wrap around 00729 } 00730 --m_eQueue.m_tail; 00731 00732 ++m_eQueue.m_nFree; // one more free event in the ring buffer 00733 00734 QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_GET, QS::aoObj_, this) 00735 QS_TIME_(); // timestamp 00736 QS_SIG_(e->sig); // the signal of this event 00737 QS_OBJ_(this); // this active object 00738 QS_U8_(QF_EVT_POOL_ID_(e)); // the pool Id of the event 00739 QS_U8_(QF_EVT_REF_CTR_(e)); // the ref count of the event 00740 QS_EQC_(m_eQueue.m_nFree); // number of free entries 00741 QS_END_NOCRIT_() 00742 } 00743 else { 00744 m_eQueue.m_frontEvt = null_evt; // the queue becomes empty 00745 QACTIVE_EQUEUE_ONEMPTY_(this); 00746 00747 QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_GET_LAST, QS::aoObj_, this) 00748 QS_TIME_(); // timestamp 00749 QS_SIG_(e->sig); // the signal of this event 00750 QS_OBJ_(this); // this active object 00751 QS_U8_(QF_EVT_POOL_ID_(e)); // the pool Id of the event 00752 QS_U8_(QF_EVT_REF_CTR_(e)); // the ref count of the event 00753 QS_END_NOCRIT_() 00754 } 00755 QF_CRIT_EXIT_(); 00756 return e; 00757 } 00758 //............................................................................ 00759 uint32_t QF::getQueueMargin(uint8_t const prio) { 00760 Q_REQUIRE((prio <= static_cast<uint8_t>(QF_MAX_ACTIVE)) 00761 && (active_[prio] != static_cast<QActive *>(0))); 00762 00763 QF_CRIT_STAT_ 00764 QF_CRIT_ENTRY_(); 00765 uint32_t margin = static_cast<uint32_t>(active_[prio]->m_eQueue.m_nMin); 00766 QF_CRIT_EXIT_(); 00767 00768 return margin; 00769 } 00770 00771 QP_END_ 00772 00773 // "qa_lifo.cpp" ============================================================= 00774 /// \brief QActive::postLIFO() implementation. 00775 /// 00776 /// \note this source file is only included in the QF library when the native 00777 /// QF active object queue is used (instead of a message queue of an RTOS). 00778 00779 QP_BEGIN_ 00780 00781 //............................................................................ 00782 void QActive::postLIFO(QEvt const * const e) { 00783 QF_CRIT_STAT_ 00784 QF_CRIT_ENTRY_(); 00785 00786 QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_POST_LIFO, QS::aoObj_, this) 00787 QS_TIME_(); // timestamp 00788 QS_SIG_(e->sig); // the signal of this event 00789 QS_OBJ_(this); // this active object 00790 QS_U8_(QF_EVT_POOL_ID_(e)); // the pool Id of the event 00791 QS_U8_(QF_EVT_REF_CTR_(e)); // the ref count of the event 00792 QS_EQC_(m_eQueue.m_nFree); // number of free entries 00793 QS_EQC_(m_eQueue.m_nMin); // min number of free entries 00794 QS_END_NOCRIT_() 00795 00796 if (QF_EVT_POOL_ID_(e) != u8_0) { // is it a dynamic event? 00797 QF_EVT_REF_CTR_INC_(e); // increment the reference counter 00798 } 00799 00800 if (m_eQueue.m_frontEvt == null_evt) { // is the queue empty? 00801 m_eQueue.m_frontEvt = e; // deliver event directly 00802 QACTIVE_EQUEUE_SIGNAL_(this); // signal the event queue 00803 } 00804 else { // queue is not empty, leave event in the ring-buffer 00805 // queue must accept all posted events 00806 Q_ASSERT(m_eQueue.m_nFree != static_cast<QEQueueCtr>(0)); 00807 00808 ++m_eQueue.m_tail; 00809 if (m_eQueue.m_tail == m_eQueue.m_end) { // need to wrap the tail? 00810 m_eQueue.m_tail = static_cast<QEQueueCtr>(0); // wrap around 00811 } 00812 00813 QF_PTR_AT_(m_eQueue.m_ring, m_eQueue.m_tail) = m_eQueue.m_frontEvt; 00814 m_eQueue.m_frontEvt = e; // put event to front 00815 00816 --m_eQueue.m_nFree; // update number of free events 00817 if (m_eQueue.m_nMin > m_eQueue.m_nFree) { 00818 m_eQueue.m_nMin = m_eQueue.m_nFree; // update minimum so far 00819 } 00820 } 00821 QF_CRIT_EXIT_(); 00822 } 00823 00824 QP_END_ 00825 00826 // "qa_sub.cpp" ============================================================== 00827 /// \brief QActive::subscribe() implementation. 00828 00829 QP_BEGIN_ 00830 00831 //............................................................................ 00832 void QActive::subscribe(enum_t const sig) const { 00833 uint8_t p = m_prio; 00834 Q_REQUIRE((Q_USER_SIG <= sig) 00835 && (sig < QF_maxSignal_) 00836 && (u8_0 < p) && (p <= static_cast<uint8_t>(QF_MAX_ACTIVE)) 00837 && (QF::active_[p] == this)); 00838 00839 uint8_t const i = Q_ROM_BYTE(QF_div8Lkup[p]); 00840 00841 QF_CRIT_STAT_ 00842 QF_CRIT_ENTRY_(); 00843 00844 QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_SUBSCRIBE, QS::aoObj_, this) 00845 QS_TIME_(); // timestamp 00846 QS_SIG_(sig); // the signal of this event 00847 QS_OBJ_(this); // this active object 00848 QS_END_NOCRIT_() 00849 // set the priority bit 00850 QF_PTR_AT_(QF_subscrList_, sig).m_bits[i] |= Q_ROM_BYTE(QF_pwr2Lkup[p]); 00851 QF_CRIT_EXIT_(); 00852 } 00853 00854 QP_END_ 00855 00856 // "qa_usub.cpp" ============================================================= 00857 /// \brief QActive::unsubscribe() implementation. 00858 00859 QP_BEGIN_ 00860 00861 //............................................................................ 00862 void QActive::unsubscribe(enum_t const sig) const { 00863 uint8_t p = m_prio; 00864 Q_REQUIRE((Q_USER_SIG <= sig) 00865 && (sig < QF_maxSignal_) 00866 && (u8_0 < p) && (p <= static_cast<uint8_t>(QF_MAX_ACTIVE)) 00867 && (QF::active_[p] == this)); 00868 00869 uint8_t const i = Q_ROM_BYTE(QF_div8Lkup[p]); 00870 00871 QF_CRIT_STAT_ 00872 QF_CRIT_ENTRY_(); 00873 00874 QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_UNSUBSCRIBE, QS::aoObj_, this) 00875 QS_TIME_(); // timestamp 00876 QS_SIG_(sig); // the signal of this event 00877 QS_OBJ_(this); // this active object 00878 QS_END_NOCRIT_() 00879 // clear the priority bit 00880 QF_PTR_AT_(QF_subscrList_,sig).m_bits[i] &= Q_ROM_BYTE(QF_invPwr2Lkup[p]); 00881 QF_CRIT_EXIT_(); 00882 } 00883 00884 QP_END_ 00885 00886 // "qa_usuba.cpp" ============================================================ 00887 /// \brief QActive::unsubscribeAll() implementation. 00888 00889 QP_BEGIN_ 00890 00891 //............................................................................ 00892 void QActive::unsubscribeAll(void) const { 00893 uint8_t const p = m_prio; 00894 Q_REQUIRE((u8_0 < p) && (p <= static_cast<uint8_t>(QF_MAX_ACTIVE)) 00895 && (QF::active_[p] == this)); 00896 00897 uint8_t const i = Q_ROM_BYTE(QF_div8Lkup[p]); 00898 00899 enum_t sig; 00900 for (sig = Q_USER_SIG; sig < QF_maxSignal_; ++sig) { 00901 QF_CRIT_STAT_ 00902 QF_CRIT_ENTRY_(); 00903 if ((QF_PTR_AT_(QF_subscrList_, sig).m_bits[i] 00904 & Q_ROM_BYTE(QF_pwr2Lkup[p])) != u8_0) 00905 { 00906 00907 QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_UNSUBSCRIBE, QS::aoObj_, this) 00908 QS_TIME_(); // timestamp 00909 QS_SIG_(sig); // the signal of this event 00910 QS_OBJ_(this); // this active object 00911 QS_END_NOCRIT_() 00912 // clear the priority bit 00913 QF_PTR_AT_(QF_subscrList_, sig).m_bits[i] &= 00914 Q_ROM_BYTE(QF_invPwr2Lkup[p]); 00915 } 00916 QF_CRIT_EXIT_(); 00917 } 00918 } 00919 00920 QP_END_ 00921 00922 // "qeq_fifo.cpp" ============================================================ 00923 /// \brief QEQueue::postFIFO() implementation. 00924 00925 QP_BEGIN_ 00926 00927 //............................................................................ 00928 void QEQueue::postFIFO(QEvt const * const e) { 00929 QF_CRIT_STAT_ 00930 QF_CRIT_ENTRY_(); 00931 00932 QS_BEGIN_NOCRIT_(QS_QF_EQUEUE_POST_FIFO, QS::eqObj_, this) 00933 QS_TIME_(); // timestamp 00934 QS_SIG_(e->sig); // the signal of this event 00935 QS_OBJ_(this); // this queue object 00936 QS_U8_(QF_EVT_POOL_ID_(e)); // the pool Id of the event 00937 QS_U8_(QF_EVT_REF_CTR_(e)); // the ref count of the event 00938 QS_EQC_(m_nFree); // number of free entries 00939 QS_EQC_(m_nMin); // min number of free entries 00940 QS_END_NOCRIT_() 00941 00942 if (QF_EVT_POOL_ID_(e) != u8_0) { // is it a dynamic event? 00943 QF_EVT_REF_CTR_INC_(e); // increment the reference counter 00944 } 00945 00946 if (m_frontEvt == null_evt) { // is the queue empty? 00947 m_frontEvt = e; // deliver event directly 00948 } 00949 else { // queue is not empty, leave event in the ring-buffer 00950 // the queue must be able to accept the event (cannot overflow) 00951 Q_ASSERT(m_nFree != static_cast<QEQueueCtr>(0)); 00952 00953 QF_PTR_AT_(m_ring, m_head) = e; // insert event into the buffer (FIFO) 00954 if (m_head == static_cast<QEQueueCtr>(0)) { // need to wrap? 00955 m_head = m_end; // wrap around 00956 } 00957 --m_head; 00958 00959 --m_nFree; // update number of free events 00960 if (m_nMin > m_nFree) { 00961 m_nMin = m_nFree; // update minimum so far 00962 } 00963 } 00964 QF_CRIT_EXIT_(); 00965 } 00966 00967 QP_END_ 00968 00969 // "qeq_get.cpp" ============================================================= 00970 /// \brief QEQueue::get() implementation. 00971 00972 QP_BEGIN_ 00973 00974 //............................................................................ 00975 QEvt const *QEQueue::get(void) { 00976 QEvt const *e; 00977 QF_CRIT_STAT_ 00978 00979 QF_CRIT_ENTRY_(); 00980 if (m_frontEvt == null_evt) { // is the queue empty? 00981 e = null_evt; // no event available at this time 00982 } 00983 else { 00984 e = m_frontEvt; 00985 00986 if (m_nFree != m_end) { // any events in the the ring buffer? 00987 m_frontEvt = QF_PTR_AT_(m_ring, m_tail); // remove from the tail 00988 if (m_tail == static_cast<QEQueueCtr>(0)) { // need to wrap? 00989 m_tail = m_end; // wrap around 00990 } 00991 --m_tail; 00992 00993 ++m_nFree; // one more free event in the ring buffer 00994 00995 QS_BEGIN_NOCRIT_(QS_QF_EQUEUE_GET, QS::eqObj_, this) 00996 QS_TIME_(); // timestamp 00997 QS_SIG_(e->sig); // the signal of this event 00998 QS_OBJ_(this); // this queue object 00999 QS_U8_(QF_EVT_POOL_ID_(e)); // the pool Id of the event 01000 QS_U8_(QF_EVT_REF_CTR_(e)); // the ref count of the event 01001 QS_EQC_(m_nFree); // number of free entries 01002 QS_END_NOCRIT_() 01003 } 01004 else { 01005 m_frontEvt = null_evt; // the queue becomes empty 01006 01007 QS_BEGIN_NOCRIT_(QS_QF_EQUEUE_GET_LAST, QS::eqObj_, this) 01008 QS_TIME_(); // timestamp 01009 QS_SIG_(e->sig); // the signal of this event 01010 QS_OBJ_(this); // this queue object 01011 QS_U8_(QF_EVT_POOL_ID_(e)); // the pool Id of the event 01012 QS_U8_(QF_EVT_REF_CTR_(e)); // the ref count of the event 01013 QS_END_NOCRIT_() 01014 } 01015 } 01016 QF_CRIT_EXIT_(); 01017 return e; 01018 } 01019 01020 QP_END_ 01021 01022 // "qeq_init.cpp" ============================================================ 01023 /// \brief QEQueue::init() implementation. 01024 01025 QP_BEGIN_ 01026 01027 //............................................................................ 01028 void QEQueue::init(QEvt const *qSto[], QEQueueCtr const qLen) { 01029 m_frontEvt = null_evt; // no events in the queue 01030 m_ring = &qSto[0]; 01031 m_end = qLen; 01032 m_head = static_cast<QEQueueCtr>(0); 01033 m_tail = static_cast<QEQueueCtr>(0); 01034 m_nFree = qLen; 01035 m_nMin = qLen; 01036 01037 QS_CRIT_STAT_ 01038 QS_BEGIN_(QS_QF_EQUEUE_INIT, QS::eqObj_, this) 01039 QS_OBJ_(qSto); // this QEQueue object 01040 QS_EQC_(qLen); // the length of the queue 01041 QS_END_() 01042 } 01043 01044 QP_END_ 01045 01046 // "qeq_lifo.cpp" ============================================================ 01047 /// \brief QEQueue::postLIFO() implementation. 01048 01049 QP_BEGIN_ 01050 01051 //............................................................................ 01052 void QEQueue::postLIFO(QEvt const * const e) { 01053 QF_CRIT_STAT_ 01054 QF_CRIT_ENTRY_(); 01055 01056 QS_BEGIN_NOCRIT_(QS_QF_EQUEUE_POST_LIFO, QS::eqObj_, this) 01057 QS_TIME_(); // timestamp 01058 QS_SIG_(e->sig); // the signal of this event 01059 QS_OBJ_(this); // this queue object 01060 QS_U8_(QF_EVT_POOL_ID_(e)); // the pool Id of the event 01061 QS_U8_(QF_EVT_REF_CTR_(e)); // the ref count of the event 01062 QS_EQC_(m_nFree); // number of free entries 01063 QS_EQC_(m_nMin); // min number of free entries 01064 QS_END_NOCRIT_() 01065 01066 if (QF_EVT_POOL_ID_(e) != u8_0) { // is it a dynamic event? 01067 QF_EVT_REF_CTR_INC_(e); // increment the reference counter 01068 } 01069 01070 if (m_frontEvt != null_evt) { // is the queue not empty? 01071 // the queue must be able to accept the event (cannot overflow) 01072 Q_ASSERT(m_nFree != static_cast<QEQueueCtr>(0)); 01073 01074 ++m_tail; 01075 if (m_tail == m_end) { // need to wrap the tail? 01076 m_tail = static_cast<QEQueueCtr>(0); // wrap around 01077 } 01078 01079 QF_PTR_AT_(m_ring, m_tail) = m_frontEvt; // buffer the old front evt 01080 01081 --m_nFree; // update number of free events 01082 if (m_nMin > m_nFree) { 01083 m_nMin = m_nFree; // update minimum so far 01084 } 01085 } 01086 01087 m_frontEvt = e; // stick the new event to the front 01088 01089 QF_CRIT_EXIT_(); 01090 } 01091 01092 QP_END_ 01093 01094 // "qf_act.cpp" ============================================================== 01095 /// \brief QF::active_[], QF::getVersion(), and QF::add_()/QF::remove_() 01096 /// implementation. 01097 01098 QP_BEGIN_ 01099 01100 // public objects ------------------------------------------------------------ 01101 QActive *QF::active_[QF_MAX_ACTIVE + 1]; // to be used by QF ports only 01102 uint8_t QF_intLockNest_; // interrupt-lock nesting level 01103 01104 //............................................................................ 01105 char_t const Q_ROM * Q_ROM_VAR QF::getVersion(void) { 01106 uint8_t const u8_zero = static_cast<uint8_t>('0'); 01107 static char_t const Q_ROM Q_ROM_VAR version[] = { 01108 static_cast<char_t>(((QP_VERSION >> 12) & 0xFU) + u8_zero), 01109 static_cast<char_t>('.'), 01110 static_cast<char_t>(((QP_VERSION >> 8) & 0xFU) + u8_zero), 01111 static_cast<char_t>('.'), 01112 static_cast<char_t>(((QP_VERSION >> 4) & 0xFU) + u8_zero), 01113 static_cast<char_t>((QP_VERSION & 0xFU) + u8_zero), 01114 static_cast<char_t>('\0') 01115 }; 01116 return version; 01117 } 01118 //............................................................................ 01119 void QF::add_(QActive * const a) { 01120 uint8_t p = a->m_prio; 01121 01122 Q_REQUIRE((u8_0 < p) && (p <= static_cast<uint8_t>(QF_MAX_ACTIVE)) 01123 && (active_[p] == static_cast<QActive *>(0))); 01124 01125 QF_CRIT_STAT_ 01126 QF_CRIT_ENTRY_(); 01127 01128 active_[p] = a; // registger the active object at this priority 01129 01130 QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_ADD, QS::aoObj_, a) 01131 QS_TIME_(); // timestamp 01132 QS_OBJ_(a); // the active object 01133 QS_U8_(p); // the priority of the active object 01134 QS_END_NOCRIT_() 01135 01136 QF_CRIT_EXIT_(); 01137 } 01138 //............................................................................ 01139 void QF::remove_(QActive const * const a) { 01140 uint8_t p = a->m_prio; 01141 01142 Q_REQUIRE((u8_0 < p) && (p <= static_cast<uint8_t>(QF_MAX_ACTIVE)) 01143 && (active_[p] == a)); 01144 01145 QF_CRIT_STAT_ 01146 QF_CRIT_ENTRY_(); 01147 01148 active_[p] = static_cast<QActive *>(0); // free-up the priority level 01149 01150 QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_REMOVE, QS::aoObj_, a) 01151 QS_TIME_(); // timestamp 01152 QS_OBJ_(a); // the active object 01153 QS_U8_(p); // the priority of the active object 01154 QS_END_NOCRIT_() 01155 01156 QF_CRIT_EXIT_(); 01157 } 01158 01159 QP_END_ 01160 01161 01162 // "qf_gc.cpp" =============================================================== 01163 /// \brief QF::gc() implementation. 01164 01165 QP_BEGIN_ 01166 01167 //............................................................................ 01168 void QF::gc(QEvt const * const e) { 01169 if (QF_EVT_POOL_ID_(e) != u8_0) { // is it a dynamic event? 01170 QF_CRIT_STAT_ 01171 QF_CRIT_ENTRY_(); 01172 01173 if (QF_EVT_REF_CTR_(e) > u8_1) { // isn't this the last reference? 01174 QF_EVT_REF_CTR_DEC_(e); // decrement the ref counter 01175 01176 QS_BEGIN_NOCRIT_(QS_QF_GC_ATTEMPT, null_void, null_void) 01177 QS_TIME_(); // timestamp 01178 QS_SIG_(e->sig); // the signal of the event 01179 QS_U8_(QF_EVT_POOL_ID_(e)); // the pool Id of the event 01180 QS_U8_(QF_EVT_REF_CTR_(e)); // the ref count of the event 01181 QS_END_NOCRIT_() 01182 01183 QF_CRIT_EXIT_(); 01184 } 01185 else { // this is the last reference to this event, recycle it 01186 uint8_t idx = static_cast<uint8_t>(QF_EVT_POOL_ID_(e) - u8_1); 01187 01188 QS_BEGIN_NOCRIT_(QS_QF_GC, null_void, null_void) 01189 QS_TIME_(); // timestamp 01190 QS_SIG_(e->sig); // the signal of the event 01191 QS_U8_(QF_EVT_POOL_ID_(e)); // the pool Id of the event 01192 QS_U8_(QF_EVT_REF_CTR_(e)); // the ref count of the event 01193 QS_END_NOCRIT_() 01194 01195 QF_CRIT_EXIT_(); 01196 01197 Q_ASSERT(idx < QF_maxPool_); 01198 01199 #ifdef Q_EVT_VIRTUAL 01200 QF_EVT_CONST_CAST_(e)->~QEvt(); // xtor, cast 'const' away, 01201 // which is legitimate, because it's a pool event 01202 #endif 01203 // cast 'const' away, which is OK, because it's a pool event 01204 QF_EPOOL_PUT_(QF_pool_[idx], QF_EVT_CONST_CAST_(e)); 01205 } 01206 } 01207 } 01208 01209 QP_END_ 01210 01211 // "qf_log2.cpp" ============================================================= 01212 /// \brief QF_log2Lkup[] implementation. 01213 01214 QP_BEGIN_ 01215 01216 // Global objects ------------------------------------------------------------ 01217 uint8_t const Q_ROM Q_ROM_VAR QF_log2Lkup[256] = { 01218 static_cast<uint8_t>(0), 01219 static_cast<uint8_t>(1), 01220 static_cast<uint8_t>(2), static_cast<uint8_t>(2), 01221 static_cast<uint8_t>(3), static_cast<uint8_t>(3), static_cast<uint8_t>(3), 01222 static_cast<uint8_t>(3), 01223 static_cast<uint8_t>(4), static_cast<uint8_t>(4), static_cast<uint8_t>(4), 01224 static_cast<uint8_t>(4), static_cast<uint8_t>(4), static_cast<uint8_t>(4), 01225 static_cast<uint8_t>(4), static_cast<uint8_t>(4), 01226 static_cast<uint8_t>(5), static_cast<uint8_t>(5), static_cast<uint8_t>(5), 01227 static_cast<uint8_t>(5), static_cast<uint8_t>(5), static_cast<uint8_t>(5), 01228 static_cast<uint8_t>(5), static_cast<uint8_t>(5), static_cast<uint8_t>(5), 01229 static_cast<uint8_t>(5), static_cast<uint8_t>(5), static_cast<uint8_t>(5), 01230 static_cast<uint8_t>(5), static_cast<uint8_t>(5), static_cast<uint8_t>(5), 01231 static_cast<uint8_t>(5), 01232 static_cast<uint8_t>(6), static_cast<uint8_t>(6), static_cast<uint8_t>(6), 01233 static_cast<uint8_t>(6), static_cast<uint8_t>(6), static_cast<uint8_t>(6), 01234 static_cast<uint8_t>(6), static_cast<uint8_t>(6), static_cast<uint8_t>(6), 01235 static_cast<uint8_t>(6), static_cast<uint8_t>(6), static_cast<uint8_t>(6), 01236 static_cast<uint8_t>(6), static_cast<uint8_t>(6), static_cast<uint8_t>(6), 01237 static_cast<uint8_t>(6), static_cast<uint8_t>(6), static_cast<uint8_t>(6), 01238 static_cast<uint8_t>(6), static_cast<uint8_t>(6), static_cast<uint8_t>(6), 01239 static_cast<uint8_t>(6), static_cast<uint8_t>(6), static_cast<uint8_t>(6), 01240 static_cast<uint8_t>(6), static_cast<uint8_t>(6), static_cast<uint8_t>(6), 01241 static_cast<uint8_t>(6), static_cast<uint8_t>(6), static_cast<uint8_t>(6), 01242 static_cast<uint8_t>(6), static_cast<uint8_t>(6), 01243 static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), 01244 static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), 01245 static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), 01246 static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), 01247 static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), 01248 static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), 01249 static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), 01250 static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), 01251 static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), 01252 static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), 01253 static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), 01254 static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), 01255 static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), 01256 static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), 01257 static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), 01258 static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), 01259 static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), 01260 static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), 01261 static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), 01262 static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), 01263 static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), 01264 static_cast<uint8_t>(7), 01265 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01266 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01267 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01268 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01269 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01270 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01271 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01272 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01273 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01274 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01275 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01276 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01277 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01278 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01279 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01280 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01281 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01282 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01283 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01284 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01285 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01286 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01287 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01288 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01289 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01290 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01291 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01292 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01293 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01294 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01295 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01296 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01297 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01298 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01299 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01300 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01301 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01302 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01303 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01304 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01305 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01306 static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), 01307 static_cast<uint8_t>(8), static_cast<uint8_t>(8) 01308 }; 01309 01310 QP_END_ 01311 01312 // "qf_new.cpp" ============================================================== 01313 /// \brief QF::new_() implementation. 01314 01315 QP_BEGIN_ 01316 01317 //............................................................................ 01318 QEvt *QF::new_(QEvtSize const evtSize, enum_t const sig) { 01319 // find the pool id that fits the requested event size ... 01320 uint8_t idx = u8_0; 01321 while (evtSize 01322 > static_cast<QEvtSize>(QF_EPOOL_EVENT_SIZE_(QF_pool_[idx]))) 01323 { 01324 ++idx; 01325 Q_ASSERT(idx < QF_maxPool_); // cannot run out of registered pools 01326 } 01327 01328 QS_CRIT_STAT_ 01329 QS_BEGIN_(QS_QF_NEW, null_void, null_void) 01330 QS_TIME_(); // timestamp 01331 QS_EVS_(evtSize); // the size of the event 01332 QS_SIG_(static_cast<QSignal>(sig)); // the signal of the event 01333 QS_END_() 01334 01335 QEvt *e; 01336 QF_EPOOL_GET_(QF_pool_[idx], e); 01337 Q_ASSERT(e != static_cast<QEvt *>(0));// pool must not run out of events 01338 01339 e->sig = static_cast<QSignal>(sig); // set signal for this event 01340 e->poolId_ = static_cast<uint8_t>(idx + u8_1); // store pool ID in the evt 01341 e->refCtr_ = u8_0; // set the reference counter to 0 01342 01343 return e; 01344 } 01345 01346 QP_END_ 01347 01348 // "qf_pool.cpp" ============================================================= 01349 /// \brief QF_pool_[] and QF_maxPool_ definition, QF::poolInit() 01350 /// implementation. 01351 01352 QP_BEGIN_ 01353 01354 // Package-scope objects ----------------------------------------------------- 01355 QF_EPOOL_TYPE_ QF_pool_[QF_MAX_EPOOL]; // allocate the event pools 01356 uint8_t QF_maxPool_; // number of initialized event pools 01357 01358 //............................................................................ 01359 void QF::poolInit(void * const poolSto, 01360 uint32_t const poolSize, uint32_t const evtSize) 01361 { 01362 // cannot exceed the number of available memory pools 01363 Q_REQUIRE(QF_maxPool_ < static_cast<uint8_t>(Q_DIM(QF_pool_))); 01364 // please initialize event pools in ascending order of evtSize: 01365 Q_REQUIRE((QF_maxPool_ == u8_0) 01366 || (QF_EPOOL_EVENT_SIZE_(QF_pool_[QF_maxPool_ - u8_1]) 01367 < evtSize)); 01368 QF_EPOOL_INIT_(QF_pool_[QF_maxPool_], poolSto, poolSize, evtSize); 01369 ++QF_maxPool_; // one more pool 01370 } 01371 01372 QP_END_ 01373 01374 01375 // "qf_psini.cpp" ============================================================ 01376 /// \brief QF_subscrList_ and QF_maxSignal_ definition, QF::psInit() 01377 /// implementation. 01378 01379 QP_BEGIN_ 01380 01381 // Package-scope objects ----------------------------------------------------- 01382 QSubscrList *QF_subscrList_; 01383 enum_t QF_maxSignal_; 01384 01385 //............................................................................ 01386 void QF::psInit(QSubscrList * const subscrSto, uint32_t const maxSignal) { 01387 QF_subscrList_ = subscrSto; 01388 QF_maxSignal_ = static_cast<enum_t>(maxSignal); 01389 } 01390 01391 QP_END_ 01392 01393 // "qf_pspub.cpp" ============================================================ 01394 /// \brief QF::publish() implementation. 01395 01396 QP_BEGIN_ 01397 01398 //............................................................................ 01399 #ifndef Q_SPY 01400 void QF::publish(QEvt const * const e) { 01401 #else 01402 void QF::publish(QEvt const * const e, void const * const sender) { 01403 #endif 01404 // make sure that the published signal is within the configured range 01405 Q_REQUIRE(static_cast<enum_t>(e->sig) < QF_maxSignal_); 01406 01407 QF_CRIT_STAT_ 01408 QF_CRIT_ENTRY_(); 01409 01410 QS_BEGIN_NOCRIT_(QS_QF_PUBLISH, null_void, null_void) 01411 QS_TIME_(); // the timestamp 01412 QS_OBJ_(sender); // the sender object 01413 QS_SIG_(e->sig); // the signal of the event 01414 QS_U8_(QF_EVT_POOL_ID_(e)); // the pool Id of the event 01415 QS_U8_(QF_EVT_REF_CTR_(e)); // the ref count of the event 01416 QS_END_NOCRIT_() 01417 01418 if (QF_EVT_POOL_ID_(e) != u8_0) { // is it a dynamic event? 01419 QF_EVT_REF_CTR_INC_(e); // increment the reference counter, NOTE01 01420 } 01421 QF_CRIT_EXIT_(); 01422 01423 #if (QF_MAX_ACTIVE <= 8) 01424 uint8_t tmp = QF_PTR_AT_(QF_subscrList_, e->sig).m_bits[0]; 01425 while (tmp != u8_0) { 01426 uint8_t p = Q_ROM_BYTE(QF_log2Lkup[tmp]); 01427 tmp &= Q_ROM_BYTE(QF_invPwr2Lkup[p]); // clear the subscriber bit 01428 Q_ASSERT(active_[p] != static_cast<QActive *>(0));//must be registered 01429 01430 // POST() asserts internally if the queue overflows 01431 active_[p]->POST(e, sender); 01432 } 01433 #else 01434 // number of bytes in the list 01435 uint8_t i = QF_SUBSCR_LIST_SIZE; 01436 do { // go through all bytes in the subsciption list 01437 --i; 01438 uint8_t tmp = QF_PTR_AT_(QF_subscrList_, e->sig).m_bits[i]; 01439 while (tmp != u8_0) { 01440 uint8_t p = Q_ROM_BYTE(QF_log2Lkup[tmp]); 01441 tmp &= Q_ROM_BYTE(QF_invPwr2Lkup[p]); // clear the subscriber bit 01442 // adjust the priority 01443 p = static_cast<uint8_t>(p + static_cast<uint8_t>(i << 3)); 01444 Q_ASSERT(active_[p] != static_cast<QActive *>(0)); // registered 01445 01446 // POST() asserts internally if the queue overflows 01447 active_[p]->POST(e, sender); 01448 } 01449 } while (i != u8_0); 01450 #endif 01451 01452 gc(e); // run the garbage collector, see NOTE01 01453 } 01454 01455 QP_END_ 01456 01457 01458 // "qf_pwr2.cpp" ============================================================= 01459 /// \brief QF_pwr2Lkup[], QF_invPwr2Lkup[], and QF_div8Lkup[] definitions. 01460 01461 QP_BEGIN_ 01462 01463 // Global objects ------------------------------------------------------------ 01464 uint8_t const Q_ROM Q_ROM_VAR QF_pwr2Lkup[65] = { 01465 static_cast<uint8_t>(0x00), // unused location 01466 static_cast<uint8_t>(0x01), static_cast<uint8_t>(0x02), 01467 static_cast<uint8_t>(0x04), static_cast<uint8_t>(0x08), 01468 static_cast<uint8_t>(0x10), static_cast<uint8_t>(0x20), 01469 static_cast<uint8_t>(0x40), static_cast<uint8_t>(0x80), 01470 static_cast<uint8_t>(0x01), static_cast<uint8_t>(0x02), 01471 static_cast<uint8_t>(0x04), static_cast<uint8_t>(0x08), 01472 static_cast<uint8_t>(0x10), static_cast<uint8_t>(0x20), 01473 static_cast<uint8_t>(0x40), static_cast<uint8_t>(0x80), 01474 static_cast<uint8_t>(0x01), static_cast<uint8_t>(0x02), 01475 static_cast<uint8_t>(0x04), static_cast<uint8_t>(0x08), 01476 static_cast<uint8_t>(0x10), static_cast<uint8_t>(0x20), 01477 static_cast<uint8_t>(0x40), static_cast<uint8_t>(0x80), 01478 static_cast<uint8_t>(0x01), static_cast<uint8_t>(0x02), 01479 static_cast<uint8_t>(0x04), static_cast<uint8_t>(0x08), 01480 static_cast<uint8_t>(0x10), static_cast<uint8_t>(0x20), 01481 static_cast<uint8_t>(0x40), static_cast<uint8_t>(0x80), 01482 static_cast<uint8_t>(0x01), static_cast<uint8_t>(0x02), 01483 static_cast<uint8_t>(0x04), static_cast<uint8_t>(0x08), 01484 static_cast<uint8_t>(0x10), static_cast<uint8_t>(0x20), 01485 static_cast<uint8_t>(0x40), static_cast<uint8_t>(0x80), 01486 static_cast<uint8_t>(0x01), static_cast<uint8_t>(0x02), 01487 static_cast<uint8_t>(0x04), static_cast<uint8_t>(0x08), 01488 static_cast<uint8_t>(0x10), static_cast<uint8_t>(0x20), 01489 static_cast<uint8_t>(0x40), static_cast<uint8_t>(0x80), 01490 static_cast<uint8_t>(0x01), static_cast<uint8_t>(0x02), 01491 static_cast<uint8_t>(0x04), static_cast<uint8_t>(0x08), 01492 static_cast<uint8_t>(0x10), static_cast<uint8_t>(0x20), 01493 static_cast<uint8_t>(0x40), static_cast<uint8_t>(0x80), 01494 static_cast<uint8_t>(0x01), static_cast<uint8_t>(0x02), 01495 static_cast<uint8_t>(0x04), static_cast<uint8_t>(0x08), 01496 static_cast<uint8_t>(0x10), static_cast<uint8_t>(0x20), 01497 static_cast<uint8_t>(0x40), static_cast<uint8_t>(0x80) 01498 }; 01499 01500 uint8_t const Q_ROM Q_ROM_VAR QF_invPwr2Lkup[65] = { 01501 static_cast<uint8_t>(0xFF), // unused location 01502 static_cast<uint8_t>(0xFE), static_cast<uint8_t>(0xFD), 01503 static_cast<uint8_t>(0xFB), static_cast<uint8_t>(0xF7), 01504 static_cast<uint8_t>(0xEF), static_cast<uint8_t>(0xDF), 01505 static_cast<uint8_t>(0xBF), static_cast<uint8_t>(0x7F), 01506 static_cast<uint8_t>(0xFE), static_cast<uint8_t>(0xFD), 01507 static_cast<uint8_t>(0xFB), static_cast<uint8_t>(0xF7), 01508 static_cast<uint8_t>(0xEF), static_cast<uint8_t>(0xDF), 01509 static_cast<uint8_t>(0xBF), static_cast<uint8_t>(0x7F), 01510 static_cast<uint8_t>(0xFE), static_cast<uint8_t>(0xFD), 01511 static_cast<uint8_t>(0xFB), static_cast<uint8_t>(0xF7), 01512 static_cast<uint8_t>(0xEF), static_cast<uint8_t>(0xDF), 01513 static_cast<uint8_t>(0xBF), static_cast<uint8_t>(0x7F), 01514 static_cast<uint8_t>(0xFE), static_cast<uint8_t>(0xFD), 01515 static_cast<uint8_t>(0xFB), static_cast<uint8_t>(0xF7), 01516 static_cast<uint8_t>(0xEF), static_cast<uint8_t>(0xDF), 01517 static_cast<uint8_t>(0xBF), static_cast<uint8_t>(0x7F), 01518 static_cast<uint8_t>(0xFE), static_cast<uint8_t>(0xFD), 01519 static_cast<uint8_t>(0xFB), static_cast<uint8_t>(0xF7), 01520 static_cast<uint8_t>(0xEF), static_cast<uint8_t>(0xDF), 01521 static_cast<uint8_t>(0xBF), static_cast<uint8_t>(0x7F), 01522 static_cast<uint8_t>(0xFE), static_cast<uint8_t>(0xFD), 01523 static_cast<uint8_t>(0xFB), static_cast<uint8_t>(0xF7), 01524 static_cast<uint8_t>(0xEF), static_cast<uint8_t>(0xDF), 01525 static_cast<uint8_t>(0xBF), static_cast<uint8_t>(0x7F), 01526 static_cast<uint8_t>(0xFE), static_cast<uint8_t>(0xFD), 01527 static_cast<uint8_t>(0xFB), static_cast<uint8_t>(0xF7), 01528 static_cast<uint8_t>(0xEF), static_cast<uint8_t>(0xDF), 01529 static_cast<uint8_t>(0xBF), static_cast<uint8_t>(0x7F), 01530 static_cast<uint8_t>(0xFE), static_cast<uint8_t>(0xFD), 01531 static_cast<uint8_t>(0xFB), static_cast<uint8_t>(0xF7), 01532 static_cast<uint8_t>(0xEF), static_cast<uint8_t>(0xDF), 01533 static_cast<uint8_t>(0xBF), static_cast<uint8_t>(0x7F) 01534 }; 01535 01536 uint8_t const Q_ROM Q_ROM_VAR QF_div8Lkup[65] = { 01537 static_cast<uint8_t>(0), // unused location 01538 static_cast<uint8_t>(0), static_cast<uint8_t>(0), static_cast<uint8_t>(0), 01539 static_cast<uint8_t>(0), static_cast<uint8_t>(0), static_cast<uint8_t>(0), 01540 static_cast<uint8_t>(0), static_cast<uint8_t>(0), 01541 static_cast<uint8_t>(1), static_cast<uint8_t>(1), static_cast<uint8_t>(1), 01542 static_cast<uint8_t>(1), static_cast<uint8_t>(1), static_cast<uint8_t>(1), 01543 static_cast<uint8_t>(1), static_cast<uint8_t>(1), 01544 static_cast<uint8_t>(2), static_cast<uint8_t>(2), static_cast<uint8_t>(2), 01545 static_cast<uint8_t>(2), static_cast<uint8_t>(2), static_cast<uint8_t>(2), 01546 static_cast<uint8_t>(2), static_cast<uint8_t>(2), 01547 static_cast<uint8_t>(3), static_cast<uint8_t>(3), static_cast<uint8_t>(3), 01548 static_cast<uint8_t>(3), static_cast<uint8_t>(3), static_cast<uint8_t>(3), 01549 static_cast<uint8_t>(3), static_cast<uint8_t>(3), 01550 static_cast<uint8_t>(4), static_cast<uint8_t>(4), static_cast<uint8_t>(4), 01551 static_cast<uint8_t>(4), static_cast<uint8_t>(4), static_cast<uint8_t>(4), 01552 static_cast<uint8_t>(4), static_cast<uint8_t>(4), 01553 static_cast<uint8_t>(5), static_cast<uint8_t>(5), static_cast<uint8_t>(5), 01554 static_cast<uint8_t>(5), static_cast<uint8_t>(5), static_cast<uint8_t>(5), 01555 static_cast<uint8_t>(5), static_cast<uint8_t>(5), 01556 static_cast<uint8_t>(6), static_cast<uint8_t>(6), static_cast<uint8_t>(6), 01557 static_cast<uint8_t>(6), static_cast<uint8_t>(6), static_cast<uint8_t>(6), 01558 static_cast<uint8_t>(6), static_cast<uint8_t>(6), 01559 static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), 01560 static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), 01561 static_cast<uint8_t>(7), static_cast<uint8_t>(7) 01562 }; 01563 01564 QP_END_ 01565 01566 // "qf_tick.cpp" ============================================================= 01567 /// \brief QF::tick() implementation. 01568 01569 QP_BEGIN_ 01570 01571 //............................................................................ 01572 #ifndef Q_SPY 01573 void QF::tick(void) { // see NOTE01 01574 #else 01575 void QF::tick(void const * const sender) { 01576 #endif 01577 01578 QF_CRIT_STAT_ 01579 QF_CRIT_ENTRY_(); 01580 01581 QS_BEGIN_NOCRIT_(QS_QF_TICK, null_void, null_void) 01582 QS_TEC_(static_cast<QTimeEvtCtr>(++QS::tickCtr_)); // the tick counter 01583 QS_END_NOCRIT_() 01584 01585 QTimeEvt *prev = null_tevt; 01586 for (QTimeEvt *t = QF_timeEvtListHead_; t != null_tevt; t = t->m_next) { 01587 if (t->m_ctr == tc_0) { // time evt. scheduled for removal? 01588 if (t == QF_timeEvtListHead_) { 01589 QF_timeEvtListHead_ = t->m_next; 01590 } 01591 else { 01592 Q_ASSERT(prev != null_tevt); 01593 prev->m_next = t->m_next; 01594 } 01595 QF_EVT_REF_CTR_DEC_(t); // mark as not linked 01596 } 01597 else { 01598 --t->m_ctr; 01599 if (t->m_ctr == tc_0) { // about to expire? 01600 if (t->m_interval != tc_0) { // periodic time event? 01601 t->m_ctr = t->m_interval; // rearm the time evt 01602 } 01603 else { 01604 QS_BEGIN_NOCRIT_(QS_QF_TIMEEVT_AUTO_DISARM, QS::teObj_, t) 01605 QS_OBJ_(t); // this time event object 01606 QS_OBJ_(t->m_act); // the active object 01607 QS_END_NOCRIT_() 01608 } 01609 01610 QS_BEGIN_NOCRIT_(QS_QF_TIMEEVT_POST, QS::teObj_, t) 01611 QS_TIME_(); // timestamp 01612 QS_OBJ_(t); // the time event object 01613 QS_SIG_(t->sig); // the signal of this time event 01614 QS_OBJ_(t->m_act); // the active object 01615 QS_END_NOCRIT_() 01616 01617 QF_CRIT_EXIT_(); // leave crit. section before posting 01618 // POST() asserts internally if the queue overflows 01619 t->m_act->POST(t, sender); 01620 QF_CRIT_ENTRY_(); // re-enter crit. section to continue 01621 01622 if (t->m_ctr == tc_0) { // still marked to expire? 01623 if (t == QF_timeEvtListHead_) { 01624 QF_timeEvtListHead_ = t->m_next; 01625 } 01626 else { 01627 Q_ASSERT(prev != null_tevt); 01628 prev->m_next = t->m_next; 01629 } 01630 QF_EVT_REF_CTR_DEC_(t); // mark as removed 01631 } 01632 else { 01633 prev = t; 01634 } 01635 } 01636 else { 01637 prev = t; 01638 } 01639 } 01640 } 01641 QF_CRIT_EXIT_(); 01642 } 01643 01644 QP_END_ 01645 01646 // "qmp_get.cpp" ============================================================= 01647 /// \brief QMPool::get() and QF::getPoolMargin() implementation. 01648 01649 QP_BEGIN_ 01650 01651 //............................................................................ 01652 void *QMPool::get(void) { 01653 QF_CRIT_STAT_ 01654 QF_CRIT_ENTRY_(); 01655 01656 QFreeBlock *fb = static_cast<QFreeBlock *>(m_free); // free block or NULL 01657 if (fb != static_cast<QFreeBlock *>(0)) { // free block available? 01658 m_free = fb->m_next; // adjust list head to the next free block 01659 01660 Q_ASSERT(m_nFree > static_cast<QMPoolCtr>(0)); // at least one free 01661 --m_nFree; // one free block less 01662 if (m_nMin > m_nFree) { 01663 m_nMin = m_nFree; // remember the minimum so far 01664 } 01665 } 01666 01667 QS_BEGIN_NOCRIT_(QS_QF_MPOOL_GET, QS::mpObj_, m_start) 01668 QS_TIME_(); // timestamp 01669 QS_OBJ_(m_start); // the memory managed by this pool 01670 QS_MPC_(m_nFree); // the number of free blocks in the pool 01671 QS_MPC_(m_nMin); // the mninimum number of free blocks in the pool 01672 QS_END_NOCRIT_() 01673 01674 QF_CRIT_EXIT_(); 01675 return fb; // return the block or NULL pointer to the caller 01676 } 01677 //............................................................................ 01678 uint32_t QF::getPoolMargin(uint8_t const poolId) { 01679 Q_REQUIRE((u8_1 <= poolId) && (poolId <= QF_maxPool_)); 01680 01681 QF_CRIT_STAT_ 01682 QF_CRIT_ENTRY_(); 01683 uint32_t margin = static_cast<uint32_t>(QF_pool_[poolId - u8_1].m_nMin); 01684 QF_CRIT_EXIT_(); 01685 01686 return margin; 01687 } 01688 01689 QP_END_ 01690 01691 // "qmp_init.cpp" ============================================================ 01692 /// \brief QMPool::init() implementation. 01693 01694 QP_BEGIN_ 01695 01696 //............................................................................ 01697 void QMPool::init(void * const poolSto, uint32_t const poolSize, 01698 QMPoolSize const blockSize) 01699 { 01700 // The memory block must be valid 01701 // and the poolSize must fit at least one free block 01702 // and the blockSize must not be too close to the top of the dynamic range 01703 Q_REQUIRE((poolSto != null_void) 01704 && (poolSize >= static_cast<uint32_t>(sizeof(QFreeBlock))) 01705 && ((blockSize + static_cast<QMPoolSize>(sizeof(QFreeBlock))) 01706 > blockSize)); 01707 01708 m_free = poolSto; 01709 01710 // round up the blockSize to fit an integer number of pointers 01711 m_blockSize = static_cast<QMPoolSize>(sizeof(QFreeBlock));//start with one 01712 uint32_t nblocks = static_cast<uint32_t>(1);//# free blocks in a mem block 01713 while (m_blockSize < blockSize) { 01714 m_blockSize += static_cast<QMPoolSize>(sizeof(QFreeBlock)); 01715 ++nblocks; 01716 } 01717 01718 // the whole pool buffer must fit at least one rounded-up block 01719 Q_ASSERT(poolSize >= static_cast<uint32_t>(m_blockSize)); 01720 01721 // chain all blocks together in a free-list... 01722 // don't chain last block 01723 uint32_t availSize = poolSize - static_cast<uint32_t>(m_blockSize); 01724 m_nTot = static_cast<QMPoolCtr>(1); // one (the last) block in the pool 01725 //start at the head of the free list 01726 QFreeBlock *fb = static_cast<QFreeBlock *>(m_free); 01727 while (availSize >= static_cast<uint32_t>(m_blockSize)) { 01728 fb->m_next = &QF_PTR_AT_(fb, nblocks); // setup the next link 01729 fb = fb->m_next; // advance to next block 01730 availSize -= static_cast<uint32_t>(m_blockSize);// less available size 01731 ++m_nTot; // increment the number of blocks so far 01732 } 01733 01734 fb->m_next = static_cast<QFreeBlock *>(0); // the last link points to NULL 01735 m_nFree = m_nTot; // all blocks are free 01736 m_nMin = m_nTot; // the minimum number of free blocks 01737 m_start = poolSto; // the original start this pool buffer 01738 m_end = fb; // the last block in this pool 01739 01740 QS_CRIT_STAT_ 01741 QS_BEGIN_(QS_QF_MPOOL_INIT, QS::mpObj_, m_start) 01742 QS_OBJ_(m_start); // the memory managed by this pool 01743 QS_MPC_(m_nTot); // the total number of blocks 01744 QS_END_() 01745 } 01746 01747 QP_END_ 01748 01749 // "qmp_put.cpp" ============================================================= 01750 /// \brief QMPool::put() implementation. 01751 01752 QP_BEGIN_ 01753 01754 // This macro is specifically and exclusively used for checking the range 01755 // of a block pointer returned to the pool. Such a check must rely on the 01756 // pointer arithmetic not compliant with the MISRA-C++:2008 rules ??? and 01757 // ???. Defining a specific macro for this purpose allows to selectively 01758 // disable the warnings for this particular case. 01759 // 01760 #define QF_PTR_RANGE_(x_, min_, max_) (((min_) <= (x_)) && ((x_) <= (max_))) 01761 01762 //............................................................................ 01763 void QMPool::put(void * const b) { 01764 01765 Q_REQUIRE(m_nFree < m_nTot); // adding one free so, # free < total 01766 Q_REQUIRE(QF_PTR_RANGE_(b, m_start, m_end)); // b must be in range 01767 01768 QF_CRIT_STAT_ 01769 QF_CRIT_ENTRY_(); 01770 01771 // link into the free list 01772 (static_cast<QFreeBlock*>(b))->m_next = static_cast<QFreeBlock *>(m_free); 01773 m_free = b; // set as new head of the free list 01774 ++m_nFree; // one more free block in this pool 01775 01776 QS_BEGIN_NOCRIT_(QS_QF_MPOOL_PUT, QS::mpObj_, m_start) 01777 QS_TIME_(); // timestamp 01778 QS_OBJ_(m_start); // the memory managed by this pool 01779 QS_MPC_(m_nFree); // the number of free blocks in the pool 01780 QS_END_NOCRIT_() 01781 01782 QF_CRIT_EXIT_(); 01783 } 01784 01785 QP_END_ 01786 01787 01788 // "qte_arm.cpp" ============================================================= 01789 /// \brief QF_timeEvtListHead_ definition and QTimeEvt::arm_() implementation. 01790 01791 QP_BEGIN_ 01792 01793 // Package-scope objects ----------------------------------------------------- 01794 QTimeEvt *QF_timeEvtListHead_; // head of linked list of time events 01795 01796 //............................................................................ 01797 bool QF::noTimeEvtsActive(void) { 01798 return QF_timeEvtListHead_ == null_tevt; 01799 } 01800 //............................................................................ 01801 void QTimeEvt::arm_(QActive * const act, QTimeEvtCtr const nTicks) { 01802 Q_REQUIRE((nTicks > tc_0) /* cannot arm with 0 ticks */ 01803 && (act != null_act) /* Active object must be provided */ 01804 && (m_ctr == tc_0) /* must be disarmed */ 01805 && (static_cast<enum_t>(sig) >= Q_USER_SIG)); // valid signal 01806 QF_CRIT_STAT_ 01807 QF_CRIT_ENTRY_(); 01808 m_ctr = nTicks; 01809 m_act = act; 01810 if (refCtr_ == u8_0) { // not linked? 01811 m_next = QF_timeEvtListHead_; 01812 QF_timeEvtListHead_ = this; 01813 QF_EVT_REF_CTR_INC_(this); // mark as linked 01814 } 01815 01816 QS_BEGIN_NOCRIT_(QS_QF_TIMEEVT_ARM, QS::teObj_, this) 01817 QS_TIME_(); // timestamp 01818 QS_OBJ_(this); // this time event object 01819 QS_OBJ_(act); // the active object 01820 QS_TEC_(nTicks); // the number of ticks 01821 QS_TEC_(m_interval); // the interval 01822 QS_END_NOCRIT_() 01823 01824 QF_CRIT_EXIT_(); 01825 } 01826 01827 QP_END_ 01828 01829 01830 // "qte_ctor.cpp" ============================================================ 01831 /// \brief QTimeEvt::QTimeEvt() implementation. 01832 QP_BEGIN_ 01833 01834 //............................................................................ 01835 QTimeEvt::QTimeEvt(enum_t const s) 01836 : 01837 #ifdef Q_EVT_CTOR 01838 QEvt(static_cast<QSignal>(s)), 01839 #endif 01840 m_next(null_tevt), 01841 m_act(null_act), 01842 m_ctr(tc_0), 01843 m_interval(tc_0) 01844 { 01845 Q_REQUIRE(s >= Q_USER_SIG); // signal must be valid 01846 #ifndef Q_EVT_CTOR 01847 sig = static_cast<QSignal>(s); 01848 #endif 01849 // time event must be static, see NOTE01 01850 poolId_ = u8_0; // not from any event pool 01851 refCtr_ = u8_0; // not linked 01852 } 01853 01854 QP_END_ 01855 01856 01857 // "qte_ctr.cpp" ============================================================= 01858 /// \brief QTimeEvt::ctr() implementation. 01859 01860 QP_BEGIN_ 01861 01862 //............................................................................ 01863 QTimeEvtCtr QTimeEvt::ctr(void) const { 01864 QF_CRIT_STAT_ 01865 01866 QF_CRIT_ENTRY_(); 01867 QTimeEvtCtr ret = m_ctr; 01868 01869 QS_BEGIN_NOCRIT_(QS_QF_TIMEEVT_CTR, QS::teObj_, this) 01870 QS_TIME_(); // timestamp 01871 QS_OBJ_(this); // this time event object 01872 QS_OBJ_(m_act); // the active object 01873 QS_TEC_(ret); // the current counter 01874 QS_TEC_(m_interval); // the interval 01875 QS_END_NOCRIT_() 01876 01877 QF_CRIT_EXIT_(); 01878 return ret; 01879 } 01880 01881 QP_END_ 01882 01883 // "qte_darm.cpp" ============================================================ 01884 /// \brief QTimeEvt::disarm() implementation. 01885 01886 QP_BEGIN_ 01887 01888 //............................................................................ 01889 // NOTE: disarm a time evt (no harm in disarming an already disarmed time evt) 01890 bool QTimeEvt::disarm(void) { 01891 QF_CRIT_STAT_ 01892 QF_CRIT_ENTRY_(); 01893 bool wasArmed; 01894 if (m_ctr != tc_0) { // is the time event actually armed? 01895 wasArmed = true; 01896 01897 QS_BEGIN_NOCRIT_(QS_QF_TIMEEVT_DISARM, QS::teObj_, this) 01898 QS_TIME_(); // timestamp 01899 QS_OBJ_(this); // this time event object 01900 QS_OBJ_(m_act); // the active object 01901 QS_TEC_(m_ctr); // the number of ticks 01902 QS_TEC_(m_interval); // the interval 01903 QS_END_NOCRIT_() 01904 01905 m_ctr = tc_0; // schedule removal from the list 01906 } 01907 else { // the time event was not armed 01908 wasArmed = false; 01909 01910 QS_BEGIN_NOCRIT_(QS_QF_TIMEEVT_DISARM_ATTEMPT, QS::teObj_, this) 01911 QS_TIME_(); // timestamp 01912 QS_OBJ_(this); // this time event object 01913 QS_OBJ_(m_act); // the active object 01914 QS_END_NOCRIT_() 01915 } 01916 QF_CRIT_EXIT_(); 01917 return wasArmed; 01918 } 01919 01920 QP_END_ 01921 01922 01923 // "qte_rarm.cpp" ============================================================ 01924 /// \brief QTimeEvt::rearm() implementation. 01925 01926 QP_BEGIN_ 01927 01928 //............................................................................ 01929 bool QTimeEvt::rearm(QTimeEvtCtr const nTicks) { 01930 Q_REQUIRE((nTicks > tc_0) /* cannot rearm with 0 ticks */ 01931 && (m_act != null_act) /* active object must be valid */ 01932 && (static_cast<enum_t>(sig) >= Q_USER_SIG)); // valid signal 01933 01934 QF_CRIT_STAT_ 01935 QF_CRIT_ENTRY_(); 01936 01937 bool isArmed; 01938 if (m_ctr == tc_0) { // is this time event disarmed? 01939 isArmed = false; 01940 m_next = QF_timeEvtListHead_; 01941 if (QF_timeEvtListHead_ != null_tevt) { 01942 m_next = QF_timeEvtListHead_; 01943 QF_timeEvtListHead_ = this; 01944 QF_EVT_REF_CTR_INC_(this); // mark as linked 01945 } 01946 } 01947 else { 01948 isArmed = true; 01949 } 01950 m_ctr = nTicks; // re-load the tick counter (shift the phasing) 01951 01952 QS_BEGIN_NOCRIT_(QS_QF_TIMEEVT_REARM, QS::teObj_, this) 01953 QS_TIME_(); // timestamp 01954 QS_OBJ_(this); // this time event object 01955 QS_OBJ_(m_act); // the active object 01956 QS_TEC_(m_ctr); // the number of ticks 01957 QS_TEC_(m_interval); // the interval 01958 QS_U8_(isArmed ? u8_1 : u8_0); // was the timer armed? 01959 QS_END_NOCRIT_() 01960 01961 QF_CRIT_EXIT_(); 01962 return isArmed; 01963 } 01964 01965 QP_END_ 01966 01967 01968 ////////////////////////////////////////////////////////////////////////////// 01969 // Kernel selection based on QK_PREEMPTIVE 01970 // 01971 #ifdef QK_PREEMPTIVE 01972 01973 // "qk_pkg.h" ================================================================ 01974 /// \brief Internal (package scope) QK/C interface. 01975 01976 #ifndef QF_CRIT_STAT_TYPE 01977 /// \brief This is an internal macro for defining the critical section 01978 /// status type. 01979 /// 01980 /// The purpose of this macro is to enable writing the same code for the 01981 /// case when critical sectgion status type is defined and when it is not. 01982 /// If the macro #QF_CRIT_STAT_TYPE is defined, this internal macro 01983 /// provides the definition of the critical section status varaible. 01984 /// Otherwise this macro is empty. 01985 /// \sa #QF_CRIT_STAT_TYPE 01986 #define QF_CRIT_STAT_ 01987 01988 /// \brief This is an internal macro for entering a critical section. 01989 /// 01990 /// The purpose of this macro is to enable writing the same code for the 01991 /// case when critical sectgion status type is defined and when it is not. 01992 /// If the macro #QF_CRIT_STAT_TYPE is defined, this internal macro 01993 /// invokes #QF_CRIT_ENTRY passing the key variable as the parameter. 01994 /// Otherwise #QF_CRIT_ENTRY is invoked with a dummy parameter. 01995 /// \sa #QF_CRIT_ENTRY 01996 #define QF_CRIT_ENTRY_() QF_CRIT_ENTRY(dummy) 01997 01998 /// \brief This is an internal macro for exiting a cricial section. 01999 /// 02000 /// The purpose of this macro is to enable writing the same code for the 02001 /// case when critical sectgion status type is defined and when it is not. 02002 /// If the macro #QF_CRIT_STAT_TYPE is defined, this internal macro 02003 /// invokes #QF_CRIT_EXIT passing the key variable as the parameter. 02004 /// Otherwise #QF_CRIT_EXIT is invoked with a dummy parameter. 02005 /// \sa #QF_CRIT_EXIT 02006 #define QF_CRIT_EXIT_() QF_CRIT_EXIT(dummy) 02007 02008 #else 02009 #define QF_CRIT_STAT_ QF_CRIT_STAT_TYPE critStat_; 02010 #define QF_CRIT_ENTRY_() QF_CRIT_ENTRY(critStat_) 02011 #define QF_CRIT_EXIT_() QF_CRIT_EXIT(critStat_) 02012 #endif 02013 // define for backwards compatibility, see NOTE01 02014 #ifndef QF_CRIT_STAT_TYPE 02015 #if !defined(QF_INT_DISABLE) && defined(QF_CRIT_ENTRY) 02016 #define QF_INT_DISABLE() QF_CRIT_ENTRY(dummy) 02017 #endif 02018 #if !defined(QF_INT_ENABLE) && defined(QF_CRIT_EXIT) 02019 #define QF_INT_ENABLE() QF_CRIT_EXIT(dummy) 02020 #endif 02021 #endif // QF_CRIT_STAT_TYPE 02022 02023 // package-scope objects... 02024 #ifndef QK_NO_MUTEX 02025 extern "C" uint8_t QK_ceilingPrio_; ///< QK mutex priority ceiling 02026 #endif 02027 02028 // "qk.cpp" ================================================================== 02029 /// \brief QK_readySet_, QK_currPrio_, and QK_intNest_ definitions and 02030 /// QK::getVersion(), QF::init(), QF::run(), QF::stop(), 02031 /// QActive::start(), QActive::stop() implementations. 02032 02033 // Public-scope objects ------------------------------------------------------ 02034 extern "C" { 02035 #if (QF_MAX_ACTIVE <= 8) 02036 QP_ QPSet8 QK_readySet_; // ready set of QK 02037 #else 02038 QP_ QPSet64 QK_readySet_; // ready set of QK 02039 #endif 02040 // start with the QK scheduler locked 02041 uint8_t QK_currPrio_ = static_cast<uint8_t>(QF_MAX_ACTIVE + 1); 02042 uint8_t QK_intNest_; // start with nesting level of 0 02043 02044 } // extern "C" 02045 02046 QP_BEGIN_ 02047 02048 //............................................................................ 02049 char_t const Q_ROM * Q_ROM_VAR QK::getVersion(void) { 02050 uint8_t const u8_zero = static_cast<uint8_t>('0'); 02051 static char_t const Q_ROM Q_ROM_VAR version[] = { 02052 static_cast<char_t>(((QP_VERSION >> 12) & 0xFU) + u8_zero), 02053 static_cast<char_t>('.'), 02054 static_cast<char_t>(((QP_VERSION >> 8) & 0xFU) + u8_zero), 02055 static_cast<char_t>('.'), 02056 static_cast<char_t>(((QP_VERSION >> 4) & 0xFU) + u8_zero), 02057 static_cast<char_t>((QP_VERSION & 0xFU) + u8_zero), 02058 static_cast<char_t>('\0') 02059 }; 02060 return version; 02061 } 02062 //............................................................................ 02063 void QF::init(void) { 02064 QK_init(); // QK initialization ("C" linkage, might be assembly) 02065 } 02066 //............................................................................ 02067 void QF::stop(void) { 02068 QF::onCleanup(); // cleanup callback 02069 // nothing else to do for the QK preemptive kernel 02070 } 02071 //............................................................................ 02072 static void initialize(void) { 02073 QK_currPrio_ = static_cast<uint8_t>(0); // priority for the QK idle loop 02074 uint8_t p = QK_schedPrio_(); 02075 if (p != static_cast<uint8_t>(0)) { 02076 QK_sched_(p); // process all events produced so far 02077 } 02078 } 02079 //............................................................................ 02080 int16_t QF::run(void) { 02081 QF_INT_DISABLE(); 02082 initialize(); 02083 onStartup(); // startup callback 02084 QF_INT_ENABLE(); 02085 02086 for (;;) { // the QK idle loop 02087 QK::onIdle(); // invoke the QK on-idle callback 02088 } 02089 // this unreachable return is to make the compiler happy 02090 return static_cast<int16_t>(0); 02091 } 02092 //............................................................................ 02093 void QActive::start(uint8_t const prio, 02094 QEvt const *qSto[], uint32_t const qLen, 02095 void * const stkSto, uint32_t const stkSize, 02096 QEvt const * const ie) 02097 { 02098 Q_REQUIRE((static_cast<uint8_t>(0) < prio) 02099 && (prio <= static_cast<uint8_t>(QF_MAX_ACTIVE))); 02100 02101 m_eQueue.init(qSto, static_cast<QEQueueCtr>(qLen)); // initialize queue 02102 m_prio = prio; 02103 QF::add_(this); // make QF aware of this active object 02104 02105 #if defined(QK_TLS) || defined(QK_EXT_SAVE) 02106 // in the QK port the parameter stkSize is used as the thread flags 02107 m_osObject = static_cast<uint8_t>(stkSize); // m_osObject contains flags 02108 02109 // in the QK port the parameter stkSto is used as the thread-local-storage 02110 m_thread = stkSto; // contains the pointer to the thread-local-storage 02111 #else 02112 Q_ASSERT((stkSto == static_cast<void *>(0)) 02113 && (stkSize == static_cast<uint32_t>(0))); 02114 #endif 02115 02116 init(ie); // execute initial transition 02117 02118 QS_FLUSH(); // flush the trace buffer to the host 02119 } 02120 //............................................................................ 02121 void QActive::stop(void) { 02122 QF::remove_(this); // remove this active object from the QF 02123 } 02124 02125 QP_END_ 02126 02127 // "qk_sched" ================================================================ 02128 /// \brief QK_schedPrio_() and QK_sched_() implementation. 02129 02130 //............................................................................ 02131 // NOTE: the QK scheduler is entered and exited with interrupts DISABLED. 02132 // QK_sched_() is extern "C", so it does not belong to the QP namespace. 02133 // 02134 extern "C" { 02135 02136 //............................................................................ 02137 // NOTE: QK schedPrio_() is entered and exited with interrupts DISABLED 02138 uint8_t QK_schedPrio_(void) { 02139 02140 uint8_t p = QK_readySet_.findMax(); 02141 02142 #ifdef QK_NO_MUTEX 02143 if (p > QK_currPrio_) { // do we have a preemption? 02144 #else // QK priority-ceiling mutexes allowed 02145 if ((p > QK_currPrio_) && (p > QK_ceilingPrio_)) { 02146 #endif 02147 } 02148 else { 02149 p = static_cast<uint8_t>(0); 02150 } 02151 return p; 02152 } 02153 //............................................................................ 02154 void QK_sched_(uint8_t p) { 02155 02156 uint8_t pin = QK_currPrio_; // save the initial priority 02157 QP_ QActive *a; 02158 #ifdef QK_TLS // thread-local storage used? 02159 uint8_t pprev = pin; 02160 #endif 02161 do { 02162 a = QP_ QF::active_[p]; // obtain the pointer to the AO 02163 QK_currPrio_ = p; // this becomes the current task priority 02164 02165 #ifdef QK_TLS // thread-local storage used? 02166 if (p != pprev) { // are we changing threads? 02167 QK_TLS(a); // switch new thread-local storage 02168 pprev = p; 02169 } 02170 #endif 02171 QS_BEGIN_NOCRIT_(QP_ QS_QK_SCHEDULE, QP_ QS::aoObj_, a) 02172 QS_TIME_(); // timestamp 02173 QS_U8_(p); // the priority of the active object 02174 QS_U8_(pin); // the preempted priority 02175 QS_END_NOCRIT_() 02176 02177 QF_INT_ENABLE(); // unconditionally enable interrupts 02178 02179 QP_ QEvt const *e = a->get_(); // get the next event for this AO 02180 a->dispatch(e); // dispatch e to this AO 02181 QP_ QF::gc(e); // garbage collect the event, if necessary 02182 02183 // determine the next highest-priority AO ready to run 02184 QF_INT_DISABLE(); // disable interrupts 02185 p = QK_readySet_.findMax(); 02186 02187 #ifdef QK_NO_MUTEX 02188 } while (p > pin); // is the new priority higher than initial? 02189 #else // QK priority-ceiling mutexes allowed 02190 } while ((p > pin) && (p > QK_ceilingPrio_)); 02191 #endif 02192 02193 QK_currPrio_ = pin; // restore the initial priority 02194 02195 #ifdef QK_TLS // thread-local storage used? 02196 if (pin != static_cast<uint8_t>(0)) { // no extended context for idle loop 02197 a = QP_ QF::active_[pin]; // the pointer to the preempted AO 02198 QK_TLS(a); // restore the original TLS 02199 } 02200 #endif 02201 } 02202 02203 } // extern "C" 02204 02205 #ifndef QK_NO_MUTEX 02206 02207 // "qk_mutex.cpp" ============================================================ 02208 /// \brief QK::mutexLock()/QK::mutexUnlock() implementation. 02209 02210 // package-scope objects ----------------------------------------------------- 02211 extern "C" { 02212 uint8_t QK_ceilingPrio_; // ceiling priority of a mutex 02213 } 02214 02215 QP_BEGIN_ 02216 02217 //............................................................................ 02218 QMutex QK::mutexLock(uint8_t const prioCeiling) { 02219 QF_CRIT_STAT_ 02220 QF_CRIT_ENTRY_(); 02221 uint8_t mutex = QK_ceilingPrio_; // original QK priority ceiling to return 02222 if (QK_ceilingPrio_ < prioCeiling) { 02223 QK_ceilingPrio_ = prioCeiling; // raise the QK priority ceiling 02224 } 02225 02226 QS_BEGIN_NOCRIT_(QS_QK_MUTEX_LOCK, 02227 static_cast<void *>(0), static_cast<void *>(0)) 02228 QS_TIME_(); // timestamp 02229 QS_U8_(mutex); // the original priority 02230 QS_U8_(QK_ceilingPrio_); // the current priority ceiling 02231 QS_END_NOCRIT_() 02232 02233 QF_CRIT_EXIT_(); 02234 return mutex; 02235 } 02236 //............................................................................ 02237 void QK::mutexUnlock(QMutex mutex) { 02238 QF_CRIT_STAT_ 02239 QF_CRIT_ENTRY_(); 02240 02241 QS_BEGIN_NOCRIT_(QS_QK_MUTEX_UNLOCK, 02242 static_cast<void *>(0), static_cast<void *>(0)) 02243 QS_TIME_(); // timestamp 02244 QS_U8_(mutex); // the original priority 02245 QS_U8_(QK_ceilingPrio_); // the current priority ceiling 02246 QS_END_NOCRIT_() 02247 02248 if (QK_ceilingPrio_ > mutex) { 02249 QK_ceilingPrio_ = mutex; // restore the saved priority ceiling 02250 mutex = QK_schedPrio_(); // reuse 'mutex' to hold priority 02251 if (mutex != static_cast<uint8_t>(0)) { 02252 QK_sched_(mutex); 02253 } 02254 } 02255 QF_CRIT_EXIT_(); 02256 } 02257 02258 QP_END_ 02259 02260 #endif // QK_NO_MUTEX 02261 02262 #else // QK_PREEMPTIVE 02263 02264 // "qvanilla.cpp" ============================================================ 02265 /// \brief "vanilla" cooperative kernel, 02266 /// QActive::start(), QActive::stop(), and QF::run() implementation. 02267 02268 QP_BEGIN_ 02269 02270 // Package-scope objects ----------------------------------------------------- 02271 extern "C" { 02272 #if (QF_MAX_ACTIVE <= 8) 02273 QPSet8 QF_readySet_; // ready set of active objects 02274 #else 02275 QPSet64 QF_readySet_; // ready set of active objects 02276 #endif 02277 02278 uint8_t QF_currPrio_; ///< current task/interrupt priority 02279 uint8_t QF_intNest_; ///< interrupt nesting level 02280 02281 } // extern "C" 02282 02283 //............................................................................ 02284 void QF::init(void) { 02285 // nothing to do for the "vanilla" kernel 02286 } 02287 //............................................................................ 02288 void QF::stop(void) { 02289 onCleanup(); // cleanup callback 02290 // nothing else to do for the "vanilla" kernel 02291 } 02292 //............................................................................ 02293 int16_t QF::run(void) { 02294 onStartup(); // startup callback 02295 02296 for (;;) { // the bacground loop 02297 QF_INT_DISABLE(); 02298 if (QF_readySet_.notEmpty()) { 02299 uint8_t p = QF_readySet_.findMax(); 02300 QActive *a = active_[p]; 02301 QF_currPrio_ = p; // save the current priority 02302 QF_INT_ENABLE(); 02303 02304 QEvt const *e = a->get_(); // get the next event for this AO 02305 a->dispatch(e); // dispatch evt to the HSM 02306 gc(e); // determine if event is garbage and collect it if so 02307 } 02308 else { 02309 onIdle(); // see NOTE01 02310 } 02311 } 02312 // this unreachable return is to make the compiler happy 02313 return static_cast<int16_t>(0); 02314 } 02315 //............................................................................ 02316 void QActive::start(uint8_t const prio, 02317 QEvt const *qSto[], uint32_t const qLen, 02318 void * const stkSto, uint32_t const, 02319 QEvt const * const ie) 02320 { 02321 Q_REQUIRE((u8_0 < prio) && (prio <= static_cast<uint8_t>(QF_MAX_ACTIVE)) 02322 && (stkSto == null_void)); // does not need per-actor stack 02323 02324 m_eQueue.init(qSto, static_cast<QEQueueCtr>(qLen)); // initialize QEQueue 02325 m_prio = prio; // set the QF priority of this active object 02326 QF::add_(this); // make QF aware of this active object 02327 init(ie); // execute initial transition 02328 02329 QS_FLUSH(); // flush the trace buffer to the host 02330 } 02331 //............................................................................ 02332 void QActive::stop(void) { 02333 QF::remove_(this); 02334 } 02335 02336 QP_END_ 02337 02338 ////////////////////////////////////////////////////////////////////////////// 02339 // NOTE01: 02340 // QF::onIdle() must be called with interrupts DISABLED because the 02341 // determination of the idle condition (no events in the queues) can change 02342 // at any time by an interrupt posting events to a queue. The QF::onIdle() 02343 // MUST enable interrups internally, perhaps at the same time as putting the 02344 // CPU into a power-saving mode. 02345 // 02346 02347 extern "C" { 02348 02349 void QK_sched_(uint8_t p) { // dummy empty definition for qk_port.s 02350 (void)p; 02351 } 02352 02353 uint8_t QK_schedPrio_(void) { // dummy empty definition for qk_port.s 02354 return static_cast<uint8_t>(0U); 02355 } 02356 02357 } // extern "C" 02358 02359 #endif // QK_PREEMPTIVE 02360 02361 ////////////////////////////////////////////////////////////////////////////// 02362 #ifdef Q_SPY 02363 02364 // "qs_pkg.h" ================================================================ 02365 /// \brief Internal (package scope) QS/C++ interface. 02366 02367 QP_BEGIN_ 02368 02369 /// \brief QS ring buffer counter and offset type 02370 typedef uint16_t QSCtr; 02371 02372 /// \brief Internal QS macro to insert an un-escaped byte into 02373 /// the QS buffer 02374 //// 02375 #define QS_INSERT_BYTE(b_) \ 02376 QS_PTR_AT_(QS_head_) = (b_); \ 02377 ++QS_head_; \ 02378 if (QS_head_ == QS_end_) { \ 02379 QS_head_ = static_cast<QSCtr>(0); \ 02380 } \ 02381 ++QS_used_; 02382 02383 /// \brief Internal QS macro to insert an escaped byte into the QS buffer 02384 #define QS_INSERT_ESC_BYTE(b_) \ 02385 QS_chksum_ = static_cast<uint8_t>(QS_chksum_ + (b_)); \ 02386 if (((b_) == QS_FRAME) || ((b_) == QS_ESC)) { \ 02387 QS_INSERT_BYTE(QS_ESC) \ 02388 QS_INSERT_BYTE(static_cast<uint8_t>((b_) ^ QS_ESC_XOR)) \ 02389 } \ 02390 else { \ 02391 QS_INSERT_BYTE(b_) \ 02392 } 02393 02394 /// \brief Internal QS macro to insert a escaped checksum byte into 02395 /// the QS buffer 02396 #define QS_INSERT_CHKSUM_BYTE() \ 02397 QS_chksum_ = static_cast<uint8_t>(~QS_chksum_); \ 02398 if ((QS_chksum_ == QS_FRAME) || (QS_chksum_ == QS_ESC)) { \ 02399 QS_INSERT_BYTE(QS_ESC) \ 02400 QS_INSERT_BYTE(static_cast<uint8_t>(QS_chksum_ ^ QS_ESC_XOR)) \ 02401 } \ 02402 else { \ 02403 QS_INSERT_BYTE(QS_chksum_) \ 02404 } 02405 02406 02407 /// \brief Internal QS macro to access the QS ring buffer 02408 /// 02409 /// \note The QS buffer is allocated by the user and is accessed through the 02410 /// pointer QS_ring_, which violates the MISRA-C 2004 Rule 17.4(req), pointer 02411 /// arithmetic other than array indexing. Encapsulating this violation in a 02412 /// macro allows to selectively suppress this specific deviation. 02413 #define QS_PTR_AT_(i_) (QS_ring_[i_]) 02414 02415 02416 /// \brief Frame character of the QS output protocol 02417 uint8_t const QS_FRAME = static_cast<uint8_t>(0x7E); 02418 02419 /// \brief Escape character of the QS output protocol 02420 uint8_t const QS_ESC = static_cast<uint8_t>(0x7D); 02421 02422 /// \brief Escape modifier of the QS output protocol 02423 /// 02424 /// The escaped byte is XOR-ed with the escape modifier before it is inserted 02425 /// into the QS buffer. 02426 uint8_t const QS_ESC_XOR = static_cast<uint8_t>(0x20); 02427 02428 #ifndef Q_ROM_BYTE 02429 /// \brief Macro to access a byte allocated in ROM 02430 /// 02431 /// Some compilers for Harvard-architecture MCUs, such as gcc for AVR, do 02432 /// not generate correct code for accessing data allocated in the program 02433 /// space (ROM). The workaround for such compilers is to explictly add 02434 /// assembly code to access each data element allocated in the program 02435 /// space. The macro Q_ROM_BYTE() retrieves a byte from the given ROM 02436 /// address. 02437 /// 02438 /// The Q_ROM_BYTE() macro should be defined for the compilers that 02439 /// cannot handle correctly data allocated in ROM (such as the gcc). 02440 /// If the macro is left undefined, the default definition simply returns 02441 /// the argument and lets the compiler generate the correct code. 02442 #define Q_ROM_BYTE(rom_var_) (rom_var_) 02443 #endif 02444 02445 //............................................................................ 02446 extern uint8_t *QS_ring_; ///< pointer to the start of the ring buffer 02447 extern QSCtr QS_end_; ///< offset of the end of the ring buffer 02448 extern QSCtr QS_head_; ///< offset to where next byte will be inserted 02449 extern QSCtr QS_tail_; ///< offset of where next event will be extracted 02450 extern QSCtr QS_used_; ///< number of bytes currently in the ring buffer 02451 extern uint8_t QS_seq_; ///< the record sequence number 02452 extern uint8_t QS_chksum_; ///< the checksum of the current record 02453 extern uint8_t QS_full_; ///< the ring buffer is temporarily full 02454 02455 QP_END_ 02456 02457 02458 // "qs.cpp" ================================================================== 02459 /// \brief QS internal variables definitions and core QS functions 02460 /// implementations. 02461 02462 QP_BEGIN_ 02463 02464 //............................................................................ 02465 uint8_t QS::glbFilter_[32]; // global QS filter 02466 02467 //............................................................................ 02468 uint8_t *QS_ring_; // pointer to the start of the ring buffer 02469 QSCtr QS_end_; // offset of the end of the ring buffer 02470 QSCtr QS_head_; // offset to where next byte will be inserted 02471 QSCtr QS_tail_; // offset of where next byte will be extracted 02472 QSCtr QS_used_; // number of bytes currently in the ring buffer 02473 uint8_t QS_seq_; // the record sequence number 02474 uint8_t QS_chksum_; // the checksum of the current record 02475 uint8_t QS_full_; // the ring buffer is temporarily full 02476 02477 //............................................................................ 02478 char_t const Q_ROM * Q_ROM_VAR QS::getVersion(void) { 02479 uint8_t const u8_zero = static_cast<uint8_t>('0'); 02480 static char_t const Q_ROM Q_ROM_VAR version[] = { 02481 static_cast<char_t>(((QP_VERSION >> 12) & 0xFU) + u8_zero), 02482 static_cast<char_t>('.'), 02483 static_cast<char_t>(((QP_VERSION >> 8) & 0xFU) + u8_zero), 02484 static_cast<char_t>('.'), 02485 static_cast<char_t>(((QP_VERSION >> 4) & 0xFU) + u8_zero), 02486 static_cast<char_t>((QP_VERSION & 0xFU) + u8_zero), 02487 static_cast<char_t>('\0') 02488 }; 02489 return version; 02490 } 02491 //............................................................................ 02492 void QS::initBuf(uint8_t sto[], uint32_t const stoSize) { 02493 QS_ring_ = &sto[0]; 02494 QS_end_ = static_cast<QSCtr>(stoSize); 02495 } 02496 //............................................................................ 02497 void QS::filterOn(uint8_t const rec) { 02498 if (rec == QS_ALL_RECORDS) { 02499 uint8_t i; 02500 for (i = static_cast<uint8_t>(0); 02501 i < static_cast<uint8_t>(sizeof(glbFilter_)); 02502 ++i) 02503 { 02504 glbFilter_[i] = static_cast<uint8_t>(0xFF); 02505 } 02506 } 02507 else { 02508 glbFilter_[rec >> 3] |= 02509 static_cast<uint8_t>(1U << (rec & static_cast<uint8_t>(0x07))); 02510 } 02511 } 02512 //............................................................................ 02513 void QS::filterOff(uint8_t const rec) { 02514 if (rec == QS_ALL_RECORDS) { 02515 uint8_t i; 02516 for (i = static_cast<uint8_t>(0); 02517 i < static_cast<uint8_t>(sizeof(glbFilter_)); 02518 ++i) 02519 { 02520 glbFilter_[i] = static_cast<uint8_t>(0); 02521 } 02522 } 02523 else { 02524 glbFilter_[rec >> 3] &= static_cast<uint8_t>( 02525 ~static_cast<uint8_t>((1U << (rec & static_cast<uint8_t>(0x07))))); 02526 } 02527 } 02528 //............................................................................ 02529 void QS::begin(uint8_t const rec) { 02530 QS_chksum_ = static_cast<uint8_t>(0); // clear the checksum 02531 ++QS_seq_; // always increment the sequence number 02532 QS_INSERT_ESC_BYTE(QS_seq_) // store the sequence number 02533 QS_INSERT_ESC_BYTE(rec) // store the record ID 02534 } 02535 //............................................................................ 02536 void QS::end(void) { 02537 QS_INSERT_CHKSUM_BYTE() 02538 QS_INSERT_BYTE(QS_FRAME) 02539 if (QS_used_ > QS_end_) { // overrun over the old data? 02540 QS_tail_ = QS_head_; // shift the tail to the old data 02541 QS_used_ = QS_end_; // the whole buffer is used 02542 } 02543 } 02544 //............................................................................ 02545 void QS::u8(uint8_t const format, uint8_t const d) { 02546 QS_INSERT_ESC_BYTE(format) 02547 QS_INSERT_ESC_BYTE(d) 02548 } 02549 //............................................................................ 02550 void QS::u16(uint8_t const format, uint16_t d) { 02551 QS_INSERT_ESC_BYTE(format) 02552 QS_INSERT_ESC_BYTE(static_cast<uint8_t>(d)) 02553 d >>= 8; 02554 QS_INSERT_ESC_BYTE(static_cast<uint8_t>(d)) 02555 } 02556 //............................................................................ 02557 void QS::u32(uint8_t const format, uint32_t d) { 02558 QS_INSERT_ESC_BYTE(format) 02559 QS_INSERT_ESC_BYTE(static_cast<uint8_t>(d)) 02560 d >>= 8; 02561 QS_INSERT_ESC_BYTE(static_cast<uint8_t>(d)) 02562 d >>= 8; 02563 QS_INSERT_ESC_BYTE(static_cast<uint8_t>(d)) 02564 d >>= 8; 02565 QS_INSERT_ESC_BYTE(static_cast<uint8_t>(d)) 02566 } 02567 02568 QP_END_ 02569 02570 02571 // "qs_.cpp" ================================================================= 02572 /// \brief QS functions for internal use inside QP components 02573 02574 QP_BEGIN_ 02575 02576 //............................................................................ 02577 void const *QS::smObj_; // local state machine for QEP filter 02578 void const *QS::aoObj_; // local active object for QF filter 02579 void const *QS::mpObj_; // local event pool for QF filter 02580 void const *QS::eqObj_; // local raw queue for QF filter 02581 void const *QS::teObj_; // local time event for QF filter 02582 void const *QS::apObj_; // local object Application filter 02583 02584 QSTimeCtr QS::tickCtr_; // tick counter for the QS_QF_TICK record 02585 02586 //............................................................................ 02587 void QS::u8_(uint8_t const d) { 02588 QS_INSERT_ESC_BYTE(d) 02589 } 02590 //............................................................................ 02591 void QS::u16_(uint16_t d) { 02592 QS_INSERT_ESC_BYTE(static_cast<uint8_t>(d)) 02593 d >>= 8; 02594 QS_INSERT_ESC_BYTE(static_cast<uint8_t>(d)) 02595 } 02596 //............................................................................ 02597 void QS::u32_(uint32_t d) { 02598 QS_INSERT_ESC_BYTE(static_cast<uint8_t>(d)) 02599 d >>= 8; 02600 QS_INSERT_ESC_BYTE(static_cast<uint8_t>(d)) 02601 d >>= 8; 02602 QS_INSERT_ESC_BYTE(static_cast<uint8_t>(d)) 02603 d >>= 8; 02604 QS_INSERT_ESC_BYTE(static_cast<uint8_t>(d)) 02605 } 02606 //............................................................................ 02607 void QS::str_(char_t const *s) { 02608 uint8_t b = static_cast<uint8_t>(*s); 02609 while (b != static_cast<uint8_t>(0)) { 02610 // ASCII characters don't need escaping 02611 QS_chksum_ = static_cast<uint8_t>(QS_chksum_ + b); 02612 QS_INSERT_BYTE(b) 02613 ++s; 02614 b = static_cast<uint8_t>(*s); 02615 } 02616 QS_INSERT_BYTE(static_cast<uint8_t>(0)) 02617 } 02618 //............................................................................ 02619 void QS::str_ROM_(char_t const Q_ROM * Q_ROM_VAR s) { 02620 uint8_t b = static_cast<uint8_t>(Q_ROM_BYTE(*s)); 02621 while (b != static_cast<uint8_t>(0)) { 02622 // ASCII characters don't need escaping 02623 QS_chksum_ = static_cast<uint8_t>(QS_chksum_ + b); 02624 QS_INSERT_BYTE(b) 02625 ++s; 02626 b = static_cast<uint8_t>(Q_ROM_BYTE(*s)); 02627 } 02628 QS_INSERT_BYTE(static_cast<uint8_t>(0)) 02629 } 02630 02631 QP_END_ 02632 02633 // "qs_blk.cpp" ============================================================== 02634 /// \brief QS::getBlock() implementation 02635 02636 QP_BEGIN_ 02637 02638 //............................................................................ 02639 // get up to *pn bytes of contiguous memory 02640 uint8_t const *QS::getBlock(uint16_t * const pNbytes) { 02641 uint8_t *block; 02642 if (QS_used_ == static_cast<QSCtr>(0)) { 02643 *pNbytes = static_cast<uint16_t>(0); 02644 block = static_cast<uint8_t *>(0); // no bytes to return right now 02645 } 02646 else { 02647 QSCtr n = static_cast<QSCtr>(QS_end_ - QS_tail_); 02648 if (n > QS_used_) { 02649 n = QS_used_; 02650 } 02651 if (n > static_cast<QSCtr>(*pNbytes)) { 02652 n = static_cast<QSCtr>(*pNbytes); 02653 } 02654 *pNbytes = static_cast<uint16_t>(n); 02655 QS_used_ = static_cast<QSCtr>(QS_used_ - n); 02656 QSCtr t = QS_tail_; 02657 QS_tail_ = static_cast<QSCtr>(QS_tail_ + n); 02658 if (QS_tail_ == QS_end_) { 02659 QS_tail_ = static_cast<QSCtr>(0); 02660 } 02661 block = &QS_PTR_AT_(t); 02662 } 02663 return block; 02664 } 02665 02666 QP_END_ 02667 02668 // "qs_byte.cpp" ============================================================= 02669 /// \brief QS::getByte() implementation 02670 02671 QP_BEGIN_ 02672 02673 //............................................................................ 02674 uint16_t QS::getByte(void) { 02675 uint16_t ret; 02676 if (QS_used_ == static_cast<QSCtr>(0)) { 02677 ret = QS_EOD; // set End-Of-Data 02678 } 02679 else { 02680 ret = static_cast<uint16_t>(QS_PTR_AT_(QS_tail_)); // byte to return 02681 ++QS_tail_; // advance the tail 02682 if (QS_tail_ == QS_end_) { // tail wrap around? 02683 QS_tail_ = static_cast<QSCtr>(0); 02684 } 02685 --QS_used_; // one less byte used 02686 } 02687 return ret; // return the byte or EOD 02688 } 02689 02690 QP_END_ 02691 02692 02693 // "qs_f32.cpp" ============================================================== 02694 /// \brief QS::f32() implementation 02695 02696 QP_BEGIN_ 02697 02698 //............................................................................ 02699 void QS::f32(uint8_t const format, float32_t const d) { 02700 union F32Rep { 02701 float32_t f; 02702 uint32_t u; 02703 } fu32; 02704 fu32.f = d; 02705 02706 QS_INSERT_ESC_BYTE(format) 02707 QS_INSERT_ESC_BYTE(static_cast<uint8_t>(fu32.u)) 02708 fu32.u >>= 8; 02709 QS_INSERT_ESC_BYTE(static_cast<uint8_t>(fu32.u)) 02710 fu32.u >>= 8; 02711 QS_INSERT_ESC_BYTE(static_cast<uint8_t>(fu32.u)) 02712 fu32.u >>= 8; 02713 QS_INSERT_ESC_BYTE(static_cast<uint8_t>(fu32.u)) 02714 } 02715 02716 QP_END_ 02717 02718 02719 // "qs_mem.cpp" ============================================================== 02720 /// \brief QS::mem() implementation 02721 02722 QP_BEGIN_ 02723 02724 //............................................................................ 02725 void QS::mem(uint8_t const *blk, uint8_t size) { 02726 QS_INSERT_BYTE(static_cast<uint8_t>(QS_MEM_T)) 02727 QS_chksum_ = 02728 static_cast<uint8_t>(QS_chksum_ + static_cast<uint8_t>(QS_MEM_T)); 02729 QS_INSERT_ESC_BYTE(size) 02730 while (size != static_cast<uint8_t>(0)) { 02731 QS_INSERT_ESC_BYTE(*blk) 02732 ++blk; 02733 --size; 02734 } 02735 } 02736 02737 QP_END_ 02738 02739 02740 // "qs_str.cpp" ============================================================== 02741 /// \brief QS::str() and QS::str_ROM() implementation 02742 02743 QP_BEGIN_ 02744 02745 //............................................................................ 02746 void QS::str(char_t const *s) { 02747 uint8_t b = static_cast<uint8_t>(*s); 02748 QS_INSERT_BYTE(static_cast<uint8_t>(QS_STR_T)) 02749 QS_chksum_ = 02750 static_cast<uint8_t>(QS_chksum_ + static_cast<uint8_t>(QS_STR_T)); 02751 while (b != static_cast<uint8_t>(0)) { 02752 // ASCII characters don't need escaping 02753 QS_INSERT_BYTE(b) 02754 QS_chksum_ = static_cast<uint8_t>(QS_chksum_ + b); 02755 ++s; 02756 b = static_cast<uint8_t>(*s); 02757 } 02758 QS_INSERT_BYTE(static_cast<uint8_t>(0)) 02759 } 02760 //............................................................................ 02761 void QS::str_ROM(char_t const Q_ROM * Q_ROM_VAR s) { 02762 uint8_t b = static_cast<uint8_t>(Q_ROM_BYTE(*s)); 02763 QS_INSERT_BYTE(static_cast<uint8_t>(QS_STR_T)) 02764 QS_chksum_ = 02765 static_cast<uint8_t>(QS_chksum_ + static_cast<uint8_t>(QS_STR_T)); 02766 while (b != static_cast<uint8_t>(0)) { 02767 // ASCII characters don't need escaping 02768 QS_INSERT_BYTE(b) 02769 QS_chksum_ = static_cast<uint8_t>(QS_chksum_ + b); 02770 ++s; 02771 b = static_cast<uint8_t>(Q_ROM_BYTE(*s)); 02772 } 02773 QS_INSERT_BYTE(static_cast<uint8_t>(0)) 02774 } 02775 02776 QP_END_ 02777 02778 #endif // Q_SPY
Generated on Wed Jul 13 2022 11:50:18 by 1.7.2