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:
Mon Sep 26 01:42:32 2011 +0000
Revision:
6:01d57c81e96a
Parent:
0:064c79e7311a
Child:
7:bf92d3a6625e
4.2.04

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