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/C++ (Quantum Platform in C++) is a lightweight, open source active object (actor) framework for building responsive and modular real-time embedded applications as systems of asynchronous event-driven active objects (actors). The QP/C++ framework is a member of a larger family consisting of QP/C++, QP/C, and QP-nano frameworks, which are all strictly quality controlled, thoroughly documented, and available under GPLv3 with a special Exception for mbed (see http://www.state-machine.com/licensing/QP-mbed_GPL_Exception.txt).
The behavior of active objects is specified in QP/C++ by means of hierarchical state machines (UML statecharts). The framework supports manual coding of UML state machines in C++ as well as automatic code generation by means of the free QM modeling tool (http://www.state-machine.com/qm).
Please see the "QP/C++ Reference Manual" (http://www.state-machine.com/qpcpp) for more information.
qp.cpp@0:064c79e7311a, 2011-02-09 (annotated)
- Committer:
- QL
- Date:
- Wed Feb 09 14:46:03 2011 +0000
- Revision:
- 0:064c79e7311a
- Child:
- 6:01d57c81e96a
4.1.06a
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
QL | 0:064c79e7311a | 1 | ////////////////////////////////////////////////////////////////////////////// |
QL | 0:064c79e7311a | 2 | // Product: QP/C++, selectabel Vanilla/QK kernels |
QL | 0:064c79e7311a | 3 | // Last Updated for QP ver: 4.1.06 (modified to fit in one file) |
QL | 0:064c79e7311a | 4 | // Date of the Last Update: Feb 08, 2011 |
QL | 0:064c79e7311a | 5 | // |
QL | 0:064c79e7311a | 6 | // Q u a n t u m L e a P s |
QL | 0:064c79e7311a | 7 | // --------------------------- |
QL | 0:064c79e7311a | 8 | // innovating embedded systems |
QL | 0:064c79e7311a | 9 | // |
QL | 0:064c79e7311a | 10 | // Copyright (C) 2002-2011 Quantum Leaps, LLC. All rights reserved. |
QL | 0:064c79e7311a | 11 | // |
QL | 0:064c79e7311a | 12 | // This software may be distributed and modified under the terms of the GNU |
QL | 0:064c79e7311a | 13 | // General Public License version 2 (GPL) as published by the Free Software |
QL | 0:064c79e7311a | 14 | // Foundation and appearing in the file GPL.TXT included in the packaging of |
QL | 0:064c79e7311a | 15 | // this file. Please note that GPL Section 2[b] requires that all works based |
QL | 0:064c79e7311a | 16 | // on this software must also be made publicly available under the terms of |
QL | 0:064c79e7311a | 17 | // the GPL ("Copyleft"). |
QL | 0:064c79e7311a | 18 | // |
QL | 0:064c79e7311a | 19 | // Alternatively, this software may be distributed and modified under the |
QL | 0:064c79e7311a | 20 | // terms of Quantum Leaps commercial licenses, which expressly supersede |
QL | 0:064c79e7311a | 21 | // the GPL and are specifically designed for licensees interested in |
QL | 0:064c79e7311a | 22 | // retaining the proprietary status of their code. |
QL | 0:064c79e7311a | 23 | // |
QL | 0:064c79e7311a | 24 | // Contact information: |
QL | 0:064c79e7311a | 25 | // Quantum Leaps Web site: http://www.quantum-leaps.com |
QL | 0:064c79e7311a | 26 | // e-mail: info@quantum-leaps.com |
QL | 0:064c79e7311a | 27 | ////////////////////////////////////////////////////////////////////////////// |
QL | 0:064c79e7311a | 28 | #include "qp_port.h" // QP port |
QL | 0:064c79e7311a | 29 | |
QL | 0:064c79e7311a | 30 | Q_DEFINE_THIS_MODULE(qp) |
QL | 0:064c79e7311a | 31 | |
QL | 0:064c79e7311a | 32 | // "qep_pkg.h" =============================================================== |
QL | 0:064c79e7311a | 33 | /// internal QEP constants |
QL | 0:064c79e7311a | 34 | enum QEPConst { |
QL | 0:064c79e7311a | 35 | QEP_EMPTY_SIG_ = 0, ///< empty signal for internal use only |
QL | 0:064c79e7311a | 36 | |
QL | 0:064c79e7311a | 37 | /// maximum depth of state nesting (including the top level), must be >= 3 |
QL | 0:064c79e7311a | 38 | QEP_MAX_NEST_DEPTH_ = 6 |
QL | 0:064c79e7311a | 39 | }; |
QL | 0:064c79e7311a | 40 | |
QL | 0:064c79e7311a | 41 | /// helper macro to trigger internal event in an HSM |
QL | 0:064c79e7311a | 42 | #define QEP_TRIG_(state_, sig_) \ |
QL | 0:064c79e7311a | 43 | ((*(state_))(this, &QEP_reservedEvt_[sig_])) |
QL | 0:064c79e7311a | 44 | |
QL | 0:064c79e7311a | 45 | /// helper macro to trigger entry action in an HSM |
QL | 0:064c79e7311a | 46 | #define QEP_EXIT_(state_) \ |
QL | 0:064c79e7311a | 47 | if (QEP_TRIG_(state_, Q_EXIT_SIG) == Q_RET_HANDLED) { \ |
QL | 0:064c79e7311a | 48 | QS_BEGIN_(QS_QEP_STATE_EXIT, QS::smObj_, this) \ |
QL | 0:064c79e7311a | 49 | QS_OBJ_(this); \ |
QL | 0:064c79e7311a | 50 | QS_FUN_(state_); \ |
QL | 0:064c79e7311a | 51 | QS_END_() \ |
QL | 0:064c79e7311a | 52 | } |
QL | 0:064c79e7311a | 53 | |
QL | 0:064c79e7311a | 54 | /// helper macro to trigger exit action in an HSM |
QL | 0:064c79e7311a | 55 | #define QEP_ENTER_(state_) \ |
QL | 0:064c79e7311a | 56 | if (QEP_TRIG_(state_, Q_ENTRY_SIG) == Q_RET_HANDLED) { \ |
QL | 0:064c79e7311a | 57 | QS_BEGIN_(QS_QEP_STATE_ENTRY, QS::smObj_, this) \ |
QL | 0:064c79e7311a | 58 | QS_OBJ_(this); \ |
QL | 0:064c79e7311a | 59 | QS_FUN_(state_); \ |
QL | 0:064c79e7311a | 60 | QS_END_() \ |
QL | 0:064c79e7311a | 61 | } |
QL | 0:064c79e7311a | 62 | |
QL | 0:064c79e7311a | 63 | // "qep.cpp" ================================================================= |
QL | 0:064c79e7311a | 64 | // Package-scope objects ----------------------------------------------------- |
QL | 0:064c79e7311a | 65 | QEvent const QEP_reservedEvt_[] = { |
QL | 0:064c79e7311a | 66 | { (QSignal)QEP_EMPTY_SIG_, (uint8_t)0 }, |
QL | 0:064c79e7311a | 67 | { (QSignal)Q_ENTRY_SIG, (uint8_t)0 }, |
QL | 0:064c79e7311a | 68 | { (QSignal)Q_EXIT_SIG, (uint8_t)0 }, |
QL | 0:064c79e7311a | 69 | { (QSignal)Q_INIT_SIG, (uint8_t)0 } |
QL | 0:064c79e7311a | 70 | }; |
QL | 0:064c79e7311a | 71 | //............................................................................ |
QL | 0:064c79e7311a | 72 | //lint -e970 -e971 ignore MISRA rules 13 and 14 in this function |
QL | 0:064c79e7311a | 73 | char const Q_ROM * Q_ROM_VAR QEP::getVersion(void) { |
QL | 0:064c79e7311a | 74 | static char const Q_ROM Q_ROM_VAR version[] = { |
QL | 0:064c79e7311a | 75 | ((QP_VERSION >> 12) & 0xF) + '0', |
QL | 0:064c79e7311a | 76 | '.', |
QL | 0:064c79e7311a | 77 | ((QP_VERSION >> 8) & 0xF) + '0', |
QL | 0:064c79e7311a | 78 | '.', |
QL | 0:064c79e7311a | 79 | ((QP_VERSION >> 4) & 0xF) + '0', |
QL | 0:064c79e7311a | 80 | (QP_VERSION & 0xF) + '0', |
QL | 0:064c79e7311a | 81 | '\0' |
QL | 0:064c79e7311a | 82 | }; |
QL | 0:064c79e7311a | 83 | return version; |
QL | 0:064c79e7311a | 84 | } |
QL | 0:064c79e7311a | 85 | |
QL | 0:064c79e7311a | 86 | // "qhsm_top.cpp" ============================================================ |
QL | 0:064c79e7311a | 87 | QState QHsm::top(QHsm *, QEvent const *) { |
QL | 0:064c79e7311a | 88 | return Q_IGNORED(); // the top state ignores all events |
QL | 0:064c79e7311a | 89 | } |
QL | 0:064c79e7311a | 90 | |
QL | 0:064c79e7311a | 91 | // "qhsm_ini.cpp" ============================================================ |
QL | 0:064c79e7311a | 92 | QHsm::~QHsm() { |
QL | 0:064c79e7311a | 93 | } |
QL | 0:064c79e7311a | 94 | //............................................................................ |
QL | 0:064c79e7311a | 95 | void QHsm::init(QEvent const *e) { |
QL | 0:064c79e7311a | 96 | QStateHandler t; |
QL | 0:064c79e7311a | 97 | QS_INT_LOCK_KEY_ |
QL | 0:064c79e7311a | 98 | |
QL | 0:064c79e7311a | 99 | // the top-most initial transition must be taken |
QL | 0:064c79e7311a | 100 | Q_ALLEGE((*m_state)(this, e) == Q_RET_TRAN); |
QL | 0:064c79e7311a | 101 | |
QL | 0:064c79e7311a | 102 | t = (QStateHandler)&QHsm::top; // HSM starts in the top state |
QL | 0:064c79e7311a | 103 | do { // drill into the target... |
QL | 0:064c79e7311a | 104 | QStateHandler path[QEP_MAX_NEST_DEPTH_]; |
QL | 0:064c79e7311a | 105 | int8_t ip = (int8_t)0; // transition entry path index |
QL | 0:064c79e7311a | 106 | |
QL | 0:064c79e7311a | 107 | |
QL | 0:064c79e7311a | 108 | QS_BEGIN_(QS_QEP_STATE_INIT, QS::smObj_, this) |
QL | 0:064c79e7311a | 109 | QS_OBJ_(this); // this state machine object |
QL | 0:064c79e7311a | 110 | QS_FUN_(t); // the source state |
QL | 0:064c79e7311a | 111 | QS_FUN_(m_state); // the target of the initial transition |
QL | 0:064c79e7311a | 112 | QS_END_() |
QL | 0:064c79e7311a | 113 | |
QL | 0:064c79e7311a | 114 | path[0] = m_state; |
QL | 0:064c79e7311a | 115 | (void)QEP_TRIG_(m_state, QEP_EMPTY_SIG_); |
QL | 0:064c79e7311a | 116 | while (m_state != t) { |
QL | 0:064c79e7311a | 117 | ++ip; |
QL | 0:064c79e7311a | 118 | path[ip] = m_state; |
QL | 0:064c79e7311a | 119 | (void)QEP_TRIG_(m_state, QEP_EMPTY_SIG_); |
QL | 0:064c79e7311a | 120 | } |
QL | 0:064c79e7311a | 121 | m_state = path[0]; |
QL | 0:064c79e7311a | 122 | // entry path must not overflow |
QL | 0:064c79e7311a | 123 | Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_); |
QL | 0:064c79e7311a | 124 | |
QL | 0:064c79e7311a | 125 | do { // retrace the entry path in reverse (desired) order... |
QL | 0:064c79e7311a | 126 | QEP_ENTER_(path[ip]); // enter path[ip] |
QL | 0:064c79e7311a | 127 | --ip; |
QL | 0:064c79e7311a | 128 | } while (ip >= (int8_t)0); |
QL | 0:064c79e7311a | 129 | |
QL | 0:064c79e7311a | 130 | t = path[0]; // current state becomes the new source |
QL | 0:064c79e7311a | 131 | } while (QEP_TRIG_(t, Q_INIT_SIG) == Q_RET_TRAN); |
QL | 0:064c79e7311a | 132 | m_state = t; |
QL | 0:064c79e7311a | 133 | |
QL | 0:064c79e7311a | 134 | QS_BEGIN_(QS_QEP_INIT_TRAN, QS::smObj_, this) |
QL | 0:064c79e7311a | 135 | QS_TIME_(); // time stamp |
QL | 0:064c79e7311a | 136 | QS_OBJ_(this); // this state machine object |
QL | 0:064c79e7311a | 137 | QS_FUN_(m_state); // the new active state |
QL | 0:064c79e7311a | 138 | QS_END_() |
QL | 0:064c79e7311a | 139 | } |
QL | 0:064c79e7311a | 140 | |
QL | 0:064c79e7311a | 141 | // "qhsm_dis.cpp" ============================================================ |
QL | 0:064c79e7311a | 142 | void QHsm::dispatch(QEvent const *e) { |
QL | 0:064c79e7311a | 143 | QStateHandler path[QEP_MAX_NEST_DEPTH_]; |
QL | 0:064c79e7311a | 144 | QStateHandler s; |
QL | 0:064c79e7311a | 145 | QStateHandler t; |
QL | 0:064c79e7311a | 146 | QState r; |
QL | 0:064c79e7311a | 147 | QS_INT_LOCK_KEY_ |
QL | 0:064c79e7311a | 148 | |
QL | 0:064c79e7311a | 149 | t = m_state; // save the current state |
QL | 0:064c79e7311a | 150 | |
QL | 0:064c79e7311a | 151 | QS_BEGIN_(QS_QEP_DISPATCH, QS::smObj_, this) |
QL | 0:064c79e7311a | 152 | QS_TIME_(); // time stamp |
QL | 0:064c79e7311a | 153 | QS_SIG_(e->sig); // the signal of the event |
QL | 0:064c79e7311a | 154 | QS_OBJ_(this); // this state machine object |
QL | 0:064c79e7311a | 155 | QS_FUN_(t); // the current state |
QL | 0:064c79e7311a | 156 | QS_END_() |
QL | 0:064c79e7311a | 157 | |
QL | 0:064c79e7311a | 158 | do { // process the event hierarchically... |
QL | 0:064c79e7311a | 159 | s = m_state; |
QL | 0:064c79e7311a | 160 | r = (*s)(this, e); // invoke state handler s |
QL | 0:064c79e7311a | 161 | } while (r == Q_RET_SUPER); |
QL | 0:064c79e7311a | 162 | |
QL | 0:064c79e7311a | 163 | if (r == Q_RET_TRAN) { // transition taken? |
QL | 0:064c79e7311a | 164 | #ifdef Q_SPY |
QL | 0:064c79e7311a | 165 | QStateHandler src = s; // save the transition source for tracing |
QL | 0:064c79e7311a | 166 | #endif |
QL | 0:064c79e7311a | 167 | int8_t ip = (int8_t)(-1); // transition entry path index |
QL | 0:064c79e7311a | 168 | int8_t iq; // helper transition entry path index |
QL | 0:064c79e7311a | 169 | |
QL | 0:064c79e7311a | 170 | path[0] = m_state; // save the target of the transition |
QL | 0:064c79e7311a | 171 | path[1] = t; |
QL | 0:064c79e7311a | 172 | |
QL | 0:064c79e7311a | 173 | while (t != s) { // exit current state to transition source s... |
QL | 0:064c79e7311a | 174 | if (QEP_TRIG_(t, Q_EXIT_SIG) == Q_RET_HANDLED) { //exit handled? |
QL | 0:064c79e7311a | 175 | QS_BEGIN_(QS_QEP_STATE_EXIT, QS::smObj_, this) |
QL | 0:064c79e7311a | 176 | QS_OBJ_(this); // this state machine object |
QL | 0:064c79e7311a | 177 | QS_FUN_(t); // the exited state |
QL | 0:064c79e7311a | 178 | QS_END_() |
QL | 0:064c79e7311a | 179 | |
QL | 0:064c79e7311a | 180 | (void)QEP_TRIG_(t, QEP_EMPTY_SIG_); // find superstate of t |
QL | 0:064c79e7311a | 181 | } |
QL | 0:064c79e7311a | 182 | t = m_state; // m_state holds the superstate |
QL | 0:064c79e7311a | 183 | } |
QL | 0:064c79e7311a | 184 | |
QL | 0:064c79e7311a | 185 | t = path[0]; // target of the transition |
QL | 0:064c79e7311a | 186 | |
QL | 0:064c79e7311a | 187 | if (s == t) { // (a) check source==target (transition to self) |
QL | 0:064c79e7311a | 188 | QEP_EXIT_(s) // exit the source |
QL | 0:064c79e7311a | 189 | ip = (int8_t)0; // enter the target |
QL | 0:064c79e7311a | 190 | } |
QL | 0:064c79e7311a | 191 | else { |
QL | 0:064c79e7311a | 192 | (void)QEP_TRIG_(t, QEP_EMPTY_SIG_); // superstate of target |
QL | 0:064c79e7311a | 193 | t = m_state; |
QL | 0:064c79e7311a | 194 | if (s == t) { // (b) check source==target->super |
QL | 0:064c79e7311a | 195 | ip = (int8_t)0; // enter the target |
QL | 0:064c79e7311a | 196 | } |
QL | 0:064c79e7311a | 197 | else { |
QL | 0:064c79e7311a | 198 | (void)QEP_TRIG_(s, QEP_EMPTY_SIG_); // superstate of src |
QL | 0:064c79e7311a | 199 | // (c) check source->super==target->super |
QL | 0:064c79e7311a | 200 | if (m_state == t) { |
QL | 0:064c79e7311a | 201 | QEP_EXIT_(s) // exit the source |
QL | 0:064c79e7311a | 202 | ip = (int8_t)0; // enter the target |
QL | 0:064c79e7311a | 203 | } |
QL | 0:064c79e7311a | 204 | else { |
QL | 0:064c79e7311a | 205 | // (d) check source->super==target |
QL | 0:064c79e7311a | 206 | if (m_state == path[0]) { |
QL | 0:064c79e7311a | 207 | QEP_EXIT_(s) // exit the source |
QL | 0:064c79e7311a | 208 | } |
QL | 0:064c79e7311a | 209 | else { // (e) check rest of source==target->super->super.. |
QL | 0:064c79e7311a | 210 | // and store the entry path along the way |
QL | 0:064c79e7311a | 211 | // |
QL | 0:064c79e7311a | 212 | iq = (int8_t)0; // indicate that LCA not found |
QL | 0:064c79e7311a | 213 | ip = (int8_t)1; // enter target and its superstate |
QL | 0:064c79e7311a | 214 | path[1] = t; // save the superstate of target |
QL | 0:064c79e7311a | 215 | t = m_state; // save source->super |
QL | 0:064c79e7311a | 216 | // find target->super->super |
QL | 0:064c79e7311a | 217 | r = QEP_TRIG_(path[1], QEP_EMPTY_SIG_); |
QL | 0:064c79e7311a | 218 | while (r == Q_RET_SUPER) { |
QL | 0:064c79e7311a | 219 | ++ip; |
QL | 0:064c79e7311a | 220 | path[ip] = m_state; // store the entry path |
QL | 0:064c79e7311a | 221 | if (m_state == s) { // is it the source? |
QL | 0:064c79e7311a | 222 | iq = (int8_t)1; // indicate that LCA found |
QL | 0:064c79e7311a | 223 | // entry path must not overflow |
QL | 0:064c79e7311a | 224 | Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_); |
QL | 0:064c79e7311a | 225 | --ip; // do not enter the source |
QL | 0:064c79e7311a | 226 | r = Q_RET_HANDLED; // terminate the loop |
QL | 0:064c79e7311a | 227 | } |
QL | 0:064c79e7311a | 228 | else { // it is not the source, keep going up |
QL | 0:064c79e7311a | 229 | r = QEP_TRIG_(m_state, QEP_EMPTY_SIG_); |
QL | 0:064c79e7311a | 230 | } |
QL | 0:064c79e7311a | 231 | } |
QL | 0:064c79e7311a | 232 | if (iq == (int8_t)0) { // the LCA not found yet? |
QL | 0:064c79e7311a | 233 | |
QL | 0:064c79e7311a | 234 | // entry path must not overflow |
QL | 0:064c79e7311a | 235 | Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_); |
QL | 0:064c79e7311a | 236 | |
QL | 0:064c79e7311a | 237 | QEP_EXIT_(s) // exit the source |
QL | 0:064c79e7311a | 238 | |
QL | 0:064c79e7311a | 239 | // (f) check the rest of source->super |
QL | 0:064c79e7311a | 240 | // == target->super->super... |
QL | 0:064c79e7311a | 241 | // |
QL | 0:064c79e7311a | 242 | iq = ip; |
QL | 0:064c79e7311a | 243 | r = Q_RET_IGNORED; // indicate LCA NOT found |
QL | 0:064c79e7311a | 244 | do { |
QL | 0:064c79e7311a | 245 | if (t == path[iq]) { // is this the LCA? |
QL | 0:064c79e7311a | 246 | r = Q_RET_HANDLED; // indicate LCA found |
QL | 0:064c79e7311a | 247 | ip = (int8_t)(iq - 1); // do not enter LCA |
QL | 0:064c79e7311a | 248 | iq = (int8_t)(-1); // terminate the loop |
QL | 0:064c79e7311a | 249 | } |
QL | 0:064c79e7311a | 250 | else { |
QL | 0:064c79e7311a | 251 | --iq; // try lower superstate of target |
QL | 0:064c79e7311a | 252 | } |
QL | 0:064c79e7311a | 253 | } while (iq >= (int8_t)0); |
QL | 0:064c79e7311a | 254 | |
QL | 0:064c79e7311a | 255 | if (r != Q_RET_HANDLED) { // LCA not found yet? |
QL | 0:064c79e7311a | 256 | // (g) check each source->super->... |
QL | 0:064c79e7311a | 257 | // for each target->super... |
QL | 0:064c79e7311a | 258 | // |
QL | 0:064c79e7311a | 259 | r = Q_RET_IGNORED; // keep looping |
QL | 0:064c79e7311a | 260 | do { |
QL | 0:064c79e7311a | 261 | // exit t unhandled? |
QL | 0:064c79e7311a | 262 | if (QEP_TRIG_(t, Q_EXIT_SIG) |
QL | 0:064c79e7311a | 263 | == Q_RET_HANDLED) |
QL | 0:064c79e7311a | 264 | { |
QL | 0:064c79e7311a | 265 | QS_BEGIN_(QS_QEP_STATE_EXIT, |
QL | 0:064c79e7311a | 266 | QS::smObj_, this) |
QL | 0:064c79e7311a | 267 | QS_OBJ_(this); |
QL | 0:064c79e7311a | 268 | QS_FUN_(t); |
QL | 0:064c79e7311a | 269 | QS_END_() |
QL | 0:064c79e7311a | 270 | |
QL | 0:064c79e7311a | 271 | (void)QEP_TRIG_(t, QEP_EMPTY_SIG_); |
QL | 0:064c79e7311a | 272 | } |
QL | 0:064c79e7311a | 273 | t = m_state; // set to super of t |
QL | 0:064c79e7311a | 274 | iq = ip; |
QL | 0:064c79e7311a | 275 | do { |
QL | 0:064c79e7311a | 276 | if (t == path[iq]) { // is this LCA? |
QL | 0:064c79e7311a | 277 | // do not enter LCA |
QL | 0:064c79e7311a | 278 | ip = (int8_t)(iq - 1); |
QL | 0:064c79e7311a | 279 | iq = (int8_t)(-1); //break inner |
QL | 0:064c79e7311a | 280 | r = Q_RET_HANDLED; //break outer |
QL | 0:064c79e7311a | 281 | } |
QL | 0:064c79e7311a | 282 | else { |
QL | 0:064c79e7311a | 283 | --iq; |
QL | 0:064c79e7311a | 284 | } |
QL | 0:064c79e7311a | 285 | } while (iq >= (int8_t)0); |
QL | 0:064c79e7311a | 286 | } while (r != Q_RET_HANDLED); |
QL | 0:064c79e7311a | 287 | } |
QL | 0:064c79e7311a | 288 | } |
QL | 0:064c79e7311a | 289 | } |
QL | 0:064c79e7311a | 290 | } |
QL | 0:064c79e7311a | 291 | } |
QL | 0:064c79e7311a | 292 | } |
QL | 0:064c79e7311a | 293 | // retrace the entry path in reverse (desired) order... |
QL | 0:064c79e7311a | 294 | for (; ip >= (int8_t)0; --ip) { |
QL | 0:064c79e7311a | 295 | QEP_ENTER_(path[ip]) // enter path[ip] |
QL | 0:064c79e7311a | 296 | } |
QL | 0:064c79e7311a | 297 | t = path[0]; // stick the target into register |
QL | 0:064c79e7311a | 298 | m_state = t; // update the current state |
QL | 0:064c79e7311a | 299 | |
QL | 0:064c79e7311a | 300 | // drill into the target hierarchy... |
QL | 0:064c79e7311a | 301 | while (QEP_TRIG_(t, Q_INIT_SIG) == Q_RET_TRAN) { |
QL | 0:064c79e7311a | 302 | |
QL | 0:064c79e7311a | 303 | QS_BEGIN_(QS_QEP_STATE_INIT, QS::smObj_, this) |
QL | 0:064c79e7311a | 304 | QS_OBJ_(this); // this state machine object |
QL | 0:064c79e7311a | 305 | QS_FUN_(t); // the source (pseudo)state |
QL | 0:064c79e7311a | 306 | QS_FUN_(m_state); // the target of the transition |
QL | 0:064c79e7311a | 307 | QS_END_() |
QL | 0:064c79e7311a | 308 | |
QL | 0:064c79e7311a | 309 | ip = (int8_t)0; |
QL | 0:064c79e7311a | 310 | path[0] = m_state; |
QL | 0:064c79e7311a | 311 | (void)QEP_TRIG_(m_state, QEP_EMPTY_SIG_); // find superstate |
QL | 0:064c79e7311a | 312 | while (m_state != t) { |
QL | 0:064c79e7311a | 313 | ++ip; |
QL | 0:064c79e7311a | 314 | path[ip] = m_state; |
QL | 0:064c79e7311a | 315 | (void)QEP_TRIG_(m_state, QEP_EMPTY_SIG_); // find superstate |
QL | 0:064c79e7311a | 316 | } |
QL | 0:064c79e7311a | 317 | m_state = path[0]; |
QL | 0:064c79e7311a | 318 | // entry path must not overflow |
QL | 0:064c79e7311a | 319 | Q_ASSERT(ip < (int8_t)QEP_MAX_NEST_DEPTH_); |
QL | 0:064c79e7311a | 320 | |
QL | 0:064c79e7311a | 321 | do { // retrace the entry path in reverse (correct) order... |
QL | 0:064c79e7311a | 322 | QEP_ENTER_(path[ip]) // enter path[ip] |
QL | 0:064c79e7311a | 323 | --ip; |
QL | 0:064c79e7311a | 324 | } while (ip >= (int8_t)0); |
QL | 0:064c79e7311a | 325 | |
QL | 0:064c79e7311a | 326 | t = path[0]; |
QL | 0:064c79e7311a | 327 | } |
QL | 0:064c79e7311a | 328 | |
QL | 0:064c79e7311a | 329 | QS_BEGIN_(QS_QEP_TRAN, QS::smObj_, this) |
QL | 0:064c79e7311a | 330 | QS_TIME_(); // time stamp |
QL | 0:064c79e7311a | 331 | QS_SIG_(e->sig); // the signal of the event |
QL | 0:064c79e7311a | 332 | QS_OBJ_(this); // this state machine object |
QL | 0:064c79e7311a | 333 | QS_FUN_(src); // the source of the transition |
QL | 0:064c79e7311a | 334 | QS_FUN_(t); // the new active state |
QL | 0:064c79e7311a | 335 | QS_END_() |
QL | 0:064c79e7311a | 336 | |
QL | 0:064c79e7311a | 337 | } |
QL | 0:064c79e7311a | 338 | else { // transition not taken |
QL | 0:064c79e7311a | 339 | #ifdef Q_SPY |
QL | 0:064c79e7311a | 340 | if (r == Q_RET_IGNORED) { // event ignored? |
QL | 0:064c79e7311a | 341 | |
QL | 0:064c79e7311a | 342 | QS_BEGIN_(QS_QEP_IGNORED, QS::smObj_, this) |
QL | 0:064c79e7311a | 343 | QS_TIME_(); // time stamp |
QL | 0:064c79e7311a | 344 | QS_SIG_(e->sig); // the signal of the event |
QL | 0:064c79e7311a | 345 | QS_OBJ_(this); // this state machine object |
QL | 0:064c79e7311a | 346 | QS_FUN_(t); // the current state |
QL | 0:064c79e7311a | 347 | QS_END_() |
QL | 0:064c79e7311a | 348 | |
QL | 0:064c79e7311a | 349 | } |
QL | 0:064c79e7311a | 350 | else { // event handled |
QL | 0:064c79e7311a | 351 | |
QL | 0:064c79e7311a | 352 | QS_BEGIN_(QS_QEP_INTERN_TRAN, QS::smObj_, this) |
QL | 0:064c79e7311a | 353 | QS_TIME_(); // time stamp |
QL | 0:064c79e7311a | 354 | QS_SIG_(e->sig); // the signal of the event |
QL | 0:064c79e7311a | 355 | QS_OBJ_(this); // this state machine object |
QL | 0:064c79e7311a | 356 | QS_FUN_(s); // the state that handled the event |
QL | 0:064c79e7311a | 357 | QS_END_() |
QL | 0:064c79e7311a | 358 | |
QL | 0:064c79e7311a | 359 | } |
QL | 0:064c79e7311a | 360 | #endif |
QL | 0:064c79e7311a | 361 | } |
QL | 0:064c79e7311a | 362 | m_state = t; // set new state or restore the current state |
QL | 0:064c79e7311a | 363 | } |
QL | 0:064c79e7311a | 364 | |
QL | 0:064c79e7311a | 365 | // "qf_pkg.h" ================================================================ |
QL | 0:064c79e7311a | 366 | // QF-specific interrupt locking/unlocking |
QL | 0:064c79e7311a | 367 | #ifndef QF_INT_KEY_TYPE |
QL | 0:064c79e7311a | 368 | |
QL | 0:064c79e7311a | 369 | /// \brief This is an internal macro for defining the interrupt lock key. |
QL | 0:064c79e7311a | 370 | /// |
QL | 0:064c79e7311a | 371 | /// The purpose of this macro is to enable writing the same code for the |
QL | 0:064c79e7311a | 372 | /// case when interrupt key is defined and when it is not. If the macro |
QL | 0:064c79e7311a | 373 | /// #QF_INT_KEY_TYPE is defined, this internal macro provides the |
QL | 0:064c79e7311a | 374 | /// definition of the lock key variable. Otherwise this macro is empty. |
QL | 0:064c79e7311a | 375 | /// \sa #QF_INT_KEY_TYPE |
QL | 0:064c79e7311a | 376 | #define QF_INT_LOCK_KEY_ |
QL | 0:064c79e7311a | 377 | |
QL | 0:064c79e7311a | 378 | /// \brief This is an internal macro for locking interrupts. |
QL | 0:064c79e7311a | 379 | /// |
QL | 0:064c79e7311a | 380 | /// The purpose of this macro is to enable writing the same code for the |
QL | 0:064c79e7311a | 381 | /// case when interrupt key is defined and when it is not. If the macro |
QL | 0:064c79e7311a | 382 | /// #QF_INT_KEY_TYPE is defined, this internal macro invokes #QF_INT_LOCK |
QL | 0:064c79e7311a | 383 | /// passing the key variable as the parameter. Otherwise #QF_INT_LOCK |
QL | 0:064c79e7311a | 384 | /// is invoked with a dummy parameter. |
QL | 0:064c79e7311a | 385 | /// \sa #QF_INT_LOCK, #QK_INT_LOCK |
QL | 0:064c79e7311a | 386 | #define QF_INT_LOCK_() QF_INT_LOCK(dummy) |
QL | 0:064c79e7311a | 387 | |
QL | 0:064c79e7311a | 388 | /// \brief This is an internal macro for unlocking interrupts. |
QL | 0:064c79e7311a | 389 | /// |
QL | 0:064c79e7311a | 390 | /// The purpose of this macro is to enable writing the same code for the |
QL | 0:064c79e7311a | 391 | /// case when interrupt key is defined and when it is not. If the macro |
QL | 0:064c79e7311a | 392 | /// #QF_INT_KEY_TYPE is defined, this internal macro invokes |
QL | 0:064c79e7311a | 393 | /// #QF_INT_UNLOCK passing the key variable as the parameter. |
QL | 0:064c79e7311a | 394 | /// Otherwise #QF_INT_UNLOCK is invoked with a dummy parameter. |
QL | 0:064c79e7311a | 395 | /// \sa #QF_INT_UNLOCK, #QK_INT_UNLOCK |
QL | 0:064c79e7311a | 396 | #define QF_INT_UNLOCK_() QF_INT_UNLOCK(dummy) |
QL | 0:064c79e7311a | 397 | #else |
QL | 0:064c79e7311a | 398 | #define QF_INT_LOCK_KEY_ QF_INT_KEY_TYPE intLockKey_; |
QL | 0:064c79e7311a | 399 | #define QF_INT_LOCK_() QF_INT_LOCK(intLockKey_) |
QL | 0:064c79e7311a | 400 | #define QF_INT_UNLOCK_() QF_INT_UNLOCK(intLockKey_) |
QL | 0:064c79e7311a | 401 | #endif |
QL | 0:064c79e7311a | 402 | |
QL | 0:064c79e7311a | 403 | // package-scope objects ----------------------------------------------------- |
QL | 0:064c79e7311a | 404 | extern QTimeEvt *QF_timeEvtListHead_; ///< head of linked list of time events |
QL | 0:064c79e7311a | 405 | extern QF_EPOOL_TYPE_ QF_pool_[3]; ///< allocate 3 event pools |
QL | 0:064c79e7311a | 406 | extern uint8_t QF_maxPool_; ///< # of initialized event pools |
QL | 0:064c79e7311a | 407 | extern QSubscrList *QF_subscrList_; ///< the subscriber list array |
QL | 0:064c79e7311a | 408 | extern QSignal QF_maxSignal_; ///< the maximum published signal |
QL | 0:064c79e7311a | 409 | |
QL | 0:064c79e7311a | 410 | //............................................................................ |
QL | 0:064c79e7311a | 411 | /// \brief Structure representing a free block in the Native QF Memory Pool |
QL | 0:064c79e7311a | 412 | /// \sa ::QMPool |
QL | 0:064c79e7311a | 413 | struct QFreeBlock { |
QL | 0:064c79e7311a | 414 | QFreeBlock *m_next; |
QL | 0:064c79e7311a | 415 | }; |
QL | 0:064c79e7311a | 416 | |
QL | 0:064c79e7311a | 417 | // "qa_defer.cpp" ============================================================ |
QL | 0:064c79e7311a | 418 | void QActive::defer(QEQueue *eq, QEvent const *e) { |
QL | 0:064c79e7311a | 419 | eq->postFIFO(e); |
QL | 0:064c79e7311a | 420 | } |
QL | 0:064c79e7311a | 421 | //............................................................................ |
QL | 0:064c79e7311a | 422 | QEvent const *QActive::recall(QEQueue *eq) { |
QL | 0:064c79e7311a | 423 | QEvent const *e = eq->get(); // try to get an event from deferred queue |
QL | 0:064c79e7311a | 424 | if (e != (QEvent *)0) { // event available? |
QL | 0:064c79e7311a | 425 | |
QL | 0:064c79e7311a | 426 | postLIFO(e); // post it to the front of the Active Object's queue |
QL | 0:064c79e7311a | 427 | |
QL | 0:064c79e7311a | 428 | QF_INT_LOCK_KEY_ |
QL | 0:064c79e7311a | 429 | QF_INT_LOCK_(); |
QL | 0:064c79e7311a | 430 | |
QL | 0:064c79e7311a | 431 | if (e->dynamic_ != (uint8_t)0) { // is it a dynamic event? |
QL | 0:064c79e7311a | 432 | |
QL | 0:064c79e7311a | 433 | // after posting to the AO's queue the event must be referenced |
QL | 0:064c79e7311a | 434 | // at least twice: once in the deferred event queue (eq->get() |
QL | 0:064c79e7311a | 435 | // did NOT decrement the reference counter) and once in the |
QL | 0:064c79e7311a | 436 | // AO's event queue. |
QL | 0:064c79e7311a | 437 | Q_ASSERT((e->dynamic_ & 0x3F) > 1); |
QL | 0:064c79e7311a | 438 | |
QL | 0:064c79e7311a | 439 | // we need to decrement the reference counter once, to account |
QL | 0:064c79e7311a | 440 | // for removing the event from the deferred event queue. |
QL | 0:064c79e7311a | 441 | // |
QL | 0:064c79e7311a | 442 | //lint -e1773 Attempt to cast away const |
QL | 0:064c79e7311a | 443 | --((QEvent *)e)->dynamic_; // decrement the reference counter |
QL | 0:064c79e7311a | 444 | // NOTE: cast the 'const' away, which is legitimate because |
QL | 0:064c79e7311a | 445 | // it's a dynamic event |
QL | 0:064c79e7311a | 446 | } |
QL | 0:064c79e7311a | 447 | |
QL | 0:064c79e7311a | 448 | QF_INT_UNLOCK_(); |
QL | 0:064c79e7311a | 449 | |
QL | 0:064c79e7311a | 450 | } |
QL | 0:064c79e7311a | 451 | return e; // pass the recalled event to the caller (NULL if not recalled) |
QL | 0:064c79e7311a | 452 | } |
QL | 0:064c79e7311a | 453 | |
QL | 0:064c79e7311a | 454 | // "qa_fifo.cpp" ============================================================= |
QL | 0:064c79e7311a | 455 | void QActive::postFIFO(QEvent const *e) { |
QL | 0:064c79e7311a | 456 | QF_INT_LOCK_KEY_ |
QL | 0:064c79e7311a | 457 | QF_INT_LOCK_(); |
QL | 0:064c79e7311a | 458 | |
QL | 0:064c79e7311a | 459 | QS_BEGIN_NOLOCK_(QS_QF_ACTIVE_POST_FIFO, QS::aoObj_, this) |
QL | 0:064c79e7311a | 460 | QS_TIME_(); // timestamp |
QL | 0:064c79e7311a | 461 | QS_SIG_(e->sig); // the signal of the event |
QL | 0:064c79e7311a | 462 | QS_OBJ_(this); // this active object |
QL | 0:064c79e7311a | 463 | QS_U8_(e->dynamic_); // the QF attribute of the event |
QL | 0:064c79e7311a | 464 | QS_EQC_(m_eQueue.m_nFree); // number of free entries |
QL | 0:064c79e7311a | 465 | QS_EQC_(m_eQueue.m_nMin); // min number of free entries |
QL | 0:064c79e7311a | 466 | QS_END_NOLOCK_() |
QL | 0:064c79e7311a | 467 | |
QL | 0:064c79e7311a | 468 | if (e->dynamic_ != (uint8_t)0) { // is it a dynamic event? |
QL | 0:064c79e7311a | 469 | //lint -e1773 Attempt to cast away const |
QL | 0:064c79e7311a | 470 | ++((QEvent *)e)->dynamic_; // increment the reference counter |
QL | 0:064c79e7311a | 471 | // NOTE: cast the 'const' away, which is legitimate because |
QL | 0:064c79e7311a | 472 | // it's a dynamic event |
QL | 0:064c79e7311a | 473 | } |
QL | 0:064c79e7311a | 474 | |
QL | 0:064c79e7311a | 475 | if (m_eQueue.m_frontEvt == (QEvent *)0) { // is the queue empty? |
QL | 0:064c79e7311a | 476 | m_eQueue.m_frontEvt = e; // deliver event directly |
QL | 0:064c79e7311a | 477 | QACTIVE_EQUEUE_SIGNAL_(this); // signal the event queue |
QL | 0:064c79e7311a | 478 | } |
QL | 0:064c79e7311a | 479 | else { // queue is not empty, leave event in the ring-buffer |
QL | 0:064c79e7311a | 480 | // queue must accept all posted events |
QL | 0:064c79e7311a | 481 | Q_ASSERT(m_eQueue.m_nFree != (QEQueueCtr)0); |
QL | 0:064c79e7311a | 482 | m_eQueue.m_ring[m_eQueue.m_head] = e;//insert e into the buffer (FIFO) |
QL | 0:064c79e7311a | 483 | if (m_eQueue.m_head == (QEQueueCtr)0) { // need to wrap the head? |
QL | 0:064c79e7311a | 484 | m_eQueue.m_head = m_eQueue.m_end; // wrap around |
QL | 0:064c79e7311a | 485 | } |
QL | 0:064c79e7311a | 486 | --m_eQueue.m_head; |
QL | 0:064c79e7311a | 487 | |
QL | 0:064c79e7311a | 488 | --m_eQueue.m_nFree; // update number of free events |
QL | 0:064c79e7311a | 489 | if (m_eQueue.m_nMin > m_eQueue.m_nFree) { |
QL | 0:064c79e7311a | 490 | m_eQueue.m_nMin = m_eQueue.m_nFree; // update minimum so far |
QL | 0:064c79e7311a | 491 | } |
QL | 0:064c79e7311a | 492 | } |
QL | 0:064c79e7311a | 493 | QF_INT_UNLOCK_(); |
QL | 0:064c79e7311a | 494 | } |
QL | 0:064c79e7311a | 495 | |
QL | 0:064c79e7311a | 496 | // "qa_get_.cpp" ============================================================= |
QL | 0:064c79e7311a | 497 | QEvent const *QActive::get_(void) { |
QL | 0:064c79e7311a | 498 | QF_INT_LOCK_KEY_ |
QL | 0:064c79e7311a | 499 | QF_INT_LOCK_(); |
QL | 0:064c79e7311a | 500 | |
QL | 0:064c79e7311a | 501 | QACTIVE_EQUEUE_WAIT_(this); // wait for event to arrive directly |
QL | 0:064c79e7311a | 502 | |
QL | 0:064c79e7311a | 503 | QEvent const *e = m_eQueue.m_frontEvt; |
QL | 0:064c79e7311a | 504 | |
QL | 0:064c79e7311a | 505 | if (m_eQueue.m_nFree != m_eQueue.m_end) { //any events in the ring buffer? |
QL | 0:064c79e7311a | 506 | // remove event from the tail |
QL | 0:064c79e7311a | 507 | m_eQueue.m_frontEvt = m_eQueue.m_ring[m_eQueue.m_tail]; |
QL | 0:064c79e7311a | 508 | if (m_eQueue.m_tail == (QEQueueCtr)0) { // need to wrap the tail? |
QL | 0:064c79e7311a | 509 | m_eQueue.m_tail = m_eQueue.m_end; // wrap around |
QL | 0:064c79e7311a | 510 | } |
QL | 0:064c79e7311a | 511 | --m_eQueue.m_tail; |
QL | 0:064c79e7311a | 512 | |
QL | 0:064c79e7311a | 513 | ++m_eQueue.m_nFree; // one more free event in the ring buffer |
QL | 0:064c79e7311a | 514 | |
QL | 0:064c79e7311a | 515 | QS_BEGIN_NOLOCK_(QS_QF_ACTIVE_GET, QS::aoObj_, this) |
QL | 0:064c79e7311a | 516 | QS_TIME_(); // timestamp |
QL | 0:064c79e7311a | 517 | QS_SIG_(e->sig); // the signal of this event |
QL | 0:064c79e7311a | 518 | QS_OBJ_(this); // this active object |
QL | 0:064c79e7311a | 519 | QS_U8_(e->dynamic_); // the dynamic attributes of the event |
QL | 0:064c79e7311a | 520 | QS_EQC_(m_eQueue.m_nFree); // number of free entries |
QL | 0:064c79e7311a | 521 | QS_END_NOLOCK_() |
QL | 0:064c79e7311a | 522 | } |
QL | 0:064c79e7311a | 523 | else { |
QL | 0:064c79e7311a | 524 | m_eQueue.m_frontEvt = (QEvent *)0; // the queue becomes empty |
QL | 0:064c79e7311a | 525 | QACTIVE_EQUEUE_ONEMPTY_(this); |
QL | 0:064c79e7311a | 526 | |
QL | 0:064c79e7311a | 527 | QS_BEGIN_NOLOCK_(QS_QF_ACTIVE_GET_LAST, QS::aoObj_, this) |
QL | 0:064c79e7311a | 528 | QS_TIME_(); // timestamp |
QL | 0:064c79e7311a | 529 | QS_SIG_(e->sig); // the signal of this event |
QL | 0:064c79e7311a | 530 | QS_OBJ_(this); // this active object |
QL | 0:064c79e7311a | 531 | QS_U8_(e->dynamic_); // the dynamic attributes of the event |
QL | 0:064c79e7311a | 532 | QS_END_NOLOCK_() |
QL | 0:064c79e7311a | 533 | } |
QL | 0:064c79e7311a | 534 | QF_INT_UNLOCK_(); |
QL | 0:064c79e7311a | 535 | return e; |
QL | 0:064c79e7311a | 536 | } |
QL | 0:064c79e7311a | 537 | //............................................................................ |
QL | 0:064c79e7311a | 538 | uint32_t QF::getQueueMargin(uint8_t prio) { |
QL | 0:064c79e7311a | 539 | Q_REQUIRE((prio <= (uint8_t)QF_MAX_ACTIVE) |
QL | 0:064c79e7311a | 540 | && (active_[prio] != (QActive *)0)); |
QL | 0:064c79e7311a | 541 | |
QL | 0:064c79e7311a | 542 | QF_INT_LOCK_KEY_ |
QL | 0:064c79e7311a | 543 | QF_INT_LOCK_(); |
QL | 0:064c79e7311a | 544 | uint32_t margin = (uint32_t)(active_[prio]->m_eQueue.m_nMin); |
QL | 0:064c79e7311a | 545 | QF_INT_UNLOCK_(); |
QL | 0:064c79e7311a | 546 | |
QL | 0:064c79e7311a | 547 | return margin; |
QL | 0:064c79e7311a | 548 | } |
QL | 0:064c79e7311a | 549 | |
QL | 0:064c79e7311a | 550 | // "qa_lifo.cpp" ============================================================= |
QL | 0:064c79e7311a | 551 | void QActive::postLIFO(QEvent const *e) { |
QL | 0:064c79e7311a | 552 | QF_INT_LOCK_KEY_ |
QL | 0:064c79e7311a | 553 | QF_INT_LOCK_(); |
QL | 0:064c79e7311a | 554 | |
QL | 0:064c79e7311a | 555 | QS_BEGIN_NOLOCK_(QS_QF_ACTIVE_POST_LIFO, QS::aoObj_, this) |
QL | 0:064c79e7311a | 556 | QS_TIME_(); // timestamp |
QL | 0:064c79e7311a | 557 | QS_SIG_(e->sig); // the signal of this event |
QL | 0:064c79e7311a | 558 | QS_OBJ_(this); // this active object |
QL | 0:064c79e7311a | 559 | QS_U8_(e->dynamic_); // the dynamic attributes of the event |
QL | 0:064c79e7311a | 560 | QS_EQC_(m_eQueue.m_nFree); // number of free entries |
QL | 0:064c79e7311a | 561 | QS_EQC_(m_eQueue.m_nMin); // min number of free entries |
QL | 0:064c79e7311a | 562 | QS_END_NOLOCK_() |
QL | 0:064c79e7311a | 563 | |
QL | 0:064c79e7311a | 564 | if (e->dynamic_ != (uint8_t)0) { // is it a pool event? |
QL | 0:064c79e7311a | 565 | //lint -e1773 Attempt to cast away const |
QL | 0:064c79e7311a | 566 | ++((QEvent *)e)->dynamic_; // increment the reference counter |
QL | 0:064c79e7311a | 567 | // NOTE: cast the 'const' away, which is legitimate because |
QL | 0:064c79e7311a | 568 | // it's a dynamic event |
QL | 0:064c79e7311a | 569 | } |
QL | 0:064c79e7311a | 570 | |
QL | 0:064c79e7311a | 571 | if (m_eQueue.m_frontEvt == (QEvent *)0) { // is the queue empty? |
QL | 0:064c79e7311a | 572 | m_eQueue.m_frontEvt = e; // deliver event directly |
QL | 0:064c79e7311a | 573 | QACTIVE_EQUEUE_SIGNAL_(this); // signal the event queue |
QL | 0:064c79e7311a | 574 | } |
QL | 0:064c79e7311a | 575 | else { // queue is not empty, leave event in the ring-buffer |
QL | 0:064c79e7311a | 576 | // queue must accept all posted events |
QL | 0:064c79e7311a | 577 | Q_ASSERT(m_eQueue.m_nFree != (QEQueueCtr)0); |
QL | 0:064c79e7311a | 578 | |
QL | 0:064c79e7311a | 579 | ++m_eQueue.m_tail; |
QL | 0:064c79e7311a | 580 | if (m_eQueue.m_tail == m_eQueue.m_end) { // need to wrap the tail? |
QL | 0:064c79e7311a | 581 | m_eQueue.m_tail = (QEQueueCtr)0; // wrap around |
QL | 0:064c79e7311a | 582 | } |
QL | 0:064c79e7311a | 583 | |
QL | 0:064c79e7311a | 584 | m_eQueue.m_ring[m_eQueue.m_tail] = m_eQueue.m_frontEvt; |
QL | 0:064c79e7311a | 585 | m_eQueue.m_frontEvt = e; // put event to front |
QL | 0:064c79e7311a | 586 | |
QL | 0:064c79e7311a | 587 | --m_eQueue.m_nFree; // update number of free events |
QL | 0:064c79e7311a | 588 | if (m_eQueue.m_nMin > m_eQueue.m_nFree) { |
QL | 0:064c79e7311a | 589 | m_eQueue.m_nMin = m_eQueue.m_nFree; // update minimum so far |
QL | 0:064c79e7311a | 590 | } |
QL | 0:064c79e7311a | 591 | } |
QL | 0:064c79e7311a | 592 | QF_INT_UNLOCK_(); |
QL | 0:064c79e7311a | 593 | } |
QL | 0:064c79e7311a | 594 | |
QL | 0:064c79e7311a | 595 | // "qa_sub.cpp" ============================================================== |
QL | 0:064c79e7311a | 596 | void QActive::subscribe(QSignal sig) const { |
QL | 0:064c79e7311a | 597 | uint8_t p = m_prio; |
QL | 0:064c79e7311a | 598 | Q_REQUIRE(((QSignal)Q_USER_SIG <= sig) |
QL | 0:064c79e7311a | 599 | && (sig < QF_maxSignal_) |
QL | 0:064c79e7311a | 600 | && ((uint8_t)0 < p) && (p <= (uint8_t)QF_MAX_ACTIVE) |
QL | 0:064c79e7311a | 601 | && (QF::active_[p] == this)); |
QL | 0:064c79e7311a | 602 | |
QL | 0:064c79e7311a | 603 | uint8_t i = Q_ROM_BYTE(QF_div8Lkup[p]); |
QL | 0:064c79e7311a | 604 | |
QL | 0:064c79e7311a | 605 | QF_INT_LOCK_KEY_ |
QL | 0:064c79e7311a | 606 | QF_INT_LOCK_(); |
QL | 0:064c79e7311a | 607 | |
QL | 0:064c79e7311a | 608 | QS_BEGIN_NOLOCK_(QS_QF_ACTIVE_SUBSCRIBE, QS::aoObj_, this) |
QL | 0:064c79e7311a | 609 | QS_TIME_(); // timestamp |
QL | 0:064c79e7311a | 610 | QS_SIG_(sig); // the signal of this event |
QL | 0:064c79e7311a | 611 | QS_OBJ_(this); // this active object |
QL | 0:064c79e7311a | 612 | QS_END_NOLOCK_() |
QL | 0:064c79e7311a | 613 | // set the priority bit |
QL | 0:064c79e7311a | 614 | QF_subscrList_[sig].m_bits[i] |= Q_ROM_BYTE(QF_pwr2Lkup[p]); |
QL | 0:064c79e7311a | 615 | QF_INT_UNLOCK_(); |
QL | 0:064c79e7311a | 616 | } |
QL | 0:064c79e7311a | 617 | |
QL | 0:064c79e7311a | 618 | // "qa_usub.cpp" ============================================================= |
QL | 0:064c79e7311a | 619 | void QActive::unsubscribe(QSignal sig) const { |
QL | 0:064c79e7311a | 620 | uint8_t p = m_prio; |
QL | 0:064c79e7311a | 621 | Q_REQUIRE(((QSignal)Q_USER_SIG <= sig) |
QL | 0:064c79e7311a | 622 | && (sig < QF_maxSignal_) |
QL | 0:064c79e7311a | 623 | && ((uint8_t)0 < p) && (p <= (uint8_t)QF_MAX_ACTIVE) |
QL | 0:064c79e7311a | 624 | && (QF::active_[p] == this)); |
QL | 0:064c79e7311a | 625 | |
QL | 0:064c79e7311a | 626 | uint8_t i = Q_ROM_BYTE(QF_div8Lkup[p]); |
QL | 0:064c79e7311a | 627 | |
QL | 0:064c79e7311a | 628 | QF_INT_LOCK_KEY_ |
QL | 0:064c79e7311a | 629 | QF_INT_LOCK_(); |
QL | 0:064c79e7311a | 630 | |
QL | 0:064c79e7311a | 631 | QS_BEGIN_NOLOCK_(QS_QF_ACTIVE_UNSUBSCRIBE, QS::aoObj_, this) |
QL | 0:064c79e7311a | 632 | QS_TIME_(); // timestamp |
QL | 0:064c79e7311a | 633 | QS_SIG_(sig); // the signal of this event |
QL | 0:064c79e7311a | 634 | QS_OBJ_(this); // this active object |
QL | 0:064c79e7311a | 635 | QS_END_NOLOCK_() |
QL | 0:064c79e7311a | 636 | // clear the priority bit |
QL | 0:064c79e7311a | 637 | QF_subscrList_[sig].m_bits[i] &= Q_ROM_BYTE(QF_invPwr2Lkup[p]); |
QL | 0:064c79e7311a | 638 | QF_INT_UNLOCK_(); |
QL | 0:064c79e7311a | 639 | } |
QL | 0:064c79e7311a | 640 | |
QL | 0:064c79e7311a | 641 | // "qa_usuba.cpp" ============================================================ |
QL | 0:064c79e7311a | 642 | void QActive::unsubscribeAll(void) const { |
QL | 0:064c79e7311a | 643 | uint8_t p = m_prio; |
QL | 0:064c79e7311a | 644 | Q_REQUIRE(((uint8_t)0 < p) && (p <= (uint8_t)QF_MAX_ACTIVE) |
QL | 0:064c79e7311a | 645 | && (QF::active_[p] == this)); |
QL | 0:064c79e7311a | 646 | |
QL | 0:064c79e7311a | 647 | uint8_t i = Q_ROM_BYTE(QF_div8Lkup[p]); |
QL | 0:064c79e7311a | 648 | |
QL | 0:064c79e7311a | 649 | QSignal sig; |
QL | 0:064c79e7311a | 650 | for (sig = (QSignal)Q_USER_SIG; sig < QF_maxSignal_; ++sig) { |
QL | 0:064c79e7311a | 651 | QF_INT_LOCK_KEY_ |
QL | 0:064c79e7311a | 652 | QF_INT_LOCK_(); |
QL | 0:064c79e7311a | 653 | if ((QF_subscrList_[sig].m_bits[i] & Q_ROM_BYTE(QF_pwr2Lkup[p])) |
QL | 0:064c79e7311a | 654 | != 0) |
QL | 0:064c79e7311a | 655 | { |
QL | 0:064c79e7311a | 656 | |
QL | 0:064c79e7311a | 657 | QS_BEGIN_NOLOCK_(QS_QF_ACTIVE_UNSUBSCRIBE, QS::aoObj_, this) |
QL | 0:064c79e7311a | 658 | QS_TIME_(); // timestamp |
QL | 0:064c79e7311a | 659 | QS_SIG_(sig); // the signal of this event |
QL | 0:064c79e7311a | 660 | QS_OBJ_(this); // this active object |
QL | 0:064c79e7311a | 661 | QS_END_NOLOCK_() |
QL | 0:064c79e7311a | 662 | // clear the priority bit |
QL | 0:064c79e7311a | 663 | QF_subscrList_[sig].m_bits[i] &= Q_ROM_BYTE(QF_invPwr2Lkup[p]); |
QL | 0:064c79e7311a | 664 | } |
QL | 0:064c79e7311a | 665 | QF_INT_UNLOCK_(); |
QL | 0:064c79e7311a | 666 | } |
QL | 0:064c79e7311a | 667 | } |
QL | 0:064c79e7311a | 668 | |
QL | 0:064c79e7311a | 669 | // "qeq_fifo.cpp" ============================================================ |
QL | 0:064c79e7311a | 670 | void QEQueue::postFIFO(QEvent const *e) { |
QL | 0:064c79e7311a | 671 | QF_INT_LOCK_KEY_ |
QL | 0:064c79e7311a | 672 | QF_INT_LOCK_(); |
QL | 0:064c79e7311a | 673 | |
QL | 0:064c79e7311a | 674 | QS_BEGIN_NOLOCK_(QS_QF_EQUEUE_POST_FIFO, QS::eqObj_, this) |
QL | 0:064c79e7311a | 675 | QS_TIME_(); // timestamp |
QL | 0:064c79e7311a | 676 | QS_SIG_(e->sig); // the signal of this event |
QL | 0:064c79e7311a | 677 | QS_OBJ_(this); // this queue object |
QL | 0:064c79e7311a | 678 | QS_U8_(e->dynamic_); // the dynamic attributes of the event |
QL | 0:064c79e7311a | 679 | QS_EQC_(m_nFree); // number of free entries |
QL | 0:064c79e7311a | 680 | QS_EQC_(m_nMin); // min number of free entries |
QL | 0:064c79e7311a | 681 | QS_END_NOLOCK_() |
QL | 0:064c79e7311a | 682 | |
QL | 0:064c79e7311a | 683 | if (e->dynamic_ != (uint8_t)0) { // is it a pool event? |
QL | 0:064c79e7311a | 684 | //lint -e1773 Attempt to cast away const |
QL | 0:064c79e7311a | 685 | ++((QEvent *)e)->dynamic_; // increment the reference counter |
QL | 0:064c79e7311a | 686 | // NOTE: cast the 'const' away, which is legitimate because |
QL | 0:064c79e7311a | 687 | // it's a dynamic event |
QL | 0:064c79e7311a | 688 | } |
QL | 0:064c79e7311a | 689 | |
QL | 0:064c79e7311a | 690 | if (m_frontEvt == (QEvent *)0) { // is the queue empty? |
QL | 0:064c79e7311a | 691 | m_frontEvt = e; // deliver event directly |
QL | 0:064c79e7311a | 692 | } |
QL | 0:064c79e7311a | 693 | else { // queue is not empty, leave event in the ring-buffer |
QL | 0:064c79e7311a | 694 | // the queue must be able to accept the event (cannot overflow) |
QL | 0:064c79e7311a | 695 | Q_ASSERT(m_nFree != (QEQueueCtr)0); |
QL | 0:064c79e7311a | 696 | |
QL | 0:064c79e7311a | 697 | m_ring[m_head] = e; // insert event into the buffer (FIFO) |
QL | 0:064c79e7311a | 698 | if (m_head == (QEQueueCtr)0) { // need to wrap the head? |
QL | 0:064c79e7311a | 699 | m_head = m_end; // wrap around |
QL | 0:064c79e7311a | 700 | } |
QL | 0:064c79e7311a | 701 | --m_head; |
QL | 0:064c79e7311a | 702 | |
QL | 0:064c79e7311a | 703 | --m_nFree; // update number of free events |
QL | 0:064c79e7311a | 704 | if (m_nMin > m_nFree) { |
QL | 0:064c79e7311a | 705 | m_nMin = m_nFree; // update minimum so far |
QL | 0:064c79e7311a | 706 | } |
QL | 0:064c79e7311a | 707 | } |
QL | 0:064c79e7311a | 708 | QF_INT_UNLOCK_(); |
QL | 0:064c79e7311a | 709 | } |
QL | 0:064c79e7311a | 710 | |
QL | 0:064c79e7311a | 711 | // "qeq_get.cpp" ============================================================= |
QL | 0:064c79e7311a | 712 | QEvent const *QEQueue::get(void) { |
QL | 0:064c79e7311a | 713 | QEvent const *e; |
QL | 0:064c79e7311a | 714 | QF_INT_LOCK_KEY_ |
QL | 0:064c79e7311a | 715 | |
QL | 0:064c79e7311a | 716 | QF_INT_LOCK_(); |
QL | 0:064c79e7311a | 717 | if (m_frontEvt == (QEvent *)0) { // is the queue empty? |
QL | 0:064c79e7311a | 718 | e = (QEvent *)0; // no event available at this time |
QL | 0:064c79e7311a | 719 | } |
QL | 0:064c79e7311a | 720 | else { |
QL | 0:064c79e7311a | 721 | e = m_frontEvt; |
QL | 0:064c79e7311a | 722 | |
QL | 0:064c79e7311a | 723 | if (m_nFree != m_end) { // any events in the the ring buffer? |
QL | 0:064c79e7311a | 724 | m_frontEvt = m_ring[m_tail]; // remove event from the tail |
QL | 0:064c79e7311a | 725 | if (m_tail == (QEQueueCtr)0) { // need to wrap the tail? |
QL | 0:064c79e7311a | 726 | m_tail = m_end; // wrap around |
QL | 0:064c79e7311a | 727 | } |
QL | 0:064c79e7311a | 728 | --m_tail; |
QL | 0:064c79e7311a | 729 | |
QL | 0:064c79e7311a | 730 | ++m_nFree; // one more free event in the ring buffer |
QL | 0:064c79e7311a | 731 | |
QL | 0:064c79e7311a | 732 | QS_BEGIN_NOLOCK_(QS_QF_EQUEUE_GET, QS::eqObj_, this) |
QL | 0:064c79e7311a | 733 | QS_TIME_(); // timestamp |
QL | 0:064c79e7311a | 734 | QS_SIG_(e->sig); // the signal of this event |
QL | 0:064c79e7311a | 735 | QS_OBJ_(this); // this queue object |
QL | 0:064c79e7311a | 736 | QS_U8_(e->dynamic_); // the dynamic attributes of the event |
QL | 0:064c79e7311a | 737 | QS_EQC_(m_nFree); // number of free entries |
QL | 0:064c79e7311a | 738 | QS_END_NOLOCK_() |
QL | 0:064c79e7311a | 739 | } |
QL | 0:064c79e7311a | 740 | else { |
QL | 0:064c79e7311a | 741 | m_frontEvt = (QEvent *)0; // the queue becomes empty |
QL | 0:064c79e7311a | 742 | |
QL | 0:064c79e7311a | 743 | QS_BEGIN_NOLOCK_(QS_QF_EQUEUE_GET_LAST, QS::eqObj_, this) |
QL | 0:064c79e7311a | 744 | QS_TIME_(); // timestamp |
QL | 0:064c79e7311a | 745 | QS_SIG_(e->sig); // the signal of this event |
QL | 0:064c79e7311a | 746 | QS_OBJ_(this); // this queue object |
QL | 0:064c79e7311a | 747 | QS_U8_(e->dynamic_); // the dynamic attribute of the event |
QL | 0:064c79e7311a | 748 | QS_END_NOLOCK_() |
QL | 0:064c79e7311a | 749 | } |
QL | 0:064c79e7311a | 750 | } |
QL | 0:064c79e7311a | 751 | QF_INT_UNLOCK_(); |
QL | 0:064c79e7311a | 752 | return e; |
QL | 0:064c79e7311a | 753 | } |
QL | 0:064c79e7311a | 754 | |
QL | 0:064c79e7311a | 755 | // "qeq_init.cpp" ============================================================ |
QL | 0:064c79e7311a | 756 | void QEQueue::init(QEvent const *qSto[], QEQueueCtr qLen) { |
QL | 0:064c79e7311a | 757 | m_frontEvt = (QEvent *)0; // no events in the queue |
QL | 0:064c79e7311a | 758 | m_ring = &qSto[0]; |
QL | 0:064c79e7311a | 759 | m_end = qLen; |
QL | 0:064c79e7311a | 760 | m_head = (QEQueueCtr)0; |
QL | 0:064c79e7311a | 761 | m_tail = (QEQueueCtr)0; |
QL | 0:064c79e7311a | 762 | m_nFree = qLen; |
QL | 0:064c79e7311a | 763 | m_nMin = qLen; |
QL | 0:064c79e7311a | 764 | |
QL | 0:064c79e7311a | 765 | QS_INT_LOCK_KEY_ |
QL | 0:064c79e7311a | 766 | QS_BEGIN_(QS_QF_EQUEUE_INIT, QS::eqObj_, this) |
QL | 0:064c79e7311a | 767 | QS_OBJ_(qSto); // this QEQueue object |
QL | 0:064c79e7311a | 768 | QS_EQC_(qLen); // the length of the queue |
QL | 0:064c79e7311a | 769 | QS_END_() |
QL | 0:064c79e7311a | 770 | } |
QL | 0:064c79e7311a | 771 | |
QL | 0:064c79e7311a | 772 | // "qeq_lifo.cpp" ============================================================ |
QL | 0:064c79e7311a | 773 | void QEQueue::postLIFO(QEvent const *e) { |
QL | 0:064c79e7311a | 774 | QF_INT_LOCK_KEY_ |
QL | 0:064c79e7311a | 775 | QF_INT_LOCK_(); |
QL | 0:064c79e7311a | 776 | |
QL | 0:064c79e7311a | 777 | QS_BEGIN_NOLOCK_(QS_QF_EQUEUE_POST_LIFO, QS::eqObj_, this) |
QL | 0:064c79e7311a | 778 | QS_TIME_(); // timestamp |
QL | 0:064c79e7311a | 779 | QS_SIG_(e->sig); // the signal of this event |
QL | 0:064c79e7311a | 780 | QS_OBJ_(this); // this queue object |
QL | 0:064c79e7311a | 781 | QS_U8_(e->dynamic_); // the dynamic attribute of the event |
QL | 0:064c79e7311a | 782 | QS_EQC_(m_nFree); // number of free entries |
QL | 0:064c79e7311a | 783 | QS_EQC_(m_nMin); // min number of free entries |
QL | 0:064c79e7311a | 784 | QS_END_NOLOCK_() |
QL | 0:064c79e7311a | 785 | |
QL | 0:064c79e7311a | 786 | if (e->dynamic_ != (uint8_t)0) { // is it a dynamic event? |
QL | 0:064c79e7311a | 787 | //lint -e1773 Attempt to cast away const |
QL | 0:064c79e7311a | 788 | ++((QEvent *)e)->dynamic_; // increment the reference counter |
QL | 0:064c79e7311a | 789 | // NOTE: cast the 'const' away, which is legitimate because |
QL | 0:064c79e7311a | 790 | // it's a dynamic event |
QL | 0:064c79e7311a | 791 | } |
QL | 0:064c79e7311a | 792 | |
QL | 0:064c79e7311a | 793 | if (m_frontEvt != (QEvent *)0) { // is the queue not empty? |
QL | 0:064c79e7311a | 794 | // the queue must be able to accept the event (cannot overflow) |
QL | 0:064c79e7311a | 795 | Q_ASSERT(m_nFree != (QEQueueCtr)0); |
QL | 0:064c79e7311a | 796 | |
QL | 0:064c79e7311a | 797 | ++m_tail; |
QL | 0:064c79e7311a | 798 | if (m_tail == m_end) { // need to wrap the tail? |
QL | 0:064c79e7311a | 799 | m_tail = (QEQueueCtr)0; // wrap around |
QL | 0:064c79e7311a | 800 | } |
QL | 0:064c79e7311a | 801 | |
QL | 0:064c79e7311a | 802 | m_ring[m_tail] = m_frontEvt; // buffer the old front evt |
QL | 0:064c79e7311a | 803 | |
QL | 0:064c79e7311a | 804 | --m_nFree; // update number of free events |
QL | 0:064c79e7311a | 805 | if (m_nMin > m_nFree) { |
QL | 0:064c79e7311a | 806 | m_nMin = m_nFree; // update minimum so far |
QL | 0:064c79e7311a | 807 | } |
QL | 0:064c79e7311a | 808 | } |
QL | 0:064c79e7311a | 809 | |
QL | 0:064c79e7311a | 810 | m_frontEvt = e; // stick the new event to the front |
QL | 0:064c79e7311a | 811 | |
QL | 0:064c79e7311a | 812 | QF_INT_UNLOCK_(); |
QL | 0:064c79e7311a | 813 | } |
QL | 0:064c79e7311a | 814 | |
QL | 0:064c79e7311a | 815 | // "qf_act.cpp" ============================================================== |
QL | 0:064c79e7311a | 816 | // public objects ------------------------------------------------------------ |
QL | 0:064c79e7311a | 817 | QActive *QF::active_[QF_MAX_ACTIVE + 1]; // to be used by QF ports only |
QL | 0:064c79e7311a | 818 | uint8_t QF_intLockNest_; // interrupt-lock nesting level |
QL | 0:064c79e7311a | 819 | |
QL | 0:064c79e7311a | 820 | //............................................................................ |
QL | 0:064c79e7311a | 821 | //lint -e970 -e971 ignore MISRA rules 13 and 14 in this function |
QL | 0:064c79e7311a | 822 | const char Q_ROM * Q_ROM_VAR QF::getVersion(void) { |
QL | 0:064c79e7311a | 823 | static char const Q_ROM Q_ROM_VAR version[] = { |
QL | 0:064c79e7311a | 824 | ((QP_VERSION >> 12) & 0xF) + '0', |
QL | 0:064c79e7311a | 825 | '.', |
QL | 0:064c79e7311a | 826 | ((QP_VERSION >> 8) & 0xF) + '0', |
QL | 0:064c79e7311a | 827 | '.', |
QL | 0:064c79e7311a | 828 | ((QP_VERSION >> 4) & 0xF) + '0', |
QL | 0:064c79e7311a | 829 | (QP_VERSION & 0xF) + '0', |
QL | 0:064c79e7311a | 830 | '\0' |
QL | 0:064c79e7311a | 831 | }; |
QL | 0:064c79e7311a | 832 | return version; |
QL | 0:064c79e7311a | 833 | } |
QL | 0:064c79e7311a | 834 | //............................................................................ |
QL | 0:064c79e7311a | 835 | void QF::add_(QActive *a) { |
QL | 0:064c79e7311a | 836 | uint8_t p = a->m_prio; |
QL | 0:064c79e7311a | 837 | |
QL | 0:064c79e7311a | 838 | Q_REQUIRE(((uint8_t)0 < p) && (p <= (uint8_t)QF_MAX_ACTIVE) |
QL | 0:064c79e7311a | 839 | && (active_[p] == (QActive *)0)); |
QL | 0:064c79e7311a | 840 | |
QL | 0:064c79e7311a | 841 | QF_INT_LOCK_KEY_ |
QL | 0:064c79e7311a | 842 | QF_INT_LOCK_(); |
QL | 0:064c79e7311a | 843 | |
QL | 0:064c79e7311a | 844 | active_[p] = a; // registger the active object at this priority |
QL | 0:064c79e7311a | 845 | |
QL | 0:064c79e7311a | 846 | QS_BEGIN_NOLOCK_(QS_QF_ACTIVE_ADD, QS::aoObj_, a) |
QL | 0:064c79e7311a | 847 | QS_TIME_(); // timestamp |
QL | 0:064c79e7311a | 848 | QS_OBJ_(a); // the active object |
QL | 0:064c79e7311a | 849 | QS_U8_(p); // the priority of the active object |
QL | 0:064c79e7311a | 850 | QS_END_NOLOCK_() |
QL | 0:064c79e7311a | 851 | |
QL | 0:064c79e7311a | 852 | QF_INT_UNLOCK_(); |
QL | 0:064c79e7311a | 853 | } |
QL | 0:064c79e7311a | 854 | //............................................................................ |
QL | 0:064c79e7311a | 855 | void QF::remove_(QActive const *a) { |
QL | 0:064c79e7311a | 856 | uint8_t p = a->m_prio; |
QL | 0:064c79e7311a | 857 | |
QL | 0:064c79e7311a | 858 | Q_REQUIRE(((uint8_t)0 < p) && (p <= (uint8_t)QF_MAX_ACTIVE) |
QL | 0:064c79e7311a | 859 | && (active_[p] == a)); |
QL | 0:064c79e7311a | 860 | |
QL | 0:064c79e7311a | 861 | QF_INT_LOCK_KEY_ |
QL | 0:064c79e7311a | 862 | QF_INT_LOCK_(); |
QL | 0:064c79e7311a | 863 | |
QL | 0:064c79e7311a | 864 | active_[p] = (QActive *)0; // free-up the priority level |
QL | 0:064c79e7311a | 865 | |
QL | 0:064c79e7311a | 866 | QS_BEGIN_NOLOCK_(QS_QF_ACTIVE_REMOVE, QS::aoObj_, a) |
QL | 0:064c79e7311a | 867 | QS_TIME_(); // timestamp |
QL | 0:064c79e7311a | 868 | QS_OBJ_(a); // the active object |
QL | 0:064c79e7311a | 869 | QS_U8_(p); // the priority of the active object |
QL | 0:064c79e7311a | 870 | QS_END_NOLOCK_() |
QL | 0:064c79e7311a | 871 | |
QL | 0:064c79e7311a | 872 | QF_INT_UNLOCK_(); |
QL | 0:064c79e7311a | 873 | } |
QL | 0:064c79e7311a | 874 | |
QL | 0:064c79e7311a | 875 | // "qf_gc.cpp" =============================================================== |
QL | 0:064c79e7311a | 876 | void QF::gc(QEvent const *e) { |
QL | 0:064c79e7311a | 877 | if (e->dynamic_ != (uint8_t)0) { // is it a dynamic event? |
QL | 0:064c79e7311a | 878 | QF_INT_LOCK_KEY_ |
QL | 0:064c79e7311a | 879 | QF_INT_LOCK_(); |
QL | 0:064c79e7311a | 880 | |
QL | 0:064c79e7311a | 881 | if ((e->dynamic_ & 0x3F) > 1) { // isn't this the last reference? |
QL | 0:064c79e7311a | 882 | |
QL | 0:064c79e7311a | 883 | //lint -e1773 Attempt to cast away const |
QL | 0:064c79e7311a | 884 | --((QEvent *)e)->dynamic_; // decrement the reference counter |
QL | 0:064c79e7311a | 885 | // NOTE: cast the 'const' away, which is legitimate because |
QL | 0:064c79e7311a | 886 | // it's a dynamic event |
QL | 0:064c79e7311a | 887 | |
QL | 0:064c79e7311a | 888 | QS_BEGIN_NOLOCK_(QS_QF_GC_ATTEMPT, (void *)0, (void *)0) |
QL | 0:064c79e7311a | 889 | QS_TIME_(); // timestamp |
QL | 0:064c79e7311a | 890 | QS_SIG_(e->sig); // the signal of the event |
QL | 0:064c79e7311a | 891 | QS_U8_(e->dynamic_); // the dynamic attributes of the event |
QL | 0:064c79e7311a | 892 | QS_END_NOLOCK_() |
QL | 0:064c79e7311a | 893 | |
QL | 0:064c79e7311a | 894 | QF_INT_UNLOCK_(); |
QL | 0:064c79e7311a | 895 | } |
QL | 0:064c79e7311a | 896 | else { // this is the last reference to this event, recycle it |
QL | 0:064c79e7311a | 897 | uint8_t idx = (uint8_t)((e->dynamic_ >> 6) - 1); |
QL | 0:064c79e7311a | 898 | |
QL | 0:064c79e7311a | 899 | QS_BEGIN_NOLOCK_(QS_QF_GC, (void *)0, (void *)0) |
QL | 0:064c79e7311a | 900 | QS_TIME_(); // timestamp |
QL | 0:064c79e7311a | 901 | QS_SIG_(e->sig); // the signal of the event |
QL | 0:064c79e7311a | 902 | QS_U8_(e->dynamic_); // the dynamic attributes of the event |
QL | 0:064c79e7311a | 903 | QS_END_NOLOCK_() |
QL | 0:064c79e7311a | 904 | |
QL | 0:064c79e7311a | 905 | QF_INT_UNLOCK_(); |
QL | 0:064c79e7311a | 906 | |
QL | 0:064c79e7311a | 907 | Q_ASSERT(idx < QF_maxPool_); |
QL | 0:064c79e7311a | 908 | |
QL | 0:064c79e7311a | 909 | //lint -e1773 Attempt to cast away const |
QL | 0:064c79e7311a | 910 | QF_EPOOL_PUT_(QF_pool_[idx], (QEvent *)e); // cast 'const' away, |
QL | 0:064c79e7311a | 911 | // which is legitimate, because it's a pool event |
QL | 0:064c79e7311a | 912 | } |
QL | 0:064c79e7311a | 913 | } |
QL | 0:064c79e7311a | 914 | } |
QL | 0:064c79e7311a | 915 | |
QL | 0:064c79e7311a | 916 | // "qf_log2.cpp" ============================================================= |
QL | 0:064c79e7311a | 917 | uint8_t const Q_ROM Q_ROM_VAR QF_log2Lkup[256] = { |
QL | 0:064c79e7311a | 918 | 0U, 1U, 2U, 2U, 3U, 3U, 3U, 3U, 4U, 4U, 4U, 4U, 4U, 4U, 4U, 4U, |
QL | 0:064c79e7311a | 919 | 5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U, |
QL | 0:064c79e7311a | 920 | 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, |
QL | 0:064c79e7311a | 921 | 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, |
QL | 0:064c79e7311a | 922 | 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, |
QL | 0:064c79e7311a | 923 | 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, |
QL | 0:064c79e7311a | 924 | 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, |
QL | 0:064c79e7311a | 925 | 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U, |
QL | 0:064c79e7311a | 926 | 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, |
QL | 0:064c79e7311a | 927 | 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, |
QL | 0:064c79e7311a | 928 | 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, |
QL | 0:064c79e7311a | 929 | 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, |
QL | 0:064c79e7311a | 930 | 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, |
QL | 0:064c79e7311a | 931 | 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, |
QL | 0:064c79e7311a | 932 | 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, |
QL | 0:064c79e7311a | 933 | 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U, 8U |
QL | 0:064c79e7311a | 934 | }; |
QL | 0:064c79e7311a | 935 | |
QL | 0:064c79e7311a | 936 | // "qf_new.cpp" ============================================================== |
QL | 0:064c79e7311a | 937 | QEvent *QF::new_(uint16_t evtSize, QSignal sig) { |
QL | 0:064c79e7311a | 938 | // find the pool id that fits the requested event size ... |
QL | 0:064c79e7311a | 939 | uint8_t id = (uint8_t)0; |
QL | 0:064c79e7311a | 940 | while (evtSize > QF_EPOOL_EVENT_SIZE_(QF_pool_[id])) { |
QL | 0:064c79e7311a | 941 | ++id; |
QL | 0:064c79e7311a | 942 | Q_ASSERT(id < QF_maxPool_); // cannot run out of registered pools |
QL | 0:064c79e7311a | 943 | } |
QL | 0:064c79e7311a | 944 | |
QL | 0:064c79e7311a | 945 | QS_INT_LOCK_KEY_ |
QL | 0:064c79e7311a | 946 | QS_BEGIN_(QS_QF_NEW, (void *)0, (void *)0) |
QL | 0:064c79e7311a | 947 | QS_TIME_(); // timestamp |
QL | 0:064c79e7311a | 948 | QS_EVS_(evtSize); // the size of the event |
QL | 0:064c79e7311a | 949 | QS_SIG_(sig); // the signal of the event |
QL | 0:064c79e7311a | 950 | QS_END_() |
QL | 0:064c79e7311a | 951 | |
QL | 0:064c79e7311a | 952 | QEvent *e; |
QL | 0:064c79e7311a | 953 | QF_EPOOL_GET_(QF_pool_[id], e); |
QL | 0:064c79e7311a | 954 | Q_ASSERT(e != (QEvent *)0); // pool must not run out of events |
QL | 0:064c79e7311a | 955 | |
QL | 0:064c79e7311a | 956 | e->sig = sig; // set signal for this event |
QL | 0:064c79e7311a | 957 | |
QL | 0:064c79e7311a | 958 | // store the dynamic attributes of the event: |
QL | 0:064c79e7311a | 959 | // the pool ID and the reference counter == 0 |
QL | 0:064c79e7311a | 960 | e->dynamic_ = (uint8_t)((id + 1) << 6); |
QL | 0:064c79e7311a | 961 | return e; |
QL | 0:064c79e7311a | 962 | } |
QL | 0:064c79e7311a | 963 | |
QL | 0:064c79e7311a | 964 | // "qf_pool.cpp" ============================================================= |
QL | 0:064c79e7311a | 965 | // Package-scope objects ----------------------------------------------------- |
QL | 0:064c79e7311a | 966 | QF_EPOOL_TYPE_ QF_pool_[3]; // allocate 3 event pools |
QL | 0:064c79e7311a | 967 | uint8_t QF_maxPool_; // number of initialized event pools |
QL | 0:064c79e7311a | 968 | |
QL | 0:064c79e7311a | 969 | //............................................................................ |
QL | 0:064c79e7311a | 970 | void QF::poolInit(void *poolSto, uint32_t poolSize, QEventSize evtSize) { |
QL | 0:064c79e7311a | 971 | // cannot exceed the number of available memory pools |
QL | 0:064c79e7311a | 972 | Q_REQUIRE(QF_maxPool_ < (uint8_t)Q_DIM(QF_pool_)); |
QL | 0:064c79e7311a | 973 | // please initialize event pools in ascending order of evtSize: |
QL | 0:064c79e7311a | 974 | Q_REQUIRE((QF_maxPool_ == (uint8_t)0) |
QL | 0:064c79e7311a | 975 | || (QF_EPOOL_EVENT_SIZE_(QF_pool_[QF_maxPool_ - 1]) < evtSize)); |
QL | 0:064c79e7311a | 976 | QF_EPOOL_INIT_(QF_pool_[QF_maxPool_], poolSto, poolSize, evtSize); |
QL | 0:064c79e7311a | 977 | ++QF_maxPool_; // one more pool |
QL | 0:064c79e7311a | 978 | } |
QL | 0:064c79e7311a | 979 | |
QL | 0:064c79e7311a | 980 | // "qf_psini.cpp" ============================================================ |
QL | 0:064c79e7311a | 981 | // Package-scope objects ----------------------------------------------------- |
QL | 0:064c79e7311a | 982 | QSubscrList *QF_subscrList_; |
QL | 0:064c79e7311a | 983 | QSignal QF_maxSignal_; |
QL | 0:064c79e7311a | 984 | |
QL | 0:064c79e7311a | 985 | //............................................................................ |
QL | 0:064c79e7311a | 986 | void QF::psInit(QSubscrList *subscrSto, QSignal maxSignal) { |
QL | 0:064c79e7311a | 987 | QF_subscrList_ = subscrSto; |
QL | 0:064c79e7311a | 988 | QF_maxSignal_ = maxSignal; |
QL | 0:064c79e7311a | 989 | } |
QL | 0:064c79e7311a | 990 | |
QL | 0:064c79e7311a | 991 | // "qf_pspub.cpp" ============================================================ |
QL | 0:064c79e7311a | 992 | void QF::publish(QEvent const *e) { |
QL | 0:064c79e7311a | 993 | // make sure that the published signal is within the configured range |
QL | 0:064c79e7311a | 994 | Q_REQUIRE(e->sig < QF_maxSignal_); |
QL | 0:064c79e7311a | 995 | |
QL | 0:064c79e7311a | 996 | QF_INT_LOCK_KEY_ |
QL | 0:064c79e7311a | 997 | QF_INT_LOCK_(); |
QL | 0:064c79e7311a | 998 | |
QL | 0:064c79e7311a | 999 | QS_BEGIN_NOLOCK_(QS_QF_PUBLISH, (void *)0, (void *)0) |
QL | 0:064c79e7311a | 1000 | QS_TIME_(); // the timestamp |
QL | 0:064c79e7311a | 1001 | QS_SIG_(e->sig); // the signal of the event |
QL | 0:064c79e7311a | 1002 | QS_U8_(e->dynamic_); // the dynamic attributes of the event |
QL | 0:064c79e7311a | 1003 | QS_END_NOLOCK_() |
QL | 0:064c79e7311a | 1004 | |
QL | 0:064c79e7311a | 1005 | if (e->dynamic_ != (uint8_t)0) { // is it a dynamic event? |
QL | 0:064c79e7311a | 1006 | //lint -e1773 Attempt to cast away const |
QL | 0:064c79e7311a | 1007 | ++((QEvent *)e)->dynamic_; // increment reference counter, NOTE01 |
QL | 0:064c79e7311a | 1008 | // NOTE: cast the 'const' away, which is legitimate because |
QL | 0:064c79e7311a | 1009 | // it's a dynamic event */ |
QL | 0:064c79e7311a | 1010 | } |
QL | 0:064c79e7311a | 1011 | QF_INT_UNLOCK_(); |
QL | 0:064c79e7311a | 1012 | |
QL | 0:064c79e7311a | 1013 | #if (QF_MAX_ACTIVE <= 8) |
QL | 0:064c79e7311a | 1014 | uint8_t tmp = QF_subscrList_[e->sig].m_bits[0]; |
QL | 0:064c79e7311a | 1015 | while (tmp != (uint8_t)0) { |
QL | 0:064c79e7311a | 1016 | uint8_t p = Q_ROM_BYTE(QF_log2Lkup[tmp]); |
QL | 0:064c79e7311a | 1017 | tmp &= Q_ROM_BYTE(QF_invPwr2Lkup[p]); // clear the subscriber bit |
QL | 0:064c79e7311a | 1018 | Q_ASSERT(active_[p] != (QActive *)0); // must be registered |
QL | 0:064c79e7311a | 1019 | |
QL | 0:064c79e7311a | 1020 | active_[p]->postFIFO(e); // internally asserts if the queue overflows |
QL | 0:064c79e7311a | 1021 | } |
QL | 0:064c79e7311a | 1022 | #else |
QL | 0:064c79e7311a | 1023 | uint8_t i = Q_DIM(QF_subscrList_[0].m_bits);// number of bytes in the list |
QL | 0:064c79e7311a | 1024 | do { // go through all bytes in the subsciption list |
QL | 0:064c79e7311a | 1025 | --i; |
QL | 0:064c79e7311a | 1026 | uint8_t tmp = QF_subscrList_[e->sig].m_bits[i]; |
QL | 0:064c79e7311a | 1027 | while (tmp != (uint8_t)0) { |
QL | 0:064c79e7311a | 1028 | uint8_t p = Q_ROM_BYTE(QF_log2Lkup[tmp]); |
QL | 0:064c79e7311a | 1029 | tmp &= Q_ROM_BYTE(QF_invPwr2Lkup[p]); // clear the subscriber bit |
QL | 0:064c79e7311a | 1030 | p = (uint8_t)(p + (i << 3)); // adjust the priority |
QL | 0:064c79e7311a | 1031 | Q_ASSERT(active_[p] != (QActive *)0); // must be registered |
QL | 0:064c79e7311a | 1032 | |
QL | 0:064c79e7311a | 1033 | // postFIFO() internally asserts if the queue overflows |
QL | 0:064c79e7311a | 1034 | active_[p]->postFIFO(e); |
QL | 0:064c79e7311a | 1035 | } |
QL | 0:064c79e7311a | 1036 | } while (i != (uint8_t)0); |
QL | 0:064c79e7311a | 1037 | #endif |
QL | 0:064c79e7311a | 1038 | |
QL | 0:064c79e7311a | 1039 | gc(e); // run the garbage collector, see NOTE01 |
QL | 0:064c79e7311a | 1040 | } |
QL | 0:064c79e7311a | 1041 | |
QL | 0:064c79e7311a | 1042 | // "qf_pwr2.cpp" ============================================================= |
QL | 0:064c79e7311a | 1043 | // Global objects ------------------------------------------------------------ |
QL | 0:064c79e7311a | 1044 | uint8_t const Q_ROM Q_ROM_VAR QF_pwr2Lkup[65] = { |
QL | 0:064c79e7311a | 1045 | 0x00U, // unused location |
QL | 0:064c79e7311a | 1046 | 0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U, |
QL | 0:064c79e7311a | 1047 | 0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U, |
QL | 0:064c79e7311a | 1048 | 0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U, |
QL | 0:064c79e7311a | 1049 | 0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U, |
QL | 0:064c79e7311a | 1050 | 0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U, |
QL | 0:064c79e7311a | 1051 | 0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U, |
QL | 0:064c79e7311a | 1052 | 0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U, |
QL | 0:064c79e7311a | 1053 | 0x01U, 0x02U, 0x04U, 0x08U, 0x10U, 0x20U, 0x40U, 0x80U |
QL | 0:064c79e7311a | 1054 | }; |
QL | 0:064c79e7311a | 1055 | |
QL | 0:064c79e7311a | 1056 | uint8_t const Q_ROM Q_ROM_VAR QF_invPwr2Lkup[65] = { |
QL | 0:064c79e7311a | 1057 | 0xFFU, // unused location |
QL | 0:064c79e7311a | 1058 | 0xFEU, 0xFDU, 0xFBU, 0xF7U, 0xEFU, 0xDFU, 0xBFU, 0x7FU, |
QL | 0:064c79e7311a | 1059 | 0xFEU, 0xFDU, 0xFBU, 0xF7U, 0xEFU, 0xDFU, 0xBFU, 0x7FU, |
QL | 0:064c79e7311a | 1060 | 0xFEU, 0xFDU, 0xFBU, 0xF7U, 0xEFU, 0xDFU, 0xBFU, 0x7FU, |
QL | 0:064c79e7311a | 1061 | 0xFEU, 0xFDU, 0xFBU, 0xF7U, 0xEFU, 0xDFU, 0xBFU, 0x7FU, |
QL | 0:064c79e7311a | 1062 | 0xFEU, 0xFDU, 0xFBU, 0xF7U, 0xEFU, 0xDFU, 0xBFU, 0x7FU, |
QL | 0:064c79e7311a | 1063 | 0xFEU, 0xFDU, 0xFBU, 0xF7U, 0xEFU, 0xDFU, 0xBFU, 0x7FU, |
QL | 0:064c79e7311a | 1064 | 0xFEU, 0xFDU, 0xFBU, 0xF7U, 0xEFU, 0xDFU, 0xBFU, 0x7FU, |
QL | 0:064c79e7311a | 1065 | 0xFEU, 0xFDU, 0xFBU, 0xF7U, 0xEFU, 0xDFU, 0xBFU, 0x7FU |
QL | 0:064c79e7311a | 1066 | }; |
QL | 0:064c79e7311a | 1067 | |
QL | 0:064c79e7311a | 1068 | uint8_t const Q_ROM Q_ROM_VAR QF_div8Lkup[65] = { |
QL | 0:064c79e7311a | 1069 | 0U, // unused location |
QL | 0:064c79e7311a | 1070 | 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, |
QL | 0:064c79e7311a | 1071 | 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, |
QL | 0:064c79e7311a | 1072 | 2U, 2U, 2U, 2U, 2U, 2U, 2U, 2U, |
QL | 0:064c79e7311a | 1073 | 3U, 3U, 3U, 3U, 3U, 3U, 3U, 3U, |
QL | 0:064c79e7311a | 1074 | 4U, 4U, 4U, 4U, 4U, 4U, 4U, 4U, |
QL | 0:064c79e7311a | 1075 | 5U, 5U, 5U, 5U, 5U, 5U, 5U, 5U, |
QL | 0:064c79e7311a | 1076 | 6U, 6U, 6U, 6U, 6U, 6U, 6U, 6U, |
QL | 0:064c79e7311a | 1077 | 7U, 7U, 7U, 7U, 7U, 7U, 7U, 7U |
QL | 0:064c79e7311a | 1078 | }; |
QL | 0:064c79e7311a | 1079 | |
QL | 0:064c79e7311a | 1080 | // "qf_tick.cpp" ============================================================= |
QL | 0:064c79e7311a | 1081 | void QF::tick(void) { // see NOTE01 |
QL | 0:064c79e7311a | 1082 | QF_INT_LOCK_KEY_ |
QL | 0:064c79e7311a | 1083 | QF_INT_LOCK_(); |
QL | 0:064c79e7311a | 1084 | |
QL | 0:064c79e7311a | 1085 | QS_BEGIN_NOLOCK_(QS_QF_TICK, (void *)0, (void *)0) |
QL | 0:064c79e7311a | 1086 | QS_TEC_(++QS::tickCtr_); // the tick counter |
QL | 0:064c79e7311a | 1087 | QS_END_NOLOCK_() |
QL | 0:064c79e7311a | 1088 | |
QL | 0:064c79e7311a | 1089 | QTimeEvt *t = QF_timeEvtListHead_; |
QL | 0:064c79e7311a | 1090 | while (t != (QTimeEvt *)0) { |
QL | 0:064c79e7311a | 1091 | --t->m_ctr; |
QL | 0:064c79e7311a | 1092 | if (t->m_ctr == (QTimeEvtCtr)0) { // is the time evt about to expire? |
QL | 0:064c79e7311a | 1093 | if (t->m_interval != (QTimeEvtCtr)0) {//is it a periodic time evt? |
QL | 0:064c79e7311a | 1094 | t->m_ctr = t->m_interval; // rearm the time evt |
QL | 0:064c79e7311a | 1095 | } |
QL | 0:064c79e7311a | 1096 | else { // one-shot time evt, disarm by removing it from the list |
QL | 0:064c79e7311a | 1097 | if (t == QF_timeEvtListHead_) { |
QL | 0:064c79e7311a | 1098 | QF_timeEvtListHead_ = t->m_next; |
QL | 0:064c79e7311a | 1099 | } |
QL | 0:064c79e7311a | 1100 | else { |
QL | 0:064c79e7311a | 1101 | if (t->m_next != (QTimeEvt *)0) {// not the last time evt? |
QL | 0:064c79e7311a | 1102 | t->m_next->m_prev = t->m_prev; |
QL | 0:064c79e7311a | 1103 | } |
QL | 0:064c79e7311a | 1104 | t->m_prev->m_next = t->m_next; |
QL | 0:064c79e7311a | 1105 | } |
QL | 0:064c79e7311a | 1106 | t->m_prev = (QTimeEvt *)0; // mark the time event disarmed |
QL | 0:064c79e7311a | 1107 | |
QL | 0:064c79e7311a | 1108 | QS_BEGIN_NOLOCK_(QS_QF_TIMEEVT_AUTO_DISARM, QS::teObj_, t) |
QL | 0:064c79e7311a | 1109 | QS_OBJ_(t); // this time event object |
QL | 0:064c79e7311a | 1110 | QS_OBJ_(t->m_act); // the active object |
QL | 0:064c79e7311a | 1111 | QS_END_NOLOCK_() |
QL | 0:064c79e7311a | 1112 | } |
QL | 0:064c79e7311a | 1113 | |
QL | 0:064c79e7311a | 1114 | QS_BEGIN_NOLOCK_(QS_QF_TIMEEVT_POST, QS::teObj_, t) |
QL | 0:064c79e7311a | 1115 | QS_TIME_(); // timestamp |
QL | 0:064c79e7311a | 1116 | QS_OBJ_(t); // the time event object |
QL | 0:064c79e7311a | 1117 | QS_SIG_(t->sig); // the signal of this time event |
QL | 0:064c79e7311a | 1118 | QS_OBJ_(t->m_act); // the active object |
QL | 0:064c79e7311a | 1119 | QS_END_NOLOCK_() |
QL | 0:064c79e7311a | 1120 | |
QL | 0:064c79e7311a | 1121 | QF_INT_UNLOCK_(); // unlock interrupts before calling QF service |
QL | 0:064c79e7311a | 1122 | |
QL | 0:064c79e7311a | 1123 | // postFIFO() asserts internally that the event was accepted |
QL | 0:064c79e7311a | 1124 | t->m_act->postFIFO(t); |
QL | 0:064c79e7311a | 1125 | } |
QL | 0:064c79e7311a | 1126 | else { |
QL | 0:064c79e7311a | 1127 | QF_INT_UNLOCK_(); |
QL | 0:064c79e7311a | 1128 | static uint8_t volatile dummy; |
QL | 0:064c79e7311a | 1129 | dummy = (uint8_t)0; // execute a few instructions, see NOTE02 |
QL | 0:064c79e7311a | 1130 | } |
QL | 0:064c79e7311a | 1131 | |
QL | 0:064c79e7311a | 1132 | QF_INT_LOCK_(); // lock interrupts again to advance the link |
QL | 0:064c79e7311a | 1133 | t = t->m_next; |
QL | 0:064c79e7311a | 1134 | } |
QL | 0:064c79e7311a | 1135 | QF_INT_UNLOCK_(); |
QL | 0:064c79e7311a | 1136 | } |
QL | 0:064c79e7311a | 1137 | |
QL | 0:064c79e7311a | 1138 | // "qmp_get.cpp" ============================================================= |
QL | 0:064c79e7311a | 1139 | void *QMPool::get(void) { |
QL | 0:064c79e7311a | 1140 | QF_INT_LOCK_KEY_ |
QL | 0:064c79e7311a | 1141 | QF_INT_LOCK_(); |
QL | 0:064c79e7311a | 1142 | |
QL | 0:064c79e7311a | 1143 | QFreeBlock *fb = (QFreeBlock *)m_free; // get a free block or NULL |
QL | 0:064c79e7311a | 1144 | if (fb != (QFreeBlock *)0) { // free block available? |
QL | 0:064c79e7311a | 1145 | m_free = fb->m_next; // adjust list head to the next free block |
QL | 0:064c79e7311a | 1146 | --m_nFree; // one free block less |
QL | 0:064c79e7311a | 1147 | if (m_nMin > m_nFree) { |
QL | 0:064c79e7311a | 1148 | m_nMin = m_nFree; // remember the minimum so far |
QL | 0:064c79e7311a | 1149 | } |
QL | 0:064c79e7311a | 1150 | } |
QL | 0:064c79e7311a | 1151 | |
QL | 0:064c79e7311a | 1152 | QS_BEGIN_NOLOCK_(QS_QF_MPOOL_GET, QS::mpObj_, m_start) |
QL | 0:064c79e7311a | 1153 | QS_TIME_(); // timestamp |
QL | 0:064c79e7311a | 1154 | QS_OBJ_(m_start); // the memory managed by this pool |
QL | 0:064c79e7311a | 1155 | QS_MPC_(m_nFree); // the number of free blocks in the pool |
QL | 0:064c79e7311a | 1156 | QS_MPC_(m_nMin); // the mninimum number of free blocks in the pool |
QL | 0:064c79e7311a | 1157 | QS_END_NOLOCK_() |
QL | 0:064c79e7311a | 1158 | |
QL | 0:064c79e7311a | 1159 | QF_INT_UNLOCK_(); |
QL | 0:064c79e7311a | 1160 | return fb; // return the block or NULL pointer to the caller |
QL | 0:064c79e7311a | 1161 | } |
QL | 0:064c79e7311a | 1162 | //............................................................................ |
QL | 0:064c79e7311a | 1163 | uint32_t QF::getPoolMargin(uint8_t poolId) { |
QL | 0:064c79e7311a | 1164 | Q_REQUIRE(((uint8_t)1 <= poolId) && (poolId <= QF_maxPool_)); |
QL | 0:064c79e7311a | 1165 | |
QL | 0:064c79e7311a | 1166 | QF_INT_LOCK_KEY_ |
QL | 0:064c79e7311a | 1167 | QF_INT_LOCK_(); |
QL | 0:064c79e7311a | 1168 | uint32_t margin = (uint32_t)QF_pool_[poolId - (uint8_t)1].m_nMin; |
QL | 0:064c79e7311a | 1169 | QF_INT_UNLOCK_(); |
QL | 0:064c79e7311a | 1170 | |
QL | 0:064c79e7311a | 1171 | return margin; |
QL | 0:064c79e7311a | 1172 | } |
QL | 0:064c79e7311a | 1173 | |
QL | 0:064c79e7311a | 1174 | // "qmp_init.cpp" ============================================================ |
QL | 0:064c79e7311a | 1175 | void QMPool::init(void *poolSto, uint32_t poolSize, QMPoolSize blockSize) { |
QL | 0:064c79e7311a | 1176 | // The memory block must be valid |
QL | 0:064c79e7311a | 1177 | // and the poolSize must fit at least one free block |
QL | 0:064c79e7311a | 1178 | // and the blockSize must not be too close to the top of the dynamic range |
QL | 0:064c79e7311a | 1179 | Q_REQUIRE((poolSto != (void *)0) |
QL | 0:064c79e7311a | 1180 | && (poolSize >= (uint32_t)sizeof(QFreeBlock)) |
QL | 0:064c79e7311a | 1181 | && ((QMPoolSize)(blockSize + (QMPoolSize)sizeof(QFreeBlock)) |
QL | 0:064c79e7311a | 1182 | > blockSize)); |
QL | 0:064c79e7311a | 1183 | |
QL | 0:064c79e7311a | 1184 | //lint -e923 ignore MISRA Rule 45 in this expression |
QL | 0:064c79e7311a | 1185 | uint32_t corr = ((uint32_t)poolSto |
QL | 0:064c79e7311a | 1186 | & ((uint32_t)sizeof(QFreeBlock) - (uint32_t)1)); |
QL | 0:064c79e7311a | 1187 | if (corr != (uint32_t)0) { // alignment needed? |
QL | 0:064c79e7311a | 1188 | corr = (uint32_t)sizeof(QFreeBlock) - corr; // amount to align poolSto |
QL | 0:064c79e7311a | 1189 | poolSize -= corr; // reduce the available pool size |
QL | 0:064c79e7311a | 1190 | } |
QL | 0:064c79e7311a | 1191 | //lint -e826 align the head of free list at the free block-size boundary |
QL | 0:064c79e7311a | 1192 | m_free = (void *)((uint8_t *)poolSto + corr); |
QL | 0:064c79e7311a | 1193 | |
QL | 0:064c79e7311a | 1194 | // round up the blockSize to fit an integer number of pointers |
QL | 0:064c79e7311a | 1195 | m_blockSize = (QMPoolSize)sizeof(QFreeBlock); // start with just one |
QL | 0:064c79e7311a | 1196 | uint32_t nblocks = (uint32_t)1;// # free blocks that fit in a memory block |
QL | 0:064c79e7311a | 1197 | while (m_blockSize < blockSize) { |
QL | 0:064c79e7311a | 1198 | m_blockSize += (QMPoolSize)sizeof(QFreeBlock); |
QL | 0:064c79e7311a | 1199 | ++nblocks; |
QL | 0:064c79e7311a | 1200 | } |
QL | 0:064c79e7311a | 1201 | blockSize = m_blockSize; // use the rounded-up value from here on |
QL | 0:064c79e7311a | 1202 | |
QL | 0:064c79e7311a | 1203 | // the whole pool buffer must fit at least one rounded-up block |
QL | 0:064c79e7311a | 1204 | Q_ASSERT(poolSize >= (uint32_t)blockSize); |
QL | 0:064c79e7311a | 1205 | |
QL | 0:064c79e7311a | 1206 | // chain all blocks together in a free-list... |
QL | 0:064c79e7311a | 1207 | poolSize -= (uint32_t)blockSize; // don't chain the last block |
QL | 0:064c79e7311a | 1208 | m_nTot = (QMPoolCtr)1; // one (the last) block in the pool |
QL | 0:064c79e7311a | 1209 | QFreeBlock *fb = (QFreeBlock *)m_free;//start at the head of the free list |
QL | 0:064c79e7311a | 1210 | while (poolSize >= (uint32_t)blockSize) { |
QL | 0:064c79e7311a | 1211 | fb->m_next = &fb[nblocks]; // setup the next link |
QL | 0:064c79e7311a | 1212 | fb = fb->m_next; // advance to next block |
QL | 0:064c79e7311a | 1213 | poolSize -= (uint32_t)blockSize; // reduce the available pool size |
QL | 0:064c79e7311a | 1214 | ++m_nTot; // increment the number of blocks so far |
QL | 0:064c79e7311a | 1215 | } |
QL | 0:064c79e7311a | 1216 | |
QL | 0:064c79e7311a | 1217 | fb->m_next = (QFreeBlock *)0; // the last link points to NULL |
QL | 0:064c79e7311a | 1218 | m_nFree = m_nTot; // all blocks are free |
QL | 0:064c79e7311a | 1219 | m_nMin = m_nTot; // the minimum number of free blocks |
QL | 0:064c79e7311a | 1220 | m_start = poolSto; // the original start this pool buffer |
QL | 0:064c79e7311a | 1221 | m_end = fb; // the last block in this pool |
QL | 0:064c79e7311a | 1222 | |
QL | 0:064c79e7311a | 1223 | QS_INT_LOCK_KEY_ |
QL | 0:064c79e7311a | 1224 | QS_BEGIN_(QS_QF_MPOOL_INIT, QS::mpObj_, m_start) |
QL | 0:064c79e7311a | 1225 | QS_OBJ_(m_start); // the memory managed by this pool |
QL | 0:064c79e7311a | 1226 | QS_MPC_(m_nTot); // the total number of blocks |
QL | 0:064c79e7311a | 1227 | QS_END_() |
QL | 0:064c79e7311a | 1228 | } |
QL | 0:064c79e7311a | 1229 | |
QL | 0:064c79e7311a | 1230 | // "qmp_put.cpp" ============================================================= |
QL | 0:064c79e7311a | 1231 | void QMPool::put(void *b) { |
QL | 0:064c79e7311a | 1232 | //lint -e946 -e1904 ignore MISRA Rule 103 in this precondition |
QL | 0:064c79e7311a | 1233 | Q_REQUIRE((m_start <= b) && (b <= m_end) /* must be in range */ |
QL | 0:064c79e7311a | 1234 | && (m_nFree <= m_nTot)); // # free blocks must be < total |
QL | 0:064c79e7311a | 1235 | |
QL | 0:064c79e7311a | 1236 | QF_INT_LOCK_KEY_ |
QL | 0:064c79e7311a | 1237 | QF_INT_LOCK_(); |
QL | 0:064c79e7311a | 1238 | |
QL | 0:064c79e7311a | 1239 | ((QFreeBlock *)b)->m_next = (QFreeBlock *)m_free;//link into the free list |
QL | 0:064c79e7311a | 1240 | m_free = b; // set as new head of the free list |
QL | 0:064c79e7311a | 1241 | ++m_nFree; // one more free block in this pool |
QL | 0:064c79e7311a | 1242 | |
QL | 0:064c79e7311a | 1243 | QS_BEGIN_NOLOCK_(QS_QF_MPOOL_PUT, QS::mpObj_, m_start) |
QL | 0:064c79e7311a | 1244 | QS_TIME_(); // timestamp |
QL | 0:064c79e7311a | 1245 | QS_OBJ_(m_start); // the memory managed by this pool |
QL | 0:064c79e7311a | 1246 | QS_MPC_(m_nFree); // the number of free blocks in the pool |
QL | 0:064c79e7311a | 1247 | QS_END_NOLOCK_() |
QL | 0:064c79e7311a | 1248 | |
QL | 0:064c79e7311a | 1249 | QF_INT_UNLOCK_(); |
QL | 0:064c79e7311a | 1250 | } |
QL | 0:064c79e7311a | 1251 | |
QL | 0:064c79e7311a | 1252 | // "qte_arm.cpp" ============================================================= |
QL | 0:064c79e7311a | 1253 | // Package-scope objects ----------------------------------------------------- |
QL | 0:064c79e7311a | 1254 | QTimeEvt *QF_timeEvtListHead_; // head of linked list of time events |
QL | 0:064c79e7311a | 1255 | |
QL | 0:064c79e7311a | 1256 | //............................................................................ |
QL | 0:064c79e7311a | 1257 | void QTimeEvt::arm_(QActive *act, QTimeEvtCtr nTicks) { |
QL | 0:064c79e7311a | 1258 | Q_REQUIRE((nTicks > (QTimeEvtCtr)0) /* cannot arm with 0 ticks */ |
QL | 0:064c79e7311a | 1259 | && (sig >= (QSignal)Q_USER_SIG) /* valid signal */ |
QL | 0:064c79e7311a | 1260 | && (m_prev == (QTimeEvt *)0) /* time event must NOT be used */ |
QL | 0:064c79e7311a | 1261 | && (act != (QActive *)0)); /* active object must be provided */ |
QL | 0:064c79e7311a | 1262 | m_ctr = nTicks; |
QL | 0:064c79e7311a | 1263 | m_prev = this; // mark the timer in use |
QL | 0:064c79e7311a | 1264 | m_act = act; |
QL | 0:064c79e7311a | 1265 | QF_INT_LOCK_KEY_ |
QL | 0:064c79e7311a | 1266 | QF_INT_LOCK_(); |
QL | 0:064c79e7311a | 1267 | |
QL | 0:064c79e7311a | 1268 | QS_BEGIN_NOLOCK_(QS_QF_TIMEEVT_ARM, QS::teObj_, this) |
QL | 0:064c79e7311a | 1269 | QS_TIME_(); // timestamp |
QL | 0:064c79e7311a | 1270 | QS_OBJ_(this); // this time event object |
QL | 0:064c79e7311a | 1271 | QS_OBJ_(act); // the active object |
QL | 0:064c79e7311a | 1272 | QS_TEC_(nTicks); // the number of ticks |
QL | 0:064c79e7311a | 1273 | QS_TEC_(m_interval); // the interval |
QL | 0:064c79e7311a | 1274 | QS_END_NOLOCK_() |
QL | 0:064c79e7311a | 1275 | |
QL | 0:064c79e7311a | 1276 | m_next = QF_timeEvtListHead_; |
QL | 0:064c79e7311a | 1277 | if (QF_timeEvtListHead_ != (QTimeEvt *)0) { |
QL | 0:064c79e7311a | 1278 | QF_timeEvtListHead_->m_prev = this; |
QL | 0:064c79e7311a | 1279 | } |
QL | 0:064c79e7311a | 1280 | QF_timeEvtListHead_ = this; |
QL | 0:064c79e7311a | 1281 | QF_INT_UNLOCK_(); |
QL | 0:064c79e7311a | 1282 | } |
QL | 0:064c79e7311a | 1283 | |
QL | 0:064c79e7311a | 1284 | // "qte_ctor.cpp" ============================================================ |
QL | 0:064c79e7311a | 1285 | QTimeEvt::QTimeEvt(QSignal s) |
QL | 0:064c79e7311a | 1286 | : m_prev((QTimeEvt *)0), |
QL | 0:064c79e7311a | 1287 | m_next((QTimeEvt *)0), |
QL | 0:064c79e7311a | 1288 | m_act((QActive *)0), |
QL | 0:064c79e7311a | 1289 | m_ctr((QTimeEvtCtr)0), |
QL | 0:064c79e7311a | 1290 | m_interval((QTimeEvtCtr)0) |
QL | 0:064c79e7311a | 1291 | { |
QL | 0:064c79e7311a | 1292 | Q_REQUIRE(s >= (QSignal)Q_USER_SIG); // valid signal |
QL | 0:064c79e7311a | 1293 | sig = s; |
QL | 0:064c79e7311a | 1294 | dynamic_ = (uint8_t)0; // time event must be static, see NOTE01 |
QL | 0:064c79e7311a | 1295 | } |
QL | 0:064c79e7311a | 1296 | |
QL | 0:064c79e7311a | 1297 | // "qte_darm.cpp" ============================================================ |
QL | 0:064c79e7311a | 1298 | // NOTE: disarm a time evt (no harm in disarming an already disarmed time evt) |
QL | 0:064c79e7311a | 1299 | uint8_t QTimeEvt::disarm(void) { |
QL | 0:064c79e7311a | 1300 | uint8_t wasArmed; |
QL | 0:064c79e7311a | 1301 | QF_INT_LOCK_KEY_ |
QL | 0:064c79e7311a | 1302 | QF_INT_LOCK_(); |
QL | 0:064c79e7311a | 1303 | if (m_prev != (QTimeEvt *)0) { // is the time event actually armed? |
QL | 0:064c79e7311a | 1304 | wasArmed = (uint8_t)1; |
QL | 0:064c79e7311a | 1305 | if (this == QF_timeEvtListHead_) { |
QL | 0:064c79e7311a | 1306 | QF_timeEvtListHead_ = m_next; |
QL | 0:064c79e7311a | 1307 | } |
QL | 0:064c79e7311a | 1308 | else { |
QL | 0:064c79e7311a | 1309 | if (m_next != (QTimeEvt *)0) { // not the last in the list? |
QL | 0:064c79e7311a | 1310 | m_next->m_prev = m_prev; |
QL | 0:064c79e7311a | 1311 | } |
QL | 0:064c79e7311a | 1312 | m_prev->m_next = m_next; |
QL | 0:064c79e7311a | 1313 | } |
QL | 0:064c79e7311a | 1314 | m_prev = (QTimeEvt *)0; // mark the time event as disarmed |
QL | 0:064c79e7311a | 1315 | |
QL | 0:064c79e7311a | 1316 | QS_BEGIN_NOLOCK_(QS_QF_TIMEEVT_DISARM, QS::teObj_, this) |
QL | 0:064c79e7311a | 1317 | QS_TIME_(); // timestamp |
QL | 0:064c79e7311a | 1318 | QS_OBJ_(this); // this time event object |
QL | 0:064c79e7311a | 1319 | QS_OBJ_(m_act); // the active object |
QL | 0:064c79e7311a | 1320 | QS_TEC_(m_ctr); // the number of ticks |
QL | 0:064c79e7311a | 1321 | QS_TEC_(m_interval); // the interval |
QL | 0:064c79e7311a | 1322 | QS_END_NOLOCK_() |
QL | 0:064c79e7311a | 1323 | } |
QL | 0:064c79e7311a | 1324 | else { // the time event was not armed |
QL | 0:064c79e7311a | 1325 | wasArmed = (uint8_t)0; |
QL | 0:064c79e7311a | 1326 | |
QL | 0:064c79e7311a | 1327 | QS_BEGIN_NOLOCK_(QS_QF_TIMEEVT_DISARM_ATTEMPT, QS::teObj_, this) |
QL | 0:064c79e7311a | 1328 | QS_TIME_(); // timestamp |
QL | 0:064c79e7311a | 1329 | QS_OBJ_(this); // this time event object |
QL | 0:064c79e7311a | 1330 | QS_OBJ_(m_act); // the active object |
QL | 0:064c79e7311a | 1331 | QS_END_NOLOCK_() |
QL | 0:064c79e7311a | 1332 | } |
QL | 0:064c79e7311a | 1333 | QF_INT_UNLOCK_(); |
QL | 0:064c79e7311a | 1334 | return wasArmed; |
QL | 0:064c79e7311a | 1335 | } |
QL | 0:064c79e7311a | 1336 | |
QL | 0:064c79e7311a | 1337 | // "qte_rarm.cpp" ============================================================ |
QL | 0:064c79e7311a | 1338 | uint8_t QTimeEvt::rearm(QTimeEvtCtr nTicks) { |
QL | 0:064c79e7311a | 1339 | Q_REQUIRE((nTicks > (QTimeEvtCtr)0) /* cannot rearm with 0 ticks */ |
QL | 0:064c79e7311a | 1340 | && (sig >= (QSignal)Q_USER_SIG) /* valid signal */ |
QL | 0:064c79e7311a | 1341 | && (m_act != (QActive *)0)); // valid active object |
QL | 0:064c79e7311a | 1342 | uint8_t isArmed; |
QL | 0:064c79e7311a | 1343 | QF_INT_LOCK_KEY_ |
QL | 0:064c79e7311a | 1344 | QF_INT_LOCK_(); |
QL | 0:064c79e7311a | 1345 | m_ctr = nTicks; |
QL | 0:064c79e7311a | 1346 | if (m_prev == (QTimeEvt *)0) { // is this time event disarmed? |
QL | 0:064c79e7311a | 1347 | isArmed = (uint8_t)0; |
QL | 0:064c79e7311a | 1348 | m_next = QF_timeEvtListHead_; |
QL | 0:064c79e7311a | 1349 | if (QF_timeEvtListHead_ != (QTimeEvt *)0) { |
QL | 0:064c79e7311a | 1350 | QF_timeEvtListHead_->m_prev = this; |
QL | 0:064c79e7311a | 1351 | } |
QL | 0:064c79e7311a | 1352 | QF_timeEvtListHead_ = this; |
QL | 0:064c79e7311a | 1353 | m_prev = this; // mark the time evt in use |
QL | 0:064c79e7311a | 1354 | } |
QL | 0:064c79e7311a | 1355 | else { // the time event is armed |
QL | 0:064c79e7311a | 1356 | isArmed = (uint8_t)1; |
QL | 0:064c79e7311a | 1357 | } |
QL | 0:064c79e7311a | 1358 | |
QL | 0:064c79e7311a | 1359 | QS_BEGIN_NOLOCK_(QS_QF_TIMEEVT_REARM, QS::teObj_, this) |
QL | 0:064c79e7311a | 1360 | QS_TIME_(); // timestamp |
QL | 0:064c79e7311a | 1361 | QS_OBJ_(this); // this time event object |
QL | 0:064c79e7311a | 1362 | QS_OBJ_(m_act); // the active object |
QL | 0:064c79e7311a | 1363 | QS_TEC_(m_ctr); // the number of ticks |
QL | 0:064c79e7311a | 1364 | QS_TEC_(m_interval); // the interval |
QL | 0:064c79e7311a | 1365 | QS_U8_(isArmed); // was the timer armed? |
QL | 0:064c79e7311a | 1366 | QS_END_NOLOCK_() |
QL | 0:064c79e7311a | 1367 | |
QL | 0:064c79e7311a | 1368 | QF_INT_UNLOCK_(); |
QL | 0:064c79e7311a | 1369 | return isArmed; |
QL | 0:064c79e7311a | 1370 | } |
QL | 0:064c79e7311a | 1371 | |
QL | 0:064c79e7311a | 1372 | ////////////////////////////////////////////////////////////////////////////// |
QL | 0:064c79e7311a | 1373 | // Kernel selection based on QK_PREEMPTIVE |
QL | 0:064c79e7311a | 1374 | // |
QL | 0:064c79e7311a | 1375 | #ifdef QK_PREEMPTIVE |
QL | 0:064c79e7311a | 1376 | |
QL | 0:064c79e7311a | 1377 | // "qk_pkg.h" ================================================================ |
QL | 0:064c79e7311a | 1378 | // QK internal interrupt locking/unlocking |
QL | 0:064c79e7311a | 1379 | #ifndef QF_INT_KEY_TYPE |
QL | 0:064c79e7311a | 1380 | #define QK_INT_LOCK_KEY_ |
QL | 0:064c79e7311a | 1381 | #define QK_INT_LOCK_() QF_INT_LOCK(dummy) |
QL | 0:064c79e7311a | 1382 | #define QK_INT_UNLOCK_() QF_INT_UNLOCK(dummy) |
QL | 0:064c79e7311a | 1383 | #else |
QL | 0:064c79e7311a | 1384 | |
QL | 0:064c79e7311a | 1385 | /// \brief This is an internal macro for defining the interrupt lock key. |
QL | 0:064c79e7311a | 1386 | /// |
QL | 0:064c79e7311a | 1387 | /// The purpose of this macro is to enable writing the same code for the |
QL | 0:064c79e7311a | 1388 | /// case when interrupt key is defined and when it is not. If the macro |
QL | 0:064c79e7311a | 1389 | /// #QF_INT_KEY_TYPE is defined, this internal macro provides the |
QL | 0:064c79e7311a | 1390 | /// definition of the lock key variable. Otherwise this macro is empty. |
QL | 0:064c79e7311a | 1391 | /// \sa #QF_INT_KEY_TYPE, #QF_INT_LOCK_, #QF_INT_UNLOCK_ |
QL | 0:064c79e7311a | 1392 | #define QK_INT_LOCK_KEY_ QF_INT_KEY_TYPE intLockKey_; |
QL | 0:064c79e7311a | 1393 | |
QL | 0:064c79e7311a | 1394 | /// \brief This is an internal macro for locking interrupts. |
QL | 0:064c79e7311a | 1395 | /// |
QL | 0:064c79e7311a | 1396 | /// The purpose of this macro is to enable writing the same code for the |
QL | 0:064c79e7311a | 1397 | /// case when interrupt key is defined and when it is not. If the macro |
QL | 0:064c79e7311a | 1398 | /// #QF_INT_KEY_TYPE is defined, this internal macro invokes #QF_INT_LOCK |
QL | 0:064c79e7311a | 1399 | /// passing the key variable as the parameter. Otherwise #QF_INT_LOCK |
QL | 0:064c79e7311a | 1400 | /// is invoked with a dummy parameter. |
QL | 0:064c79e7311a | 1401 | /// \sa #QK_INT_LOCK_KEY_, #QK_INT_UNLOCK_ |
QL | 0:064c79e7311a | 1402 | #define QK_INT_LOCK_() QF_INT_LOCK(intLockKey_) |
QL | 0:064c79e7311a | 1403 | |
QL | 0:064c79e7311a | 1404 | /// \brief This is an internal macro for unlocking interrupts. |
QL | 0:064c79e7311a | 1405 | /// |
QL | 0:064c79e7311a | 1406 | /// The purpose of this macro is to enable writing the same code for the |
QL | 0:064c79e7311a | 1407 | /// case when interrupt key is defined and when it is not. If the macro |
QL | 0:064c79e7311a | 1408 | /// #QF_INT_KEY_TYPE is defined, this internal macro invokes |
QL | 0:064c79e7311a | 1409 | /// #QF_INT_UNLOCK passing the key variable as the parameter. Otherwise |
QL | 0:064c79e7311a | 1410 | /// #QF_INT_UNLOCK is invoked with a dummy parameter. |
QL | 0:064c79e7311a | 1411 | /// \sa #QK_INT_LOCK_KEY_, #QK_INT_LOCK_ |
QL | 0:064c79e7311a | 1412 | #define QK_INT_UNLOCK_() QF_INT_UNLOCK(intLockKey_) |
QL | 0:064c79e7311a | 1413 | #endif |
QL | 0:064c79e7311a | 1414 | |
QL | 0:064c79e7311a | 1415 | // package-scope objects... |
QL | 0:064c79e7311a | 1416 | #ifndef QK_NO_MUTEX |
QL | 0:064c79e7311a | 1417 | extern uint8_t volatile QK_ceilingPrio_; ///< QK mutex priority ceiling |
QL | 0:064c79e7311a | 1418 | #endif |
QL | 0:064c79e7311a | 1419 | |
QL | 0:064c79e7311a | 1420 | // "qk.cpp" ================================================================== |
QL | 0:064c79e7311a | 1421 | // Public-scope objects ------------------------------------------------------ |
QL | 0:064c79e7311a | 1422 | #if (QF_MAX_ACTIVE <= 8) |
QL | 0:064c79e7311a | 1423 | QPSet8 volatile QK_readySet_; // ready set of QK |
QL | 0:064c79e7311a | 1424 | #else |
QL | 0:064c79e7311a | 1425 | QPSet64 volatile QK_readySet_; // ready set of QK |
QL | 0:064c79e7311a | 1426 | #endif |
QL | 0:064c79e7311a | 1427 | // start with the QK scheduler locked |
QL | 0:064c79e7311a | 1428 | uint8_t volatile QK_currPrio_ = (uint8_t)(QF_MAX_ACTIVE + 1); |
QL | 0:064c79e7311a | 1429 | uint8_t volatile QK_intNest_; // start with nesting level of 0 |
QL | 0:064c79e7311a | 1430 | |
QL | 0:064c79e7311a | 1431 | |
QL | 0:064c79e7311a | 1432 | //............................................................................ |
QL | 0:064c79e7311a | 1433 | //lint -e970 -e971 ignore MISRA rules 13 and 14 in this function |
QL | 0:064c79e7311a | 1434 | char const Q_ROM * Q_ROM_VAR QK::getVersion(void) { |
QL | 0:064c79e7311a | 1435 | static char const Q_ROM Q_ROM_VAR version[] = { |
QL | 0:064c79e7311a | 1436 | ((QP_VERSION >> 12) & 0xF) + '0', |
QL | 0:064c79e7311a | 1437 | '.', |
QL | 0:064c79e7311a | 1438 | ((QP_VERSION >> 8) & 0xF) + '0', |
QL | 0:064c79e7311a | 1439 | '.', |
QL | 0:064c79e7311a | 1440 | ((QP_VERSION >> 4) & 0xF) + '0', |
QL | 0:064c79e7311a | 1441 | (QP_VERSION & 0xF) + '0', |
QL | 0:064c79e7311a | 1442 | '\0' |
QL | 0:064c79e7311a | 1443 | }; |
QL | 0:064c79e7311a | 1444 | return version; |
QL | 0:064c79e7311a | 1445 | } |
QL | 0:064c79e7311a | 1446 | //............................................................................ |
QL | 0:064c79e7311a | 1447 | void QF::init(void) { |
QL | 0:064c79e7311a | 1448 | QK_init(); // QK initialization ("C" linkage, might be assembly) |
QL | 0:064c79e7311a | 1449 | } |
QL | 0:064c79e7311a | 1450 | //............................................................................ |
QL | 0:064c79e7311a | 1451 | void QF::stop(void) { |
QL | 0:064c79e7311a | 1452 | QF::onCleanup(); // cleanup callback |
QL | 0:064c79e7311a | 1453 | // nothing else to do for the QK preemptive kernel |
QL | 0:064c79e7311a | 1454 | } |
QL | 0:064c79e7311a | 1455 | //............................................................................ |
QL | 0:064c79e7311a | 1456 | void QF::run(void) { |
QL | 0:064c79e7311a | 1457 | QK_INT_LOCK_KEY_ |
QL | 0:064c79e7311a | 1458 | |
QL | 0:064c79e7311a | 1459 | QK_INT_LOCK_(); |
QL | 0:064c79e7311a | 1460 | QK_currPrio_ = (uint8_t)0; // set the priority for the QK idle loop |
QL | 0:064c79e7311a | 1461 | QK_SCHEDULE_(); // process all events produced so far |
QL | 0:064c79e7311a | 1462 | QK_INT_UNLOCK_(); |
QL | 0:064c79e7311a | 1463 | |
QL | 0:064c79e7311a | 1464 | QF::onStartup(); // startup callback |
QL | 0:064c79e7311a | 1465 | |
QL | 0:064c79e7311a | 1466 | for (;;) { // the QK idle loop |
QL | 0:064c79e7311a | 1467 | QK::onIdle(); // invoke the QK on-idle callback |
QL | 0:064c79e7311a | 1468 | } |
QL | 0:064c79e7311a | 1469 | } |
QL | 0:064c79e7311a | 1470 | //............................................................................ |
QL | 0:064c79e7311a | 1471 | void QActive::start(uint8_t prio, |
QL | 0:064c79e7311a | 1472 | QEvent const *qSto[], uint32_t qLen, |
QL | 0:064c79e7311a | 1473 | void *tls, uint32_t flags, |
QL | 0:064c79e7311a | 1474 | QEvent const *ie) |
QL | 0:064c79e7311a | 1475 | { |
QL | 0:064c79e7311a | 1476 | Q_REQUIRE(((uint8_t)0 < prio) && (prio <= (uint8_t)QF_MAX_ACTIVE)); |
QL | 0:064c79e7311a | 1477 | |
QL | 0:064c79e7311a | 1478 | m_eQueue.init(qSto, (QEQueueCtr)qLen); // initialize the event queue |
QL | 0:064c79e7311a | 1479 | m_prio = prio; |
QL | 0:064c79e7311a | 1480 | QF::add_(this); // make QF aware of this active object |
QL | 0:064c79e7311a | 1481 | |
QL | 0:064c79e7311a | 1482 | #if defined(QK_TLS) || defined(QK_EXT_SAVE) |
QL | 0:064c79e7311a | 1483 | m_osObject = (uint8_t)flags; // m_osObject contains the thread flags |
QL | 0:064c79e7311a | 1484 | m_thread = tls; // contains the pointer to the thread-local-storage |
QL | 0:064c79e7311a | 1485 | #else |
QL | 0:064c79e7311a | 1486 | Q_ASSERT((tls == (void *)0) && (flags == (uint32_t)0)); |
QL | 0:064c79e7311a | 1487 | #endif |
QL | 0:064c79e7311a | 1488 | |
QL | 0:064c79e7311a | 1489 | init(ie); // execute initial transition |
QL | 0:064c79e7311a | 1490 | |
QL | 0:064c79e7311a | 1491 | QS_FLUSH(); // flush the trace buffer to the host |
QL | 0:064c79e7311a | 1492 | } |
QL | 0:064c79e7311a | 1493 | //............................................................................ |
QL | 0:064c79e7311a | 1494 | void QActive::stop(void) { |
QL | 0:064c79e7311a | 1495 | QF::remove_(this); // remove this active object from the QF |
QL | 0:064c79e7311a | 1496 | } |
QL | 0:064c79e7311a | 1497 | |
QL | 0:064c79e7311a | 1498 | // "qk_sched" ================================================================ |
QL | 0:064c79e7311a | 1499 | //............................................................................ |
QL | 0:064c79e7311a | 1500 | // NOTE: the QK scheduler is entered and exited with interrupts LOCKED |
QL | 0:064c79e7311a | 1501 | #ifndef QF_INT_KEY_TYPE |
QL | 0:064c79e7311a | 1502 | void QK_schedule_(void) { |
QL | 0:064c79e7311a | 1503 | #else |
QL | 0:064c79e7311a | 1504 | void QK_schedule_(QF_INT_KEY_TYPE intLockKey_) { |
QL | 0:064c79e7311a | 1505 | #endif |
QL | 0:064c79e7311a | 1506 | // the QK scheduler must be called at task level only |
QL | 0:064c79e7311a | 1507 | Q_REQUIRE(QK_intNest_ == (uint8_t)0); |
QL | 0:064c79e7311a | 1508 | |
QL | 0:064c79e7311a | 1509 | // determine the priority of the highest-priority task ready to run |
QL | 0:064c79e7311a | 1510 | uint8_t p = QK_readySet_.findMax(); |
QL | 0:064c79e7311a | 1511 | |
QL | 0:064c79e7311a | 1512 | #ifdef QK_NO_MUTEX |
QL | 0:064c79e7311a | 1513 | if (p > QK_currPrio_) { // do we have a preemption? |
QL | 0:064c79e7311a | 1514 | #else // QK priority-ceiling mutexes allowed |
QL | 0:064c79e7311a | 1515 | if ((p > QK_currPrio_) && (p > QK_ceilingPrio_)) { |
QL | 0:064c79e7311a | 1516 | #endif |
QL | 0:064c79e7311a | 1517 | uint8_t pin = QK_currPrio_; // save the initial priority |
QL | 0:064c79e7311a | 1518 | QActive *a; |
QL | 0:064c79e7311a | 1519 | #ifdef QK_TLS // thread-local storage used? |
QL | 0:064c79e7311a | 1520 | uint8_t pprev = pin; |
QL | 0:064c79e7311a | 1521 | #endif |
QL | 0:064c79e7311a | 1522 | do { |
QL | 0:064c79e7311a | 1523 | QEvent const *e; |
QL | 0:064c79e7311a | 1524 | a = QF::active_[p]; // obtain the pointer to the AO |
QL | 0:064c79e7311a | 1525 | QK_currPrio_ = p; // this becomes the current task priority |
QL | 0:064c79e7311a | 1526 | |
QL | 0:064c79e7311a | 1527 | #ifdef QK_TLS // thread-local storage used? |
QL | 0:064c79e7311a | 1528 | if (p != pprev) { // are we changing threads? |
QL | 0:064c79e7311a | 1529 | QK_TLS(a); // switch new thread-local storage |
QL | 0:064c79e7311a | 1530 | pprev = p; |
QL | 0:064c79e7311a | 1531 | } |
QL | 0:064c79e7311a | 1532 | #endif |
QL | 0:064c79e7311a | 1533 | QS_BEGIN_NOLOCK_(QS_QK_SCHEDULE, QS::aoObj_, a) |
QL | 0:064c79e7311a | 1534 | QS_TIME_(); // timestamp |
QL | 0:064c79e7311a | 1535 | QS_U8_(p); // the priority of the active object |
QL | 0:064c79e7311a | 1536 | QS_U8_(pin); // the preempted priority |
QL | 0:064c79e7311a | 1537 | QS_END_NOLOCK_() |
QL | 0:064c79e7311a | 1538 | |
QL | 0:064c79e7311a | 1539 | QK_INT_UNLOCK_(); // unlock the interrupts |
QL | 0:064c79e7311a | 1540 | |
QL | 0:064c79e7311a | 1541 | e = a->get_(); // get the next event for this active object |
QL | 0:064c79e7311a | 1542 | a->dispatch(e); // dispatch e to the active object |
QL | 0:064c79e7311a | 1543 | QF::gc(e); // garbage collect the event, if necessary |
QL | 0:064c79e7311a | 1544 | |
QL | 0:064c79e7311a | 1545 | QK_INT_LOCK_(); |
QL | 0:064c79e7311a | 1546 | // determine the highest-priority AO ready to run |
QL | 0:064c79e7311a | 1547 | if (QK_readySet_.notEmpty()) { |
QL | 0:064c79e7311a | 1548 | p = QK_readySet_.findMax(); |
QL | 0:064c79e7311a | 1549 | } |
QL | 0:064c79e7311a | 1550 | else { |
QL | 0:064c79e7311a | 1551 | p = (uint8_t)0; |
QL | 0:064c79e7311a | 1552 | } |
QL | 0:064c79e7311a | 1553 | #ifdef QK_NO_MUTEX |
QL | 0:064c79e7311a | 1554 | } while (p > pin); // is the new priority higher than initial? |
QL | 0:064c79e7311a | 1555 | #else // QK priority-ceiling mutexes allowed |
QL | 0:064c79e7311a | 1556 | } while ((p > pin) && (p > QK_ceilingPrio_)); |
QL | 0:064c79e7311a | 1557 | #endif |
QL | 0:064c79e7311a | 1558 | QK_currPrio_ = pin; // restore the initial priority |
QL | 0:064c79e7311a | 1559 | |
QL | 0:064c79e7311a | 1560 | #ifdef QK_TLS // thread-local storage used? |
QL | 0:064c79e7311a | 1561 | if (pin != (uint8_t)0) { // no extended context for the idle loop |
QL | 0:064c79e7311a | 1562 | a = QF::active_[pin]; // the pointer to the preempted AO |
QL | 0:064c79e7311a | 1563 | QK_TLS(a); // restore the original TLS |
QL | 0:064c79e7311a | 1564 | } |
QL | 0:064c79e7311a | 1565 | #endif |
QL | 0:064c79e7311a | 1566 | } |
QL | 0:064c79e7311a | 1567 | } |
QL | 0:064c79e7311a | 1568 | |
QL | 0:064c79e7311a | 1569 | // "qk_mutex.cpp" ============================================================ |
QL | 0:064c79e7311a | 1570 | #ifndef QK_NO_MUTEX |
QL | 0:064c79e7311a | 1571 | |
QL | 0:064c79e7311a | 1572 | // package-scope objects ----------------------------------------------------- |
QL | 0:064c79e7311a | 1573 | uint8_t volatile QK_ceilingPrio_; // ceiling priority of a mutex |
QL | 0:064c79e7311a | 1574 | |
QL | 0:064c79e7311a | 1575 | //............................................................................ |
QL | 0:064c79e7311a | 1576 | QMutex QK::mutexLock(uint8_t prioCeiling) { |
QL | 0:064c79e7311a | 1577 | QK_INT_LOCK_KEY_ |
QL | 0:064c79e7311a | 1578 | QK_INT_LOCK_(); |
QL | 0:064c79e7311a | 1579 | uint8_t mutex = QK_ceilingPrio_; // original QK priority ceiling to return |
QL | 0:064c79e7311a | 1580 | if (QK_ceilingPrio_ < prioCeiling) { |
QL | 0:064c79e7311a | 1581 | QK_ceilingPrio_ = prioCeiling; // raise the QK priority ceiling |
QL | 0:064c79e7311a | 1582 | } |
QL | 0:064c79e7311a | 1583 | |
QL | 0:064c79e7311a | 1584 | QS_BEGIN_NOLOCK_(QS_QK_MUTEX_LOCK, (void *)0, (void *)0) |
QL | 0:064c79e7311a | 1585 | QS_TIME_(); // timestamp |
QL | 0:064c79e7311a | 1586 | QS_U8_(mutex); // the original priority |
QL | 0:064c79e7311a | 1587 | QS_U8_(QK_ceilingPrio_); // the current priority ceiling |
QL | 0:064c79e7311a | 1588 | QS_END_NOLOCK_() |
QL | 0:064c79e7311a | 1589 | |
QL | 0:064c79e7311a | 1590 | QK_INT_UNLOCK_(); |
QL | 0:064c79e7311a | 1591 | return mutex; |
QL | 0:064c79e7311a | 1592 | } |
QL | 0:064c79e7311a | 1593 | //............................................................................ |
QL | 0:064c79e7311a | 1594 | void QK::mutexUnlock(QMutex mutex) { |
QL | 0:064c79e7311a | 1595 | QK_INT_LOCK_KEY_ |
QL | 0:064c79e7311a | 1596 | QK_INT_LOCK_(); |
QL | 0:064c79e7311a | 1597 | |
QL | 0:064c79e7311a | 1598 | QS_BEGIN_NOLOCK_(QS_QK_MUTEX_UNLOCK, (void *)0, (void *)0) |
QL | 0:064c79e7311a | 1599 | QS_TIME_(); // timestamp |
QL | 0:064c79e7311a | 1600 | QS_U8_(mutex); // the original priority |
QL | 0:064c79e7311a | 1601 | QS_U8_(QK_ceilingPrio_); // the current priority ceiling |
QL | 0:064c79e7311a | 1602 | QS_END_NOLOCK_() |
QL | 0:064c79e7311a | 1603 | |
QL | 0:064c79e7311a | 1604 | if (QK_ceilingPrio_ > mutex) { |
QL | 0:064c79e7311a | 1605 | QK_ceilingPrio_ = mutex; // restore the saved priority ceiling |
QL | 0:064c79e7311a | 1606 | QK_SCHEDULE_(); |
QL | 0:064c79e7311a | 1607 | } |
QL | 0:064c79e7311a | 1608 | QK_INT_UNLOCK_(); |
QL | 0:064c79e7311a | 1609 | } |
QL | 0:064c79e7311a | 1610 | #endif // QK_NO_MUTEX |
QL | 0:064c79e7311a | 1611 | |
QL | 0:064c79e7311a | 1612 | #else // QK_PREEMPTIVE |
QL | 0:064c79e7311a | 1613 | |
QL | 0:064c79e7311a | 1614 | // "qvanilla.cpp" ============================================================ |
QL | 0:064c79e7311a | 1615 | // Package-scope objects ----------------------------------------------------- |
QL | 0:064c79e7311a | 1616 | #if (QF_MAX_ACTIVE <= 8) |
QL | 0:064c79e7311a | 1617 | QPSet8 volatile QF_readySet_; // QF-ready set of active objects |
QL | 0:064c79e7311a | 1618 | #else |
QL | 0:064c79e7311a | 1619 | QPSet64 volatile QF_readySet_; // QF-ready set of active objects |
QL | 0:064c79e7311a | 1620 | #endif |
QL | 0:064c79e7311a | 1621 | |
QL | 0:064c79e7311a | 1622 | //............................................................................ |
QL | 0:064c79e7311a | 1623 | char const Q_ROM * Q_ROM_VAR QF::getPortVersion(void) { |
QL | 0:064c79e7311a | 1624 | static const char Q_ROM version[] = "4.0.00"; |
QL | 0:064c79e7311a | 1625 | return version; |
QL | 0:064c79e7311a | 1626 | } |
QL | 0:064c79e7311a | 1627 | //............................................................................ |
QL | 0:064c79e7311a | 1628 | void QF::init(void) { |
QL | 0:064c79e7311a | 1629 | // nothing to do for the "vanilla" kernel |
QL | 0:064c79e7311a | 1630 | } |
QL | 0:064c79e7311a | 1631 | //............................................................................ |
QL | 0:064c79e7311a | 1632 | void QActive::start(uint8_t prio, |
QL | 0:064c79e7311a | 1633 | QEvent const *qSto[], uint32_t qLen, |
QL | 0:064c79e7311a | 1634 | void *stkSto, uint32_t /*lint -e1904 stkSize */, |
QL | 0:064c79e7311a | 1635 | QEvent const *ie) |
QL | 0:064c79e7311a | 1636 | { |
QL | 0:064c79e7311a | 1637 | Q_REQUIRE(((uint8_t)0 < prio) && (prio <= (uint8_t)QF_MAX_ACTIVE) |
QL | 0:064c79e7311a | 1638 | && (stkSto == (void *)0)); // does not need per-actor stack |
QL | 0:064c79e7311a | 1639 | |
QL | 0:064c79e7311a | 1640 | m_eQueue.init(qSto, (QEQueueCtr)qLen); // initialize QEQueue |
QL | 0:064c79e7311a | 1641 | m_prio = prio; // set the QF priority of this active object |
QL | 0:064c79e7311a | 1642 | QF::add_(this); // make QF aware of this active object |
QL | 0:064c79e7311a | 1643 | init(ie); // execute initial transition |
QL | 0:064c79e7311a | 1644 | |
QL | 0:064c79e7311a | 1645 | QS_FLUSH(); // flush the trace buffer to the host |
QL | 0:064c79e7311a | 1646 | } |
QL | 0:064c79e7311a | 1647 | //............................................................................ |
QL | 0:064c79e7311a | 1648 | void QActive::stop(void) { |
QL | 0:064c79e7311a | 1649 | QF::remove_(this); |
QL | 0:064c79e7311a | 1650 | } |
QL | 0:064c79e7311a | 1651 | |
QL | 0:064c79e7311a | 1652 | //............................................................................ |
QL | 0:064c79e7311a | 1653 | void QF::stop(void) { |
QL | 0:064c79e7311a | 1654 | QF::onCleanup(); // cleanup callback |
QL | 0:064c79e7311a | 1655 | // nothing else to do for the "vanilla" kernel |
QL | 0:064c79e7311a | 1656 | } |
QL | 0:064c79e7311a | 1657 | //............................................................................ |
QL | 0:064c79e7311a | 1658 | void QF::run(void) { |
QL | 0:064c79e7311a | 1659 | QF::onStartup(); // startup callback |
QL | 0:064c79e7311a | 1660 | |
QL | 0:064c79e7311a | 1661 | for (;;) { // the bacground loop |
QL | 0:064c79e7311a | 1662 | QF_INT_LOCK_KEY_ |
QL | 0:064c79e7311a | 1663 | QF_INT_LOCK_(); |
QL | 0:064c79e7311a | 1664 | if (QF_readySet_.notEmpty()) { |
QL | 0:064c79e7311a | 1665 | uint8_t p = QF_readySet_.findMax(); |
QL | 0:064c79e7311a | 1666 | QActive *a = active_[p]; |
QL | 0:064c79e7311a | 1667 | QF_INT_UNLOCK_(); |
QL | 0:064c79e7311a | 1668 | |
QL | 0:064c79e7311a | 1669 | QEvent const *e = a->get_(); // get the next event for this AO |
QL | 0:064c79e7311a | 1670 | a->dispatch(e); // dispatch evt to the HSM |
QL | 0:064c79e7311a | 1671 | gc(e); // determine if event is garbage and collect it if so |
QL | 0:064c79e7311a | 1672 | } |
QL | 0:064c79e7311a | 1673 | else { |
QL | 0:064c79e7311a | 1674 | #ifndef QF_INT_KEY_TYPE |
QL | 0:064c79e7311a | 1675 | onIdle(); // see NOTE01 |
QL | 0:064c79e7311a | 1676 | #else |
QL | 0:064c79e7311a | 1677 | onIdle(intLockKey_); // see NOTE01 |
QL | 0:064c79e7311a | 1678 | #endif // QF_INT_KEY_TYPE |
QL | 0:064c79e7311a | 1679 | } |
QL | 0:064c79e7311a | 1680 | } |
QL | 0:064c79e7311a | 1681 | } |
QL | 0:064c79e7311a | 1682 | |
QL | 0:064c79e7311a | 1683 | ////////////////////////////////////////////////////////////////////////////// |
QL | 0:064c79e7311a | 1684 | // NOTE01: |
QL | 0:064c79e7311a | 1685 | // QF::onIdle() must be called with interrupts LOCKED because the |
QL | 0:064c79e7311a | 1686 | // determination of the idle condition (no events in the queues) can change |
QL | 0:064c79e7311a | 1687 | // at any time by an interrupt posting events to a queue. The QF::onIdle() |
QL | 0:064c79e7311a | 1688 | // MUST enable interrups internally, perhaps at the same time as putting the |
QL | 0:064c79e7311a | 1689 | // CPU into a power-saving mode. |
QL | 0:064c79e7311a | 1690 | // |
QL | 0:064c79e7311a | 1691 | |
QL | 0:064c79e7311a | 1692 | #endif // QK_PREEMPTIVE |
QL | 0:064c79e7311a | 1693 | |
QL | 0:064c79e7311a | 1694 | ////////////////////////////////////////////////////////////////////////////// |
QL | 0:064c79e7311a | 1695 | #ifdef Q_SPY |
QL | 0:064c79e7311a | 1696 | |
QL | 0:064c79e7311a | 1697 | // "qs_pkg.h" ================================================================ |
QL | 0:064c79e7311a | 1698 | /// \brief QS ring buffer counter and offset type |
QL | 0:064c79e7311a | 1699 | typedef uint16_t QSCtr; |
QL | 0:064c79e7311a | 1700 | |
QL | 0:064c79e7311a | 1701 | /// \brief Internal QS macro to insert an un-escaped byte into |
QL | 0:064c79e7311a | 1702 | /// the QS buffer |
QL | 0:064c79e7311a | 1703 | //// |
QL | 0:064c79e7311a | 1704 | #define QS_INSERT_BYTE(b_) \ |
QL | 0:064c79e7311a | 1705 | QS_ring_[QS_head_] = (b_); \ |
QL | 0:064c79e7311a | 1706 | ++QS_head_; \ |
QL | 0:064c79e7311a | 1707 | if (QS_head_ == QS_end_) { \ |
QL | 0:064c79e7311a | 1708 | QS_head_ = (QSCtr)0; \ |
QL | 0:064c79e7311a | 1709 | } \ |
QL | 0:064c79e7311a | 1710 | ++QS_used_; |
QL | 0:064c79e7311a | 1711 | |
QL | 0:064c79e7311a | 1712 | /// \brief Internal QS macro to insert an escaped byte into the QS buffer |
QL | 0:064c79e7311a | 1713 | #define QS_INSERT_ESC_BYTE(b_) \ |
QL | 0:064c79e7311a | 1714 | QS_chksum_ = (uint8_t)(QS_chksum_ + (b_)); \ |
QL | 0:064c79e7311a | 1715 | if (((b_) == QS_FRAME) || ((b_) == QS_ESC)) { \ |
QL | 0:064c79e7311a | 1716 | QS_INSERT_BYTE(QS_ESC) \ |
QL | 0:064c79e7311a | 1717 | QS_INSERT_BYTE((uint8_t)((b_) ^ QS_ESC_XOR)) \ |
QL | 0:064c79e7311a | 1718 | } \ |
QL | 0:064c79e7311a | 1719 | else { \ |
QL | 0:064c79e7311a | 1720 | QS_INSERT_BYTE(b_) \ |
QL | 0:064c79e7311a | 1721 | } |
QL | 0:064c79e7311a | 1722 | |
QL | 0:064c79e7311a | 1723 | /// \brief Internal QS macro to insert a escaped checksum byte into |
QL | 0:064c79e7311a | 1724 | /// the QS buffer |
QL | 0:064c79e7311a | 1725 | #define QS_INSERT_CHKSUM_BYTE() \ |
QL | 0:064c79e7311a | 1726 | QS_chksum_ = (uint8_t)~QS_chksum_; \ |
QL | 0:064c79e7311a | 1727 | if ((QS_chksum_ == QS_FRAME) || (QS_chksum_ == QS_ESC)) { \ |
QL | 0:064c79e7311a | 1728 | QS_INSERT_BYTE(QS_ESC) \ |
QL | 0:064c79e7311a | 1729 | QS_INSERT_BYTE((uint8_t)(QS_chksum_ ^ QS_ESC_XOR)) \ |
QL | 0:064c79e7311a | 1730 | } \ |
QL | 0:064c79e7311a | 1731 | else { \ |
QL | 0:064c79e7311a | 1732 | QS_INSERT_BYTE(QS_chksum_) \ |
QL | 0:064c79e7311a | 1733 | } |
QL | 0:064c79e7311a | 1734 | |
QL | 0:064c79e7311a | 1735 | |
QL | 0:064c79e7311a | 1736 | /// \brief Frame character of the QS output protocol |
QL | 0:064c79e7311a | 1737 | #define QS_FRAME ((uint8_t)0x7E) |
QL | 0:064c79e7311a | 1738 | |
QL | 0:064c79e7311a | 1739 | /// \brief Escape character of the QS output protocol |
QL | 0:064c79e7311a | 1740 | #define QS_ESC ((uint8_t)0x7D) |
QL | 0:064c79e7311a | 1741 | |
QL | 0:064c79e7311a | 1742 | /// \brief Escape modifier of the QS output protocol |
QL | 0:064c79e7311a | 1743 | /// |
QL | 0:064c79e7311a | 1744 | /// The escaped byte is XOR-ed with the escape modifier before it is inserted |
QL | 0:064c79e7311a | 1745 | /// into the QS buffer. |
QL | 0:064c79e7311a | 1746 | #define QS_ESC_XOR 0x20 |
QL | 0:064c79e7311a | 1747 | |
QL | 0:064c79e7311a | 1748 | #ifndef Q_ROM_BYTE |
QL | 0:064c79e7311a | 1749 | /// \brief Macro to access a byte allocated in ROM |
QL | 0:064c79e7311a | 1750 | /// |
QL | 0:064c79e7311a | 1751 | /// Some compilers for Harvard-architecture MCUs, such as gcc for AVR, do |
QL | 0:064c79e7311a | 1752 | /// not generate correct code for accessing data allocated in the program |
QL | 0:064c79e7311a | 1753 | /// space (ROM). The workaround for such compilers is to explictly add |
QL | 0:064c79e7311a | 1754 | /// assembly code to access each data element allocated in the program |
QL | 0:064c79e7311a | 1755 | /// space. The macro Q_ROM_BYTE() retrieves a byte from the given ROM |
QL | 0:064c79e7311a | 1756 | /// address. |
QL | 0:064c79e7311a | 1757 | /// |
QL | 0:064c79e7311a | 1758 | /// The Q_ROM_BYTE() macro should be defined for the compilers that |
QL | 0:064c79e7311a | 1759 | /// cannot handle correctly data allocated in ROM (such as the gcc). |
QL | 0:064c79e7311a | 1760 | /// If the macro is left undefined, the default definition simply returns |
QL | 0:064c79e7311a | 1761 | /// the argument and lets the compiler generate the correct code. |
QL | 0:064c79e7311a | 1762 | #define Q_ROM_BYTE(rom_var_) (rom_var_) |
QL | 0:064c79e7311a | 1763 | #endif |
QL | 0:064c79e7311a | 1764 | |
QL | 0:064c79e7311a | 1765 | //............................................................................ |
QL | 0:064c79e7311a | 1766 | extern uint8_t *QS_ring_; ///< pointer to the start of the ring buffer |
QL | 0:064c79e7311a | 1767 | extern QSCtr QS_end_; ///< offset of the end of the ring buffer |
QL | 0:064c79e7311a | 1768 | extern QSCtr QS_head_; ///< offset to where next byte will be inserted |
QL | 0:064c79e7311a | 1769 | extern QSCtr QS_tail_; ///< offset of where next event will be extracted |
QL | 0:064c79e7311a | 1770 | extern QSCtr QS_used_; ///< number of bytes currently in the ring buffer |
QL | 0:064c79e7311a | 1771 | extern uint8_t QS_seq_; ///< the record sequence number |
QL | 0:064c79e7311a | 1772 | extern uint8_t QS_chksum_; ///< the checksum of the current record |
QL | 0:064c79e7311a | 1773 | extern uint8_t QS_full_; ///< the ring buffer is temporarily full |
QL | 0:064c79e7311a | 1774 | |
QL | 0:064c79e7311a | 1775 | // "qs.cpp" ================================================================== |
QL | 0:064c79e7311a | 1776 | //............................................................................ |
QL | 0:064c79e7311a | 1777 | uint8_t QS::glbFilter_[32]; // global QS filter |
QL | 0:064c79e7311a | 1778 | |
QL | 0:064c79e7311a | 1779 | //............................................................................ |
QL | 0:064c79e7311a | 1780 | uint8_t *QS_ring_; // pointer to the start of the ring buffer |
QL | 0:064c79e7311a | 1781 | QSCtr QS_end_; // offset of the end of the ring buffer |
QL | 0:064c79e7311a | 1782 | QSCtr QS_head_; // offset to where next byte will be inserted |
QL | 0:064c79e7311a | 1783 | QSCtr QS_tail_; // offset of where next byte will be extracted |
QL | 0:064c79e7311a | 1784 | QSCtr QS_used_; // number of bytes currently in the ring buffer |
QL | 0:064c79e7311a | 1785 | uint8_t QS_seq_; // the record sequence number |
QL | 0:064c79e7311a | 1786 | uint8_t QS_chksum_; // the checksum of the current record |
QL | 0:064c79e7311a | 1787 | uint8_t QS_full_; // the ring buffer is temporarily full |
QL | 0:064c79e7311a | 1788 | |
QL | 0:064c79e7311a | 1789 | //............................................................................ |
QL | 0:064c79e7311a | 1790 | //lint -e970 -e971 ignore MISRA rules 13 and 14 in this function |
QL | 0:064c79e7311a | 1791 | char const Q_ROM * Q_ROM_VAR QS::getVersion(void) { |
QL | 0:064c79e7311a | 1792 | static char const Q_ROM Q_ROM_VAR version[] = { |
QL | 0:064c79e7311a | 1793 | ((QP_VERSION >> 12) & 0xF) + '0', |
QL | 0:064c79e7311a | 1794 | '.', |
QL | 0:064c79e7311a | 1795 | ((QP_VERSION >> 8) & 0xF) + '0', |
QL | 0:064c79e7311a | 1796 | '.', |
QL | 0:064c79e7311a | 1797 | ((QP_VERSION >> 4) & 0xF) + '0', |
QL | 0:064c79e7311a | 1798 | (QP_VERSION & 0xF) + '0', |
QL | 0:064c79e7311a | 1799 | '\0' |
QL | 0:064c79e7311a | 1800 | }; |
QL | 0:064c79e7311a | 1801 | return version; |
QL | 0:064c79e7311a | 1802 | } |
QL | 0:064c79e7311a | 1803 | //............................................................................ |
QL | 0:064c79e7311a | 1804 | void QS::initBuf(uint8_t sto[], uint32_t stoSize) { |
QL | 0:064c79e7311a | 1805 | QS_ring_ = &sto[0]; |
QL | 0:064c79e7311a | 1806 | QS_end_ = (QSCtr)stoSize; |
QL | 0:064c79e7311a | 1807 | } |
QL | 0:064c79e7311a | 1808 | //............................................................................ |
QL | 0:064c79e7311a | 1809 | void QS::filterOn(uint8_t rec) { |
QL | 0:064c79e7311a | 1810 | if (rec == QS_ALL_RECORDS) { |
QL | 0:064c79e7311a | 1811 | uint8_t i; |
QL | 0:064c79e7311a | 1812 | for (i = (uint8_t)0; i < (uint8_t)sizeof(glbFilter_); ++i) { |
QL | 0:064c79e7311a | 1813 | glbFilter_[i] = (uint8_t)0xFF; |
QL | 0:064c79e7311a | 1814 | } |
QL | 0:064c79e7311a | 1815 | } |
QL | 0:064c79e7311a | 1816 | else { |
QL | 0:064c79e7311a | 1817 | glbFilter_[rec >> 3] |= (uint8_t)(1U << (rec & 0x07)); |
QL | 0:064c79e7311a | 1818 | } |
QL | 0:064c79e7311a | 1819 | } |
QL | 0:064c79e7311a | 1820 | //............................................................................ |
QL | 0:064c79e7311a | 1821 | void QS::filterOff(uint8_t rec) { |
QL | 0:064c79e7311a | 1822 | if (rec == QS_ALL_RECORDS) { |
QL | 0:064c79e7311a | 1823 | uint8_t i; |
QL | 0:064c79e7311a | 1824 | for (i = (uint8_t)0; i < (uint8_t)sizeof(glbFilter_); ++i) { |
QL | 0:064c79e7311a | 1825 | glbFilter_[i] = (uint8_t)0; |
QL | 0:064c79e7311a | 1826 | } |
QL | 0:064c79e7311a | 1827 | } |
QL | 0:064c79e7311a | 1828 | else { |
QL | 0:064c79e7311a | 1829 | glbFilter_[rec >> 3] &= (uint8_t)(~(1U << (rec & 0x07))); |
QL | 0:064c79e7311a | 1830 | } |
QL | 0:064c79e7311a | 1831 | } |
QL | 0:064c79e7311a | 1832 | //............................................................................ |
QL | 0:064c79e7311a | 1833 | void QS::begin(uint8_t rec) { |
QL | 0:064c79e7311a | 1834 | QS_chksum_ = (uint8_t)0; // clear the checksum |
QL | 0:064c79e7311a | 1835 | ++QS_seq_; // always increment the sequence number |
QL | 0:064c79e7311a | 1836 | QS_INSERT_ESC_BYTE(QS_seq_) // store the sequence number |
QL | 0:064c79e7311a | 1837 | QS_INSERT_ESC_BYTE(rec) // store the record ID |
QL | 0:064c79e7311a | 1838 | } |
QL | 0:064c79e7311a | 1839 | //............................................................................ |
QL | 0:064c79e7311a | 1840 | void QS::end(void) { |
QL | 0:064c79e7311a | 1841 | QS_INSERT_CHKSUM_BYTE() |
QL | 0:064c79e7311a | 1842 | QS_INSERT_BYTE(QS_FRAME) |
QL | 0:064c79e7311a | 1843 | if (QS_used_ > QS_end_) { // overrun over the old data? |
QL | 0:064c79e7311a | 1844 | QS_tail_ = QS_head_; // shift the tail to the old data |
QL | 0:064c79e7311a | 1845 | QS_used_ = QS_end_; // the whole buffer is used |
QL | 0:064c79e7311a | 1846 | } |
QL | 0:064c79e7311a | 1847 | } |
QL | 0:064c79e7311a | 1848 | //............................................................................ |
QL | 0:064c79e7311a | 1849 | void QS::u8(uint8_t format, uint8_t d) { |
QL | 0:064c79e7311a | 1850 | QS_INSERT_ESC_BYTE(format) |
QL | 0:064c79e7311a | 1851 | QS_INSERT_ESC_BYTE(d) |
QL | 0:064c79e7311a | 1852 | } |
QL | 0:064c79e7311a | 1853 | //............................................................................ |
QL | 0:064c79e7311a | 1854 | void QS::u16(uint8_t format, uint16_t d) { |
QL | 0:064c79e7311a | 1855 | QS_INSERT_ESC_BYTE(format) |
QL | 0:064c79e7311a | 1856 | QS_INSERT_ESC_BYTE((uint8_t)d) |
QL | 0:064c79e7311a | 1857 | d >>= 8; |
QL | 0:064c79e7311a | 1858 | QS_INSERT_ESC_BYTE((uint8_t)d) |
QL | 0:064c79e7311a | 1859 | } |
QL | 0:064c79e7311a | 1860 | //............................................................................ |
QL | 0:064c79e7311a | 1861 | void QS::u32(uint8_t format, uint32_t d) { |
QL | 0:064c79e7311a | 1862 | QS_INSERT_ESC_BYTE(format) |
QL | 0:064c79e7311a | 1863 | QS_INSERT_ESC_BYTE((uint8_t)d) |
QL | 0:064c79e7311a | 1864 | d >>= 8; |
QL | 0:064c79e7311a | 1865 | QS_INSERT_ESC_BYTE((uint8_t)d) |
QL | 0:064c79e7311a | 1866 | d >>= 8; |
QL | 0:064c79e7311a | 1867 | QS_INSERT_ESC_BYTE((uint8_t)d) |
QL | 0:064c79e7311a | 1868 | d >>= 8; |
QL | 0:064c79e7311a | 1869 | QS_INSERT_ESC_BYTE((uint8_t)d) |
QL | 0:064c79e7311a | 1870 | } |
QL | 0:064c79e7311a | 1871 | |
QL | 0:064c79e7311a | 1872 | // "qs_.cpp" ================================================================= |
QL | 0:064c79e7311a | 1873 | //............................................................................ |
QL | 0:064c79e7311a | 1874 | void const *QS::smObj_; // local state machine for QEP filter |
QL | 0:064c79e7311a | 1875 | void const *QS::aoObj_; // local active object for QF filter |
QL | 0:064c79e7311a | 1876 | void const *QS::mpObj_; // local event pool for QF filter |
QL | 0:064c79e7311a | 1877 | void const *QS::eqObj_; // local raw queue for QF filter |
QL | 0:064c79e7311a | 1878 | void const *QS::teObj_; // local time event for QF filter |
QL | 0:064c79e7311a | 1879 | void const *QS::apObj_; // local object Application filter |
QL | 0:064c79e7311a | 1880 | |
QL | 0:064c79e7311a | 1881 | QSTimeCtr volatile QS::tickCtr_; // tick counter for the QS_QF_TICK record |
QL | 0:064c79e7311a | 1882 | |
QL | 0:064c79e7311a | 1883 | //............................................................................ |
QL | 0:064c79e7311a | 1884 | void QS::u8_(uint8_t d) { |
QL | 0:064c79e7311a | 1885 | QS_INSERT_ESC_BYTE(d) |
QL | 0:064c79e7311a | 1886 | } |
QL | 0:064c79e7311a | 1887 | //............................................................................ |
QL | 0:064c79e7311a | 1888 | void QS::u16_(uint16_t d) { |
QL | 0:064c79e7311a | 1889 | QS_INSERT_ESC_BYTE((uint8_t)d) |
QL | 0:064c79e7311a | 1890 | d >>= 8; |
QL | 0:064c79e7311a | 1891 | QS_INSERT_ESC_BYTE((uint8_t)d) |
QL | 0:064c79e7311a | 1892 | } |
QL | 0:064c79e7311a | 1893 | //............................................................................ |
QL | 0:064c79e7311a | 1894 | void QS::u32_(uint32_t d) { |
QL | 0:064c79e7311a | 1895 | QS_INSERT_ESC_BYTE((uint8_t)d) |
QL | 0:064c79e7311a | 1896 | d >>= 8; |
QL | 0:064c79e7311a | 1897 | QS_INSERT_ESC_BYTE((uint8_t)d) |
QL | 0:064c79e7311a | 1898 | d >>= 8; |
QL | 0:064c79e7311a | 1899 | QS_INSERT_ESC_BYTE((uint8_t)d) |
QL | 0:064c79e7311a | 1900 | d >>= 8; |
QL | 0:064c79e7311a | 1901 | QS_INSERT_ESC_BYTE((uint8_t)d) |
QL | 0:064c79e7311a | 1902 | } |
QL | 0:064c79e7311a | 1903 | //............................................................................ |
QL | 0:064c79e7311a | 1904 | //lint -e970 -e971 ignore MISRA rules 13 and 14 in this function |
QL | 0:064c79e7311a | 1905 | void QS::str_(char const *s) { |
QL | 0:064c79e7311a | 1906 | while (*s != '\0') { |
QL | 0:064c79e7311a | 1907 | // ASCII characters don't need escaping |
QL | 0:064c79e7311a | 1908 | QS_chksum_ = (uint8_t)(QS_chksum_ + (uint8_t)(*s)); |
QL | 0:064c79e7311a | 1909 | QS_INSERT_BYTE((uint8_t)(*s)) |
QL | 0:064c79e7311a | 1910 | ++s; |
QL | 0:064c79e7311a | 1911 | } |
QL | 0:064c79e7311a | 1912 | QS_INSERT_BYTE((uint8_t)0) |
QL | 0:064c79e7311a | 1913 | } |
QL | 0:064c79e7311a | 1914 | //............................................................................ |
QL | 0:064c79e7311a | 1915 | //lint -e970 -e971 ignore MISRA rules 13 and 14 in this function |
QL | 0:064c79e7311a | 1916 | void QS::str_ROM_(char const Q_ROM * Q_ROM_VAR s) { |
QL | 0:064c79e7311a | 1917 | uint8_t b; |
QL | 0:064c79e7311a | 1918 | while ((b = (uint8_t)Q_ROM_BYTE(*s)) != (uint8_t)0) { |
QL | 0:064c79e7311a | 1919 | // ASCII characters don't need escaping |
QL | 0:064c79e7311a | 1920 | QS_chksum_ = (uint8_t)(QS_chksum_ + b); |
QL | 0:064c79e7311a | 1921 | QS_INSERT_BYTE(b) |
QL | 0:064c79e7311a | 1922 | ++s; |
QL | 0:064c79e7311a | 1923 | } |
QL | 0:064c79e7311a | 1924 | QS_INSERT_BYTE((uint8_t)0) |
QL | 0:064c79e7311a | 1925 | } |
QL | 0:064c79e7311a | 1926 | |
QL | 0:064c79e7311a | 1927 | // "qs_blk.cpp" ============================================================== |
QL | 0:064c79e7311a | 1928 | //............................................................................ |
QL | 0:064c79e7311a | 1929 | // get up to *pn bytes of contiguous memory |
QL | 0:064c79e7311a | 1930 | uint8_t const *QS::getBlock(uint16_t *pNbytes) { |
QL | 0:064c79e7311a | 1931 | uint8_t *block; |
QL | 0:064c79e7311a | 1932 | if (QS_used_ == (QSCtr)0) { |
QL | 0:064c79e7311a | 1933 | *pNbytes = (uint16_t)0; |
QL | 0:064c79e7311a | 1934 | block = (uint8_t *)0; // no bytes to return right now |
QL | 0:064c79e7311a | 1935 | } |
QL | 0:064c79e7311a | 1936 | else { |
QL | 0:064c79e7311a | 1937 | QSCtr n = (QSCtr)(QS_end_ - QS_tail_); |
QL | 0:064c79e7311a | 1938 | if (n > QS_used_) { |
QL | 0:064c79e7311a | 1939 | n = QS_used_; |
QL | 0:064c79e7311a | 1940 | } |
QL | 0:064c79e7311a | 1941 | if (n > (QSCtr)(*pNbytes)) { |
QL | 0:064c79e7311a | 1942 | n = (QSCtr)(*pNbytes); |
QL | 0:064c79e7311a | 1943 | } |
QL | 0:064c79e7311a | 1944 | *pNbytes = (uint16_t)n; |
QL | 0:064c79e7311a | 1945 | QS_used_ = (QSCtr)(QS_used_ - n); |
QL | 0:064c79e7311a | 1946 | QSCtr t = QS_tail_; |
QL | 0:064c79e7311a | 1947 | QS_tail_ = (QSCtr)(QS_tail_ + n); |
QL | 0:064c79e7311a | 1948 | if (QS_tail_ == QS_end_) { |
QL | 0:064c79e7311a | 1949 | QS_tail_ = (QSCtr)0; |
QL | 0:064c79e7311a | 1950 | } |
QL | 0:064c79e7311a | 1951 | block = &QS_ring_[t]; |
QL | 0:064c79e7311a | 1952 | } |
QL | 0:064c79e7311a | 1953 | return block; |
QL | 0:064c79e7311a | 1954 | } |
QL | 0:064c79e7311a | 1955 | |
QL | 0:064c79e7311a | 1956 | // "qs_byte.cpp" ============================================================= |
QL | 0:064c79e7311a | 1957 | //............................................................................ |
QL | 0:064c79e7311a | 1958 | uint16_t QS::getByte(void) { |
QL | 0:064c79e7311a | 1959 | uint16_t ret; |
QL | 0:064c79e7311a | 1960 | if (QS_used_ == (QSCtr)0) { |
QL | 0:064c79e7311a | 1961 | ret = QS_EOD; // set End-Of-Data |
QL | 0:064c79e7311a | 1962 | } |
QL | 0:064c79e7311a | 1963 | else { |
QL | 0:064c79e7311a | 1964 | ret = QS_ring_[QS_tail_]; // set the byte to return |
QL | 0:064c79e7311a | 1965 | ++QS_tail_; // advance the tail |
QL | 0:064c79e7311a | 1966 | if (QS_tail_ == QS_end_) { // tail wrap around? |
QL | 0:064c79e7311a | 1967 | QS_tail_ = (QSCtr)0; |
QL | 0:064c79e7311a | 1968 | } |
QL | 0:064c79e7311a | 1969 | --QS_used_; // one less byte used |
QL | 0:064c79e7311a | 1970 | } |
QL | 0:064c79e7311a | 1971 | return ret; // return the byte or EOD |
QL | 0:064c79e7311a | 1972 | } |
QL | 0:064c79e7311a | 1973 | |
QL | 0:064c79e7311a | 1974 | // "qs_f32.cpp" ============================================================== |
QL | 0:064c79e7311a | 1975 | //............................................................................ |
QL | 0:064c79e7311a | 1976 | void QS::f32(uint8_t format, float f) { |
QL | 0:064c79e7311a | 1977 | union F32Rep { |
QL | 0:064c79e7311a | 1978 | float f; |
QL | 0:064c79e7311a | 1979 | uint32_t u; |
QL | 0:064c79e7311a | 1980 | } fu32; |
QL | 0:064c79e7311a | 1981 | fu32.f = f; |
QL | 0:064c79e7311a | 1982 | |
QL | 0:064c79e7311a | 1983 | QS_INSERT_ESC_BYTE(format) |
QL | 0:064c79e7311a | 1984 | QS_INSERT_ESC_BYTE((uint8_t)fu32.u) |
QL | 0:064c79e7311a | 1985 | fu32.u >>= 8; |
QL | 0:064c79e7311a | 1986 | QS_INSERT_ESC_BYTE((uint8_t)fu32.u) |
QL | 0:064c79e7311a | 1987 | fu32.u >>= 8; |
QL | 0:064c79e7311a | 1988 | QS_INSERT_ESC_BYTE((uint8_t)fu32.u) |
QL | 0:064c79e7311a | 1989 | fu32.u >>= 8; |
QL | 0:064c79e7311a | 1990 | QS_INSERT_ESC_BYTE((uint8_t)fu32.u) |
QL | 0:064c79e7311a | 1991 | } |
QL | 0:064c79e7311a | 1992 | |
QL | 0:064c79e7311a | 1993 | // "qs_f64.cpp" ============================================================== |
QL | 0:064c79e7311a | 1994 | //............................................................................ |
QL | 0:064c79e7311a | 1995 | void QS::f64(uint8_t format, double d) { |
QL | 0:064c79e7311a | 1996 | union F64Rep { |
QL | 0:064c79e7311a | 1997 | double d; |
QL | 0:064c79e7311a | 1998 | struct UInt2 { |
QL | 0:064c79e7311a | 1999 | uint32_t u1, u2; |
QL | 0:064c79e7311a | 2000 | } i; |
QL | 0:064c79e7311a | 2001 | } fu64; |
QL | 0:064c79e7311a | 2002 | fu64.d = d; |
QL | 0:064c79e7311a | 2003 | |
QL | 0:064c79e7311a | 2004 | QS_INSERT_ESC_BYTE(format) |
QL | 0:064c79e7311a | 2005 | |
QL | 0:064c79e7311a | 2006 | QS_INSERT_ESC_BYTE((uint8_t)fu64.i.u1) |
QL | 0:064c79e7311a | 2007 | fu64.i.u1 >>= 8; |
QL | 0:064c79e7311a | 2008 | QS_INSERT_ESC_BYTE((uint8_t)fu64.i.u1) |
QL | 0:064c79e7311a | 2009 | fu64.i.u1 >>= 8; |
QL | 0:064c79e7311a | 2010 | QS_INSERT_ESC_BYTE((uint8_t)fu64.i.u1) |
QL | 0:064c79e7311a | 2011 | fu64.i.u1 >>= 8; |
QL | 0:064c79e7311a | 2012 | QS_INSERT_ESC_BYTE((uint8_t)fu64.i.u1) |
QL | 0:064c79e7311a | 2013 | |
QL | 0:064c79e7311a | 2014 | QS_INSERT_ESC_BYTE((uint8_t)fu64.i.u2) |
QL | 0:064c79e7311a | 2015 | fu64.i.u2 >>= 8; |
QL | 0:064c79e7311a | 2016 | QS_INSERT_ESC_BYTE((uint8_t)fu64.i.u2) |
QL | 0:064c79e7311a | 2017 | fu64.i.u2 >>= 8; |
QL | 0:064c79e7311a | 2018 | QS_INSERT_ESC_BYTE((uint8_t)fu64.i.u2) |
QL | 0:064c79e7311a | 2019 | fu64.i.u2 >>= 8; |
QL | 0:064c79e7311a | 2020 | QS_INSERT_ESC_BYTE((uint8_t)fu64.i.u2) |
QL | 0:064c79e7311a | 2021 | } |
QL | 0:064c79e7311a | 2022 | |
QL | 0:064c79e7311a | 2023 | // "qs_mem.cpp" ============================================================== |
QL | 0:064c79e7311a | 2024 | //............................................................................ |
QL | 0:064c79e7311a | 2025 | void QS::mem(uint8_t const *blk, uint8_t size) { |
QL | 0:064c79e7311a | 2026 | QS_INSERT_BYTE((uint8_t)QS_MEM_T) |
QL | 0:064c79e7311a | 2027 | QS_chksum_ = (uint8_t)(QS_chksum_ + (uint8_t)QS_MEM_T); |
QL | 0:064c79e7311a | 2028 | QS_INSERT_ESC_BYTE(size) |
QL | 0:064c79e7311a | 2029 | while (size != (uint8_t)0) { |
QL | 0:064c79e7311a | 2030 | QS_INSERT_ESC_BYTE(*blk) |
QL | 0:064c79e7311a | 2031 | ++blk; |
QL | 0:064c79e7311a | 2032 | --size; |
QL | 0:064c79e7311a | 2033 | } |
QL | 0:064c79e7311a | 2034 | } |
QL | 0:064c79e7311a | 2035 | |
QL | 0:064c79e7311a | 2036 | // "qs_str.cpp" ============================================================== |
QL | 0:064c79e7311a | 2037 | //............................................................................ |
QL | 0:064c79e7311a | 2038 | //lint -e970 -e971 ignore MISRA rules 13 and 14 in this function |
QL | 0:064c79e7311a | 2039 | void QS::str(char const *s) { |
QL | 0:064c79e7311a | 2040 | QS_INSERT_BYTE((uint8_t)QS_STR_T) |
QL | 0:064c79e7311a | 2041 | QS_chksum_ = (uint8_t)(QS_chksum_ + (uint8_t)QS_STR_T); |
QL | 0:064c79e7311a | 2042 | while ((*s) != '\0') { |
QL | 0:064c79e7311a | 2043 | // ASCII characters don't need escaping |
QL | 0:064c79e7311a | 2044 | QS_INSERT_BYTE((uint8_t)(*s)) |
QL | 0:064c79e7311a | 2045 | QS_chksum_ = (uint8_t)(QS_chksum_ + (uint8_t)(*s)); |
QL | 0:064c79e7311a | 2046 | ++s; |
QL | 0:064c79e7311a | 2047 | } |
QL | 0:064c79e7311a | 2048 | QS_INSERT_BYTE((uint8_t)0) |
QL | 0:064c79e7311a | 2049 | } |
QL | 0:064c79e7311a | 2050 | //............................................................................ |
QL | 0:064c79e7311a | 2051 | //lint -e970 -e971 ignore MISRA rules 13 and 14 in this function |
QL | 0:064c79e7311a | 2052 | void QS::str_ROM(char const Q_ROM * Q_ROM_VAR s) { |
QL | 0:064c79e7311a | 2053 | QS_INSERT_BYTE((uint8_t)QS_STR_T) |
QL | 0:064c79e7311a | 2054 | QS_chksum_ = (uint8_t)(QS_chksum_ + (uint8_t)QS_STR_T); |
QL | 0:064c79e7311a | 2055 | uint8_t b; |
QL | 0:064c79e7311a | 2056 | while ((b = (uint8_t)Q_ROM_BYTE(*s)) != (uint8_t)0) { |
QL | 0:064c79e7311a | 2057 | // ASCII characters don't need escaping |
QL | 0:064c79e7311a | 2058 | QS_INSERT_BYTE(b) |
QL | 0:064c79e7311a | 2059 | QS_chksum_ = (uint8_t)(QS_chksum_ + b); |
QL | 0:064c79e7311a | 2060 | ++s; |
QL | 0:064c79e7311a | 2061 | } |
QL | 0:064c79e7311a | 2062 | QS_INSERT_BYTE((uint8_t)0) |
QL | 0:064c79e7311a | 2063 | } |
QL | 0:064c79e7311a | 2064 | |
QL | 0:064c79e7311a | 2065 | #endif // Q_SPY |
QL | 0:064c79e7311a | 2066 | |
QL | 0:064c79e7311a | 2067 |