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.h
00001 ////////////////////////////////////////////////////////////////////////////// 00002 // Product: QP/C++ platform-independent interface 00003 // Last Updated for QP ver: 4.5.02 (modified to fit in one file) 00004 // Date of the Last Update: Aug 24, 2012 00005 // 00006 // Q u a n t u m L e a P s 00007 // --------------------------- 00008 // innovating embedded systems 00009 // 00010 // Copyright (C) 2002-2012 Quantum Leaps, LLC. All rights reserved. 00011 // 00012 // This program is open source software: you can redistribute it and/or 00013 // modify it under the terms of the GNU General Public License as published 00014 // by the Free Software Foundation, either version 2 of the License, or 00015 // (at your option) any later version. 00016 // 00017 // Alternatively, this program may be distributed and modified under the 00018 // terms of Quantum Leaps commercial licenses, which expressly supersede 00019 // the GNU General Public License and are specifically designed for 00020 // licensees interested in retaining the proprietary status of their code. 00021 // 00022 // This program is distributed in the hope that it will be useful, 00023 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00024 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00025 // GNU General Public License for more details. 00026 // 00027 // You should have received a copy of the GNU General Public License 00028 // along with this program. If not, see <http://www.gnu.org/licenses/>. 00029 // 00030 // Contact information: 00031 // Quantum Leaps Web sites: http://www.quantum-leaps.com 00032 // http://www.state-machine.com 00033 // e-mail: info@quantum-leaps.com 00034 ////////////////////////////////////////////////////////////////////////////// 00035 #ifndef qp_h 00036 #define qp_h 00037 00038 // "qevt.h" ================================================================== 00039 /// \brief QEvt class and basic macros used by all QP components. 00040 /// 00041 /// This header file must be included, perhaps indirectly, in all modules 00042 /// (*.cpp files) that use any component of QP/C++ (such as QEP, QF, or QK). 00043 00044 ////////////////////////////////////////////////////////////////////////////// 00045 /// \brief The current QP version number 00046 /// 00047 /// \return version of the QP as a hex constant constant 0xXYZZ, where X is 00048 /// a 1-digit major version number, Y is a 1-digit minor version number, and 00049 /// ZZ is a 2-digit release number. 00050 #define QP_VERSION 0x4502U 00051 00052 #ifndef Q_ROM 00053 /// \brief Macro to specify compiler-specific directive for placing a 00054 /// constant object in ROM. 00055 /// 00056 /// Many compilers for Harvard-architecture MCUs provide non-stanard 00057 /// extensions to support placement of objects in different memories. 00058 /// In order to conserve the precious RAM, QP uses the Q_ROM macro for 00059 /// all constant objects that can be allocated in ROM. 00060 /// 00061 /// To override the following empty definition, you need to define the 00062 /// Q_ROM macro in the qep_port.h header file. Some examples of valid 00063 /// Q_ROM macro definitions are: __code (IAR 8051 compiler), code (Keil 00064 /// Cx51 compiler), PROGMEM (gcc for AVR), __flash (IAR for AVR). 00065 #define Q_ROM 00066 #endif 00067 #ifndef Q_ROM_VAR // if NOT defined, provide the default definition 00068 /// \brief Macro to specify compiler-specific directive for accessing a 00069 /// constant object in ROM. 00070 /// 00071 /// Many compilers for MCUs provide different size pointers for 00072 /// accessing objects in various memories. Constant objects allocated 00073 /// in ROM (see #Q_ROM macro) often mandate the use of specific-size 00074 /// pointers (e.g., far pointers) to get access to ROM objects. The 00075 /// macro Q_ROM_VAR specifies the kind of the pointer to be used to access 00076 /// the ROM objects. 00077 /// 00078 /// To override the following empty definition, you need to define the 00079 /// Q_ROM_VAR macro in the qep_port.h header file. An example of valid 00080 /// Q_ROM_VAR macro definition is: __far (Freescale HC(S)08 compiler). 00081 #define Q_ROM_VAR 00082 #endif 00083 #ifndef Q_ROM_BYTE 00084 /// \brief Macro to access a byte allocated in ROM 00085 /// 00086 /// Some compilers for Harvard-architecture MCUs, such as gcc for AVR, do 00087 /// not generate correct code for accessing data allocated in the program 00088 /// space (ROM). The workaround for such compilers is to explictly add 00089 /// assembly code to access each data element allocated in the program 00090 /// space. The macro Q_ROM_BYTE() retrieves a byte from the given ROM 00091 /// address. 00092 /// 00093 /// The Q_ROM_BYTE() macro should be defined for the compilers that 00094 /// cannot handle correctly data allocated in ROM (such as the gcc). 00095 /// If the macro is left undefined, the default definition simply returns 00096 /// the argument and lets the compiler generate the correct code. 00097 #define Q_ROM_BYTE(rom_var_) (rom_var_) 00098 #endif 00099 00100 #ifndef Q_SIGNAL_SIZE 00101 /// \brief The size (in bytes) of the signal of an event. Valid values: 00102 /// 1, 2, or 4; default 1 00103 /// 00104 /// This macro can be defined in the QEP port file (qep_port.h) to 00105 /// configure the ::QSignal type. When the macro is not defined, the 00106 /// default of 1 byte is chosen. 00107 #define Q_SIGNAL_SIZE 2 00108 #endif 00109 00110 #ifndef Q_NNAMESPACE 00111 00112 /// \brief begin of the namespace QP 00113 /// 00114 /// \note defines to nothing if #Q_USE_NAMESPACE is undefined 00115 #define QP_BEGIN_ namespace QP { 00116 00117 /// \brief end of the namespace QP 00118 /// 00119 /// \note defines to nothing if #Q_USE_NAMESPACE is undefined 00120 #define QP_END_ } 00121 00122 /// \brief namespace QP prefix 00123 /// 00124 /// \note defines to nothing if #Q_USE_NAMESPACE is undefined 00125 #define QP_ QP:: 00126 00127 #else 00128 00129 #define QP_BEGIN_ 00130 #define QP_END_ 00131 #define QP_ 00132 00133 #endif 00134 00135 QP_BEGIN_ 00136 00137 #if (Q_SIGNAL_SIZE == 1) 00138 typedef uint8_t QSignal; 00139 #elif (Q_SIGNAL_SIZE == 2) 00140 /// \brief QSignal represents the signal of an event. 00141 /// 00142 /// The relationship between an event and a signal is as follows. A signal 00143 /// in UML is the specification of an asynchronous stimulus that triggers 00144 /// reactions [<A HREF="http://www.omg.org/docs/ptc/03-08-02.pdf">UML 00145 /// document ptc/03-08-02</A>], and as such is an essential part of an 00146 /// event. (The signal conveys the type of the occurrence-what happened?) 00147 /// However, an event can also contain additional quantitative information 00148 /// about the occurrence in form of event parameters. Please refer to the 00149 typedef uint16_t QSignal; 00150 #elif (Q_SIGNAL_SIZE == 4) 00151 typedef uint32_t QSignal; 00152 #else 00153 #error "Q_SIGNAL_SIZE defined incorrectly, expected 1, 2, or 4" 00154 #endif 00155 00156 #ifdef Q_EVT_CTOR // Provide the constructor for the QEvt class? 00157 00158 ////////////////////////////////////////////////////////////////////////// 00159 /// \brief QEvt base class. 00160 /// 00161 /// QEvt represents events without parameters and serves as the base class 00162 /// for derivation of events with parameters. 00163 /// 00164 /// The following example illustrates how to add an event parameter by 00165 /// inheriting from the QEvt class. 00166 /// \include qep_qevent.cpp 00167 class QEvt { 00168 public: 00169 QSignal sig; ///< signal of the event instance 00170 00171 QEvt(QSignal const s) // poolId_ intentionally uninitialized 00172 : sig(s) {} 00173 00174 #ifdef Q_EVT_VIRTUAL 00175 virtual ~QEvt() {} // virtual destructor 00176 #endif 00177 00178 private: 00179 uint8_t poolId_; ///< pool ID (0 for static event) 00180 uint8_t refCtr_; ///< reference counter 00181 00182 friend class QF; 00183 friend class QTimeEvt; 00184 friend uint8_t QF_EVT_POOL_ID_ (QEvt const * const e); 00185 friend uint8_t QF_EVT_REF_CTR_ (QEvt const * const e); 00186 friend void QF_EVT_REF_CTR_INC_(QEvt const * const e); 00187 friend void QF_EVT_REF_CTR_DEC_(QEvt const * const e); 00188 }; 00189 00190 #else // QEvt is a POD (Plain Old Datatype) 00191 00192 struct QEvt { 00193 QSignal sig; ///< signal of the event instance 00194 uint8_t poolId_; ///< pool ID (0 for static event) 00195 uint8_t refCtr_; ///< reference counter 00196 }; 00197 00198 #endif // Q_EVT_CTOR 00199 00200 QP_END_ 00201 00202 ////////////////////////////////////////////////////////////////////////////// 00203 /// helper macro to calculate static dimension of a 1-dim array \a array_ 00204 #define Q_DIM(array_) (sizeof(array_) / sizeof(array_[0])) 00205 00206 ////////////////////////////////////////////////////////////////////////////// 00207 // typedefs for basic numerical types; MISRA-C++ 2008 rule 3-9-2(req). 00208 00209 /// \brief typedef for character strings. 00210 /// 00211 /// This typedef specifies character type for exclusive use in character 00212 /// strings. Use of this type, rather than plain 'char', is in compliance 00213 /// with the MISRA-C 2004 Rules 6.1(req), 6.3(adv). 00214 /// 00215 typedef char char_t; 00216 00217 /// typedef for 32-bit IEEE 754 floating point numbers 00218 typedef float float32_t; 00219 00220 /// typedef for 64-bit IEEE 754 floating point numbers 00221 typedef double float64_t; 00222 00223 /// typedef for enumerations used for event signals 00224 typedef int enum_t; 00225 00226 /// \brief Perform cast from unsigned integer \a uint_ to pointer 00227 /// of type \a type_. 00228 /// 00229 /// This macro encapsulates the cast to (type_ *), which QP ports or 00230 /// application might use to access embedded hardware registers. 00231 /// Such uses can trigger PC-Lint "Note 923: cast from int to pointer" 00232 /// and this macro helps to encapsulate this deviation. 00233 /// 00234 #define Q_UINT2PTR_CAST(type_, uint_) (reinterpret_cast<type_ *>(uint_)) 00235 00236 /// \brief Initializer of static constant QEvt instances 00237 /// 00238 /// This macro encapsulates the ugly casting of enumerated signals 00239 /// to QSignal and constants for QEvt.poolID and QEvt.refCtr_. 00240 /// 00241 #define QEVT_INITIALIZER(sig_) { static_cast<QP_ QSignal>(sig_), \ 00242 static_cast<uint8_t>(0), static_cast<uint8_t>(0) } 00243 00244 ////////////////////////////////////////////////////////////////////////////// 00245 // facilities for backwards compatibility 00246 // 00247 #ifndef Q_NQEVENT 00248 // typedef struct QEvt QEvent; 00249 #define QEvent QEvt 00250 #endif 00251 00252 00253 // "qep.h" =================================================================== 00254 /// \brief QEP/C++ platform-independent public interface. 00255 /// 00256 /// This header file must be included directly or indirectly 00257 /// in all modules (*.cpp files) that use QEP/C++. 00258 00259 /// \brief Designates a target for an initial or regular transition. 00260 /// Q_TRAN() can be used both in the FSMs and HSMs. 00261 /// 00262 /// \include qep_qtran.c 00263 /// 00264 #define Q_TRAN(target_) (me->tran(Q_STATE_CAST(target_))) 00265 00266 /// \brief Designates the superstate of a given state in an HSM. 00267 /// 00268 /// \include qep_qhsm.c 00269 /// 00270 #define Q_SUPER(super_) (me->super(Q_STATE_CAST(super_))) 00271 00272 /// \brief Perform cast to QStateHandler. 00273 /// 00274 /// This macro encapsulates the cast of a specific state handler function 00275 /// pointer to QStateHandler, which violates MISRA-C 2004 rule 11.4(advisory). 00276 /// This macro helps to localize this deviation. 00277 /// 00278 #define Q_STATE_CAST(handler_) \ 00279 (reinterpret_cast<QP_ QStateHandler>(handler_)) 00280 00281 /// \brief Perform downcast of an event onto a subclass of QEvt \a class_ 00282 /// 00283 /// This macro encapsulates the downcast of QEvt pointers, which violates 00284 /// MISRA-C 2004 rule 11.4(advisory). This macro helps to localize this 00285 /// deviation. 00286 /// 00287 #define Q_EVT_CAST(class_) (static_cast<class_ const *>(e)) 00288 00289 ////////////////////////////////////////////////////////////////////////////// 00290 QP_BEGIN_ 00291 00292 /// \brief Provides miscellaneous QEP services. 00293 class QEP { 00294 public: 00295 /// \brief get the current QEP version number string 00296 /// 00297 /// \return version of the QEP as a constant 6-character string of the 00298 /// form x.y.zz, where x is a 1-digit major version number, y is a 00299 /// 1-digit minor version number, and zz is a 2-digit release number. 00300 static char_t const Q_ROM * Q_ROM_VAR getVersion(void); 00301 }; 00302 00303 ////////////////////////////////////////////////////////////////////////////// 00304 00305 /// \brief Type returned from a state-handler function 00306 typedef uint8_t QState; 00307 /// \brief pointer to state-handler function 00308 typedef QState (*QStateHandler)(void * const me, QEvt const * const e); 00309 00310 ////////////////////////////////////////////////////////////////////////////// 00311 /// \brief Value returned by a state-handler function when it handles 00312 /// the event. 00313 QState const Q_RET_HANDLED = static_cast<QState>(0); 00314 00315 /// \brief Value returned by a non-hierarchical state-handler function when 00316 /// it ignores (does not handle) the event. 00317 QState const Q_RET_IGNORED = static_cast<QState>(1); 00318 00319 /// \brief Value returned by a state-handler function when it takes a 00320 /// regular state transition. 00321 QState const Q_RET_TRAN = static_cast<QState>(2); 00322 00323 /// \brief Value returned by a state-handler function when it forwards 00324 /// the event to the superstate to handle. 00325 QState const Q_RET_SUPER = static_cast<QState>(3); 00326 00327 /// \brief Value returned by a state-handler function when a guard 00328 /// condition prevents it from handling the event. 00329 /// 00330 QState const Q_RET_UNHANDLED = static_cast<QState>(4); 00331 00332 00333 /// Offset or the user signals 00334 enum_t const Q_USER_SIG = static_cast<enum_t>(4); 00335 00336 00337 ////////////////////////////////////////////////////////////////////////////// 00338 /// \brief Finite State Machine base class 00339 /// 00340 /// QFsm represents a traditional non-hierarchical Finite State Machine (FSM) 00341 /// without state hierarchy, but with entry/exit actions. 00342 /// 00343 /// QFsm is also a base structure for the ::QHsm class. 00344 /// 00345 /// \note QFsm is not intended to be instantiated directly, but rather serves 00346 /// as the base class for derivation of state machines in the application 00347 /// code. 00348 /// 00349 /// The following example illustrates how to derive a state machine class 00350 /// from QFsm. 00351 /// \include qep_qfsm.cpp 00352 class QFsm { 00353 private: 00354 QStateHandler m_state; ///< current active state (state-variable) 00355 QStateHandler m_temp; ///< temporary state: target of tran. or superstate 00356 00357 public: 00358 /// \brief virtual destructor 00359 virtual ~QFsm(); 00360 00361 /// \brief Performs the second step of FSM initialization by triggering 00362 /// the top-most initial transition. 00363 /// 00364 /// The argument \a e is constant pointer to ::QEvt or a class 00365 /// derived from ::QEvt. 00366 /// 00367 /// \note Must be called only ONCE before QFsm::dispatch() 00368 /// 00369 /// The following example illustrates how to initialize a FSM, and 00370 /// dispatch events to it: 00371 /// \include qep_qfsm_use.cpp 00372 void init(QEvt const * const e = static_cast<QEvt const *>(0)); 00373 00374 /// \brief Dispatches an event to a FSM 00375 /// 00376 /// Processes one event at a time in Run-to-Completion (RTC) fashion. 00377 /// The argument \a e is a constant pointer the ::QEvt or a 00378 /// class derived from ::QEvt. 00379 /// 00380 /// \note Must be called after QFsm::init(). 00381 /// 00382 /// \sa example for QFsm::init() 00383 void dispatch(QEvt const * const e); 00384 00385 protected: 00386 /// \brief Protected constructor of a FSM. 00387 /// 00388 /// Performs the first step of FSM initialization by assigning the 00389 /// initial pseudostate to the currently active state of the state 00390 /// machine. 00391 /// 00392 /// \note The constructor is protected to prevent direct instantiating 00393 /// of QFsm objects. This class is intended for subclassing only. 00394 /// 00395 /// \sa The ::QFsm example illustrates how to use the QHsm constructor 00396 /// in the constructor initializer list of the derived state machines. 00397 QFsm(QStateHandler const initial) 00398 : m_state(Q_STATE_CAST(0)), 00399 m_temp(initial) 00400 {} 00401 00402 /// \brief Return the current active state. 00403 QStateHandler state(void) const { 00404 return m_state; 00405 } 00406 00407 /// \brief Inline function to specify the return of a state-handler 00408 /// when it igonres (does not handle in any way) the event. 00409 static QState Q_IGNORED(void) { return Q_RET_IGNORED; } 00410 00411 /// \brief Inline function to specify the return of a state-handler 00412 /// when it handles the event. 00413 /// 00414 /// \include qep_qhsm.cpp 00415 static QState Q_HANDLED(void) { return Q_RET_HANDLED; } 00416 00417 /// \brief Macro to specify the return of a state-handler function when 00418 /// it attempts to handle the event but a guard condition evaluates to 00419 /// false and there is no other explicit way of handling the event. 00420 static QState Q_UNHANDLED(void) { return Q_RET_UNHANDLED; } 00421 00422 /// \brief internal helper function to record a state transition 00423 QState tran(QStateHandler const target) { 00424 m_temp = target; 00425 return Q_RET_TRAN; 00426 } 00427 00428 enum ReservedFsmSignals { 00429 Q_ENTRY_SIG = 1, ///< signal for entry actions 00430 Q_EXIT_SIG ///< signal for exit actions 00431 }; 00432 }; 00433 00434 ////////////////////////////////////////////////////////////////////////////// 00435 /// \brief Hierarchical State Machine base class 00436 /// 00437 /// QHsm represents a Hierarchical Finite State Machine (HSM). QHsm derives 00438 /// from the ::QFsm class and extends the capabilities of a basic FSM 00439 /// with state hierarchy. 00440 /// 00441 /// \note QHsm is not intended to be instantiated directly, but rather serves 00442 /// as the base structure for derivation of state machines in the application 00443 /// code. 00444 /// 00445 /// The following example illustrates how to derive a state machine class 00446 /// from QHsm. 00447 /// \include qep_qhsm.cpp 00448 class QHsm { 00449 private: 00450 QStateHandler m_state; ///< current active state (state-variable) 00451 QStateHandler m_temp; ///< temporary state: target of tran. or superstate 00452 00453 public: 00454 /// \brief virtual destructor 00455 virtual ~QHsm(); 00456 00457 /// \brief Performs the second step of HSM initialization by triggering 00458 /// the top-most initial transition. 00459 /// 00460 /// \param e constant pointer ::QEvt or a class derived from ::QEvt 00461 /// \note Must be called only ONCE before QHsm::dispatch() 00462 /// 00463 /// The following example illustrates how to initialize a HSM, and 00464 /// dispatch events to it: 00465 /// \include qep_qhsm_use.cpp 00466 void init(QEvt const * const e = static_cast<QEvt const *>(0)); 00467 00468 /// \brief Dispatches an event to a HSM 00469 /// 00470 /// Processes one event at a time in Run-to-Completion (RTC) fashion. 00471 /// The argument \a e is a constant pointer the ::QEvt or a 00472 /// class derived from ::QEvt. 00473 /// 00474 /// \note Must be called after QHsm::init(). 00475 /// 00476 /// \sa example for QHsm::init() 00477 void dispatch(QEvt const * const e); 00478 00479 /// \brief Tests if a given state is part of the current active state 00480 /// configuratioin 00481 /// 00482 /// \param state is a pointer to the state handler function, e.g., 00483 /// &QCalc::on. 00484 bool isIn(QStateHandler const s); 00485 00486 protected: 00487 /// \brief Protected constructor of a HSM. 00488 /// 00489 /// Performs the first step of HSM initialization by assigning the 00490 /// initial pseudostate to the currently active state of the state 00491 /// machine. 00492 /// 00493 /// \note The constructor is protected to prevent direct instantiating 00494 /// of QHsm objects. This class is intended for subclassing only. 00495 /// 00496 /// \sa The ::QHsm example illustrates how to use the QHsm constructor 00497 /// in the constructor initializer list of the derived state machines. 00498 /// \sa QFsm::QFsm() 00499 QHsm(QStateHandler const initial) 00500 : m_state(Q_STATE_CAST(&QHsm::top)), 00501 m_temp(initial) 00502 {} 00503 00504 /// \brief Return the current active state. 00505 QStateHandler state(void) const { 00506 return m_state; 00507 } 00508 00509 /// \brief the top-state. 00510 /// 00511 /// QHsm::top() is the ultimate root of state hierarchy in all HSMs 00512 /// derived from ::QHsm. This state handler always returns (QSTATE)0, 00513 /// which means that it "handles" all events. 00514 /// 00515 /// \sa Example of the QCalc::on() state handler. 00516 static QState top(void * const me, QEvt const * const e); 00517 00518 /// \brief Inline function to specify the return of a state-handler 00519 /// when it handles the event. 00520 /// 00521 /// \include qep_qhsm.cpp 00522 static QState Q_HANDLED(void) { return Q_RET_HANDLED; } 00523 00524 /// \brief Macro to specify the return of a state-handler function when 00525 /// it attempts to handle the event but a guard condition evaluates to 00526 /// false and there is no other explicit way of handling the event. 00527 static QState Q_UNHANDLED(void) { return Q_RET_UNHANDLED; } 00528 00529 /// \brief internal helper function to record a state transition 00530 QState tran(QStateHandler const target) { 00531 m_temp = target; 00532 return Q_RET_TRAN; 00533 } 00534 00535 /// \brief internal helper function to record the superstate 00536 QState super(QStateHandler const superstate) { 00537 m_temp = superstate; 00538 return Q_RET_SUPER; 00539 } 00540 00541 enum ReservedHsmSignals { 00542 Q_ENTRY_SIG = 1, ///< signal for entry actions 00543 Q_EXIT_SIG, ///< signal for exit actions 00544 Q_INIT_SIG ///< signal for nested initial transitions 00545 }; 00546 }; 00547 00548 ////////////////////////////////////////////////////////////////////////////// 00549 00550 QP_END_ 00551 00552 // "qequeue.h" =============================================================== 00553 /// \brief platform-independent event queue interface. 00554 /// 00555 /// This header file must be included in all QF ports that use native QF 00556 /// event queue implementation. Also, this file is needed when the "raw" 00557 /// thread-safe queues are used for communication between active objects 00558 /// and non-framework entities, such as ISRs, device drivers, or legacy 00559 /// code. 00560 00561 #ifndef QF_EQUEUE_CTR_SIZE 00562 00563 /// \brief The size (in bytes) of the ring-buffer counters used in the 00564 /// native QF event queue implementation. Valid values: 1, 2, or 4; 00565 /// default 1. 00566 /// 00567 /// This macro can be defined in the QF port file (qf_port.h) to 00568 /// configure the ::QEQueueCtr type. Here the macro is not defined so the 00569 /// default of 1 byte is chosen. 00570 #define QF_EQUEUE_CTR_SIZE 1 00571 #endif 00572 00573 QP_BEGIN_ 00574 00575 #if (QF_EQUEUE_CTR_SIZE == 1) 00576 /// \brief The data type to store the ring-buffer counters based on 00577 /// the macro #QF_EQUEUE_CTR_SIZE. 00578 /// 00579 /// The dynamic range of this data type determines the maximum length 00580 /// of the ring buffer managed by the native QF event queue. 00581 typedef uint8_t QEQueueCtr; 00582 #elif (QF_EQUEUE_CTR_SIZE == 2) 00583 typedef uint16_t QEQueueCtr; 00584 #elif (QF_EQUEUE_CTR_SIZE == 4) 00585 typedef uint32_t QEQueueCtr; 00586 #else 00587 #error "QF_EQUEUE_CTR_SIZE defined incorrectly, expected 1, 2, or 4" 00588 #endif 00589 00590 00591 ////////////////////////////////////////////////////////////////////////////// 00592 /// \brief Native QF Event Queue class 00593 /// 00594 /// This structure describes the native QF event queue, which can be used as 00595 /// the event queue for active objects, or as a simple "raw" event queue for 00596 /// thread-safe event passing among non-framework entities, such as ISRs, 00597 /// device drivers, or other third-party components. 00598 /// 00599 /// The native QF event queue is configured by defining the macro 00600 /// #QF_EQUEUE_TYPE as ::QEQueue in the specific QF port header file. 00601 /// 00602 /// The ::QEQueue structure contains only data members for managing an event 00603 /// queue, but does not contain the storage for the queue buffer, which must 00604 /// be provided externally during the queue initialization. 00605 /// 00606 /// The event queue can store only event pointers, not the whole events. The 00607 /// internal implementation uses the standard ring-buffer plus one external 00608 /// location that optimizes the queue operation for the most frequent case 00609 /// of empty queue. 00610 /// 00611 /// The ::QEQueue structure is used with two sets of functions. One set is for 00612 /// the active object event queue, which needs to block the active object 00613 /// task when the event queue is empty and unblock it when events are posted 00614 /// to the queue. The interface for the native active object event queue 00615 /// consists of the following functions: QActive::postFIFO_(), 00616 /// QActive::postLIFO_(), and QActive::get_(). Additionally the function 00617 /// QEQueue_init() is used to initialize the queue. 00618 /// 00619 /// The other set of functions, uses this structure as a simple "raw" event 00620 /// queue to pass events between entities other than active objects, such as 00621 /// ISRs. The "raw" event queue is not capable of blocking on the get() 00622 /// operation, but is still thread-safe because it uses QF critical section 00623 /// to protect its integrity. The interface for the "raw" thread-safe queue 00624 /// consists of the following functions: QEQueue::postFIFO(), 00625 /// QEQueue::postLIFO(), and QEQueue::get(). Additionally the function 00626 /// QEQueue::init() is used to initialize the queue. 00627 /// 00628 /// \note Most event queue operations (both the active object queues and 00629 /// the "raw" queues) internally use the QF critical section. You should be 00630 /// careful not to invoke those operations from other critical sections when 00631 /// nesting of critical sections is not supported. 00632 class QEQueue { 00633 private: 00634 00635 /// \brief pointer to event at the front of the queue 00636 /// 00637 /// All incoming and outgoing events pass through the m_frontEvt location. 00638 /// When the queue is empty (which is most of the time), the extra 00639 /// m_frontEvt location allows to bypass the ring buffer altogether, 00640 /// greatly optimizing the performance of the queue. Only bursts of events 00641 /// engage the ring buffer. 00642 /// 00643 /// The additional role of this attribute is to indicate the empty status 00644 /// of the queue. The queue is empty if the m_frontEvt location is NULL. 00645 QEvt const *m_frontEvt; 00646 00647 /// \brief pointer to the start of the ring buffer 00648 QEvt const **m_ring; 00649 00650 /// \brief offset of the end of the ring buffer from the start of the 00651 /// buffer m_ring 00652 QEQueueCtr m_end; 00653 00654 /// \brief offset to where next event will be inserted into the buffer 00655 QEQueueCtr m_head; 00656 00657 /// \brief offset of where next event will be extracted from the buffer 00658 QEQueueCtr m_tail; 00659 00660 /// \brief number of free events in the ring buffer 00661 QEQueueCtr m_nFree; 00662 00663 /// \brief minimum number of free events ever in the ring buffer. 00664 /// 00665 /// \note this attribute remembers the low-watermark of the ring buffer, 00666 /// which provides a valuable information for sizing event queues. 00667 /// \sa QF::getQueueMargin(). 00668 QEQueueCtr m_nMin; 00669 00670 public: 00671 00672 /// \brief Initializes the native QF event queue 00673 /// 00674 /// The parameters are as follows: \a qSto[] is the ring buffer storage, 00675 /// \a qLen is the length of the ring buffer in the units of event- 00676 /// pointers. 00677 /// 00678 /// \note The actual capacity of the queue is qLen + 1, because of the 00679 /// extra location fornEvt_. 00680 void init(QEvt const *qSto[], QEQueueCtr const qLen); 00681 00682 /// \brief "raw" thread-safe QF event queue implementation for the 00683 /// First-In-First-Out (FIFO) event posting. You can call this function 00684 /// from any task context or ISR context. Please note that this function 00685 /// uses internally a critical section. 00686 /// 00687 /// \note The function raises an assertion if the native QF queue becomes 00688 /// full and cannot accept the event. 00689 /// 00690 /// \sa QEQueue::postLIFO(), QEQueue::get() 00691 void postFIFO(QEvt const * const e); 00692 00693 /// \brief "raw" thread-safe QF event queue implementation for the 00694 /// First-In-First-Out (FIFO) event posting. You can call this function 00695 /// from any task context or ISR context. Please note that this function 00696 /// uses internally a critical section. 00697 /// 00698 /// \note The function raises an assertion if the native QF queue becomes 00699 /// full and cannot accept the event. 00700 /// 00701 /// \sa QEQueue::postLIFO(), QEQueue::get() 00702 void postLIFO(QEvt const * const e); 00703 00704 /// \brief "raw" thread-safe QF event queue implementation for the 00705 /// Last-In-First-Out (LIFO) event posting. 00706 /// 00707 /// \note The LIFO policy should be used only with great caution because 00708 /// it alters order of events in the queue. 00709 /// \note The function raises an assertion if the native QF queue becomes 00710 /// full and cannot accept the event. You can call this function from 00711 /// any task context or ISR context. Please note that this function uses 00712 /// internally a critical section. 00713 /// 00714 /// \sa QEQueue::postFIFO(), QEQueue::get() 00715 QEvt const *get(void); 00716 00717 /// \brief "raw" thread-safe QF event queue operation for 00718 /// obtaining the number of free entries still available in the queue. 00719 /// 00720 /// \note This operation needs to be used with caution because the 00721 /// number of free entries can change unexpectedly. The main intent for 00722 /// using this operation is in conjunction with event deferral. In this 00723 /// case the queue is accessed only from a single thread (by a single AO), 00724 /// so the number of free entries cannot change unexpectedly. 00725 /// 00726 /// \sa QActive::defer(), QActive::recall() 00727 QEQueueCtr getNFree(void) const { 00728 return m_nFree; 00729 } 00730 00731 private: 00732 friend class QF; 00733 friend class QActive; 00734 }; 00735 00736 QP_END_ 00737 00738 // "qmpool.h" ================================================================ 00739 /// \brief platform-independent memory pool interface. 00740 /// 00741 /// This header file must be included in all QF ports that use native QF 00742 /// memory pool implementation. 00743 00744 #ifndef QF_MPOOL_SIZ_SIZE 00745 /// \brief macro to override the default ::QMPoolSize size. 00746 /// Valid values 1, 2, or 4; default 2 00747 #define QF_MPOOL_SIZ_SIZE 2 00748 #endif 00749 00750 #ifndef QF_MPOOL_CTR_SIZE 00751 00752 /// \brief macro to override the default QMPoolCtr size. 00753 /// Valid values 1, 2, or 4; default 2 00754 #define QF_MPOOL_CTR_SIZE 2 00755 #endif 00756 00757 ////////////////////////////////////////////////////////////////////////////// 00758 QP_BEGIN_ 00759 00760 #if (QF_MPOOL_SIZ_SIZE == 1) 00761 /// \brief The data type to store the block-size based on the macro 00762 /// #QF_MPOOL_SIZ_SIZE. 00763 /// 00764 /// The dynamic range of this data type determines the maximum size 00765 /// of blocks that can be managed by the native QF event pool. 00766 typedef uint8_t QMPoolSize; 00767 #elif (QF_MPOOL_SIZ_SIZE == 2) 00768 00769 typedef uint16_t QMPoolSize; 00770 #elif (QF_MPOOL_SIZ_SIZE == 4) 00771 typedef uint32_t QMPoolSize; 00772 #else 00773 #error "QF_MPOOL_SIZ_SIZE defined incorrectly, expected 1, 2, or 4" 00774 #endif 00775 00776 #if (QF_MPOOL_CTR_SIZE == 1) 00777 /// \brief The data type to store the block-counter based on the macro 00778 /// #QF_MPOOL_CTR_SIZE. 00779 /// 00780 /// The dynamic range of this data type determines the maximum number 00781 /// of blocks that can be stored in the pool. 00782 typedef uint8_t QMPoolCtr; 00783 #elif (QF_MPOOL_CTR_SIZE == 2) 00784 typedef uint16_t QMPoolCtr; 00785 #elif (QF_MPOOL_CTR_SIZE == 4) 00786 typedef uint32_t QMPoolCtr; 00787 #else 00788 #error "QF_MPOOL_CTR_SIZE defined incorrectly, expected 1, 2, or 4" 00789 #endif 00790 00791 ////////////////////////////////////////////////////////////////////////////// 00792 /// \brief Native QF memory pool class 00793 /// 00794 /// This class describes the native QF memory pool, which can be used as 00795 /// the event pool for dynamic event allocation, or as a fast, deterministic 00796 /// fixed block-size heap for any other objects in your application. 00797 /// 00798 /// The ::QMPool structure contains only data members for managing a memory 00799 /// pool, but does not contain the pool storage, which must be provided 00800 /// externally during the pool initialization. 00801 /// 00802 /// The native QF event pool is configured by defining the macro 00803 /// #QF_EPOOL_TYPE_ as QEQueue in the specific QF port header file. 00804 class QMPool { 00805 private: 00806 00807 /// start of the memory managed by this memory pool 00808 void *m_start; 00809 00810 /// end of the memory managed by this memory pool 00811 void *m_end; 00812 00813 /// linked list of free blocks 00814 void *m_free; 00815 00816 /// maximum block size (in bytes) 00817 QMPoolSize m_blockSize; 00818 00819 /// total number of blocks 00820 QMPoolCtr m_nTot; 00821 00822 /// number of free blocks remaining 00823 QMPoolCtr m_nFree; 00824 00825 /// minimum number of free blocks ever present in this pool 00826 /// 00827 /// \note this attribute remembers the low watermark of the pool, 00828 /// which provides a valuable information for sizing event pools. 00829 /// \sa QF::getPoolMargin(). 00830 QMPoolCtr m_nMin; 00831 00832 public: 00833 00834 /// \brief Initializes the native QF event pool 00835 /// 00836 /// The parameters are as follows: \a poolSto is the pool storage, 00837 /// \a poolSize is the size of the pool storage in bytes, and 00838 /// \a blockSize is the block size of this pool. 00839 /// 00840 /// The caller of this method must make sure that the \a poolSto pointer 00841 /// is properly aligned. In particular, it must be possible to efficiently 00842 /// store a pointer at the location pointed to by \a poolSto. 00843 /// Internally, the QMPool::init() function rounds up the block size 00844 /// \a blockSize so that it can fit an integer number of pointers. 00845 /// This is done to achieve proper alignment of the blocks within the 00846 /// pool. 00847 /// 00848 /// \note Due to the rounding of block size the actual capacity of the 00849 /// pool might be less than (\a poolSize / \a blockSize). You can check 00850 /// the capacity of the pool by calling the QF::getPoolMargin() function. 00851 void init(void * const poolSto, uint32_t const poolSize, 00852 QMPoolSize const blockSize); 00853 00854 /// \brief Obtains a memory block from a memory pool. 00855 /// 00856 /// The only parameter \a me is a pointer to the ::QMPool from which the 00857 /// block is requested. The function returns a pointer to the allocated 00858 /// memory block or NULL if no free blocks are available. 00859 /// 00860 /// A allocated block must be returned to the same pool from which it has 00861 /// been allocated. 00862 /// 00863 /// This function can be called from any task level or ISR level. 00864 /// 00865 /// \note The memory pool \a me must be initialized before any events can 00866 /// be requested from it. Also, the QMPool::get() function uses internally 00867 /// a QF critical section, so you should be careful not to call it from 00868 /// within a critical section when nesting of critical section is not 00869 /// supported. 00870 /// 00871 /// \sa QMPool::put() 00872 void *get(void); 00873 00874 /// \brief Returns a memory block back to a memory pool. 00875 /// 00876 /// 00877 /// This function can be called from any task level or ISR level. 00878 /// 00879 /// \note The block must be allocated from the same memory pool to which 00880 /// it is returned. The QMPool::put() function raises an assertion if the 00881 /// returned pointer to the block points outside of the original memory 00882 /// buffer managed by the memory pool. Also, the QMPool::put() function 00883 /// uses internally a QF critical section, so you should be careful not 00884 /// to call it from within a critical section when nesting of critical 00885 /// section is not supported. 00886 /// 00887 /// \sa QMPool::get() 00888 void put(void * const b); 00889 00890 /// \brief return the fixed block-size of the blocks managed by this pool 00891 QMPoolSize getBlockSize(void) const { 00892 return m_blockSize; 00893 } 00894 00895 private: 00896 friend class QF; 00897 }; 00898 00899 QP_END_ 00900 00901 /// \brief Memory pool element to allocate correctly aligned storage 00902 /// for QMPool class. 00903 /// 00904 #define QF_MPOOL_EL(type_) \ 00905 struct { void *sto_[((sizeof(type_) - 1U)/sizeof(void*)) + 1U]; } 00906 00907 // "qpset.h" ================================================================= 00908 /// \brief platform-independent priority sets of 8 or 64 elements. 00909 /// 00910 /// This header file must be included in those QF ports that use the 00911 /// cooperative multitasking QF scheduler or the QK. 00912 00913 QP_BEGIN_ 00914 00915 ////////////////////////////////////////////////////////////////////////////// 00916 // useful lookup tables 00917 00918 /// \brief Lookup table for (log2(n) + 1), where n is the index 00919 /// into the table. 00920 /// 00921 /// This lookup delivers the 1-based number of the most significant 1-bit 00922 /// of a byte. 00923 /// 00924 /// \note Index range n = 0..255. The first index (n == 0) should never 00925 /// be used. 00926 /// 00927 extern uint8_t const Q_ROM Q_ROM_VAR QF_log2Lkup[256]; 00928 00929 /// \brief Lookup table for (1 << ((n-1) % 8)), where n is the index 00930 /// into the table. 00931 /// 00932 /// \note Index range n = 0..64. The first index (n == 0) should never 00933 /// be used. 00934 extern uint8_t const Q_ROM Q_ROM_VAR QF_pwr2Lkup[65]; 00935 00936 /// \brief Lookup table for ~(1 << ((n-1) % 8)), where n is the index 00937 /// into the table. 00938 /// 00939 /// \note Index range n = 0..64. The first index (n == 0) should never 00940 /// be used. 00941 extern uint8_t const Q_ROM Q_ROM_VAR QF_invPwr2Lkup[65]; 00942 00943 /// \brief Lookup table for (n-1)/8 00944 /// 00945 /// \note Index range n = 0..64. The first index (n == 0) should never 00946 /// be used. 00947 extern uint8_t const Q_ROM Q_ROM_VAR QF_div8Lkup[65]; 00948 00949 00950 ////////////////////////////////////////////////////////////////////////////// 00951 /// \brief Priority Set of up to 8 elements for building various schedulers, 00952 /// but also useful as a general set of up to 8 elements of any kind. 00953 /// 00954 /// The priority set represents the set of active objects that are ready to 00955 /// run and need to be considered by scheduling processing. The set is capable 00956 /// of storing up to 8 priority levels. 00957 class QPSet8 { 00958 00959 ////////////////////////////////////////////////////////////////////////// 00960 /// \brief bimask representing elements of the set 00961 uint8_t m_bits; 00962 00963 public: 00964 00965 /// \brief the function evaluates to TRUE if the set is empty, 00966 /// which means that no active objects are ready to run. 00967 bool isEmpty(void) const { 00968 return (m_bits == static_cast<uint8_t>(0)); 00969 } 00970 00971 /// \brief the function evaluates to TRUE if the set has elements, 00972 /// which means that some active objects are ready to run. 00973 bool notEmpty(void) const { 00974 return (m_bits != static_cast<uint8_t>(0)); 00975 } 00976 00977 /// \brief the function evaluates to TRUE if the priority set has the 00978 /// element \a n. 00979 bool hasElement(uint8_t const n) const { 00980 return ((m_bits & Q_ROM_BYTE(QF_pwr2Lkup[n])) 00981 != static_cast<uint8_t>(0)); 00982 } 00983 00984 /// \brief insert element \a n into the set, n = 1..8 00985 void insert(uint8_t const n) { 00986 m_bits |= Q_ROM_BYTE(QF_pwr2Lkup[n]); 00987 } 00988 00989 /// \brief remove element \a n from the set, n = 1..8 00990 void remove(uint8_t const n) { 00991 m_bits &= Q_ROM_BYTE(QF_invPwr2Lkup[n]); 00992 } 00993 00994 /// \brief find the maximum element in the set, 00995 /// \note returns zero if the set is empty 00996 uint8_t findMax(void) const { 00997 return Q_ROM_BYTE(QF_log2Lkup[m_bits]); 00998 } 00999 01000 friend class QPSet64; 01001 }; 01002 01003 ////////////////////////////////////////////////////////////////////////////// 01004 /// \brief Priority Set of up to 64 elements for building various schedulers, 01005 /// but also useful as a general set of up to 64 elements of any kind. 01006 /// 01007 /// The priority set represents the set of active objects that are ready to 01008 /// run and need to be considered by scheduling processing. The set is capable 01009 /// of storing up to 64 priority levels. 01010 /// 01011 /// The priority set allows to build cooperative multitasking schedulers 01012 /// to manage up to 64 tasks. It is also used in the Quantum Kernel (QK) 01013 /// preemptive scheduler. 01014 /// 01015 /// The inherited 8-bit set is used as the 8-elemtn set of of 8-bit subsets 01016 /// Each bit in the super.bits set represents a subset (8-elements) 01017 /// as follows: \n 01018 /// bit 0 in this->m_bits is 1 when subset[0] is not empty \n 01019 /// bit 1 in this->m_bits is 1 when subset[1] is not empty \n 01020 /// bit 2 in this->m_bits is 1 when subset[2] is not empty \n 01021 /// bit 3 in this->m_bits is 1 when subset[3] is not empty \n 01022 /// bit 4 in this->m_bits is 1 when subset[4] is not empty \n 01023 /// bit 5 in this->m_bits is 1 when subset[5] is not empty \n 01024 /// bit 6 in this->m_bits is 1 when subset[6] is not empty \n 01025 /// bit 7 in this->m_bits is 1 when subset[7] is not empty \n 01026 class QPSet64 { 01027 01028 ////////////////////////////////////////////////////////////////////////// 01029 /// \brief bimask representing 8-element subsets of the set 01030 uint8_t m_bytes; 01031 01032 /// \brief bits representing elements in the set as follows: \n 01033 /// m_bits[0] represent elements 1..8 \n 01034 /// m_bits[1] represent elements 9..16 \n 01035 /// m_bits[2] represent elements 17..24 \n 01036 /// m_bits[3] represent elements 25..32 \n 01037 /// m_bits[4] represent elements 33..40 \n 01038 /// m_bits[5] represent elements 41..48 \n 01039 /// m_bits[6] represent elements 49..56 \n 01040 /// m_bits[7] represent elements 57..64 \n 01041 uint8_t m_bits[8]; 01042 01043 public: 01044 01045 /// \brief the function evaluates to TRUE if the set is empty, 01046 /// which means that no active objects are ready to run. 01047 bool isEmpty(void) const { 01048 return (m_bytes == static_cast<uint8_t>(0)); 01049 } 01050 01051 /// \brief the function evaluates to TRUE if the set has elements, 01052 /// which means that some active objects are ready to run. 01053 bool notEmpty(void) const { 01054 return (m_bytes != static_cast<uint8_t>(0)); 01055 } 01056 01057 /// \brief the function evaluates to TRUE if the priority set has the 01058 /// element \a n. 01059 bool hasElement(uint8_t const n) const { 01060 uint8_t const m = Q_ROM_BYTE(QF_div8Lkup[n]); 01061 return ((m_bits[m] & Q_ROM_BYTE(QF_pwr2Lkup[n])) 01062 != static_cast<uint8_t>(0)); 01063 } 01064 01065 /// \brief insert element \a n into the set, n = 1..64 01066 void insert(uint8_t const n) { 01067 uint8_t m = Q_ROM_BYTE(QF_div8Lkup[n]); 01068 m_bits[m] |= Q_ROM_BYTE(QF_pwr2Lkup[n]); 01069 m_bytes |= Q_ROM_BYTE(QF_pwr2Lkup[m + static_cast<uint8_t>(1)]); 01070 } 01071 01072 /// \brief remove element \a n from the set, n = 1..64 01073 void remove(uint8_t const n) { 01074 uint8_t m = Q_ROM_BYTE(QF_div8Lkup[n]); 01075 if ((m_bits[m] &= Q_ROM_BYTE(QF_invPwr2Lkup[n])) 01076 == static_cast<uint8_t>(0)) 01077 { 01078 m_bytes &=Q_ROM_BYTE(QF_invPwr2Lkup[m + static_cast<uint8_t>(1)]); 01079 } 01080 } 01081 01082 /// \brief find the maximum element in the set, 01083 /// \note returns zero if the set is empty 01084 uint8_t findMax(void) const { 01085 uint8_t n; 01086 if (m_bytes != static_cast<uint8_t>(0)) { 01087 n = static_cast<uint8_t>(Q_ROM_BYTE(QF_log2Lkup[m_bytes]) 01088 - static_cast<uint8_t>(1)); 01089 n = static_cast<uint8_t>( 01090 Q_ROM_BYTE(QF_log2Lkup[m_bits[n]]) 01091 + static_cast<uint8_t>(n << 3)); 01092 } 01093 else { 01094 n = static_cast<uint8_t>(0); 01095 } 01096 return n; 01097 } 01098 }; 01099 01100 QP_END_ 01101 01102 01103 ////////////////////////////////////////////////////////////////////////////// 01104 // Kernel selection based on QK_PREEMPTIVE 01105 // 01106 #ifdef QK_PREEMPTIVE 01107 01108 // "qk.h" ==================================================================== 01109 /// \brief This macro defines the type of the event queue used for the 01110 /// active objects. 01111 /// 01112 /// \note This is just an example of the macro definition. Typically, you need 01113 /// to define it in the specific QF port file (qf_port.h). In case of QK, 01114 /// which always depends on the native QF queue, this macro is defined at the 01115 /// level of the platform-independent interface qk.h. 01116 #define QF_EQUEUE_TYPE QEQueue 01117 01118 #if defined(QK_TLS) || defined(QK_EXT_SAVE) 01119 /// \brief This macro defines the type of the OS-Object used for blocking 01120 /// the native QF event queue when the queue is empty 01121 /// 01122 /// In QK, the OS object is used to hold the per-thread flags, which might 01123 /// be used, for example, to rembember the thread attributes (e.g., 01124 /// if the thread uses a floating point co-processor). The OS object value 01125 /// is set on per-thread basis in QActive::start(). Later, the extended 01126 /// context switch macros (QK_EXT_SAVE() and QK_EXT_RESTORE()) might use 01127 /// the per-thread flags to determine what kind of extended context switch 01128 /// this particular thread needs (e.g., the thread might not be using the 01129 /// coprocessor or might be using a different one). 01130 #define QF_OS_OBJECT_TYPE uint8_t 01131 01132 /// \brief This macro defines the type of the thread handle used for the 01133 /// active objects. 01134 /// 01135 /// The thread type in QK is the pointer to the thread-local storage (TLS) 01136 /// This thread-local storage can be set on per-thread basis in 01137 /// QActive::start(). Later, the QK scheduler, passes the pointer to the 01138 /// thread-local storage to the macro #QK_TLS. 01139 #define QF_THREAD_TYPE void * 01140 #endif // QK_TLS || QK_EXT_SAVE 01141 01142 #if (QF_MAX_ACTIVE <= 8) 01143 extern "C" QP_ QPSet8 QK_readySet_; ///< ready set of QK 01144 #else 01145 extern "C" QP_ QPSet64 QK_readySet_; ///< ready set of QK 01146 #endif 01147 01148 extern "C" uint8_t QK_currPrio_; ///< current task/interrupt priority 01149 extern "C" uint8_t QK_intNest_; ///< interrupt nesting level 01150 01151 // QK active object queue implementation ..................................... 01152 01153 /// \brief Platform-dependent macro defining how QF should block the calling 01154 /// task when the QF native queue is empty 01155 /// 01156 /// \note This is just an example of #QACTIVE_EQUEUE_WAIT_ for the QK-port 01157 /// of QF. QK never activates a task that has no events to process, so in this 01158 /// case the macro asserts that the queue is not empty. In other QF ports you 01159 // need to define the macro appropriately for the underlying kernel/OS you're 01160 /// using. 01161 #define QACTIVE_EQUEUE_WAIT_(me_) \ 01162 Q_ASSERT((me_)->m_eQueue.m_frontEvt != static_cast<QEvt const *>(0)) 01163 01164 /// \brief Platform-dependent macro defining how QF should signal the 01165 /// active object task that an event has just arrived. 01166 /// 01167 /// The macro is necessary only when the native QF event queue is used. 01168 /// The signaling of task involves unblocking the task if it is blocked. 01169 /// 01170 /// \note #QACTIVE_EQUEUE_SIGNAL_ is called from a critical section. 01171 /// It might leave the critical section internally, but must restore 01172 /// the critical section before exiting to the caller. 01173 /// 01174 /// \note This is just an example of #QACTIVE_EQUEUE_SIGNAL_ for the QK-port 01175 /// of QF. In other QF ports you need to define the macro appropriately for 01176 /// the underlying kernel/OS you're using. 01177 #define QACTIVE_EQUEUE_SIGNAL_(me_) do { \ 01178 QK_readySet_.insert((me_)->m_prio); \ 01179 if (QK_intNest_ == static_cast<uint8_t>(0)) { \ 01180 uint8_t p = QK_schedPrio_(); \ 01181 if (p != static_cast<uint8_t>(0)) { \ 01182 QK_sched_(p); \ 01183 } \ 01184 } \ 01185 } while (false) 01186 01187 /// \brief Platform-dependent macro defining the action QF should take 01188 /// when the native QF event queue becomes empty. 01189 /// 01190 /// \note #QACTIVE_EQUEUE_ONEMPTY_ is called from a critical section. 01191 /// It should not leave the critical section. 01192 /// 01193 /// \note This is just an example of #QACTIVE_EQUEUE_ONEMPTY_ for the QK-port 01194 /// of QF. In other QF ports you need to define the macro appropriately for 01195 /// the underlying kernel/OS you're using. 01196 #define QACTIVE_EQUEUE_ONEMPTY_(me_) \ 01197 QK_readySet_.remove((me_)->m_prio) 01198 01199 // QK event pool operations .................................................. 01200 01201 /// \brief This macro defines the type of the event pool used in this QF port. 01202 /// 01203 /// \note This is a specific implementation for the QK-port of QF. 01204 /// In other QF ports you need to define the macro appropriately for 01205 /// the underlying kernel/OS you're using. 01206 #define QF_EPOOL_TYPE_ QMPool 01207 01208 /// \brief Platform-dependent macro defining the event pool initialization 01209 /// 01210 /// \note This is a specific implementation for the QK-port of QF. 01211 /// In other QF ports you need to define the macro appropriately for 01212 /// the underlying kernel/OS you're using. 01213 #define QF_EPOOL_INIT_(p_, poolSto_, poolSize_, evtSize_) \ 01214 (p_).init((poolSto_), (poolSize_), \ 01215 static_cast<QMPoolSize>(evtSize_)) 01216 01217 /// \brief Platform-dependent macro defining how QF should obtain the 01218 /// event pool block-size 01219 /// 01220 /// \note This is a specific implementation for the QK-port of QF. 01221 /// In other QF ports you need to define the macro appropriately for 01222 /// the underlying kernel/OS you're using. 01223 #define QF_EPOOL_EVENT_SIZE_(p_) \ 01224 static_cast<uint32_t>((p_).getBlockSize()) 01225 01226 /// \brief Platform-dependent macro defining how QF should obtain an event 01227 /// \a e_ from the event pool \a p_ 01228 /// 01229 /// \note This is a specific implementation for the QK-port of QF. 01230 /// In other QF ports you need to define the macro appropriately for 01231 /// the underlying kernel/OS you're using. 01232 #define QF_EPOOL_GET_(p_, e_) ((e_) = static_cast<QEvt *>((p_).get())) 01233 01234 /// \brief Platform-dependent macro defining how QF should return an event 01235 /// \a e_ to the event pool \a p_ 01236 /// 01237 /// \note This is a specific implementation for the QK-port of QF. 01238 /// In other QF ports you need to define the macro appropriately for 01239 /// the underlying kernel/OS you're using. 01240 #define QF_EPOOL_PUT_(p_, e_) ((p_).put(e_)) 01241 01242 ////////////////////////////////////////////////////////////////////////////// 01243 QP_BEGIN_ 01244 01245 #ifndef QK_NO_MUTEX 01246 ////////////////////////////////////////////////////////////////////////// 01247 /// \brief QK Mutex type. 01248 /// 01249 /// QMutex represents the priority-ceiling mutex available in QK. 01250 /// \sa QK::mutexLock() 01251 /// \sa QK::mutexUnlock() 01252 typedef uint8_t QMutex; 01253 #endif // QK_NO_MUTEX 01254 01255 ////////////////////////////////////////////////////////////////////////////// 01256 /// \brief QK services. 01257 /// 01258 /// This class groups together QK services. It has only static members and 01259 /// should not be instantiated. 01260 /// 01261 // \note The QK scheduler, QK priority, QK ready set, etc. belong conceptually 01262 /// to the QK class (as static class members). However, to avoid C++ potential 01263 /// name-mangling problems in assembly language, these elements are defined 01264 /// outside of the QK class and use the extern "C" linkage specification. 01265 /// 01266 class QK { 01267 public: 01268 01269 /// \brief get the current QK version number string 01270 /// 01271 /// \return version of the QK as a constant 6-character string of the 01272 /// form x.y.zz, where x is a 1-digit major version number, y is a 01273 /// 1-digit minor version number, and zz is a 2-digit release number. 01274 static char_t const Q_ROM * Q_ROM_VAR getVersion(void); 01275 01276 /// \brief QK idle callback (customized in BSPs for QK) 01277 /// 01278 /// QK::onIdle() is called continously by the QK idle loop. This callback 01279 /// gives the application an opportunity to enter a power-saving CPU mode, 01280 /// or perform some other idle processing. 01281 /// 01282 /// \note QK::onIdle() is invoked with interrupts unlocked and must also 01283 /// return with interrupts unlocked. 01284 /// 01285 /// \sa QF::onIdle() 01286 static void onIdle(void); 01287 01288 #ifndef QK_NO_MUTEX 01289 01290 /// \brief QK priority-ceiling mutex lock 01291 /// 01292 /// Lock the QK scheduler up to the priority level \a prioCeiling. 01293 /// 01294 // \note This function should be always paired with QK::mutexUnlock(). 01295 /// The code between QK::mutexLock() and QK::mutexUnlock() should be 01296 /// kept to the minimum. 01297 /// 01298 /// \include qk_mux.cpp 01299 static QMutex mutexLock(uint8_t const prioCeiling); 01300 01301 /// \brief QK priority-ceiling mutex unlock 01302 /// 01303 /// \note This function should be always paired with QK::mutexLock(). 01304 /// The code between QK::mutexLock() and QK::mutexUnlock() should be 01305 /// kept to the minimum. 01306 /// 01307 /// \include qk_mux.cpp 01308 static void mutexUnlock(QMutex const mutex); 01309 01310 #endif // QK_NO_MUTEX 01311 01312 }; 01313 01314 QP_END_ 01315 01316 ////////////////////////////////////////////////////////////////////////////// 01317 extern "C" { 01318 01319 /// \brief QK initialization 01320 /// 01321 /// QK_init() is called from QF_init() in qk.cpp. This function is 01322 /// defined in the QK ports. 01323 void QK_init(void); 01324 01325 /// \brief The QK scheduler 01326 /// 01327 /// \note The QK scheduler must be always called with the interrupts 01328 /// disabled and enables interrupts internally. 01329 /// 01330 /// \sa QK_schedPrio_() 01331 void QK_sched_(uint8_t p); 01332 01333 /// \brief The QK extended scheduler for interrupt context 01334 /// 01335 /// \note The QK extended exscheduler must be always called with the 01336 /// interrupts disabled and enables interrupts internally. 01337 /// 01338 /// \sa QK_schedPrio_() 01339 void QK_schedExt_(uint8_t p); 01340 01341 /// \brief Find the highest-priority task ready to run 01342 /// 01343 /// \note QK_schedPrio_() must be always called with interrupts disabled 01344 /// and returns with interrupts disabled. 01345 uint8_t QK_schedPrio_(void); 01346 01347 } // extern "C" 01348 01349 #else // QK_PREEMPTIVE 01350 01351 // "qvanilla.h" ============================================================== 01352 /// \brief platform-independent interface to the cooperative "vanilla" kernel. 01353 01354 QP_BEGIN_ 01355 // the event queue type for the "Vanilla" kernel 01356 #define QF_EQUEUE_TYPE QEQueue 01357 // native event queue operations 01358 #define QACTIVE_EQUEUE_WAIT_(me_) \ 01359 Q_ASSERT((me_)->m_eQueue.m_frontEvt != static_cast<QEvt const *>(0)) 01360 01361 #define QACTIVE_EQUEUE_SIGNAL_(me_) \ 01362 (QF_readySet_.insert((me_)->m_prio)) 01363 01364 #define QACTIVE_EQUEUE_ONEMPTY_(me_) \ 01365 (QF_readySet_.remove((me_)->m_prio)) 01366 01367 // native QF event pool operations 01368 #define QF_EPOOL_TYPE_ QMPool 01369 #define QF_EPOOL_INIT_(p_, poolSto_, poolSize_, evtSize_) \ 01370 (p_).init((poolSto_), (poolSize_), static_cast<QMPoolSize>(evtSize_)) 01371 #define QF_EPOOL_EVENT_SIZE_(p_) \ 01372 static_cast<uint32_t>((p_).getBlockSize()) 01373 #define QF_EPOOL_GET_(p_, e_) ((e_) = static_cast<QEvt *>((p_).get())) 01374 #define QF_EPOOL_PUT_(p_, e_) ((p_).put(e_)) 01375 01376 QP_END_ 01377 01378 #if (QF_MAX_ACTIVE <= 8) 01379 extern "C" QP_ QPSet8 QF_readySet_; ///< ready set of active objects 01380 #else 01381 extern "C" QP_ QPSet64 QF_readySet_; ///< ready set of active objects 01382 #endif 01383 01384 extern "C" uint8_t QF_currPrio_; ///< current task/interrupt priority 01385 extern "C" uint8_t QF_intNest_; ///< interrupt nesting level 01386 01387 #endif // QK_PREEMPTIVE 01388 01389 01390 // qf.h (QF platform-independent public interface) =========================== 01391 01392 /// \brief QF/C++ platform-independent public interface. 01393 /// 01394 /// This header file must be included directly or indirectly 01395 /// in all modules (*.cpp files) that use QF/C++. 01396 01397 ////////////////////////////////////////////////////////////////////////////// 01398 #ifdef Q_EVT_CTOR 01399 #include <new> // for placement new 01400 #endif 01401 01402 ////////////////////////////////////////////////////////////////////////////// 01403 // apply defaults for all undefined configuration parameters 01404 // 01405 #ifndef QF_EVENT_SIZ_SIZE 01406 /// \brief Default value of the macro configurable value in qf_port.h 01407 #define QF_EVENT_SIZ_SIZE 2 01408 #endif 01409 01410 #ifndef QF_MAX_EPOOL 01411 /// \brief Default value of the macro configurable value in qf_port.h 01412 #define QF_MAX_EPOOL 3 01413 #endif 01414 01415 #ifndef QF_TIMEEVT_CTR_SIZE 01416 /// \brief macro to override the default QTimeEvtCtr size. 01417 /// Valid values 1, 2, or 4; default 2 01418 #define QF_TIMEEVT_CTR_SIZE 2 01419 #endif 01420 01421 #if (QF_MAX_ACTIVE < 1) || (63 < QF_MAX_ACTIVE) 01422 #error "QF_MAX_ACTIVE not defined or out of range. Valid range is 1..63" 01423 #endif 01424 01425 #ifndef QF_ACTIVE_SUPER_ 01426 01427 ////////////////////////////////////////////////////////////////////////// 01428 /// \brief The macro defining the base class for QActive. 01429 /// 01430 /// By default, the ::QActive class is derived from ::QHsm. However, 01431 /// if the macro QF_ACTIVE_SUPER_ is defined, QActive is derived from 01432 /// QF_ACTIVE_SUPER_. 01433 /// 01434 /// Clients might choose, for example, to define QF_ACTIVE_SUPER_ as QFsm 01435 /// to avoid the 1-2KB overhead of the hierarchical event processor. 01436 /// 01437 /// Clients might also choose to define QF_ACTIVE_SUPER_ as their own 01438 /// completely customized class that has nothing to do with QHsm or QFsm. 01439 /// The QF_ACTIVE_SUPER_ class must provide member functions init() and 01440 /// dispatch(), consistent with the signatures of QHsm and QFsm. But 01441 /// the implementatin of these functions is completely open. 01442 #define QF_ACTIVE_SUPER_ QHsm 01443 01444 /// \brief The argument of the base class' constructor. 01445 #define QF_ACTIVE_STATE_ QStateHandler 01446 01447 #endif 01448 01449 ////////////////////////////////////////////////////////////////////////////// 01450 QP_BEGIN_ 01451 01452 ////////////////////////////////////////////////////////////////////////////// 01453 #if (QF_EVENT_SIZ_SIZE == 1) 01454 01455 /// \brief The data type to store the block-size defined based on 01456 /// the macro #QF_EVENT_SIZ_SIZE. 01457 /// 01458 /// The dynamic range of this data type determines the maximum block 01459 /// size that can be managed by the pool. 01460 typedef uint8_t QEvtSize; 01461 #elif (QF_EVENT_SIZ_SIZE == 2) 01462 typedef uint16_t QEvtSize; 01463 #elif (QF_EVENT_SIZ_SIZE == 4) 01464 typedef uint32_t QEvtSize; 01465 #else 01466 #error "QF_EVENT_SIZ_SIZE defined incorrectly, expected 1, 2, or 4" 01467 #endif 01468 01469 ////////////////////////////////////////////////////////////////////////////// 01470 #if (QF_TIMEEVT_CTR_SIZE == 1) 01471 /// \brief type of the Time Event counter, which determines the dynamic 01472 /// range of the time delays measured in clock ticks. 01473 /// 01474 /// This typedef is configurable via the preprocessor switch 01475 /// #QF_TIMEEVT_CTR_SIZE. The other possible values of this type are 01476 /// as follows: \n 01477 /// uint8_t when (QF_TIMEEVT_CTR_SIZE == 1), and \n 01478 /// uint32_t when (QF_TIMEEVT_CTR_SIZE == 4). 01479 typedef uint8_t QTimeEvtCtr; 01480 #elif (QF_TIMEEVT_CTR_SIZE == 2) 01481 typedef uint16_t QTimeEvtCtr; 01482 #elif (QF_TIMEEVT_CTR_SIZE == 4) 01483 typedef uint32_t QTimeEvtCtr; 01484 #else 01485 #error "QF_TIMEEVT_CTR_SIZE defined incorrectly, expected 1, 2, or 4" 01486 #endif 01487 01488 class QEQueue; // forward declaration 01489 01490 ////////////////////////////////////////////////////////////////////////////// 01491 /// \brief Base class for derivation of application-level active object 01492 /// classes. 01493 /// 01494 /// QActive is the base class for derivation of active objects. Active objects 01495 /// in QF are encapsulated tasks (each embedding a state machine and an event 01496 /// queue) that communicate with one another asynchronously by sending and 01497 /// receiving events. Within an active object, events are processed 01498 /// sequentially in a run-to-completion (RTC) fashion, while QF encapsulates 01499 /// all the details of thread-safe event exchange and queuing. 01500 /// 01501 /// \note QActive is not intended to be instantiated directly, but rather 01502 /// serves as the base class for derivation of active objects in the 01503 /// application code. 01504 /// 01505 /// The following example illustrates how to derive an active object from 01506 /// QActive. 01507 /// \include qf_qactive.cpp 01508 /// 01509 /// \sa #QF_ACTIVE_SUPER_ defines the base class for QActive 01510 class QActive : public QF_ACTIVE_SUPER_ { 01511 01512 #ifdef QF_EQUEUE_TYPE 01513 /// \brief OS-dependent event-queue type. 01514 /// 01515 /// The type of the queue depends on the underlying operating system or 01516 /// a kernel. Many kernels support "message queues" that can be adapted 01517 /// to deliver QF events to the active object. Alternatively, QF provides 01518 /// a native event queue implementation that can be used as well. 01519 /// 01520 /// The native QF event queue is configured by defining the macro 01521 /// #QF_EQUEUE_TYPE as ::QEQueue. 01522 QF_EQUEUE_TYPE m_eQueue; 01523 #endif 01524 01525 #ifdef QF_OS_OBJECT_TYPE 01526 /// \brief OS-dependent per-thread object. 01527 /// 01528 /// This data might be used in various ways, depending on the QF port. 01529 /// In some ports m_osObject is used to block the calling thread when 01530 /// the native QF queue is empty. In other QF ports the OS-dependent 01531 /// object might be used differently. 01532 QF_OS_OBJECT_TYPE m_osObject; 01533 #endif 01534 01535 #ifdef QF_THREAD_TYPE 01536 /// \brief OS-dependent representation of the thread of the active 01537 /// object. 01538 /// 01539 /// This data might be used in various ways, depending on the QF port. 01540 /// In some ports m_thread is used store the thread handle. In other ports 01541 /// m_thread can be a pointer to the Thread-Local-Storage (TLS). 01542 QF_THREAD_TYPE m_thread; 01543 #endif 01544 01545 /// \brief QF priority associated with the active object. 01546 /// \sa QActive::start() 01547 uint8_t m_prio; 01548 01549 public: 01550 /// \brief Starts execution of an active object and registers the object 01551 /// with the framework. 01552 /// 01553 /// The function takes six arguments. 01554 /// \a prio is the priority of the active object. QF allows you to start 01555 /// up to 63 active objects, each one having a unique priority number 01556 /// between 1 and 63 inclusive, where higher numerical values correspond 01557 /// to higher priority (urgency) of the active object relative to the 01558 /// others. 01559 /// \a qSto[] and \a qLen arguments are the storage and size of the event 01560 /// queue used by this active object. 01561 /// \a stkSto and \a stkSize are the stack storage and size in bytes. 01562 /// Please note that a per-active object stack is used only when the 01563 /// underlying OS requies it. If the stack is not required, or the 01564 /// underlying OS allocates the stack internally, the \a stkSto should be 01565 /// NULL and/or \a stkSize should be 0. 01566 /// \a ie is an optional initialization event that can be used to pass 01567 /// additional startup data to the active object. (Pass NULL if your 01568 /// active object does not expect the initialization event). 01569 /// 01570 /// \note This function is strongly OS-dependent and must be defined in 01571 /// the QF port to a particular platform. 01572 /// 01573 /// The following example shows starting of the Philosopher object when a 01574 /// per-task stack is required: 01575 /// \include qf_start.cpp 01576 void start(uint8_t const prio, 01577 QEvt const *qSto[], uint32_t const qLen, 01578 void * const stkSto, uint32_t const stkSize, 01579 QEvt const * const ie = static_cast<QEvt *>(0)); 01580 01581 /// \brief Posts an event \a e directly to the event queue of the acitve 01582 /// object \a me using the First-In-First-Out (FIFO) policy. 01583 /// 01584 /// Direct event posting is the simplest asynchronous communication method 01585 /// available in QF. The following example illustrates how the Philosopher 01586 /// active obejct posts directly the HUNGRY event to the Table active 01587 /// object. \include qf_post.cpp 01588 /// 01589 /// \note The producer of the event (Philosopher in this case) must only 01590 /// "know" the recipient (Table) by a generic (QActive *QDPP_table) 01591 /// pointer, but the specific definition of the Table class is not 01592 /// required. 01593 /// 01594 /// \note Direct event posting should not be confused with direct event 01595 /// dispatching. In contrast to asynchronous event posting through event 01596 /// queues, direct event dispatching is synchronous. Direct event 01597 /// dispatching occurs when you call QHsm::dispatch(), or QFsm::dispatch() 01598 /// function. 01599 #ifndef Q_SPY 01600 void postFIFO(QEvt const * const e); 01601 #else 01602 void postFIFO(QEvt const * const e, void const * const sender); 01603 #endif 01604 01605 /// \brief Un-subscribes from the delivery of all signals to the active 01606 /// object. 01607 /// 01608 /// This function is part of the Publish-Subscribe event delivery 01609 /// mechanism available in QF. Un-subscribing from all events means that 01610 /// the framework will stop posting any published events to the event 01611 /// queue of the active object. 01612 /// 01613 /// \note Due to the latency of event queues, an active object should NOT 01614 /// assume that no events will ever be dispatched to the state machine of 01615 /// the active object after un-subscribing from all events. 01616 /// The events might be already in the queue, or just about to be posted 01617 /// and the un-subscribe operation will not flush such events. Also, the 01618 /// alternative event-delivery mechanisms, such as direct event posting or 01619 /// time events, can be still delivered to the event queue of the active 01620 /// object. 01621 /// 01622 /// \sa QF::publish(), QActive::subscribe(), and QActive::unsubscribe() 01623 void unsubscribeAll(void) const; 01624 01625 protected: 01626 /// \brief protected constructor 01627 /// 01628 /// Performs the first step of active object initialization by assigning 01629 /// the initial pseudostate to the currently active state of the state 01630 /// machine. 01631 /// 01632 /// \note The constructor is protected to prevent direct instantiation 01633 /// of QActive objects. This class is intended only for derivation 01634 /// (abstract class). 01635 QActive(QF_ACTIVE_STATE_ const initial) : QF_ACTIVE_SUPER_(initial) { 01636 } 01637 01638 /// \brief Posts an event directly to the event queue of the active object 01639 /// \a me using the Last-In-First-Out (LIFO) policy. 01640 /// 01641 /// \note The LIFO policy should be used only for self-posting and with 01642 /// great caution because it alters order of events in the queue. 01643 /// 01644 /// \sa QActive::postFIFO() 01645 void postLIFO(QEvt const * const e); 01646 01647 /// \brief Stops execution of an active object and removes it from the 01648 /// framework's supervision. 01649 /// 01650 /// The preferred way of calling this function is from within the active 01651 /// object that needs to stop (that's why this function is protected). 01652 /// In other words, an active object should stop itself rather than being 01653 /// stopped by some other entity. This policy works best, because only 01654 /// the active object itself "knows" when it has reached the appropriate 01655 /// state for the shutdown. 01656 /// 01657 /// \note This function is strongly OS-dependent and should be defined in 01658 /// the QF port to a particular platform. This function is optional in 01659 /// embedded systems where active objects never need to be stopped. 01660 void stop(void); 01661 01662 /// \brief Subscribes for delivery of signal \a sig to the active object 01663 /// 01664 /// This function is part of the Publish-Subscribe event delivery 01665 /// mechanism available in QF. Subscribing to an event means that the 01666 /// framework will start posting all published events with a given signal 01667 /// \a sig to the event queue of the active object. 01668 /// 01669 /// The following example shows how the Table active object subscribes 01670 /// to three signals in the initial transition: 01671 /// \include qf_subscribe.cpp 01672 /// 01673 /// \sa QF::publish(), QActive::unsubscribe(), and 01674 /// QActive::unsubscribeAll() 01675 void subscribe(enum_t const sig) const; 01676 01677 /// \brief Un-subscribes from the delivery of signal \a sig to the 01678 /// active object. 01679 /// 01680 /// This function is part of the Publish-Subscribe event delivery 01681 /// mechanism available in QF. Un-subscribing from an event means that 01682 /// the framework will stop posting published events with a given signal 01683 /// \a sig to the event queue of the active object. 01684 /// 01685 /// \note Due to the latency of event queues, an active object should NOT 01686 /// assume that a given signal \a sig will never be dispatched to the 01687 /// state machine of the active object after un-subscribing from that 01688 /// signal. The event might be already in the queue, or just about to be 01689 /// posted and the un-subscribe operation will not flush such events. 01690 /// 01691 /// \note Un-subscribing from a signal that has never been subscribed in 01692 /// the first place is considered an error and QF will rise an assertion. 01693 /// 01694 /// \sa QF::publish(), QActive::subscribe(), and QActive::unsubscribeAll() 01695 void unsubscribe(enum_t const sig) const; 01696 01697 /// \brief Defer an event to a given separate event queue. 01698 /// 01699 /// This function is part of the event deferral support. An active object 01700 /// uses this function to defer an event \a e to the QF-supported native 01701 /// event queue \a eq. QF correctly accounts for another outstanding 01702 /// reference to the event and will not recycle the event at the end of 01703 /// the RTC step. Later, the active object might recall one event at a 01704 /// time from the event queue. 01705 /// 01706 /// An active object can use multiple event queues to defer events of 01707 /// different kinds. 01708 /// 01709 /// \sa QActive::recall(), QEQueue 01710 void defer(QEQueue * const eq, QEvt const * const e) const; 01711 01712 /// \brief Recall a deferred event from a given event queue. 01713 /// 01714 /// This function is part of the event deferral support. An active object 01715 /// uses this function to recall a deferred event from a given QF 01716 /// event queue. Recalling an event means that it is removed from the 01717 /// deferred event queue \a eq and posted (LIFO) to the event queue of 01718 /// the active object. 01719 /// 01720 /// QActive::recall() returns true if an event has been recalled. 01721 /// Otherwise the function returns false. 01722 /// 01723 /// An active object can use multiple event queues to defer events of 01724 /// different kinds. 01725 /// 01726 /// \sa QActive::defer(), QEQueue, QActive::postLIFO() 01727 bool recall(QEQueue * const eq); 01728 01729 private: 01730 01731 /// \brief Get an event from the event queue of an active object. 01732 /// 01733 /// This function is used internally by a QF port to extract events from 01734 /// the event queue of an active object. This function depends on the 01735 /// event queue implementation and is sometimes implemented in the QF port 01736 /// (qf_port.cpp file). Depending on the underlying OS or kernel, the 01737 /// function might block the calling thread when no events are available. 01738 /// 01739 /// \note QActive::get_() is public because it often needs to be called 01740 /// from thread-run routines with difficult to foresee signature (so 01741 /// declaring friendship with such function(s) is not possible.) 01742 /// 01743 /// \sa QActive::postFIFO(), QActive::postLIFO() 01744 QEvt const *get_(void); 01745 01746 friend class QF; 01747 friend class QTimeEvt; 01748 01749 #ifdef QK_PREEMPTIVE // is this QK port? 01750 friend void ::QK_schedExt_(uint8_t p); 01751 friend void ::QK_sched_(uint8_t p); 01752 #endif 01753 01754 }; 01755 01756 ////////////////////////////////////////////////////////////////////////////// 01757 /// \brief Time Event class 01758 /// 01759 /// Time events are special QF events equipped with the notion of time 01760 /// passage. The basic usage model of the time events is as follows. An 01761 /// active object allocates one or more QTimeEvt objects (provides the 01762 /// storage for them). When the active object needs to arrange for a timeout, 01763 /// it arms one of its time events to fire either just once (one-shot) or 01764 /// periodically. Each time event times out independently from the others, 01765 /// so a QF application can make multiple parallel timeout requests (from the 01766 /// same or different active objects). When QF detects that the appropriate 01767 /// moment has arrived, it inserts the time event directly into the 01768 /// recipient's event queue. The recipient then processes the time event just 01769 /// like any other event. 01770 /// 01771 /// Time events, as any other QF events derive from the ::QEvt base 01772 /// class. Typically, you will use a time event as-is, but you can also 01773 /// further derive more specialized time events from it by adding some more 01774 /// data members and/or specialized functions that operate on the specialized 01775 /// time events. 01776 /// 01777 /// Internally, the armed time events are organized into a bi-directional 01778 /// linked list. This linked list is scanned in every invocation of the 01779 /// QF::tick() function. Only armed (timing out) time events are in the list, 01780 /// so only armed time events consume CPU cycles. 01781 /// 01782 /// \note QF manages the time events in the function QF::tick(), which 01783 /// must be called periodically, preferably from the clock tick ISR. 01784 /// \note In this version of QF QTimeEvt objects should be allocated 01785 /// statically rather than dynamically from event pools. Currently, QF will 01786 /// not correctly recycle the dynamically allocated Time Events. 01787 class QTimeEvt : public QEvt { 01788 private: 01789 01790 /// link to the next time event in the list 01791 QTimeEvt *m_next; 01792 01793 /// the active object that receives the time events. 01794 QActive *m_act; 01795 01796 /// the internal down-counter of the time event. The down-counter 01797 /// is decremented by 1 in every QF_tick() invocation. The time event 01798 /// fires (gets posted or published) when the down-counter reaches zero. 01799 QTimeEvtCtr m_ctr; 01800 01801 /// the interval for the periodic time event (zero for the one-shot 01802 /// time event). The value of the interval is re-loaded to the internal 01803 /// down-counter when the time event expires, so that the time event 01804 /// keeps timing out periodically. 01805 QTimeEvtCtr m_interval; 01806 01807 public: 01808 01809 /// \brief The Time Event constructor. 01810 /// 01811 /// The most important initialization performed in the constructor is 01812 /// assigning a signal to the Time Event. You can reuse the Time Event 01813 /// any number of times, but you cannot change the signal. 01814 /// This is because pointers to Time Events might still be held in event 01815 /// queues and changing signal could to hard-to-detect errors. 01816 /// 01817 /// The following example shows the use of QTimeEvt::QTimeEvt() 01818 /// constructor in the constructor initializer list of the Philosopher 01819 /// active object constructor that owns the time event 01820 /// \include qf_ctor.cpp 01821 QTimeEvt(enum_t const s); 01822 01823 /// \brief Arm a one-shot time event for direct event posting. 01824 /// 01825 /// Arms a time event to fire in \a nTicks clock ticks (one-shot time 01826 /// event). The time event gets directly posted (using the FIFO policy) 01827 /// into the event queue of the active object \a act. 01828 /// 01829 /// After posting, the time event gets automatically disarmed and can be 01830 /// reused for a one-shot or periodic timeout requests. 01831 /// 01832 /// A one-shot time event can be disarmed at any time by calling the 01833 /// QTimeEvt::disarm() function. Also, a one-shot time event can be 01834 /// re-armed to fire in a different number of clock ticks by calling the 01835 /// QTimeEvt::rearm() function. 01836 /// 01837 /// The following example shows how to arm a one-shot time event from a 01838 /// state machine of an active object: 01839 /// \include qf_state.cpp 01840 void postIn(QActive * const act, QTimeEvtCtr const nTicks) { 01841 m_interval = static_cast<QTimeEvtCtr>(0); 01842 arm_(act, nTicks); 01843 } 01844 01845 /// \brief Arm a periodic time event for direct event posting. 01846 /// 01847 /// Arms a time event to fire every \a nTicks clock ticks (periodic time 01848 /// event). The time event gets directly posted (using the FIFO policy) 01849 /// into the event queue of the active object \a act. 01850 /// 01851 /// After posting, the time event gets automatically re-armed to fire 01852 /// again in the specified \a nTicks clock ticks. 01853 /// 01854 /// A periodic time event can be disarmed only by calling the 01855 /// QTimeEvt::disarm() function. After disarming, the time event can be 01856 /// reused for a one-shot or periodic timeout requests. 01857 /// 01858 /// \note An attempt to reuse (arm again) a running periodic time event 01859 /// raises an assertion. 01860 /// 01861 /// Also, a periodic time event can be re-armed to shorten or extend the 01862 /// current period by calling the QTimeEvt_rearm() function. After 01863 /// adjusting the current period, the periodic time event goes back 01864 /// timing out at the original rate. 01865 void postEvery(QActive * const act, QTimeEvtCtr const nTicks) { 01866 m_interval = nTicks; 01867 arm_(act, nTicks); 01868 } 01869 01870 /// \brief Disarm a time event. 01871 /// 01872 /// The time event gets disarmed and can be reused. The function 01873 /// returns true if the time event was truly disarmed, that is, it 01874 /// was running. The return of false means that the time event was 01875 /// not truly disarmed because it was not running. The 'false' return is 01876 /// only possible for one-shot time events that have been automatically 01877 /// disarmed upon expiration. In this case the 'false' return means that 01878 /// the time event has already been posted or published and should be 01879 /// expected in the active object's state machine. 01880 bool disarm(void); 01881 01882 /// \brief Rearm a time event. 01883 /// 01884 /// The time event gets rearmed with a new number of clock ticks 01885 /// \a nTicks. This facility can be used to prevent a one-shot time event 01886 /// from expiring (e.g., a watchdog time event), or to adjusts the 01887 /// current period of a periodic time event. Rearming a periodic timer 01888 /// leaves the interval unchanged and is a convenient method to adjust 01889 /// the phasing of the periodic time event. 01890 /// 01891 /// The function returns true if the time event was running as it 01892 /// was re-armed. The return of false means that the time event was 01893 /// not truly rearmed because it was not running. The 'false' return is 01894 /// only possible for one-shot time events that have been automatically 01895 /// disarmed upon expiration. In this case the 'false' return means that 01896 /// the time event has already been posted or published and should be 01897 /// expected in the active object's state machine. 01898 bool rearm(QTimeEvtCtr const nTicks); 01899 01900 /// \brief Get the current value of the down-counter of a time event. 01901 /// 01902 /// If the time event is armed, the function returns the current value of 01903 /// the down-counter of the given time event. If the time event is not 01904 /// armed, the function returns 0. 01905 /// 01906 /// /note The function is thread-safe. 01907 QTimeEvtCtr ctr(void) const; 01908 01909 private: 01910 01911 /// \brief Arm a time event (internal function to be used through macros 01912 /// only). 01913 /// 01914 /// \sa QTimeEvt::postIn(), QTimeEvt::postEvery(), 01915 /// \sa QTimeEvt::publishIn(), QTimeEvt::publishEvery() 01916 void arm_(QActive * const act, QTimeEvtCtr const nTicks); 01917 01918 friend class QF; 01919 }; 01920 01921 01922 ////////////////////////////////////////////////////////////////////////////// 01923 /// \brief The size of the Subscriber list bit array 01924 /// 01925 /// The size is determined of the maximum number of active objects in the 01926 /// application configured by the #QF_MAX_ACTIVE macro. 01927 uint8_t const QF_SUBSCR_LIST_SIZE = 01928 static_cast<uint8_t>(((QF_MAX_ACTIVE - 1) / 8) + 1); 01929 01930 /// \brief Subscriber List class 01931 /// 01932 /// This data type represents a set of active objects that subscribe to 01933 /// a given signal. The set is represented as an array of bits, where each 01934 /// bit corresponds to the unique priority of an active object. 01935 class QSubscrList { 01936 private: 01937 01938 /// An array of bits representing subscriber active objects. Each bit 01939 /// in the array corresponds to the unique priority of the active object. 01940 /// The size of the array is determined of the maximum number of active 01941 /// objects in the application configured by the #QF_MAX_ACTIVE macro. 01942 /// For example, an active object of priority p is a subscriber if the 01943 /// following is true: ((m_bits[QF_div8Lkup[p]] & QF_pwr2Lkup[p]) != 0) 01944 /// 01945 /// \sa QF::psInit(), QF_div8Lkup, QF_pwr2Lkup, #QF_MAX_ACTIVE 01946 uint8_t m_bits[QF_SUBSCR_LIST_SIZE]; 01947 01948 friend class QF; 01949 friend class QActive; 01950 }; 01951 01952 ////////////////////////////////////////////////////////////////////////////// 01953 /// \brief QF services. 01954 /// 01955 /// This class groups together QF services. It has only static members and 01956 /// should not be instantiated. 01957 class QF { 01958 public: 01959 01960 /// \brief QF initialization. 01961 /// 01962 /// This function initializes QF and must be called exactly once before 01963 /// any other QF function. 01964 static void init(void); 01965 01966 /// \brief Publish-subscribe initialization. 01967 /// 01968 /// This function initializes the publish-subscribe facilities of QF and 01969 /// must be called exactly once before any subscriptions/publications 01970 /// occur in the application. The arguments are as follows: \a subscrSto 01971 /// is a pointer to the array of subscriber-lists. \a maxSignal is the 01972 /// dimension of this array and at the same time the maximum signal that 01973 /// can be published or subscribed. 01974 /// 01975 /// The array of subscriber-lists is indexed by signals and provides 01976 /// mapping between the signals and subscirber-lists. The subscriber- 01977 /// lists are bitmasks of type ::QSubscrList, each bit in the bitmask 01978 /// corresponding to the unique priority of an active object. The size 01979 /// of the ::QSubscrList bitmask depends on the value of the 01980 /// #QF_MAX_ACTIVE macro. 01981 /// 01982 /// \note The publish-subscribe facilities are optional, meaning that 01983 /// you might choose not to use publish-subscribe. In that case calling 01984 /// QF::psInit() and using up memory for the subscriber-lists is 01985 /// unnecessary. 01986 /// 01987 /// \sa ::QSubscrList 01988 /// 01989 /// The following example shows the typical initialization sequence of 01990 /// QF: \include qf_main.cpp 01991 static void psInit(QSubscrList * const subscrSto, 01992 uint32_t const maxSignal); 01993 01994 /// \brief Event pool initialization for dynamic allocation of events. 01995 /// 01996 /// This function initializes one event pool at a time and must be called 01997 /// exactly once for each event pool before the pool can be used. 01998 /// The arguments are as follows: \a poolSto is a pointer to the memory 01999 /// block for the events. \a poolSize is the size of the memory block in 02000 /// bytes. \a evtSize is the block-size of the pool in bytes, which 02001 /// determines the maximum size of events that can be allocated from the 02002 /// pool. 02003 /// 02004 /// You might initialize one, two, and up to three event pools by making 02005 /// one, two, or three calls to the QF_poolInit() function. However, 02006 /// for the simplicity of the internal implementation, you must initialize 02007 /// event pools in the ascending order of the event size. 02008 /// 02009 /// Many RTOSes provide fixed block-size heaps, a.k.a. memory pools that 02010 /// can be used for QF event pools. In case such support is missing, QF 02011 /// provides a native QF event pool implementation. The macro 02012 /// #QF_EPOOL_TYPE_ determines the type of event pool used by a 02013 /// particular QF port. See class ::QMPool for more information. 02014 /// 02015 /// \note The actual number of events available in the pool might be 02016 /// actually less than (\a poolSize / \a evtSize) due to the internal 02017 /// alignment of the blocks that the pool might perform. You can always 02018 /// check the capacity of the pool by calling QF::getPoolMargin(). 02019 /// 02020 /// \note The dynamic allocation of events is optional, meaning that you 02021 /// might choose not to use dynamic events. In that case calling 02022 /// QF::poolInit() and using up memory for the memory blocks is 02023 /// unnecessary. 02024 /// 02025 /// \sa QF initialization example for QF::init() 02026 static void poolInit(void * const poolSto, uint32_t const poolSize, 02027 uint32_t const evtSize); 02028 02029 /// \brief Transfers control to QF to run the application. 02030 /// 02031 /// QF::run() is typically called from your startup code after you 02032 /// initialize the QF and start at least one active object with 02033 /// QActive::start(). Also, QF::start() call must precede the transfer 02034 /// of control to QF::run(), but some QF ports might call QF::start() 02035 /// from QF::run(). QF::run() typically never returns to the caller, 02036 /// but when it does, it returns the error code (0 for success) 02037 /// 02038 /// \note This function is strongly platform-dependent and is not 02039 /// implemented in the QF, but either in the QF port or in the 02040 /// Board Support Package (BSP) for the given application. All QF ports 02041 /// must implement QF::run(). 02042 /// 02043 /// \note When the Quantum Kernel (QK) is used as the underlying real-time 02044 /// kernel for the QF, all platfrom dependencies are handled in the QK, so 02045 /// no porting of QF is necessary. In other words, you only need to 02046 /// recompile the QF platform-independent code with the compiler for your 02047 /// platform, but you don't need to provide any platform-specific 02048 /// implementation (so, no qf_port.cpp file is necessary). Moreover, QK 02049 /// implements the function QF::run() in a platform-independent way, 02050 /// in the modile qk.cpp. 02051 static int16_t run(void); 02052 02053 /// \brief Startup QF callback. 02054 /// 02055 /// The timeline for calling QF::onStartup() depends on the particular 02056 /// QF port. In most cases, QF::onStartup() is called from QF::run(), 02057 /// right before starting any multitasking kernel or the background loop. 02058 static void onStartup(void); 02059 02060 /// \brief Cleanup QF callback. 02061 /// 02062 /// QF::onCleanup() is called in some QF ports before QF returns to the 02063 /// underlying operating system or RTOS. 02064 /// 02065 /// This function is strongly platform-specific and is not implemented in 02066 /// the QF but either in the QF port or in the Board Support Package (BSP) 02067 /// for the given application. Some QF ports might not require 02068 /// implementing QF::onCleanup() at all, because many embedded 02069 /// applications don't have anything to exit to. 02070 /// 02071 /// \sa QF::init() and QF::stop() 02072 static void onCleanup(void); 02073 02074 /// \brief QF idle callback (customized in BSPs for QF) 02075 /// 02076 /// QF::onIdle() is called by the non-preemptive "Vanilla" scheduler built 02077 /// into QF when the framework detects that no events are available for 02078 /// active objects (the idle condition). This callback gives the 02079 /// application an opportunity to enter a power-saving CPU mode, or 02080 /// perform some other idle processing (such as Q-Spy output). 02081 /// 02082 /// \note QF_onIdle() is invoked with interrupts DISABLED because the idle 02083 /// condition can be asynchronously changed at any time by an interrupt. 02084 /// QF_onIdle() MUST enable the interrupts internally, but not before 02085 /// putting the CPU into the low-power mode. (Ideally, enabling interrupts 02086 /// and low-power mode should happen atomically). At the very least, the 02087 /// function MUST enable interrupts, otherwise interrups will remain 02088 /// disabled permanently. 02089 /// 02090 /// \note QF::onIdle() is only used by the non-preemptive "Vanilla" 02091 /// scheduler in the "bare metal" QF port, and is NOT used in any other 02092 /// QF ports. When QF is combined with QK, the QK idle loop calls a 02093 /// different function QK::onIdle(), with different semantics than 02094 /// QF::onIdle(). When QF is combined with a 3rd-party RTOS or kernel, the 02095 /// idle processing mechanism of the RTOS or kernal is used instead of 02096 /// QF::onIdle(). 02097 /// 02098 static void onIdle(void); 02099 02100 /// \brief Function invoked by the application layer to stop the QF 02101 /// application and return control to the OS/Kernel. 02102 /// 02103 /// This function stops the QF application. After calling this function, 02104 /// QF attempts to gracefully stop the application. This graceful 02105 /// shutdown might take some time to complete. The typical use of this 02106 /// funcition is for terminating the QF application to return back to the 02107 /// operating system or for handling fatal errors that require shutting 02108 /// down (and possibly re-setting) the system. 02109 /// 02110 /// This function is strongly platform-specific and is not implemented in 02111 /// the QF but either in the QF port or in the Board Support Package (BSP) 02112 /// for the given application. Some QF ports might not require 02113 /// implementing QF::stop() at all, because many embedded application 02114 /// don't have anything to exit to. 02115 /// 02116 /// \sa QF::stop() and QF::onCleanup() 02117 static void stop(void); 02118 02119 /// \brief Publish event to the framework. 02120 /// 02121 /// This function posts (using the FIFO policy) the event \a e it to ALL 02122 /// active object that have subscribed to the signal \a e->sig. 02123 /// This function is designed to be callable from any part of the system, 02124 /// including ISRs, device drivers, and active objects. 02125 /// 02126 /// In the general case, event publishing requires multi-casting the 02127 /// event to multiple subscribers. This happens in the caller's thread 02128 /// with the scheduler locked to prevent preemptions during the multi- 02129 /// casting process. (Please note that the interrupts are not locked.) 02130 #ifndef Q_SPY 02131 static void publish(QEvt const *e); 02132 #else 02133 static void publish(QEvt const *e, void const *sender); 02134 #endif 02135 02136 /// \brief Processes all armed time events at every clock tick. 02137 /// 02138 /// This function must be called periodically from a time-tick ISR or from 02139 /// the highest-priority task so that QF can manage the timeout events. 02140 /// 02141 /// \note The QF::tick() function is not reentrant meaning that it must 02142 /// run to completion before it is called again. Also, QF::tick() assumes 02143 /// that it never will get preempted by a task, which is always the case 02144 /// when it is called from an ISR or the highest-priority task. 02145 /// 02146 /// \sa ::QTimeEvt. 02147 /// 02148 /// The following example illustrates the call to QF::tick(): 02149 /// \include qf_tick.cpp 02150 #ifndef Q_SPY 02151 static void tick(void); 02152 #else 02153 static void tick(void const * const sender); 02154 #endif 02155 02156 /// \brief Returns true if all time events are inactive and false 02157 /// any time event is active. 02158 /// 02159 /// \note This function should be called in critical section. 02160 static bool noTimeEvtsActive(void); 02161 02162 /// \brief Returns the QF version. 02163 /// 02164 /// This function returns constant version string in the format x.y.zz, 02165 /// where x (one digit) is the major version, y (one digit) is the minor 02166 /// version, and zz (two digits) is the maintenance release version. 02167 /// An example of the version string is "3.1.03". 02168 /// 02169 /// The following example illustrates the usage of this function: 02170 /// \include qf_version.cpp 02171 static char_t const Q_ROM * Q_ROM_VAR getVersion(void); 02172 02173 /// \brief This function returns the margin of the given event pool. 02174 /// 02175 /// This function returns the margin of the given event pool \a poolId, 02176 /// where poolId is the ID of the pool initialized by the call to 02177 /// QF::poolInit(). The poolId of the first initialized pool is 1, the 02178 /// second 2, and so on. 02179 /// 02180 /// The returned pool margin is the minimal number of free blocks 02181 /// encountered in the given pool since system startup. 02182 /// 02183 /// \note Requesting the margin of an un-initialized pool raises an 02184 /// assertion in the QF. 02185 static uint32_t getPoolMargin(uint8_t const poolId); 02186 02187 /// \brief This function returns the margin of the given event queue. 02188 /// 02189 /// This function returns the margin of the given event queue of an active 02190 /// object with priority \a prio. (QF priorities start with 1 and go up to 02191 /// #QF_MAX_ACTIVE.) The margin is the minimal number of free events 02192 /// encountered in the given queue since system startup. 02193 /// 02194 /// \note QF::getQueueMargin() is available only when the native QF event 02195 /// queue implementation is used. Requesting the queue margin of an unused 02196 /// priority level raises an assertion in the QF. (A priority level 02197 /// becomes used in QF after the call to the QF::add_() function.) 02198 static uint32_t getQueueMargin(uint8_t const prio); 02199 02200 /// \brief Internal QF implementation of the dynamic event allocator. 02201 /// 02202 /// \note The application code should not call this function directly. 02203 /// Please use the macro #Q_NEW. 02204 static QEvt *new_(QEvtSize const evtSize, enum_t const sig); 02205 02206 /// \brief Recycle a dynamic event. 02207 /// 02208 /// This function implements a simple garbage collector for the dynamic 02209 /// events. Only dynamic events are candidates for recycling. (A dynamic 02210 /// event is one that is allocated from an event pool, which is 02211 /// determined as non-zero e->attrQF__ attribute.) Next, the function 02212 /// decrements the reference counter of the event, and recycles the event 02213 /// only if the counter drops to zero (meaning that no more references 02214 /// are outstanding for this event). The dynamic event is recycled by 02215 /// returning it to the pool from which it was originally allocated. 02216 /// The pool-of-origin information is stored in the upper 2-MSBs of the 02217 /// e->attrQF__ attribute.) 02218 /// 02219 /// \note QF invokes the garbage collector at all appropriate contexts, 02220 /// when an event can become garbage (automatic garbage collection), 02221 /// so the application code should have NO need to call QF::gc() directly. 02222 /// The QF::gc() function is exposed only for special cases when your 02223 /// application sends dynamic events to the "raw" thread-safe queues 02224 /// (see ::QEQueue). Such queues are processed outside of QF and the 02225 /// automatic garbage collection CANNOT be performed for these events. 02226 /// In this case you need to call QF::gc() explicitly. 02227 static void gc(QEvt const *e); 02228 02229 private: // functions to be used in QF ports only 02230 02231 /// \brief Register an active object to be managed by the framework 02232 /// 02233 /// This function should not be called by the application directly, only 02234 /// through the function QActive::start(). The priority of the active 02235 /// object \a a should be set before calling this function. 02236 /// 02237 /// \note This function raises an assertion if the priority of the active 02238 /// object exceeds the maximum value #QF_MAX_ACTIVE. Also, this function 02239 /// raises an assertion if the priority of the active object is already in 02240 /// use. (QF requires each active object to have a UNIQUE priority.) 02241 static void add_(QActive * const a); 02242 02243 public: 02244 /// \brief Remove the active object from the framework. 02245 /// 02246 /// This function should not be called by the application directly, only 02247 /// inside the QF port. The priority level occupied by the active object 02248 /// is freed-up and can be reused for another active object. 02249 /// 02250 /// The active object that is removed from the framework can no longer 02251 /// participate in the publish-subscribe event exchange. 02252 /// 02253 /// \note This function raises an assertion if the priority of the active 02254 /// object exceeds the maximum value #QF_MAX_ACTIVE or is not used. 02255 static void remove_(QActive const * const a); 02256 02257 /// \brief array of registered active objects 02258 /// 02259 /// \note Not to be used by Clients directly, only in ports of QF 02260 static QActive *active_[]; 02261 02262 /// \brief Thread routine for executing an active object \a act. 02263 /// 02264 /// This function is actually implemented internally by certain QF ports 02265 /// to be called by the active object thread routine. 02266 static void thread_(QActive *act); 02267 02268 friend class QActive; 02269 }; 02270 02271 QP_END_ 02272 02273 ////////////////////////////////////////////////////////////////////////////// 02274 #ifdef Q_EVT_CTOR // Provide the constructor for the QEvt class? 02275 02276 /// \brief Allocate a dynamic event. 02277 /// 02278 /// This macro returns an event pointer cast to the type \a evtT_. The 02279 /// event is initialized with the signal \a sig. Internally, the macro 02280 /// calls the internal QF function QF::new_(), which always returns a 02281 /// valid event pointer. 02282 /// 02283 /// \note The internal QF function QF::new_() raises an assertion when 02284 /// the allocation of the event turns out to be impossible due to 02285 /// event pool depletion, or incorrect (too big) size of the requested 02286 /// event. 02287 /// 02288 /// The following example illustrates dynamic allocation of an event: 02289 /// \include qf_post.cpp 02290 #define Q_NEW(evtT_, sig_, ...) \ 02291 (new(QP_ QF::new_( \ 02292 static_cast<QP_ QEvtSize>(sizeof(evtT_)), (sig_))) \ 02293 evtT_((sig_), ##__VA_ARGS__)) 02294 #else // QEvt is a POD (Plain Old Datatype) 02295 02296 #define Q_NEW(evtT_, sig_) \ 02297 (static_cast<evtT_ *>( \ 02298 QP_ QF::new_(static_cast<QP_ QEvtSize>(sizeof(evtT_)), (sig_)))) 02299 #endif 02300 02301 ////////////////////////////////////////////////////////////////////////////// 02302 // QS software tracing integration, only if enabled 02303 #ifdef Q_SPY // QS software tracing enabled? 02304 02305 /// \brief Invoke the system clock tick processing QF::tick(). This macro 02306 /// is the recommended way of invoking clock tick processing, because it 02307 /// provides the vital information for software tracing and avoids any 02308 /// overhead when the tracing is disabled. 02309 /// 02310 /// This macro takes the argument \a sender_, which is a pointer to the 02311 /// sender object. This argument is actually only used when QS software 02312 /// tracing is enabled (macro #Q_SPY is defined). When QS software 02313 /// tracing is disabled, the macro calls QF::tick() without any 02314 /// arguments, so the overhead of passing this extra argument is 02315 /// entirely avoided. 02316 /// 02317 /// \note the pointer to the sender object is not necessarily a poiner 02318 /// to an active object. In fact, typically QF::TICK() will be called from 02319 /// an interrupt, in which case you would create a unique object just to 02320 /// unambiguously identify the ISR as the sender of the time events. 02321 /// 02322 /// \sa QF::tick() 02323 #define TICK(sender_) tick(sender_) 02324 02325 /// \brief Invoke the event publishing facility QF::publish(). This macro 02326 /// is the recommended way of publishing events, because it provides the 02327 /// vital information for software tracing and avoids any overhead when 02328 /// the tracing is disabled. 02329 /// 02330 /// 02331 /// This macro takes the last argument \a sender_, which is a pointer to 02332 /// the sender object. This argument is actually only used when QS 02333 /// tracing is enabled (macro #Q_SPY is defined). When QS software 02334 /// tracing is disabled, the macro calls QF::publish() without the 02335 /// \a sender_ argument, so the overhead of passing this extra argument 02336 /// is entirely avoided. 02337 /// 02338 /// \note the pointer to the sender object is not necessarily a poiner 02339 /// to an active object. In fact, if QF::PUBLISH() is called from an 02340 /// interrupt or other context, you can create a unique object just to 02341 /// unambiguously identify the publisher of the event. 02342 /// 02343 /// \sa QF::publish() 02344 #define PUBLISH(e_, sender_) publish((e_), (sender_)) 02345 02346 /// \brief Invoke the direct event posting facility QActive::postFIFO(). 02347 /// This macro is the recommended way of posting events, because it 02348 /// provides the vital information for software tracing and avoids any 02349 /// overhead when the tracing is disabled. 02350 /// 02351 /// 02352 /// This macro takes the last argument \a sender_, which is a pointer to 02353 /// the sender object. This argument is actually only used when QS 02354 /// tracing is disabled (macro #Q_SPY is defined). When QS software 02355 /// tracing is not enabled, the macro calls QF_publish() without the 02356 /// \a sender_ argument, so the overhead of passing this extra argument 02357 /// is entirely avoided. 02358 /// 02359 /// \note the pointer to the sender object is not necessarily a poiner 02360 /// to an active object. In fact, if ao->POST() is called from an 02361 /// interrupt or other context, you can create a unique object just to 02362 /// unambiguously identify the publisher of the event. 02363 /// 02364 /// \sa QActive::postFIFO() 02365 #define POST(e_, sender_) postFIFO((e_), (sender_)) 02366 02367 #else 02368 02369 #define TICK(dummy_) tick() 02370 #define PUBLISH(e_, dummy_) publish(e_) 02371 #define POST(e_, dummy_) postFIFO(e_) 02372 02373 #endif // Q_SPY 02374 02375 ////////////////////////////////////////////////////////////////////////////// 02376 // QS software tracing 02377 #ifdef Q_SPY 02378 02379 // qs.h ====================================================================== 02380 /// \brief QS/C++ platform-independent public interface. 02381 /// This header file must be included directly or indirectly 02382 /// in all modules (*.cpp files) that use QS/C++. 02383 02384 #ifndef Q_SPY 02385 #error "Q_SPY must be defined to include qs.h" 02386 #endif 02387 02388 #ifndef Q_ROM // provide the default if Q_ROM NOT defined 02389 #define Q_ROM 02390 #endif 02391 #ifndef Q_ROM_VAR // provide the default if Q_ROM_VAR NOT defined 02392 #define Q_ROM_VAR 02393 #endif 02394 #ifndef Q_ROM_BYTE // provide the default if Q_ROM_BYTE NOT defined 02395 #define Q_ROM_BYTE(rom_var_) (rom_var_) 02396 #endif 02397 02398 #ifndef QS_TIME_SIZE 02399 02400 /// \brief The size (in bytes) of the QS time stamp. Valid values: 1, 2, 02401 /// or 4; default 4. 02402 /// 02403 /// This macro can be defined in the QS port file (qs_port.h) to 02404 /// configure the ::QSTimeCtr type. Here the macro is not defined so the 02405 /// default of 4 byte is chosen. 02406 #define QS_TIME_SIZE 4 02407 #endif 02408 02409 ////////////////////////////////////////////////////////////////////////////// 02410 QP_BEGIN_ 02411 02412 /// \brief Quantum Spy record types. 02413 /// 02414 /// The following constants specify the QS record types used in QP components. 02415 /// You can specify your own record types starting from the ::QS_USER offset. 02416 /// Currently, the maximum of all records cannot exceed 256. 02417 /// \sa QS::filterOn()/#QS_FILTER_ON and QS::filterOff()/#QS_FILTER_OFF 02418 02419 enum QSpyRecords { 02420 QS_QP_RESET, ///< reset the QP (start of a new QS session) 02421 02422 // QEP records 02423 QS_QEP_STATE_ENTRY, ///< a state was entered 02424 QS_QEP_STATE_EXIT, ///< a state was exited 02425 QS_QEP_STATE_INIT, ///< an intial transition was taken in a state 02426 QS_QEP_INIT_TRAN, ///< the top-most initial transition was taken 02427 QS_QEP_INTERN_TRAN, ///< an internal transition was taken 02428 QS_QEP_TRAN, ///< a regular transition was taken 02429 QS_QEP_IGNORED, ///< an event was ignored (silently discarded) 02430 QS_QEP_DISPATCH, ///< an event was dispatched (begin of RTC step) 02431 QS_QEP_UNHANDLED, ///< an event was unhandled due to a guard 02432 02433 // QF records 02434 QS_QF_ACTIVE_ADD, ///< an AO has been added to QF (started) 02435 QS_QF_ACTIVE_REMOVE, ///< an AO has been removed from QF (stopped) 02436 QS_QF_ACTIVE_SUBSCRIBE, ///< an AO subscribed to an event 02437 QS_QF_ACTIVE_UNSUBSCRIBE, ///< an AO unsubscribed to an event 02438 QS_QF_ACTIVE_POST_FIFO, ///< an event was posted (FIFO) directly to an AO 02439 QS_QF_ACTIVE_POST_LIFO, ///< an event was posted (LIFO) directly to an AO 02440 QS_QF_ACTIVE_GET, ///< an AO got an event and its queue is still not empty 02441 QS_QF_ACTIVE_GET_LAST, ///< an AO got an event and its queue is empty 02442 QS_QF_EQUEUE_INIT, ///< an event queue was initialized 02443 QS_QF_EQUEUE_POST_FIFO, ///< an event was posted (FIFO) to a raw queue 02444 QS_QF_EQUEUE_POST_LIFO, ///< an event was posted (LIFO) to a raw queue 02445 QS_QF_EQUEUE_GET, ///< get an event and queue still not empty 02446 QS_QF_EQUEUE_GET_LAST, ///< get the last event from the queue 02447 QS_QF_MPOOL_INIT, ///< a memory pool was initialized 02448 QS_QF_MPOOL_GET, ///< a memory block was removed from a memory pool 02449 QS_QF_MPOOL_PUT, ///< a memory block was returned to a memory pool 02450 QS_QF_PUBLISH, ///< an event was truly published to some subscribers 02451 QS_QF_RESERVED8, 02452 QS_QF_NEW, ///< new event creation 02453 QS_QF_GC_ATTEMPT, ///< garbage collection attempt 02454 QS_QF_GC, ///< garbage collection 02455 QS_QF_TICK, ///< QF::tick() was called 02456 QS_QF_TIMEEVT_ARM, ///< a time event was armed 02457 QS_QF_TIMEEVT_AUTO_DISARM, ///< a time event expired and was disarmed 02458 QS_QF_TIMEEVT_DISARM_ATTEMPT,///< an attempt to disarmed a disarmed tevent 02459 QS_QF_TIMEEVT_DISARM, ///< true disarming of an armed time event 02460 QS_QF_TIMEEVT_REARM, ///< rearming of a time event 02461 QS_QF_TIMEEVT_POST, ///< a time event posted itself directly to an AO 02462 QS_QF_TIMEEVT_CTR, ///< a time event counter was requested 02463 QS_QF_CRIT_ENTRY, ///< critical section was entered 02464 QS_QF_CRIT_EXIT, ///< critical section was exited 02465 QS_QF_ISR_ENTRY, ///< an ISR was entered 02466 QS_QF_ISR_EXIT, ///< an ISR was exited 02467 QS_QF_INT_DISABLE, ///< interrupts were disabled 02468 QS_QF_INT_ENABLE, ///< interrupts were enabled 02469 QS_QF_RESERVED4, 02470 QS_QF_RESERVED3, 02471 QS_QF_RESERVED2, 02472 QS_QF_RESERVED1, 02473 QS_QF_RESERVED0, 02474 02475 // QK records 02476 QS_QK_MUTEX_LOCK, ///< the QK mutex was locked 02477 QS_QK_MUTEX_UNLOCK, ///< the QK mutex was unlocked 02478 QS_QK_SCHEDULE, ///< the QK scheduler scheduled a new task to execute 02479 QS_QK_RESERVED6, 02480 QS_QK_RESERVED5, 02481 QS_QK_RESERVED4, 02482 QS_QK_RESERVED3, 02483 QS_QK_RESERVED2, 02484 QS_QK_RESERVED1, 02485 QS_QK_RESERVED0, 02486 02487 // Miscellaneous QS records 02488 QS_SIG_DIC, ///< signal dictionary entry 02489 QS_OBJ_DIC, ///< object dictionary entry 02490 QS_FUN_DIC, ///< function dictionary entry 02491 QS_USR_DIC, ///< user QS record dictionary entry 02492 QS_RESERVED4, 02493 QS_RESERVED3, 02494 QS_RESERVED2, 02495 QS_RESERVED1, 02496 QS_RESERVED0, 02497 QS_ASSERT, ///< assertion fired in the code 02498 02499 // User records 02500 QS_USER ///< the first record available for user QS records 02501 }; 02502 02503 /// \brief Specification of all QS records for the QS::filterOn() and 02504 /// QS::filterOff() 02505 uint8_t const QS_ALL_RECORDS = static_cast<uint8_t>(0xFF); 02506 02507 /// \brief Constant representing End-Of-Data condition returned from the 02508 /// QS::getByte() function. 02509 uint16_t const QS_EOD = static_cast<uint16_t>(0xFFFF); 02510 02511 02512 #if (QS_TIME_SIZE == 1) 02513 typedef uint8_t QSTimeCtr; 02514 #define QS_TIME_() (QP_ QS::u8_(QP_ QS::onGetTime())) 02515 #elif (QS_TIME_SIZE == 2) 02516 typedef uint16_t QSTimeCtr; 02517 #define QS_TIME_() (QP_ QS::u16_(QP_ QS::onGetTime())) 02518 #elif (QS_TIME_SIZE == 4) 02519 02520 /// \brief The type of the QS time stamp 02521 /// 02522 /// This type determines the dynamic range of QS time stamps 02523 typedef uint32_t QSTimeCtr; 02524 02525 /// \brief Internal macro to output time stamp to the QS record 02526 #define QS_TIME_() (QP_ QS::u32_(QP_ QS::onGetTime())) 02527 #else 02528 #error "QS_TIME_SIZE defined incorrectly, expected 1, 2, or 4" 02529 #endif 02530 02531 /// \brief Quantum Spy logging facilities 02532 /// 02533 /// This class groups together QS services. It has only static members and 02534 /// should not be instantiated. 02535 class QS { 02536 public: 02537 02538 /// \brief Get the current version of QS 02539 /// 02540 /// \return version of the QS as a constant 6-character string of the form 02541 /// x.y.zz, where x is a 1-digit major version number, y is a 1-digit 02542 /// minor version number, and zz is a 2-digit release number. 02543 static char_t const Q_ROM * Q_ROM_VAR getVersion(void); 02544 02545 /// \brief Initialize the QS data buffer. 02546 /// 02547 /// This function should be called from QS_init() to provide QS with the 02548 /// data buffer. The first argument \a sto[] is the address of the memory 02549 /// block, and the second argument \a stoSize is the size of this block 02550 /// in bytes. Currently the size of the QS buffer cannot exceed 64KB. 02551 /// 02552 /// QS can work with quite small data buffers, but you will start losing 02553 /// data if the buffer is too small for the bursts of logging activity. 02554 /// The right size of the buffer depends on the data production rate and 02555 /// the data output rate. QS offers flexible filtering to reduce the data 02556 /// production rate. 02557 /// 02558 /// \note If the data output rate cannot keep up with the production rate, 02559 /// QS will start overwriting the older data with newer data. This is 02560 /// consistent with the "last-is-best" QS policy. The record sequence 02561 /// counters and checksums on each record allow to easily detect data 02562 /// loss. 02563 static void initBuf(uint8_t sto[], uint32_t const stoSize); 02564 02565 /// \brief Turn the global Filter on for a given record type \a rec. 02566 /// 02567 /// This function sets up the QS filter to enable the record type \a rec. 02568 /// The argument #QS_ALL_RECORDS specifies to filter-on all records. 02569 /// This function should be called indirectly through the macro 02570 /// #QS_FILTER_ON. 02571 /// 02572 /// \note Filtering based on the record-type is only the first layer of 02573 /// filtering. The second layer is based on the object-type. Both filter 02574 /// layers must be enabled for the QS record to be inserted into the QS 02575 /// buffer. 02576 /// \sa QS_filterOff(), #QS_FILTER_SM_OBJ, #QS_FILTER_AO_OBJ, 02577 /// #QS_FILTER_MP_OBJ, #QS_FILTER_EQ_OBJ, and #QS_FILTER_TE_OBJ. 02578 static void filterOn(uint8_t const rec); 02579 02580 /// \brief Turn the global Filter off for a given record type \a rec. 02581 /// 02582 /// This function sets up the QS filter to disable the record type \a rec. 02583 /// The argument #QS_ALL_RECORDS specifies to suppress all records. 02584 /// This function should be called indirectly through the macro 02585 /// #QS_FILTER_OFF. 02586 /// 02587 /// \note Filtering records based on the record-type is only the first 02588 /// layer of filtering. The second layer is based on the object-type. 02589 /// Both filter layers must be enabled for the QS record to be inserted 02590 /// into the QS buffer. 02591 /// \sa 02592 static void filterOff(uint8_t const rec); 02593 02594 /// \brief Mark the begin of a QS record \a rec 02595 /// 02596 /// This function must be called at the beginning of each QS record. 02597 /// This function should be called indirectly through the macro #QS_BEGIN, 02598 /// or #QS_BEGIN_NOCRIT, depending if it's called in a normal code or from 02599 /// a critical section. 02600 static void begin(uint8_t const rec); 02601 02602 /// \brief Mark the end of a QS record \a rec 02603 /// 02604 /// This function must be called at the end of each QS record. 02605 /// This function should be called indirectly through the macro #QS_END, 02606 /// or #QS_END_NOCRIT, depending if it's called in a normal code or from 02607 /// a critical section. 02608 static void end(void); 02609 02610 // unformatted data elements output ...................................... 02611 02612 /// \brief output uint8_t data element without format information 02613 /// \note This function is only to be used through macros, never in the 02614 /// client code directly. 02615 static void u8_(uint8_t const d); 02616 02617 /// \brief Output uint16_t data element without format information 02618 /// \note This function is only to be used through macros, never in the 02619 /// client code directly. 02620 static void u16_(uint16_t d); 02621 02622 /// \brief Output uint32_t data element without format information 02623 /// \note This function is only to be used through macros, never in the 02624 /// client code directly. 02625 static void u32_(uint32_t d); 02626 02627 /// \brief Output zero-terminated ASCII string element without format 02628 /// information 02629 /// \note This function is only to be used through macros, never in the 02630 /// client code directly. 02631 static void str_(char_t const *s); 02632 02633 /// \brief Output zero-terminated ASCII string element allocated in ROM 02634 /// without format information 02635 /// \note This function is only to be used through macros, never in the 02636 /// client code directly. 02637 static void str_ROM_(char_t const Q_ROM * Q_ROM_VAR s); 02638 02639 // formatted data elements output ........................................ 02640 02641 /// \brief Output uint8_t data element with format information 02642 /// \note This function is only to be used through macros, never in the 02643 /// client code directly. 02644 static void u8(uint8_t const format, uint8_t const d); 02645 02646 /// \brief output uint16_t data element with format information 02647 /// \note This function is only to be used through macros, never in the 02648 /// client code directly. 02649 static void u16(uint8_t const format, uint16_t d); 02650 02651 /// \brief Output uint32_t data element with format information 02652 /// \note This function is only to be used through macros, never in the 02653 /// client code directly. 02654 static void u32(uint8_t const format, uint32_t d); 02655 02656 /// \brief Output 32-bit floating point data element with format 02657 /// information 02658 /// \note This function is only to be used through macros, never in the 02659 /// client code directly. 02660 static void f32(uint8_t const format, float32_t const d); 02661 02662 /// \brief Output 64-bit floating point data element with format 02663 /// information 02664 /// \note This function is only to be used through macros, never in the 02665 /// client code directly. 02666 static void f64(uint8_t const format, float64_t const d); 02667 02668 /// \brief Output zero-terminated ASCII string element with format 02669 /// information 02670 /// \note This function is only to be used through macros, never in the 02671 /// client code directly. 02672 static void str(char_t const *s); 02673 02674 /// \brief Output zero-terminated ASCII string element allocated in ROM 02675 /// with format information 02676 /// \note This function is only to be used through macros, never in the 02677 /// client code directly. 02678 static void str_ROM(char_t const Q_ROM * Q_ROM_VAR s); 02679 02680 /// \brief Output memory block of up to 255-bytes with format information 02681 /// \note This function is only to be used through macros, never in the 02682 /// client code directly. 02683 static void mem(uint8_t const *blk, uint8_t size); 02684 02685 #if (QS_OBJ_PTR_SIZE == 8) || (QS_FUN_PTR_SIZE == 8) 02686 /// \brief Output uint64_t data element without format information 02687 /// \note This function is only to be used through macros, never in the 02688 /// client code directly. 02689 static void u64_(uint64_t d); 02690 02691 /// \brief Output uint64_t data element with format information 02692 /// \note This function is only to be used through macros, never in the 02693 /// client code directly. 02694 static void u64(uint8_t format, uint64_t d); 02695 #endif 02696 02697 // QS buffer access ...................................................... 02698 02699 /// \brief Byte-oriented interface to the QS data buffer. 02700 /// 02701 /// This function delivers one byte at a time from the QS data buffer. 02702 /// The function returns the byte in the least-significant 8-bits of the 02703 /// 16-bit return value if the byte is available. If no more data is 02704 /// available at the time, the function returns QS_EOD (End-Of-Data). 02705 /// 02706 /// \note QS::getByte() is NOT protected with a critical section. 02707 static uint16_t getByte(void); 02708 02709 /// \brief Block-oriented interface to the QS data buffer. 02710 /// 02711 /// This function delivers a contiguous block of data from the QS data 02712 /// buffer. The function returns the pointer to the beginning of the 02713 /// block, and writes the number of bytes in the block to the location 02714 /// pointed to by \a pNbytes. The argument \a pNbytes is also used as 02715 /// input to provide the maximum size of the data block that the caller 02716 /// can accept. 02717 /// 02718 /// If no bytes are available in the QS buffer when the function is 02719 /// called, the function returns a NULL pointer and sets the value 02720 /// pointed to by \a pNbytes to zero. 02721 /// 02722 /// \note Only the NULL return from QS::getBlock() indicates that the QS 02723 /// buffer is empty at the time of the call. The non-NULL return often 02724 /// means that the block is at the end of the buffer and you need to call 02725 /// QS::getBlock() again to obtain the rest of the data that "wrapped 02726 /// around" to the beginning of the QS data buffer. 02727 /// 02728 /// \note QS::getBlock() is NOT protected with a critical section. 02729 static uint8_t const *getBlock(uint16_t * const pNbytes); 02730 02731 ////////////////////////////////////////////////////////////////////////// 02732 // platform-dependent callback functions to be implemented by clients 02733 02734 // platform-specific callback functions, need to be implemented by clients 02735 /// \brief Callback to startup the QS facility 02736 /// 02737 /// This is a platform-dependent "callback" function invoked through the 02738 /// macro #QS_INIT. You need to implement this function in your 02739 /// application. At a minimum, the function must configure the QS buffer 02740 /// by calling QS::initBuf(). Typically, you will also want to open/ 02741 /// configure the QS output channel, such as a serial port, or a file. 02742 /// The void* argument \a arg can be used to pass parameter(s) needed to 02743 /// configure the output channel. 02744 /// 02745 /// The function returns true if the QS initialization was successful, 02746 /// or false if it failed. 02747 /// 02748 /// The following example illustrates an implementation of QS_onStartup(): 02749 /// \include qs_startup.cpp 02750 static bool onStartup(void const *arg); 02751 02752 /// \brief Callback to cleanup the QS facility 02753 /// 02754 /// This is a platform-dependent "callback" function invoked through the 02755 /// macro #QS_EXIT. You need to implement this function in your 02756 /// application. The main purpose of this function is to close the QS 02757 /// output channel, if necessary. 02758 static void onCleanup(void); 02759 02760 /// \brief Callback to flush the QS trace data to the host 02761 /// 02762 /// This is a platform-dependent "callback" function to flush the QS 02763 /// trace buffer to the host. The function typically busy-waits until all 02764 /// the data in the buffer is sent to the host. This is acceptable only 02765 /// in the initial transient. 02766 static void onFlush(void); 02767 02768 /// \brief Callback to obtain a timestamp for a QS record. 02769 /// 02770 /// This is a platform-dependent "callback" function invoked from the 02771 /// macro #QS_TIME_ to add the time stamp to the QS record. 02772 /// 02773 /// \note Some of the pre-defined QS records from QP do not output the 02774 /// time stamp. However, ALL user records do output the time stamp. 02775 /// \note QS::onGetTime() is called in a critical section and should not 02776 /// exit critical section. 02777 /// 02778 /// The following example shows using a system call to implement QS 02779 /// time stamping: 02780 /// \include qs_onGetTime.cpp 02781 static QSTimeCtr onGetTime(void); 02782 02783 ////////////////////////////////////////////////////////////////////////// 02784 // Global and Local QS filters 02785 static uint8_t glbFilter_[32]; ///< global on/off QS filter 02786 static void const *smObj_; ///< state machine for QEP local filter 02787 static void const *aoObj_; ///< active object for QF/QK local filter 02788 static void const *mpObj_; ///< event pool for QF local filter 02789 static void const *eqObj_; ///< raw queue for QF local filter 02790 static void const *teObj_; ///< time event for QF local filter 02791 static void const *apObj_;///< generic object Application QF local filter 02792 02793 ////////////////////////////////////////////////////////////////////////// 02794 // Miscallaneous 02795 /// tick counter for the QS_QF_TICK record 02796 static QSTimeCtr tickCtr_; 02797 }; 02798 02799 /// \brief Enumerates data formats recognized by QS 02800 /// 02801 /// QS uses this enumeration is used only internally for the formatted user 02802 /// data elements. 02803 enum QSType { 02804 QS_I8_T, ///< signed 8-bit integer format 02805 QS_U8_T, ///< unsigned 8-bit integer format 02806 QS_I16_T, ///< signed 16-bit integer format 02807 QS_U16_T, ///< unsigned 16-bit integer format 02808 QS_I32_T, ///< signed 32-bit integer format 02809 QS_U32_T, ///< unsigned 32-bit integer format 02810 QS_F32_T, ///< 32-bit floating point format 02811 QS_F64_T, ///< 64-bit floating point format 02812 QS_STR_T, ///< zero-terminated ASCII string format 02813 QS_MEM_T, ///< up to 255-bytes memory block format 02814 QS_SIG_T, ///< event signal format 02815 QS_OBJ_T, ///< object pointer format 02816 QS_FUN_T, ///< function pointer format 02817 QS_I64_T, ///< signed 64-bit integer format 02818 QS_U64_T, ///< unsigned 64-bit integer format 02819 QS_U32_HEX_T ///< unsigned 32-bit integer in hex format 02820 }; 02821 02822 /// \brief critical section nesting level 02823 /// 02824 /// \note Not to be used by Clients directly, only in ports of QF 02825 extern uint8_t QF_critNest_; 02826 02827 QP_END_ 02828 02829 02830 ////////////////////////////////////////////////////////////////////////////// 02831 // Macros for adding QS instrumentation to the client code 02832 02833 /// \brief Initialize the QS facility. 02834 /// 02835 /// This macro provides an indirection layer to invoke the QS initialization 02836 /// routine if #Q_SPY is defined, or do nothing if #Q_SPY is not defined. 02837 /// \sa QS::onStartup(), example of setting up a QS filter in #QS_FILTER_IN 02838 #define QS_INIT(arg_) (QP_ QS::onStartup(arg_)) 02839 02840 /// \brief Cleanup the QS facility. 02841 /// 02842 /// This macro provides an indirection layer to invoke the QS cleanup 02843 /// routine if #Q_SPY is defined, or do nothing if #Q_SPY is not defined. 02844 /// \sa QS::onCleanup() 02845 #define QS_EXIT() (QP_ QS::onCleanup()) 02846 02847 /// \brief Global Filter ON for a given record type \a rec. 02848 /// 02849 /// This macro provides an indirection layer to call QS::filterOn() if #Q_SPY 02850 /// is defined, or do nothing if #Q_SPY is not defined. 02851 /// 02852 /// The following example shows how to use QS filters: 02853 /// \include qs_filter.cpp 02854 #define QS_FILTER_ON(rec_) (QP_ QS::filterOn(static_cast<uint8_t>(rec_))) 02855 02856 /// \brief Global filter OFF for a given record type \a rec. 02857 /// 02858 /// This macro provides an indirection layer to call QS::filterOff() if #Q_SPY 02859 /// is defined, or do nothing if #Q_SPY is not defined. 02860 /// 02861 /// \sa Example of using QS filters in #QS_FILTER_ON documentation 02862 #define QS_FILTER_OFF(rec_) (QP_ QS::filterOff(static_cast<uint8_t>(rec_))) 02863 02864 /// \brief Local Filter for a given state machine object \a obj_. 02865 /// 02866 /// This macro sets up the state machine object local filter if #Q_SPY is 02867 /// defined, or does nothing if #Q_SPY is not defined. The argument \a obj_ 02868 /// is the pointer to the state machine object that you want to monitor. 02869 /// 02870 /// The state machine object filter allows you to filter QS records pertaining 02871 /// only to a given state machine object. With this filter disabled, QS will 02872 /// output records from all state machines in your application. The object 02873 /// filter is disabled by setting the state machine pointer to NULL. 02874 /// 02875 /// The state machine filter affects the following QS records: 02876 /// ::QS_QEP_STATE_ENTRY, ::QS_QEP_STATE_EXIT, ::QS_QEP_STATE_INIT, 02877 /// ::QS_QEP_INIT_TRAN, ::QS_QEP_INTERN_TRAN, ::QS_QEP_TRAN, 02878 /// and ::QS_QEP_IGNORED. 02879 /// 02880 /// \note Because active objects are state machines at the same time, 02881 /// the state machine filter (#QS_FILTER_SM_OBJ) pertains to active 02882 /// objects as well. However, the state machine filter is more general, 02883 /// because it can be used only for state machines that are not active 02884 /// objects, such as "Orthogonal Components". 02885 /// 02886 /// \sa Example of using QS filters in #QS_FILTER_ON documentation 02887 #define QS_FILTER_SM_OBJ(obj_) (QP_ QS::smObj_ = (obj_)) 02888 02889 /// \brief Local Filter for a given active object \a obj_. 02890 /// 02891 /// This macro sets up the active object local filter if #Q_SPY is defined, 02892 /// or does nothing if #Q_SPY is not defined. The argument \a obj_ is the 02893 /// pointer to the active object that you want to monitor. 02894 /// 02895 /// The active object filter allows you to filter QS records pertaining 02896 /// only to a given active object. With this filter disabled, QS will 02897 /// output records from all active objects in your application. The object 02898 /// filter is disabled by setting the active object pointer \a obj_ to NULL. 02899 /// 02900 /// The active object filter affects the following QS records: 02901 /// ::QS_QF_ACTIVE_ADD, ::QS_QF_ACTIVE_REMOVE, ::QS_QF_ACTIVE_SUBSCRIBE, 02902 /// ::QS_QF_ACTIVE_UNSUBSCRIBE, ::QS_QF_ACTIVE_POST_FIFO, 02903 /// ::QS_QF_ACTIVE_POST_LIFO, ::QS_QF_ACTIVE_GET, and ::QS_QF_ACTIVE_GET_LAST. 02904 /// 02905 /// \sa Example of using QS filters in #QS_FILTER_ON documentation 02906 #define QS_FILTER_AO_OBJ(obj_) (QP_ QS::aoObj_ = (obj_)) 02907 02908 /// \brief Local Filter for a given memory pool object \a obj_. 02909 /// 02910 /// This macro sets up the memory pool object local filter if #Q_SPY is 02911 /// defined, or does nothing if #Q_SPY is not defined. The argument \a obj_ 02912 /// is the pointer to the memory buffer used during the initialization of the 02913 /// event pool with QF::poolInit(). 02914 /// 02915 /// The memory pool filter allows you to filter QS records pertaining 02916 /// only to a given memory pool. With this filter disabled, QS will 02917 /// output records from all memory pools in your application. The object 02918 /// filter is disabled by setting the memory pool pointer \a obj_ to NULL. 02919 /// 02920 /// The memory pool filter affects the following QS records: 02921 /// ::QS_QF_MPOOL_INIT, ::QS_QF_MPOOL_GET, and ::QS_QF_MPOOL_PUT. 02922 /// 02923 /// \sa Example of using QS filters in #QS_FILTER_ON documentation 02924 #define QS_FILTER_MP_OBJ(obj_) (QP_ QS::mpObj_ = (obj_)) 02925 02926 /// \brief Filter for a given event queue object \a obj_. 02927 /// 02928 /// This macro sets up the event queue object filter if #Q_SPY is defined, 02929 /// or does nothing if #Q_SPY is not defined. The argument \a obj_ is the 02930 /// pointer to the "raw" thread-safe queue object you want to monitor. 02931 /// 02932 /// The event queue filter allows you to filter QS records pertaining 02933 /// only to a given event queue. With this filter disabled, QS will 02934 /// output records from all event queues in your application. The object 02935 /// filter is disabled by setting the event queue pointer \a obj_ to NULL. 02936 /// 02937 /// The event queue filter affects the following QS records: 02938 /// ::QS_QF_EQUEUE_INIT, ::QS_QF_EQUEUE_POST_FIFO, ::QS_QF_EQUEUE_POST_LIFO, 02939 /// ::QS_QF_EQUEUE_GET, and ::QS_QF_EQUEUE_GET_LAST. 02940 /// 02941 /// \sa Example of using QS filters in #QS_FILTER_IN documentation 02942 #define QS_FILTER_EQ_OBJ(obj_) (QP_ QS::eqObj_ = (obj_)) 02943 02944 /// \brief Local Filter for a given time event object \a obj_. 02945 /// 02946 /// This macro sets up the time event object local filter if #Q_SPY is 02947 /// defined, or does nothing if #Q_SPY is not defined. The argument \a obj_ 02948 /// is the pointer to the time event object you want to monitor. 02949 /// 02950 /// The time event filter allows you to filter QS records pertaining 02951 /// only to a given time event. With this filter disabled, QS will 02952 /// output records from all time events in your application. The object 02953 /// filter is disabled by setting the time event pointer \a obj_ to NULL. 02954 /// 02955 /// The time event filter affects the following QS records: 02956 /// ::QS_QF_TIMEEVT_ARM, ::QS_QF_TIMEEVT_AUTO_DISARM, 02957 /// ::QS_QF_TIMEEVT_DISARM_ATTEMPT, ::QS_QF_TIMEEVT_DISARM, 02958 /// ::QS_QF_TIMEEVT_REARM, ::QS_QF_TIMEEVT_POST, and ::QS_QF_TIMEEVT_PUBLISH. 02959 /// 02960 /// \sa Example of using QS filters in #QS_FILTER_ON documentation 02961 #define QS_FILTER_TE_OBJ(obj_) (QP_ QS::teObj_ = (obj_)) 02962 02963 /// \brief Local Filter for a generic application object \a obj_. 02964 /// 02965 /// This macro sets up the local application object filter if #Q_SPY is 02966 /// defined, or does nothing if #Q_SPY is not defined. The argument \a obj_ 02967 /// is the pointer to the application object you want to monitor. 02968 /// 02969 /// The application object filter allows you to filter QS records pertaining 02970 /// only to a given application object. With this filter disabled, QS will 02971 /// output records from all application-records enabled by the global filter. 02972 /// The local filter is disabled by setting the time event pointer \a obj_ 02973 /// to NULL. 02974 /// 02975 /// \sa Example of using QS filters in #QS_FILTER_ON documentation 02976 #define QS_FILTER_AP_OBJ(obj_) (QP_ QS::apObj_ = (obj_)) 02977 02978 02979 ////////////////////////////////////////////////////////////////////////////// 02980 // Macros to generate user QS records 02981 02982 #define QS_GLB_FILTER_(rec_) \ 02983 ((QP_ QS::glbFilter_[static_cast<uint8_t>(rec_) >> 3] \ 02984 & (static_cast<uint8_t>(1U << (static_cast<uint8_t>(rec_) \ 02985 & static_cast<uint8_t>(7))))) \ 02986 != static_cast<uint8_t>(0)) 02987 02988 /// \brief Begin a QS user record without entering critical section. 02989 #define QS_BEGIN_NOCRIT(rec_, obj_) \ 02990 if (QS_GLB_FILTER_(rec_) \ 02991 && ((QP_ QS::apObj_ == static_cast<void *>(0)) \ 02992 || (QP_ QS::apObj_ == (obj_)))) \ 02993 { \ 02994 QP_ QS::begin(static_cast<uint8_t>(rec_)); \ 02995 QS_TIME_(); 02996 02997 /// \brief End a QS user record without exiting critical section. 02998 #define QS_END_NOCRIT() \ 02999 QS_END_NOCRIT_() 03000 03001 // QS-specific critical section 03002 #ifndef QF_CRIT_STAT_TYPE 03003 /// \brief This is an internal macro for defining the critical section 03004 /// status type. 03005 /// 03006 /// The purpose of this macro is to enable writing the same code for the 03007 /// case when critical sectgion status type is defined and when it is not. 03008 /// If the macro #QF_CRIT_STAT_TYPE is defined, this internal macro 03009 /// provides the definition of the critical section status variable. 03010 /// Otherwise this macro is empty. 03011 /// \sa #QF_CRIT_STAT_TYPE 03012 /// 03013 #define QS_CRIT_STAT_ 03014 03015 /// \brief This is an internal macro for entering a critical section. 03016 /// 03017 /// The purpose of this macro is to enable writing the same code for the 03018 /// case when critical sectgion status type is defined and when it is not. 03019 /// If the macro #QF_CRIT_STAT_TYPE is defined, this internal macro 03020 /// invokes #QF_CRIT_ENTRY passing the key variable as the parameter. 03021 /// Otherwise #QF_CRIT_ENTRY is invoked with a dummy parameter. 03022 /// \sa #QF_CRIT_ENTRY 03023 /// 03024 #define QS_CRIT_ENTRY_() QF_CRIT_ENTRY(dummy) 03025 03026 /// \brief This is an internal macro for exiting a cricial section. 03027 /// 03028 /// The purpose of this macro is to enable writing the same code for the 03029 /// case when critical sectgion status type is defined and when it is not. 03030 /// If the macro #QF_CRIT_STAT_TYPE is defined, this internal macro 03031 /// invokes #QF_CRIT_EXIT passing the key variable as the parameter. 03032 /// Otherwise #QF_CRIT_EXIT is invoked with a dummy parameter. 03033 /// \sa #QF_CRIT_EXIT 03034 /// 03035 #define QS_CRIT_EXIT_() QF_CRIT_EXIT(dummy) 03036 03037 #else 03038 #define QS_CRIT_STAT_ QF_CRIT_STAT_TYPE critStat_; 03039 #define QS_CRIT_ENTRY_() QF_CRIT_ENTRY(critStat_) 03040 #define QS_CRIT_EXIT_() QF_CRIT_EXIT(critStat_) 03041 #endif 03042 03043 /// \brief Begin a user QS record with entering critical section. 03044 /// 03045 /// The following example shows how to build a user QS record using the 03046 /// macros #QS_BEGIN, #QS_END, and the formatted output macros: #QS_U8 and 03047 /// #QS_STR. 03048 /// \include qs_user.cpp 03049 /// \note Must always be used in pair with #QS_END 03050 #define QS_BEGIN(rec_, obj_) \ 03051 if (QS_GLB_FILTER_(rec_) \ 03052 && ((QP_ QS::apObj_ == static_cast<void *>(0)) \ 03053 || (QP_ QS::apObj_ == (obj_)))) \ 03054 { \ 03055 QS_CRIT_STAT_ \ 03056 QS_CRIT_ENTRY_(); \ 03057 QP_ QS::begin(static_cast<uint8_t>(rec_)); \ 03058 QS_TIME_(); 03059 03060 /// \brief End a QS record with exiting critical section. 03061 /// \sa example for #QS_BEGIN 03062 /// \note Must always be used in pair with #QS_BEGIN 03063 #define QS_END() \ 03064 QS_END_() 03065 03066 03067 ////////////////////////////////////////////////////////////////////////////// 03068 // Macros for use inside other macros or internally in the QP code 03069 03070 /// \brief Internal QS macro to begin a QS record with entering critical 03071 /// section. 03072 /// \note This macro is intended to use only inside QP components and NOT 03073 /// at the application level. \sa #QS_BEGIN 03074 #define QS_BEGIN_(rec_, objFilter_, obj_) \ 03075 if (QS_GLB_FILTER_(rec_) \ 03076 && (((objFilter_) == static_cast<void *>(0)) \ 03077 || ((objFilter_) == (obj_)))) \ 03078 { \ 03079 QS_CRIT_ENTRY_(); \ 03080 QP_ QS::begin(static_cast<uint8_t>(rec_)); 03081 03082 /// \brief Internal QS macro to end a QS record with exiting critical 03083 /// section. 03084 /// \note This macro is intended to use only inside QP components and NOT 03085 /// at the application level. \sa #QS_END 03086 #define QS_END_() \ 03087 QP_ QS::end(); \ 03088 QS_CRIT_EXIT_(); \ 03089 } 03090 03091 /// \brief Internal QS macro to begin a QS record without entering critical 03092 /// section. 03093 /// \note This macro is intended to use only inside QP components and NOT 03094 /// at the application level. \sa #QS_BEGIN_NOCRIT 03095 #define QS_BEGIN_NOCRIT_(rec_, objFilter_, obj_) \ 03096 if (QS_GLB_FILTER_(rec_) \ 03097 && (((objFilter_) == static_cast<void *>(0)) \ 03098 || ((objFilter_) == (obj_)))) \ 03099 { \ 03100 QP_ QS::begin(static_cast<uint8_t>(rec_)); 03101 03102 /// \brief Internal QS macro to end a QS record without exiting critical 03103 /// section. 03104 /// \note This macro is intended to use only inside QP components and NOT 03105 /// at the application level. \sa #QS_END_NOCRIT 03106 #define QS_END_NOCRIT_() \ 03107 QP_ QS::end(); \ 03108 } 03109 03110 #if (Q_SIGNAL_SIZE == 1) 03111 /// \brief Internal QS macro to output an unformatted event signal 03112 /// data element 03113 /// \note the size of the pointer depends on the macro #Q_SIGNAL_SIZE. 03114 #define QS_SIG_(sig_) (QP_ QS::u8_(static_cast<uint8_t>(sig_)))) 03115 #elif (Q_SIGNAL_SIZE == 2) 03116 #define QS_SIG_(sig_) (QP_ QS::u16_(static_cast<uint16_t>(sig_))) 03117 #elif (Q_SIGNAL_SIZE == 4) 03118 #define QS_SIG_(sig_) (QP_ QS::u32_(static_cast<uint32_t>(sig_))) 03119 #endif 03120 03121 /// \brief Internal QS macro to output an unformatted uint8_t data element 03122 #define QS_U8_(data_) (QP_ QS::u8_(data_)) 03123 03124 /// \brief Internal QS macro to output an unformatted uint16_t data element 03125 #define QS_U16_(data_) (QP_ QS::u16_(data_)) 03126 03127 /// \brief Internal QS macro to output an unformatted uint32_t data element 03128 #define QS_U32_(data_) (QP_ QS::u32_(data_)) 03129 03130 03131 #if (QS_OBJ_PTR_SIZE == 1) 03132 #define QS_OBJ_(obj_) (QP_ QS::u8_(reinterpret_cast<uint8_t>(obj_))) 03133 #elif (QS_OBJ_PTR_SIZE == 2) 03134 #define QS_OBJ_(obj_) (QP_ QS::u16_(reinterpret_cast<uint16_t>(obj_))) 03135 #elif (QS_OBJ_PTR_SIZE == 4) 03136 #define QS_OBJ_(obj_) (QP_ QS::u32_(reinterpret_cast<uint32_t>(obj_))) 03137 #elif (QS_OBJ_PTR_SIZE == 8) 03138 #define QS_OBJ_(obj_) (QP_ QS::u64_(reinterpret_cast<uint64_t>(obj_))) 03139 #else 03140 03141 /// \brief Internal QS macro to output an unformatted object pointer 03142 /// data element 03143 /// \note the size of the pointer depends on the macro #QS_OBJ_PTR_SIZE. 03144 /// If the size is not defined the size of pointer is assumed 4-bytes. 03145 #define QS_OBJ_(obj_) (QP_ QS::u32_(reinterpret_cast<uint32_t>(obj_))) 03146 #endif 03147 03148 03149 #if (QS_FUN_PTR_SIZE == 1) 03150 #define QS_FUN_(fun_) (QP_ QS::u8_(reinterpret_cast<uint8_t>(fun_))) 03151 #elif (QS_FUN_PTR_SIZE == 2) 03152 #define QS_FUN_(fun_) (QP_ QS::u16_(reinterpret_cast<uint16_t>(fun_))) 03153 #elif (QS_FUN_PTR_SIZE == 4) 03154 #define QS_FUN_(fun_) (QP_ QS::u32_(reinterpret_cast<uint32_t>(fun_))) 03155 #elif (QS_FUN_PTR_SIZE == 8) 03156 #define QS_FUN_(fun_) (QP_ QS::u64_(reinterpret_cast<uint64_t>(fun_))) 03157 #else 03158 03159 /// \brief Internal QS macro to output an unformatted function pointer 03160 /// data element 03161 /// \note the size of the pointer depends on the macro #QS_FUN_PTR_SIZE. 03162 /// If the size is not defined the size of pointer is assumed 4-bytes. 03163 #define QS_FUN_(fun_) (QP_ QS::u32_(reinterpret_cast<uint32_t>(fun_))) 03164 #endif 03165 03166 /// \brief Internal QS macro to output a zero-terminated ASCII string 03167 /// data element 03168 #define QS_STR_(msg_) (QP_ QS::str_(msg_)) 03169 03170 /// \brief Internal QS macro to output a zero-terminated ASCII string 03171 /// allocated in ROM data element 03172 #define QS_STR_ROM_(msg_) (QP_ QS::str_ROM_(msg_)) 03173 03174 ////////////////////////////////////////////////////////////////////////////// 03175 // Macros for use in the client code 03176 03177 /// \brief Output formatted int8_t to the QS record 03178 #define QS_I8(width_, data_) \ 03179 (QP_ QS::u8(static_cast<uint8_t>((static_cast<uint8_t>((width_) << 4)) \ 03180 | static_cast<uint8_t>(QP_ QS_I8_T)), (data_))) 03181 03182 /// \brief Output formatted uint8_t to the QS record 03183 #define QS_U8(width_, data_) \ 03184 (QP_ QS::u8(static_cast<uint8_t>((static_cast<uint8_t>((width_) << 4)) \ 03185 | static_cast<uint8_t>(QP_ QS_U8_T)), (data_))) 03186 03187 /// \brief Output formatted int16_t to the QS record 03188 #define QS_I16(width_, data_) \ 03189 (QP_ QS::u16(static_cast<uint8_t>((static_cast<uint8_t>((width_) << 4)) \ 03190 | static_cast<uint8_t>(QP_ QS_I16_T)), (data_))) 03191 03192 /// \brief Output formatted uint16_t to the QS record 03193 #define QS_U16(width_, data_) \ 03194 (QP_ QS::u16(static_cast<uint8_t>((((width_) << 4)) \ 03195 | static_cast<uint8_t>(QP_ QS_U16_T)), (data_))) 03196 03197 /// \brief Output formatted int32_t to the QS record 03198 #define QS_I32(width_, data_) \ 03199 (QP_ QS::u32(static_cast<uint8_t>((static_cast<uint8_t>((width_) << 4)) \ 03200 | static_cast<uint8_t>(QP_ QS_I32_T)), (data_))) 03201 03202 /// \brief Output formatted uint32_t to the QS record 03203 #define QS_U32(width_, data_) \ 03204 (QP_ QS::u32(static_cast<uint8_t>((static_cast<uint8_t>((width_) << 4)) \ 03205 | static_cast<uint8_t>(QP_ QS_U32_T)), (data_))) 03206 03207 /// \brief Output formatted 32-bit floating point number to the QS record 03208 #define QS_F32(width_, data_) \ 03209 QP_ QS::f32(static_cast<uint8_t>((static_cast<uint8_t>((width_) << 4)) \ 03210 | static_cast<uint8_t>(QP_ QS_F32_T)), (data_))) 03211 03212 /// \brief Output formatted 64-bit floating point number to the QS record 03213 #define QS_F64(width_, data_) \ 03214 (QP_ QS::f64(static_cast<uint8_t>((static_cast<uint8_t>((width_) << 4)) \ 03215 | static_cast<uint8_t>(QP_ QS_F64_T)), (data_))) 03216 03217 /// \brief Output formatted int64_t to the QS record 03218 #define QS_I64(width_, data_) \ 03219 (QP_ QS::u64(static_cast<uint8_t>((static_cast<uint8_t>((width_) << 4)) \ 03220 | static_cast<uint8_t>(QP_ QS_I64_T)), (data_))) 03221 03222 /// \brief Output formatted uint64_t to the QS record 03223 #define QS_U64(width_, data_) \ 03224 (QP_ QS::u64(static_cast<uint8_t>((static_cast<uint8_t>((width_) << 4)) \ 03225 | static_cast<uint8_t>(QP_ QS_U64_T)), (data_))) 03226 03227 /// \brief Output formatted uint32_t to the QS record 03228 #define QS_U32_HEX(width_, data_) \ 03229 (QP_ QS::u32(static_cast<uint8_t>((static_cast<uint8_t>((width_) << 4)) \ 03230 | static_cast<uint8_t>(QP_ QS_U32_HEX_T)), (data_))) 03231 03232 /// \brief Output formatted zero-terminated ASCII string to the QS record 03233 #define QS_STR(str_) (QP_ QS::str(str_)) 03234 03235 /// \brief Output formatted zero-terminated ASCII string from ROM 03236 /// to the QS record 03237 #define QS_STR_ROM(str_) (QP_ QS::str_ROM(str_)) 03238 03239 /// \brief Output formatted memory block of up to 255 bytes to the QS 03240 /// record 03241 #define QS_MEM(mem_, size_) (QP_ QS::mem((mem_), (size_))) 03242 03243 03244 #if (QS_OBJ_PTR_SIZE == 1) 03245 #define QS_OBJ(obj_) (QP_ QS::u8(QS_OBJ_T, (uint8_t)(obj_))) 03246 #elif (QS_OBJ_PTR_SIZE == 2) 03247 #define QS_OBJ(obj_) (QP_ QS::u16(QS_OBJ_T, (uint16_t)(obj_))) 03248 #elif (QS_OBJ_PTR_SIZE == 4) 03249 #define QS_OBJ(obj_) (QP_ QS::u32(QS_OBJ_T, (uint32_t)(obj_))) 03250 #elif (QS_OBJ_PTR_SIZE == 8) 03251 #define QS_OBJ(obj_) (QP_ QS::u64(QS_OBJ_T, (uint64_t)(obj_))) 03252 #else 03253 /// \brief Output formatted object pointer to the QS record 03254 #define QS_OBJ(obj_) (QP_ QS::u32(QS_OBJ_T, (uint32_t)(obj_))) 03255 #endif 03256 03257 03258 #if (QS_FUN_PTR_SIZE == 1) 03259 #define QS_FUN(fun_) (QP_ QS::u8(QS_FUN_T, (uint8_t)(fun_))) 03260 #elif (QS_FUN_PTR_SIZE == 2) 03261 #define QS_FUN(fun_) (QP_ QS::u16(QS_FUN_T, (uint16_t)(fun_))) 03262 #elif (QS_FUN_PTR_SIZE == 4) 03263 #define QS_FUN(fun_) (QP_ QS::u32(QS_FUN_T, (uint32_t)(fun_))) 03264 #elif (QS_FUN_PTR_SIZE == 8) 03265 #define QS_FUN(fun_) (QP_ QS::u64(QS_FUN_T, (uint64_t)(fun_))) 03266 #else 03267 /// \brief Output formatted function pointer to the QS record 03268 #define QS_FUN(fun_) (QP_ QS::u32(QS_FUN_T, (uint32_t)(fun_))) 03269 #endif 03270 03271 03272 /// \brief Reset the QS session. 03273 /// 03274 /// This trace record should be generated at the beginning of the QS session. 03275 /// It informs the QSPY host application that the new session has been started. 03276 #define QS_RESET() do { \ 03277 if (QS_GLB_FILTER_(QP_ QS_QP_RESET)) { \ 03278 QS_CRIT_STAT_ \ 03279 QS_CRIT_ENTRY_(); \ 03280 QP_ QS::begin(static_cast<uint8_t>(QP_ QS_QP_RESET)); \ 03281 QP_ QS::end(); \ 03282 QS_CRIT_EXIT_(); \ 03283 QP_ QS::onFlush(); \ 03284 } \ 03285 } while (false) 03286 03287 /// \brief Output signal dictionary record 03288 /// 03289 /// A signal dictionary record associates the numerical value of the signal 03290 /// and the binary address of the state machine that consumes that signal 03291 /// with the human-readable name of the signal. 03292 /// 03293 /// Providing a signal dictionary QS record can vastly improve readability of 03294 /// the QS log, because instead of dealing with cryptic machine addresses the 03295 /// QSpy host utility can display human-readable names. 03296 /// 03297 /// A signal dictionary entry is associated with both the signal value \a sig_ 03298 /// and the state machine \a obj_, because signals are required to be unique 03299 /// only within a given state machine and therefore the same numerical values 03300 /// can represent different signals in different state machines. 03301 /// 03302 /// For the "global" signals that have the same meaning in all state machines 03303 /// (such as globally published signals), you can specify a signal dictionary 03304 /// entry with the \a obj_ parameter set to NULL. 03305 /// 03306 /// The following example shows the definition of signal dictionary entries 03307 /// in the initial transition of the Table active object. Please note that 03308 /// signals HUNGRY_SIG and DONE_SIG are associated with the Table state 03309 /// machine only ("me" \a obj_ pointer). The EAT_SIG signal, on the other 03310 /// hand, is global (0 \a obj_ pointer): 03311 /// \include qs_sigDic.cpp 03312 /// 03313 /// \note The QSpy log utility must capture the signal dictionary record 03314 /// in order to use the human-readable information. You need to connect to 03315 /// the target before the dictionary entries have been transmitted. 03316 /// 03317 /// The following QSpy log example shows the signal dictionary records 03318 /// generated from the Table initial transition and subsequent records that 03319 /// show human-readable names of the signals: 03320 /// \include qs_sigLog.txt 03321 /// 03322 /// The following QSpy log example shows the same sequence of records, but 03323 /// with dictionary records removed. The human-readable signal names are not 03324 /// available. 03325 /// \include qs_sigLog0.txt 03326 #define QS_SIG_DICTIONARY(sig_, obj_) do { \ 03327 if (QS_GLB_FILTER_(QP_ QS_SIG_DIC)) { \ 03328 static char_t const Q_ROM Q_ROM_VAR sig_name_[] = #sig_; \ 03329 QS_CRIT_STAT_ \ 03330 QS_CRIT_ENTRY_(); \ 03331 QP_ QS::begin(static_cast<uint8_t>(QP_ QS_SIG_DIC)); \ 03332 QS_SIG_(sig_); \ 03333 QS_OBJ_(obj_); \ 03334 QS_STR_ROM_(&sig_name_[0]); \ 03335 QP_ QS::end(); \ 03336 QS_CRIT_EXIT_(); \ 03337 QP_ QS::onFlush(); \ 03338 } \ 03339 } while (false) 03340 03341 /// \brief Output object dictionary record 03342 /// 03343 /// An object dictionary record associates the binary address of an object 03344 /// in the target's memory with the human-readable name of the object. 03345 /// 03346 /// Providing an object dictionary QS record can vastly improve readability of 03347 /// the QS log, because instead of dealing with cryptic machine addresses the 03348 /// QSpy host utility can display human-readable object names. 03349 /// 03350 /// The following example shows the definition of object dictionary entry 03351 /// for the Table active object: 03352 /// \include qs_objDic.cpp 03353 #define QS_OBJ_DICTIONARY(obj_) do { \ 03354 if (QS_GLB_FILTER_(QP_ QS_OBJ_DIC)) { \ 03355 static char_t const Q_ROM Q_ROM_VAR obj_name_[] = #obj_; \ 03356 QS_CRIT_STAT_ \ 03357 QS_CRIT_ENTRY_(); \ 03358 QP_ QS::begin(static_cast<uint8_t>(QP_ QS_OBJ_DIC)); \ 03359 QS_OBJ_(obj_); \ 03360 QS_STR_ROM_(&obj_name_[0]); \ 03361 QP_ QS::end(); \ 03362 QS_CRIT_EXIT_(); \ 03363 QP_ QS::onFlush(); \ 03364 } \ 03365 } while (false) 03366 03367 /// \brief Output function dictionary record 03368 /// 03369 /// A function dictionary record associates the binary address of a function 03370 /// in the target's memory with the human-readable name of the function. 03371 /// 03372 /// Providing a function dictionary QS record can vastly improve readability 03373 /// of the QS log, because instead of dealing with cryptic machine addresses 03374 /// the QSpy host utility can display human-readable function names. 03375 /// 03376 /// The example from #QS_SIG_DICTIONARY shows the definition of a function 03377 /// dictionary. 03378 #define QS_FUN_DICTIONARY(fun_) do { \ 03379 if (QS_GLB_FILTER_(QP_ QS_FUN_DIC)) { \ 03380 static char_t const Q_ROM Q_ROM_VAR fun_name_[] = #fun_; \ 03381 QS_CRIT_STAT_ \ 03382 QS_CRIT_ENTRY_(); \ 03383 QP_ QS::begin(static_cast<uint8_t>(QP_ QS_FUN_DIC)); \ 03384 QS_FUN_(fun_); \ 03385 QS_STR_ROM_(&fun_name_[0]); \ 03386 QP_ QS::end(); \ 03387 QS_CRIT_EXIT_(); \ 03388 QP_ QS::onFlush(); \ 03389 } \ 03390 } while (false) 03391 03392 /// \brief Output user QS rectord dictionary record 03393 /// 03394 /// A user QS record dictionary record associates the numerical value of a 03395 /// user record with the human-readable identifier. 03396 #define QS_USR_DICTIONARY(rec_) do { \ 03397 if (QS_GLB_FILTER_(QP_ QS_USR_DIC)) { \ 03398 static char_t const Q_ROM Q_ROM_VAR usr_name_[] = #rec_; \ 03399 QS_CRIT_STAT_ \ 03400 QS_CRIT_ENTRY_(); \ 03401 QP_ QS::begin(static_cast<uint8_t>(QP_ QS_USR_DIC)); \ 03402 QS_U8_(static_cast<uint8_t>(rec_)); \ 03403 QS_STR_ROM_(&usr_name_[0]); \ 03404 QP_ QS::end(); \ 03405 QS_CRIT_EXIT_(); \ 03406 QP_ QS::onFlush(); \ 03407 } \ 03408 } while (false) 03409 03410 /// \brief Output the assertion violation 03411 #define QS_ASSERTION(module_, loc_) do { \ 03412 QS_BEGIN_NOCRIT_(QP_ QS_ASSERT, \ 03413 static_cast<void *>(0), static_cast<void *>(0)) \ 03414 QS_TIME_(); \ 03415 QS_U16_(static_cast<uint16_t>(loc_)); \ 03416 QS_STR_ROM_(module_); \ 03417 QS_END_NOCRIT_() \ 03418 QP_ QS::onFlush(); \ 03419 } while (false) 03420 03421 /// \brief Flush the QS trace data to the host 03422 /// 03423 /// This macro invokes the QS::flush() platform-dependent callback function 03424 /// to flush the QS trace buffer to the host. The function typically 03425 /// busy-waits until all the data in the buffer is sent to the host. 03426 /// This is acceptable only in the initial transient. 03427 #define QS_FLUSH() (QP_ QS::onFlush()) 03428 03429 /// \brief Output the critical section entry record 03430 #define QF_QS_CRIT_ENTRY() \ 03431 QS_BEGIN_NOCRIT_(QP_ QS_QF_CRIT_ENTRY, \ 03432 static_cast<void *>(0), static_cast<void *>(0)) \ 03433 QS_TIME_(); \ 03434 QS_U8_((uint8_t)(++QF_critNest_)); \ 03435 QS_END_NOCRIT_() 03436 03437 /// \brief Output the critical section exit record 03438 #define QF_QS_CRIT_EXIT() \ 03439 QS_BEGIN_NOCRIT_(QP_ QS_QF_CRIT_EXIT, \ 03440 static_cast<void *>(0), static_cast<void *>(0)) \ 03441 QS_TIME_(); \ 03442 QS_U8_((uint8_t)(QF_critNest_--)); \ 03443 QS_END_NOCRIT_() 03444 03445 /// \brief Output the interrupt entry record 03446 #define QF_QS_ISR_ENTRY(isrnest_, prio_) \ 03447 QS_BEGIN_NOCRIT_(QP_ QS_QF_ISR_ENTRY, \ 03448 static_cast<void *>(0), static_cast<void *>(0)) \ 03449 QS_TIME_(); \ 03450 QS_U8_(isrnest_); \ 03451 QS_U8_(prio_); \ 03452 QS_END_NOCRIT_() 03453 03454 /// \brief Output the interrupt exit record 03455 #define QF_QS_ISR_EXIT(isrnest_, prio_) \ 03456 QS_BEGIN_NOCRIT_(QP_ QS_QF_ISR_EXIT, \ 03457 static_cast<void *>(0), static_cast<void *>(0)) \ 03458 QS_TIME_(); \ 03459 QS_U8_(isrnest_); \ 03460 QS_U8_(prio_); \ 03461 QS_END_NOCRIT_() 03462 03463 /// \brief Execute an action that is only necessary for QS output 03464 #define QF_QS_ACTION(act_) (act_) 03465 03466 #else // Q_SPY 03467 03468 // qs_dummy.h ================================================================ 03469 /// \brief Dummy definitions of the QS macros that avoid code generation from 03470 /// the QS instrumentation. 03471 03472 #define QS_INIT(arg_) (true) 03473 #define QS_EXIT() ((void)0) 03474 #define QS_DUMP() ((void)0) 03475 #define QS_RESET() ((void)0) 03476 #define QS_FILTER_ON(rec_) ((void)0) 03477 #define QS_FILTER_OFF(rec_) ((void)0) 03478 #define QS_FILTER_SM_OBJ(obj_) ((void)0) 03479 #define QS_FILTER_AO_OBJ(obj_) ((void)0) 03480 #define QS_FILTER_MP_OBJ(obj_) ((void)0) 03481 #define QS_FILTER_EQ_OBJ(obj_) ((void)0) 03482 #define QS_FILTER_TE_OBJ(obj_) ((void)0) 03483 #define QS_FILTER_AP_OBJ(obj_) ((void)0) 03484 03485 #define QS_GET_BYTE(pByte_) (static_cast<uint16_t>(0xFFFFU)) 03486 #define QS_GET_BLOCK(pSize_) (static_cast<uint8_t *>(0)) 03487 03488 #define QS_BEGIN(rec_, obj_) if (false) { 03489 #define QS_END() } 03490 #define QS_BEGIN_NOCRIT(rec_, obj_) if (false) { 03491 #define QS_END_NOCRIT() } 03492 03493 #define QS_I8(width_, data_) ((void)0) 03494 #define QS_U8(width_, data_) ((void)0) 03495 #define QS_I16(width_, data_) ((void)0) 03496 #define QS_U16(width_, data_) ((void)0) 03497 #define QS_I32(width_, data_) ((void)0) 03498 #define QS_U32(width_, data_) ((void)0) 03499 #define QS_F32(width_, data_) ((void)0) 03500 #define QS_F64(width_, data_) ((void)0) 03501 #define QS_U64(width_, data_) ((void)0) 03502 #define QS_STR(str_) ((void)0) 03503 #define QS_U32_HEX(width_, data_) ((void)0) 03504 #define QS_STR_ROM(str_) ((void)0) 03505 #define QS_MEM(mem_, size_) ((void)0) 03506 #define QS_SIG(sig_, obj_) ((void)0) 03507 #define QS_OBJ(obj_) ((void)0) 03508 #define QS_FUN(fun_) ((void)0) 03509 03510 #define QS_SIG_DICTIONARY(sig_, obj_) ((void)0) 03511 #define QS_OBJ_DICTIONARY(obj_) ((void)0) 03512 #define QS_FUN_DICTIONARY(fun_) ((void)0) 03513 #define QS_USR_DICTIONARY(rec_) ((void)0) 03514 #define QS_ASSERTION(module_, loc_) ((void)0) 03515 #define QS_FLUSH() ((void)0) 03516 03517 // internal QS macros used only in the QP components ......................... 03518 #define QS_CRIT_STAT_ 03519 #define QS_BEGIN_(rec_, refObj_, obj_) if (false) { 03520 #define QS_END_() } 03521 #define QS_BEGIN_NOCRIT_(rec_, refObj_, obj_) if (false) { 03522 #define QS_END_NOCRIT_() } 03523 #define QS_U8_(data_) ((void)0) 03524 #define QS_U16_(data_) ((void)0) 03525 #define QS_U32_(data_) ((void)0) 03526 #define QS_U64_(data_) ((void)0) 03527 #define QS_TIME_() ((void)0) 03528 #define QS_SIG_(sig_) ((void)0) 03529 #define QS_EVS_(size_) ((void)0) 03530 #define QS_OBJ_(obj_) ((void)0) 03531 #define QS_FUN_(fun_) ((void)0) 03532 #define QS_EQC_(ctr_) ((void)0) 03533 #define QS_MPC_(ctr_) ((void)0) 03534 #define QS_MPS_(size_) ((void)0) 03535 #define QS_TEC_(ctr_) ((void)0) 03536 03537 #define QF_QS_CRIT_ENTRY() ((void)0) 03538 #define QF_QS_CRIT_EXIT() ((void)0) 03539 #define QF_QS_ISR_ENTRY(isrnest_, prio_) ((void)0) 03540 #define QF_QS_ISR_EXIT(isrnest_, prio_) ((void)0) 03541 #define QF_QS_ACTION(act_) ((void)0) 03542 03543 #endif // Q_SPY 03544 03545 // qassert.h ================================================================= 03546 /* \brief Customizable QP assertions. 03547 * 03548 * Defines customizable and memory-efficient assertions applicable to 03549 * embedded systems. This header file can be used in C, C++, and mixed C/C++ 03550 * programs. 03551 * 03552 * \note The preprocessor switch Q_NASSERT disables checking assertions. 03553 * In particular macros #Q_ASSERT, #Q_REQUIRE, #Q_ENSURE, #Q_INVARIANT, 03554 * #Q_ERROR as well as #Q_ASSERT_ID, #Q_REQUIRE_ID, #Q_ENSURE_ID, 03555 * #Q_INVARIANT_ID, and #Q_ERROR_ID do NOT evaluate the test condition 03556 * passed as the argument to these macros. One notable exception is the 03557 * macro #Q_ALLEGE, that still evaluates the test condition, but does 03558 * not report assertion failures when the switch Q_NASSERT is defined. 03559 */ 03560 #ifdef Q_NASSERT /* Q_NASSERT defined--assertion checking disabled */ 03561 03562 #define Q_DEFINE_THIS_FILE 03563 #define Q_DEFINE_THIS_MODULE(name_) 03564 #define Q_ASSERT(test_) ((void)0) 03565 #define Q_ASSERT_ID(id_, test_) ((void)0) 03566 #define Q_ALLEGE(test_) ((void)(test_)) 03567 #define Q_ALLEGE_ID(id_, test_) ((void)(test_)) 03568 #define Q_ERROR() ((void)0) 03569 #define Q_ERROR_ID(id_) ((void)0) 03570 03571 #else /* Q_NASSERT not defined--assertion checking enabled */ 03572 03573 #ifdef __cplusplus 03574 extern "C" { 03575 #endif 03576 03577 /** \brief Type for line numbers. 03578 * 03579 * This typedef specifies strong type for line numbers. The use of this 03580 * type, rather than plain 'int', is in compliance with the MISRA-C 2004 03581 * Rule 6.3(adv). 03582 */ 03583 typedef int int_t; 03584 03585 /** callback invoked in case the condition passed to #Q_ASSERT, 03586 * #Q_REQUIRE, #Q_ENSURE, #Q_ERROR, #Q_ALLEGE as well as #Q_ASSERT_ID, 03587 * #Q_REQUIRE_ID, #Q_ENSURE_ID, #Q_ERROR_ID, and #Q_ALLEGE_ID evaluates 03588 * to FALSE. 03589 * 03590 * \param file name where the assertion failed 03591 * \param line number at which the assertion failed 03592 */ 03593 void Q_onAssert(char_t const Q_ROM * const Q_ROM_VAR file, 03594 int_t const line); 03595 03596 #ifdef __cplusplus 03597 } 03598 #endif 03599 03600 /** Place this macro at the top of each C/C++ module to define the file 03601 * name string using __FILE__ (NOTE: __FILE__ might contain lengthy path 03602 * name). This file name will be used in reporting assertions in this file. 03603 */ 03604 #define Q_DEFINE_THIS_FILE \ 03605 static char_t const Q_ROM Q_ROM_VAR l_this_file[] = __FILE__; 03606 03607 /** Place this macro at the top of each C/C++ module to define the module 03608 * name as the argument \a name_. This file name will be used in reporting 03609 * assertions in this file. 03610 */ 03611 #define Q_DEFINE_THIS_MODULE(name_) \ 03612 static char_t const Q_ROM Q_ROM_VAR l_this_file[] = name_; 03613 03614 /** General purpose assertion that makes sure the \a test_ argument is 03615 * TRUE. Calls the Q_onAssert() callback if the \a test_ evaluates 03616 * to FALSE. 03617 * \note the \a test_ is NOT evaluated if assertions are disabled with 03618 * the Q_NASSERT switch. 03619 * \sa #Q_ASSERT_ID 03620 */ 03621 #define Q_ASSERT(test_) \ 03622 ((test_) ? (void)0 : Q_onAssert(&l_this_file[0], (int_t)__LINE__)) 03623 03624 /** General purpose assertion that makes sure the \a test_ argument is 03625 * TRUE. Calls the Q_onAssert() callback if the \a test_ evaluates 03626 * to FALSE. The argument \a id_ is the ID number (unique within 03627 * the file) of the assertion. This assertion style is better suited 03628 * for unit testig, because it avoids the volatility of line numbers 03629 * for indentifying assertions. 03630 * \note the \a test_ is NOT evaluated if assertions are disabled with 03631 * the Q_NASSERT switch. 03632 * \sa #Q_ASSERT 03633 */ 03634 #define Q_ASSERT_ID(id_, test_) \ 03635 ((test_) ? (void)0 : Q_onAssert(&l_this_file[0], (int_t)(id_)) 03636 03637 /** General purpose assertion that ALWAYS evaluates the \a test_ 03638 * argument and calls the Q_onAssert() callback if the \a test_ 03639 * evaluates to FALSE. 03640 * \note the \a test_ argument IS always evaluated even when assertions 03641 * are disabled with the Q_NASSERT macro. When the Q_NASSERT macro is 03642 * defined, the Q_onAssert() callback is NOT called, even if the 03643 * \a test_ evaluates to FALSE. 03644 * \sa #Q_ALLEGE_ID 03645 */ 03646 #define Q_ALLEGE(test_) Q_ASSERT(test_) 03647 03648 /** General purpose assertion that ALWAYS evaluates the \a test_ 03649 * argument and calls the Q_onAssert() callback if the \a test_ 03650 * evaluates to FALSE. This assertion style is better suited 03651 * for unit testig, because it avoids the volatility of line numbers 03652 * for indentifying assertions. 03653 * \note the \a test_ argument IS always evaluated even when assertions 03654 * are disabled with the Q_NASSERT macro. When the Q_NASSERT macro is 03655 * defined, the Q_onAssert() callback is NOT called, even if the 03656 * \a test_ evaluates to FALSE. 03657 * \sa #Q_ALLEGE 03658 */ 03659 #define Q_ALLEGE_ID(id_, test_) Q_ASSERT_ID(id_, test_) 03660 03661 /** Assertion that always calls the Q_onAssert() callback if 03662 * ever executed. 03663 * \note can be disabled with the Q_NASSERT switch. 03664 * \sa #Q_ERROR_ID 03665 */ 03666 #define Q_ERROR() \ 03667 Q_onAssert(&l_this_file[0], (int_t)__LINE__) 03668 03669 /** Assertion that always calls the Q_onAssert() callback if 03670 * ever executed. This assertion style is better suited for unit 03671 * testig, because it avoids the volatility of line numbers for 03672 * indentifying assertions. 03673 * \note can be disabled with the Q_NASSERT switch. 03674 * \sa #Q_ERROR 03675 */ 03676 #define Q_ERROR_ID(id_) \ 03677 Q_onAssert(l_this_file, (int_t)(id_)) 03678 03679 #endif /* Q_NASSERT */ 03680 03681 /** Assertion that checks for a precondition. This macro is equivalent to 03682 * #Q_ASSERT, except the name provides a better documentation of the 03683 * intention of this assertion. 03684 * \sa #Q_REQUIRE_ID 03685 */ 03686 #define Q_REQUIRE(test_) Q_ASSERT(test_) 03687 03688 /** Assertion that checks for a precondition. This macro is equivalent to 03689 * #Q_ASSERT_ID, except the name provides a better documentation of the 03690 * intention of this assertion. 03691 * \sa #Q_REQUIRE 03692 */ 03693 #define Q_REQUIRE_ID(id_, test_) Q_ASSERT_ID(id_, test_) 03694 03695 /** Assertion that checks for a postcondition. This macro is equivalent to 03696 * #Q_ASSERT, except the name provides a better documentation of the 03697 * intention of this assertion. 03698 * \sa #Q_ENSURE_ID 03699 */ 03700 #define Q_ENSURE(test_) Q_ASSERT(test_) 03701 03702 /** Assertion that checks for a postcondition. This macro is equivalent to 03703 * #Q_ASSERT_ID, except the name provides a better documentation of the 03704 * intention of this assertion. 03705 * \sa #Q_ENSURE 03706 */ 03707 #define Q_ENSURE_ID(id_, test_) Q_ASSERT_ID(id_, test_) 03708 03709 /** Assertion that checks for an invariant. This macro is equivalent to 03710 * #Q_ASSERT, except the name provides a better documentation of the 03711 * intention of this assertion. 03712 * \sa #Q_INVARIANT_ID 03713 */ 03714 #define Q_INVARIANT(test_) Q_ASSERT(test_) 03715 03716 /** Assertion that checks for an invariant. This macro is equivalent to 03717 * #Q_ASSERT_ID, except the name provides a better documentation of the 03718 * intention of this assertion. 03719 * \sa #Q_INVARIANT 03720 */ 03721 #define Q_INVARIANT_ID(id_, test_) Q_ASSERT_ID(id_, test_) 03722 03723 /** Compile-time assertion exploits the fact that in C/C++ a dimension of 03724 * an array cannot be negative. The following declaration causes a compilation 03725 * error if the compile-time expression (\a test_) is not TRUE. The assertion 03726 * has no runtime side effects. 03727 */ 03728 #define Q_ASSERT_COMPILE(test_) \ 03729 extern int_t Q_assert_compile[(test_) ? 1 : -1] 03730 03731 #endif // qp_h
Generated on Wed Jul 13 2022 11:50:18 by
![doxygen](doxygen.png)