QP is an event-driven, RTOS-like, active object framework for microcontrollers, such as mbed. The QP framework provides thread-safe execution of active objects (concurrent state machines) and support both manual and automatic coding of UML statecharts in readable, production-quality C or C++. Automatic code generation of QP code is supported by the free QM modeling tool.
Dependents: qp_hangman qp_dpp qp_blinky
QP/C++ (Quantum Platform in C++) is a lightweight, open source active object (actor) framework for building responsive and modular real-time embedded applications as systems of asynchronous event-driven active objects (actors). The QP/C++ framework is a member of a larger family consisting of QP/C++, QP/C, and QP-nano frameworks, which are all strictly quality controlled, thoroughly documented, and available under GPLv3 with a special Exception for mbed (see http://www.state-machine.com/licensing/QP-mbed_GPL_Exception.txt).
The behavior of active objects is specified in QP/C++ by means of hierarchical state machines (UML statecharts). The framework supports manual coding of UML state machines in C++ as well as automatic code generation by means of the free QM modeling tool (http://www.state-machine.com/qm).
Please see the "QP/C++ Reference Manual" (http://www.state-machine.com/qpcpp) for more information.
qp.cpp@9:ca2e6010d9e2, 2012-09-04 (annotated)
- Committer:
- QL
- Date:
- Tue Sep 04 22:20:52 2012 +0000
- Revision:
- 9:ca2e6010d9e2
- Parent:
- 7:bf92d3a6625e
QP/C++ 4.5.02 compatible with QM 2.2.xx
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
QL | 9:ca2e6010d9e2 | 1 | ////////////////////////////////////////////////////////////////////////////// |
QL | 9:ca2e6010d9e2 | 2 | // Product: QP/C++ |
QL | 9:ca2e6010d9e2 | 3 | // Last Updated for QP ver: 4.5.02 (modified to fit in one file) |
QL | 9:ca2e6010d9e2 | 4 | // Date of the Last Update: Aug 24, 2012 |
QL | 9:ca2e6010d9e2 | 5 | // |
QL | 9:ca2e6010d9e2 | 6 | // Q u a n t u m L e a P s |
QL | 9:ca2e6010d9e2 | 7 | // --------------------------- |
QL | 9:ca2e6010d9e2 | 8 | // innovating embedded systems |
QL | 9:ca2e6010d9e2 | 9 | // |
QL | 9:ca2e6010d9e2 | 10 | // Copyright (C) 2002-2012 Quantum Leaps, LLC. All rights reserved. |
QL | 9:ca2e6010d9e2 | 11 | // |
QL | 9:ca2e6010d9e2 | 12 | // This program is open source software: you can redistribute it and/or |
QL | 9:ca2e6010d9e2 | 13 | // modify it under the terms of the GNU General Public License as published |
QL | 9:ca2e6010d9e2 | 14 | // by the Free Software Foundation, either version 2 of the License, or |
QL | 9:ca2e6010d9e2 | 15 | // (at your option) any later version. |
QL | 9:ca2e6010d9e2 | 16 | // |
QL | 9:ca2e6010d9e2 | 17 | // Alternatively, this program may be distributed and modified under the |
QL | 9:ca2e6010d9e2 | 18 | // terms of Quantum Leaps commercial licenses, which expressly supersede |
QL | 9:ca2e6010d9e2 | 19 | // the GNU General Public License and are specifically designed for |
QL | 9:ca2e6010d9e2 | 20 | // licensees interested in retaining the proprietary status of their code. |
QL | 9:ca2e6010d9e2 | 21 | // |
QL | 9:ca2e6010d9e2 | 22 | // This program is distributed in the hope that it will be useful, |
QL | 9:ca2e6010d9e2 | 23 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
QL | 9:ca2e6010d9e2 | 24 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
QL | 9:ca2e6010d9e2 | 25 | // GNU General Public License for more details. |
QL | 9:ca2e6010d9e2 | 26 | // |
QL | 9:ca2e6010d9e2 | 27 | // You should have received a copy of the GNU General Public License |
QL | 9:ca2e6010d9e2 | 28 | // along with this program. If not, see <http://www.gnu.org/licenses/>. |
QL | 9:ca2e6010d9e2 | 29 | // |
QL | 9:ca2e6010d9e2 | 30 | // Contact information: |
QL | 9:ca2e6010d9e2 | 31 | // Quantum Leaps Web sites: http://www.quantum-leaps.com |
QL | 9:ca2e6010d9e2 | 32 | // http://www.state-machine.com |
QL | 9:ca2e6010d9e2 | 33 | // e-mail: info@quantum-leaps.com |
QL | 9:ca2e6010d9e2 | 34 | ////////////////////////////////////////////////////////////////////////////// |
QL | 9:ca2e6010d9e2 | 35 | #include "qp_port.h" // QP port |
QL | 9:ca2e6010d9e2 | 36 | |
QL | 9:ca2e6010d9e2 | 37 | // "qep_pkg.h" =============================================================== |
QL | 9:ca2e6010d9e2 | 38 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 39 | |
QL | 9:ca2e6010d9e2 | 40 | Q_DEFINE_THIS_MODULE("qp") |
QL | 9:ca2e6010d9e2 | 41 | |
QL | 9:ca2e6010d9e2 | 42 | ////////////////////////////////////////////////////////////////////////////// |
QL | 9:ca2e6010d9e2 | 43 | /// preallocated reserved events |
QL | 9:ca2e6010d9e2 | 44 | extern QEvt const QEP_reservedEvt_[]; |
QL | 9:ca2e6010d9e2 | 45 | |
QL | 9:ca2e6010d9e2 | 46 | /// empty signal for internal use only |
QL | 9:ca2e6010d9e2 | 47 | QSignal const QEP_EMPTY_SIG_ = static_cast<QSignal>(0); |
QL | 9:ca2e6010d9e2 | 48 | |
QL | 9:ca2e6010d9e2 | 49 | /// maximum depth of state nesting (including the top level), must be >= 3 |
QL | 9:ca2e6010d9e2 | 50 | int8_t const QEP_MAX_NEST_DEPTH_ = static_cast<int8_t>(6); |
QL | 9:ca2e6010d9e2 | 51 | |
QL | 9:ca2e6010d9e2 | 52 | uint8_t const u8_0 = static_cast<uint8_t>(0); ///< \brief constant (uint8_t)0 |
QL | 9:ca2e6010d9e2 | 53 | uint8_t const u8_1 = static_cast<uint8_t>(1); ///< \brief constant (uint8_t)1 |
QL | 9:ca2e6010d9e2 | 54 | int8_t const s8_0 = static_cast<int8_t>(0); ///< \brief constant (int8_t)0 |
QL | 9:ca2e6010d9e2 | 55 | int8_t const s8_1 = static_cast<int8_t>(1); ///< \brief constant (int8_t)1 |
QL | 9:ca2e6010d9e2 | 56 | int8_t const s8_n1 = static_cast<int8_t>(-1); ///< \brief constant (int8_t)-1 |
QL | 9:ca2e6010d9e2 | 57 | |
QL | 9:ca2e6010d9e2 | 58 | QP_END_ |
QL | 9:ca2e6010d9e2 | 59 | |
QL | 9:ca2e6010d9e2 | 60 | /// helper macro to trigger internal event in an HSM |
QL | 9:ca2e6010d9e2 | 61 | #define QEP_TRIG_(state_, sig_) \ |
QL | 9:ca2e6010d9e2 | 62 | ((*(state_))(this, &QEP_reservedEvt_[sig_])) |
QL | 9:ca2e6010d9e2 | 63 | |
QL | 9:ca2e6010d9e2 | 64 | /// helper macro to trigger exit action in an HSM |
QL | 9:ca2e6010d9e2 | 65 | #define QEP_EXIT_(state_) do { \ |
QL | 9:ca2e6010d9e2 | 66 | if (QEP_TRIG_(state_, Q_EXIT_SIG) == Q_RET_HANDLED) { \ |
QL | 9:ca2e6010d9e2 | 67 | QS_BEGIN_(QS_QEP_STATE_EXIT, QS::smObj_, this) \ |
QL | 9:ca2e6010d9e2 | 68 | QS_OBJ_(this); \ |
QL | 9:ca2e6010d9e2 | 69 | QS_FUN_(state_); \ |
QL | 9:ca2e6010d9e2 | 70 | QS_END_() \ |
QL | 9:ca2e6010d9e2 | 71 | } \ |
QL | 9:ca2e6010d9e2 | 72 | } while (false) |
QL | 9:ca2e6010d9e2 | 73 | |
QL | 9:ca2e6010d9e2 | 74 | /// helper macro to trigger entry action in an HSM |
QL | 9:ca2e6010d9e2 | 75 | #define QEP_ENTER_(state_) do { \ |
QL | 9:ca2e6010d9e2 | 76 | if (QEP_TRIG_(state_, Q_ENTRY_SIG) == Q_RET_HANDLED) { \ |
QL | 9:ca2e6010d9e2 | 77 | QS_BEGIN_(QS_QEP_STATE_ENTRY, QS::smObj_, this) \ |
QL | 9:ca2e6010d9e2 | 78 | QS_OBJ_(this); \ |
QL | 9:ca2e6010d9e2 | 79 | QS_FUN_(state_); \ |
QL | 9:ca2e6010d9e2 | 80 | QS_END_() \ |
QL | 9:ca2e6010d9e2 | 81 | } \ |
QL | 9:ca2e6010d9e2 | 82 | } while (false) |
QL | 9:ca2e6010d9e2 | 83 | |
QL | 9:ca2e6010d9e2 | 84 | // "qep.cpp" ================================================================= |
QL | 9:ca2e6010d9e2 | 85 | /// \brief ::QEP_reservedEvt_ definition and QEP::getVersion() implementation. |
QL | 9:ca2e6010d9e2 | 86 | |
QL | 9:ca2e6010d9e2 | 87 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 88 | |
QL | 9:ca2e6010d9e2 | 89 | // Package-scope objects ----------------------------------------------------- |
QL | 9:ca2e6010d9e2 | 90 | QEvt const QEP_reservedEvt_[] = { |
QL | 9:ca2e6010d9e2 | 91 | #ifdef Q_EVT_CTOR // Is the QEvt constructor provided? |
QL | 9:ca2e6010d9e2 | 92 | static_cast<QSignal>(0), |
QL | 9:ca2e6010d9e2 | 93 | static_cast<QSignal>(1), |
QL | 9:ca2e6010d9e2 | 94 | static_cast<QSignal>(2), |
QL | 9:ca2e6010d9e2 | 95 | static_cast<QSignal>(3) |
QL | 9:ca2e6010d9e2 | 96 | #else // QEvt is a POD (Plain Old Datatype) |
QL | 9:ca2e6010d9e2 | 97 | { static_cast<QSignal>(0), u8_0, u8_0 }, |
QL | 9:ca2e6010d9e2 | 98 | { static_cast<QSignal>(1), u8_0, u8_0 }, |
QL | 9:ca2e6010d9e2 | 99 | { static_cast<QSignal>(2), u8_0, u8_0 }, |
QL | 9:ca2e6010d9e2 | 100 | { static_cast<QSignal>(3), u8_0, u8_0 } |
QL | 9:ca2e6010d9e2 | 101 | #endif |
QL | 9:ca2e6010d9e2 | 102 | }; |
QL | 9:ca2e6010d9e2 | 103 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 104 | char_t const Q_ROM * Q_ROM_VAR QEP::getVersion(void) { |
QL | 9:ca2e6010d9e2 | 105 | uint8_t const u8_zero = static_cast<uint8_t>('0'); |
QL | 9:ca2e6010d9e2 | 106 | static char_t const Q_ROM Q_ROM_VAR version[] = { |
QL | 9:ca2e6010d9e2 | 107 | static_cast<char_t>(((QP_VERSION >> 12) & 0xFU) + u8_zero), |
QL | 9:ca2e6010d9e2 | 108 | static_cast<char_t>('.'), |
QL | 9:ca2e6010d9e2 | 109 | static_cast<char_t>(((QP_VERSION >> 8) & 0xFU) + u8_zero), |
QL | 9:ca2e6010d9e2 | 110 | static_cast<char_t>('.'), |
QL | 9:ca2e6010d9e2 | 111 | static_cast<char_t>(((QP_VERSION >> 4) & 0xFU) + u8_zero), |
QL | 9:ca2e6010d9e2 | 112 | static_cast<char_t>((QP_VERSION & 0xFU) + u8_zero), |
QL | 9:ca2e6010d9e2 | 113 | static_cast<char_t>('\0') |
QL | 9:ca2e6010d9e2 | 114 | }; |
QL | 9:ca2e6010d9e2 | 115 | return version; |
QL | 9:ca2e6010d9e2 | 116 | } |
QL | 9:ca2e6010d9e2 | 117 | |
QL | 9:ca2e6010d9e2 | 118 | QP_END_ |
QL | 9:ca2e6010d9e2 | 119 | |
QL | 9:ca2e6010d9e2 | 120 | // "qhsm_top.cpp" ============================================================ |
QL | 9:ca2e6010d9e2 | 121 | /// \brief QHsm::top() implementation. |
QL | 9:ca2e6010d9e2 | 122 | |
QL | 9:ca2e6010d9e2 | 123 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 124 | |
QL | 9:ca2e6010d9e2 | 125 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 126 | QState QHsm::top(void * const, QEvt const * const) { |
QL | 9:ca2e6010d9e2 | 127 | return Q_RET_IGNORED; // the top state ignores all events |
QL | 9:ca2e6010d9e2 | 128 | } |
QL | 9:ca2e6010d9e2 | 129 | |
QL | 9:ca2e6010d9e2 | 130 | QP_END_ |
QL | 9:ca2e6010d9e2 | 131 | |
QL | 9:ca2e6010d9e2 | 132 | // "qhsm_ini.cpp" ============================================================ |
QL | 9:ca2e6010d9e2 | 133 | /// \brief QHsm::init() implementation. |
QL | 9:ca2e6010d9e2 | 134 | |
QL | 9:ca2e6010d9e2 | 135 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 136 | |
QL | 9:ca2e6010d9e2 | 137 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 138 | QHsm::~QHsm() { |
QL | 9:ca2e6010d9e2 | 139 | } |
QL | 9:ca2e6010d9e2 | 140 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 141 | void QHsm::init(QEvt const * const e) { |
QL | 9:ca2e6010d9e2 | 142 | QStateHandler t = m_state; |
QL | 9:ca2e6010d9e2 | 143 | |
QL | 9:ca2e6010d9e2 | 144 | Q_REQUIRE((m_temp != Q_STATE_CAST(0)) // ctor must be executed |
QL | 9:ca2e6010d9e2 | 145 | && (t == Q_STATE_CAST(&QHsm::top))); // initial tran. NOT taken |
QL | 9:ca2e6010d9e2 | 146 | |
QL | 9:ca2e6010d9e2 | 147 | // the top-most initial transition must be taken |
QL | 9:ca2e6010d9e2 | 148 | Q_ALLEGE((*m_temp)(this, e) == Q_RET_TRAN); |
QL | 9:ca2e6010d9e2 | 149 | |
QL | 9:ca2e6010d9e2 | 150 | QS_CRIT_STAT_ |
QL | 9:ca2e6010d9e2 | 151 | do { // drill into the target... |
QL | 9:ca2e6010d9e2 | 152 | QStateHandler path[QEP_MAX_NEST_DEPTH_]; |
QL | 9:ca2e6010d9e2 | 153 | int8_t ip = s8_0; // transition entry path index |
QL | 9:ca2e6010d9e2 | 154 | |
QL | 9:ca2e6010d9e2 | 155 | QS_BEGIN_(QS_QEP_STATE_INIT, QS::smObj_, this) |
QL | 9:ca2e6010d9e2 | 156 | QS_OBJ_(this); // this state machine object |
QL | 9:ca2e6010d9e2 | 157 | QS_FUN_(t); // the source state |
QL | 9:ca2e6010d9e2 | 158 | QS_FUN_(m_temp); // the target of the initial transition |
QL | 9:ca2e6010d9e2 | 159 | QS_END_() |
QL | 9:ca2e6010d9e2 | 160 | |
QL | 9:ca2e6010d9e2 | 161 | path[0] = m_temp; |
QL | 9:ca2e6010d9e2 | 162 | (void)QEP_TRIG_(m_temp, QEP_EMPTY_SIG_); |
QL | 9:ca2e6010d9e2 | 163 | while (m_temp != t) { |
QL | 9:ca2e6010d9e2 | 164 | ++ip; |
QL | 9:ca2e6010d9e2 | 165 | path[ip] = m_temp; |
QL | 9:ca2e6010d9e2 | 166 | (void)QEP_TRIG_(m_temp, QEP_EMPTY_SIG_); |
QL | 9:ca2e6010d9e2 | 167 | } |
QL | 9:ca2e6010d9e2 | 168 | m_temp = path[0]; |
QL | 9:ca2e6010d9e2 | 169 | // entry path must not overflow |
QL | 9:ca2e6010d9e2 | 170 | Q_ASSERT(ip < QEP_MAX_NEST_DEPTH_); |
QL | 9:ca2e6010d9e2 | 171 | |
QL | 9:ca2e6010d9e2 | 172 | do { // retrace the entry path in reverse (desired) order... |
QL | 9:ca2e6010d9e2 | 173 | QEP_ENTER_(path[ip]); // enter path[ip] |
QL | 9:ca2e6010d9e2 | 174 | --ip; |
QL | 9:ca2e6010d9e2 | 175 | } while (ip >= s8_0); |
QL | 9:ca2e6010d9e2 | 176 | |
QL | 9:ca2e6010d9e2 | 177 | t = path[0]; // current state becomes the new source |
QL | 9:ca2e6010d9e2 | 178 | } while (QEP_TRIG_(t, Q_INIT_SIG) == Q_RET_TRAN); |
QL | 9:ca2e6010d9e2 | 179 | |
QL | 9:ca2e6010d9e2 | 180 | QS_BEGIN_(QS_QEP_INIT_TRAN, QS::smObj_, this) |
QL | 9:ca2e6010d9e2 | 181 | QS_TIME_(); // time stamp |
QL | 9:ca2e6010d9e2 | 182 | QS_OBJ_(this); // this state machine object |
QL | 9:ca2e6010d9e2 | 183 | QS_FUN_(t); // the new active state |
QL | 9:ca2e6010d9e2 | 184 | QS_END_() |
QL | 9:ca2e6010d9e2 | 185 | |
QL | 9:ca2e6010d9e2 | 186 | m_state = t; // change the current active state |
QL | 9:ca2e6010d9e2 | 187 | m_temp = t; // mark the configuration as stable |
QL | 9:ca2e6010d9e2 | 188 | } |
QL | 9:ca2e6010d9e2 | 189 | |
QL | 9:ca2e6010d9e2 | 190 | QP_END_ |
QL | 9:ca2e6010d9e2 | 191 | |
QL | 9:ca2e6010d9e2 | 192 | // "qhsm_dis.cpp" ============================================================ |
QL | 9:ca2e6010d9e2 | 193 | /// \brief QHsm::dispatch() implementation. |
QL | 9:ca2e6010d9e2 | 194 | |
QL | 9:ca2e6010d9e2 | 195 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 196 | |
QL | 9:ca2e6010d9e2 | 197 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 198 | void QHsm::dispatch(QEvt const * const e) { |
QL | 9:ca2e6010d9e2 | 199 | QStateHandler t = m_state; |
QL | 9:ca2e6010d9e2 | 200 | |
QL | 9:ca2e6010d9e2 | 201 | Q_REQUIRE(t == m_temp); // the state configuration must be stable |
QL | 9:ca2e6010d9e2 | 202 | |
QL | 9:ca2e6010d9e2 | 203 | QStateHandler s; |
QL | 9:ca2e6010d9e2 | 204 | QState r; |
QL | 9:ca2e6010d9e2 | 205 | QS_CRIT_STAT_ |
QL | 9:ca2e6010d9e2 | 206 | |
QL | 9:ca2e6010d9e2 | 207 | QS_BEGIN_(QS_QEP_DISPATCH, QS::smObj_, this) |
QL | 9:ca2e6010d9e2 | 208 | QS_TIME_(); // time stamp |
QL | 9:ca2e6010d9e2 | 209 | QS_SIG_(e->sig); // the signal of the event |
QL | 9:ca2e6010d9e2 | 210 | QS_OBJ_(this); // this state machine object |
QL | 9:ca2e6010d9e2 | 211 | QS_FUN_(t); // the current state |
QL | 9:ca2e6010d9e2 | 212 | QS_END_() |
QL | 9:ca2e6010d9e2 | 213 | |
QL | 9:ca2e6010d9e2 | 214 | do { // process the event hierarchically... |
QL | 9:ca2e6010d9e2 | 215 | s = m_temp; |
QL | 9:ca2e6010d9e2 | 216 | r = (*s)(this, e); // invoke state handler s |
QL | 9:ca2e6010d9e2 | 217 | |
QL | 9:ca2e6010d9e2 | 218 | if (r == Q_RET_UNHANDLED) { // unhandled due to a guard? |
QL | 9:ca2e6010d9e2 | 219 | |
QL | 9:ca2e6010d9e2 | 220 | QS_BEGIN_(QS_QEP_UNHANDLED, QS::smObj_, this) |
QL | 9:ca2e6010d9e2 | 221 | QS_SIG_(e->sig); // the signal of the event |
QL | 9:ca2e6010d9e2 | 222 | QS_OBJ_(this); // this state machine object |
QL | 9:ca2e6010d9e2 | 223 | QS_FUN_(s); // the current state |
QL | 9:ca2e6010d9e2 | 224 | QS_END_() |
QL | 9:ca2e6010d9e2 | 225 | |
QL | 9:ca2e6010d9e2 | 226 | r = QEP_TRIG_(s, QEP_EMPTY_SIG_); // find superstate of s |
QL | 9:ca2e6010d9e2 | 227 | } |
QL | 9:ca2e6010d9e2 | 228 | } while (r == Q_RET_SUPER); |
QL | 9:ca2e6010d9e2 | 229 | |
QL | 9:ca2e6010d9e2 | 230 | if (r == Q_RET_TRAN) { // transition taken? |
QL | 9:ca2e6010d9e2 | 231 | QStateHandler path[QEP_MAX_NEST_DEPTH_]; |
QL | 9:ca2e6010d9e2 | 232 | int8_t ip = s8_n1; // transition entry path index |
QL | 9:ca2e6010d9e2 | 233 | int8_t iq; // helper transition entry path index |
QL | 9:ca2e6010d9e2 | 234 | #ifdef Q_SPY |
QL | 9:ca2e6010d9e2 | 235 | QStateHandler src = s; // save the transition source for tracing |
QL | 9:ca2e6010d9e2 | 236 | #endif |
QL | 9:ca2e6010d9e2 | 237 | |
QL | 9:ca2e6010d9e2 | 238 | path[0] = m_temp; // save the target of the transition |
QL | 9:ca2e6010d9e2 | 239 | path[1] = t; |
QL | 9:ca2e6010d9e2 | 240 | |
QL | 9:ca2e6010d9e2 | 241 | while (t != s) { // exit current state to transition source s... |
QL | 9:ca2e6010d9e2 | 242 | if (QEP_TRIG_(t, Q_EXIT_SIG) == Q_RET_HANDLED) { //exit handled? |
QL | 9:ca2e6010d9e2 | 243 | QS_BEGIN_(QS_QEP_STATE_EXIT, QS::smObj_, this) |
QL | 9:ca2e6010d9e2 | 244 | QS_OBJ_(this); // this state machine object |
QL | 9:ca2e6010d9e2 | 245 | QS_FUN_(t); // the exited state |
QL | 9:ca2e6010d9e2 | 246 | QS_END_() |
QL | 9:ca2e6010d9e2 | 247 | |
QL | 9:ca2e6010d9e2 | 248 | (void)QEP_TRIG_(t, QEP_EMPTY_SIG_); // find superstate of t |
QL | 9:ca2e6010d9e2 | 249 | } |
QL | 9:ca2e6010d9e2 | 250 | t = m_temp; // m_temp holds the superstate |
QL | 9:ca2e6010d9e2 | 251 | } |
QL | 9:ca2e6010d9e2 | 252 | |
QL | 9:ca2e6010d9e2 | 253 | t = path[0]; // target of the transition |
QL | 9:ca2e6010d9e2 | 254 | |
QL | 9:ca2e6010d9e2 | 255 | if (s == t) { // (a) check source==target (transition to self) |
QL | 9:ca2e6010d9e2 | 256 | QEP_EXIT_(s); // exit the source |
QL | 9:ca2e6010d9e2 | 257 | ip = s8_0; // enter the target |
QL | 9:ca2e6010d9e2 | 258 | } |
QL | 9:ca2e6010d9e2 | 259 | else { |
QL | 9:ca2e6010d9e2 | 260 | (void)QEP_TRIG_(t, QEP_EMPTY_SIG_); // superstate of target |
QL | 9:ca2e6010d9e2 | 261 | t = m_temp; |
QL | 9:ca2e6010d9e2 | 262 | if (s == t) { // (b) check source==target->super |
QL | 9:ca2e6010d9e2 | 263 | ip = s8_0; // enter the target |
QL | 9:ca2e6010d9e2 | 264 | } |
QL | 9:ca2e6010d9e2 | 265 | else { |
QL | 9:ca2e6010d9e2 | 266 | (void)QEP_TRIG_(s, QEP_EMPTY_SIG_); // superstate of src |
QL | 9:ca2e6010d9e2 | 267 | // (c) check source->super==target->super |
QL | 9:ca2e6010d9e2 | 268 | if (m_temp == t) { |
QL | 9:ca2e6010d9e2 | 269 | QEP_EXIT_(s); // exit the source |
QL | 9:ca2e6010d9e2 | 270 | ip = s8_0; // enter the target |
QL | 9:ca2e6010d9e2 | 271 | } |
QL | 9:ca2e6010d9e2 | 272 | else { |
QL | 9:ca2e6010d9e2 | 273 | // (d) check source->super==target |
QL | 9:ca2e6010d9e2 | 274 | if (m_temp == path[0]) { |
QL | 9:ca2e6010d9e2 | 275 | QEP_EXIT_(s); // exit the source |
QL | 9:ca2e6010d9e2 | 276 | } |
QL | 9:ca2e6010d9e2 | 277 | else { // (e) check rest of source==target->super->super.. |
QL | 9:ca2e6010d9e2 | 278 | // and store the entry path along the way |
QL | 9:ca2e6010d9e2 | 279 | // |
QL | 9:ca2e6010d9e2 | 280 | iq = s8_0; // indicate LCA not found |
QL | 9:ca2e6010d9e2 | 281 | ip = s8_1; // enter target's superst |
QL | 9:ca2e6010d9e2 | 282 | path[1] = t; // save the superstate of target |
QL | 9:ca2e6010d9e2 | 283 | t = m_temp; // save source->super |
QL | 9:ca2e6010d9e2 | 284 | // find target->super->super |
QL | 9:ca2e6010d9e2 | 285 | r = QEP_TRIG_(path[1], QEP_EMPTY_SIG_); |
QL | 9:ca2e6010d9e2 | 286 | while (r == Q_RET_SUPER) { |
QL | 9:ca2e6010d9e2 | 287 | ++ip; |
QL | 9:ca2e6010d9e2 | 288 | path[ip] = m_temp; // store the entry path |
QL | 9:ca2e6010d9e2 | 289 | if (m_temp == s) { // is it the source? |
QL | 9:ca2e6010d9e2 | 290 | // indicate that LCA found |
QL | 9:ca2e6010d9e2 | 291 | iq = s8_1; |
QL | 9:ca2e6010d9e2 | 292 | // entry path must not overflow |
QL | 9:ca2e6010d9e2 | 293 | Q_ASSERT(ip < QEP_MAX_NEST_DEPTH_); |
QL | 9:ca2e6010d9e2 | 294 | --ip; // do not enter the source |
QL | 9:ca2e6010d9e2 | 295 | r = Q_RET_HANDLED; // terminate the loop |
QL | 9:ca2e6010d9e2 | 296 | } |
QL | 9:ca2e6010d9e2 | 297 | else { // it is not the source, keep going up |
QL | 9:ca2e6010d9e2 | 298 | r = QEP_TRIG_(m_temp, QEP_EMPTY_SIG_); |
QL | 9:ca2e6010d9e2 | 299 | } |
QL | 9:ca2e6010d9e2 | 300 | } |
QL | 9:ca2e6010d9e2 | 301 | if (iq == s8_0) { // LCA found yet? |
QL | 9:ca2e6010d9e2 | 302 | |
QL | 9:ca2e6010d9e2 | 303 | // entry path must not overflow |
QL | 9:ca2e6010d9e2 | 304 | Q_ASSERT(ip < QEP_MAX_NEST_DEPTH_); |
QL | 9:ca2e6010d9e2 | 305 | |
QL | 9:ca2e6010d9e2 | 306 | QEP_EXIT_(s); // exit the source |
QL | 9:ca2e6010d9e2 | 307 | |
QL | 9:ca2e6010d9e2 | 308 | // (f) check the rest of source->super |
QL | 9:ca2e6010d9e2 | 309 | // == target->super->super... |
QL | 9:ca2e6010d9e2 | 310 | // |
QL | 9:ca2e6010d9e2 | 311 | iq = ip; |
QL | 9:ca2e6010d9e2 | 312 | r = Q_RET_IGNORED; // indicate LCA NOT found |
QL | 9:ca2e6010d9e2 | 313 | do { |
QL | 9:ca2e6010d9e2 | 314 | if (t == path[iq]) { // is this the LCA? |
QL | 9:ca2e6010d9e2 | 315 | r = Q_RET_HANDLED; // indicate LCA found |
QL | 9:ca2e6010d9e2 | 316 | // do not enter LCA |
QL | 9:ca2e6010d9e2 | 317 | ip = static_cast<int8_t>(iq - s8_1); |
QL | 9:ca2e6010d9e2 | 318 | // terminate the loop |
QL | 9:ca2e6010d9e2 | 319 | iq = s8_n1; |
QL | 9:ca2e6010d9e2 | 320 | } |
QL | 9:ca2e6010d9e2 | 321 | else { |
QL | 9:ca2e6010d9e2 | 322 | --iq; // try lower superstate of target |
QL | 9:ca2e6010d9e2 | 323 | } |
QL | 9:ca2e6010d9e2 | 324 | } while (iq >= s8_0); |
QL | 9:ca2e6010d9e2 | 325 | |
QL | 9:ca2e6010d9e2 | 326 | if (r != Q_RET_HANDLED) { // LCA not found yet? |
QL | 9:ca2e6010d9e2 | 327 | // (g) check each source->super->... |
QL | 9:ca2e6010d9e2 | 328 | // for each target->super... |
QL | 9:ca2e6010d9e2 | 329 | // |
QL | 9:ca2e6010d9e2 | 330 | r = Q_RET_IGNORED; // keep looping |
QL | 9:ca2e6010d9e2 | 331 | do { |
QL | 9:ca2e6010d9e2 | 332 | // exit t unhandled? |
QL | 9:ca2e6010d9e2 | 333 | if (QEP_TRIG_(t, Q_EXIT_SIG) |
QL | 9:ca2e6010d9e2 | 334 | == Q_RET_HANDLED) |
QL | 9:ca2e6010d9e2 | 335 | { |
QL | 9:ca2e6010d9e2 | 336 | QS_BEGIN_(QS_QEP_STATE_EXIT, |
QL | 9:ca2e6010d9e2 | 337 | QS::smObj_, this) |
QL | 9:ca2e6010d9e2 | 338 | QS_OBJ_(this); |
QL | 9:ca2e6010d9e2 | 339 | QS_FUN_(t); |
QL | 9:ca2e6010d9e2 | 340 | QS_END_() |
QL | 9:ca2e6010d9e2 | 341 | |
QL | 9:ca2e6010d9e2 | 342 | (void)QEP_TRIG_(t, QEP_EMPTY_SIG_); |
QL | 9:ca2e6010d9e2 | 343 | } |
QL | 9:ca2e6010d9e2 | 344 | t = m_temp; // set to super of t |
QL | 9:ca2e6010d9e2 | 345 | iq = ip; |
QL | 9:ca2e6010d9e2 | 346 | do { |
QL | 9:ca2e6010d9e2 | 347 | if (t == path[iq]) { // is this LCA? |
QL | 9:ca2e6010d9e2 | 348 | // do not enter LCA |
QL | 9:ca2e6010d9e2 | 349 | ip = static_cast<int8_t>(iq-s8_1); |
QL | 9:ca2e6010d9e2 | 350 | // break out of the inner loop |
QL | 9:ca2e6010d9e2 | 351 | iq = s8_n1; |
QL | 9:ca2e6010d9e2 | 352 | r = Q_RET_HANDLED; // break outer |
QL | 9:ca2e6010d9e2 | 353 | } |
QL | 9:ca2e6010d9e2 | 354 | else { |
QL | 9:ca2e6010d9e2 | 355 | --iq; |
QL | 9:ca2e6010d9e2 | 356 | } |
QL | 9:ca2e6010d9e2 | 357 | } while (iq >= s8_0); |
QL | 9:ca2e6010d9e2 | 358 | } while (r != Q_RET_HANDLED); |
QL | 9:ca2e6010d9e2 | 359 | } |
QL | 9:ca2e6010d9e2 | 360 | } |
QL | 9:ca2e6010d9e2 | 361 | } |
QL | 9:ca2e6010d9e2 | 362 | } |
QL | 9:ca2e6010d9e2 | 363 | } |
QL | 9:ca2e6010d9e2 | 364 | } |
QL | 9:ca2e6010d9e2 | 365 | // retrace the entry path in reverse (desired) order... |
QL | 9:ca2e6010d9e2 | 366 | for (; ip >= s8_0; --ip) { |
QL | 9:ca2e6010d9e2 | 367 | QEP_ENTER_(path[ip]); // enter path[ip] |
QL | 9:ca2e6010d9e2 | 368 | } |
QL | 9:ca2e6010d9e2 | 369 | t = path[0]; // stick the target into register |
QL | 9:ca2e6010d9e2 | 370 | m_temp = t; // update the next state |
QL | 9:ca2e6010d9e2 | 371 | |
QL | 9:ca2e6010d9e2 | 372 | // drill into the target hierarchy... |
QL | 9:ca2e6010d9e2 | 373 | while (QEP_TRIG_(t, Q_INIT_SIG) == Q_RET_TRAN) { |
QL | 9:ca2e6010d9e2 | 374 | |
QL | 9:ca2e6010d9e2 | 375 | QS_BEGIN_(QS_QEP_STATE_INIT, QS::smObj_, this) |
QL | 9:ca2e6010d9e2 | 376 | QS_OBJ_(this); // this state machine object |
QL | 9:ca2e6010d9e2 | 377 | QS_FUN_(t); // the source (pseudo)state |
QL | 9:ca2e6010d9e2 | 378 | QS_FUN_(m_temp); // the target of the transition |
QL | 9:ca2e6010d9e2 | 379 | QS_END_() |
QL | 9:ca2e6010d9e2 | 380 | |
QL | 9:ca2e6010d9e2 | 381 | ip = s8_0; |
QL | 9:ca2e6010d9e2 | 382 | path[0] = m_temp; |
QL | 9:ca2e6010d9e2 | 383 | (void)QEP_TRIG_(m_temp, QEP_EMPTY_SIG_); // find superstate |
QL | 9:ca2e6010d9e2 | 384 | while (m_temp != t) { |
QL | 9:ca2e6010d9e2 | 385 | ++ip; |
QL | 9:ca2e6010d9e2 | 386 | path[ip] = m_temp; |
QL | 9:ca2e6010d9e2 | 387 | (void)QEP_TRIG_(m_temp, QEP_EMPTY_SIG_); // find superstate |
QL | 9:ca2e6010d9e2 | 388 | } |
QL | 9:ca2e6010d9e2 | 389 | m_temp = path[0]; |
QL | 9:ca2e6010d9e2 | 390 | // entry path must not overflow |
QL | 9:ca2e6010d9e2 | 391 | Q_ASSERT(ip < QEP_MAX_NEST_DEPTH_); |
QL | 9:ca2e6010d9e2 | 392 | |
QL | 9:ca2e6010d9e2 | 393 | do { // retrace the entry path in reverse (correct) order... |
QL | 9:ca2e6010d9e2 | 394 | QEP_ENTER_(path[ip]); // enter path[ip] |
QL | 9:ca2e6010d9e2 | 395 | --ip; |
QL | 9:ca2e6010d9e2 | 396 | } while (ip >= s8_0); |
QL | 9:ca2e6010d9e2 | 397 | |
QL | 9:ca2e6010d9e2 | 398 | t = path[0]; |
QL | 9:ca2e6010d9e2 | 399 | } |
QL | 9:ca2e6010d9e2 | 400 | |
QL | 9:ca2e6010d9e2 | 401 | QS_BEGIN_(QS_QEP_TRAN, QS::smObj_, this) |
QL | 9:ca2e6010d9e2 | 402 | QS_TIME_(); // time stamp |
QL | 9:ca2e6010d9e2 | 403 | QS_SIG_(e->sig); // the signal of the event |
QL | 9:ca2e6010d9e2 | 404 | QS_OBJ_(this); // this state machine object |
QL | 9:ca2e6010d9e2 | 405 | QS_FUN_(src); // the source of the transition |
QL | 9:ca2e6010d9e2 | 406 | QS_FUN_(t); // the new active state |
QL | 9:ca2e6010d9e2 | 407 | QS_END_() |
QL | 9:ca2e6010d9e2 | 408 | |
QL | 9:ca2e6010d9e2 | 409 | } |
QL | 9:ca2e6010d9e2 | 410 | else { // transition not taken |
QL | 9:ca2e6010d9e2 | 411 | #ifdef Q_SPY |
QL | 9:ca2e6010d9e2 | 412 | if (r == Q_RET_HANDLED) { |
QL | 9:ca2e6010d9e2 | 413 | |
QL | 9:ca2e6010d9e2 | 414 | QS_BEGIN_(QS_QEP_INTERN_TRAN, QS::smObj_, this) |
QL | 9:ca2e6010d9e2 | 415 | QS_TIME_(); // time stamp |
QL | 9:ca2e6010d9e2 | 416 | QS_SIG_(e->sig); // the signal of the event |
QL | 9:ca2e6010d9e2 | 417 | QS_OBJ_(this); // this state machine object |
QL | 9:ca2e6010d9e2 | 418 | QS_FUN_(m_state); // the state that handled the event |
QL | 9:ca2e6010d9e2 | 419 | QS_END_() |
QL | 9:ca2e6010d9e2 | 420 | |
QL | 9:ca2e6010d9e2 | 421 | } |
QL | 9:ca2e6010d9e2 | 422 | else { |
QL | 9:ca2e6010d9e2 | 423 | |
QL | 9:ca2e6010d9e2 | 424 | QS_BEGIN_(QS_QEP_IGNORED, QS::smObj_, this) |
QL | 9:ca2e6010d9e2 | 425 | QS_TIME_(); // time stamp |
QL | 9:ca2e6010d9e2 | 426 | QS_SIG_(e->sig); // the signal of the event |
QL | 9:ca2e6010d9e2 | 427 | QS_OBJ_(this); // this state machine object |
QL | 9:ca2e6010d9e2 | 428 | QS_FUN_(m_state); // the current state |
QL | 9:ca2e6010d9e2 | 429 | QS_END_() |
QL | 9:ca2e6010d9e2 | 430 | |
QL | 9:ca2e6010d9e2 | 431 | } |
QL | 9:ca2e6010d9e2 | 432 | #endif |
QL | 9:ca2e6010d9e2 | 433 | } |
QL | 9:ca2e6010d9e2 | 434 | |
QL | 9:ca2e6010d9e2 | 435 | m_state = t; // change the current active state |
QL | 9:ca2e6010d9e2 | 436 | m_temp = t; // mark the configuration as stable |
QL | 9:ca2e6010d9e2 | 437 | } |
QL | 9:ca2e6010d9e2 | 438 | |
QL | 9:ca2e6010d9e2 | 439 | QP_END_ |
QL | 9:ca2e6010d9e2 | 440 | |
QL | 9:ca2e6010d9e2 | 441 | // "qf_pkg.h" ================================================================ |
QL | 9:ca2e6010d9e2 | 442 | /// \brief Internal (package scope) QF/C++ interface. |
QL | 9:ca2e6010d9e2 | 443 | |
QL | 9:ca2e6010d9e2 | 444 | /// \brief helper macro to cast const away from an event pointer \a e_ |
QL | 9:ca2e6010d9e2 | 445 | #define QF_EVT_CONST_CAST_(e_) const_cast<QEvt *>(e_) |
QL | 9:ca2e6010d9e2 | 446 | |
QL | 9:ca2e6010d9e2 | 447 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 448 | // QF-specific critical section |
QL | 9:ca2e6010d9e2 | 449 | #ifndef QF_CRIT_STAT_TYPE |
QL | 9:ca2e6010d9e2 | 450 | /// \brief This is an internal macro for defining the critical section |
QL | 9:ca2e6010d9e2 | 451 | /// status type. |
QL | 9:ca2e6010d9e2 | 452 | /// |
QL | 9:ca2e6010d9e2 | 453 | /// The purpose of this macro is to enable writing the same code for the |
QL | 9:ca2e6010d9e2 | 454 | /// case when critical sectgion status type is defined and when it is not. |
QL | 9:ca2e6010d9e2 | 455 | /// If the macro #QF_CRIT_STAT_TYPE is defined, this internal macro |
QL | 9:ca2e6010d9e2 | 456 | /// provides the definition of the critical section status varaible. |
QL | 9:ca2e6010d9e2 | 457 | /// Otherwise this macro is empty. |
QL | 9:ca2e6010d9e2 | 458 | /// \sa #QF_CRIT_STAT_TYPE |
QL | 9:ca2e6010d9e2 | 459 | /// |
QL | 9:ca2e6010d9e2 | 460 | #define QF_CRIT_STAT_ |
QL | 9:ca2e6010d9e2 | 461 | |
QL | 9:ca2e6010d9e2 | 462 | /// \brief This is an internal macro for entering a critical section. |
QL | 9:ca2e6010d9e2 | 463 | /// |
QL | 9:ca2e6010d9e2 | 464 | /// The purpose of this macro is to enable writing the same code for the |
QL | 9:ca2e6010d9e2 | 465 | /// case when critical sectgion status type is defined and when it is not. |
QL | 9:ca2e6010d9e2 | 466 | /// If the macro #QF_CRIT_STAT_TYPE is defined, this internal macro |
QL | 9:ca2e6010d9e2 | 467 | /// invokes #QF_CRIT_ENTRY passing the key variable as the parameter. |
QL | 9:ca2e6010d9e2 | 468 | /// Otherwise #QF_CRIT_ENTRY is invoked with a dummy parameter. |
QL | 9:ca2e6010d9e2 | 469 | /// \sa #QF_CRIT_ENTRY |
QL | 9:ca2e6010d9e2 | 470 | /// |
QL | 9:ca2e6010d9e2 | 471 | #define QF_CRIT_ENTRY_() QF_CRIT_ENTRY(dummy) |
QL | 9:ca2e6010d9e2 | 472 | |
QL | 9:ca2e6010d9e2 | 473 | /// \brief This is an internal macro for exiting a cricial section. |
QL | 9:ca2e6010d9e2 | 474 | /// |
QL | 9:ca2e6010d9e2 | 475 | /// The purpose of this macro is to enable writing the same code for the |
QL | 9:ca2e6010d9e2 | 476 | /// case when critical sectgion status type is defined and when it is not. |
QL | 9:ca2e6010d9e2 | 477 | /// If the macro #QF_CRIT_STAT_TYPE is defined, this internal macro |
QL | 9:ca2e6010d9e2 | 478 | /// invokes #QF_CRIT_EXIT passing the key variable as the parameter. |
QL | 9:ca2e6010d9e2 | 479 | /// Otherwise #QF_CRIT_EXIT is invoked with a dummy parameter. |
QL | 9:ca2e6010d9e2 | 480 | /// \sa #QF_CRIT_EXIT |
QL | 9:ca2e6010d9e2 | 481 | /// |
QL | 9:ca2e6010d9e2 | 482 | #define QF_CRIT_EXIT_() QF_CRIT_EXIT(dummy) |
QL | 9:ca2e6010d9e2 | 483 | |
QL | 9:ca2e6010d9e2 | 484 | #else |
QL | 9:ca2e6010d9e2 | 485 | #define QF_CRIT_STAT_ QF_CRIT_STAT_TYPE critStat_; |
QL | 9:ca2e6010d9e2 | 486 | #define QF_CRIT_ENTRY_() QF_CRIT_ENTRY(critStat_) |
QL | 9:ca2e6010d9e2 | 487 | #define QF_CRIT_EXIT_() QF_CRIT_EXIT(critStat_) |
QL | 9:ca2e6010d9e2 | 488 | #endif |
QL | 9:ca2e6010d9e2 | 489 | |
QL | 9:ca2e6010d9e2 | 490 | // package-scope objects ----------------------------------------------------- |
QL | 9:ca2e6010d9e2 | 491 | extern QTimeEvt *QF_timeEvtListHead_; ///< head of linked list of time events |
QL | 9:ca2e6010d9e2 | 492 | extern QF_EPOOL_TYPE_ QF_pool_[QF_MAX_EPOOL]; ///< allocate event pools |
QL | 9:ca2e6010d9e2 | 493 | extern uint8_t QF_maxPool_; ///< # of initialized event pools |
QL | 9:ca2e6010d9e2 | 494 | extern QSubscrList *QF_subscrList_; ///< the subscriber list array |
QL | 9:ca2e6010d9e2 | 495 | extern enum_t QF_maxSignal_; ///< the maximum published signal |
QL | 9:ca2e6010d9e2 | 496 | |
QL | 9:ca2e6010d9e2 | 497 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 498 | /// \brief Structure representing a free block in the Native QF Memory Pool |
QL | 9:ca2e6010d9e2 | 499 | /// \sa ::QMPool |
QL | 9:ca2e6010d9e2 | 500 | struct QFreeBlock { |
QL | 9:ca2e6010d9e2 | 501 | QFreeBlock *m_next; |
QL | 9:ca2e6010d9e2 | 502 | }; |
QL | 9:ca2e6010d9e2 | 503 | |
QL | 9:ca2e6010d9e2 | 504 | ////////////////////////////////////////////////////////////////////////////// |
QL | 9:ca2e6010d9e2 | 505 | // internal helper inline functions |
QL | 9:ca2e6010d9e2 | 506 | |
QL | 9:ca2e6010d9e2 | 507 | /// \brief access to the poolId_ of an event \a e |
QL | 9:ca2e6010d9e2 | 508 | inline uint8_t QF_EVT_POOL_ID_(QEvt const * const e) { return e->poolId_; } |
QL | 9:ca2e6010d9e2 | 509 | |
QL | 9:ca2e6010d9e2 | 510 | /// \brief access to the refCtr_ of an event \a e |
QL | 9:ca2e6010d9e2 | 511 | inline uint8_t QF_EVT_REF_CTR_(QEvt const * const e) { return e->refCtr_; } |
QL | 9:ca2e6010d9e2 | 512 | |
QL | 9:ca2e6010d9e2 | 513 | /// \brief increment the refCtr_ of an event \a e |
QL | 9:ca2e6010d9e2 | 514 | inline void QF_EVT_REF_CTR_INC_(QEvt const * const e) { |
QL | 9:ca2e6010d9e2 | 515 | ++(QF_EVT_CONST_CAST_(e))->refCtr_; |
QL | 9:ca2e6010d9e2 | 516 | } |
QL | 9:ca2e6010d9e2 | 517 | |
QL | 9:ca2e6010d9e2 | 518 | /// \brief decrement the refCtr_ of an event \a e |
QL | 9:ca2e6010d9e2 | 519 | inline void QF_EVT_REF_CTR_DEC_(QEvt const * const e) { |
QL | 9:ca2e6010d9e2 | 520 | --(QF_EVT_CONST_CAST_(e))->refCtr_; |
QL | 9:ca2e6010d9e2 | 521 | } |
QL | 9:ca2e6010d9e2 | 522 | |
QL | 9:ca2e6010d9e2 | 523 | ////////////////////////////////////////////////////////////////////////////// |
QL | 9:ca2e6010d9e2 | 524 | // internal frequently used srongly-typed constants |
QL | 9:ca2e6010d9e2 | 525 | |
QL | 9:ca2e6010d9e2 | 526 | QTimeEvtCtr const tc_0 = static_cast<QTimeEvtCtr>(0); |
QL | 9:ca2e6010d9e2 | 527 | |
QL | 9:ca2e6010d9e2 | 528 | void * const null_void = static_cast<void *>(0); |
QL | 9:ca2e6010d9e2 | 529 | QEvt const * const null_evt = static_cast<QEvt const *>(0); |
QL | 9:ca2e6010d9e2 | 530 | QTimeEvt * const null_tevt = static_cast<QTimeEvt *>(0); |
QL | 9:ca2e6010d9e2 | 531 | QActive * const null_act = static_cast<QActive *>(0); |
QL | 9:ca2e6010d9e2 | 532 | |
QL | 9:ca2e6010d9e2 | 533 | QP_END_ |
QL | 9:ca2e6010d9e2 | 534 | |
QL | 9:ca2e6010d9e2 | 535 | /// \brief access element at index \a i_ from the base pointer \a base_ |
QL | 9:ca2e6010d9e2 | 536 | #define QF_PTR_AT_(base_, i_) (base_[i_]) |
QL | 9:ca2e6010d9e2 | 537 | |
QL | 9:ca2e6010d9e2 | 538 | ////////////////////////////////////////////////////////////////////////////// |
QL | 9:ca2e6010d9e2 | 539 | #ifdef Q_SPY // QS software tracing enabled? |
QL | 9:ca2e6010d9e2 | 540 | |
QL | 9:ca2e6010d9e2 | 541 | #if (QF_EQUEUE_CTR_SIZE == 1) |
QL | 9:ca2e6010d9e2 | 542 | |
QL | 9:ca2e6010d9e2 | 543 | /// \brief Internal QS macro to output an unformatted event queue |
QL | 9:ca2e6010d9e2 | 544 | /// counter data element |
QL | 9:ca2e6010d9e2 | 545 | /// \note the counter size depends on the macro #QF_EQUEUE_CTR_SIZE. |
QL | 9:ca2e6010d9e2 | 546 | #define QS_EQC_(ctr_) QS::u8_(ctr_) |
QL | 9:ca2e6010d9e2 | 547 | #elif (QF_EQUEUE_CTR_SIZE == 2) |
QL | 9:ca2e6010d9e2 | 548 | #define QS_EQC_(ctr_) QS::u16_(ctr_) |
QL | 9:ca2e6010d9e2 | 549 | #elif (QF_EQUEUE_CTR_SIZE == 4) |
QL | 9:ca2e6010d9e2 | 550 | #define QS_EQC_(ctr_) QS::u32_(ctr_) |
QL | 9:ca2e6010d9e2 | 551 | #else |
QL | 9:ca2e6010d9e2 | 552 | #error "QF_EQUEUE_CTR_SIZE not defined" |
QL | 9:ca2e6010d9e2 | 553 | #endif |
QL | 9:ca2e6010d9e2 | 554 | |
QL | 9:ca2e6010d9e2 | 555 | |
QL | 9:ca2e6010d9e2 | 556 | #if (QF_EVENT_SIZ_SIZE == 1) |
QL | 9:ca2e6010d9e2 | 557 | |
QL | 9:ca2e6010d9e2 | 558 | /// \brief Internal QS macro to output an unformatted event size |
QL | 9:ca2e6010d9e2 | 559 | /// data element |
QL | 9:ca2e6010d9e2 | 560 | /// \note the event size depends on the macro #QF_EVENT_SIZ_SIZE. |
QL | 9:ca2e6010d9e2 | 561 | #define QS_EVS_(size_) QS::u8_(size_) |
QL | 9:ca2e6010d9e2 | 562 | #elif (QF_EVENT_SIZ_SIZE == 2) |
QL | 9:ca2e6010d9e2 | 563 | #define QS_EVS_(size_) QS::u16_(size_) |
QL | 9:ca2e6010d9e2 | 564 | #elif (QF_EVENT_SIZ_SIZE == 4) |
QL | 9:ca2e6010d9e2 | 565 | #define QS_EVS_(size_) QS::u32_(size_) |
QL | 9:ca2e6010d9e2 | 566 | #endif |
QL | 9:ca2e6010d9e2 | 567 | |
QL | 9:ca2e6010d9e2 | 568 | |
QL | 9:ca2e6010d9e2 | 569 | #if (QF_MPOOL_SIZ_SIZE == 1) |
QL | 9:ca2e6010d9e2 | 570 | |
QL | 9:ca2e6010d9e2 | 571 | /// \brief Internal QS macro to output an unformatted memory pool |
QL | 9:ca2e6010d9e2 | 572 | /// block-size data element |
QL | 9:ca2e6010d9e2 | 573 | /// \note the block-size depends on the macro #QF_MPOOL_SIZ_SIZE. |
QL | 9:ca2e6010d9e2 | 574 | #define QS_MPS_(size_) QS::u8_(size_) |
QL | 9:ca2e6010d9e2 | 575 | #elif (QF_MPOOL_SIZ_SIZE == 2) |
QL | 9:ca2e6010d9e2 | 576 | #define QS_MPS_(size_) QS::u16_(size_) |
QL | 9:ca2e6010d9e2 | 577 | #elif (QF_MPOOL_SIZ_SIZE == 4) |
QL | 9:ca2e6010d9e2 | 578 | #define QS_MPS_(size_) QS::u32_(size_) |
QL | 9:ca2e6010d9e2 | 579 | #endif |
QL | 9:ca2e6010d9e2 | 580 | |
QL | 9:ca2e6010d9e2 | 581 | #if (QF_MPOOL_CTR_SIZE == 1) |
QL | 9:ca2e6010d9e2 | 582 | |
QL | 9:ca2e6010d9e2 | 583 | /// \brief Internal QS macro to output an unformatted memory pool |
QL | 9:ca2e6010d9e2 | 584 | /// block-counter data element |
QL | 9:ca2e6010d9e2 | 585 | /// \note the counter size depends on the macro #QF_MPOOL_CTR_SIZE. |
QL | 9:ca2e6010d9e2 | 586 | #define QS_MPC_(ctr_) QS::u8_(ctr_) |
QL | 9:ca2e6010d9e2 | 587 | #elif (QF_MPOOL_CTR_SIZE == 2) |
QL | 9:ca2e6010d9e2 | 588 | #define QS_MPC_(ctr_) QS::u16_(ctr_) |
QL | 9:ca2e6010d9e2 | 589 | #elif (QF_MPOOL_CTR_SIZE == 4) |
QL | 9:ca2e6010d9e2 | 590 | #define QS_MPC_(ctr_) QS::u32_(ctr_) |
QL | 9:ca2e6010d9e2 | 591 | #endif |
QL | 9:ca2e6010d9e2 | 592 | |
QL | 9:ca2e6010d9e2 | 593 | |
QL | 9:ca2e6010d9e2 | 594 | #if (QF_TIMEEVT_CTR_SIZE == 1) |
QL | 9:ca2e6010d9e2 | 595 | |
QL | 9:ca2e6010d9e2 | 596 | /// \brief Internal QS macro to output an unformatted time event |
QL | 9:ca2e6010d9e2 | 597 | /// tick-counter data element |
QL | 9:ca2e6010d9e2 | 598 | /// \note the counter size depends on the macro #QF_TIMEEVT_CTR_SIZE. |
QL | 9:ca2e6010d9e2 | 599 | #define QS_TEC_(ctr_) QS::u8_(ctr_) |
QL | 9:ca2e6010d9e2 | 600 | #elif (QF_TIMEEVT_CTR_SIZE == 2) |
QL | 9:ca2e6010d9e2 | 601 | #define QS_TEC_(ctr_) QS::u16_(ctr_) |
QL | 9:ca2e6010d9e2 | 602 | #elif (QF_TIMEEVT_CTR_SIZE == 4) |
QL | 9:ca2e6010d9e2 | 603 | #define QS_TEC_(ctr_) QS::u32_(ctr_) |
QL | 9:ca2e6010d9e2 | 604 | #endif |
QL | 9:ca2e6010d9e2 | 605 | |
QL | 9:ca2e6010d9e2 | 606 | #endif // Q_SPY |
QL | 9:ca2e6010d9e2 | 607 | |
QL | 9:ca2e6010d9e2 | 608 | // "qa_defer.cpp" ============================================================ |
QL | 9:ca2e6010d9e2 | 609 | /// \brief QActive::defer() and QActive::recall() implementation. |
QL | 9:ca2e6010d9e2 | 610 | /// |
QL | 9:ca2e6010d9e2 | 611 | |
QL | 9:ca2e6010d9e2 | 612 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 613 | |
QL | 9:ca2e6010d9e2 | 614 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 615 | void QActive::defer(QEQueue * const eq, QEvt const * const e) const { |
QL | 9:ca2e6010d9e2 | 616 | eq->postFIFO(e); |
QL | 9:ca2e6010d9e2 | 617 | } |
QL | 9:ca2e6010d9e2 | 618 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 619 | bool QActive::recall(QEQueue * const eq) { |
QL | 9:ca2e6010d9e2 | 620 | QEvt const * const e = eq->get(); // try to get evt from deferred queue |
QL | 9:ca2e6010d9e2 | 621 | bool const recalled = (e != null_evt); // event available? |
QL | 9:ca2e6010d9e2 | 622 | if (recalled) { |
QL | 9:ca2e6010d9e2 | 623 | postLIFO(e); // post it to the front of the Active Object's queue |
QL | 9:ca2e6010d9e2 | 624 | |
QL | 9:ca2e6010d9e2 | 625 | QF_CRIT_STAT_ |
QL | 9:ca2e6010d9e2 | 626 | QF_CRIT_ENTRY_(); |
QL | 9:ca2e6010d9e2 | 627 | |
QL | 9:ca2e6010d9e2 | 628 | if (QF_EVT_POOL_ID_(e) != u8_0) { // is it a dynamic event? |
QL | 9:ca2e6010d9e2 | 629 | |
QL | 9:ca2e6010d9e2 | 630 | // after posting to the AO's queue the event must be referenced |
QL | 9:ca2e6010d9e2 | 631 | // at least twice: once in the deferred event queue (eq->get() |
QL | 9:ca2e6010d9e2 | 632 | // did NOT decrement the reference counter) and once in the |
QL | 9:ca2e6010d9e2 | 633 | // AO's event queue. |
QL | 9:ca2e6010d9e2 | 634 | Q_ASSERT(QF_EVT_REF_CTR_(e) > u8_1); |
QL | 9:ca2e6010d9e2 | 635 | |
QL | 9:ca2e6010d9e2 | 636 | // we need to decrement the reference counter once, to account |
QL | 9:ca2e6010d9e2 | 637 | // for removing the event from the deferred event queue. |
QL | 9:ca2e6010d9e2 | 638 | // |
QL | 9:ca2e6010d9e2 | 639 | QF_EVT_REF_CTR_DEC_(e); // decrement the reference counter |
QL | 9:ca2e6010d9e2 | 640 | } |
QL | 9:ca2e6010d9e2 | 641 | |
QL | 9:ca2e6010d9e2 | 642 | QF_CRIT_EXIT_(); |
QL | 9:ca2e6010d9e2 | 643 | } |
QL | 9:ca2e6010d9e2 | 644 | return recalled; // event not recalled |
QL | 9:ca2e6010d9e2 | 645 | } |
QL | 9:ca2e6010d9e2 | 646 | |
QL | 9:ca2e6010d9e2 | 647 | QP_END_ |
QL | 9:ca2e6010d9e2 | 648 | |
QL | 9:ca2e6010d9e2 | 649 | |
QL | 9:ca2e6010d9e2 | 650 | // "qa_fifo.cpp" ============================================================= |
QL | 9:ca2e6010d9e2 | 651 | /// \brief QActive::postFIFO() implementation. |
QL | 9:ca2e6010d9e2 | 652 | /// |
QL | 9:ca2e6010d9e2 | 653 | /// \note this source file is only included in the QF library when the native |
QL | 9:ca2e6010d9e2 | 654 | /// QF active object queue is used (instead of a message queue of an RTOS). |
QL | 9:ca2e6010d9e2 | 655 | |
QL | 9:ca2e6010d9e2 | 656 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 657 | |
QL | 9:ca2e6010d9e2 | 658 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 659 | #ifndef Q_SPY |
QL | 9:ca2e6010d9e2 | 660 | void QActive::postFIFO(QEvt const * const e) { |
QL | 9:ca2e6010d9e2 | 661 | #else |
QL | 9:ca2e6010d9e2 | 662 | void QActive::postFIFO(QEvt const * const e, void const * const sender) { |
QL | 9:ca2e6010d9e2 | 663 | #endif |
QL | 9:ca2e6010d9e2 | 664 | |
QL | 9:ca2e6010d9e2 | 665 | QF_CRIT_STAT_ |
QL | 9:ca2e6010d9e2 | 666 | QF_CRIT_ENTRY_(); |
QL | 9:ca2e6010d9e2 | 667 | |
QL | 9:ca2e6010d9e2 | 668 | QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_POST_FIFO, QS::aoObj_, this) |
QL | 9:ca2e6010d9e2 | 669 | QS_TIME_(); // timestamp |
QL | 9:ca2e6010d9e2 | 670 | QS_OBJ_(sender); // the sender object |
QL | 9:ca2e6010d9e2 | 671 | QS_SIG_(e->sig); // the signal of the event |
QL | 9:ca2e6010d9e2 | 672 | QS_OBJ_(this); // this active object |
QL | 9:ca2e6010d9e2 | 673 | QS_U8_(QF_EVT_POOL_ID_(e)); // the pool Id of the event |
QL | 9:ca2e6010d9e2 | 674 | QS_U8_(QF_EVT_REF_CTR_(e)); // the ref count of the event |
QL | 9:ca2e6010d9e2 | 675 | QS_EQC_(m_eQueue.m_nFree); // number of free entries |
QL | 9:ca2e6010d9e2 | 676 | QS_EQC_(m_eQueue.m_nMin); // min number of free entries |
QL | 9:ca2e6010d9e2 | 677 | QS_END_NOCRIT_() |
QL | 9:ca2e6010d9e2 | 678 | |
QL | 9:ca2e6010d9e2 | 679 | if (QF_EVT_POOL_ID_(e) != u8_0) { // is it a dynamic event? |
QL | 9:ca2e6010d9e2 | 680 | QF_EVT_REF_CTR_INC_(e); // increment the reference counter |
QL | 9:ca2e6010d9e2 | 681 | } |
QL | 9:ca2e6010d9e2 | 682 | |
QL | 9:ca2e6010d9e2 | 683 | if (m_eQueue.m_frontEvt == null_evt) { // is the queue empty? |
QL | 9:ca2e6010d9e2 | 684 | m_eQueue.m_frontEvt = e; // deliver event directly |
QL | 9:ca2e6010d9e2 | 685 | QACTIVE_EQUEUE_SIGNAL_(this); // signal the event queue |
QL | 9:ca2e6010d9e2 | 686 | } |
QL | 9:ca2e6010d9e2 | 687 | else { // queue is not empty, leave event in the ring-buffer |
QL | 9:ca2e6010d9e2 | 688 | // queue must accept all posted events |
QL | 9:ca2e6010d9e2 | 689 | Q_ASSERT(m_eQueue.m_nFree != static_cast<QEQueueCtr>(0)); |
QL | 9:ca2e6010d9e2 | 690 | // insert event pointer e into the buffer (FIFO) |
QL | 9:ca2e6010d9e2 | 691 | QF_PTR_AT_(m_eQueue.m_ring, m_eQueue.m_head) = e; |
QL | 9:ca2e6010d9e2 | 692 | if (m_eQueue.m_head == static_cast<QEQueueCtr>(0)) { // need to wrap? |
QL | 9:ca2e6010d9e2 | 693 | m_eQueue.m_head = m_eQueue.m_end; // wrap around |
QL | 9:ca2e6010d9e2 | 694 | } |
QL | 9:ca2e6010d9e2 | 695 | --m_eQueue.m_head; |
QL | 9:ca2e6010d9e2 | 696 | |
QL | 9:ca2e6010d9e2 | 697 | --m_eQueue.m_nFree; // update number of free events |
QL | 9:ca2e6010d9e2 | 698 | if (m_eQueue.m_nMin > m_eQueue.m_nFree) { |
QL | 9:ca2e6010d9e2 | 699 | m_eQueue.m_nMin = m_eQueue.m_nFree; // update minimum so far |
QL | 9:ca2e6010d9e2 | 700 | } |
QL | 9:ca2e6010d9e2 | 701 | } |
QL | 9:ca2e6010d9e2 | 702 | QF_CRIT_EXIT_(); |
QL | 9:ca2e6010d9e2 | 703 | } |
QL | 9:ca2e6010d9e2 | 704 | |
QL | 9:ca2e6010d9e2 | 705 | QP_END_ |
QL | 9:ca2e6010d9e2 | 706 | |
QL | 9:ca2e6010d9e2 | 707 | // "qa_get_.cpp" ============================================================= |
QL | 9:ca2e6010d9e2 | 708 | /// \brief QActive::get_() and QF::getQueueMargin() definitions. |
QL | 9:ca2e6010d9e2 | 709 | /// |
QL | 9:ca2e6010d9e2 | 710 | /// \note this source file is only included in the QF library when the native |
QL | 9:ca2e6010d9e2 | 711 | /// QF active object queue is used (instead of a message queue of an RTOS). |
QL | 9:ca2e6010d9e2 | 712 | |
QL | 9:ca2e6010d9e2 | 713 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 714 | |
QL | 9:ca2e6010d9e2 | 715 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 716 | QEvt const *QActive::get_(void) { |
QL | 9:ca2e6010d9e2 | 717 | QF_CRIT_STAT_ |
QL | 9:ca2e6010d9e2 | 718 | QF_CRIT_ENTRY_(); |
QL | 9:ca2e6010d9e2 | 719 | |
QL | 9:ca2e6010d9e2 | 720 | QACTIVE_EQUEUE_WAIT_(this); // wait for event to arrive directly |
QL | 9:ca2e6010d9e2 | 721 | |
QL | 9:ca2e6010d9e2 | 722 | QEvt const *e = m_eQueue.m_frontEvt; |
QL | 9:ca2e6010d9e2 | 723 | |
QL | 9:ca2e6010d9e2 | 724 | if (m_eQueue.m_nFree != m_eQueue.m_end) { //any events in the ring buffer? |
QL | 9:ca2e6010d9e2 | 725 | // remove event from the tail |
QL | 9:ca2e6010d9e2 | 726 | m_eQueue.m_frontEvt = QF_PTR_AT_(m_eQueue.m_ring, m_eQueue.m_tail); |
QL | 9:ca2e6010d9e2 | 727 | if (m_eQueue.m_tail == static_cast<QEQueueCtr>(0)) { // need to wrap? |
QL | 9:ca2e6010d9e2 | 728 | m_eQueue.m_tail = m_eQueue.m_end; // wrap around |
QL | 9:ca2e6010d9e2 | 729 | } |
QL | 9:ca2e6010d9e2 | 730 | --m_eQueue.m_tail; |
QL | 9:ca2e6010d9e2 | 731 | |
QL | 9:ca2e6010d9e2 | 732 | ++m_eQueue.m_nFree; // one more free event in the ring buffer |
QL | 9:ca2e6010d9e2 | 733 | |
QL | 9:ca2e6010d9e2 | 734 | QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_GET, QS::aoObj_, this) |
QL | 9:ca2e6010d9e2 | 735 | QS_TIME_(); // timestamp |
QL | 9:ca2e6010d9e2 | 736 | QS_SIG_(e->sig); // the signal of this event |
QL | 9:ca2e6010d9e2 | 737 | QS_OBJ_(this); // this active object |
QL | 9:ca2e6010d9e2 | 738 | QS_U8_(QF_EVT_POOL_ID_(e)); // the pool Id of the event |
QL | 9:ca2e6010d9e2 | 739 | QS_U8_(QF_EVT_REF_CTR_(e)); // the ref count of the event |
QL | 9:ca2e6010d9e2 | 740 | QS_EQC_(m_eQueue.m_nFree); // number of free entries |
QL | 9:ca2e6010d9e2 | 741 | QS_END_NOCRIT_() |
QL | 9:ca2e6010d9e2 | 742 | } |
QL | 9:ca2e6010d9e2 | 743 | else { |
QL | 9:ca2e6010d9e2 | 744 | m_eQueue.m_frontEvt = null_evt; // the queue becomes empty |
QL | 9:ca2e6010d9e2 | 745 | QACTIVE_EQUEUE_ONEMPTY_(this); |
QL | 9:ca2e6010d9e2 | 746 | |
QL | 9:ca2e6010d9e2 | 747 | QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_GET_LAST, QS::aoObj_, this) |
QL | 9:ca2e6010d9e2 | 748 | QS_TIME_(); // timestamp |
QL | 9:ca2e6010d9e2 | 749 | QS_SIG_(e->sig); // the signal of this event |
QL | 9:ca2e6010d9e2 | 750 | QS_OBJ_(this); // this active object |
QL | 9:ca2e6010d9e2 | 751 | QS_U8_(QF_EVT_POOL_ID_(e)); // the pool Id of the event |
QL | 9:ca2e6010d9e2 | 752 | QS_U8_(QF_EVT_REF_CTR_(e)); // the ref count of the event |
QL | 9:ca2e6010d9e2 | 753 | QS_END_NOCRIT_() |
QL | 9:ca2e6010d9e2 | 754 | } |
QL | 9:ca2e6010d9e2 | 755 | QF_CRIT_EXIT_(); |
QL | 9:ca2e6010d9e2 | 756 | return e; |
QL | 9:ca2e6010d9e2 | 757 | } |
QL | 9:ca2e6010d9e2 | 758 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 759 | uint32_t QF::getQueueMargin(uint8_t const prio) { |
QL | 9:ca2e6010d9e2 | 760 | Q_REQUIRE((prio <= static_cast<uint8_t>(QF_MAX_ACTIVE)) |
QL | 9:ca2e6010d9e2 | 761 | && (active_[prio] != static_cast<QActive *>(0))); |
QL | 9:ca2e6010d9e2 | 762 | |
QL | 9:ca2e6010d9e2 | 763 | QF_CRIT_STAT_ |
QL | 9:ca2e6010d9e2 | 764 | QF_CRIT_ENTRY_(); |
QL | 9:ca2e6010d9e2 | 765 | uint32_t margin = static_cast<uint32_t>(active_[prio]->m_eQueue.m_nMin); |
QL | 9:ca2e6010d9e2 | 766 | QF_CRIT_EXIT_(); |
QL | 9:ca2e6010d9e2 | 767 | |
QL | 9:ca2e6010d9e2 | 768 | return margin; |
QL | 9:ca2e6010d9e2 | 769 | } |
QL | 9:ca2e6010d9e2 | 770 | |
QL | 9:ca2e6010d9e2 | 771 | QP_END_ |
QL | 9:ca2e6010d9e2 | 772 | |
QL | 9:ca2e6010d9e2 | 773 | // "qa_lifo.cpp" ============================================================= |
QL | 9:ca2e6010d9e2 | 774 | /// \brief QActive::postLIFO() implementation. |
QL | 9:ca2e6010d9e2 | 775 | /// |
QL | 9:ca2e6010d9e2 | 776 | /// \note this source file is only included in the QF library when the native |
QL | 9:ca2e6010d9e2 | 777 | /// QF active object queue is used (instead of a message queue of an RTOS). |
QL | 9:ca2e6010d9e2 | 778 | |
QL | 9:ca2e6010d9e2 | 779 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 780 | |
QL | 9:ca2e6010d9e2 | 781 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 782 | void QActive::postLIFO(QEvt const * const e) { |
QL | 9:ca2e6010d9e2 | 783 | QF_CRIT_STAT_ |
QL | 9:ca2e6010d9e2 | 784 | QF_CRIT_ENTRY_(); |
QL | 9:ca2e6010d9e2 | 785 | |
QL | 9:ca2e6010d9e2 | 786 | QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_POST_LIFO, QS::aoObj_, this) |
QL | 9:ca2e6010d9e2 | 787 | QS_TIME_(); // timestamp |
QL | 9:ca2e6010d9e2 | 788 | QS_SIG_(e->sig); // the signal of this event |
QL | 9:ca2e6010d9e2 | 789 | QS_OBJ_(this); // this active object |
QL | 9:ca2e6010d9e2 | 790 | QS_U8_(QF_EVT_POOL_ID_(e)); // the pool Id of the event |
QL | 9:ca2e6010d9e2 | 791 | QS_U8_(QF_EVT_REF_CTR_(e)); // the ref count of the event |
QL | 9:ca2e6010d9e2 | 792 | QS_EQC_(m_eQueue.m_nFree); // number of free entries |
QL | 9:ca2e6010d9e2 | 793 | QS_EQC_(m_eQueue.m_nMin); // min number of free entries |
QL | 9:ca2e6010d9e2 | 794 | QS_END_NOCRIT_() |
QL | 9:ca2e6010d9e2 | 795 | |
QL | 9:ca2e6010d9e2 | 796 | if (QF_EVT_POOL_ID_(e) != u8_0) { // is it a dynamic event? |
QL | 9:ca2e6010d9e2 | 797 | QF_EVT_REF_CTR_INC_(e); // increment the reference counter |
QL | 9:ca2e6010d9e2 | 798 | } |
QL | 9:ca2e6010d9e2 | 799 | |
QL | 9:ca2e6010d9e2 | 800 | if (m_eQueue.m_frontEvt == null_evt) { // is the queue empty? |
QL | 9:ca2e6010d9e2 | 801 | m_eQueue.m_frontEvt = e; // deliver event directly |
QL | 9:ca2e6010d9e2 | 802 | QACTIVE_EQUEUE_SIGNAL_(this); // signal the event queue |
QL | 9:ca2e6010d9e2 | 803 | } |
QL | 9:ca2e6010d9e2 | 804 | else { // queue is not empty, leave event in the ring-buffer |
QL | 9:ca2e6010d9e2 | 805 | // queue must accept all posted events |
QL | 9:ca2e6010d9e2 | 806 | Q_ASSERT(m_eQueue.m_nFree != static_cast<QEQueueCtr>(0)); |
QL | 9:ca2e6010d9e2 | 807 | |
QL | 9:ca2e6010d9e2 | 808 | ++m_eQueue.m_tail; |
QL | 9:ca2e6010d9e2 | 809 | if (m_eQueue.m_tail == m_eQueue.m_end) { // need to wrap the tail? |
QL | 9:ca2e6010d9e2 | 810 | m_eQueue.m_tail = static_cast<QEQueueCtr>(0); // wrap around |
QL | 9:ca2e6010d9e2 | 811 | } |
QL | 9:ca2e6010d9e2 | 812 | |
QL | 9:ca2e6010d9e2 | 813 | QF_PTR_AT_(m_eQueue.m_ring, m_eQueue.m_tail) = m_eQueue.m_frontEvt; |
QL | 9:ca2e6010d9e2 | 814 | m_eQueue.m_frontEvt = e; // put event to front |
QL | 9:ca2e6010d9e2 | 815 | |
QL | 9:ca2e6010d9e2 | 816 | --m_eQueue.m_nFree; // update number of free events |
QL | 9:ca2e6010d9e2 | 817 | if (m_eQueue.m_nMin > m_eQueue.m_nFree) { |
QL | 9:ca2e6010d9e2 | 818 | m_eQueue.m_nMin = m_eQueue.m_nFree; // update minimum so far |
QL | 9:ca2e6010d9e2 | 819 | } |
QL | 9:ca2e6010d9e2 | 820 | } |
QL | 9:ca2e6010d9e2 | 821 | QF_CRIT_EXIT_(); |
QL | 9:ca2e6010d9e2 | 822 | } |
QL | 9:ca2e6010d9e2 | 823 | |
QL | 9:ca2e6010d9e2 | 824 | QP_END_ |
QL | 9:ca2e6010d9e2 | 825 | |
QL | 9:ca2e6010d9e2 | 826 | // "qa_sub.cpp" ============================================================== |
QL | 9:ca2e6010d9e2 | 827 | /// \brief QActive::subscribe() implementation. |
QL | 9:ca2e6010d9e2 | 828 | |
QL | 9:ca2e6010d9e2 | 829 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 830 | |
QL | 9:ca2e6010d9e2 | 831 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 832 | void QActive::subscribe(enum_t const sig) const { |
QL | 9:ca2e6010d9e2 | 833 | uint8_t p = m_prio; |
QL | 9:ca2e6010d9e2 | 834 | Q_REQUIRE((Q_USER_SIG <= sig) |
QL | 9:ca2e6010d9e2 | 835 | && (sig < QF_maxSignal_) |
QL | 9:ca2e6010d9e2 | 836 | && (u8_0 < p) && (p <= static_cast<uint8_t>(QF_MAX_ACTIVE)) |
QL | 9:ca2e6010d9e2 | 837 | && (QF::active_[p] == this)); |
QL | 9:ca2e6010d9e2 | 838 | |
QL | 9:ca2e6010d9e2 | 839 | uint8_t const i = Q_ROM_BYTE(QF_div8Lkup[p]); |
QL | 9:ca2e6010d9e2 | 840 | |
QL | 9:ca2e6010d9e2 | 841 | QF_CRIT_STAT_ |
QL | 9:ca2e6010d9e2 | 842 | QF_CRIT_ENTRY_(); |
QL | 9:ca2e6010d9e2 | 843 | |
QL | 9:ca2e6010d9e2 | 844 | QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_SUBSCRIBE, QS::aoObj_, this) |
QL | 9:ca2e6010d9e2 | 845 | QS_TIME_(); // timestamp |
QL | 9:ca2e6010d9e2 | 846 | QS_SIG_(sig); // the signal of this event |
QL | 9:ca2e6010d9e2 | 847 | QS_OBJ_(this); // this active object |
QL | 9:ca2e6010d9e2 | 848 | QS_END_NOCRIT_() |
QL | 9:ca2e6010d9e2 | 849 | // set the priority bit |
QL | 9:ca2e6010d9e2 | 850 | QF_PTR_AT_(QF_subscrList_, sig).m_bits[i] |= Q_ROM_BYTE(QF_pwr2Lkup[p]); |
QL | 9:ca2e6010d9e2 | 851 | QF_CRIT_EXIT_(); |
QL | 9:ca2e6010d9e2 | 852 | } |
QL | 9:ca2e6010d9e2 | 853 | |
QL | 9:ca2e6010d9e2 | 854 | QP_END_ |
QL | 9:ca2e6010d9e2 | 855 | |
QL | 9:ca2e6010d9e2 | 856 | // "qa_usub.cpp" ============================================================= |
QL | 9:ca2e6010d9e2 | 857 | /// \brief QActive::unsubscribe() implementation. |
QL | 9:ca2e6010d9e2 | 858 | |
QL | 9:ca2e6010d9e2 | 859 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 860 | |
QL | 9:ca2e6010d9e2 | 861 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 862 | void QActive::unsubscribe(enum_t const sig) const { |
QL | 9:ca2e6010d9e2 | 863 | uint8_t p = m_prio; |
QL | 9:ca2e6010d9e2 | 864 | Q_REQUIRE((Q_USER_SIG <= sig) |
QL | 9:ca2e6010d9e2 | 865 | && (sig < QF_maxSignal_) |
QL | 9:ca2e6010d9e2 | 866 | && (u8_0 < p) && (p <= static_cast<uint8_t>(QF_MAX_ACTIVE)) |
QL | 9:ca2e6010d9e2 | 867 | && (QF::active_[p] == this)); |
QL | 9:ca2e6010d9e2 | 868 | |
QL | 9:ca2e6010d9e2 | 869 | uint8_t const i = Q_ROM_BYTE(QF_div8Lkup[p]); |
QL | 9:ca2e6010d9e2 | 870 | |
QL | 9:ca2e6010d9e2 | 871 | QF_CRIT_STAT_ |
QL | 9:ca2e6010d9e2 | 872 | QF_CRIT_ENTRY_(); |
QL | 9:ca2e6010d9e2 | 873 | |
QL | 9:ca2e6010d9e2 | 874 | QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_UNSUBSCRIBE, QS::aoObj_, this) |
QL | 9:ca2e6010d9e2 | 875 | QS_TIME_(); // timestamp |
QL | 9:ca2e6010d9e2 | 876 | QS_SIG_(sig); // the signal of this event |
QL | 9:ca2e6010d9e2 | 877 | QS_OBJ_(this); // this active object |
QL | 9:ca2e6010d9e2 | 878 | QS_END_NOCRIT_() |
QL | 9:ca2e6010d9e2 | 879 | // clear the priority bit |
QL | 9:ca2e6010d9e2 | 880 | QF_PTR_AT_(QF_subscrList_,sig).m_bits[i] &= Q_ROM_BYTE(QF_invPwr2Lkup[p]); |
QL | 9:ca2e6010d9e2 | 881 | QF_CRIT_EXIT_(); |
QL | 9:ca2e6010d9e2 | 882 | } |
QL | 9:ca2e6010d9e2 | 883 | |
QL | 9:ca2e6010d9e2 | 884 | QP_END_ |
QL | 9:ca2e6010d9e2 | 885 | |
QL | 9:ca2e6010d9e2 | 886 | // "qa_usuba.cpp" ============================================================ |
QL | 9:ca2e6010d9e2 | 887 | /// \brief QActive::unsubscribeAll() implementation. |
QL | 9:ca2e6010d9e2 | 888 | |
QL | 9:ca2e6010d9e2 | 889 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 890 | |
QL | 9:ca2e6010d9e2 | 891 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 892 | void QActive::unsubscribeAll(void) const { |
QL | 9:ca2e6010d9e2 | 893 | uint8_t const p = m_prio; |
QL | 9:ca2e6010d9e2 | 894 | Q_REQUIRE((u8_0 < p) && (p <= static_cast<uint8_t>(QF_MAX_ACTIVE)) |
QL | 9:ca2e6010d9e2 | 895 | && (QF::active_[p] == this)); |
QL | 9:ca2e6010d9e2 | 896 | |
QL | 9:ca2e6010d9e2 | 897 | uint8_t const i = Q_ROM_BYTE(QF_div8Lkup[p]); |
QL | 9:ca2e6010d9e2 | 898 | |
QL | 9:ca2e6010d9e2 | 899 | enum_t sig; |
QL | 9:ca2e6010d9e2 | 900 | for (sig = Q_USER_SIG; sig < QF_maxSignal_; ++sig) { |
QL | 9:ca2e6010d9e2 | 901 | QF_CRIT_STAT_ |
QL | 9:ca2e6010d9e2 | 902 | QF_CRIT_ENTRY_(); |
QL | 9:ca2e6010d9e2 | 903 | if ((QF_PTR_AT_(QF_subscrList_, sig).m_bits[i] |
QL | 9:ca2e6010d9e2 | 904 | & Q_ROM_BYTE(QF_pwr2Lkup[p])) != u8_0) |
QL | 9:ca2e6010d9e2 | 905 | { |
QL | 9:ca2e6010d9e2 | 906 | |
QL | 9:ca2e6010d9e2 | 907 | QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_UNSUBSCRIBE, QS::aoObj_, this) |
QL | 9:ca2e6010d9e2 | 908 | QS_TIME_(); // timestamp |
QL | 9:ca2e6010d9e2 | 909 | QS_SIG_(sig); // the signal of this event |
QL | 9:ca2e6010d9e2 | 910 | QS_OBJ_(this); // this active object |
QL | 9:ca2e6010d9e2 | 911 | QS_END_NOCRIT_() |
QL | 9:ca2e6010d9e2 | 912 | // clear the priority bit |
QL | 9:ca2e6010d9e2 | 913 | QF_PTR_AT_(QF_subscrList_, sig).m_bits[i] &= |
QL | 9:ca2e6010d9e2 | 914 | Q_ROM_BYTE(QF_invPwr2Lkup[p]); |
QL | 9:ca2e6010d9e2 | 915 | } |
QL | 9:ca2e6010d9e2 | 916 | QF_CRIT_EXIT_(); |
QL | 9:ca2e6010d9e2 | 917 | } |
QL | 9:ca2e6010d9e2 | 918 | } |
QL | 9:ca2e6010d9e2 | 919 | |
QL | 9:ca2e6010d9e2 | 920 | QP_END_ |
QL | 9:ca2e6010d9e2 | 921 | |
QL | 9:ca2e6010d9e2 | 922 | // "qeq_fifo.cpp" ============================================================ |
QL | 9:ca2e6010d9e2 | 923 | /// \brief QEQueue::postFIFO() implementation. |
QL | 9:ca2e6010d9e2 | 924 | |
QL | 9:ca2e6010d9e2 | 925 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 926 | |
QL | 9:ca2e6010d9e2 | 927 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 928 | void QEQueue::postFIFO(QEvt const * const e) { |
QL | 9:ca2e6010d9e2 | 929 | QF_CRIT_STAT_ |
QL | 9:ca2e6010d9e2 | 930 | QF_CRIT_ENTRY_(); |
QL | 9:ca2e6010d9e2 | 931 | |
QL | 9:ca2e6010d9e2 | 932 | QS_BEGIN_NOCRIT_(QS_QF_EQUEUE_POST_FIFO, QS::eqObj_, this) |
QL | 9:ca2e6010d9e2 | 933 | QS_TIME_(); // timestamp |
QL | 9:ca2e6010d9e2 | 934 | QS_SIG_(e->sig); // the signal of this event |
QL | 9:ca2e6010d9e2 | 935 | QS_OBJ_(this); // this queue object |
QL | 9:ca2e6010d9e2 | 936 | QS_U8_(QF_EVT_POOL_ID_(e)); // the pool Id of the event |
QL | 9:ca2e6010d9e2 | 937 | QS_U8_(QF_EVT_REF_CTR_(e)); // the ref count of the event |
QL | 9:ca2e6010d9e2 | 938 | QS_EQC_(m_nFree); // number of free entries |
QL | 9:ca2e6010d9e2 | 939 | QS_EQC_(m_nMin); // min number of free entries |
QL | 9:ca2e6010d9e2 | 940 | QS_END_NOCRIT_() |
QL | 9:ca2e6010d9e2 | 941 | |
QL | 9:ca2e6010d9e2 | 942 | if (QF_EVT_POOL_ID_(e) != u8_0) { // is it a dynamic event? |
QL | 9:ca2e6010d9e2 | 943 | QF_EVT_REF_CTR_INC_(e); // increment the reference counter |
QL | 9:ca2e6010d9e2 | 944 | } |
QL | 9:ca2e6010d9e2 | 945 | |
QL | 9:ca2e6010d9e2 | 946 | if (m_frontEvt == null_evt) { // is the queue empty? |
QL | 9:ca2e6010d9e2 | 947 | m_frontEvt = e; // deliver event directly |
QL | 9:ca2e6010d9e2 | 948 | } |
QL | 9:ca2e6010d9e2 | 949 | else { // queue is not empty, leave event in the ring-buffer |
QL | 9:ca2e6010d9e2 | 950 | // the queue must be able to accept the event (cannot overflow) |
QL | 9:ca2e6010d9e2 | 951 | Q_ASSERT(m_nFree != static_cast<QEQueueCtr>(0)); |
QL | 9:ca2e6010d9e2 | 952 | |
QL | 9:ca2e6010d9e2 | 953 | QF_PTR_AT_(m_ring, m_head) = e; // insert event into the buffer (FIFO) |
QL | 9:ca2e6010d9e2 | 954 | if (m_head == static_cast<QEQueueCtr>(0)) { // need to wrap? |
QL | 9:ca2e6010d9e2 | 955 | m_head = m_end; // wrap around |
QL | 9:ca2e6010d9e2 | 956 | } |
QL | 9:ca2e6010d9e2 | 957 | --m_head; |
QL | 9:ca2e6010d9e2 | 958 | |
QL | 9:ca2e6010d9e2 | 959 | --m_nFree; // update number of free events |
QL | 9:ca2e6010d9e2 | 960 | if (m_nMin > m_nFree) { |
QL | 9:ca2e6010d9e2 | 961 | m_nMin = m_nFree; // update minimum so far |
QL | 9:ca2e6010d9e2 | 962 | } |
QL | 9:ca2e6010d9e2 | 963 | } |
QL | 9:ca2e6010d9e2 | 964 | QF_CRIT_EXIT_(); |
QL | 9:ca2e6010d9e2 | 965 | } |
QL | 9:ca2e6010d9e2 | 966 | |
QL | 9:ca2e6010d9e2 | 967 | QP_END_ |
QL | 9:ca2e6010d9e2 | 968 | |
QL | 9:ca2e6010d9e2 | 969 | // "qeq_get.cpp" ============================================================= |
QL | 9:ca2e6010d9e2 | 970 | /// \brief QEQueue::get() implementation. |
QL | 9:ca2e6010d9e2 | 971 | |
QL | 9:ca2e6010d9e2 | 972 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 973 | |
QL | 9:ca2e6010d9e2 | 974 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 975 | QEvt const *QEQueue::get(void) { |
QL | 9:ca2e6010d9e2 | 976 | QEvt const *e; |
QL | 9:ca2e6010d9e2 | 977 | QF_CRIT_STAT_ |
QL | 9:ca2e6010d9e2 | 978 | |
QL | 9:ca2e6010d9e2 | 979 | QF_CRIT_ENTRY_(); |
QL | 9:ca2e6010d9e2 | 980 | if (m_frontEvt == null_evt) { // is the queue empty? |
QL | 9:ca2e6010d9e2 | 981 | e = null_evt; // no event available at this time |
QL | 9:ca2e6010d9e2 | 982 | } |
QL | 9:ca2e6010d9e2 | 983 | else { |
QL | 9:ca2e6010d9e2 | 984 | e = m_frontEvt; |
QL | 9:ca2e6010d9e2 | 985 | |
QL | 9:ca2e6010d9e2 | 986 | if (m_nFree != m_end) { // any events in the the ring buffer? |
QL | 9:ca2e6010d9e2 | 987 | m_frontEvt = QF_PTR_AT_(m_ring, m_tail); // remove from the tail |
QL | 9:ca2e6010d9e2 | 988 | if (m_tail == static_cast<QEQueueCtr>(0)) { // need to wrap? |
QL | 9:ca2e6010d9e2 | 989 | m_tail = m_end; // wrap around |
QL | 9:ca2e6010d9e2 | 990 | } |
QL | 9:ca2e6010d9e2 | 991 | --m_tail; |
QL | 9:ca2e6010d9e2 | 992 | |
QL | 9:ca2e6010d9e2 | 993 | ++m_nFree; // one more free event in the ring buffer |
QL | 9:ca2e6010d9e2 | 994 | |
QL | 9:ca2e6010d9e2 | 995 | QS_BEGIN_NOCRIT_(QS_QF_EQUEUE_GET, QS::eqObj_, this) |
QL | 9:ca2e6010d9e2 | 996 | QS_TIME_(); // timestamp |
QL | 9:ca2e6010d9e2 | 997 | QS_SIG_(e->sig); // the signal of this event |
QL | 9:ca2e6010d9e2 | 998 | QS_OBJ_(this); // this queue object |
QL | 9:ca2e6010d9e2 | 999 | QS_U8_(QF_EVT_POOL_ID_(e)); // the pool Id of the event |
QL | 9:ca2e6010d9e2 | 1000 | QS_U8_(QF_EVT_REF_CTR_(e)); // the ref count of the event |
QL | 9:ca2e6010d9e2 | 1001 | QS_EQC_(m_nFree); // number of free entries |
QL | 9:ca2e6010d9e2 | 1002 | QS_END_NOCRIT_() |
QL | 9:ca2e6010d9e2 | 1003 | } |
QL | 9:ca2e6010d9e2 | 1004 | else { |
QL | 9:ca2e6010d9e2 | 1005 | m_frontEvt = null_evt; // the queue becomes empty |
QL | 9:ca2e6010d9e2 | 1006 | |
QL | 9:ca2e6010d9e2 | 1007 | QS_BEGIN_NOCRIT_(QS_QF_EQUEUE_GET_LAST, QS::eqObj_, this) |
QL | 9:ca2e6010d9e2 | 1008 | QS_TIME_(); // timestamp |
QL | 9:ca2e6010d9e2 | 1009 | QS_SIG_(e->sig); // the signal of this event |
QL | 9:ca2e6010d9e2 | 1010 | QS_OBJ_(this); // this queue object |
QL | 9:ca2e6010d9e2 | 1011 | QS_U8_(QF_EVT_POOL_ID_(e)); // the pool Id of the event |
QL | 9:ca2e6010d9e2 | 1012 | QS_U8_(QF_EVT_REF_CTR_(e)); // the ref count of the event |
QL | 9:ca2e6010d9e2 | 1013 | QS_END_NOCRIT_() |
QL | 9:ca2e6010d9e2 | 1014 | } |
QL | 9:ca2e6010d9e2 | 1015 | } |
QL | 9:ca2e6010d9e2 | 1016 | QF_CRIT_EXIT_(); |
QL | 9:ca2e6010d9e2 | 1017 | return e; |
QL | 9:ca2e6010d9e2 | 1018 | } |
QL | 9:ca2e6010d9e2 | 1019 | |
QL | 9:ca2e6010d9e2 | 1020 | QP_END_ |
QL | 9:ca2e6010d9e2 | 1021 | |
QL | 9:ca2e6010d9e2 | 1022 | // "qeq_init.cpp" ============================================================ |
QL | 9:ca2e6010d9e2 | 1023 | /// \brief QEQueue::init() implementation. |
QL | 9:ca2e6010d9e2 | 1024 | |
QL | 9:ca2e6010d9e2 | 1025 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 1026 | |
QL | 9:ca2e6010d9e2 | 1027 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 1028 | void QEQueue::init(QEvt const *qSto[], QEQueueCtr const qLen) { |
QL | 9:ca2e6010d9e2 | 1029 | m_frontEvt = null_evt; // no events in the queue |
QL | 9:ca2e6010d9e2 | 1030 | m_ring = &qSto[0]; |
QL | 9:ca2e6010d9e2 | 1031 | m_end = qLen; |
QL | 9:ca2e6010d9e2 | 1032 | m_head = static_cast<QEQueueCtr>(0); |
QL | 9:ca2e6010d9e2 | 1033 | m_tail = static_cast<QEQueueCtr>(0); |
QL | 9:ca2e6010d9e2 | 1034 | m_nFree = qLen; |
QL | 9:ca2e6010d9e2 | 1035 | m_nMin = qLen; |
QL | 9:ca2e6010d9e2 | 1036 | |
QL | 9:ca2e6010d9e2 | 1037 | QS_CRIT_STAT_ |
QL | 9:ca2e6010d9e2 | 1038 | QS_BEGIN_(QS_QF_EQUEUE_INIT, QS::eqObj_, this) |
QL | 9:ca2e6010d9e2 | 1039 | QS_OBJ_(qSto); // this QEQueue object |
QL | 9:ca2e6010d9e2 | 1040 | QS_EQC_(qLen); // the length of the queue |
QL | 9:ca2e6010d9e2 | 1041 | QS_END_() |
QL | 9:ca2e6010d9e2 | 1042 | } |
QL | 9:ca2e6010d9e2 | 1043 | |
QL | 9:ca2e6010d9e2 | 1044 | QP_END_ |
QL | 9:ca2e6010d9e2 | 1045 | |
QL | 9:ca2e6010d9e2 | 1046 | // "qeq_lifo.cpp" ============================================================ |
QL | 9:ca2e6010d9e2 | 1047 | /// \brief QEQueue::postLIFO() implementation. |
QL | 9:ca2e6010d9e2 | 1048 | |
QL | 9:ca2e6010d9e2 | 1049 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 1050 | |
QL | 9:ca2e6010d9e2 | 1051 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 1052 | void QEQueue::postLIFO(QEvt const * const e) { |
QL | 9:ca2e6010d9e2 | 1053 | QF_CRIT_STAT_ |
QL | 9:ca2e6010d9e2 | 1054 | QF_CRIT_ENTRY_(); |
QL | 9:ca2e6010d9e2 | 1055 | |
QL | 9:ca2e6010d9e2 | 1056 | QS_BEGIN_NOCRIT_(QS_QF_EQUEUE_POST_LIFO, QS::eqObj_, this) |
QL | 9:ca2e6010d9e2 | 1057 | QS_TIME_(); // timestamp |
QL | 9:ca2e6010d9e2 | 1058 | QS_SIG_(e->sig); // the signal of this event |
QL | 9:ca2e6010d9e2 | 1059 | QS_OBJ_(this); // this queue object |
QL | 9:ca2e6010d9e2 | 1060 | QS_U8_(QF_EVT_POOL_ID_(e)); // the pool Id of the event |
QL | 9:ca2e6010d9e2 | 1061 | QS_U8_(QF_EVT_REF_CTR_(e)); // the ref count of the event |
QL | 9:ca2e6010d9e2 | 1062 | QS_EQC_(m_nFree); // number of free entries |
QL | 9:ca2e6010d9e2 | 1063 | QS_EQC_(m_nMin); // min number of free entries |
QL | 9:ca2e6010d9e2 | 1064 | QS_END_NOCRIT_() |
QL | 9:ca2e6010d9e2 | 1065 | |
QL | 9:ca2e6010d9e2 | 1066 | if (QF_EVT_POOL_ID_(e) != u8_0) { // is it a dynamic event? |
QL | 9:ca2e6010d9e2 | 1067 | QF_EVT_REF_CTR_INC_(e); // increment the reference counter |
QL | 9:ca2e6010d9e2 | 1068 | } |
QL | 9:ca2e6010d9e2 | 1069 | |
QL | 9:ca2e6010d9e2 | 1070 | if (m_frontEvt != null_evt) { // is the queue not empty? |
QL | 9:ca2e6010d9e2 | 1071 | // the queue must be able to accept the event (cannot overflow) |
QL | 9:ca2e6010d9e2 | 1072 | Q_ASSERT(m_nFree != static_cast<QEQueueCtr>(0)); |
QL | 9:ca2e6010d9e2 | 1073 | |
QL | 9:ca2e6010d9e2 | 1074 | ++m_tail; |
QL | 9:ca2e6010d9e2 | 1075 | if (m_tail == m_end) { // need to wrap the tail? |
QL | 9:ca2e6010d9e2 | 1076 | m_tail = static_cast<QEQueueCtr>(0); // wrap around |
QL | 9:ca2e6010d9e2 | 1077 | } |
QL | 9:ca2e6010d9e2 | 1078 | |
QL | 9:ca2e6010d9e2 | 1079 | QF_PTR_AT_(m_ring, m_tail) = m_frontEvt; // buffer the old front evt |
QL | 9:ca2e6010d9e2 | 1080 | |
QL | 9:ca2e6010d9e2 | 1081 | --m_nFree; // update number of free events |
QL | 9:ca2e6010d9e2 | 1082 | if (m_nMin > m_nFree) { |
QL | 9:ca2e6010d9e2 | 1083 | m_nMin = m_nFree; // update minimum so far |
QL | 9:ca2e6010d9e2 | 1084 | } |
QL | 9:ca2e6010d9e2 | 1085 | } |
QL | 9:ca2e6010d9e2 | 1086 | |
QL | 9:ca2e6010d9e2 | 1087 | m_frontEvt = e; // stick the new event to the front |
QL | 9:ca2e6010d9e2 | 1088 | |
QL | 9:ca2e6010d9e2 | 1089 | QF_CRIT_EXIT_(); |
QL | 9:ca2e6010d9e2 | 1090 | } |
QL | 9:ca2e6010d9e2 | 1091 | |
QL | 9:ca2e6010d9e2 | 1092 | QP_END_ |
QL | 9:ca2e6010d9e2 | 1093 | |
QL | 9:ca2e6010d9e2 | 1094 | // "qf_act.cpp" ============================================================== |
QL | 9:ca2e6010d9e2 | 1095 | /// \brief QF::active_[], QF::getVersion(), and QF::add_()/QF::remove_() |
QL | 9:ca2e6010d9e2 | 1096 | /// implementation. |
QL | 9:ca2e6010d9e2 | 1097 | |
QL | 9:ca2e6010d9e2 | 1098 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 1099 | |
QL | 9:ca2e6010d9e2 | 1100 | // public objects ------------------------------------------------------------ |
QL | 9:ca2e6010d9e2 | 1101 | QActive *QF::active_[QF_MAX_ACTIVE + 1]; // to be used by QF ports only |
QL | 9:ca2e6010d9e2 | 1102 | uint8_t QF_intLockNest_; // interrupt-lock nesting level |
QL | 9:ca2e6010d9e2 | 1103 | |
QL | 9:ca2e6010d9e2 | 1104 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 1105 | char_t const Q_ROM * Q_ROM_VAR QF::getVersion(void) { |
QL | 9:ca2e6010d9e2 | 1106 | uint8_t const u8_zero = static_cast<uint8_t>('0'); |
QL | 9:ca2e6010d9e2 | 1107 | static char_t const Q_ROM Q_ROM_VAR version[] = { |
QL | 9:ca2e6010d9e2 | 1108 | static_cast<char_t>(((QP_VERSION >> 12) & 0xFU) + u8_zero), |
QL | 9:ca2e6010d9e2 | 1109 | static_cast<char_t>('.'), |
QL | 9:ca2e6010d9e2 | 1110 | static_cast<char_t>(((QP_VERSION >> 8) & 0xFU) + u8_zero), |
QL | 9:ca2e6010d9e2 | 1111 | static_cast<char_t>('.'), |
QL | 9:ca2e6010d9e2 | 1112 | static_cast<char_t>(((QP_VERSION >> 4) & 0xFU) + u8_zero), |
QL | 9:ca2e6010d9e2 | 1113 | static_cast<char_t>((QP_VERSION & 0xFU) + u8_zero), |
QL | 9:ca2e6010d9e2 | 1114 | static_cast<char_t>('\0') |
QL | 9:ca2e6010d9e2 | 1115 | }; |
QL | 9:ca2e6010d9e2 | 1116 | return version; |
QL | 9:ca2e6010d9e2 | 1117 | } |
QL | 9:ca2e6010d9e2 | 1118 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 1119 | void QF::add_(QActive * const a) { |
QL | 9:ca2e6010d9e2 | 1120 | uint8_t p = a->m_prio; |
QL | 9:ca2e6010d9e2 | 1121 | |
QL | 9:ca2e6010d9e2 | 1122 | Q_REQUIRE((u8_0 < p) && (p <= static_cast<uint8_t>(QF_MAX_ACTIVE)) |
QL | 9:ca2e6010d9e2 | 1123 | && (active_[p] == static_cast<QActive *>(0))); |
QL | 9:ca2e6010d9e2 | 1124 | |
QL | 9:ca2e6010d9e2 | 1125 | QF_CRIT_STAT_ |
QL | 9:ca2e6010d9e2 | 1126 | QF_CRIT_ENTRY_(); |
QL | 9:ca2e6010d9e2 | 1127 | |
QL | 9:ca2e6010d9e2 | 1128 | active_[p] = a; // registger the active object at this priority |
QL | 9:ca2e6010d9e2 | 1129 | |
QL | 9:ca2e6010d9e2 | 1130 | QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_ADD, QS::aoObj_, a) |
QL | 9:ca2e6010d9e2 | 1131 | QS_TIME_(); // timestamp |
QL | 9:ca2e6010d9e2 | 1132 | QS_OBJ_(a); // the active object |
QL | 9:ca2e6010d9e2 | 1133 | QS_U8_(p); // the priority of the active object |
QL | 9:ca2e6010d9e2 | 1134 | QS_END_NOCRIT_() |
QL | 9:ca2e6010d9e2 | 1135 | |
QL | 9:ca2e6010d9e2 | 1136 | QF_CRIT_EXIT_(); |
QL | 9:ca2e6010d9e2 | 1137 | } |
QL | 9:ca2e6010d9e2 | 1138 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 1139 | void QF::remove_(QActive const * const a) { |
QL | 9:ca2e6010d9e2 | 1140 | uint8_t p = a->m_prio; |
QL | 9:ca2e6010d9e2 | 1141 | |
QL | 9:ca2e6010d9e2 | 1142 | Q_REQUIRE((u8_0 < p) && (p <= static_cast<uint8_t>(QF_MAX_ACTIVE)) |
QL | 9:ca2e6010d9e2 | 1143 | && (active_[p] == a)); |
QL | 9:ca2e6010d9e2 | 1144 | |
QL | 9:ca2e6010d9e2 | 1145 | QF_CRIT_STAT_ |
QL | 9:ca2e6010d9e2 | 1146 | QF_CRIT_ENTRY_(); |
QL | 9:ca2e6010d9e2 | 1147 | |
QL | 9:ca2e6010d9e2 | 1148 | active_[p] = static_cast<QActive *>(0); // free-up the priority level |
QL | 9:ca2e6010d9e2 | 1149 | |
QL | 9:ca2e6010d9e2 | 1150 | QS_BEGIN_NOCRIT_(QS_QF_ACTIVE_REMOVE, QS::aoObj_, a) |
QL | 9:ca2e6010d9e2 | 1151 | QS_TIME_(); // timestamp |
QL | 9:ca2e6010d9e2 | 1152 | QS_OBJ_(a); // the active object |
QL | 9:ca2e6010d9e2 | 1153 | QS_U8_(p); // the priority of the active object |
QL | 9:ca2e6010d9e2 | 1154 | QS_END_NOCRIT_() |
QL | 9:ca2e6010d9e2 | 1155 | |
QL | 9:ca2e6010d9e2 | 1156 | QF_CRIT_EXIT_(); |
QL | 9:ca2e6010d9e2 | 1157 | } |
QL | 9:ca2e6010d9e2 | 1158 | |
QL | 9:ca2e6010d9e2 | 1159 | QP_END_ |
QL | 9:ca2e6010d9e2 | 1160 | |
QL | 9:ca2e6010d9e2 | 1161 | |
QL | 9:ca2e6010d9e2 | 1162 | // "qf_gc.cpp" =============================================================== |
QL | 9:ca2e6010d9e2 | 1163 | /// \brief QF::gc() implementation. |
QL | 9:ca2e6010d9e2 | 1164 | |
QL | 9:ca2e6010d9e2 | 1165 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 1166 | |
QL | 9:ca2e6010d9e2 | 1167 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 1168 | void QF::gc(QEvt const * const e) { |
QL | 9:ca2e6010d9e2 | 1169 | if (QF_EVT_POOL_ID_(e) != u8_0) { // is it a dynamic event? |
QL | 9:ca2e6010d9e2 | 1170 | QF_CRIT_STAT_ |
QL | 9:ca2e6010d9e2 | 1171 | QF_CRIT_ENTRY_(); |
QL | 9:ca2e6010d9e2 | 1172 | |
QL | 9:ca2e6010d9e2 | 1173 | if (QF_EVT_REF_CTR_(e) > u8_1) { // isn't this the last reference? |
QL | 9:ca2e6010d9e2 | 1174 | QF_EVT_REF_CTR_DEC_(e); // decrement the ref counter |
QL | 9:ca2e6010d9e2 | 1175 | |
QL | 9:ca2e6010d9e2 | 1176 | QS_BEGIN_NOCRIT_(QS_QF_GC_ATTEMPT, null_void, null_void) |
QL | 9:ca2e6010d9e2 | 1177 | QS_TIME_(); // timestamp |
QL | 9:ca2e6010d9e2 | 1178 | QS_SIG_(e->sig); // the signal of the event |
QL | 9:ca2e6010d9e2 | 1179 | QS_U8_(QF_EVT_POOL_ID_(e)); // the pool Id of the event |
QL | 9:ca2e6010d9e2 | 1180 | QS_U8_(QF_EVT_REF_CTR_(e)); // the ref count of the event |
QL | 9:ca2e6010d9e2 | 1181 | QS_END_NOCRIT_() |
QL | 9:ca2e6010d9e2 | 1182 | |
QL | 9:ca2e6010d9e2 | 1183 | QF_CRIT_EXIT_(); |
QL | 9:ca2e6010d9e2 | 1184 | } |
QL | 9:ca2e6010d9e2 | 1185 | else { // this is the last reference to this event, recycle it |
QL | 9:ca2e6010d9e2 | 1186 | uint8_t idx = static_cast<uint8_t>(QF_EVT_POOL_ID_(e) - u8_1); |
QL | 9:ca2e6010d9e2 | 1187 | |
QL | 9:ca2e6010d9e2 | 1188 | QS_BEGIN_NOCRIT_(QS_QF_GC, null_void, null_void) |
QL | 9:ca2e6010d9e2 | 1189 | QS_TIME_(); // timestamp |
QL | 9:ca2e6010d9e2 | 1190 | QS_SIG_(e->sig); // the signal of the event |
QL | 9:ca2e6010d9e2 | 1191 | QS_U8_(QF_EVT_POOL_ID_(e)); // the pool Id of the event |
QL | 9:ca2e6010d9e2 | 1192 | QS_U8_(QF_EVT_REF_CTR_(e)); // the ref count of the event |
QL | 9:ca2e6010d9e2 | 1193 | QS_END_NOCRIT_() |
QL | 9:ca2e6010d9e2 | 1194 | |
QL | 9:ca2e6010d9e2 | 1195 | QF_CRIT_EXIT_(); |
QL | 9:ca2e6010d9e2 | 1196 | |
QL | 9:ca2e6010d9e2 | 1197 | Q_ASSERT(idx < QF_maxPool_); |
QL | 9:ca2e6010d9e2 | 1198 | |
QL | 9:ca2e6010d9e2 | 1199 | #ifdef Q_EVT_VIRTUAL |
QL | 9:ca2e6010d9e2 | 1200 | QF_EVT_CONST_CAST_(e)->~QEvt(); // xtor, cast 'const' away, |
QL | 9:ca2e6010d9e2 | 1201 | // which is legitimate, because it's a pool event |
QL | 9:ca2e6010d9e2 | 1202 | #endif |
QL | 9:ca2e6010d9e2 | 1203 | // cast 'const' away, which is OK, because it's a pool event |
QL | 9:ca2e6010d9e2 | 1204 | QF_EPOOL_PUT_(QF_pool_[idx], QF_EVT_CONST_CAST_(e)); |
QL | 9:ca2e6010d9e2 | 1205 | } |
QL | 9:ca2e6010d9e2 | 1206 | } |
QL | 9:ca2e6010d9e2 | 1207 | } |
QL | 9:ca2e6010d9e2 | 1208 | |
QL | 9:ca2e6010d9e2 | 1209 | QP_END_ |
QL | 9:ca2e6010d9e2 | 1210 | |
QL | 9:ca2e6010d9e2 | 1211 | // "qf_log2.cpp" ============================================================= |
QL | 9:ca2e6010d9e2 | 1212 | /// \brief QF_log2Lkup[] implementation. |
QL | 9:ca2e6010d9e2 | 1213 | |
QL | 9:ca2e6010d9e2 | 1214 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 1215 | |
QL | 9:ca2e6010d9e2 | 1216 | // Global objects ------------------------------------------------------------ |
QL | 9:ca2e6010d9e2 | 1217 | uint8_t const Q_ROM Q_ROM_VAR QF_log2Lkup[256] = { |
QL | 9:ca2e6010d9e2 | 1218 | static_cast<uint8_t>(0), |
QL | 9:ca2e6010d9e2 | 1219 | static_cast<uint8_t>(1), |
QL | 9:ca2e6010d9e2 | 1220 | static_cast<uint8_t>(2), static_cast<uint8_t>(2), |
QL | 9:ca2e6010d9e2 | 1221 | static_cast<uint8_t>(3), static_cast<uint8_t>(3), static_cast<uint8_t>(3), |
QL | 9:ca2e6010d9e2 | 1222 | static_cast<uint8_t>(3), |
QL | 9:ca2e6010d9e2 | 1223 | static_cast<uint8_t>(4), static_cast<uint8_t>(4), static_cast<uint8_t>(4), |
QL | 9:ca2e6010d9e2 | 1224 | static_cast<uint8_t>(4), static_cast<uint8_t>(4), static_cast<uint8_t>(4), |
QL | 9:ca2e6010d9e2 | 1225 | static_cast<uint8_t>(4), static_cast<uint8_t>(4), |
QL | 9:ca2e6010d9e2 | 1226 | static_cast<uint8_t>(5), static_cast<uint8_t>(5), static_cast<uint8_t>(5), |
QL | 9:ca2e6010d9e2 | 1227 | static_cast<uint8_t>(5), static_cast<uint8_t>(5), static_cast<uint8_t>(5), |
QL | 9:ca2e6010d9e2 | 1228 | static_cast<uint8_t>(5), static_cast<uint8_t>(5), static_cast<uint8_t>(5), |
QL | 9:ca2e6010d9e2 | 1229 | static_cast<uint8_t>(5), static_cast<uint8_t>(5), static_cast<uint8_t>(5), |
QL | 9:ca2e6010d9e2 | 1230 | static_cast<uint8_t>(5), static_cast<uint8_t>(5), static_cast<uint8_t>(5), |
QL | 9:ca2e6010d9e2 | 1231 | static_cast<uint8_t>(5), |
QL | 9:ca2e6010d9e2 | 1232 | static_cast<uint8_t>(6), static_cast<uint8_t>(6), static_cast<uint8_t>(6), |
QL | 9:ca2e6010d9e2 | 1233 | static_cast<uint8_t>(6), static_cast<uint8_t>(6), static_cast<uint8_t>(6), |
QL | 9:ca2e6010d9e2 | 1234 | static_cast<uint8_t>(6), static_cast<uint8_t>(6), static_cast<uint8_t>(6), |
QL | 9:ca2e6010d9e2 | 1235 | static_cast<uint8_t>(6), static_cast<uint8_t>(6), static_cast<uint8_t>(6), |
QL | 9:ca2e6010d9e2 | 1236 | static_cast<uint8_t>(6), static_cast<uint8_t>(6), static_cast<uint8_t>(6), |
QL | 9:ca2e6010d9e2 | 1237 | static_cast<uint8_t>(6), static_cast<uint8_t>(6), static_cast<uint8_t>(6), |
QL | 9:ca2e6010d9e2 | 1238 | static_cast<uint8_t>(6), static_cast<uint8_t>(6), static_cast<uint8_t>(6), |
QL | 9:ca2e6010d9e2 | 1239 | static_cast<uint8_t>(6), static_cast<uint8_t>(6), static_cast<uint8_t>(6), |
QL | 9:ca2e6010d9e2 | 1240 | static_cast<uint8_t>(6), static_cast<uint8_t>(6), static_cast<uint8_t>(6), |
QL | 9:ca2e6010d9e2 | 1241 | static_cast<uint8_t>(6), static_cast<uint8_t>(6), static_cast<uint8_t>(6), |
QL | 9:ca2e6010d9e2 | 1242 | static_cast<uint8_t>(6), static_cast<uint8_t>(6), |
QL | 9:ca2e6010d9e2 | 1243 | static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), |
QL | 9:ca2e6010d9e2 | 1244 | static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), |
QL | 9:ca2e6010d9e2 | 1245 | static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), |
QL | 9:ca2e6010d9e2 | 1246 | static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), |
QL | 9:ca2e6010d9e2 | 1247 | static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), |
QL | 9:ca2e6010d9e2 | 1248 | static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), |
QL | 9:ca2e6010d9e2 | 1249 | static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), |
QL | 9:ca2e6010d9e2 | 1250 | static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), |
QL | 9:ca2e6010d9e2 | 1251 | static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), |
QL | 9:ca2e6010d9e2 | 1252 | static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), |
QL | 9:ca2e6010d9e2 | 1253 | static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), |
QL | 9:ca2e6010d9e2 | 1254 | static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), |
QL | 9:ca2e6010d9e2 | 1255 | static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), |
QL | 9:ca2e6010d9e2 | 1256 | static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), |
QL | 9:ca2e6010d9e2 | 1257 | static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), |
QL | 9:ca2e6010d9e2 | 1258 | static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), |
QL | 9:ca2e6010d9e2 | 1259 | static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), |
QL | 9:ca2e6010d9e2 | 1260 | static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), |
QL | 9:ca2e6010d9e2 | 1261 | static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), |
QL | 9:ca2e6010d9e2 | 1262 | static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), |
QL | 9:ca2e6010d9e2 | 1263 | static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), |
QL | 9:ca2e6010d9e2 | 1264 | static_cast<uint8_t>(7), |
QL | 9:ca2e6010d9e2 | 1265 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1266 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1267 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1268 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1269 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1270 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1271 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1272 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1273 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1274 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1275 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1276 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1277 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1278 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1279 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1280 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1281 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1282 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1283 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1284 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1285 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1286 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1287 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1288 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1289 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1290 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1291 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1292 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1293 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1294 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1295 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1296 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1297 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1298 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1299 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1300 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1301 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1302 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1303 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1304 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1305 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1306 | static_cast<uint8_t>(8), static_cast<uint8_t>(8), static_cast<uint8_t>(8), |
QL | 9:ca2e6010d9e2 | 1307 | static_cast<uint8_t>(8), static_cast<uint8_t>(8) |
QL | 9:ca2e6010d9e2 | 1308 | }; |
QL | 9:ca2e6010d9e2 | 1309 | |
QL | 9:ca2e6010d9e2 | 1310 | QP_END_ |
QL | 9:ca2e6010d9e2 | 1311 | |
QL | 9:ca2e6010d9e2 | 1312 | // "qf_new.cpp" ============================================================== |
QL | 9:ca2e6010d9e2 | 1313 | /// \brief QF::new_() implementation. |
QL | 9:ca2e6010d9e2 | 1314 | |
QL | 9:ca2e6010d9e2 | 1315 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 1316 | |
QL | 9:ca2e6010d9e2 | 1317 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 1318 | QEvt *QF::new_(QEvtSize const evtSize, enum_t const sig) { |
QL | 9:ca2e6010d9e2 | 1319 | // find the pool id that fits the requested event size ... |
QL | 9:ca2e6010d9e2 | 1320 | uint8_t idx = u8_0; |
QL | 9:ca2e6010d9e2 | 1321 | while (evtSize |
QL | 9:ca2e6010d9e2 | 1322 | > static_cast<QEvtSize>(QF_EPOOL_EVENT_SIZE_(QF_pool_[idx]))) |
QL | 9:ca2e6010d9e2 | 1323 | { |
QL | 9:ca2e6010d9e2 | 1324 | ++idx; |
QL | 9:ca2e6010d9e2 | 1325 | Q_ASSERT(idx < QF_maxPool_); // cannot run out of registered pools |
QL | 9:ca2e6010d9e2 | 1326 | } |
QL | 9:ca2e6010d9e2 | 1327 | |
QL | 9:ca2e6010d9e2 | 1328 | QS_CRIT_STAT_ |
QL | 9:ca2e6010d9e2 | 1329 | QS_BEGIN_(QS_QF_NEW, null_void, null_void) |
QL | 9:ca2e6010d9e2 | 1330 | QS_TIME_(); // timestamp |
QL | 9:ca2e6010d9e2 | 1331 | QS_EVS_(evtSize); // the size of the event |
QL | 9:ca2e6010d9e2 | 1332 | QS_SIG_(static_cast<QSignal>(sig)); // the signal of the event |
QL | 9:ca2e6010d9e2 | 1333 | QS_END_() |
QL | 9:ca2e6010d9e2 | 1334 | |
QL | 9:ca2e6010d9e2 | 1335 | QEvt *e; |
QL | 9:ca2e6010d9e2 | 1336 | QF_EPOOL_GET_(QF_pool_[idx], e); |
QL | 9:ca2e6010d9e2 | 1337 | Q_ASSERT(e != static_cast<QEvt *>(0));// pool must not run out of events |
QL | 9:ca2e6010d9e2 | 1338 | |
QL | 9:ca2e6010d9e2 | 1339 | e->sig = static_cast<QSignal>(sig); // set signal for this event |
QL | 9:ca2e6010d9e2 | 1340 | e->poolId_ = static_cast<uint8_t>(idx + u8_1); // store pool ID in the evt |
QL | 9:ca2e6010d9e2 | 1341 | e->refCtr_ = u8_0; // set the reference counter to 0 |
QL | 9:ca2e6010d9e2 | 1342 | |
QL | 9:ca2e6010d9e2 | 1343 | return e; |
QL | 9:ca2e6010d9e2 | 1344 | } |
QL | 9:ca2e6010d9e2 | 1345 | |
QL | 9:ca2e6010d9e2 | 1346 | QP_END_ |
QL | 9:ca2e6010d9e2 | 1347 | |
QL | 9:ca2e6010d9e2 | 1348 | // "qf_pool.cpp" ============================================================= |
QL | 9:ca2e6010d9e2 | 1349 | /// \brief QF_pool_[] and QF_maxPool_ definition, QF::poolInit() |
QL | 9:ca2e6010d9e2 | 1350 | /// implementation. |
QL | 9:ca2e6010d9e2 | 1351 | |
QL | 9:ca2e6010d9e2 | 1352 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 1353 | |
QL | 9:ca2e6010d9e2 | 1354 | // Package-scope objects ----------------------------------------------------- |
QL | 9:ca2e6010d9e2 | 1355 | QF_EPOOL_TYPE_ QF_pool_[QF_MAX_EPOOL]; // allocate the event pools |
QL | 9:ca2e6010d9e2 | 1356 | uint8_t QF_maxPool_; // number of initialized event pools |
QL | 9:ca2e6010d9e2 | 1357 | |
QL | 9:ca2e6010d9e2 | 1358 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 1359 | void QF::poolInit(void * const poolSto, |
QL | 9:ca2e6010d9e2 | 1360 | uint32_t const poolSize, uint32_t const evtSize) |
QL | 9:ca2e6010d9e2 | 1361 | { |
QL | 9:ca2e6010d9e2 | 1362 | // cannot exceed the number of available memory pools |
QL | 9:ca2e6010d9e2 | 1363 | Q_REQUIRE(QF_maxPool_ < static_cast<uint8_t>(Q_DIM(QF_pool_))); |
QL | 9:ca2e6010d9e2 | 1364 | // please initialize event pools in ascending order of evtSize: |
QL | 9:ca2e6010d9e2 | 1365 | Q_REQUIRE((QF_maxPool_ == u8_0) |
QL | 9:ca2e6010d9e2 | 1366 | || (QF_EPOOL_EVENT_SIZE_(QF_pool_[QF_maxPool_ - u8_1]) |
QL | 9:ca2e6010d9e2 | 1367 | < evtSize)); |
QL | 9:ca2e6010d9e2 | 1368 | QF_EPOOL_INIT_(QF_pool_[QF_maxPool_], poolSto, poolSize, evtSize); |
QL | 9:ca2e6010d9e2 | 1369 | ++QF_maxPool_; // one more pool |
QL | 9:ca2e6010d9e2 | 1370 | } |
QL | 9:ca2e6010d9e2 | 1371 | |
QL | 9:ca2e6010d9e2 | 1372 | QP_END_ |
QL | 9:ca2e6010d9e2 | 1373 | |
QL | 9:ca2e6010d9e2 | 1374 | |
QL | 9:ca2e6010d9e2 | 1375 | // "qf_psini.cpp" ============================================================ |
QL | 9:ca2e6010d9e2 | 1376 | /// \brief QF_subscrList_ and QF_maxSignal_ definition, QF::psInit() |
QL | 9:ca2e6010d9e2 | 1377 | /// implementation. |
QL | 9:ca2e6010d9e2 | 1378 | |
QL | 9:ca2e6010d9e2 | 1379 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 1380 | |
QL | 9:ca2e6010d9e2 | 1381 | // Package-scope objects ----------------------------------------------------- |
QL | 9:ca2e6010d9e2 | 1382 | QSubscrList *QF_subscrList_; |
QL | 9:ca2e6010d9e2 | 1383 | enum_t QF_maxSignal_; |
QL | 9:ca2e6010d9e2 | 1384 | |
QL | 9:ca2e6010d9e2 | 1385 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 1386 | void QF::psInit(QSubscrList * const subscrSto, uint32_t const maxSignal) { |
QL | 9:ca2e6010d9e2 | 1387 | QF_subscrList_ = subscrSto; |
QL | 9:ca2e6010d9e2 | 1388 | QF_maxSignal_ = static_cast<enum_t>(maxSignal); |
QL | 9:ca2e6010d9e2 | 1389 | } |
QL | 9:ca2e6010d9e2 | 1390 | |
QL | 9:ca2e6010d9e2 | 1391 | QP_END_ |
QL | 9:ca2e6010d9e2 | 1392 | |
QL | 9:ca2e6010d9e2 | 1393 | // "qf_pspub.cpp" ============================================================ |
QL | 9:ca2e6010d9e2 | 1394 | /// \brief QF::publish() implementation. |
QL | 9:ca2e6010d9e2 | 1395 | |
QL | 9:ca2e6010d9e2 | 1396 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 1397 | |
QL | 9:ca2e6010d9e2 | 1398 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 1399 | #ifndef Q_SPY |
QL | 9:ca2e6010d9e2 | 1400 | void QF::publish(QEvt const * const e) { |
QL | 9:ca2e6010d9e2 | 1401 | #else |
QL | 9:ca2e6010d9e2 | 1402 | void QF::publish(QEvt const * const e, void const * const sender) { |
QL | 9:ca2e6010d9e2 | 1403 | #endif |
QL | 9:ca2e6010d9e2 | 1404 | // make sure that the published signal is within the configured range |
QL | 9:ca2e6010d9e2 | 1405 | Q_REQUIRE(static_cast<enum_t>(e->sig) < QF_maxSignal_); |
QL | 9:ca2e6010d9e2 | 1406 | |
QL | 9:ca2e6010d9e2 | 1407 | QF_CRIT_STAT_ |
QL | 9:ca2e6010d9e2 | 1408 | QF_CRIT_ENTRY_(); |
QL | 9:ca2e6010d9e2 | 1409 | |
QL | 9:ca2e6010d9e2 | 1410 | QS_BEGIN_NOCRIT_(QS_QF_PUBLISH, null_void, null_void) |
QL | 9:ca2e6010d9e2 | 1411 | QS_TIME_(); // the timestamp |
QL | 9:ca2e6010d9e2 | 1412 | QS_OBJ_(sender); // the sender object |
QL | 9:ca2e6010d9e2 | 1413 | QS_SIG_(e->sig); // the signal of the event |
QL | 9:ca2e6010d9e2 | 1414 | QS_U8_(QF_EVT_POOL_ID_(e)); // the pool Id of the event |
QL | 9:ca2e6010d9e2 | 1415 | QS_U8_(QF_EVT_REF_CTR_(e)); // the ref count of the event |
QL | 9:ca2e6010d9e2 | 1416 | QS_END_NOCRIT_() |
QL | 9:ca2e6010d9e2 | 1417 | |
QL | 9:ca2e6010d9e2 | 1418 | if (QF_EVT_POOL_ID_(e) != u8_0) { // is it a dynamic event? |
QL | 9:ca2e6010d9e2 | 1419 | QF_EVT_REF_CTR_INC_(e); // increment the reference counter, NOTE01 |
QL | 9:ca2e6010d9e2 | 1420 | } |
QL | 9:ca2e6010d9e2 | 1421 | QF_CRIT_EXIT_(); |
QL | 9:ca2e6010d9e2 | 1422 | |
QL | 9:ca2e6010d9e2 | 1423 | #if (QF_MAX_ACTIVE <= 8) |
QL | 9:ca2e6010d9e2 | 1424 | uint8_t tmp = QF_PTR_AT_(QF_subscrList_, e->sig).m_bits[0]; |
QL | 9:ca2e6010d9e2 | 1425 | while (tmp != u8_0) { |
QL | 9:ca2e6010d9e2 | 1426 | uint8_t p = Q_ROM_BYTE(QF_log2Lkup[tmp]); |
QL | 9:ca2e6010d9e2 | 1427 | tmp &= Q_ROM_BYTE(QF_invPwr2Lkup[p]); // clear the subscriber bit |
QL | 9:ca2e6010d9e2 | 1428 | Q_ASSERT(active_[p] != static_cast<QActive *>(0));//must be registered |
QL | 9:ca2e6010d9e2 | 1429 | |
QL | 9:ca2e6010d9e2 | 1430 | // POST() asserts internally if the queue overflows |
QL | 9:ca2e6010d9e2 | 1431 | active_[p]->POST(e, sender); |
QL | 9:ca2e6010d9e2 | 1432 | } |
QL | 9:ca2e6010d9e2 | 1433 | #else |
QL | 9:ca2e6010d9e2 | 1434 | // number of bytes in the list |
QL | 9:ca2e6010d9e2 | 1435 | uint8_t i = QF_SUBSCR_LIST_SIZE; |
QL | 9:ca2e6010d9e2 | 1436 | do { // go through all bytes in the subsciption list |
QL | 9:ca2e6010d9e2 | 1437 | --i; |
QL | 9:ca2e6010d9e2 | 1438 | uint8_t tmp = QF_PTR_AT_(QF_subscrList_, e->sig).m_bits[i]; |
QL | 9:ca2e6010d9e2 | 1439 | while (tmp != u8_0) { |
QL | 9:ca2e6010d9e2 | 1440 | uint8_t p = Q_ROM_BYTE(QF_log2Lkup[tmp]); |
QL | 9:ca2e6010d9e2 | 1441 | tmp &= Q_ROM_BYTE(QF_invPwr2Lkup[p]); // clear the subscriber bit |
QL | 9:ca2e6010d9e2 | 1442 | // adjust the priority |
QL | 9:ca2e6010d9e2 | 1443 | p = static_cast<uint8_t>(p + static_cast<uint8_t>(i << 3)); |
QL | 9:ca2e6010d9e2 | 1444 | Q_ASSERT(active_[p] != static_cast<QActive *>(0)); // registered |
QL | 9:ca2e6010d9e2 | 1445 | |
QL | 9:ca2e6010d9e2 | 1446 | // POST() asserts internally if the queue overflows |
QL | 9:ca2e6010d9e2 | 1447 | active_[p]->POST(e, sender); |
QL | 9:ca2e6010d9e2 | 1448 | } |
QL | 9:ca2e6010d9e2 | 1449 | } while (i != u8_0); |
QL | 9:ca2e6010d9e2 | 1450 | #endif |
QL | 9:ca2e6010d9e2 | 1451 | |
QL | 9:ca2e6010d9e2 | 1452 | gc(e); // run the garbage collector, see NOTE01 |
QL | 9:ca2e6010d9e2 | 1453 | } |
QL | 9:ca2e6010d9e2 | 1454 | |
QL | 9:ca2e6010d9e2 | 1455 | QP_END_ |
QL | 9:ca2e6010d9e2 | 1456 | |
QL | 9:ca2e6010d9e2 | 1457 | |
QL | 9:ca2e6010d9e2 | 1458 | // "qf_pwr2.cpp" ============================================================= |
QL | 9:ca2e6010d9e2 | 1459 | /// \brief QF_pwr2Lkup[], QF_invPwr2Lkup[], and QF_div8Lkup[] definitions. |
QL | 9:ca2e6010d9e2 | 1460 | |
QL | 9:ca2e6010d9e2 | 1461 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 1462 | |
QL | 9:ca2e6010d9e2 | 1463 | // Global objects ------------------------------------------------------------ |
QL | 9:ca2e6010d9e2 | 1464 | uint8_t const Q_ROM Q_ROM_VAR QF_pwr2Lkup[65] = { |
QL | 9:ca2e6010d9e2 | 1465 | static_cast<uint8_t>(0x00), // unused location |
QL | 9:ca2e6010d9e2 | 1466 | static_cast<uint8_t>(0x01), static_cast<uint8_t>(0x02), |
QL | 9:ca2e6010d9e2 | 1467 | static_cast<uint8_t>(0x04), static_cast<uint8_t>(0x08), |
QL | 9:ca2e6010d9e2 | 1468 | static_cast<uint8_t>(0x10), static_cast<uint8_t>(0x20), |
QL | 9:ca2e6010d9e2 | 1469 | static_cast<uint8_t>(0x40), static_cast<uint8_t>(0x80), |
QL | 9:ca2e6010d9e2 | 1470 | static_cast<uint8_t>(0x01), static_cast<uint8_t>(0x02), |
QL | 9:ca2e6010d9e2 | 1471 | static_cast<uint8_t>(0x04), static_cast<uint8_t>(0x08), |
QL | 9:ca2e6010d9e2 | 1472 | static_cast<uint8_t>(0x10), static_cast<uint8_t>(0x20), |
QL | 9:ca2e6010d9e2 | 1473 | static_cast<uint8_t>(0x40), static_cast<uint8_t>(0x80), |
QL | 9:ca2e6010d9e2 | 1474 | static_cast<uint8_t>(0x01), static_cast<uint8_t>(0x02), |
QL | 9:ca2e6010d9e2 | 1475 | static_cast<uint8_t>(0x04), static_cast<uint8_t>(0x08), |
QL | 9:ca2e6010d9e2 | 1476 | static_cast<uint8_t>(0x10), static_cast<uint8_t>(0x20), |
QL | 9:ca2e6010d9e2 | 1477 | static_cast<uint8_t>(0x40), static_cast<uint8_t>(0x80), |
QL | 9:ca2e6010d9e2 | 1478 | static_cast<uint8_t>(0x01), static_cast<uint8_t>(0x02), |
QL | 9:ca2e6010d9e2 | 1479 | static_cast<uint8_t>(0x04), static_cast<uint8_t>(0x08), |
QL | 9:ca2e6010d9e2 | 1480 | static_cast<uint8_t>(0x10), static_cast<uint8_t>(0x20), |
QL | 9:ca2e6010d9e2 | 1481 | static_cast<uint8_t>(0x40), static_cast<uint8_t>(0x80), |
QL | 9:ca2e6010d9e2 | 1482 | static_cast<uint8_t>(0x01), static_cast<uint8_t>(0x02), |
QL | 9:ca2e6010d9e2 | 1483 | static_cast<uint8_t>(0x04), static_cast<uint8_t>(0x08), |
QL | 9:ca2e6010d9e2 | 1484 | static_cast<uint8_t>(0x10), static_cast<uint8_t>(0x20), |
QL | 9:ca2e6010d9e2 | 1485 | static_cast<uint8_t>(0x40), static_cast<uint8_t>(0x80), |
QL | 9:ca2e6010d9e2 | 1486 | static_cast<uint8_t>(0x01), static_cast<uint8_t>(0x02), |
QL | 9:ca2e6010d9e2 | 1487 | static_cast<uint8_t>(0x04), static_cast<uint8_t>(0x08), |
QL | 9:ca2e6010d9e2 | 1488 | static_cast<uint8_t>(0x10), static_cast<uint8_t>(0x20), |
QL | 9:ca2e6010d9e2 | 1489 | static_cast<uint8_t>(0x40), static_cast<uint8_t>(0x80), |
QL | 9:ca2e6010d9e2 | 1490 | static_cast<uint8_t>(0x01), static_cast<uint8_t>(0x02), |
QL | 9:ca2e6010d9e2 | 1491 | static_cast<uint8_t>(0x04), static_cast<uint8_t>(0x08), |
QL | 9:ca2e6010d9e2 | 1492 | static_cast<uint8_t>(0x10), static_cast<uint8_t>(0x20), |
QL | 9:ca2e6010d9e2 | 1493 | static_cast<uint8_t>(0x40), static_cast<uint8_t>(0x80), |
QL | 9:ca2e6010d9e2 | 1494 | static_cast<uint8_t>(0x01), static_cast<uint8_t>(0x02), |
QL | 9:ca2e6010d9e2 | 1495 | static_cast<uint8_t>(0x04), static_cast<uint8_t>(0x08), |
QL | 9:ca2e6010d9e2 | 1496 | static_cast<uint8_t>(0x10), static_cast<uint8_t>(0x20), |
QL | 9:ca2e6010d9e2 | 1497 | static_cast<uint8_t>(0x40), static_cast<uint8_t>(0x80) |
QL | 9:ca2e6010d9e2 | 1498 | }; |
QL | 9:ca2e6010d9e2 | 1499 | |
QL | 9:ca2e6010d9e2 | 1500 | uint8_t const Q_ROM Q_ROM_VAR QF_invPwr2Lkup[65] = { |
QL | 9:ca2e6010d9e2 | 1501 | static_cast<uint8_t>(0xFF), // unused location |
QL | 9:ca2e6010d9e2 | 1502 | static_cast<uint8_t>(0xFE), static_cast<uint8_t>(0xFD), |
QL | 9:ca2e6010d9e2 | 1503 | static_cast<uint8_t>(0xFB), static_cast<uint8_t>(0xF7), |
QL | 9:ca2e6010d9e2 | 1504 | static_cast<uint8_t>(0xEF), static_cast<uint8_t>(0xDF), |
QL | 9:ca2e6010d9e2 | 1505 | static_cast<uint8_t>(0xBF), static_cast<uint8_t>(0x7F), |
QL | 9:ca2e6010d9e2 | 1506 | static_cast<uint8_t>(0xFE), static_cast<uint8_t>(0xFD), |
QL | 9:ca2e6010d9e2 | 1507 | static_cast<uint8_t>(0xFB), static_cast<uint8_t>(0xF7), |
QL | 9:ca2e6010d9e2 | 1508 | static_cast<uint8_t>(0xEF), static_cast<uint8_t>(0xDF), |
QL | 9:ca2e6010d9e2 | 1509 | static_cast<uint8_t>(0xBF), static_cast<uint8_t>(0x7F), |
QL | 9:ca2e6010d9e2 | 1510 | static_cast<uint8_t>(0xFE), static_cast<uint8_t>(0xFD), |
QL | 9:ca2e6010d9e2 | 1511 | static_cast<uint8_t>(0xFB), static_cast<uint8_t>(0xF7), |
QL | 9:ca2e6010d9e2 | 1512 | static_cast<uint8_t>(0xEF), static_cast<uint8_t>(0xDF), |
QL | 9:ca2e6010d9e2 | 1513 | static_cast<uint8_t>(0xBF), static_cast<uint8_t>(0x7F), |
QL | 9:ca2e6010d9e2 | 1514 | static_cast<uint8_t>(0xFE), static_cast<uint8_t>(0xFD), |
QL | 9:ca2e6010d9e2 | 1515 | static_cast<uint8_t>(0xFB), static_cast<uint8_t>(0xF7), |
QL | 9:ca2e6010d9e2 | 1516 | static_cast<uint8_t>(0xEF), static_cast<uint8_t>(0xDF), |
QL | 9:ca2e6010d9e2 | 1517 | static_cast<uint8_t>(0xBF), static_cast<uint8_t>(0x7F), |
QL | 9:ca2e6010d9e2 | 1518 | static_cast<uint8_t>(0xFE), static_cast<uint8_t>(0xFD), |
QL | 9:ca2e6010d9e2 | 1519 | static_cast<uint8_t>(0xFB), static_cast<uint8_t>(0xF7), |
QL | 9:ca2e6010d9e2 | 1520 | static_cast<uint8_t>(0xEF), static_cast<uint8_t>(0xDF), |
QL | 9:ca2e6010d9e2 | 1521 | static_cast<uint8_t>(0xBF), static_cast<uint8_t>(0x7F), |
QL | 9:ca2e6010d9e2 | 1522 | static_cast<uint8_t>(0xFE), static_cast<uint8_t>(0xFD), |
QL | 9:ca2e6010d9e2 | 1523 | static_cast<uint8_t>(0xFB), static_cast<uint8_t>(0xF7), |
QL | 9:ca2e6010d9e2 | 1524 | static_cast<uint8_t>(0xEF), static_cast<uint8_t>(0xDF), |
QL | 9:ca2e6010d9e2 | 1525 | static_cast<uint8_t>(0xBF), static_cast<uint8_t>(0x7F), |
QL | 9:ca2e6010d9e2 | 1526 | static_cast<uint8_t>(0xFE), static_cast<uint8_t>(0xFD), |
QL | 9:ca2e6010d9e2 | 1527 | static_cast<uint8_t>(0xFB), static_cast<uint8_t>(0xF7), |
QL | 9:ca2e6010d9e2 | 1528 | static_cast<uint8_t>(0xEF), static_cast<uint8_t>(0xDF), |
QL | 9:ca2e6010d9e2 | 1529 | static_cast<uint8_t>(0xBF), static_cast<uint8_t>(0x7F), |
QL | 9:ca2e6010d9e2 | 1530 | static_cast<uint8_t>(0xFE), static_cast<uint8_t>(0xFD), |
QL | 9:ca2e6010d9e2 | 1531 | static_cast<uint8_t>(0xFB), static_cast<uint8_t>(0xF7), |
QL | 9:ca2e6010d9e2 | 1532 | static_cast<uint8_t>(0xEF), static_cast<uint8_t>(0xDF), |
QL | 9:ca2e6010d9e2 | 1533 | static_cast<uint8_t>(0xBF), static_cast<uint8_t>(0x7F) |
QL | 9:ca2e6010d9e2 | 1534 | }; |
QL | 9:ca2e6010d9e2 | 1535 | |
QL | 9:ca2e6010d9e2 | 1536 | uint8_t const Q_ROM Q_ROM_VAR QF_div8Lkup[65] = { |
QL | 9:ca2e6010d9e2 | 1537 | static_cast<uint8_t>(0), // unused location |
QL | 9:ca2e6010d9e2 | 1538 | static_cast<uint8_t>(0), static_cast<uint8_t>(0), static_cast<uint8_t>(0), |
QL | 9:ca2e6010d9e2 | 1539 | static_cast<uint8_t>(0), static_cast<uint8_t>(0), static_cast<uint8_t>(0), |
QL | 9:ca2e6010d9e2 | 1540 | static_cast<uint8_t>(0), static_cast<uint8_t>(0), |
QL | 9:ca2e6010d9e2 | 1541 | static_cast<uint8_t>(1), static_cast<uint8_t>(1), static_cast<uint8_t>(1), |
QL | 9:ca2e6010d9e2 | 1542 | static_cast<uint8_t>(1), static_cast<uint8_t>(1), static_cast<uint8_t>(1), |
QL | 9:ca2e6010d9e2 | 1543 | static_cast<uint8_t>(1), static_cast<uint8_t>(1), |
QL | 9:ca2e6010d9e2 | 1544 | static_cast<uint8_t>(2), static_cast<uint8_t>(2), static_cast<uint8_t>(2), |
QL | 9:ca2e6010d9e2 | 1545 | static_cast<uint8_t>(2), static_cast<uint8_t>(2), static_cast<uint8_t>(2), |
QL | 9:ca2e6010d9e2 | 1546 | static_cast<uint8_t>(2), static_cast<uint8_t>(2), |
QL | 9:ca2e6010d9e2 | 1547 | static_cast<uint8_t>(3), static_cast<uint8_t>(3), static_cast<uint8_t>(3), |
QL | 9:ca2e6010d9e2 | 1548 | static_cast<uint8_t>(3), static_cast<uint8_t>(3), static_cast<uint8_t>(3), |
QL | 9:ca2e6010d9e2 | 1549 | static_cast<uint8_t>(3), static_cast<uint8_t>(3), |
QL | 9:ca2e6010d9e2 | 1550 | static_cast<uint8_t>(4), static_cast<uint8_t>(4), static_cast<uint8_t>(4), |
QL | 9:ca2e6010d9e2 | 1551 | static_cast<uint8_t>(4), static_cast<uint8_t>(4), static_cast<uint8_t>(4), |
QL | 9:ca2e6010d9e2 | 1552 | static_cast<uint8_t>(4), static_cast<uint8_t>(4), |
QL | 9:ca2e6010d9e2 | 1553 | static_cast<uint8_t>(5), static_cast<uint8_t>(5), static_cast<uint8_t>(5), |
QL | 9:ca2e6010d9e2 | 1554 | static_cast<uint8_t>(5), static_cast<uint8_t>(5), static_cast<uint8_t>(5), |
QL | 9:ca2e6010d9e2 | 1555 | static_cast<uint8_t>(5), static_cast<uint8_t>(5), |
QL | 9:ca2e6010d9e2 | 1556 | static_cast<uint8_t>(6), static_cast<uint8_t>(6), static_cast<uint8_t>(6), |
QL | 9:ca2e6010d9e2 | 1557 | static_cast<uint8_t>(6), static_cast<uint8_t>(6), static_cast<uint8_t>(6), |
QL | 9:ca2e6010d9e2 | 1558 | static_cast<uint8_t>(6), static_cast<uint8_t>(6), |
QL | 9:ca2e6010d9e2 | 1559 | static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), |
QL | 9:ca2e6010d9e2 | 1560 | static_cast<uint8_t>(7), static_cast<uint8_t>(7), static_cast<uint8_t>(7), |
QL | 9:ca2e6010d9e2 | 1561 | static_cast<uint8_t>(7), static_cast<uint8_t>(7) |
QL | 9:ca2e6010d9e2 | 1562 | }; |
QL | 9:ca2e6010d9e2 | 1563 | |
QL | 9:ca2e6010d9e2 | 1564 | QP_END_ |
QL | 9:ca2e6010d9e2 | 1565 | |
QL | 9:ca2e6010d9e2 | 1566 | // "qf_tick.cpp" ============================================================= |
QL | 9:ca2e6010d9e2 | 1567 | /// \brief QF::tick() implementation. |
QL | 9:ca2e6010d9e2 | 1568 | |
QL | 9:ca2e6010d9e2 | 1569 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 1570 | |
QL | 9:ca2e6010d9e2 | 1571 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 1572 | #ifndef Q_SPY |
QL | 9:ca2e6010d9e2 | 1573 | void QF::tick(void) { // see NOTE01 |
QL | 9:ca2e6010d9e2 | 1574 | #else |
QL | 9:ca2e6010d9e2 | 1575 | void QF::tick(void const * const sender) { |
QL | 9:ca2e6010d9e2 | 1576 | #endif |
QL | 9:ca2e6010d9e2 | 1577 | |
QL | 9:ca2e6010d9e2 | 1578 | QF_CRIT_STAT_ |
QL | 9:ca2e6010d9e2 | 1579 | QF_CRIT_ENTRY_(); |
QL | 9:ca2e6010d9e2 | 1580 | |
QL | 9:ca2e6010d9e2 | 1581 | QS_BEGIN_NOCRIT_(QS_QF_TICK, null_void, null_void) |
QL | 9:ca2e6010d9e2 | 1582 | QS_TEC_(static_cast<QTimeEvtCtr>(++QS::tickCtr_)); // the tick counter |
QL | 9:ca2e6010d9e2 | 1583 | QS_END_NOCRIT_() |
QL | 9:ca2e6010d9e2 | 1584 | |
QL | 9:ca2e6010d9e2 | 1585 | QTimeEvt *prev = null_tevt; |
QL | 9:ca2e6010d9e2 | 1586 | for (QTimeEvt *t = QF_timeEvtListHead_; t != null_tevt; t = t->m_next) { |
QL | 9:ca2e6010d9e2 | 1587 | if (t->m_ctr == tc_0) { // time evt. scheduled for removal? |
QL | 9:ca2e6010d9e2 | 1588 | if (t == QF_timeEvtListHead_) { |
QL | 9:ca2e6010d9e2 | 1589 | QF_timeEvtListHead_ = t->m_next; |
QL | 9:ca2e6010d9e2 | 1590 | } |
QL | 9:ca2e6010d9e2 | 1591 | else { |
QL | 9:ca2e6010d9e2 | 1592 | Q_ASSERT(prev != null_tevt); |
QL | 9:ca2e6010d9e2 | 1593 | prev->m_next = t->m_next; |
QL | 9:ca2e6010d9e2 | 1594 | } |
QL | 9:ca2e6010d9e2 | 1595 | QF_EVT_REF_CTR_DEC_(t); // mark as not linked |
QL | 9:ca2e6010d9e2 | 1596 | } |
QL | 9:ca2e6010d9e2 | 1597 | else { |
QL | 9:ca2e6010d9e2 | 1598 | --t->m_ctr; |
QL | 9:ca2e6010d9e2 | 1599 | if (t->m_ctr == tc_0) { // about to expire? |
QL | 9:ca2e6010d9e2 | 1600 | if (t->m_interval != tc_0) { // periodic time event? |
QL | 9:ca2e6010d9e2 | 1601 | t->m_ctr = t->m_interval; // rearm the time evt |
QL | 9:ca2e6010d9e2 | 1602 | } |
QL | 9:ca2e6010d9e2 | 1603 | else { |
QL | 9:ca2e6010d9e2 | 1604 | QS_BEGIN_NOCRIT_(QS_QF_TIMEEVT_AUTO_DISARM, QS::teObj_, t) |
QL | 9:ca2e6010d9e2 | 1605 | QS_OBJ_(t); // this time event object |
QL | 9:ca2e6010d9e2 | 1606 | QS_OBJ_(t->m_act); // the active object |
QL | 9:ca2e6010d9e2 | 1607 | QS_END_NOCRIT_() |
QL | 9:ca2e6010d9e2 | 1608 | } |
QL | 9:ca2e6010d9e2 | 1609 | |
QL | 9:ca2e6010d9e2 | 1610 | QS_BEGIN_NOCRIT_(QS_QF_TIMEEVT_POST, QS::teObj_, t) |
QL | 9:ca2e6010d9e2 | 1611 | QS_TIME_(); // timestamp |
QL | 9:ca2e6010d9e2 | 1612 | QS_OBJ_(t); // the time event object |
QL | 9:ca2e6010d9e2 | 1613 | QS_SIG_(t->sig); // the signal of this time event |
QL | 9:ca2e6010d9e2 | 1614 | QS_OBJ_(t->m_act); // the active object |
QL | 9:ca2e6010d9e2 | 1615 | QS_END_NOCRIT_() |
QL | 9:ca2e6010d9e2 | 1616 | |
QL | 9:ca2e6010d9e2 | 1617 | QF_CRIT_EXIT_(); // leave crit. section before posting |
QL | 9:ca2e6010d9e2 | 1618 | // POST() asserts internally if the queue overflows |
QL | 9:ca2e6010d9e2 | 1619 | t->m_act->POST(t, sender); |
QL | 9:ca2e6010d9e2 | 1620 | QF_CRIT_ENTRY_(); // re-enter crit. section to continue |
QL | 9:ca2e6010d9e2 | 1621 | |
QL | 9:ca2e6010d9e2 | 1622 | if (t->m_ctr == tc_0) { // still marked to expire? |
QL | 9:ca2e6010d9e2 | 1623 | if (t == QF_timeEvtListHead_) { |
QL | 9:ca2e6010d9e2 | 1624 | QF_timeEvtListHead_ = t->m_next; |
QL | 9:ca2e6010d9e2 | 1625 | } |
QL | 9:ca2e6010d9e2 | 1626 | else { |
QL | 9:ca2e6010d9e2 | 1627 | Q_ASSERT(prev != null_tevt); |
QL | 9:ca2e6010d9e2 | 1628 | prev->m_next = t->m_next; |
QL | 9:ca2e6010d9e2 | 1629 | } |
QL | 9:ca2e6010d9e2 | 1630 | QF_EVT_REF_CTR_DEC_(t); // mark as removed |
QL | 9:ca2e6010d9e2 | 1631 | } |
QL | 9:ca2e6010d9e2 | 1632 | else { |
QL | 9:ca2e6010d9e2 | 1633 | prev = t; |
QL | 9:ca2e6010d9e2 | 1634 | } |
QL | 9:ca2e6010d9e2 | 1635 | } |
QL | 9:ca2e6010d9e2 | 1636 | else { |
QL | 9:ca2e6010d9e2 | 1637 | prev = t; |
QL | 9:ca2e6010d9e2 | 1638 | } |
QL | 9:ca2e6010d9e2 | 1639 | } |
QL | 9:ca2e6010d9e2 | 1640 | } |
QL | 9:ca2e6010d9e2 | 1641 | QF_CRIT_EXIT_(); |
QL | 9:ca2e6010d9e2 | 1642 | } |
QL | 9:ca2e6010d9e2 | 1643 | |
QL | 9:ca2e6010d9e2 | 1644 | QP_END_ |
QL | 9:ca2e6010d9e2 | 1645 | |
QL | 9:ca2e6010d9e2 | 1646 | // "qmp_get.cpp" ============================================================= |
QL | 9:ca2e6010d9e2 | 1647 | /// \brief QMPool::get() and QF::getPoolMargin() implementation. |
QL | 9:ca2e6010d9e2 | 1648 | |
QL | 9:ca2e6010d9e2 | 1649 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 1650 | |
QL | 9:ca2e6010d9e2 | 1651 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 1652 | void *QMPool::get(void) { |
QL | 9:ca2e6010d9e2 | 1653 | QF_CRIT_STAT_ |
QL | 9:ca2e6010d9e2 | 1654 | QF_CRIT_ENTRY_(); |
QL | 9:ca2e6010d9e2 | 1655 | |
QL | 9:ca2e6010d9e2 | 1656 | QFreeBlock *fb = static_cast<QFreeBlock *>(m_free); // free block or NULL |
QL | 9:ca2e6010d9e2 | 1657 | if (fb != static_cast<QFreeBlock *>(0)) { // free block available? |
QL | 9:ca2e6010d9e2 | 1658 | m_free = fb->m_next; // adjust list head to the next free block |
QL | 9:ca2e6010d9e2 | 1659 | |
QL | 9:ca2e6010d9e2 | 1660 | Q_ASSERT(m_nFree > static_cast<QMPoolCtr>(0)); // at least one free |
QL | 9:ca2e6010d9e2 | 1661 | --m_nFree; // one free block less |
QL | 9:ca2e6010d9e2 | 1662 | if (m_nMin > m_nFree) { |
QL | 9:ca2e6010d9e2 | 1663 | m_nMin = m_nFree; // remember the minimum so far |
QL | 9:ca2e6010d9e2 | 1664 | } |
QL | 9:ca2e6010d9e2 | 1665 | } |
QL | 9:ca2e6010d9e2 | 1666 | |
QL | 9:ca2e6010d9e2 | 1667 | QS_BEGIN_NOCRIT_(QS_QF_MPOOL_GET, QS::mpObj_, m_start) |
QL | 9:ca2e6010d9e2 | 1668 | QS_TIME_(); // timestamp |
QL | 9:ca2e6010d9e2 | 1669 | QS_OBJ_(m_start); // the memory managed by this pool |
QL | 9:ca2e6010d9e2 | 1670 | QS_MPC_(m_nFree); // the number of free blocks in the pool |
QL | 9:ca2e6010d9e2 | 1671 | QS_MPC_(m_nMin); // the mninimum number of free blocks in the pool |
QL | 9:ca2e6010d9e2 | 1672 | QS_END_NOCRIT_() |
QL | 9:ca2e6010d9e2 | 1673 | |
QL | 9:ca2e6010d9e2 | 1674 | QF_CRIT_EXIT_(); |
QL | 9:ca2e6010d9e2 | 1675 | return fb; // return the block or NULL pointer to the caller |
QL | 9:ca2e6010d9e2 | 1676 | } |
QL | 9:ca2e6010d9e2 | 1677 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 1678 | uint32_t QF::getPoolMargin(uint8_t const poolId) { |
QL | 9:ca2e6010d9e2 | 1679 | Q_REQUIRE((u8_1 <= poolId) && (poolId <= QF_maxPool_)); |
QL | 9:ca2e6010d9e2 | 1680 | |
QL | 9:ca2e6010d9e2 | 1681 | QF_CRIT_STAT_ |
QL | 9:ca2e6010d9e2 | 1682 | QF_CRIT_ENTRY_(); |
QL | 9:ca2e6010d9e2 | 1683 | uint32_t margin = static_cast<uint32_t>(QF_pool_[poolId - u8_1].m_nMin); |
QL | 9:ca2e6010d9e2 | 1684 | QF_CRIT_EXIT_(); |
QL | 9:ca2e6010d9e2 | 1685 | |
QL | 9:ca2e6010d9e2 | 1686 | return margin; |
QL | 9:ca2e6010d9e2 | 1687 | } |
QL | 9:ca2e6010d9e2 | 1688 | |
QL | 9:ca2e6010d9e2 | 1689 | QP_END_ |
QL | 9:ca2e6010d9e2 | 1690 | |
QL | 9:ca2e6010d9e2 | 1691 | // "qmp_init.cpp" ============================================================ |
QL | 9:ca2e6010d9e2 | 1692 | /// \brief QMPool::init() implementation. |
QL | 9:ca2e6010d9e2 | 1693 | |
QL | 9:ca2e6010d9e2 | 1694 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 1695 | |
QL | 9:ca2e6010d9e2 | 1696 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 1697 | void QMPool::init(void * const poolSto, uint32_t const poolSize, |
QL | 9:ca2e6010d9e2 | 1698 | QMPoolSize const blockSize) |
QL | 9:ca2e6010d9e2 | 1699 | { |
QL | 9:ca2e6010d9e2 | 1700 | // The memory block must be valid |
QL | 9:ca2e6010d9e2 | 1701 | // and the poolSize must fit at least one free block |
QL | 9:ca2e6010d9e2 | 1702 | // and the blockSize must not be too close to the top of the dynamic range |
QL | 9:ca2e6010d9e2 | 1703 | Q_REQUIRE((poolSto != null_void) |
QL | 9:ca2e6010d9e2 | 1704 | && (poolSize >= static_cast<uint32_t>(sizeof(QFreeBlock))) |
QL | 9:ca2e6010d9e2 | 1705 | && ((blockSize + static_cast<QMPoolSize>(sizeof(QFreeBlock))) |
QL | 9:ca2e6010d9e2 | 1706 | > blockSize)); |
QL | 9:ca2e6010d9e2 | 1707 | |
QL | 9:ca2e6010d9e2 | 1708 | m_free = poolSto; |
QL | 9:ca2e6010d9e2 | 1709 | |
QL | 9:ca2e6010d9e2 | 1710 | // round up the blockSize to fit an integer number of pointers |
QL | 9:ca2e6010d9e2 | 1711 | m_blockSize = static_cast<QMPoolSize>(sizeof(QFreeBlock));//start with one |
QL | 9:ca2e6010d9e2 | 1712 | uint32_t nblocks = static_cast<uint32_t>(1);//# free blocks in a mem block |
QL | 9:ca2e6010d9e2 | 1713 | while (m_blockSize < blockSize) { |
QL | 9:ca2e6010d9e2 | 1714 | m_blockSize += static_cast<QMPoolSize>(sizeof(QFreeBlock)); |
QL | 9:ca2e6010d9e2 | 1715 | ++nblocks; |
QL | 9:ca2e6010d9e2 | 1716 | } |
QL | 9:ca2e6010d9e2 | 1717 | |
QL | 9:ca2e6010d9e2 | 1718 | // the whole pool buffer must fit at least one rounded-up block |
QL | 9:ca2e6010d9e2 | 1719 | Q_ASSERT(poolSize >= static_cast<uint32_t>(m_blockSize)); |
QL | 9:ca2e6010d9e2 | 1720 | |
QL | 9:ca2e6010d9e2 | 1721 | // chain all blocks together in a free-list... |
QL | 9:ca2e6010d9e2 | 1722 | // don't chain last block |
QL | 9:ca2e6010d9e2 | 1723 | uint32_t availSize = poolSize - static_cast<uint32_t>(m_blockSize); |
QL | 9:ca2e6010d9e2 | 1724 | m_nTot = static_cast<QMPoolCtr>(1); // one (the last) block in the pool |
QL | 9:ca2e6010d9e2 | 1725 | //start at the head of the free list |
QL | 9:ca2e6010d9e2 | 1726 | QFreeBlock *fb = static_cast<QFreeBlock *>(m_free); |
QL | 9:ca2e6010d9e2 | 1727 | while (availSize >= static_cast<uint32_t>(m_blockSize)) { |
QL | 9:ca2e6010d9e2 | 1728 | fb->m_next = &QF_PTR_AT_(fb, nblocks); // setup the next link |
QL | 9:ca2e6010d9e2 | 1729 | fb = fb->m_next; // advance to next block |
QL | 9:ca2e6010d9e2 | 1730 | availSize -= static_cast<uint32_t>(m_blockSize);// less available size |
QL | 9:ca2e6010d9e2 | 1731 | ++m_nTot; // increment the number of blocks so far |
QL | 9:ca2e6010d9e2 | 1732 | } |
QL | 9:ca2e6010d9e2 | 1733 | |
QL | 9:ca2e6010d9e2 | 1734 | fb->m_next = static_cast<QFreeBlock *>(0); // the last link points to NULL |
QL | 9:ca2e6010d9e2 | 1735 | m_nFree = m_nTot; // all blocks are free |
QL | 9:ca2e6010d9e2 | 1736 | m_nMin = m_nTot; // the minimum number of free blocks |
QL | 9:ca2e6010d9e2 | 1737 | m_start = poolSto; // the original start this pool buffer |
QL | 9:ca2e6010d9e2 | 1738 | m_end = fb; // the last block in this pool |
QL | 9:ca2e6010d9e2 | 1739 | |
QL | 9:ca2e6010d9e2 | 1740 | QS_CRIT_STAT_ |
QL | 9:ca2e6010d9e2 | 1741 | QS_BEGIN_(QS_QF_MPOOL_INIT, QS::mpObj_, m_start) |
QL | 9:ca2e6010d9e2 | 1742 | QS_OBJ_(m_start); // the memory managed by this pool |
QL | 9:ca2e6010d9e2 | 1743 | QS_MPC_(m_nTot); // the total number of blocks |
QL | 9:ca2e6010d9e2 | 1744 | QS_END_() |
QL | 9:ca2e6010d9e2 | 1745 | } |
QL | 9:ca2e6010d9e2 | 1746 | |
QL | 9:ca2e6010d9e2 | 1747 | QP_END_ |
QL | 9:ca2e6010d9e2 | 1748 | |
QL | 9:ca2e6010d9e2 | 1749 | // "qmp_put.cpp" ============================================================= |
QL | 9:ca2e6010d9e2 | 1750 | /// \brief QMPool::put() implementation. |
QL | 9:ca2e6010d9e2 | 1751 | |
QL | 9:ca2e6010d9e2 | 1752 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 1753 | |
QL | 9:ca2e6010d9e2 | 1754 | // This macro is specifically and exclusively used for checking the range |
QL | 9:ca2e6010d9e2 | 1755 | // of a block pointer returned to the pool. Such a check must rely on the |
QL | 9:ca2e6010d9e2 | 1756 | // pointer arithmetic not compliant with the MISRA-C++:2008 rules ??? and |
QL | 9:ca2e6010d9e2 | 1757 | // ???. Defining a specific macro for this purpose allows to selectively |
QL | 9:ca2e6010d9e2 | 1758 | // disable the warnings for this particular case. |
QL | 9:ca2e6010d9e2 | 1759 | // |
QL | 9:ca2e6010d9e2 | 1760 | #define QF_PTR_RANGE_(x_, min_, max_) (((min_) <= (x_)) && ((x_) <= (max_))) |
QL | 9:ca2e6010d9e2 | 1761 | |
QL | 9:ca2e6010d9e2 | 1762 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 1763 | void QMPool::put(void * const b) { |
QL | 9:ca2e6010d9e2 | 1764 | |
QL | 9:ca2e6010d9e2 | 1765 | Q_REQUIRE(m_nFree < m_nTot); // adding one free so, # free < total |
QL | 9:ca2e6010d9e2 | 1766 | Q_REQUIRE(QF_PTR_RANGE_(b, m_start, m_end)); // b must be in range |
QL | 9:ca2e6010d9e2 | 1767 | |
QL | 9:ca2e6010d9e2 | 1768 | QF_CRIT_STAT_ |
QL | 9:ca2e6010d9e2 | 1769 | QF_CRIT_ENTRY_(); |
QL | 9:ca2e6010d9e2 | 1770 | |
QL | 9:ca2e6010d9e2 | 1771 | // link into the free list |
QL | 9:ca2e6010d9e2 | 1772 | (static_cast<QFreeBlock*>(b))->m_next = static_cast<QFreeBlock *>(m_free); |
QL | 9:ca2e6010d9e2 | 1773 | m_free = b; // set as new head of the free list |
QL | 9:ca2e6010d9e2 | 1774 | ++m_nFree; // one more free block in this pool |
QL | 9:ca2e6010d9e2 | 1775 | |
QL | 9:ca2e6010d9e2 | 1776 | QS_BEGIN_NOCRIT_(QS_QF_MPOOL_PUT, QS::mpObj_, m_start) |
QL | 9:ca2e6010d9e2 | 1777 | QS_TIME_(); // timestamp |
QL | 9:ca2e6010d9e2 | 1778 | QS_OBJ_(m_start); // the memory managed by this pool |
QL | 9:ca2e6010d9e2 | 1779 | QS_MPC_(m_nFree); // the number of free blocks in the pool |
QL | 9:ca2e6010d9e2 | 1780 | QS_END_NOCRIT_() |
QL | 9:ca2e6010d9e2 | 1781 | |
QL | 9:ca2e6010d9e2 | 1782 | QF_CRIT_EXIT_(); |
QL | 9:ca2e6010d9e2 | 1783 | } |
QL | 9:ca2e6010d9e2 | 1784 | |
QL | 9:ca2e6010d9e2 | 1785 | QP_END_ |
QL | 9:ca2e6010d9e2 | 1786 | |
QL | 9:ca2e6010d9e2 | 1787 | |
QL | 9:ca2e6010d9e2 | 1788 | // "qte_arm.cpp" ============================================================= |
QL | 9:ca2e6010d9e2 | 1789 | /// \brief QF_timeEvtListHead_ definition and QTimeEvt::arm_() implementation. |
QL | 9:ca2e6010d9e2 | 1790 | |
QL | 9:ca2e6010d9e2 | 1791 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 1792 | |
QL | 9:ca2e6010d9e2 | 1793 | // Package-scope objects ----------------------------------------------------- |
QL | 9:ca2e6010d9e2 | 1794 | QTimeEvt *QF_timeEvtListHead_; // head of linked list of time events |
QL | 9:ca2e6010d9e2 | 1795 | |
QL | 9:ca2e6010d9e2 | 1796 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 1797 | bool QF::noTimeEvtsActive(void) { |
QL | 9:ca2e6010d9e2 | 1798 | return QF_timeEvtListHead_ == null_tevt; |
QL | 9:ca2e6010d9e2 | 1799 | } |
QL | 9:ca2e6010d9e2 | 1800 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 1801 | void QTimeEvt::arm_(QActive * const act, QTimeEvtCtr const nTicks) { |
QL | 9:ca2e6010d9e2 | 1802 | Q_REQUIRE((nTicks > tc_0) /* cannot arm with 0 ticks */ |
QL | 9:ca2e6010d9e2 | 1803 | && (act != null_act) /* Active object must be provided */ |
QL | 9:ca2e6010d9e2 | 1804 | && (m_ctr == tc_0) /* must be disarmed */ |
QL | 9:ca2e6010d9e2 | 1805 | && (static_cast<enum_t>(sig) >= Q_USER_SIG)); // valid signal |
QL | 9:ca2e6010d9e2 | 1806 | QF_CRIT_STAT_ |
QL | 9:ca2e6010d9e2 | 1807 | QF_CRIT_ENTRY_(); |
QL | 9:ca2e6010d9e2 | 1808 | m_ctr = nTicks; |
QL | 9:ca2e6010d9e2 | 1809 | m_act = act; |
QL | 9:ca2e6010d9e2 | 1810 | if (refCtr_ == u8_0) { // not linked? |
QL | 9:ca2e6010d9e2 | 1811 | m_next = QF_timeEvtListHead_; |
QL | 9:ca2e6010d9e2 | 1812 | QF_timeEvtListHead_ = this; |
QL | 9:ca2e6010d9e2 | 1813 | QF_EVT_REF_CTR_INC_(this); // mark as linked |
QL | 9:ca2e6010d9e2 | 1814 | } |
QL | 9:ca2e6010d9e2 | 1815 | |
QL | 9:ca2e6010d9e2 | 1816 | QS_BEGIN_NOCRIT_(QS_QF_TIMEEVT_ARM, QS::teObj_, this) |
QL | 9:ca2e6010d9e2 | 1817 | QS_TIME_(); // timestamp |
QL | 9:ca2e6010d9e2 | 1818 | QS_OBJ_(this); // this time event object |
QL | 9:ca2e6010d9e2 | 1819 | QS_OBJ_(act); // the active object |
QL | 9:ca2e6010d9e2 | 1820 | QS_TEC_(nTicks); // the number of ticks |
QL | 9:ca2e6010d9e2 | 1821 | QS_TEC_(m_interval); // the interval |
QL | 9:ca2e6010d9e2 | 1822 | QS_END_NOCRIT_() |
QL | 9:ca2e6010d9e2 | 1823 | |
QL | 9:ca2e6010d9e2 | 1824 | QF_CRIT_EXIT_(); |
QL | 9:ca2e6010d9e2 | 1825 | } |
QL | 9:ca2e6010d9e2 | 1826 | |
QL | 9:ca2e6010d9e2 | 1827 | QP_END_ |
QL | 9:ca2e6010d9e2 | 1828 | |
QL | 9:ca2e6010d9e2 | 1829 | |
QL | 9:ca2e6010d9e2 | 1830 | // "qte_ctor.cpp" ============================================================ |
QL | 9:ca2e6010d9e2 | 1831 | /// \brief QTimeEvt::QTimeEvt() implementation. |
QL | 9:ca2e6010d9e2 | 1832 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 1833 | |
QL | 9:ca2e6010d9e2 | 1834 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 1835 | QTimeEvt::QTimeEvt(enum_t const s) |
QL | 9:ca2e6010d9e2 | 1836 | : |
QL | 9:ca2e6010d9e2 | 1837 | #ifdef Q_EVT_CTOR |
QL | 9:ca2e6010d9e2 | 1838 | QEvt(static_cast<QSignal>(s)), |
QL | 9:ca2e6010d9e2 | 1839 | #endif |
QL | 9:ca2e6010d9e2 | 1840 | m_next(null_tevt), |
QL | 9:ca2e6010d9e2 | 1841 | m_act(null_act), |
QL | 9:ca2e6010d9e2 | 1842 | m_ctr(tc_0), |
QL | 9:ca2e6010d9e2 | 1843 | m_interval(tc_0) |
QL | 9:ca2e6010d9e2 | 1844 | { |
QL | 9:ca2e6010d9e2 | 1845 | Q_REQUIRE(s >= Q_USER_SIG); // signal must be valid |
QL | 9:ca2e6010d9e2 | 1846 | #ifndef Q_EVT_CTOR |
QL | 9:ca2e6010d9e2 | 1847 | sig = static_cast<QSignal>(s); |
QL | 9:ca2e6010d9e2 | 1848 | #endif |
QL | 9:ca2e6010d9e2 | 1849 | // time event must be static, see NOTE01 |
QL | 9:ca2e6010d9e2 | 1850 | poolId_ = u8_0; // not from any event pool |
QL | 9:ca2e6010d9e2 | 1851 | refCtr_ = u8_0; // not linked |
QL | 9:ca2e6010d9e2 | 1852 | } |
QL | 9:ca2e6010d9e2 | 1853 | |
QL | 9:ca2e6010d9e2 | 1854 | QP_END_ |
QL | 9:ca2e6010d9e2 | 1855 | |
QL | 9:ca2e6010d9e2 | 1856 | |
QL | 9:ca2e6010d9e2 | 1857 | // "qte_ctr.cpp" ============================================================= |
QL | 9:ca2e6010d9e2 | 1858 | /// \brief QTimeEvt::ctr() implementation. |
QL | 9:ca2e6010d9e2 | 1859 | |
QL | 9:ca2e6010d9e2 | 1860 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 1861 | |
QL | 9:ca2e6010d9e2 | 1862 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 1863 | QTimeEvtCtr QTimeEvt::ctr(void) const { |
QL | 9:ca2e6010d9e2 | 1864 | QF_CRIT_STAT_ |
QL | 9:ca2e6010d9e2 | 1865 | |
QL | 9:ca2e6010d9e2 | 1866 | QF_CRIT_ENTRY_(); |
QL | 9:ca2e6010d9e2 | 1867 | QTimeEvtCtr ret = m_ctr; |
QL | 9:ca2e6010d9e2 | 1868 | |
QL | 9:ca2e6010d9e2 | 1869 | QS_BEGIN_NOCRIT_(QS_QF_TIMEEVT_CTR, QS::teObj_, this) |
QL | 9:ca2e6010d9e2 | 1870 | QS_TIME_(); // timestamp |
QL | 9:ca2e6010d9e2 | 1871 | QS_OBJ_(this); // this time event object |
QL | 9:ca2e6010d9e2 | 1872 | QS_OBJ_(m_act); // the active object |
QL | 9:ca2e6010d9e2 | 1873 | QS_TEC_(ret); // the current counter |
QL | 9:ca2e6010d9e2 | 1874 | QS_TEC_(m_interval); // the interval |
QL | 9:ca2e6010d9e2 | 1875 | QS_END_NOCRIT_() |
QL | 9:ca2e6010d9e2 | 1876 | |
QL | 9:ca2e6010d9e2 | 1877 | QF_CRIT_EXIT_(); |
QL | 9:ca2e6010d9e2 | 1878 | return ret; |
QL | 9:ca2e6010d9e2 | 1879 | } |
QL | 9:ca2e6010d9e2 | 1880 | |
QL | 9:ca2e6010d9e2 | 1881 | QP_END_ |
QL | 9:ca2e6010d9e2 | 1882 | |
QL | 9:ca2e6010d9e2 | 1883 | // "qte_darm.cpp" ============================================================ |
QL | 9:ca2e6010d9e2 | 1884 | /// \brief QTimeEvt::disarm() implementation. |
QL | 9:ca2e6010d9e2 | 1885 | |
QL | 9:ca2e6010d9e2 | 1886 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 1887 | |
QL | 9:ca2e6010d9e2 | 1888 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 1889 | // NOTE: disarm a time evt (no harm in disarming an already disarmed time evt) |
QL | 9:ca2e6010d9e2 | 1890 | bool QTimeEvt::disarm(void) { |
QL | 9:ca2e6010d9e2 | 1891 | QF_CRIT_STAT_ |
QL | 9:ca2e6010d9e2 | 1892 | QF_CRIT_ENTRY_(); |
QL | 9:ca2e6010d9e2 | 1893 | bool wasArmed; |
QL | 9:ca2e6010d9e2 | 1894 | if (m_ctr != tc_0) { // is the time event actually armed? |
QL | 9:ca2e6010d9e2 | 1895 | wasArmed = true; |
QL | 9:ca2e6010d9e2 | 1896 | |
QL | 9:ca2e6010d9e2 | 1897 | QS_BEGIN_NOCRIT_(QS_QF_TIMEEVT_DISARM, QS::teObj_, this) |
QL | 9:ca2e6010d9e2 | 1898 | QS_TIME_(); // timestamp |
QL | 9:ca2e6010d9e2 | 1899 | QS_OBJ_(this); // this time event object |
QL | 9:ca2e6010d9e2 | 1900 | QS_OBJ_(m_act); // the active object |
QL | 9:ca2e6010d9e2 | 1901 | QS_TEC_(m_ctr); // the number of ticks |
QL | 9:ca2e6010d9e2 | 1902 | QS_TEC_(m_interval); // the interval |
QL | 9:ca2e6010d9e2 | 1903 | QS_END_NOCRIT_() |
QL | 9:ca2e6010d9e2 | 1904 | |
QL | 9:ca2e6010d9e2 | 1905 | m_ctr = tc_0; // schedule removal from the list |
QL | 9:ca2e6010d9e2 | 1906 | } |
QL | 9:ca2e6010d9e2 | 1907 | else { // the time event was not armed |
QL | 9:ca2e6010d9e2 | 1908 | wasArmed = false; |
QL | 9:ca2e6010d9e2 | 1909 | |
QL | 9:ca2e6010d9e2 | 1910 | QS_BEGIN_NOCRIT_(QS_QF_TIMEEVT_DISARM_ATTEMPT, QS::teObj_, this) |
QL | 9:ca2e6010d9e2 | 1911 | QS_TIME_(); // timestamp |
QL | 9:ca2e6010d9e2 | 1912 | QS_OBJ_(this); // this time event object |
QL | 9:ca2e6010d9e2 | 1913 | QS_OBJ_(m_act); // the active object |
QL | 9:ca2e6010d9e2 | 1914 | QS_END_NOCRIT_() |
QL | 9:ca2e6010d9e2 | 1915 | } |
QL | 9:ca2e6010d9e2 | 1916 | QF_CRIT_EXIT_(); |
QL | 9:ca2e6010d9e2 | 1917 | return wasArmed; |
QL | 9:ca2e6010d9e2 | 1918 | } |
QL | 9:ca2e6010d9e2 | 1919 | |
QL | 9:ca2e6010d9e2 | 1920 | QP_END_ |
QL | 9:ca2e6010d9e2 | 1921 | |
QL | 9:ca2e6010d9e2 | 1922 | |
QL | 9:ca2e6010d9e2 | 1923 | // "qte_rarm.cpp" ============================================================ |
QL | 9:ca2e6010d9e2 | 1924 | /// \brief QTimeEvt::rearm() implementation. |
QL | 9:ca2e6010d9e2 | 1925 | |
QL | 9:ca2e6010d9e2 | 1926 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 1927 | |
QL | 9:ca2e6010d9e2 | 1928 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 1929 | bool QTimeEvt::rearm(QTimeEvtCtr const nTicks) { |
QL | 9:ca2e6010d9e2 | 1930 | Q_REQUIRE((nTicks > tc_0) /* cannot rearm with 0 ticks */ |
QL | 9:ca2e6010d9e2 | 1931 | && (m_act != null_act) /* active object must be valid */ |
QL | 9:ca2e6010d9e2 | 1932 | && (static_cast<enum_t>(sig) >= Q_USER_SIG)); // valid signal |
QL | 9:ca2e6010d9e2 | 1933 | |
QL | 9:ca2e6010d9e2 | 1934 | QF_CRIT_STAT_ |
QL | 9:ca2e6010d9e2 | 1935 | QF_CRIT_ENTRY_(); |
QL | 9:ca2e6010d9e2 | 1936 | |
QL | 9:ca2e6010d9e2 | 1937 | bool isArmed; |
QL | 9:ca2e6010d9e2 | 1938 | if (m_ctr == tc_0) { // is this time event disarmed? |
QL | 9:ca2e6010d9e2 | 1939 | isArmed = false; |
QL | 9:ca2e6010d9e2 | 1940 | m_next = QF_timeEvtListHead_; |
QL | 9:ca2e6010d9e2 | 1941 | if (QF_timeEvtListHead_ != null_tevt) { |
QL | 9:ca2e6010d9e2 | 1942 | m_next = QF_timeEvtListHead_; |
QL | 9:ca2e6010d9e2 | 1943 | QF_timeEvtListHead_ = this; |
QL | 9:ca2e6010d9e2 | 1944 | QF_EVT_REF_CTR_INC_(this); // mark as linked |
QL | 9:ca2e6010d9e2 | 1945 | } |
QL | 9:ca2e6010d9e2 | 1946 | } |
QL | 9:ca2e6010d9e2 | 1947 | else { |
QL | 9:ca2e6010d9e2 | 1948 | isArmed = true; |
QL | 9:ca2e6010d9e2 | 1949 | } |
QL | 9:ca2e6010d9e2 | 1950 | m_ctr = nTicks; // re-load the tick counter (shift the phasing) |
QL | 9:ca2e6010d9e2 | 1951 | |
QL | 9:ca2e6010d9e2 | 1952 | QS_BEGIN_NOCRIT_(QS_QF_TIMEEVT_REARM, QS::teObj_, this) |
QL | 9:ca2e6010d9e2 | 1953 | QS_TIME_(); // timestamp |
QL | 9:ca2e6010d9e2 | 1954 | QS_OBJ_(this); // this time event object |
QL | 9:ca2e6010d9e2 | 1955 | QS_OBJ_(m_act); // the active object |
QL | 9:ca2e6010d9e2 | 1956 | QS_TEC_(m_ctr); // the number of ticks |
QL | 9:ca2e6010d9e2 | 1957 | QS_TEC_(m_interval); // the interval |
QL | 9:ca2e6010d9e2 | 1958 | QS_U8_(isArmed ? u8_1 : u8_0); // was the timer armed? |
QL | 9:ca2e6010d9e2 | 1959 | QS_END_NOCRIT_() |
QL | 9:ca2e6010d9e2 | 1960 | |
QL | 9:ca2e6010d9e2 | 1961 | QF_CRIT_EXIT_(); |
QL | 9:ca2e6010d9e2 | 1962 | return isArmed; |
QL | 9:ca2e6010d9e2 | 1963 | } |
QL | 9:ca2e6010d9e2 | 1964 | |
QL | 9:ca2e6010d9e2 | 1965 | QP_END_ |
QL | 9:ca2e6010d9e2 | 1966 | |
QL | 9:ca2e6010d9e2 | 1967 | |
QL | 9:ca2e6010d9e2 | 1968 | ////////////////////////////////////////////////////////////////////////////// |
QL | 9:ca2e6010d9e2 | 1969 | // Kernel selection based on QK_PREEMPTIVE |
QL | 9:ca2e6010d9e2 | 1970 | // |
QL | 9:ca2e6010d9e2 | 1971 | #ifdef QK_PREEMPTIVE |
QL | 9:ca2e6010d9e2 | 1972 | |
QL | 9:ca2e6010d9e2 | 1973 | // "qk_pkg.h" ================================================================ |
QL | 9:ca2e6010d9e2 | 1974 | /// \brief Internal (package scope) QK/C interface. |
QL | 9:ca2e6010d9e2 | 1975 | |
QL | 9:ca2e6010d9e2 | 1976 | #ifndef QF_CRIT_STAT_TYPE |
QL | 9:ca2e6010d9e2 | 1977 | /// \brief This is an internal macro for defining the critical section |
QL | 9:ca2e6010d9e2 | 1978 | /// status type. |
QL | 9:ca2e6010d9e2 | 1979 | /// |
QL | 9:ca2e6010d9e2 | 1980 | /// The purpose of this macro is to enable writing the same code for the |
QL | 9:ca2e6010d9e2 | 1981 | /// case when critical sectgion status type is defined and when it is not. |
QL | 9:ca2e6010d9e2 | 1982 | /// If the macro #QF_CRIT_STAT_TYPE is defined, this internal macro |
QL | 9:ca2e6010d9e2 | 1983 | /// provides the definition of the critical section status varaible. |
QL | 9:ca2e6010d9e2 | 1984 | /// Otherwise this macro is empty. |
QL | 9:ca2e6010d9e2 | 1985 | /// \sa #QF_CRIT_STAT_TYPE |
QL | 9:ca2e6010d9e2 | 1986 | #define QF_CRIT_STAT_ |
QL | 9:ca2e6010d9e2 | 1987 | |
QL | 9:ca2e6010d9e2 | 1988 | /// \brief This is an internal macro for entering a critical section. |
QL | 9:ca2e6010d9e2 | 1989 | /// |
QL | 9:ca2e6010d9e2 | 1990 | /// The purpose of this macro is to enable writing the same code for the |
QL | 9:ca2e6010d9e2 | 1991 | /// case when critical sectgion status type is defined and when it is not. |
QL | 9:ca2e6010d9e2 | 1992 | /// If the macro #QF_CRIT_STAT_TYPE is defined, this internal macro |
QL | 9:ca2e6010d9e2 | 1993 | /// invokes #QF_CRIT_ENTRY passing the key variable as the parameter. |
QL | 9:ca2e6010d9e2 | 1994 | /// Otherwise #QF_CRIT_ENTRY is invoked with a dummy parameter. |
QL | 9:ca2e6010d9e2 | 1995 | /// \sa #QF_CRIT_ENTRY |
QL | 9:ca2e6010d9e2 | 1996 | #define QF_CRIT_ENTRY_() QF_CRIT_ENTRY(dummy) |
QL | 9:ca2e6010d9e2 | 1997 | |
QL | 9:ca2e6010d9e2 | 1998 | /// \brief This is an internal macro for exiting a cricial section. |
QL | 9:ca2e6010d9e2 | 1999 | /// |
QL | 9:ca2e6010d9e2 | 2000 | /// The purpose of this macro is to enable writing the same code for the |
QL | 9:ca2e6010d9e2 | 2001 | /// case when critical sectgion status type is defined and when it is not. |
QL | 9:ca2e6010d9e2 | 2002 | /// If the macro #QF_CRIT_STAT_TYPE is defined, this internal macro |
QL | 9:ca2e6010d9e2 | 2003 | /// invokes #QF_CRIT_EXIT passing the key variable as the parameter. |
QL | 9:ca2e6010d9e2 | 2004 | /// Otherwise #QF_CRIT_EXIT is invoked with a dummy parameter. |
QL | 9:ca2e6010d9e2 | 2005 | /// \sa #QF_CRIT_EXIT |
QL | 9:ca2e6010d9e2 | 2006 | #define QF_CRIT_EXIT_() QF_CRIT_EXIT(dummy) |
QL | 9:ca2e6010d9e2 | 2007 | |
QL | 9:ca2e6010d9e2 | 2008 | #else |
QL | 9:ca2e6010d9e2 | 2009 | #define QF_CRIT_STAT_ QF_CRIT_STAT_TYPE critStat_; |
QL | 9:ca2e6010d9e2 | 2010 | #define QF_CRIT_ENTRY_() QF_CRIT_ENTRY(critStat_) |
QL | 9:ca2e6010d9e2 | 2011 | #define QF_CRIT_EXIT_() QF_CRIT_EXIT(critStat_) |
QL | 9:ca2e6010d9e2 | 2012 | #endif |
QL | 9:ca2e6010d9e2 | 2013 | // define for backwards compatibility, see NOTE01 |
QL | 9:ca2e6010d9e2 | 2014 | #ifndef QF_CRIT_STAT_TYPE |
QL | 9:ca2e6010d9e2 | 2015 | #if !defined(QF_INT_DISABLE) && defined(QF_CRIT_ENTRY) |
QL | 9:ca2e6010d9e2 | 2016 | #define QF_INT_DISABLE() QF_CRIT_ENTRY(dummy) |
QL | 9:ca2e6010d9e2 | 2017 | #endif |
QL | 9:ca2e6010d9e2 | 2018 | #if !defined(QF_INT_ENABLE) && defined(QF_CRIT_EXIT) |
QL | 9:ca2e6010d9e2 | 2019 | #define QF_INT_ENABLE() QF_CRIT_EXIT(dummy) |
QL | 9:ca2e6010d9e2 | 2020 | #endif |
QL | 9:ca2e6010d9e2 | 2021 | #endif // QF_CRIT_STAT_TYPE |
QL | 9:ca2e6010d9e2 | 2022 | |
QL | 9:ca2e6010d9e2 | 2023 | // package-scope objects... |
QL | 9:ca2e6010d9e2 | 2024 | #ifndef QK_NO_MUTEX |
QL | 9:ca2e6010d9e2 | 2025 | extern "C" uint8_t QK_ceilingPrio_; ///< QK mutex priority ceiling |
QL | 9:ca2e6010d9e2 | 2026 | #endif |
QL | 9:ca2e6010d9e2 | 2027 | |
QL | 9:ca2e6010d9e2 | 2028 | // "qk.cpp" ================================================================== |
QL | 9:ca2e6010d9e2 | 2029 | /// \brief QK_readySet_, QK_currPrio_, and QK_intNest_ definitions and |
QL | 9:ca2e6010d9e2 | 2030 | /// QK::getVersion(), QF::init(), QF::run(), QF::stop(), |
QL | 9:ca2e6010d9e2 | 2031 | /// QActive::start(), QActive::stop() implementations. |
QL | 9:ca2e6010d9e2 | 2032 | |
QL | 9:ca2e6010d9e2 | 2033 | // Public-scope objects ------------------------------------------------------ |
QL | 9:ca2e6010d9e2 | 2034 | extern "C" { |
QL | 9:ca2e6010d9e2 | 2035 | #if (QF_MAX_ACTIVE <= 8) |
QL | 9:ca2e6010d9e2 | 2036 | QP_ QPSet8 QK_readySet_; // ready set of QK |
QL | 9:ca2e6010d9e2 | 2037 | #else |
QL | 9:ca2e6010d9e2 | 2038 | QP_ QPSet64 QK_readySet_; // ready set of QK |
QL | 9:ca2e6010d9e2 | 2039 | #endif |
QL | 9:ca2e6010d9e2 | 2040 | // start with the QK scheduler locked |
QL | 9:ca2e6010d9e2 | 2041 | uint8_t QK_currPrio_ = static_cast<uint8_t>(QF_MAX_ACTIVE + 1); |
QL | 9:ca2e6010d9e2 | 2042 | uint8_t QK_intNest_; // start with nesting level of 0 |
QL | 9:ca2e6010d9e2 | 2043 | |
QL | 9:ca2e6010d9e2 | 2044 | } // extern "C" |
QL | 9:ca2e6010d9e2 | 2045 | |
QL | 9:ca2e6010d9e2 | 2046 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 2047 | |
QL | 9:ca2e6010d9e2 | 2048 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2049 | char_t const Q_ROM * Q_ROM_VAR QK::getVersion(void) { |
QL | 9:ca2e6010d9e2 | 2050 | uint8_t const u8_zero = static_cast<uint8_t>('0'); |
QL | 9:ca2e6010d9e2 | 2051 | static char_t const Q_ROM Q_ROM_VAR version[] = { |
QL | 9:ca2e6010d9e2 | 2052 | static_cast<char_t>(((QP_VERSION >> 12) & 0xFU) + u8_zero), |
QL | 9:ca2e6010d9e2 | 2053 | static_cast<char_t>('.'), |
QL | 9:ca2e6010d9e2 | 2054 | static_cast<char_t>(((QP_VERSION >> 8) & 0xFU) + u8_zero), |
QL | 9:ca2e6010d9e2 | 2055 | static_cast<char_t>('.'), |
QL | 9:ca2e6010d9e2 | 2056 | static_cast<char_t>(((QP_VERSION >> 4) & 0xFU) + u8_zero), |
QL | 9:ca2e6010d9e2 | 2057 | static_cast<char_t>((QP_VERSION & 0xFU) + u8_zero), |
QL | 9:ca2e6010d9e2 | 2058 | static_cast<char_t>('\0') |
QL | 9:ca2e6010d9e2 | 2059 | }; |
QL | 9:ca2e6010d9e2 | 2060 | return version; |
QL | 9:ca2e6010d9e2 | 2061 | } |
QL | 9:ca2e6010d9e2 | 2062 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2063 | void QF::init(void) { |
QL | 9:ca2e6010d9e2 | 2064 | QK_init(); // QK initialization ("C" linkage, might be assembly) |
QL | 9:ca2e6010d9e2 | 2065 | } |
QL | 9:ca2e6010d9e2 | 2066 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2067 | void QF::stop(void) { |
QL | 9:ca2e6010d9e2 | 2068 | QF::onCleanup(); // cleanup callback |
QL | 9:ca2e6010d9e2 | 2069 | // nothing else to do for the QK preemptive kernel |
QL | 9:ca2e6010d9e2 | 2070 | } |
QL | 9:ca2e6010d9e2 | 2071 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2072 | static void initialize(void) { |
QL | 9:ca2e6010d9e2 | 2073 | QK_currPrio_ = static_cast<uint8_t>(0); // priority for the QK idle loop |
QL | 9:ca2e6010d9e2 | 2074 | uint8_t p = QK_schedPrio_(); |
QL | 9:ca2e6010d9e2 | 2075 | if (p != static_cast<uint8_t>(0)) { |
QL | 9:ca2e6010d9e2 | 2076 | QK_sched_(p); // process all events produced so far |
QL | 9:ca2e6010d9e2 | 2077 | } |
QL | 9:ca2e6010d9e2 | 2078 | } |
QL | 9:ca2e6010d9e2 | 2079 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2080 | int16_t QF::run(void) { |
QL | 9:ca2e6010d9e2 | 2081 | QF_INT_DISABLE(); |
QL | 9:ca2e6010d9e2 | 2082 | initialize(); |
QL | 9:ca2e6010d9e2 | 2083 | onStartup(); // startup callback |
QL | 9:ca2e6010d9e2 | 2084 | QF_INT_ENABLE(); |
QL | 9:ca2e6010d9e2 | 2085 | |
QL | 9:ca2e6010d9e2 | 2086 | for (;;) { // the QK idle loop |
QL | 9:ca2e6010d9e2 | 2087 | QK::onIdle(); // invoke the QK on-idle callback |
QL | 9:ca2e6010d9e2 | 2088 | } |
QL | 9:ca2e6010d9e2 | 2089 | // this unreachable return is to make the compiler happy |
QL | 9:ca2e6010d9e2 | 2090 | return static_cast<int16_t>(0); |
QL | 9:ca2e6010d9e2 | 2091 | } |
QL | 9:ca2e6010d9e2 | 2092 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2093 | void QActive::start(uint8_t const prio, |
QL | 9:ca2e6010d9e2 | 2094 | QEvt const *qSto[], uint32_t const qLen, |
QL | 9:ca2e6010d9e2 | 2095 | void * const stkSto, uint32_t const stkSize, |
QL | 9:ca2e6010d9e2 | 2096 | QEvt const * const ie) |
QL | 9:ca2e6010d9e2 | 2097 | { |
QL | 9:ca2e6010d9e2 | 2098 | Q_REQUIRE((static_cast<uint8_t>(0) < prio) |
QL | 9:ca2e6010d9e2 | 2099 | && (prio <= static_cast<uint8_t>(QF_MAX_ACTIVE))); |
QL | 9:ca2e6010d9e2 | 2100 | |
QL | 9:ca2e6010d9e2 | 2101 | m_eQueue.init(qSto, static_cast<QEQueueCtr>(qLen)); // initialize queue |
QL | 9:ca2e6010d9e2 | 2102 | m_prio = prio; |
QL | 9:ca2e6010d9e2 | 2103 | QF::add_(this); // make QF aware of this active object |
QL | 9:ca2e6010d9e2 | 2104 | |
QL | 9:ca2e6010d9e2 | 2105 | #if defined(QK_TLS) || defined(QK_EXT_SAVE) |
QL | 9:ca2e6010d9e2 | 2106 | // in the QK port the parameter stkSize is used as the thread flags |
QL | 9:ca2e6010d9e2 | 2107 | m_osObject = static_cast<uint8_t>(stkSize); // m_osObject contains flags |
QL | 9:ca2e6010d9e2 | 2108 | |
QL | 9:ca2e6010d9e2 | 2109 | // in the QK port the parameter stkSto is used as the thread-local-storage |
QL | 9:ca2e6010d9e2 | 2110 | m_thread = stkSto; // contains the pointer to the thread-local-storage |
QL | 9:ca2e6010d9e2 | 2111 | #else |
QL | 9:ca2e6010d9e2 | 2112 | Q_ASSERT((stkSto == static_cast<void *>(0)) |
QL | 9:ca2e6010d9e2 | 2113 | && (stkSize == static_cast<uint32_t>(0))); |
QL | 9:ca2e6010d9e2 | 2114 | #endif |
QL | 9:ca2e6010d9e2 | 2115 | |
QL | 9:ca2e6010d9e2 | 2116 | init(ie); // execute initial transition |
QL | 9:ca2e6010d9e2 | 2117 | |
QL | 9:ca2e6010d9e2 | 2118 | QS_FLUSH(); // flush the trace buffer to the host |
QL | 9:ca2e6010d9e2 | 2119 | } |
QL | 9:ca2e6010d9e2 | 2120 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2121 | void QActive::stop(void) { |
QL | 9:ca2e6010d9e2 | 2122 | QF::remove_(this); // remove this active object from the QF |
QL | 9:ca2e6010d9e2 | 2123 | } |
QL | 9:ca2e6010d9e2 | 2124 | |
QL | 9:ca2e6010d9e2 | 2125 | QP_END_ |
QL | 9:ca2e6010d9e2 | 2126 | |
QL | 9:ca2e6010d9e2 | 2127 | // "qk_sched" ================================================================ |
QL | 9:ca2e6010d9e2 | 2128 | /// \brief QK_schedPrio_() and QK_sched_() implementation. |
QL | 9:ca2e6010d9e2 | 2129 | |
QL | 9:ca2e6010d9e2 | 2130 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2131 | // NOTE: the QK scheduler is entered and exited with interrupts DISABLED. |
QL | 9:ca2e6010d9e2 | 2132 | // QK_sched_() is extern "C", so it does not belong to the QP namespace. |
QL | 9:ca2e6010d9e2 | 2133 | // |
QL | 9:ca2e6010d9e2 | 2134 | extern "C" { |
QL | 9:ca2e6010d9e2 | 2135 | |
QL | 9:ca2e6010d9e2 | 2136 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2137 | // NOTE: QK schedPrio_() is entered and exited with interrupts DISABLED |
QL | 9:ca2e6010d9e2 | 2138 | uint8_t QK_schedPrio_(void) { |
QL | 9:ca2e6010d9e2 | 2139 | |
QL | 9:ca2e6010d9e2 | 2140 | uint8_t p = QK_readySet_.findMax(); |
QL | 9:ca2e6010d9e2 | 2141 | |
QL | 9:ca2e6010d9e2 | 2142 | #ifdef QK_NO_MUTEX |
QL | 9:ca2e6010d9e2 | 2143 | if (p > QK_currPrio_) { // do we have a preemption? |
QL | 9:ca2e6010d9e2 | 2144 | #else // QK priority-ceiling mutexes allowed |
QL | 9:ca2e6010d9e2 | 2145 | if ((p > QK_currPrio_) && (p > QK_ceilingPrio_)) { |
QL | 9:ca2e6010d9e2 | 2146 | #endif |
QL | 9:ca2e6010d9e2 | 2147 | } |
QL | 9:ca2e6010d9e2 | 2148 | else { |
QL | 9:ca2e6010d9e2 | 2149 | p = static_cast<uint8_t>(0); |
QL | 9:ca2e6010d9e2 | 2150 | } |
QL | 9:ca2e6010d9e2 | 2151 | return p; |
QL | 9:ca2e6010d9e2 | 2152 | } |
QL | 9:ca2e6010d9e2 | 2153 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2154 | void QK_sched_(uint8_t p) { |
QL | 9:ca2e6010d9e2 | 2155 | |
QL | 9:ca2e6010d9e2 | 2156 | uint8_t pin = QK_currPrio_; // save the initial priority |
QL | 9:ca2e6010d9e2 | 2157 | QP_ QActive *a; |
QL | 9:ca2e6010d9e2 | 2158 | #ifdef QK_TLS // thread-local storage used? |
QL | 9:ca2e6010d9e2 | 2159 | uint8_t pprev = pin; |
QL | 9:ca2e6010d9e2 | 2160 | #endif |
QL | 9:ca2e6010d9e2 | 2161 | do { |
QL | 9:ca2e6010d9e2 | 2162 | a = QP_ QF::active_[p]; // obtain the pointer to the AO |
QL | 9:ca2e6010d9e2 | 2163 | QK_currPrio_ = p; // this becomes the current task priority |
QL | 9:ca2e6010d9e2 | 2164 | |
QL | 9:ca2e6010d9e2 | 2165 | #ifdef QK_TLS // thread-local storage used? |
QL | 9:ca2e6010d9e2 | 2166 | if (p != pprev) { // are we changing threads? |
QL | 9:ca2e6010d9e2 | 2167 | QK_TLS(a); // switch new thread-local storage |
QL | 9:ca2e6010d9e2 | 2168 | pprev = p; |
QL | 9:ca2e6010d9e2 | 2169 | } |
QL | 9:ca2e6010d9e2 | 2170 | #endif |
QL | 9:ca2e6010d9e2 | 2171 | QS_BEGIN_NOCRIT_(QP_ QS_QK_SCHEDULE, QP_ QS::aoObj_, a) |
QL | 9:ca2e6010d9e2 | 2172 | QS_TIME_(); // timestamp |
QL | 9:ca2e6010d9e2 | 2173 | QS_U8_(p); // the priority of the active object |
QL | 9:ca2e6010d9e2 | 2174 | QS_U8_(pin); // the preempted priority |
QL | 9:ca2e6010d9e2 | 2175 | QS_END_NOCRIT_() |
QL | 9:ca2e6010d9e2 | 2176 | |
QL | 9:ca2e6010d9e2 | 2177 | QF_INT_ENABLE(); // unconditionally enable interrupts |
QL | 9:ca2e6010d9e2 | 2178 | |
QL | 9:ca2e6010d9e2 | 2179 | QP_ QEvt const *e = a->get_(); // get the next event for this AO |
QL | 9:ca2e6010d9e2 | 2180 | a->dispatch(e); // dispatch e to this AO |
QL | 9:ca2e6010d9e2 | 2181 | QP_ QF::gc(e); // garbage collect the event, if necessary |
QL | 9:ca2e6010d9e2 | 2182 | |
QL | 9:ca2e6010d9e2 | 2183 | // determine the next highest-priority AO ready to run |
QL | 9:ca2e6010d9e2 | 2184 | QF_INT_DISABLE(); // disable interrupts |
QL | 9:ca2e6010d9e2 | 2185 | p = QK_readySet_.findMax(); |
QL | 9:ca2e6010d9e2 | 2186 | |
QL | 9:ca2e6010d9e2 | 2187 | #ifdef QK_NO_MUTEX |
QL | 9:ca2e6010d9e2 | 2188 | } while (p > pin); // is the new priority higher than initial? |
QL | 9:ca2e6010d9e2 | 2189 | #else // QK priority-ceiling mutexes allowed |
QL | 9:ca2e6010d9e2 | 2190 | } while ((p > pin) && (p > QK_ceilingPrio_)); |
QL | 9:ca2e6010d9e2 | 2191 | #endif |
QL | 9:ca2e6010d9e2 | 2192 | |
QL | 9:ca2e6010d9e2 | 2193 | QK_currPrio_ = pin; // restore the initial priority |
QL | 9:ca2e6010d9e2 | 2194 | |
QL | 9:ca2e6010d9e2 | 2195 | #ifdef QK_TLS // thread-local storage used? |
QL | 9:ca2e6010d9e2 | 2196 | if (pin != static_cast<uint8_t>(0)) { // no extended context for idle loop |
QL | 9:ca2e6010d9e2 | 2197 | a = QP_ QF::active_[pin]; // the pointer to the preempted AO |
QL | 9:ca2e6010d9e2 | 2198 | QK_TLS(a); // restore the original TLS |
QL | 9:ca2e6010d9e2 | 2199 | } |
QL | 9:ca2e6010d9e2 | 2200 | #endif |
QL | 9:ca2e6010d9e2 | 2201 | } |
QL | 9:ca2e6010d9e2 | 2202 | |
QL | 9:ca2e6010d9e2 | 2203 | } // extern "C" |
QL | 9:ca2e6010d9e2 | 2204 | |
QL | 9:ca2e6010d9e2 | 2205 | #ifndef QK_NO_MUTEX |
QL | 9:ca2e6010d9e2 | 2206 | |
QL | 9:ca2e6010d9e2 | 2207 | // "qk_mutex.cpp" ============================================================ |
QL | 9:ca2e6010d9e2 | 2208 | /// \brief QK::mutexLock()/QK::mutexUnlock() implementation. |
QL | 9:ca2e6010d9e2 | 2209 | |
QL | 9:ca2e6010d9e2 | 2210 | // package-scope objects ----------------------------------------------------- |
QL | 9:ca2e6010d9e2 | 2211 | extern "C" { |
QL | 9:ca2e6010d9e2 | 2212 | uint8_t QK_ceilingPrio_; // ceiling priority of a mutex |
QL | 9:ca2e6010d9e2 | 2213 | } |
QL | 9:ca2e6010d9e2 | 2214 | |
QL | 9:ca2e6010d9e2 | 2215 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 2216 | |
QL | 9:ca2e6010d9e2 | 2217 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2218 | QMutex QK::mutexLock(uint8_t const prioCeiling) { |
QL | 9:ca2e6010d9e2 | 2219 | QF_CRIT_STAT_ |
QL | 9:ca2e6010d9e2 | 2220 | QF_CRIT_ENTRY_(); |
QL | 9:ca2e6010d9e2 | 2221 | uint8_t mutex = QK_ceilingPrio_; // original QK priority ceiling to return |
QL | 9:ca2e6010d9e2 | 2222 | if (QK_ceilingPrio_ < prioCeiling) { |
QL | 9:ca2e6010d9e2 | 2223 | QK_ceilingPrio_ = prioCeiling; // raise the QK priority ceiling |
QL | 9:ca2e6010d9e2 | 2224 | } |
QL | 9:ca2e6010d9e2 | 2225 | |
QL | 9:ca2e6010d9e2 | 2226 | QS_BEGIN_NOCRIT_(QS_QK_MUTEX_LOCK, |
QL | 9:ca2e6010d9e2 | 2227 | static_cast<void *>(0), static_cast<void *>(0)) |
QL | 9:ca2e6010d9e2 | 2228 | QS_TIME_(); // timestamp |
QL | 9:ca2e6010d9e2 | 2229 | QS_U8_(mutex); // the original priority |
QL | 9:ca2e6010d9e2 | 2230 | QS_U8_(QK_ceilingPrio_); // the current priority ceiling |
QL | 9:ca2e6010d9e2 | 2231 | QS_END_NOCRIT_() |
QL | 9:ca2e6010d9e2 | 2232 | |
QL | 9:ca2e6010d9e2 | 2233 | QF_CRIT_EXIT_(); |
QL | 9:ca2e6010d9e2 | 2234 | return mutex; |
QL | 9:ca2e6010d9e2 | 2235 | } |
QL | 9:ca2e6010d9e2 | 2236 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2237 | void QK::mutexUnlock(QMutex mutex) { |
QL | 9:ca2e6010d9e2 | 2238 | QF_CRIT_STAT_ |
QL | 9:ca2e6010d9e2 | 2239 | QF_CRIT_ENTRY_(); |
QL | 9:ca2e6010d9e2 | 2240 | |
QL | 9:ca2e6010d9e2 | 2241 | QS_BEGIN_NOCRIT_(QS_QK_MUTEX_UNLOCK, |
QL | 9:ca2e6010d9e2 | 2242 | static_cast<void *>(0), static_cast<void *>(0)) |
QL | 9:ca2e6010d9e2 | 2243 | QS_TIME_(); // timestamp |
QL | 9:ca2e6010d9e2 | 2244 | QS_U8_(mutex); // the original priority |
QL | 9:ca2e6010d9e2 | 2245 | QS_U8_(QK_ceilingPrio_); // the current priority ceiling |
QL | 9:ca2e6010d9e2 | 2246 | QS_END_NOCRIT_() |
QL | 9:ca2e6010d9e2 | 2247 | |
QL | 9:ca2e6010d9e2 | 2248 | if (QK_ceilingPrio_ > mutex) { |
QL | 9:ca2e6010d9e2 | 2249 | QK_ceilingPrio_ = mutex; // restore the saved priority ceiling |
QL | 9:ca2e6010d9e2 | 2250 | mutex = QK_schedPrio_(); // reuse 'mutex' to hold priority |
QL | 9:ca2e6010d9e2 | 2251 | if (mutex != static_cast<uint8_t>(0)) { |
QL | 9:ca2e6010d9e2 | 2252 | QK_sched_(mutex); |
QL | 9:ca2e6010d9e2 | 2253 | } |
QL | 9:ca2e6010d9e2 | 2254 | } |
QL | 9:ca2e6010d9e2 | 2255 | QF_CRIT_EXIT_(); |
QL | 9:ca2e6010d9e2 | 2256 | } |
QL | 9:ca2e6010d9e2 | 2257 | |
QL | 9:ca2e6010d9e2 | 2258 | QP_END_ |
QL | 9:ca2e6010d9e2 | 2259 | |
QL | 9:ca2e6010d9e2 | 2260 | #endif // QK_NO_MUTEX |
QL | 9:ca2e6010d9e2 | 2261 | |
QL | 9:ca2e6010d9e2 | 2262 | #else // QK_PREEMPTIVE |
QL | 9:ca2e6010d9e2 | 2263 | |
QL | 9:ca2e6010d9e2 | 2264 | // "qvanilla.cpp" ============================================================ |
QL | 9:ca2e6010d9e2 | 2265 | /// \brief "vanilla" cooperative kernel, |
QL | 9:ca2e6010d9e2 | 2266 | /// QActive::start(), QActive::stop(), and QF::run() implementation. |
QL | 9:ca2e6010d9e2 | 2267 | |
QL | 9:ca2e6010d9e2 | 2268 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 2269 | |
QL | 9:ca2e6010d9e2 | 2270 | // Package-scope objects ----------------------------------------------------- |
QL | 9:ca2e6010d9e2 | 2271 | extern "C" { |
QL | 9:ca2e6010d9e2 | 2272 | #if (QF_MAX_ACTIVE <= 8) |
QL | 9:ca2e6010d9e2 | 2273 | QPSet8 QF_readySet_; // ready set of active objects |
QL | 9:ca2e6010d9e2 | 2274 | #else |
QL | 9:ca2e6010d9e2 | 2275 | QPSet64 QF_readySet_; // ready set of active objects |
QL | 9:ca2e6010d9e2 | 2276 | #endif |
QL | 9:ca2e6010d9e2 | 2277 | |
QL | 9:ca2e6010d9e2 | 2278 | uint8_t QF_currPrio_; ///< current task/interrupt priority |
QL | 9:ca2e6010d9e2 | 2279 | uint8_t QF_intNest_; ///< interrupt nesting level |
QL | 9:ca2e6010d9e2 | 2280 | |
QL | 9:ca2e6010d9e2 | 2281 | } // extern "C" |
QL | 9:ca2e6010d9e2 | 2282 | |
QL | 9:ca2e6010d9e2 | 2283 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2284 | void QF::init(void) { |
QL | 9:ca2e6010d9e2 | 2285 | // nothing to do for the "vanilla" kernel |
QL | 9:ca2e6010d9e2 | 2286 | } |
QL | 9:ca2e6010d9e2 | 2287 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2288 | void QF::stop(void) { |
QL | 9:ca2e6010d9e2 | 2289 | onCleanup(); // cleanup callback |
QL | 9:ca2e6010d9e2 | 2290 | // nothing else to do for the "vanilla" kernel |
QL | 9:ca2e6010d9e2 | 2291 | } |
QL | 9:ca2e6010d9e2 | 2292 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2293 | int16_t QF::run(void) { |
QL | 9:ca2e6010d9e2 | 2294 | onStartup(); // startup callback |
QL | 9:ca2e6010d9e2 | 2295 | |
QL | 9:ca2e6010d9e2 | 2296 | for (;;) { // the bacground loop |
QL | 9:ca2e6010d9e2 | 2297 | QF_INT_DISABLE(); |
QL | 9:ca2e6010d9e2 | 2298 | if (QF_readySet_.notEmpty()) { |
QL | 9:ca2e6010d9e2 | 2299 | uint8_t p = QF_readySet_.findMax(); |
QL | 9:ca2e6010d9e2 | 2300 | QActive *a = active_[p]; |
QL | 9:ca2e6010d9e2 | 2301 | QF_currPrio_ = p; // save the current priority |
QL | 9:ca2e6010d9e2 | 2302 | QF_INT_ENABLE(); |
QL | 9:ca2e6010d9e2 | 2303 | |
QL | 9:ca2e6010d9e2 | 2304 | QEvt const *e = a->get_(); // get the next event for this AO |
QL | 9:ca2e6010d9e2 | 2305 | a->dispatch(e); // dispatch evt to the HSM |
QL | 9:ca2e6010d9e2 | 2306 | gc(e); // determine if event is garbage and collect it if so |
QL | 9:ca2e6010d9e2 | 2307 | } |
QL | 9:ca2e6010d9e2 | 2308 | else { |
QL | 9:ca2e6010d9e2 | 2309 | onIdle(); // see NOTE01 |
QL | 9:ca2e6010d9e2 | 2310 | } |
QL | 9:ca2e6010d9e2 | 2311 | } |
QL | 9:ca2e6010d9e2 | 2312 | // this unreachable return is to make the compiler happy |
QL | 9:ca2e6010d9e2 | 2313 | return static_cast<int16_t>(0); |
QL | 9:ca2e6010d9e2 | 2314 | } |
QL | 9:ca2e6010d9e2 | 2315 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2316 | void QActive::start(uint8_t const prio, |
QL | 9:ca2e6010d9e2 | 2317 | QEvt const *qSto[], uint32_t const qLen, |
QL | 9:ca2e6010d9e2 | 2318 | void * const stkSto, uint32_t const, |
QL | 9:ca2e6010d9e2 | 2319 | QEvt const * const ie) |
QL | 9:ca2e6010d9e2 | 2320 | { |
QL | 9:ca2e6010d9e2 | 2321 | Q_REQUIRE((u8_0 < prio) && (prio <= static_cast<uint8_t>(QF_MAX_ACTIVE)) |
QL | 9:ca2e6010d9e2 | 2322 | && (stkSto == null_void)); // does not need per-actor stack |
QL | 9:ca2e6010d9e2 | 2323 | |
QL | 9:ca2e6010d9e2 | 2324 | m_eQueue.init(qSto, static_cast<QEQueueCtr>(qLen)); // initialize QEQueue |
QL | 9:ca2e6010d9e2 | 2325 | m_prio = prio; // set the QF priority of this active object |
QL | 9:ca2e6010d9e2 | 2326 | QF::add_(this); // make QF aware of this active object |
QL | 9:ca2e6010d9e2 | 2327 | init(ie); // execute initial transition |
QL | 9:ca2e6010d9e2 | 2328 | |
QL | 9:ca2e6010d9e2 | 2329 | QS_FLUSH(); // flush the trace buffer to the host |
QL | 9:ca2e6010d9e2 | 2330 | } |
QL | 9:ca2e6010d9e2 | 2331 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2332 | void QActive::stop(void) { |
QL | 9:ca2e6010d9e2 | 2333 | QF::remove_(this); |
QL | 9:ca2e6010d9e2 | 2334 | } |
QL | 9:ca2e6010d9e2 | 2335 | |
QL | 9:ca2e6010d9e2 | 2336 | QP_END_ |
QL | 9:ca2e6010d9e2 | 2337 | |
QL | 9:ca2e6010d9e2 | 2338 | ////////////////////////////////////////////////////////////////////////////// |
QL | 9:ca2e6010d9e2 | 2339 | // NOTE01: |
QL | 9:ca2e6010d9e2 | 2340 | // QF::onIdle() must be called with interrupts DISABLED because the |
QL | 9:ca2e6010d9e2 | 2341 | // determination of the idle condition (no events in the queues) can change |
QL | 9:ca2e6010d9e2 | 2342 | // at any time by an interrupt posting events to a queue. The QF::onIdle() |
QL | 9:ca2e6010d9e2 | 2343 | // MUST enable interrups internally, perhaps at the same time as putting the |
QL | 9:ca2e6010d9e2 | 2344 | // CPU into a power-saving mode. |
QL | 9:ca2e6010d9e2 | 2345 | // |
QL | 9:ca2e6010d9e2 | 2346 | |
QL | 9:ca2e6010d9e2 | 2347 | extern "C" { |
QL | 9:ca2e6010d9e2 | 2348 | |
QL | 9:ca2e6010d9e2 | 2349 | void QK_sched_(uint8_t p) { // dummy empty definition for qk_port.s |
QL | 9:ca2e6010d9e2 | 2350 | (void)p; |
QL | 9:ca2e6010d9e2 | 2351 | } |
QL | 9:ca2e6010d9e2 | 2352 | |
QL | 9:ca2e6010d9e2 | 2353 | uint8_t QK_schedPrio_(void) { // dummy empty definition for qk_port.s |
QL | 9:ca2e6010d9e2 | 2354 | return static_cast<uint8_t>(0U); |
QL | 9:ca2e6010d9e2 | 2355 | } |
QL | 9:ca2e6010d9e2 | 2356 | |
QL | 9:ca2e6010d9e2 | 2357 | } // extern "C" |
QL | 9:ca2e6010d9e2 | 2358 | |
QL | 9:ca2e6010d9e2 | 2359 | #endif // QK_PREEMPTIVE |
QL | 9:ca2e6010d9e2 | 2360 | |
QL | 9:ca2e6010d9e2 | 2361 | ////////////////////////////////////////////////////////////////////////////// |
QL | 9:ca2e6010d9e2 | 2362 | #ifdef Q_SPY |
QL | 9:ca2e6010d9e2 | 2363 | |
QL | 9:ca2e6010d9e2 | 2364 | // "qs_pkg.h" ================================================================ |
QL | 9:ca2e6010d9e2 | 2365 | /// \brief Internal (package scope) QS/C++ interface. |
QL | 9:ca2e6010d9e2 | 2366 | |
QL | 9:ca2e6010d9e2 | 2367 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 2368 | |
QL | 9:ca2e6010d9e2 | 2369 | /// \brief QS ring buffer counter and offset type |
QL | 9:ca2e6010d9e2 | 2370 | typedef uint16_t QSCtr; |
QL | 9:ca2e6010d9e2 | 2371 | |
QL | 9:ca2e6010d9e2 | 2372 | /// \brief Internal QS macro to insert an un-escaped byte into |
QL | 9:ca2e6010d9e2 | 2373 | /// the QS buffer |
QL | 9:ca2e6010d9e2 | 2374 | //// |
QL | 9:ca2e6010d9e2 | 2375 | #define QS_INSERT_BYTE(b_) \ |
QL | 9:ca2e6010d9e2 | 2376 | QS_PTR_AT_(QS_head_) = (b_); \ |
QL | 9:ca2e6010d9e2 | 2377 | ++QS_head_; \ |
QL | 9:ca2e6010d9e2 | 2378 | if (QS_head_ == QS_end_) { \ |
QL | 9:ca2e6010d9e2 | 2379 | QS_head_ = static_cast<QSCtr>(0); \ |
QL | 9:ca2e6010d9e2 | 2380 | } \ |
QL | 9:ca2e6010d9e2 | 2381 | ++QS_used_; |
QL | 9:ca2e6010d9e2 | 2382 | |
QL | 9:ca2e6010d9e2 | 2383 | /// \brief Internal QS macro to insert an escaped byte into the QS buffer |
QL | 9:ca2e6010d9e2 | 2384 | #define QS_INSERT_ESC_BYTE(b_) \ |
QL | 9:ca2e6010d9e2 | 2385 | QS_chksum_ = static_cast<uint8_t>(QS_chksum_ + (b_)); \ |
QL | 9:ca2e6010d9e2 | 2386 | if (((b_) == QS_FRAME) || ((b_) == QS_ESC)) { \ |
QL | 9:ca2e6010d9e2 | 2387 | QS_INSERT_BYTE(QS_ESC) \ |
QL | 9:ca2e6010d9e2 | 2388 | QS_INSERT_BYTE(static_cast<uint8_t>((b_) ^ QS_ESC_XOR)) \ |
QL | 9:ca2e6010d9e2 | 2389 | } \ |
QL | 9:ca2e6010d9e2 | 2390 | else { \ |
QL | 9:ca2e6010d9e2 | 2391 | QS_INSERT_BYTE(b_) \ |
QL | 9:ca2e6010d9e2 | 2392 | } |
QL | 9:ca2e6010d9e2 | 2393 | |
QL | 9:ca2e6010d9e2 | 2394 | /// \brief Internal QS macro to insert a escaped checksum byte into |
QL | 9:ca2e6010d9e2 | 2395 | /// the QS buffer |
QL | 9:ca2e6010d9e2 | 2396 | #define QS_INSERT_CHKSUM_BYTE() \ |
QL | 9:ca2e6010d9e2 | 2397 | QS_chksum_ = static_cast<uint8_t>(~QS_chksum_); \ |
QL | 9:ca2e6010d9e2 | 2398 | if ((QS_chksum_ == QS_FRAME) || (QS_chksum_ == QS_ESC)) { \ |
QL | 9:ca2e6010d9e2 | 2399 | QS_INSERT_BYTE(QS_ESC) \ |
QL | 9:ca2e6010d9e2 | 2400 | QS_INSERT_BYTE(static_cast<uint8_t>(QS_chksum_ ^ QS_ESC_XOR)) \ |
QL | 9:ca2e6010d9e2 | 2401 | } \ |
QL | 9:ca2e6010d9e2 | 2402 | else { \ |
QL | 9:ca2e6010d9e2 | 2403 | QS_INSERT_BYTE(QS_chksum_) \ |
QL | 9:ca2e6010d9e2 | 2404 | } |
QL | 9:ca2e6010d9e2 | 2405 | |
QL | 9:ca2e6010d9e2 | 2406 | |
QL | 9:ca2e6010d9e2 | 2407 | /// \brief Internal QS macro to access the QS ring buffer |
QL | 9:ca2e6010d9e2 | 2408 | /// |
QL | 9:ca2e6010d9e2 | 2409 | /// \note The QS buffer is allocated by the user and is accessed through the |
QL | 9:ca2e6010d9e2 | 2410 | /// pointer QS_ring_, which violates the MISRA-C 2004 Rule 17.4(req), pointer |
QL | 9:ca2e6010d9e2 | 2411 | /// arithmetic other than array indexing. Encapsulating this violation in a |
QL | 9:ca2e6010d9e2 | 2412 | /// macro allows to selectively suppress this specific deviation. |
QL | 9:ca2e6010d9e2 | 2413 | #define QS_PTR_AT_(i_) (QS_ring_[i_]) |
QL | 9:ca2e6010d9e2 | 2414 | |
QL | 9:ca2e6010d9e2 | 2415 | |
QL | 9:ca2e6010d9e2 | 2416 | /// \brief Frame character of the QS output protocol |
QL | 9:ca2e6010d9e2 | 2417 | uint8_t const QS_FRAME = static_cast<uint8_t>(0x7E); |
QL | 9:ca2e6010d9e2 | 2418 | |
QL | 9:ca2e6010d9e2 | 2419 | /// \brief Escape character of the QS output protocol |
QL | 9:ca2e6010d9e2 | 2420 | uint8_t const QS_ESC = static_cast<uint8_t>(0x7D); |
QL | 9:ca2e6010d9e2 | 2421 | |
QL | 9:ca2e6010d9e2 | 2422 | /// \brief Escape modifier of the QS output protocol |
QL | 9:ca2e6010d9e2 | 2423 | /// |
QL | 9:ca2e6010d9e2 | 2424 | /// The escaped byte is XOR-ed with the escape modifier before it is inserted |
QL | 9:ca2e6010d9e2 | 2425 | /// into the QS buffer. |
QL | 9:ca2e6010d9e2 | 2426 | uint8_t const QS_ESC_XOR = static_cast<uint8_t>(0x20); |
QL | 9:ca2e6010d9e2 | 2427 | |
QL | 9:ca2e6010d9e2 | 2428 | #ifndef Q_ROM_BYTE |
QL | 9:ca2e6010d9e2 | 2429 | /// \brief Macro to access a byte allocated in ROM |
QL | 9:ca2e6010d9e2 | 2430 | /// |
QL | 9:ca2e6010d9e2 | 2431 | /// Some compilers for Harvard-architecture MCUs, such as gcc for AVR, do |
QL | 9:ca2e6010d9e2 | 2432 | /// not generate correct code for accessing data allocated in the program |
QL | 9:ca2e6010d9e2 | 2433 | /// space (ROM). The workaround for such compilers is to explictly add |
QL | 9:ca2e6010d9e2 | 2434 | /// assembly code to access each data element allocated in the program |
QL | 9:ca2e6010d9e2 | 2435 | /// space. The macro Q_ROM_BYTE() retrieves a byte from the given ROM |
QL | 9:ca2e6010d9e2 | 2436 | /// address. |
QL | 9:ca2e6010d9e2 | 2437 | /// |
QL | 9:ca2e6010d9e2 | 2438 | /// The Q_ROM_BYTE() macro should be defined for the compilers that |
QL | 9:ca2e6010d9e2 | 2439 | /// cannot handle correctly data allocated in ROM (such as the gcc). |
QL | 9:ca2e6010d9e2 | 2440 | /// If the macro is left undefined, the default definition simply returns |
QL | 9:ca2e6010d9e2 | 2441 | /// the argument and lets the compiler generate the correct code. |
QL | 9:ca2e6010d9e2 | 2442 | #define Q_ROM_BYTE(rom_var_) (rom_var_) |
QL | 9:ca2e6010d9e2 | 2443 | #endif |
QL | 9:ca2e6010d9e2 | 2444 | |
QL | 9:ca2e6010d9e2 | 2445 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2446 | extern uint8_t *QS_ring_; ///< pointer to the start of the ring buffer |
QL | 9:ca2e6010d9e2 | 2447 | extern QSCtr QS_end_; ///< offset of the end of the ring buffer |
QL | 9:ca2e6010d9e2 | 2448 | extern QSCtr QS_head_; ///< offset to where next byte will be inserted |
QL | 9:ca2e6010d9e2 | 2449 | extern QSCtr QS_tail_; ///< offset of where next event will be extracted |
QL | 9:ca2e6010d9e2 | 2450 | extern QSCtr QS_used_; ///< number of bytes currently in the ring buffer |
QL | 9:ca2e6010d9e2 | 2451 | extern uint8_t QS_seq_; ///< the record sequence number |
QL | 9:ca2e6010d9e2 | 2452 | extern uint8_t QS_chksum_; ///< the checksum of the current record |
QL | 9:ca2e6010d9e2 | 2453 | extern uint8_t QS_full_; ///< the ring buffer is temporarily full |
QL | 9:ca2e6010d9e2 | 2454 | |
QL | 9:ca2e6010d9e2 | 2455 | QP_END_ |
QL | 9:ca2e6010d9e2 | 2456 | |
QL | 9:ca2e6010d9e2 | 2457 | |
QL | 9:ca2e6010d9e2 | 2458 | // "qs.cpp" ================================================================== |
QL | 9:ca2e6010d9e2 | 2459 | /// \brief QS internal variables definitions and core QS functions |
QL | 9:ca2e6010d9e2 | 2460 | /// implementations. |
QL | 9:ca2e6010d9e2 | 2461 | |
QL | 9:ca2e6010d9e2 | 2462 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 2463 | |
QL | 9:ca2e6010d9e2 | 2464 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2465 | uint8_t QS::glbFilter_[32]; // global QS filter |
QL | 9:ca2e6010d9e2 | 2466 | |
QL | 9:ca2e6010d9e2 | 2467 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2468 | uint8_t *QS_ring_; // pointer to the start of the ring buffer |
QL | 9:ca2e6010d9e2 | 2469 | QSCtr QS_end_; // offset of the end of the ring buffer |
QL | 9:ca2e6010d9e2 | 2470 | QSCtr QS_head_; // offset to where next byte will be inserted |
QL | 9:ca2e6010d9e2 | 2471 | QSCtr QS_tail_; // offset of where next byte will be extracted |
QL | 9:ca2e6010d9e2 | 2472 | QSCtr QS_used_; // number of bytes currently in the ring buffer |
QL | 9:ca2e6010d9e2 | 2473 | uint8_t QS_seq_; // the record sequence number |
QL | 9:ca2e6010d9e2 | 2474 | uint8_t QS_chksum_; // the checksum of the current record |
QL | 9:ca2e6010d9e2 | 2475 | uint8_t QS_full_; // the ring buffer is temporarily full |
QL | 9:ca2e6010d9e2 | 2476 | |
QL | 9:ca2e6010d9e2 | 2477 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2478 | char_t const Q_ROM * Q_ROM_VAR QS::getVersion(void) { |
QL | 9:ca2e6010d9e2 | 2479 | uint8_t const u8_zero = static_cast<uint8_t>('0'); |
QL | 9:ca2e6010d9e2 | 2480 | static char_t const Q_ROM Q_ROM_VAR version[] = { |
QL | 9:ca2e6010d9e2 | 2481 | static_cast<char_t>(((QP_VERSION >> 12) & 0xFU) + u8_zero), |
QL | 9:ca2e6010d9e2 | 2482 | static_cast<char_t>('.'), |
QL | 9:ca2e6010d9e2 | 2483 | static_cast<char_t>(((QP_VERSION >> 8) & 0xFU) + u8_zero), |
QL | 9:ca2e6010d9e2 | 2484 | static_cast<char_t>('.'), |
QL | 9:ca2e6010d9e2 | 2485 | static_cast<char_t>(((QP_VERSION >> 4) & 0xFU) + u8_zero), |
QL | 9:ca2e6010d9e2 | 2486 | static_cast<char_t>((QP_VERSION & 0xFU) + u8_zero), |
QL | 9:ca2e6010d9e2 | 2487 | static_cast<char_t>('\0') |
QL | 9:ca2e6010d9e2 | 2488 | }; |
QL | 9:ca2e6010d9e2 | 2489 | return version; |
QL | 9:ca2e6010d9e2 | 2490 | } |
QL | 9:ca2e6010d9e2 | 2491 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2492 | void QS::initBuf(uint8_t sto[], uint32_t const stoSize) { |
QL | 9:ca2e6010d9e2 | 2493 | QS_ring_ = &sto[0]; |
QL | 9:ca2e6010d9e2 | 2494 | QS_end_ = static_cast<QSCtr>(stoSize); |
QL | 9:ca2e6010d9e2 | 2495 | } |
QL | 9:ca2e6010d9e2 | 2496 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2497 | void QS::filterOn(uint8_t const rec) { |
QL | 9:ca2e6010d9e2 | 2498 | if (rec == QS_ALL_RECORDS) { |
QL | 9:ca2e6010d9e2 | 2499 | uint8_t i; |
QL | 9:ca2e6010d9e2 | 2500 | for (i = static_cast<uint8_t>(0); |
QL | 9:ca2e6010d9e2 | 2501 | i < static_cast<uint8_t>(sizeof(glbFilter_)); |
QL | 9:ca2e6010d9e2 | 2502 | ++i) |
QL | 9:ca2e6010d9e2 | 2503 | { |
QL | 9:ca2e6010d9e2 | 2504 | glbFilter_[i] = static_cast<uint8_t>(0xFF); |
QL | 9:ca2e6010d9e2 | 2505 | } |
QL | 9:ca2e6010d9e2 | 2506 | } |
QL | 9:ca2e6010d9e2 | 2507 | else { |
QL | 9:ca2e6010d9e2 | 2508 | glbFilter_[rec >> 3] |= |
QL | 9:ca2e6010d9e2 | 2509 | static_cast<uint8_t>(1U << (rec & static_cast<uint8_t>(0x07))); |
QL | 9:ca2e6010d9e2 | 2510 | } |
QL | 9:ca2e6010d9e2 | 2511 | } |
QL | 9:ca2e6010d9e2 | 2512 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2513 | void QS::filterOff(uint8_t const rec) { |
QL | 9:ca2e6010d9e2 | 2514 | if (rec == QS_ALL_RECORDS) { |
QL | 9:ca2e6010d9e2 | 2515 | uint8_t i; |
QL | 9:ca2e6010d9e2 | 2516 | for (i = static_cast<uint8_t>(0); |
QL | 9:ca2e6010d9e2 | 2517 | i < static_cast<uint8_t>(sizeof(glbFilter_)); |
QL | 9:ca2e6010d9e2 | 2518 | ++i) |
QL | 9:ca2e6010d9e2 | 2519 | { |
QL | 9:ca2e6010d9e2 | 2520 | glbFilter_[i] = static_cast<uint8_t>(0); |
QL | 9:ca2e6010d9e2 | 2521 | } |
QL | 9:ca2e6010d9e2 | 2522 | } |
QL | 9:ca2e6010d9e2 | 2523 | else { |
QL | 9:ca2e6010d9e2 | 2524 | glbFilter_[rec >> 3] &= static_cast<uint8_t>( |
QL | 9:ca2e6010d9e2 | 2525 | ~static_cast<uint8_t>((1U << (rec & static_cast<uint8_t>(0x07))))); |
QL | 9:ca2e6010d9e2 | 2526 | } |
QL | 9:ca2e6010d9e2 | 2527 | } |
QL | 9:ca2e6010d9e2 | 2528 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2529 | void QS::begin(uint8_t const rec) { |
QL | 9:ca2e6010d9e2 | 2530 | QS_chksum_ = static_cast<uint8_t>(0); // clear the checksum |
QL | 9:ca2e6010d9e2 | 2531 | ++QS_seq_; // always increment the sequence number |
QL | 9:ca2e6010d9e2 | 2532 | QS_INSERT_ESC_BYTE(QS_seq_) // store the sequence number |
QL | 9:ca2e6010d9e2 | 2533 | QS_INSERT_ESC_BYTE(rec) // store the record ID |
QL | 9:ca2e6010d9e2 | 2534 | } |
QL | 9:ca2e6010d9e2 | 2535 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2536 | void QS::end(void) { |
QL | 9:ca2e6010d9e2 | 2537 | QS_INSERT_CHKSUM_BYTE() |
QL | 9:ca2e6010d9e2 | 2538 | QS_INSERT_BYTE(QS_FRAME) |
QL | 9:ca2e6010d9e2 | 2539 | if (QS_used_ > QS_end_) { // overrun over the old data? |
QL | 9:ca2e6010d9e2 | 2540 | QS_tail_ = QS_head_; // shift the tail to the old data |
QL | 9:ca2e6010d9e2 | 2541 | QS_used_ = QS_end_; // the whole buffer is used |
QL | 9:ca2e6010d9e2 | 2542 | } |
QL | 9:ca2e6010d9e2 | 2543 | } |
QL | 9:ca2e6010d9e2 | 2544 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2545 | void QS::u8(uint8_t const format, uint8_t const d) { |
QL | 9:ca2e6010d9e2 | 2546 | QS_INSERT_ESC_BYTE(format) |
QL | 9:ca2e6010d9e2 | 2547 | QS_INSERT_ESC_BYTE(d) |
QL | 9:ca2e6010d9e2 | 2548 | } |
QL | 9:ca2e6010d9e2 | 2549 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2550 | void QS::u16(uint8_t const format, uint16_t d) { |
QL | 9:ca2e6010d9e2 | 2551 | QS_INSERT_ESC_BYTE(format) |
QL | 9:ca2e6010d9e2 | 2552 | QS_INSERT_ESC_BYTE(static_cast<uint8_t>(d)) |
QL | 9:ca2e6010d9e2 | 2553 | d >>= 8; |
QL | 9:ca2e6010d9e2 | 2554 | QS_INSERT_ESC_BYTE(static_cast<uint8_t>(d)) |
QL | 9:ca2e6010d9e2 | 2555 | } |
QL | 9:ca2e6010d9e2 | 2556 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2557 | void QS::u32(uint8_t const format, uint32_t d) { |
QL | 9:ca2e6010d9e2 | 2558 | QS_INSERT_ESC_BYTE(format) |
QL | 9:ca2e6010d9e2 | 2559 | QS_INSERT_ESC_BYTE(static_cast<uint8_t>(d)) |
QL | 9:ca2e6010d9e2 | 2560 | d >>= 8; |
QL | 9:ca2e6010d9e2 | 2561 | QS_INSERT_ESC_BYTE(static_cast<uint8_t>(d)) |
QL | 9:ca2e6010d9e2 | 2562 | d >>= 8; |
QL | 9:ca2e6010d9e2 | 2563 | QS_INSERT_ESC_BYTE(static_cast<uint8_t>(d)) |
QL | 9:ca2e6010d9e2 | 2564 | d >>= 8; |
QL | 9:ca2e6010d9e2 | 2565 | QS_INSERT_ESC_BYTE(static_cast<uint8_t>(d)) |
QL | 9:ca2e6010d9e2 | 2566 | } |
QL | 9:ca2e6010d9e2 | 2567 | |
QL | 9:ca2e6010d9e2 | 2568 | QP_END_ |
QL | 9:ca2e6010d9e2 | 2569 | |
QL | 9:ca2e6010d9e2 | 2570 | |
QL | 9:ca2e6010d9e2 | 2571 | // "qs_.cpp" ================================================================= |
QL | 9:ca2e6010d9e2 | 2572 | /// \brief QS functions for internal use inside QP components |
QL | 9:ca2e6010d9e2 | 2573 | |
QL | 9:ca2e6010d9e2 | 2574 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 2575 | |
QL | 9:ca2e6010d9e2 | 2576 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2577 | void const *QS::smObj_; // local state machine for QEP filter |
QL | 9:ca2e6010d9e2 | 2578 | void const *QS::aoObj_; // local active object for QF filter |
QL | 9:ca2e6010d9e2 | 2579 | void const *QS::mpObj_; // local event pool for QF filter |
QL | 9:ca2e6010d9e2 | 2580 | void const *QS::eqObj_; // local raw queue for QF filter |
QL | 9:ca2e6010d9e2 | 2581 | void const *QS::teObj_; // local time event for QF filter |
QL | 9:ca2e6010d9e2 | 2582 | void const *QS::apObj_; // local object Application filter |
QL | 9:ca2e6010d9e2 | 2583 | |
QL | 9:ca2e6010d9e2 | 2584 | QSTimeCtr QS::tickCtr_; // tick counter for the QS_QF_TICK record |
QL | 9:ca2e6010d9e2 | 2585 | |
QL | 9:ca2e6010d9e2 | 2586 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2587 | void QS::u8_(uint8_t const d) { |
QL | 9:ca2e6010d9e2 | 2588 | QS_INSERT_ESC_BYTE(d) |
QL | 9:ca2e6010d9e2 | 2589 | } |
QL | 9:ca2e6010d9e2 | 2590 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2591 | void QS::u16_(uint16_t d) { |
QL | 9:ca2e6010d9e2 | 2592 | QS_INSERT_ESC_BYTE(static_cast<uint8_t>(d)) |
QL | 9:ca2e6010d9e2 | 2593 | d >>= 8; |
QL | 9:ca2e6010d9e2 | 2594 | QS_INSERT_ESC_BYTE(static_cast<uint8_t>(d)) |
QL | 9:ca2e6010d9e2 | 2595 | } |
QL | 9:ca2e6010d9e2 | 2596 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2597 | void QS::u32_(uint32_t d) { |
QL | 9:ca2e6010d9e2 | 2598 | QS_INSERT_ESC_BYTE(static_cast<uint8_t>(d)) |
QL | 9:ca2e6010d9e2 | 2599 | d >>= 8; |
QL | 9:ca2e6010d9e2 | 2600 | QS_INSERT_ESC_BYTE(static_cast<uint8_t>(d)) |
QL | 9:ca2e6010d9e2 | 2601 | d >>= 8; |
QL | 9:ca2e6010d9e2 | 2602 | QS_INSERT_ESC_BYTE(static_cast<uint8_t>(d)) |
QL | 9:ca2e6010d9e2 | 2603 | d >>= 8; |
QL | 9:ca2e6010d9e2 | 2604 | QS_INSERT_ESC_BYTE(static_cast<uint8_t>(d)) |
QL | 9:ca2e6010d9e2 | 2605 | } |
QL | 9:ca2e6010d9e2 | 2606 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2607 | void QS::str_(char_t const *s) { |
QL | 9:ca2e6010d9e2 | 2608 | uint8_t b = static_cast<uint8_t>(*s); |
QL | 9:ca2e6010d9e2 | 2609 | while (b != static_cast<uint8_t>(0)) { |
QL | 9:ca2e6010d9e2 | 2610 | // ASCII characters don't need escaping |
QL | 9:ca2e6010d9e2 | 2611 | QS_chksum_ = static_cast<uint8_t>(QS_chksum_ + b); |
QL | 9:ca2e6010d9e2 | 2612 | QS_INSERT_BYTE(b) |
QL | 9:ca2e6010d9e2 | 2613 | ++s; |
QL | 9:ca2e6010d9e2 | 2614 | b = static_cast<uint8_t>(*s); |
QL | 9:ca2e6010d9e2 | 2615 | } |
QL | 9:ca2e6010d9e2 | 2616 | QS_INSERT_BYTE(static_cast<uint8_t>(0)) |
QL | 9:ca2e6010d9e2 | 2617 | } |
QL | 9:ca2e6010d9e2 | 2618 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2619 | void QS::str_ROM_(char_t const Q_ROM * Q_ROM_VAR s) { |
QL | 9:ca2e6010d9e2 | 2620 | uint8_t b = static_cast<uint8_t>(Q_ROM_BYTE(*s)); |
QL | 9:ca2e6010d9e2 | 2621 | while (b != static_cast<uint8_t>(0)) { |
QL | 9:ca2e6010d9e2 | 2622 | // ASCII characters don't need escaping |
QL | 9:ca2e6010d9e2 | 2623 | QS_chksum_ = static_cast<uint8_t>(QS_chksum_ + b); |
QL | 9:ca2e6010d9e2 | 2624 | QS_INSERT_BYTE(b) |
QL | 9:ca2e6010d9e2 | 2625 | ++s; |
QL | 9:ca2e6010d9e2 | 2626 | b = static_cast<uint8_t>(Q_ROM_BYTE(*s)); |
QL | 9:ca2e6010d9e2 | 2627 | } |
QL | 9:ca2e6010d9e2 | 2628 | QS_INSERT_BYTE(static_cast<uint8_t>(0)) |
QL | 9:ca2e6010d9e2 | 2629 | } |
QL | 9:ca2e6010d9e2 | 2630 | |
QL | 9:ca2e6010d9e2 | 2631 | QP_END_ |
QL | 9:ca2e6010d9e2 | 2632 | |
QL | 9:ca2e6010d9e2 | 2633 | // "qs_blk.cpp" ============================================================== |
QL | 9:ca2e6010d9e2 | 2634 | /// \brief QS::getBlock() implementation |
QL | 9:ca2e6010d9e2 | 2635 | |
QL | 9:ca2e6010d9e2 | 2636 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 2637 | |
QL | 9:ca2e6010d9e2 | 2638 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2639 | // get up to *pn bytes of contiguous memory |
QL | 9:ca2e6010d9e2 | 2640 | uint8_t const *QS::getBlock(uint16_t * const pNbytes) { |
QL | 9:ca2e6010d9e2 | 2641 | uint8_t *block; |
QL | 9:ca2e6010d9e2 | 2642 | if (QS_used_ == static_cast<QSCtr>(0)) { |
QL | 9:ca2e6010d9e2 | 2643 | *pNbytes = static_cast<uint16_t>(0); |
QL | 9:ca2e6010d9e2 | 2644 | block = static_cast<uint8_t *>(0); // no bytes to return right now |
QL | 9:ca2e6010d9e2 | 2645 | } |
QL | 9:ca2e6010d9e2 | 2646 | else { |
QL | 9:ca2e6010d9e2 | 2647 | QSCtr n = static_cast<QSCtr>(QS_end_ - QS_tail_); |
QL | 9:ca2e6010d9e2 | 2648 | if (n > QS_used_) { |
QL | 9:ca2e6010d9e2 | 2649 | n = QS_used_; |
QL | 9:ca2e6010d9e2 | 2650 | } |
QL | 9:ca2e6010d9e2 | 2651 | if (n > static_cast<QSCtr>(*pNbytes)) { |
QL | 9:ca2e6010d9e2 | 2652 | n = static_cast<QSCtr>(*pNbytes); |
QL | 9:ca2e6010d9e2 | 2653 | } |
QL | 9:ca2e6010d9e2 | 2654 | *pNbytes = static_cast<uint16_t>(n); |
QL | 9:ca2e6010d9e2 | 2655 | QS_used_ = static_cast<QSCtr>(QS_used_ - n); |
QL | 9:ca2e6010d9e2 | 2656 | QSCtr t = QS_tail_; |
QL | 9:ca2e6010d9e2 | 2657 | QS_tail_ = static_cast<QSCtr>(QS_tail_ + n); |
QL | 9:ca2e6010d9e2 | 2658 | if (QS_tail_ == QS_end_) { |
QL | 9:ca2e6010d9e2 | 2659 | QS_tail_ = static_cast<QSCtr>(0); |
QL | 9:ca2e6010d9e2 | 2660 | } |
QL | 9:ca2e6010d9e2 | 2661 | block = &QS_PTR_AT_(t); |
QL | 9:ca2e6010d9e2 | 2662 | } |
QL | 9:ca2e6010d9e2 | 2663 | return block; |
QL | 9:ca2e6010d9e2 | 2664 | } |
QL | 9:ca2e6010d9e2 | 2665 | |
QL | 9:ca2e6010d9e2 | 2666 | QP_END_ |
QL | 9:ca2e6010d9e2 | 2667 | |
QL | 9:ca2e6010d9e2 | 2668 | // "qs_byte.cpp" ============================================================= |
QL | 9:ca2e6010d9e2 | 2669 | /// \brief QS::getByte() implementation |
QL | 9:ca2e6010d9e2 | 2670 | |
QL | 9:ca2e6010d9e2 | 2671 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 2672 | |
QL | 9:ca2e6010d9e2 | 2673 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2674 | uint16_t QS::getByte(void) { |
QL | 9:ca2e6010d9e2 | 2675 | uint16_t ret; |
QL | 9:ca2e6010d9e2 | 2676 | if (QS_used_ == static_cast<QSCtr>(0)) { |
QL | 9:ca2e6010d9e2 | 2677 | ret = QS_EOD; // set End-Of-Data |
QL | 9:ca2e6010d9e2 | 2678 | } |
QL | 9:ca2e6010d9e2 | 2679 | else { |
QL | 9:ca2e6010d9e2 | 2680 | ret = static_cast<uint16_t>(QS_PTR_AT_(QS_tail_)); // byte to return |
QL | 9:ca2e6010d9e2 | 2681 | ++QS_tail_; // advance the tail |
QL | 9:ca2e6010d9e2 | 2682 | if (QS_tail_ == QS_end_) { // tail wrap around? |
QL | 9:ca2e6010d9e2 | 2683 | QS_tail_ = static_cast<QSCtr>(0); |
QL | 9:ca2e6010d9e2 | 2684 | } |
QL | 9:ca2e6010d9e2 | 2685 | --QS_used_; // one less byte used |
QL | 9:ca2e6010d9e2 | 2686 | } |
QL | 9:ca2e6010d9e2 | 2687 | return ret; // return the byte or EOD |
QL | 9:ca2e6010d9e2 | 2688 | } |
QL | 9:ca2e6010d9e2 | 2689 | |
QL | 9:ca2e6010d9e2 | 2690 | QP_END_ |
QL | 9:ca2e6010d9e2 | 2691 | |
QL | 9:ca2e6010d9e2 | 2692 | |
QL | 9:ca2e6010d9e2 | 2693 | // "qs_f32.cpp" ============================================================== |
QL | 9:ca2e6010d9e2 | 2694 | /// \brief QS::f32() implementation |
QL | 9:ca2e6010d9e2 | 2695 | |
QL | 9:ca2e6010d9e2 | 2696 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 2697 | |
QL | 9:ca2e6010d9e2 | 2698 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2699 | void QS::f32(uint8_t const format, float32_t const d) { |
QL | 9:ca2e6010d9e2 | 2700 | union F32Rep { |
QL | 9:ca2e6010d9e2 | 2701 | float32_t f; |
QL | 9:ca2e6010d9e2 | 2702 | uint32_t u; |
QL | 9:ca2e6010d9e2 | 2703 | } fu32; |
QL | 9:ca2e6010d9e2 | 2704 | fu32.f = d; |
QL | 9:ca2e6010d9e2 | 2705 | |
QL | 9:ca2e6010d9e2 | 2706 | QS_INSERT_ESC_BYTE(format) |
QL | 9:ca2e6010d9e2 | 2707 | QS_INSERT_ESC_BYTE(static_cast<uint8_t>(fu32.u)) |
QL | 9:ca2e6010d9e2 | 2708 | fu32.u >>= 8; |
QL | 9:ca2e6010d9e2 | 2709 | QS_INSERT_ESC_BYTE(static_cast<uint8_t>(fu32.u)) |
QL | 9:ca2e6010d9e2 | 2710 | fu32.u >>= 8; |
QL | 9:ca2e6010d9e2 | 2711 | QS_INSERT_ESC_BYTE(static_cast<uint8_t>(fu32.u)) |
QL | 9:ca2e6010d9e2 | 2712 | fu32.u >>= 8; |
QL | 9:ca2e6010d9e2 | 2713 | QS_INSERT_ESC_BYTE(static_cast<uint8_t>(fu32.u)) |
QL | 9:ca2e6010d9e2 | 2714 | } |
QL | 9:ca2e6010d9e2 | 2715 | |
QL | 9:ca2e6010d9e2 | 2716 | QP_END_ |
QL | 9:ca2e6010d9e2 | 2717 | |
QL | 9:ca2e6010d9e2 | 2718 | |
QL | 9:ca2e6010d9e2 | 2719 | // "qs_mem.cpp" ============================================================== |
QL | 9:ca2e6010d9e2 | 2720 | /// \brief QS::mem() implementation |
QL | 9:ca2e6010d9e2 | 2721 | |
QL | 9:ca2e6010d9e2 | 2722 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 2723 | |
QL | 9:ca2e6010d9e2 | 2724 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2725 | void QS::mem(uint8_t const *blk, uint8_t size) { |
QL | 9:ca2e6010d9e2 | 2726 | QS_INSERT_BYTE(static_cast<uint8_t>(QS_MEM_T)) |
QL | 9:ca2e6010d9e2 | 2727 | QS_chksum_ = |
QL | 9:ca2e6010d9e2 | 2728 | static_cast<uint8_t>(QS_chksum_ + static_cast<uint8_t>(QS_MEM_T)); |
QL | 9:ca2e6010d9e2 | 2729 | QS_INSERT_ESC_BYTE(size) |
QL | 9:ca2e6010d9e2 | 2730 | while (size != static_cast<uint8_t>(0)) { |
QL | 9:ca2e6010d9e2 | 2731 | QS_INSERT_ESC_BYTE(*blk) |
QL | 9:ca2e6010d9e2 | 2732 | ++blk; |
QL | 9:ca2e6010d9e2 | 2733 | --size; |
QL | 9:ca2e6010d9e2 | 2734 | } |
QL | 9:ca2e6010d9e2 | 2735 | } |
QL | 9:ca2e6010d9e2 | 2736 | |
QL | 9:ca2e6010d9e2 | 2737 | QP_END_ |
QL | 9:ca2e6010d9e2 | 2738 | |
QL | 9:ca2e6010d9e2 | 2739 | |
QL | 9:ca2e6010d9e2 | 2740 | // "qs_str.cpp" ============================================================== |
QL | 9:ca2e6010d9e2 | 2741 | /// \brief QS::str() and QS::str_ROM() implementation |
QL | 9:ca2e6010d9e2 | 2742 | |
QL | 9:ca2e6010d9e2 | 2743 | QP_BEGIN_ |
QL | 9:ca2e6010d9e2 | 2744 | |
QL | 9:ca2e6010d9e2 | 2745 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2746 | void QS::str(char_t const *s) { |
QL | 9:ca2e6010d9e2 | 2747 | uint8_t b = static_cast<uint8_t>(*s); |
QL | 9:ca2e6010d9e2 | 2748 | QS_INSERT_BYTE(static_cast<uint8_t>(QS_STR_T)) |
QL | 9:ca2e6010d9e2 | 2749 | QS_chksum_ = |
QL | 9:ca2e6010d9e2 | 2750 | static_cast<uint8_t>(QS_chksum_ + static_cast<uint8_t>(QS_STR_T)); |
QL | 9:ca2e6010d9e2 | 2751 | while (b != static_cast<uint8_t>(0)) { |
QL | 9:ca2e6010d9e2 | 2752 | // ASCII characters don't need escaping |
QL | 9:ca2e6010d9e2 | 2753 | QS_INSERT_BYTE(b) |
QL | 9:ca2e6010d9e2 | 2754 | QS_chksum_ = static_cast<uint8_t>(QS_chksum_ + b); |
QL | 9:ca2e6010d9e2 | 2755 | ++s; |
QL | 9:ca2e6010d9e2 | 2756 | b = static_cast<uint8_t>(*s); |
QL | 9:ca2e6010d9e2 | 2757 | } |
QL | 9:ca2e6010d9e2 | 2758 | QS_INSERT_BYTE(static_cast<uint8_t>(0)) |
QL | 9:ca2e6010d9e2 | 2759 | } |
QL | 9:ca2e6010d9e2 | 2760 | //............................................................................ |
QL | 9:ca2e6010d9e2 | 2761 | void QS::str_ROM(char_t const Q_ROM * Q_ROM_VAR s) { |
QL | 9:ca2e6010d9e2 | 2762 | uint8_t b = static_cast<uint8_t>(Q_ROM_BYTE(*s)); |
QL | 9:ca2e6010d9e2 | 2763 | QS_INSERT_BYTE(static_cast<uint8_t>(QS_STR_T)) |
QL | 9:ca2e6010d9e2 | 2764 | QS_chksum_ = |
QL | 9:ca2e6010d9e2 | 2765 | static_cast<uint8_t>(QS_chksum_ + static_cast<uint8_t>(QS_STR_T)); |
QL | 9:ca2e6010d9e2 | 2766 | while (b != static_cast<uint8_t>(0)) { |
QL | 9:ca2e6010d9e2 | 2767 | // ASCII characters don't need escaping |
QL | 9:ca2e6010d9e2 | 2768 | QS_INSERT_BYTE(b) |
QL | 9:ca2e6010d9e2 | 2769 | QS_chksum_ = static_cast<uint8_t>(QS_chksum_ + b); |
QL | 9:ca2e6010d9e2 | 2770 | ++s; |
QL | 9:ca2e6010d9e2 | 2771 | b = static_cast<uint8_t>(Q_ROM_BYTE(*s)); |
QL | 9:ca2e6010d9e2 | 2772 | } |
QL | 9:ca2e6010d9e2 | 2773 | QS_INSERT_BYTE(static_cast<uint8_t>(0)) |
QL | 9:ca2e6010d9e2 | 2774 | } |
QL | 9:ca2e6010d9e2 | 2775 | |
QL | 9:ca2e6010d9e2 | 2776 | QP_END_ |
QL | 9:ca2e6010d9e2 | 2777 | |
QL | 9:ca2e6010d9e2 | 2778 | #endif // Q_SPY |