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.

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?

UserRevisionLine numberNew 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