From a2c05d3b05af026249b0185dea28f8ec511542bf Mon Sep 17 00:00:00 2001 From: MMS Date: Sat, 17 Feb 2024 21:27:27 -0500 Subject: [PATCH] 7.3.3 bug https://sourceforge.net/p/qpc/bugs/349/ QS adaptation for MPU isolation --- 3rd_party | 2 +- examples | 2 +- include/qp.hpp | 28 +- include/qs.hpp | 372 ++++++++------ ports/lint-plus/cstddef | 42 ++ ports/lint-plus/new | 29 -- ports/lint-plus/options.lnt | 48 +- ports/lint-plus/qpcpp.lnt | 33 +- qpcpp.md5 | 21 +- qpcpp.qm | 990 +++++++++++++++++++----------------- qpcpp_md5.bat | 1 + src/qf/qep_hsm.cpp | 110 ++-- src/qf/qep_msm.cpp | 105 ++-- src/qf/qf_dyn.cpp | 24 +- src/qs/qs_rx.cpp | 508 +++++++++--------- 15 files changed, 1245 insertions(+), 1070 deletions(-) create mode 100644 ports/lint-plus/cstddef delete mode 100644 ports/lint-plus/new diff --git a/3rd_party b/3rd_party index 025100adc..ebe4896f8 160000 --- a/3rd_party +++ b/3rd_party @@ -1 +1 @@ -Subproject commit 025100adc4853702cd6ce6fa733b206c6a70ee8a +Subproject commit ebe4896f82bdb7b883f42f930307d243a4cd43d6 diff --git a/examples b/examples index 9b8141914..c89346fe6 160000 --- a/examples +++ b/examples @@ -1 +1 @@ -Subproject commit 9b8141914cce0d7320b1407c0c4c2448f046c271 +Subproject commit c89346fe6c765ac03d6d55d7ee0aa9c082bfa046 diff --git a/include/qp.hpp b/include/qp.hpp index 8cb9c9849..0000778d6 100644 --- a/include/qp.hpp +++ b/include/qp.hpp @@ -99,11 +99,6 @@ //! @endcond //============================================================================ -#ifdef QEVT_DYN_CTOR -#include // for placement new -#include // for va_list -#endif // QEVT_DYN_CTOR - //$declare${glob-types} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv //${glob-types::int_t} ....................................................... @@ -155,19 +150,16 @@ class QEvt { #endif // def QEVT_DYN_CTOR public: - QEvt() = delete; + +#ifdef QEVT_DYN_CTOR + QEvt * ctor(DynEvt const dummy) noexcept; +#endif // def QEVT_DYN_CTOR explicit constexpr QEvt(QSignal const s) noexcept : sig(s), refCtr_(0U), evtTag_(MARKER) {} - -#ifdef QEVT_DYN_CTOR - explicit QEvt(DynEvt dummy) noexcept { - static_cast(dummy); // unused parameter - // dynamic event already initialized in QP::QF::newX_() - } -#endif // def QEVT_DYN_CTOR + QEvt() = delete; static bool verify_(QEvt const * const e) noexcept { return (e != nullptr) && ((e->evtTag_ & 0xF0U) == MARKER); @@ -1188,9 +1180,8 @@ void QF_onContextSw( //${QF-macros::Q_NEW} ........................................................ #ifdef QEVT_DYN_CTOR -#define Q_NEW(evtT_, sig_, ...) (static_cast( \ - new(QP::QF::newX_(sizeof(evtT_), QP::QF::NO_MARGIN, (sig_))) \ - evtT_(__VA_ARGS__))) +#define Q_NEW(evtT_, sig_, ...) ( static_cast( \ + QP::QF::newX_(sizeof(evtT_), QP::QF::NO_MARGIN, (sig_)))->ctor(__VA_ARGS__)) #endif // def QEVT_DYN_CTOR //${QF-macros::Q_NEW_X} ...................................................... @@ -1201,9 +1192,8 @@ void QF_onContextSw( //${QF-macros::Q_NEW_X} ...................................................... #ifdef QEVT_DYN_CTOR -#define Q_NEW_X(evtT_, margin_, sig_, ...) (static_cast( \ - new(QP::QF::newX_(sizeof(evtT_), (margin_), (sig_))) \ - evtT_(__VA_ARGS__))) +#define Q_NEW_X(evtT_, margin_, sig_, ...) ( static_cast( \ + QP::QF::newX_(sizeof(evtT_), (margin_), (sig_)))->ctor(__VA_ARGS__)) #endif // def QEVT_DYN_CTOR //${QF-macros::Q_NEW_REF} .................................................... diff --git a/include/qs.hpp b/include/qs.hpp index 24e4bcaaf..f6466051a 100644 --- a/include/qs.hpp +++ b/include/qs.hpp @@ -249,6 +249,36 @@ struct QSpyId { } }; +//${QS::types::QSObj} ........................................................ +#if (QS_OBJ_PTR_SIZE == 2U) +using QSObj = std::uint16_t; +#endif // (QS_OBJ_PTR_SIZE == 2U) + +//${QS::types::QSObj} ........................................................ +#if (QS_OBJ_PTR_SIZE == 4U) +using QSObj = std::uint32_t; +#endif // (QS_OBJ_PTR_SIZE == 4U) + +//${QS::types::QSObj} ........................................................ +#if (QS_OBJ_PTR_SIZE == 8U) +using QSObj = std::uint64_t; +#endif // (QS_OBJ_PTR_SIZE == 8U) + +//${QS::types::QSFun} ........................................................ +#if (QS_FUN_PTR_SIZE == 2U) +using QSFun = std::uint16_t; +#endif // (QS_FUN_PTR_SIZE == 2U) + +//${QS::types::QSFun} ........................................................ +#if (QS_FUN_PTR_SIZE == 4U) +using QSFun = std::uint32_t; +#endif // (QS_FUN_PTR_SIZE == 4U) + +//${QS::types::QSFun} ........................................................ +#if (QS_FUN_PTR_SIZE == 8U) +using QSFun = std::uint64_t; +#endif // (QS_FUN_PTR_SIZE == 8U) + //${QS::types::QSpyFunPtr} ................................................... using QSpyFunPtr = void (*)(); @@ -272,21 +302,6 @@ using QSTimeCtr = std::uint16_t; using QSTimeCtr = std::uint32_t; #endif // (QS_TIME_SIZE == 4U) -//${QS::types::QSFun} ........................................................ -#if (QS_FUN_PTR_SIZE == 2U) -using QSFun = std::uint16_t; -#endif // (QS_FUN_PTR_SIZE == 2U) - -//${QS::types::QSFun} ........................................................ -#if (QS_FUN_PTR_SIZE == 4U) -using QSFun = std::uint32_t; -#endif // (QS_FUN_PTR_SIZE == 4U) - -//${QS::types::QSFun} ........................................................ -#if (QS_FUN_PTR_SIZE == 8U) -using QSFun = std::uint64_t; -#endif // (QS_FUN_PTR_SIZE == 8U) - } // namespace QP //$enddecl${QS::types} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //$declare${QS::filters} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv @@ -624,71 +639,43 @@ void beginRec_(std::uint_fast8_t const rec) noexcept; void endRec_() noexcept; void u8_raw_(std::uint8_t const d) noexcept; -void u8u8_raw_( - std::uint8_t const d1, - std::uint8_t const d2) noexcept; +void u8u8_raw_(std::uint8_t const d1, std::uint8_t const d2) noexcept; void u16_raw_(std::uint16_t d) noexcept; void u32_raw_(std::uint32_t d) noexcept; void u64_raw_(std::uint64_t d) noexcept; void obj_raw_(void const * const obj) noexcept; void str_raw_(char const * s) noexcept; -void u8_fmt_( - std::uint8_t const format, - std::uint8_t const d) noexcept; -void u16_fmt_( - std::uint8_t format, - std::uint16_t d) noexcept; -void u32_fmt_( - std::uint8_t format, +void u8_fmt_(std::uint8_t const format, std::uint8_t const d) noexcept; +void u16_fmt_(std::uint8_t format, std::uint16_t d) noexcept; +void u32_fmt_(std::uint8_t format, std::uint32_t d) noexcept; -void u64_fmt_( - std::uint8_t format, - std::uint64_t d) noexcept; -void f32_fmt_( - std::uint8_t format, - float32_t f) noexcept; -void f64_fmt_( - std::uint8_t format, - float64_t d) noexcept; +void u64_fmt_(std::uint8_t format, std::uint64_t d) noexcept; +void f32_fmt_(std::uint8_t format, float32_t f) noexcept; +void f64_fmt_(std::uint8_t format, float64_t d) noexcept; void str_fmt_(char const * s) noexcept; -void mem_fmt_( - std::uint8_t const * blk, - std::uint8_t size) noexcept; +void mem_fmt_(std::uint8_t const * blk, std::uint8_t size) noexcept; -void sig_dict_pre_( - QSignal const sig, - void const * const obj, +void sig_dict_pre_(QSignal const sig, void const * const obj, char const * const name) noexcept; -void obj_dict_pre_( - void const * const obj, +void obj_dict_pre_(void const * const obj, char const * const name) noexcept; -void obj_arr_dict_pre_( - void const * const obj, +void obj_arr_dict_pre_(void const * const obj, std::uint_fast16_t const idx, char const * const name) noexcept; -void fun_dict_pre_( - QSpyFunPtr fun, +void fun_dict_pre_(QSpyFunPtr fun, char const * const name) noexcept; -void usr_dict_pre_( - enum_t const rec, - char const * const name) noexcept; -void enum_dict_pre_( - enum_t const value, - std::uint8_t const group, +void usr_dict_pre_(enum_t const rec, char const * const name) noexcept; +void enum_dict_pre_(enum_t const value, std::uint8_t const group, char const * const name) noexcept; -void assertion_pre_( - char const * const module, - int_t const id, +void assertion_pre_(char const * const module, int_t const id, std::uint32_t const delay) noexcept; void crit_entry_pre_() noexcept; void crit_exit_pre_() noexcept; -void isr_entry_pre_( - std::uint8_t const isrnest, +void isr_entry_pre_(std::uint8_t const isrnest, std::uint8_t const prio) noexcept; -void isr_exit_pre_( - std::uint8_t const isrnest, +void isr_exit_pre_(std::uint8_t const isrnest, std::uint8_t const prio) noexcept; void target_info_pre_(std::uint8_t const isReset); @@ -763,105 +750,6 @@ QSTimeCtr onGetTime(); } // namespace QP //$enddecl${QS::QS-TX} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//============================================================================ -//! @cond INTERNAL - -namespace QP { -namespace QS { - -struct RxAttr { - void * currObj[8]; - std::uint8_t * buf; - QSCtr end; - QSCtr volatile head; - QSCtr volatile tail; -#ifdef Q_UTEST - bool inTestLoop; -#endif -} ; - -extern RxAttr rxPriv_; - -} // namespace QS -} // namespace QP - -//! @endcond -//============================================================================ - -//$declare${QS::QS-RX} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { -namespace QS { - -//${QS::QS-RX::QSpyObjKind} .................................................. -//! Kinds of objects used QS-RX -enum QSpyObjKind : std::uint8_t { - SM_OBJ, //!< state machine object - AO_OBJ, //!< active object - MP_OBJ, //!< event pool object - EQ_OBJ, //!< raw queue object - TE_OBJ, //!< time event object - AP_OBJ, //!< generic Application-specific object - MAX_OBJ -}; - -//${QS::QS-RX::OSpyObjCombnation} ............................................ -//! Object combinations for QS-RX -enum OSpyObjCombnation : std::uint8_t { - SM_AO_OBJ = MAX_OBJ //!< combination of SM and AO -}; - -//${QS::QS-RX::rxInitBuf} .................................................... -void rxInitBuf( - std::uint8_t * const sto, - std::uint16_t const stoSize) noexcept; - -//${QS::QS-RX::rxPut} ........................................................ -inline bool rxPut(std::uint8_t const b) noexcept { - // NOTE: does not need critical section - // But requires system-level memory access (QF_MEM_SYS()). - - QSCtr head = rxPriv_.head + 1U; - if (head == rxPriv_.end) { - head = 0U; - } - if (head != rxPriv_.tail) { // buffer NOT full? - rxPriv_.buf[rxPriv_.head] = b; - rxPriv_.head = head; - return true; // byte placed in the buffer - } - else { - return false; // byte NOT placed in the buffer - } -} - -//${QS::QS-RX::rxParse} ...................................................... -void rxParse(); - -//${QS::QS-RX::setCurrObj} ................................................... -void setCurrObj( - std::uint8_t const obj_kind, - void * const obj_ptr); - -//${QS::QS-RX::rxGetNfree} ................................................... -std::uint16_t rxGetNfree() noexcept; - -//${QS::QS-RX::doInput} ...................................................... -void doInput(); - -//${QS::QS-RX::onReset} ...................................................... -void onReset(); - -//${QS::QS-RX::onCommand} .................................................... -void onCommand( - std::uint8_t cmdId, - std::uint32_t param1, - std::uint32_t param2, - std::uint32_t param3); - -} // namespace QS -} // namespace QP -//$enddecl${QS::QS-RX} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - //============================================================================ #ifdef Q_UTEST @@ -1001,4 +889,170 @@ class QActiveDummy : public QP::QActive { #endif // Q_UTEST +//============================================================================ +//! @cond INTERNAL + +namespace QP { +namespace QS { + +//............................................................................ +struct CmdVar { + std::uint32_t param1; + std::uint32_t param2; + std::uint32_t param3; + std::uint8_t idx; + std::uint8_t cmdId; +}; + +struct TickVar { + std::uint_fast8_t rate; +}; + +struct PeekVar { + std::uint16_t offs; + std::uint8_t size; + std::uint8_t num; + std::uint8_t idx; +}; + +struct PokeVar { + std::uint32_t data; + std::uint16_t offs; + std::uint8_t size; + std::uint8_t num; + std::uint8_t idx; + std::uint8_t fill; +}; + +struct FltVar { + std::uint8_t data[16]; + std::uint8_t idx; + std::uint8_t recId; // global/local +}; + +struct ObjVar { + QSObj addr; + std::uint8_t idx; + std::uint8_t kind; // see qs.hpp, enum QSpyObjKind + std::uint8_t recId; +}; + +struct EvtVar { + QP::QEvt *e; + std::uint8_t *p; + QP::QSignal sig; + std::uint16_t len; + std::uint8_t prio; + std::uint8_t idx; +}; + +struct RxAttr { + void * currObj[8]; + std::uint8_t * buf; + QSCtr end; + QSCtr volatile head; + QSCtr volatile tail; + std::uint8_t state; + std::uint8_t esc; + std::uint8_t seq; + std::uint8_t chksum; +#ifdef Q_UTEST + bool inTestLoop; +#endif + union Variant { + CmdVar cmd; + TickVar tick; + PeekVar peek; + PokeVar poke; + FltVar flt; + ObjVar obj; + EvtVar evt; +#ifdef Q_UTEST + QP::QS::TProbe tp; +#endif // Q_UTEST + } var; +} ; + +extern RxAttr rxPriv_; + +} // namespace QS +} // namespace QP + +//! @endcond +//============================================================================ + +//$declare${QS::QS-RX} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +namespace QP { +namespace QS { + +//${QS::QS-RX::QSpyObjKind} .................................................. +//! Kinds of objects used QS-RX +enum QSpyObjKind : std::uint8_t { + SM_OBJ, //!< state machine object + AO_OBJ, //!< active object + MP_OBJ, //!< event pool object + EQ_OBJ, //!< raw queue object + TE_OBJ, //!< time event object + AP_OBJ, //!< generic Application-specific object + MAX_OBJ +}; + +//${QS::QS-RX::OSpyObjCombnation} ............................................ +//! Object combinations for QS-RX +enum OSpyObjCombnation : std::uint8_t { + SM_AO_OBJ = MAX_OBJ //!< combination of SM and AO +}; + +//${QS::QS-RX::rxInitBuf} .................................................... +void rxInitBuf( + std::uint8_t * const sto, + std::uint16_t const stoSize) noexcept; + +//${QS::QS-RX::rxPut} ........................................................ +inline bool rxPut(std::uint8_t const b) noexcept { + // NOTE: does not need critical section + // But requires system-level memory access (QF_MEM_SYS()). + + QSCtr head = rxPriv_.head + 1U; + if (head == rxPriv_.end) { + head = 0U; + } + if (head != rxPriv_.tail) { // buffer NOT full? + rxPriv_.buf[rxPriv_.head] = b; + rxPriv_.head = head; + return true; // byte placed in the buffer + } + else { + return false; // byte NOT placed in the buffer + } +} + +//${QS::QS-RX::rxParse} ...................................................... +void rxParse(); + +//${QS::QS-RX::setCurrObj} ................................................... +void setCurrObj( + std::uint8_t const obj_kind, + void * const obj_ptr); + +//${QS::QS-RX::rxGetNfree} ................................................... +std::uint16_t rxGetNfree() noexcept; + +//${QS::QS-RX::doInput} ...................................................... +void doInput(); + +//${QS::QS-RX::onReset} ...................................................... +void onReset(); + +//${QS::QS-RX::onCommand} .................................................... +void onCommand( + std::uint8_t cmdId, + std::uint32_t param1, + std::uint32_t param2, + std::uint32_t param3); + +} // namespace QS +} // namespace QP +//$enddecl${QS::QS-RX} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + #endif // QS_HPP_ diff --git a/ports/lint-plus/cstddef b/ports/lint-plus/cstddef new file mode 100644 index 000000000..f2d44f23b --- /dev/null +++ b/ports/lint-plus/cstddef @@ -0,0 +1,42 @@ +#ifndef _CSTDDEF_ +#define _CSTDDEF_ + +//lint -save +//lint -e9093 the name is reserved to the compiler +//lint -e9141 global declaration of symbol 'operator new' +//lint -e9215 unnamed parameter for 'non-virtual' function 'operator new' + +namespace std { + using ptrdiff_t = unsigned int; + using size_t = unsigned int; + using max_align_t = unsigned int; + using nullptr_t = decltype(nullptr); + + enum class byte : unsigned char {}; + + // byte type operations + template + constexpr byte& operator<<=(byte& b, IntType shift) noexcept; + template + constexpr byte operator<<(byte b, IntType shift) noexcept; + template + constexpr byte& operator>>=(byte& b, IntType shift) noexcept; + template + constexpr byte operator>>(byte b, IntType shift) noexcept; + constexpr byte& operator|=(byte& l, byte r) noexcept; + constexpr byte operator|(byte l, byte r) noexcept; + constexpr byte& operator&=(byte& l, byte r) noexcept; + constexpr byte operator&(byte l, byte r) noexcept; + constexpr byte& operator^=(byte& l, byte r) noexcept; + constexpr byte operator^(byte l, byte r) noexcept; + constexpr byte operator~(byte b) noexcept; + template + constexpr IntType to_integer(byte b) noexcept; +} + +#define NULL nullptr +//#define offsetof(type, member) ... + +//lint -restore + +#endif // _CSTDDEF_ \ No newline at end of file diff --git a/ports/lint-plus/new b/ports/lint-plus/new deleted file mode 100644 index 807f5192f..000000000 --- a/ports/lint-plus/new +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef _NEW -#define _NEW - -namespace std { - -typedef unsigned long size_t; - -// These are replaceable signatures: -// - normal single new and delete (no arguments, throw @c bad_alloc on error) -// - normal array new and delete (same) -// - @c nothrow single new and delete (take a @c nothrow argument, return -// @c NULL on error) -// - @c nothrow array new and delete (same) -// -// Placement new and delete signatures (take a memory address argument, -// does nothing) may not be replaced by a user's program. -// - -// Default placement versions of operator new. -inline void *operator new(size_t, void *__p) throw() { return __p; } -inline void *operator new[](size_t, void *__p) throw() { return __p; } - -// Default placement versions of operator delete. -inline void operator delete (void *, void *) throw() { } -inline void operator delete[](void *, void *) throw() { } - -} // namespace std - -#endif diff --git a/ports/lint-plus/options.lnt b/ports/lint-plus/options.lnt index abf3ccc9d..cb496832f 100644 --- a/ports/lint-plus/options.lnt +++ b/ports/lint-plus/options.lnt @@ -22,7 +22,7 @@ // // //============================================================================ -//! @date Last updated on: 2023-09-08 +//! @date Last updated on: 2024-02-19 //! @version Last updated for: @ref qpcpp_7_3_0 //! //! @file @@ -141,12 +141,13 @@ qpcpp.lnt // QP/C++ options -emacro(826, QTICKER_CAST_) -// AUTOSAR Rule M5-2-9 casting from pointer type to integer type +// AC++M5-2-9 casting from pointer type to integer type -emacro(9091, Q_UINTPTR_CAST_) -// [AUTOSAR Rule A12-1-1] non-static data member not initialized by ctor +// [AC++M12-1-1] non-static data member not initialized by ctor -esym(1401, + QP::QEvt::*, QP::QActive::*) // definition of macro ends in semi-colon @@ -179,15 +180,6 @@ qpcpp.lnt // QP/C++ options -emacro(9079, QF_EPOOL_GET_) --efunc(9079, - QP::QF::bzero_, - QP::QTimeEvt::armX, - QP::QTimeEvt::disarm, - QP::QTimeEvt::rearm, - QP::QMPool::init, - QP::QMPool::get, - QP::QMPool::put) - // M3-R18.3(r) relational operator <= applied to pointers -emacro(946, QF_PTR_RANGE_) @@ -208,16 +200,7 @@ qpcpp.lnt // QP/C++ options -esym(952, QP::QEQueue::init) -// call to unqualified virtual function 'QP::*::init' -// from non-static member function --esym(1933, - QP::*::init) - -// [AUTOSAR Rule M7-3-1] lobal declaration of symbol 'dummy' in the file --esym(9141, - dummy) - -// AUTOSAR Rule M5-2-3: downcast of polymorphic type +// AC++M5-2-3: downcast of polymorphic type -efunc(9171, QP::QActive::post_, QP::QActive::postLIFO) @@ -227,11 +210,30 @@ qpcpp.lnt // QP/C++ options QP::QActive::post_, QP::QActive::postLIFO) -// PCLP-1939: casting from base class to derived class +// [AC++M5-2-2]: casting from base class to derived class (QP::QActiveDummy) -efunc(1939, QP::QActive::post_, QP::QActive::postLIFO) +// PCLP-1731: public virtual function (in a class without virtual destructor) +-esym(1731, + QP::QTicker::*) + + // PCLP-1933: call to unqualified virtual function from non-static member function +-efunc(1933, + QP::QActive::start) + +// PCLP-9079: +-efunc(9079, + QP::QF::bzero_, + QP::QTimeEvt::armX, + QP::QTimeEvt::disarm, + QP::QTimeEvt::rearm, + QP::QMPool::init, + QP::QMPool::get, + QP::QMPool::put) + + // QV ------------------------------------------------------------------------ // MC++R16-0-4 function-like macro -esym(9026, diff --git a/ports/lint-plus/qpcpp.lnt b/ports/lint-plus/qpcpp.lnt index 9e12efb06..dd1d1eb16 100644 --- a/ports/lint-plus/qpcpp.lnt +++ b/ports/lint-plus/qpcpp.lnt @@ -22,8 +22,8 @@ // // //============================================================================ -//! @date Last updated on: 2023-09-01 -//! @version Last updated for version: 7.3.0 +//! @date Last updated on: 2024-02-18 +//! @version Last updated for version: 7.3.3 //! //! @file //! @brief PC-Lint-Plus option file for linting QP/C++ __Applications__ @@ -270,25 +270,6 @@ Q_NEW_X, Q_NEW_REF) -// implicit conversion (call) from 'enum ...' to 'const enum_t' --emacro(713, - Q_NEW, - Q_NEW_X) - -// implicit conversion of 'enum ...' to integral type 'enum_t' --emacro(641, - Q_NEW, - Q_NEW_X) - -// public virtual function 'QP::QHsm::...' --esym(1731, - QP::QActive::*, - QP::QMActive::*, - QP::QTicker::*) - -// public base 'QP::QEvt' has no non-destructor virtual functions --esym(1790, - QP::QEvt) // QK ------------------------------------------------------------------------ @@ -297,7 +278,7 @@ QK_ISR_ENTRY, QK_ISR_EXIT) -// MC++R7-3-1 global declaration of symbol +// AC++M7-3-1 global declaration of symbol -esym(9141, QK_Attr) @@ -453,10 +434,6 @@ QS_USR_DICTIONARY, QS_ENUM_DICTIONARY) -// MC++R9-5-1 union 'TCast' declared --esym(9018, - TCast) - // M3-R10.3(r) cannot assign enum to different essential type -emacro(9034, QS_SIG_DICTIONARY) @@ -476,5 +453,7 @@ -esym(9018, F32Rep, F64Rep, - U32Rep) + U32Rep, + TCast, + QP::QS::RxAttr::Variant) diff --git a/qpcpp.md5 b/qpcpp.md5 index e7564ffc7..0887c8018 100644 --- a/qpcpp.md5 +++ b/qpcpp.md5 @@ -1,23 +1,23 @@ -47986b70c115871c237783a4e4eb4576 *qpcpp.qm +ddd90780c6b874c0f8d27fe842e6005e *qpcpp.qm da3f0e1d1bc147b9e5ee801bc1fdd130 *include/qequeue.hpp fe1ff6084ff592ca8d14a6efffec296c *include/qk.hpp ebf2cb455c1471c2248bbde4b90ce634 *include/qmpool.hpp -377391a63f2d24d9ba9f1d8cff2f5366 *include/qp.hpp +344c0ecb3d7f5645a5f4e75aea7956ac *include/qp.hpp 61c7a3aa8cb265f478915f39b7fae9cc *include/qp_pkg.hpp 81e2fed348f03200d00b4d7c4473826f *include/qpcpp.hpp -b97591429612996ff62d1f2c472b82fb *include/qs.hpp +be2da5d56117fd172f12c8b6589f6402 *include/qs.hpp d59808009be96849963572ffcbf9dceb *include/qs_dummy.hpp db4013ceefb33498f5d38e15d0cb9323 *include/qs_pkg.hpp 2a36b08d4f3ec92da6ae6f7c18ad83ca *include/qsafe.h e66cf5dd191fb0e7c1f8660fb477b860 *include/qstamp.hpp d42a19307ba3c0c5b890431767f35b42 *include/qv.hpp c0bc33e3823dde00803a301c4b85637d *include/qxk.hpp -fbf5677e511880c581cf4a12269174d3 *src/qf/qep_hsm.cpp -03756de2431414185d61aa3f838e699d *src/qf/qep_msm.cpp +88c84e634597fafced2012faea838750 *src/qf/qep_hsm.cpp +becbd953c6da010daddf4907784e9766 *src/qf/qep_msm.cpp 8b5c1ece58069ed5582864fd2dc58167 *src/qf/qf_act.cpp 8fca896aa3dee712f6c844a0f31c130e *src/qf/qf_actq.cpp 39b02b596faa57abfa96b0f7c3f7fb82 *src/qf/qf_defer.cpp -69c1fcdd15230427a077a607ebb9a7a0 *src/qf/qf_dyn.cpp +069220fa20ca5bd9e0ddfcb2f4f8f0ba *src/qf/qf_dyn.cpp 0d3572af3a2acbf7144b27be35fa018a *src/qf/qf_mem.cpp 40218fcd6cbb521f2c8ae5f7c0d5c04e *src/qf/qf_ps.cpp 19cf8976578a43e93bfbb51dbe932b6c *src/qf/qf_qact.cpp @@ -28,7 +28,7 @@ c49e1c15e6d6e035668d910c8d13a684 *src/qf/qf_time.cpp ecdd6f0f0a7dc56d8bb0c769e67b48fc *src/qs/qs.cpp a2ca20b2332d025067645839e4b25711 *src/qs/qs_64bit.cpp 8f6551c7786fdbb106c3d1bc7824c060 *src/qs/qs_fp.cpp -4e403740b59b9352c7bf3fea54c0e524 *src/qs/qs_rx.cpp +4af89f114491668f7a26af694ff11993 *src/qs/qs_rx.cpp 2655cd10d009075b71a84368fb6bf4d4 *src/qs/qstamp.cpp 180d454ecdbd08f522ff9a9c299de5df *src/qs/qutest.cpp deac78388761a8e1d4d0e5c51d5b338b *src/qv/qv.cpp @@ -36,6 +36,13 @@ deac78388761a8e1d4d0e5c51d5b338b *src/qv/qv.cpp efe0395b16911eaff880649a9968d6a3 *src/qxk/qxk_mutex.cpp ce5ff1926bd91dd8683e0232d3e1d471 *src/qxk/qxk_sema.cpp 78ec1d0d6aa9efbdc8b3d09e6deea40e *src/qxk/qxk_xthr.cpp +bf56a383eb7dafafa408d6219b585b40 *ports/lint-plus/au-autosar.lnt +e3e3f3000f9a80a446255ef52f3a6299 *ports/lint-plus/au-autosar19.lnt +2a8fea61bccbe5e8c7536a29f2ec8e98 *ports/lint-plus/au-ds.lnt +ede719cdbc201d14586a3f11e77ced26 *ports/lint-plus/au-ql-cpp11.lnt +dddbecd55afec10d85006f7787e40c7d *ports/lint-plus/options.lnt +00e7bc0ddabc998469615ac2ff9d79f1 *ports/lint-plus/qpcpp.lnt +5f789348dba099c2055f737ba756faac *ports/lint-plus/std.lnt 1f3d9dfbf71077abbdb9f27c96879101 *ports/arm-cm/qk/armclang/qk_port.cpp aba379ac6a39b1f21057bed8156f0516 *ports/arm-cm/qk/armclang/qp_port.hpp 91a3b66c3f12a98bef48b00640ed5e6d *ports/arm-cm/qk/armclang/qs_port.hpp diff --git a/qpcpp.qm b/qpcpp.qm index 0a838d1a5..715c0a74f 100644 --- a/qpcpp.qm +++ b/qpcpp.qm @@ -79,9 +79,13 @@ Contact information: : std::uint8_t { DYNAMIC }; - - - = delete + + + noexcept + + + Q_UNUSED_PAR(dummy); +return this; @@ -93,12 +97,8 @@ Contact information: evtTag_(MARKER) - - noexcept - - - static_cast<void>(dummy); // unused parameter -// dynamic event already initialized in QP::QF::newX_() + + = delete @@ -472,20 +472,24 @@ QS_MEM_APP(); QF_CRIT_EXIT(); // drill down into the state hierarchy with initial transitions... +std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit do { QStateHandler path[MAX_NEST_DEPTH_]; // tran entry path array - std::int_fast8_t ip = 0; // entry path index + std::int_fast8_t ip = 0; // tran entry path index path[0] = m_temp.fun; static_cast<void>(QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG)); while (m_temp.fun != t) { ++ip; - QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(220, ip < MAX_NEST_DEPTH_); - QF_CRIT_EXIT(); path[ip] = m_temp.fun; static_cast<void>(QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG)); } + QF_CRIT_ENTRY(); + // The initial transition source state must be reached + // Too many state nesting levels or "malformed" HSM. + Q_ASSERT_INCRIT(220, m_temp.fun == t); + QF_CRIT_EXIT(); + m_temp.fun = path[0]; // retrace the entry path in reverse (desired) order... @@ -517,9 +521,14 @@ do { } #endif // Q_SPY -} while (r == Q_RET_TRAN); + --limit; +} while ((r == Q_RET_TRAN) && (limit > 0)); + +QF_CRIT_ENTRY(); +// Loop limit must not be reached. +// Too many state nesting levels or likely "malformed" HSM +Q_ENSURE_INCRIT(290, limit > 0); -QS_CRIT_ENTRY(); QS_MEM_SYS(); QS_BEGIN_PRE_(QS_QEP_INIT_TRAN, qsId) QS_TIME_PRE_(); // time stamp @@ -527,7 +536,8 @@ QS_BEGIN_PRE_(QS_QEP_INIT_TRAN, qsId) QS_FUN_PRE_(t); // the new active state QS_END_PRE_() QS_MEM_APP(); -QS_CRIT_EXIT(); + +QF_CRIT_EXIT(); m_state.fun = t; // change the current active state #ifndef Q_UNSAFE @@ -575,6 +585,7 @@ QF_CRIT_EXIT(); // process the event hierarchically... QState r; m_temp.fun = s; +std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit do { s = m_temp.fun; r = (*s)(this, e); // invoke state handler s @@ -593,7 +604,13 @@ do { r = QHSM_RESERVED_EVT_(s, Q_EMPTY_SIG); // superstate of s } -} while (r == Q_RET_SUPER); + + --limit; +} while ((r == Q_RET_SUPER) && (limit > 0)); + +QF_CRIT_ENTRY(); +Q_ASSERT_INCRIT(310, limit > 0); +QF_CRIT_EXIT(); if (r >= Q_RET_TRAN) { // regular tran. taken? QStateHandler path[MAX_NEST_DEPTH_]; @@ -603,14 +620,20 @@ if (r >= Q_RET_TRAN) { // regular tran. taken? path[2] = s; // tran. source // exit current state to tran. source s... - for (; t != s; t = m_temp.fun) { + limit = MAX_NEST_DEPTH_; // loop hard limit + for (; (t != s) && (limit > 0); t = m_temp.fun) { // exit from t if (QHSM_RESERVED_EVT_(t, Q_EXIT_SIG) == Q_RET_HANDLED) { QS_STATE_EXIT_(t, qsId); // find superstate of t static_cast<void>(QHSM_RESERVED_EVT_(t, Q_EMPTY_SIG)); } + --limit; } + QF_CRIT_ENTRY(); + Q_ASSERT_INCRIT(320, limit > 0); + QF_CRIT_EXIT(); + std::int_fast8_t ip = hsm_tran(path, qsId); // take the tran. #ifdef Q_SPY @@ -658,20 +681,21 @@ if (r >= Q_RET_TRAN) { // regular tran. taken? // find superstate static_cast<void>(QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG)); - while (m_temp.fun != t) { + while ((m_temp.fun != t) && (ip < (MAX_NEST_DEPTH_ - 1))) { ++ip; path[ip] = m_temp.fun; // find superstate static_cast<void>( QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG)); } - m_temp.fun = path[0]; - - // entry path must not overflow QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(410, ip < MAX_NEST_DEPTH_); + // The initial transition source state must be reached. + // Too many state nesting levels or "malformed" HSM. + Q_ASSERT_INCRIT(330, m_temp.fun == t); QF_CRIT_EXIT(); + m_temp.fun = path[0]; + // retrace the entry path in reverse (correct) order... do { // enter path[ip] @@ -866,21 +890,18 @@ else { // and store the entry path along the way std::int_fast8_t iq = 0; // indicate that LCA was found ip = 1; // enter target and its superstate - path[1] = t; // save the superstate of target - t = m_temp.fun; // save source->super + path[1] = t; // save the superstate of target + t = m_temp.fun; // save source->super // find target->super->super... QState r = QHSM_RESERVED_EVT_(path[1], Q_EMPTY_SIG); - while (r == Q_RET_SUPER) { + while ((r == Q_RET_SUPER) + && (ip < (MAX_NEST_DEPTH_ - 1))) + { ++ip; path[ip] = m_temp.fun; // store the entry path if (m_temp.fun == s) { // is it the source? iq = 1; // indicate that the LCA found - - // entry path must not overflow - QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(510, ip < MAX_NEST_DEPTH_); - QF_CRIT_EXIT(); --ip; // do not enter the source r = Q_RET_HANDLED; // terminate the loop } @@ -888,14 +909,14 @@ else { r = QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG); } } + QF_CRIT_ENTRY(); + // Tran. source must be found within the nesting depth + // Too many state nesting levels or "malformed" HSM. + Q_ASSERT_INCRIT(510, r != Q_RET_SUPER); + QF_CRIT_EXIT(); // the LCA not found yet? if (iq == 0) { - // entry path must not overflow - QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(520, ip < MAX_NEST_DEPTH_); - QF_CRIT_EXIT(); - // exit source s if (QHSM_RESERVED_EVT_(s, Q_EXIT_SIG) == Q_RET_HANDLED) @@ -923,6 +944,7 @@ else { // (g) check each source->super->... // for each target->super... r = Q_RET_IGNORED; // keep looping + std::int_fast8_t limit = MAX_NEST_DEPTH_; do { // exit from t if (QHSM_RESERVED_EVT_(t, Q_EXIT_SIG) @@ -946,13 +968,21 @@ else { --iq; } } while (iq >= 0); - } while (r != Q_RET_HANDLED); + + --limit; + } while ((r != Q_RET_HANDLED) && (limit > 0)); + QF_CRIT_ENTRY(); + Q_ASSERT_INCRIT(530, limit > 0); + QF_CRIT_EXIT(); } } } } } } +QF_CRIT_ENTRY(); +Q_ENSURE_INCRIT(590, ip < MAX_NEST_DEPTH_); +QF_CRIT_EXIT(); return ip; @@ -1007,12 +1037,16 @@ QF_CRIT_EXIT(); m_state.obj = m_temp.tatbl->target; // drill down into the state hierarchy with initial transitions... +std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit do { // execute the tran. table r = execTatbl_(m_temp.tatbl, qsId); -} while (r >= Q_RET_TRAN_INIT); + --limit; +} while ((r >= Q_RET_TRAN_INIT) && (limit > 0)); + +QF_CRIT_ENTRY(); +Q_ENSURE_INCRIT(290, limit > 0); -QS_CRIT_ENTRY(); QS_MEM_SYS(); QS_BEGIN_PRE_(QS_QEP_INIT_TRAN, qsId) QS_TIME_PRE_(); // time stamp @@ -1020,7 +1054,8 @@ QS_BEGIN_PRE_(QS_QEP_INIT_TRAN, qsId) QS_FUN_PRE_(m_state.obj->stateHandler); // the new current state QS_END_PRE_() QS_MEM_APP(); -QS_CRIT_EXIT(); + +QF_CRIT_EXIT(); #ifndef Q_UNSAFE m_temp.uint = ~m_state.uint; @@ -1066,6 +1101,7 @@ QF_CRIT_EXIT(); // scan the state hierarchy up to the top state... QState r; +std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit do { r = (*t->stateHandler)(this, e); // call state handler function @@ -1098,11 +1134,15 @@ do { t = t->superstate; // advance to the superstate } -} while (t != nullptr); + --limit; +} while ((t != nullptr) && (limit > 0)); +QF_CRIT_ENTRY(); +Q_ASSERT_INCRIT(310, limit > 0); +QF_CRIT_EXIT(); if (r >= Q_RET_TRAN) { // any kind of tran. taken? #ifdef Q_SPY - QMState const * const ts = t; // transition source for QS tracing + QMState const * const ts = t; // tran. source for QS tracing QF_CRIT_ENTRY(); // the tran. source state must not be nullptr @@ -1110,6 +1150,7 @@ if (r >= Q_RET_TRAN) { // any kind of tran. taken? QF_CRIT_EXIT(); #endif // Q_SPY + limit = MAX_NEST_DEPTH_; // loop hard limit do { // save the tran-action table before it gets clobbered QMTranActTable const * const tatbl = m_temp.tatbl; @@ -1176,10 +1217,12 @@ if (r >= Q_RET_TRAN) { // any kind of tran. taken? } t = s; // set target to the current state + --limit; + } while ((r >= Q_RET_TRAN) && (limit > 0)); - } while (r >= Q_RET_TRAN); + QF_CRIT_ENTRY(); + Q_ASSERT_INCRIT(320, limit > 0); - QS_CRIT_ENTRY(); QS_MEM_SYS(); QS_BEGIN_PRE_(QS_QEP_TRAN, qsId) QS_TIME_PRE_(); // time stamp @@ -1189,7 +1232,8 @@ if (r >= Q_RET_TRAN) { // any kind of tran. taken? QS_FUN_PRE_(s->stateHandler); // the new active state QS_END_PRE_() QS_MEM_APP(); - QS_CRIT_EXIT(); + + QF_CRIT_EXIT(); } #ifdef Q_SPY @@ -1242,12 +1286,12 @@ m_temp.uint = ~m_state.uint; noexcept override - bool inState = false; // assume that this MSM is not in 'state' + bool inState = false; // assume that this SM is not in 'state' QMState const *s = m_state.obj; -std::int_fast8_t limit = 6; // loop hard limit +std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit for (; (s != nullptr) && (limit > 0); --limit) { - if (s->stateHandler == state) { // match found? + if (s->stateHandler == state) { // match found? inState = true; break; } @@ -1258,7 +1302,7 @@ for (; (s != nullptr) && (limit > 0); --limit) { QF_CRIT_STAT QF_CRIT_ENTRY(); -Q_ENSURE_INCRIT(690, limit > 0); +Q_ENSURE_INCRIT(490, limit > 0); QF_CRIT_EXIT(); return inState; @@ -1269,12 +1313,12 @@ return inState; //! @deprecated instead use: QMsm::isIn() - bool inState = false; // assume that this MSM is not in 'state' + bool inState = false; // assume that this SM is not in 'state' QMState const *s = m_state.obj; -std::int_fast8_t limit = 6; // loop hard limit +std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit for (; (s != nullptr) && (limit > 0); --limit) { - if (s == stateObj) { // match found? + if (s == stateObj) { // match found? inState = true; break; } @@ -1285,7 +1329,7 @@ for (; (s != nullptr) && (limit > 0); --limit) { QF_CRIT_STAT QF_CRIT_ENTRY(); -Q_ENSURE_INCRIT(790, limit > 0); +Q_ENSURE_INCRIT(590, limit > 0); QF_CRIT_EXIT(); return inState; @@ -1299,7 +1343,11 @@ return inState; bool isFound = false; // start with the child not found QMState const *s; -for (s = m_state.obj; s != nullptr; s = s->superstate) { +std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit +for (s = m_state.obj; + (s != nullptr) && (limit > 0); + s = s->superstate) +{ if (s == parent) { isFound = true; // child is found break; @@ -1307,9 +1355,19 @@ for (s = m_state.obj; s != nullptr; s = s->superstate) { else { child = s; } + --limit; } +QF_CRIT_STAT +QF_CRIT_ENTRY(); +Q_ASSERT_INCRIT(610, limit > 0); +QF_CRIT_EXIT(); + if (!isFound) { // still not found? - for (s = m_temp.obj; s != nullptr; s = s->superstate) { + limit = MAX_NEST_DEPTH_; // loop hard limit + for (s = m_temp.obj; + (s != nullptr) && (limit > 0); + s = s->superstate) + { if (s == parent) { isFound = true; // child is found break; @@ -1317,12 +1375,12 @@ if (!isFound) { // still not found? else { child = s; } + --limit; } } -QF_CRIT_STAT QF_CRIT_ENTRY(); -Q_ASSERT_INCRIT(890, isFound); +Q_ENSURE_INCRIT(690, isFound && (limit > 0)); QF_CRIT_EXIT(); return child; // return the child @@ -1341,11 +1399,13 @@ QF_CRIT_STAT QF_CRIT_ENTRY(); // precondition: // - the tran-action table pointer must not be NULL -Q_REQUIRE_INCRIT(400, tatbl != nullptr); +Q_REQUIRE_INCRIT(700, tatbl != nullptr); QF_CRIT_EXIT(); QState r = Q_RET_NULL; -for (QActionHandler const *a = &tatbl->act[0]; *a != nullptr; ++a) { +std::int_fast8_t limit = MAX_TRAN_LENGTH_; // loop hard limit +QActionHandler const *a = &tatbl->act[0]; +for (; (*a != nullptr) && (limit > 0); ++a) { r = (*(*a))(this); // call the action through the 'a' pointer #ifdef Q_SPY QS_CRIT_ENTRY(); @@ -1389,7 +1449,11 @@ for (QActionHandler const *a = &tatbl->act[0]; *a != nullptr; ++a) { QS_MEM_APP(); QS_CRIT_EXIT(); #endif // Q_SPY + --limit; } +QF_CRIT_ENTRY(); +Q_ENSURE_INCRIT(790, *a == nullptr); +QF_CRIT_EXIT(); m_state.obj = (r >= Q_RET_TRAN) ? m_temp.tatbl->target @@ -1412,7 +1476,8 @@ QF_CRIT_STAT // exit states from the current state to the tran. source state QMState const *s = cs; -while (s != ts) { +std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit +for (; (s != ts) && (limit > 0); --limit) { // exit action provided in state 's'? if (s->exitAction != nullptr) { // execute the exit action @@ -1433,10 +1498,13 @@ while (s != ts) { if (s == nullptr) { // reached the top of a submachine? s = m_temp.obj; // the superstate from QM_SM_EXIT() QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(510, s != nullptr); + Q_ASSERT_INCRIT(810, s != nullptr); // must be valid QF_CRIT_EXIT(); } -} +} +QF_CRIT_ENTRY(); +Q_ENSURE_INCRIT(890, limit > 0); +QF_CRIT_EXIT(); @@ -1465,11 +1533,8 @@ QS_MEM_APP(); QS_CRIT_EXIT(); std::int_fast8_t i = 0; // tran. entry path index -while (s != ts) { +while ((s != ts) && (i < MAX_ENTRY_DEPTH_)) { if (s->entryAction != nullptr) { - QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(620, i < MAX_ENTRY_DEPTH_); - QF_CRIT_EXIT(); epath[i] = s; ++i; } @@ -1478,6 +1543,9 @@ while (s != ts) { ts = s; // force exit from the for-loop } } +QF_CRIT_ENTRY(); +Q_ASSERT_INCRIT(910, s == ts); +QF_CRIT_EXIT(); // retrace the entry path in reverse (desired) order... while (i > 0) { @@ -4048,7 +4116,15 @@ QF_EPOOL_INIT_(priv_.ePool_[poolNum], poolSto, poolSize, evtSize); noexcept - return QF_EPOOL_EVENT_SIZE_(priv_.ePool_[priv_.maxPool_ - 1U]); + QF_CRIT_STAT +QF_CRIT_ENTRY(); +QF_MEM_SYS(); +std::uint_fast16_t const max_size = + QF_EPOOL_EVENT_SIZE_(priv_.ePool_[priv_.maxPool_ - 1U]); +QF_MEM_APP(); +QF_CRIT_EXIT(); + +return max_size; @@ -4331,9 +4407,8 @@ gc(evtRef); // recycle the referenced event - (static_cast<evtT_ *>( \ - new(QP::QF::newX_(sizeof(evtT_), QP::QF::NO_MARGIN, (sig_))) \ - evtT_(__VA_ARGS__))) + ( static_cast<evtT_ *>( \ + QP::QF::newX_(sizeof(evtT_), QP::QF::NO_MARGIN, (sig_)))->ctor(__VA_ARGS__)) @@ -4356,9 +4431,8 @@ gc(evtRef); // recycle the referenced event - (static_cast<evtT_ *>( \ - new(QP::QF::newX_(sizeof(evtT_), (margin_), (sig_))) \ - evtT_(__VA_ARGS__))) + ( static_cast<evtT_ *>( \ + QP::QF::newX_(sizeof(evtT_), (margin_), (sig_)))->ctor(__VA_ARGS__)) @@ -7120,6 +7194,30 @@ QF_CRIT_EXIT(); } }; + + + = std::uint16_t; + + + + = std::uint32_t; + + + + = std::uint64_t; + + + + = std::uint16_t; + + + + = std::uint32_t; + + + + = std::uint64_t; + = void (*)(); @@ -7140,18 +7238,6 @@ QF_CRIT_EXIT(); = std::uint32_t; - - - = std::uint16_t; - - - - = std::uint32_t; - - - - = std::uint64_t; - @@ -7345,9 +7431,9 @@ rxPriv_.currObj[QS::TE_OBJ] = nullptr; rxPriv_.currObj[QS::AP_OBJ] = nullptr; tran_(WAIT4_SEQ); -l_rx.esc = 0U; -l_rx.seq = 0U; -l_rx.chksum = 0U; +QP::QS::rxPriv_.esc = 0U; +QP::QS::rxPriv_.seq = 0U; +QP::QS::rxPriv_.chksum = 0U; beginRec_(static_cast<std::uint_fast8_t>(QS_OBJ_DICT)); QS_OBJ_PRE_(&rxPriv_); @@ -7383,10 +7469,7 @@ else { - // NOTE: Must be called IN critical section. -// Also requires system-level memory access (QF_MEM_SYS()). - -QSCtr tail = rxPriv_.tail; + QSCtr tail = rxPriv_.tail; while (rxPriv_.head != tail) { // QS-RX buffer NOT empty? std::uint8_t b = rxPriv_.buf[tail]; @@ -7396,34 +7479,34 @@ while (rxPriv_.head != tail) { // QS-RX buffer NOT empty? } rxPriv_.tail = tail; // update the tail to a *valid* index - if (l_rx.esc != 0U) { // escaped byte arrived? - l_rx.esc = 0U; + if (QP::QS::rxPriv_.esc != 0U) { // escaped byte arrived? + QP::QS::rxPriv_.esc = 0U; b ^= QS_ESC_XOR; - l_rx.chksum += b; + QP::QS::rxPriv_.chksum += b; rxParseData_(b); } else if (b == QS_ESC) { - l_rx.esc = 1U; + QP::QS::rxPriv_.esc = 1U; } else if (b == QS_FRAME) { // get ready for the next frame - b = l_rx.state; // save the current state in b - l_rx.esc = 0U; + b = QP::QS::rxPriv_.state; // save the current state in b + QP::QS::rxPriv_.esc = 0U; tran_(WAIT4_SEQ); - if (l_rx.chksum == QS_GOOD_CHKSUM) { - l_rx.chksum = 0U; + if (QP::QS::rxPriv_.chksum == QS_GOOD_CHKSUM) { + QP::QS::rxPriv_.chksum = 0U; rxHandleGoodFrame_(b); } else { // bad checksum - l_rx.chksum = 0U; + QP::QS::rxPriv_.chksum = 0U; rxReportError_(0x41U); rxHandleBadFrame_(b); } } else { - l_rx.chksum += b; + QP::QS::rxPriv_.chksum += b; rxParseData_(b); } } @@ -8422,11 +8505,6 @@ if (QS_GLB_CHECK_(rec_) && QS_LOC_CHECK_(qsId_)) { \ //! @endcond //============================================================================ -#ifdef QEVT_DYN_CTOR -#include <new> // for placement new -#include <cstdarg> // for va_list -#endif // QEVT_DYN_CTOR - $declare ${glob-types} $declare ${QEP} @@ -8702,71 +8780,43 @@ void beginRec_(std::uint_fast8_t const rec) noexcept; void endRec_() noexcept; void u8_raw_(std::uint8_t const d) noexcept; -void u8u8_raw_( - std::uint8_t const d1, - std::uint8_t const d2) noexcept; +void u8u8_raw_(std::uint8_t const d1, std::uint8_t const d2) noexcept; void u16_raw_(std::uint16_t d) noexcept; void u32_raw_(std::uint32_t d) noexcept; void u64_raw_(std::uint64_t d) noexcept; void obj_raw_(void const * const obj) noexcept; void str_raw_(char const * s) noexcept; -void u8_fmt_( - std::uint8_t const format, - std::uint8_t const d) noexcept; -void u16_fmt_( - std::uint8_t format, - std::uint16_t d) noexcept; -void u32_fmt_( - std::uint8_t format, +void u8_fmt_(std::uint8_t const format, std::uint8_t const d) noexcept; +void u16_fmt_(std::uint8_t format, std::uint16_t d) noexcept; +void u32_fmt_(std::uint8_t format, std::uint32_t d) noexcept; -void u64_fmt_( - std::uint8_t format, - std::uint64_t d) noexcept; -void f32_fmt_( - std::uint8_t format, - float32_t f) noexcept; -void f64_fmt_( - std::uint8_t format, - float64_t d) noexcept; +void u64_fmt_(std::uint8_t format, std::uint64_t d) noexcept; +void f32_fmt_(std::uint8_t format, float32_t f) noexcept; +void f64_fmt_(std::uint8_t format, float64_t d) noexcept; void str_fmt_(char const * s) noexcept; -void mem_fmt_( - std::uint8_t const * blk, - std::uint8_t size) noexcept; +void mem_fmt_(std::uint8_t const * blk, std::uint8_t size) noexcept; -void sig_dict_pre_( - QSignal const sig, - void const * const obj, +void sig_dict_pre_(QSignal const sig, void const * const obj, char const * const name) noexcept; -void obj_dict_pre_( - void const * const obj, +void obj_dict_pre_(void const * const obj, char const * const name) noexcept; -void obj_arr_dict_pre_( - void const * const obj, +void obj_arr_dict_pre_(void const * const obj, std::uint_fast16_t const idx, char const * const name) noexcept; -void fun_dict_pre_( - QSpyFunPtr fun, +void fun_dict_pre_(QSpyFunPtr fun, char const * const name) noexcept; -void usr_dict_pre_( - enum_t const rec, - char const * const name) noexcept; -void enum_dict_pre_( - enum_t const value, - std::uint8_t const group, +void usr_dict_pre_(enum_t const rec, char const * const name) noexcept; +void enum_dict_pre_(enum_t const value, std::uint8_t const group, char const * const name) noexcept; -void assertion_pre_( - char const * const module, - int_t const id, +void assertion_pre_(char const * const module, int_t const id, std::uint32_t const delay) noexcept; void crit_entry_pre_() noexcept; void crit_exit_pre_() noexcept; -void isr_entry_pre_( - std::uint8_t const isrnest, +void isr_entry_pre_(std::uint8_t const isrnest, std::uint8_t const prio) noexcept; -void isr_exit_pre_( - std::uint8_t const isrnest, +void isr_exit_pre_(std::uint8_t const isrnest, std::uint8_t const prio) noexcept; void target_info_pre_(std::uint8_t const isReset); @@ -8779,33 +8829,6 @@ void target_info_pre_(std::uint8_t const isReset); $declare ${QS::QS-TX} -//============================================================================ -//! @cond INTERNAL - -namespace QP { -namespace QS { - -struct RxAttr { - void * currObj[8]; - std::uint8_t * buf; - QSCtr end; - QSCtr volatile head; - QSCtr volatile tail; -#ifdef Q_UTEST - bool inTestLoop; -#endif -} ; - -extern RxAttr rxPriv_; - -} // namespace QS -} // namespace QP - -//! @endcond -//============================================================================ - -$declare ${QS::QS-RX} - //============================================================================ #ifdef Q_UTEST @@ -8871,6 +8894,100 @@ $declare ${QS::QUTest-stub::QActiveDummy} #endif // Q_UTEST +//============================================================================ +//! @cond INTERNAL + +namespace QP { +namespace QS { + +//............................................................................ +struct CmdVar { + std::uint32_t param1; + std::uint32_t param2; + std::uint32_t param3; + std::uint8_t idx; + std::uint8_t cmdId; +}; + +struct TickVar { + std::uint_fast8_t rate; +}; + +struct PeekVar { + std::uint16_t offs; + std::uint8_t size; + std::uint8_t num; + std::uint8_t idx; +}; + +struct PokeVar { + std::uint32_t data; + std::uint16_t offs; + std::uint8_t size; + std::uint8_t num; + std::uint8_t idx; + std::uint8_t fill; +}; + +struct FltVar { + std::uint8_t data[16]; + std::uint8_t idx; + std::uint8_t recId; // global/local +}; + +struct ObjVar { + QSObj addr; + std::uint8_t idx; + std::uint8_t kind; // see qs.hpp, enum QSpyObjKind + std::uint8_t recId; +}; + +struct EvtVar { + QP::QEvt *e; + std::uint8_t *p; + QP::QSignal sig; + std::uint16_t len; + std::uint8_t prio; + std::uint8_t idx; +}; + +struct RxAttr { + void * currObj[8]; + std::uint8_t * buf; + QSCtr end; + QSCtr volatile head; + QSCtr volatile tail; + std::uint8_t state; + std::uint8_t esc; + std::uint8_t seq; + std::uint8_t chksum; +#ifdef Q_UTEST + bool inTestLoop; +#endif + union Variant { + CmdVar cmd; + TickVar tick; + PeekVar peek; + PokeVar poke; + FltVar flt; + ObjVar obj; + EvtVar evt; +#ifdef Q_UTEST + QP::QS::TProbe tp; +#endif // Q_UTEST + } var; +} ; + +extern RxAttr rxPriv_; + +} // namespace QS +} // namespace QP + +//! @endcond +//============================================================================ + +$declare ${QS::QS-RX} + #endif // QS_HPP_ @@ -9409,24 +9526,24 @@ static QP::QEvt const l_reservedEvt_[4] { // helper macro to trace state entry #define QS_STATE_ENTRY_(state_, qsId_) \ - QS_CRIT_ENTRY(); \ - QS_MEM_SYS(); \ + QS_CRIT_ENTRY(); \ + QS_MEM_SYS(); \ QS_BEGIN_PRE_(QS_QEP_STATE_ENTRY, (qsId_)) \ - QS_OBJ_PRE_(this); \ - QS_FUN_PRE_(state_); \ - QS_END_PRE_() \ - QS_MEM_APP(); \ + QS_OBJ_PRE_(this); \ + QS_FUN_PRE_(state_); \ + QS_END_PRE_() \ + QS_MEM_APP(); \ QS_CRIT_EXIT() // helper macro to trace state exit #define QS_STATE_EXIT_(state_, qsId_) \ - QS_CRIT_ENTRY(); \ - QS_MEM_SYS(); \ + QS_CRIT_ENTRY(); \ + QS_MEM_SYS(); \ QS_BEGIN_PRE_(QS_QEP_STATE_EXIT, (qsId_)) \ - QS_OBJ_PRE_(this); \ - QS_FUN_PRE_(state_); \ - QS_END_PRE_() \ - QS_MEM_APP(); \ + QS_OBJ_PRE_(this); \ + QS_FUN_PRE_(state_); \ + QS_END_PRE_() \ + QS_MEM_APP(); \ QS_CRIT_EXIT() //! @endcond @@ -9457,6 +9574,15 @@ namespace { Q_DEFINE_THIS_MODULE("qep_msm") +// maximum depth of state nesting in a QMsm (including the top level) +static constexpr std::int_fast8_t MAX_NEST_DEPTH_ {6}; + +// maximum length of transition-action array +static constexpr std::int_fast8_t MAX_TRAN_LENGTH_ {3*MAX_NEST_DEPTH_}; + +// maximum depth of entry levels in a MSM for tran. to history. +static constexpr std::int_fast8_t MAX_ENTRY_DEPTH_ {4}; + // top-state object for QMsm-style state machines QP::QMState const l_msm_top_s = { nullptr, @@ -9466,8 +9592,6 @@ QP::QMState const l_msm_top_s = { nullptr }; -static constexpr std::int_fast8_t MAX_ENTRY_DEPTH_ {4}; - } // unnamed namespace //! @endcond @@ -9570,6 +9694,7 @@ namespace { Q_DEFINE_THIS_MODULE("qf_dyn") } // unnamed namespace +$define ${QEP::QEvt::ctor} $define ${QF::QF-dyn} #endif // (QF_MAX_EPOOL > 0U) mutable events configured @@ -10984,85 +11109,6 @@ namespace { // unnamed local namespace Q_DEFINE_THIS_MODULE("qs_rx") -//............................................................................ -#if (QS_OBJ_PTR_SIZE == 2U) - using QSObj = std::uint16_t; -#elif (QS_OBJ_PTR_SIZE == 4U) - using QSObj = std::uint32_t; -#elif (QS_OBJ_PTR_SIZE == 8U) - using QSObj = std::uint64_t; -#endif - -struct CmdVar { - std::uint32_t param1; - std::uint32_t param2; - std::uint32_t param3; - std::uint8_t idx; - std::uint8_t cmdId; -}; - -struct TickVar { - std::uint_fast8_t rate; -}; - -struct PeekVar { - std::uint16_t offs; - std::uint8_t size; - std::uint8_t num; - std::uint8_t idx; -}; - -struct PokeVar { - std::uint32_t data; - std::uint16_t offs; - std::uint8_t size; - std::uint8_t num; - std::uint8_t idx; - std::uint8_t fill; -}; - -struct FltVar { - std::uint8_t data[16]; - std::uint8_t idx; - std::uint8_t recId; // global/local -}; - -struct ObjVar { - QSObj addr; - std::uint8_t idx; - std::uint8_t kind; // see qs.hpp, enum QSpyObjKind - std::uint8_t recId; -}; - -struct EvtVar { - QP::QEvt *e; - std::uint8_t *p; - QP::QSignal sig; - std::uint16_t len; - std::uint8_t prio; - std::uint8_t idx; -}; - -// extended-state variables for the current QS-RX state -static struct ExtState { - union Variant { - CmdVar cmd; - TickVar tick; - PeekVar peek; - PokeVar poke; - FltVar flt; - ObjVar obj; - EvtVar evt; -#ifdef Q_UTEST - QP::QS::TProbe tp; -#endif // Q_UTEST - } var; - std::uint8_t state; - std::uint8_t esc; - std::uint8_t seq; - std::uint8_t chksum; -} l_rx; - enum RxStateEnum : std::uint8_t { ERROR_STATE, WAIT4_SEQ, @@ -11124,16 +11170,18 @@ static void rxPoke_() noexcept; // Internal QS-RX function to take a tran. in the QS-RX FSM static inline void tran_(RxStateEnum const target) noexcept { - l_rx.state = static_cast<std::uint8_t>(target); + QP::QS::rxPriv_.state = static_cast<std::uint8_t>(target); } } // unnamed namespace +#ifndef QF_MEM_ISOLATE namespace QP { namespace QS { RxAttr rxPriv_; } // namespace QS } // namespace QP +#endif // QF_MEM_ISOLATE //! @endcond //============================================================================ @@ -11146,12 +11194,12 @@ namespace { // unnamed local namespace //............................................................................ static void rxParseData_(std::uint8_t const b) noexcept { - switch (l_rx.state) { + switch (QP::QS::rxPriv_.state) { case WAIT4_SEQ: { - ++l_rx.seq; - if (l_rx.seq != b) { // not the expected sequence? + ++QP::QS::rxPriv_.seq; + if (QP::QS::rxPriv_.seq != b) { // not the expected sequence? rxReportError_(0x42U); - l_rx.seq = b; // update the sequence + QP::QS::rxPriv_.seq = b; // update the sequence } tran_(WAIT4_REC); break; @@ -11172,8 +11220,8 @@ static void rxParseData_(std::uint8_t const b) noexcept { break; case QP::QS_RX_PEEK: if (QP::QS::rxPriv_.currObj[QP::QS::AP_OBJ] != nullptr) { - l_rx.var.peek.offs = 0U; - l_rx.var.peek.idx = 0U; + QP::QS::rxPriv_.var.peek.offs = 0U; + QP::QS::rxPriv_.var.peek.idx = 0U; tran_(WAIT4_PEEK_OFFS); } else { @@ -11184,18 +11232,17 @@ static void rxParseData_(std::uint8_t const b) noexcept { break; case QP::QS_RX_POKE: case QP::QS_RX_FILL: - l_rx.var.poke.fill = + QP::QS::rxPriv_.var.poke.fill = (b == static_cast<std::uint8_t>(QP::QS_RX_FILL)) - ? 1U - : 0U; + ? 1U : 0U; if (QP::QS::rxPriv_.currObj[QP::QS::AP_OBJ] != nullptr) { - l_rx.var.poke.offs = 0U; - l_rx.var.poke.idx = 0U; + QP::QS::rxPriv_.var.poke.offs = 0U; + QP::QS::rxPriv_.var.poke.idx = 0U; tran_(WAIT4_POKE_OFFS); } else { rxReportError_( - (l_rx.var.poke.fill != 0U) + (QP::QS::rxPriv_.var.poke.fill != 0U) ? static_cast<std::uint8_t>(QP::QS_RX_FILL) : static_cast<std::uint8_t>(QP::QS_RX_POKE)); tran_(ERROR_STATE); @@ -11203,16 +11250,16 @@ static void rxParseData_(std::uint8_t const b) noexcept { break; case QP::QS_RX_GLB_FILTER: // intentionally fall-through case QP::QS_RX_LOC_FILTER: - l_rx.var.flt.recId = b; + QP::QS::rxPriv_.var.flt.recId = b; tran_(WAIT4_FILTER_LEN); break; case QP::QS_RX_AO_FILTER: // intentionally fall-through case QP::QS_RX_CURR_OBJ: - l_rx.var.obj.recId = b; + QP::QS::rxPriv_.var.obj.recId = b; tran_(WAIT4_OBJ_KIND); break; case QP::QS_RX_QUERY_CURR: - l_rx.var.obj.recId = + QP::QS::rxPriv_.var.obj.recId = static_cast<std::uint8_t>(QP::QS_RX_QUERY_CURR); tran_(WAIT4_QUERY_KIND); break; @@ -11236,8 +11283,8 @@ static void rxParseData_(std::uint8_t const b) noexcept { (sizeof(QP::QS::tstPriv_.tpBuf) / sizeof(QP::QS::tstPriv_.tpBuf[0])))) { - l_rx.var.tp.data = 0U; - l_rx.var.tp.idx = 0U; + QP::QS::rxPriv_.var.tp.data = 0U; + QP::QS::rxPriv_.var.tp.idx = 0U; tran_(WAIT4_TEST_PROBE_DATA); } else { // the # Test-Probes exceeded @@ -11260,40 +11307,40 @@ static void rxParseData_(std::uint8_t const b) noexcept { break; } case WAIT4_CMD_ID: { - l_rx.var.cmd.cmdId = b; - l_rx.var.cmd.idx = 0U; - l_rx.var.cmd.param1 = 0U; - l_rx.var.cmd.param2 = 0U; - l_rx.var.cmd.param3 = 0U; + QP::QS::rxPriv_.var.cmd.cmdId = b; + QP::QS::rxPriv_.var.cmd.idx = 0U; + QP::QS::rxPriv_.var.cmd.param1 = 0U; + QP::QS::rxPriv_.var.cmd.param2 = 0U; + QP::QS::rxPriv_.var.cmd.param3 = 0U; tran_(WAIT4_CMD_PARAM1); break; } case WAIT4_CMD_PARAM1: { - l_rx.var.cmd.param1 |= - (static_cast<std::uint32_t>(b) << l_rx.var.cmd.idx); - l_rx.var.cmd.idx += 8U; - if (l_rx.var.cmd.idx == (8U*4U)) { - l_rx.var.cmd.idx = 0U; + QP::QS::rxPriv_.var.cmd.param1 |= + (static_cast<std::uint32_t>(b) << QP::QS::rxPriv_.var.cmd.idx); + QP::QS::rxPriv_.var.cmd.idx += 8U; + if (QP::QS::rxPriv_.var.cmd.idx == (8U * 4U)) { + QP::QS::rxPriv_.var.cmd.idx = 0U; tran_(WAIT4_CMD_PARAM2); } break; } case WAIT4_CMD_PARAM2: { - l_rx.var.cmd.param2 |= - static_cast<std::uint32_t>(b) << l_rx.var.cmd.idx; - l_rx.var.cmd.idx += 8U; - if (l_rx.var.cmd.idx == (8U*4U)) { - l_rx.var.cmd.idx = 0U; + QP::QS::rxPriv_.var.cmd.param2 |= + static_cast<std::uint32_t>(b) << QP::QS::rxPriv_.var.cmd.idx; + QP::QS::rxPriv_.var.cmd.idx += 8U; + if (QP::QS::rxPriv_.var.cmd.idx == (8U * 4U)) { + QP::QS::rxPriv_.var.cmd.idx = 0U; tran_(WAIT4_CMD_PARAM3); } break; } case WAIT4_CMD_PARAM3: { - l_rx.var.cmd.param3 |= - static_cast<std::uint32_t>(b) << l_rx.var.cmd.idx; - l_rx.var.cmd.idx += 8U; - if (l_rx.var.cmd.idx == (8U*4U)) { - l_rx.var.cmd.idx = 0U; + QP::QS::rxPriv_.var.cmd.param3 |= + static_cast<std::uint32_t>(b) << QP::QS::rxPriv_.var.cmd.idx; + QP::QS::rxPriv_.var.cmd.idx += 8U; + if (QP::QS::rxPriv_.var.cmd.idx == (8U * 4U)) { + QP::QS::rxPriv_.var.cmd.idx = 0U; tran_(WAIT4_CMD_FRAME); } break; @@ -11307,7 +11354,7 @@ static void rxParseData_(std::uint8_t const b) noexcept { break; } case WAIT4_TICK_RATE: { - l_rx.var.tick.rate = static_cast<std::uint_fast8_t>(b); + QP::QS::rxPriv_.var.tick.rate = static_cast<std::uint_fast8_t>(b); tran_(WAIT4_TICK_FRAME); break; } @@ -11316,12 +11363,12 @@ static void rxParseData_(std::uint8_t const b) noexcept { break; } case WAIT4_PEEK_OFFS: { - if (l_rx.var.peek.idx == 0U) { - l_rx.var.peek.offs = static_cast<std::uint16_t>(b); - l_rx.var.peek.idx += 8U; + if (QP::QS::rxPriv_.var.peek.idx == 0U) { + QP::QS::rxPriv_.var.peek.offs = static_cast<std::uint16_t>(b); + QP::QS::rxPriv_.var.peek.idx += 8U; } else { - l_rx.var.peek.offs |= static_cast<std::uint16_t>( + QP::QS::rxPriv_.var.peek.offs |= static_cast<std::uint16_t>( static_cast<std::uint16_t>(b) << 8U); tran_(WAIT4_PEEK_SIZE); } @@ -11329,7 +11376,7 @@ static void rxParseData_(std::uint8_t const b) noexcept { } case WAIT4_PEEK_SIZE: { if ((b == 1U) || (b == 2U) || (b == 4U)) { - l_rx.var.peek.size = b; + QP::QS::rxPriv_.var.peek.size = b; tran_(WAIT4_PEEK_NUM); } else { @@ -11339,7 +11386,7 @@ static void rxParseData_(std::uint8_t const b) noexcept { break; } case WAIT4_PEEK_NUM: { - l_rx.var.peek.num = b; + QP::QS::rxPriv_.var.peek.num = b; tran_(WAIT4_PEEK_FRAME); break; } @@ -11348,12 +11395,12 @@ static void rxParseData_(std::uint8_t const b) noexcept { break; } case WAIT4_POKE_OFFS: { - if (l_rx.var.poke.idx == 0U) { - l_rx.var.poke.offs = static_cast<std::uint16_t>(b); - l_rx.var.poke.idx = 1U; + if (QP::QS::rxPriv_.var.poke.idx == 0U) { + QP::QS::rxPriv_.var.poke.offs = static_cast<std::uint16_t>(b); + QP::QS::rxPriv_.var.poke.idx = 1U; } else { - l_rx.var.poke.offs |= static_cast<std::uint16_t>( + QP::QS::rxPriv_.var.poke.offs |= static_cast<std::uint16_t>( static_cast<std::uint16_t>(b) << 8U); tran_(WAIT4_POKE_SIZE); } @@ -11361,11 +11408,11 @@ static void rxParseData_(std::uint8_t const b) noexcept { } case WAIT4_POKE_SIZE: { if ((b == 1U) || (b == 2U) || (b == 4U)) { - l_rx.var.poke.size = b; + QP::QS::rxPriv_.var.poke.size = b; tran_(WAIT4_POKE_NUM); } else { - rxReportError_((l_rx.var.poke.fill != 0U) + rxReportError_((QP::QS::rxPriv_.var.poke.fill != 0U) ? static_cast<std::uint8_t>(QP::QS_RX_FILL) : static_cast<std::uint8_t>(QP::QS_RX_POKE)); tran_(ERROR_STATE); @@ -11374,15 +11421,15 @@ static void rxParseData_(std::uint8_t const b) noexcept { } case WAIT4_POKE_NUM: { if (b > 0U) { - l_rx.var.poke.num = b; - l_rx.var.poke.data = 0U; - l_rx.var.poke.idx = 0U; - tran_((l_rx.var.poke.fill != 0U) + QP::QS::rxPriv_.var.poke.num = b; + QP::QS::rxPriv_.var.poke.data = 0U; + QP::QS::rxPriv_.var.poke.idx = 0U; + tran_((QP::QS::rxPriv_.var.poke.fill != 0U) ? WAIT4_FILL_DATA : WAIT4_POKE_DATA); } else { - rxReportError_((l_rx.var.poke.fill != 0U) + rxReportError_((QP::QS::rxPriv_.var.poke.fill != 0U) ? static_cast<std::uint8_t>(QP::QS_RX_FILL) : static_cast<std::uint8_t>(QP::QS_RX_POKE)); tran_(ERROR_STATE); @@ -11390,22 +11437,22 @@ static void rxParseData_(std::uint8_t const b) noexcept { break; } case WAIT4_FILL_DATA: { - l_rx.var.poke.data |= - static_cast<std::uint32_t>(b) << l_rx.var.poke.idx; - l_rx.var.poke.idx += 8U; - if ((l_rx.var.poke.idx >> 3U) == l_rx.var.poke.size) { + QP::QS::rxPriv_.var.poke.data |= + static_cast<std::uint32_t>(b) << QP::QS::rxPriv_.var.poke.idx; + QP::QS::rxPriv_.var.poke.idx += 8U; + if ((QP::QS::rxPriv_.var.poke.idx >> 3U) == QP::QS::rxPriv_.var.poke.size) { tran_(WAIT4_FILL_FRAME); } break; } case WAIT4_POKE_DATA: { - l_rx.var.poke.data |= - static_cast<std::uint32_t>(b) << l_rx.var.poke.idx; - l_rx.var.poke.idx += 8U; - if ((l_rx.var.poke.idx >> 3U) == l_rx.var.poke.size) { + QP::QS::rxPriv_.var.poke.data |= + static_cast<std::uint32_t>(b) << QP::QS::rxPriv_.var.poke.idx; + QP::QS::rxPriv_.var.poke.idx += 8U; + if ((QP::QS::rxPriv_.var.poke.idx >> 3U) == QP::QS::rxPriv_.var.poke.size) { rxPoke_(); - --l_rx.var.poke.num; - if (l_rx.var.poke.num == 0U) { + --QP::QS::rxPriv_.var.poke.num; + if (QP::QS::rxPriv_.var.poke.num == 0U) { tran_(WAIT4_POKE_FRAME); } } @@ -11420,20 +11467,20 @@ static void rxParseData_(std::uint8_t const b) noexcept { break; } case WAIT4_FILTER_LEN: { - if (b == static_cast<std::uint8_t>(sizeof(l_rx.var.flt.data))) { - l_rx.var.flt.idx = 0U; + if (b == static_cast<std::uint8_t>(sizeof(QP::QS::rxPriv_.var.flt.data))) { + QP::QS::rxPriv_.var.flt.idx = 0U; tran_(WAIT4_FILTER_DATA); } else { - rxReportError_(l_rx.var.flt.recId); + rxReportError_(QP::QS::rxPriv_.var.flt.recId); tran_(ERROR_STATE); } break; } case WAIT4_FILTER_DATA: { - l_rx.var.flt.data[l_rx.var.flt.idx] = b; - ++l_rx.var.flt.idx; - if (l_rx.var.flt.idx == sizeof(l_rx.var.flt.data)) { + QP::QS::rxPriv_.var.flt.data[QP::QS::rxPriv_.var.flt.idx] = b; + ++QP::QS::rxPriv_.var.flt.idx; + if (QP::QS::rxPriv_.var.flt.idx == sizeof(QP::QS::rxPriv_.var.flt.data)) { tran_(WAIT4_FILTER_FRAME); } break; @@ -11444,22 +11491,22 @@ static void rxParseData_(std::uint8_t const b) noexcept { } case WAIT4_OBJ_KIND: { if (b <= static_cast<std::uint8_t>(QP::QS::SM_AO_OBJ)) { - l_rx.var.obj.kind = b; - l_rx.var.obj.addr = 0U; - l_rx.var.obj.idx = 0U; + QP::QS::rxPriv_.var.obj.kind = b; + QP::QS::rxPriv_.var.obj.addr = 0U; + QP::QS::rxPriv_.var.obj.idx = 0U; tran_(WAIT4_OBJ_ADDR); } else { - rxReportError_(l_rx.var.obj.recId); + rxReportError_(QP::QS::rxPriv_.var.obj.recId); tran_(ERROR_STATE); } break; } case WAIT4_OBJ_ADDR: { - l_rx.var.obj.addr |= - static_cast<QSObj>(b) << l_rx.var.obj.idx; - l_rx.var.obj.idx += 8U; - if (l_rx.var.obj.idx + QP::QS::rxPriv_.var.obj.addr |= + static_cast<QP::QSObj>(b) << QP::QS::rxPriv_.var.obj.idx; + QP::QS::rxPriv_.var.obj.idx += 8U; + if (QP::QS::rxPriv_.var.obj.idx == (8U * static_cast<unsigned>(QS_OBJ_PTR_SIZE))) { tran_(WAIT4_OBJ_FRAME); @@ -11472,11 +11519,11 @@ static void rxParseData_(std::uint8_t const b) noexcept { } case WAIT4_QUERY_KIND: { if (b < static_cast<std::uint8_t>(QP::QS::MAX_OBJ)) { - l_rx.var.obj.kind = b; + QP::QS::rxPriv_.var.obj.kind = b; tran_(WAIT4_QUERY_FRAME); } else { - rxReportError_(l_rx.var.obj.recId); + rxReportError_(QP::QS::rxPriv_.var.obj.recId); tran_(ERROR_STATE); } break; @@ -11486,48 +11533,47 @@ static void rxParseData_(std::uint8_t const b) noexcept { break; } case WAIT4_EVT_PRIO: { - l_rx.var.evt.prio = b; - l_rx.var.evt.sig = 0U; - l_rx.var.evt.idx = 0U; + QP::QS::rxPriv_.var.evt.prio = b; + QP::QS::rxPriv_.var.evt.sig = 0U; + QP::QS::rxPriv_.var.evt.idx = 0U; tran_(WAIT4_EVT_SIG); break; } case WAIT4_EVT_SIG: { - l_rx.var.evt.sig |= static_cast<QP::QSignal>( - static_cast<std::uint32_t>(b) << l_rx.var.evt.idx); - l_rx.var.evt.idx += 8U; - if (l_rx.var.evt.idx + QP::QS::rxPriv_.var.evt.sig |= static_cast<QP::QSignal>( + static_cast<std::uint32_t>(b) << QP::QS::rxPriv_.var.evt.idx); + QP::QS::rxPriv_.var.evt.idx += 8U; + if (QP::QS::rxPriv_.var.evt.idx == (8U *static_cast<unsigned>(Q_SIGNAL_SIZE))) { - l_rx.var.evt.len = 0U; - l_rx.var.evt.idx = 0U; + QP::QS::rxPriv_.var.evt.len = 0U; + QP::QS::rxPriv_.var.evt.idx = 0U; tran_(WAIT4_EVT_LEN); } break; } case WAIT4_EVT_LEN: { - l_rx.var.evt.len |= static_cast<std::uint16_t>( - static_cast<unsigned>(b) << l_rx.var.evt.idx); - l_rx.var.evt.idx += 8U; - if (l_rx.var.evt.idx == (8U * 2U)) { - if ((l_rx.var.evt.len + sizeof(QP::QEvt)) - <= static_cast<std::uint16_t>( - QP::QF::poolGetMaxBlockSize())) + QP::QS::rxPriv_.var.evt.len |= static_cast<std::uint16_t>( + static_cast<unsigned>(b) << QP::QS::rxPriv_.var.evt.idx); + QP::QS::rxPriv_.var.evt.idx += 8U; + if (QP::QS::rxPriv_.var.evt.idx == (8U * 2U)) { + if ((QP::QS::rxPriv_.var.evt.len + sizeof(QP::QEvt)) + <= QP::QF::poolGetMaxBlockSize()) { // report Ack before generating any other QS records rxReportAck_(QP::QS_RX_EVENT); - l_rx.var.evt.e = QP::QF::newX_( - (static_cast<std::uint_fast16_t>(l_rx.var.evt.len) + QP::QS::rxPriv_.var.evt.e = QP::QF::newX_( + (static_cast<std::uint_fast16_t>(QP::QS::rxPriv_.var.evt.len) + sizeof(QP::QEvt)), 0U, // margin - static_cast<enum_t>(l_rx.var.evt.sig)); + static_cast<enum_t>(QP::QS::rxPriv_.var.evt.sig)); // event allocated? - if (l_rx.var.evt.e != nullptr) { - l_rx.var.evt.p = - reinterpret_cast<std::uint8_t *>(l_rx.var.evt.e); - l_rx.var.evt.p = &l_rx.var.evt.p[sizeof(QP::QEvt)]; - if (l_rx.var.evt.len > 0U) { + if (QP::QS::rxPriv_.var.evt.e != nullptr) { + QP::QS::rxPriv_.var.evt.p = + reinterpret_cast<std::uint8_t *>(QP::QS::rxPriv_.var.evt.e); + QP::QS::rxPriv_.var.evt.p = &QP::QS::rxPriv_.var.evt.p[sizeof(QP::QEvt)]; + if (QP::QS::rxPriv_.var.evt.len > 0U) { tran_(WAIT4_EVT_PAR); } else { @@ -11549,10 +11595,10 @@ static void rxParseData_(std::uint8_t const b) noexcept { break; } case WAIT4_EVT_PAR: { // event parameters - *l_rx.var.evt.p = b; - ++l_rx.var.evt.p; - --l_rx.var.evt.len; - if (l_rx.var.evt.len == 0U) { + *QP::QS::rxPriv_.var.evt.p = b; + ++QP::QS::rxPriv_.var.evt.p; + --QP::QS::rxPriv_.var.evt.len; + if (QP::QS::rxPriv_.var.evt.len == 0U) { tran_(WAIT4_EVT_FRAME); } break; @@ -11576,21 +11622,21 @@ static void rxParseData_(std::uint8_t const b) noexcept { break; } case WAIT4_TEST_PROBE_DATA: { - l_rx.var.tp.data |= - (static_cast<QP::QSFun>(b) << l_rx.var.tp.idx); - l_rx.var.tp.idx += 8U; - if (l_rx.var.tp.idx == (8U * sizeof(std::uint32_t))) { - l_rx.var.tp.addr = 0U; - l_rx.var.tp.idx = 0U; + QP::QS::rxPriv_.var.tp.data |= + (static_cast<QP::QSFun>(b) << QP::QS::rxPriv_.var.tp.idx); + QP::QS::rxPriv_.var.tp.idx += 8U; + if (QP::QS::rxPriv_.var.tp.idx == (8U * sizeof(std::uint32_t))) { + QP::QS::rxPriv_.var.tp.addr = 0U; + QP::QS::rxPriv_.var.tp.idx = 0U; tran_(WAIT4_TEST_PROBE_ADDR); } break; } case WAIT4_TEST_PROBE_ADDR: { - l_rx.var.tp.addr |= - (static_cast<std::uint32_t>(b) << l_rx.var.tp.idx); - l_rx.var.tp.idx += 8U; - if (l_rx.var.tp.idx + QP::QS::rxPriv_.var.tp.addr |= + (static_cast<std::uint32_t>(b) << QP::QS::rxPriv_.var.tp.idx); + QP::QS::rxPriv_.var.tp.idx += 8U; + if (QP::QS::rxPriv_.var.tp.idx == (8U * static_cast<unsigned>(QS_FUN_PTR_SIZE))) { tran_(WAIT4_TEST_PROBE_FRAME); @@ -11619,11 +11665,16 @@ static void rxParseData_(std::uint8_t const b) noexcept { void rxHandleGoodFrame_(std::uint8_t const state) { std::uint8_t i; std::uint8_t *ptr; + QS_CRIT_STAT switch (state) { case WAIT4_INFO_FRAME: { // no need to report Ack or Done + QS_CRIT_ENTRY(); + QS_MEM_SYS(); QP::QS::target_info_pre_(0U); // send only Target info + QS_MEM_APP(); + QS_CRIT_EXIT(); break; } case WAIT4_RESET_FRAME: { @@ -11636,8 +11687,8 @@ void rxHandleGoodFrame_(std::uint8_t const state) { case WAIT4_CMD_PARAM3: // intentionally fall-through case WAIT4_CMD_FRAME: { rxReportAck_(QP::QS_RX_COMMAND); - QP::QS::onCommand(l_rx.var.cmd.cmdId, l_rx.var.cmd.param1, - l_rx.var.cmd.param2, l_rx.var.cmd.param3); + QP::QS::onCommand(QP::QS::rxPriv_.var.cmd.cmdId, QP::QS::rxPriv_.var.cmd.param1, + QP::QS::rxPriv_.var.cmd.param2, QP::QS::rxPriv_.var.cmd.param3); #ifdef Q_UTEST #if Q_UTEST != 0 QP::QS::processTestEvts_(); // process all events produced @@ -11650,14 +11701,14 @@ void rxHandleGoodFrame_(std::uint8_t const state) { rxReportAck_(QP::QS_RX_TICK); #ifdef Q_UTEST QP::QTimeEvt::tick1_( - static_cast<std::uint_fast8_t>(l_rx.var.tick.rate), + static_cast<std::uint_fast8_t>(QP::QS::rxPriv_.var.tick.rate), &QP::QS::rxPriv_); #if Q_UTEST != 0 QP::QS::processTestEvts_(); // process all events produced #endif // Q_UTEST != 0 #else QP::QTimeEvt::tick( - static_cast<std::uint_fast8_t>(l_rx.var.tick.rate), + static_cast<std::uint_fast8_t>(QP::QS::rxPriv_.var.tick.rate), &QP::QS::rxPriv_); #endif // Q_UTEST rxReportDone_(QP::QS_RX_TICK); @@ -11665,17 +11716,19 @@ void rxHandleGoodFrame_(std::uint8_t const state) { } case WAIT4_PEEK_FRAME: { // no need to report Ack or Done + QS_CRIT_ENTRY(); + QS_MEM_SYS(); QP::QS::beginRec_(static_cast<std::uint_fast8_t>( QP::QS_PEEK_DATA)); ptr = static_cast<std::uint8_t*>( QP::QS::rxPriv_.currObj[QP::QS::AP_OBJ]); - ptr = &ptr[l_rx.var.peek.offs]; + ptr = &ptr[QP::QS::rxPriv_.var.peek.offs]; QS_TIME_PRE_(); // timestamp - QS_U16_PRE_(l_rx.var.peek.offs); // data offset - QS_U8_PRE_(l_rx.var.peek.size); // data size - QS_U8_PRE_(l_rx.var.peek.num); // number of data items - for (i = 0U; i < l_rx.var.peek.num; ++i) { - switch (l_rx.var.peek.size) { + QS_U16_PRE_(QP::QS::rxPriv_.var.peek.offs); // data offset + QS_U8_PRE_(QP::QS::rxPriv_.var.peek.size); // data size + QS_U8_PRE_(QP::QS::rxPriv_.var.peek.num); // number of data items + for (i = 0U; i < QP::QS::rxPriv_.var.peek.num; ++i) { + switch (QP::QS::rxPriv_.var.peek.size) { case 1: QS_U8_PRE_(ptr[i]); break; @@ -11693,6 +11746,8 @@ void rxHandleGoodFrame_(std::uint8_t const state) { } } QP::QS::endRec_(); + QS_MEM_APP(); + QS_CRIT_EXIT(); QS_REC_DONE(); // user callback (if defined) break; @@ -11711,20 +11766,20 @@ void rxHandleGoodFrame_(std::uint8_t const state) { rxReportAck_(QP::QS_RX_FILL); ptr = static_cast<std::uint8_t *>( QP::QS::rxPriv_.currObj[QP::QS::AP_OBJ]); - ptr = &ptr[l_rx.var.poke.offs]; - for (i = 0U; i < l_rx.var.poke.num; ++i) { - switch (l_rx.var.poke.size) { + ptr = &ptr[QP::QS::rxPriv_.var.poke.offs]; + for (i = 0U; i < QP::QS::rxPriv_.var.poke.num; ++i) { + switch (QP::QS::rxPriv_.var.poke.size) { case 1: ptr[i] = - static_cast<std::uint8_t>(l_rx.var.poke.data); + static_cast<std::uint8_t>(QP::QS::rxPriv_.var.poke.data); break; case 2: reinterpret_cast<std::uint16_t *>(ptr)[i] = - static_cast<std::uint16_t>(l_rx.var.poke.data); + static_cast<std::uint16_t>(QP::QS::rxPriv_.var.poke.data); break; case 4: reinterpret_cast<std::uint32_t *>(ptr)[i] = - l_rx.var.poke.data; + QP::QS::rxPriv_.var.poke.data; break; default: // intentionally empty @@ -11735,17 +11790,17 @@ void rxHandleGoodFrame_(std::uint8_t const state) { } case WAIT4_FILTER_FRAME: { rxReportAck_(static_cast<enum QP::QSpyRxRecords>( - l_rx.var.flt.recId)); + QP::QS::rxPriv_.var.flt.recId)); // apply the received filters - if (l_rx.var.flt.recId + if (QP::QS::rxPriv_.var.flt.recId == static_cast<std::uint8_t>(QP::QS_RX_GLB_FILTER)) { for (i = 0U; i < static_cast<std::uint8_t>(sizeof(QP::QS::filt_.glb)); ++i) { - QP::QS::filt_.glb[i] = l_rx.var.flt.data[i]; + QP::QS::filt_.glb[i] = QP::QS::rxPriv_.var.flt.data[i]; } // leave the "not maskable" filters enabled, // see qs.hpp, Miscellaneous QS records (not maskable) @@ -11756,39 +11811,39 @@ void rxHandleGoodFrame_(std::uint8_t const state) { // never enable the last 3 records (0x7D, 0x7E, 0x7F) QP::QS::filt_.glb[15] &= 0x1FU; } - else if (l_rx.var.flt.recId + else if (QP::QS::rxPriv_.var.flt.recId == static_cast<std::uint8_t>(QP::QS_RX_LOC_FILTER)) { for (i = 0U; i < Q_DIM(QP::QS::filt_.loc); ++i) { - QP::QS::filt_.loc[i] = l_rx.var.flt.data[i]; + QP::QS::filt_.loc[i] = QP::QS::rxPriv_.var.flt.data[i]; } // leave QS_ID == 0 always on QP::QS::filt_.loc[0] |= 0x01U; } else { - rxReportError_(l_rx.var.flt.recId); + rxReportError_(QP::QS::rxPriv_.var.flt.recId); } // no need to report Done break; } case WAIT4_OBJ_FRAME: { - i = l_rx.var.obj.kind; + i = QP::QS::rxPriv_.var.obj.kind; if (i < static_cast<std::uint8_t>(QP::QS::MAX_OBJ)) { - if (l_rx.var.obj.recId + if (QP::QS::rxPriv_.var.obj.recId == static_cast<std::uint8_t>(QP::QS_RX_CURR_OBJ)) { QP::QS::rxPriv_.currObj[i] = - reinterpret_cast<void *>(l_rx.var.obj.addr); + reinterpret_cast<void *>(QP::QS::rxPriv_.var.obj.addr); rxReportAck_(QP::QS_RX_CURR_OBJ); } - else if (l_rx.var.obj.recId + else if (QP::QS::rxPriv_.var.obj.recId == static_cast<std::uint8_t>(QP::QS_RX_AO_FILTER)) { - if (l_rx.var.obj.addr != 0U) { + if (QP::QS::rxPriv_.var.obj.addr != 0U) { std::int_fast16_t const filter = static_cast<std::int_fast16_t>( reinterpret_cast<QP::QActive *>( - l_rx.var.obj.addr)->getPrio()); + QP::QS::rxPriv_.var.obj.addr)->getPrio()); QP::QS::locFilter_((i == 0) ? filter :-filter); @@ -11800,92 +11855,92 @@ void rxHandleGoodFrame_(std::uint8_t const state) { } } else { - rxReportError_(l_rx.var.obj.recId); + rxReportError_(QP::QS::rxPriv_.var.obj.recId); } } // both SM and AO else if (i == static_cast<std::uint8_t>(QP::QS::SM_AO_OBJ)) { - if (l_rx.var.obj.recId + if (QP::QS::rxPriv_.var.obj.recId == static_cast<std::uint8_t>(QP::QS_RX_CURR_OBJ)) { QP::QS::rxPriv_.currObj[QP::QS::SM_OBJ] - = reinterpret_cast<void *>(l_rx.var.obj.addr); + = reinterpret_cast<void *>(QP::QS::rxPriv_.var.obj.addr); QP::QS::rxPriv_.currObj[QP::QS::AO_OBJ] - = reinterpret_cast<void *>(l_rx.var.obj.addr); + = reinterpret_cast<void *>(QP::QS::rxPriv_.var.obj.addr); } rxReportAck_( - static_cast<enum QP::QSpyRxRecords>(l_rx.var.obj.recId)); + static_cast<enum QP::QSpyRxRecords>(QP::QS::rxPriv_.var.obj.recId)); } else { - rxReportError_(l_rx.var.obj.recId); + rxReportError_(QP::QS::rxPriv_.var.obj.recId); } break; } case WAIT4_QUERY_FRAME: { - queryCurrObj_(l_rx.var.obj.kind); + queryCurrObj_(QP::QS::rxPriv_.var.obj.kind); break; } case WAIT4_EVT_FRAME: { // NOTE: Ack was already reported in the WAIT4_EVT_LEN state #ifdef Q_UTEST - QP::QS::onTestEvt(l_rx.var.evt.e); // "massage" the event + QP::QS::onTestEvt(QP::QS::rxPriv_.var.evt.e); // "massage" the event #endif // Q_UTEST // use 'i' as status, 0 == success,no-recycle i = 0U; - if (l_rx.var.evt.prio == 0U) { // publish - QP::QActive::publish_(l_rx.var.evt.e, &QP::QS::rxPriv_, 0U); + if (QP::QS::rxPriv_.var.evt.prio == 0U) { // publish + QP::QActive::publish_(QP::QS::rxPriv_.var.evt.e, &QP::QS::rxPriv_, 0U); } - else if (l_rx.var.evt.prio < QF_MAX_ACTIVE) { - if (!QP::QActive::registry_[l_rx.var.evt.prio]->POST_X( - l_rx.var.evt.e, + else if (QP::QS::rxPriv_.var.evt.prio < QF_MAX_ACTIVE) { + if (!QP::QActive::registry_[QP::QS::rxPriv_.var.evt.prio]->POST_X( + QP::QS::rxPriv_.var.evt.e, 0U, // margin &QP::QS::rxPriv_)) { // failed QACTIVE_POST() recycles the event - i = 0x80U; // failure, no recycle + i = 0x80U; // failure status, no recycle } } - else if (l_rx.var.evt.prio == 255U) { + else if (QP::QS::rxPriv_.var.evt.prio == 255U) { // dispatch to the current SM object if (QP::QS::rxPriv_.currObj[QP::QS::SM_OBJ] != nullptr) { // increment the ref-ctr to simulate the situation // when the event is just retrieved from a queue. // This is expected for the following QF::gc() call. - QP::QEvt_refCtr_inc_(l_rx.var.evt.e); + QP::QEvt_refCtr_inc_(QP::QS::rxPriv_.var.evt.e); static_cast<QP::QAsm *>( QP::QS::rxPriv_.currObj[QP::QS::SM_OBJ]) - ->dispatch(l_rx.var.evt.e, 0U); + ->dispatch(QP::QS::rxPriv_.var.evt.e, 0U); i = 0x01U; // success, recycle } else { i = 0x81U; // failure, recycle } } - else if (l_rx.var.evt.prio == 254U) { + else if (QP::QS::rxPriv_.var.evt.prio == 254U) { // init the current SM object" if (QP::QS::rxPriv_.currObj[QP::QS::SM_OBJ] != nullptr) { // increment the ref-ctr to simulate the situation // when the event is just retrieved from a queue. // This is expected for the following QF::gc() call. - QP::QEvt_refCtr_inc_(l_rx.var.evt.e); + QP::QEvt_refCtr_inc_(QP::QS::rxPriv_.var.evt.e); static_cast<QP::QAsm *>( QP::QS::rxPriv_.currObj[QP::QS::SM_OBJ]) - ->init(l_rx.var.evt.e, 0U); + ->init(QP::QS::rxPriv_.var.evt.e, 0U); i = 0x01U; // success, recycle } else { i = 0x81U; // failure, recycle } } - else if (l_rx.var.evt.prio == 253U) { + else if (QP::QS::rxPriv_.var.evt.prio == 253U) { // post to the current AO if (QP::QS::rxPriv_.currObj[QP::QS::AO_OBJ] != nullptr) { if (!static_cast<QP::QActive *>( QP::QS::rxPriv_.currObj[QP::QS::AO_OBJ])->POST_X( - l_rx.var.evt.e, + QP::QS::rxPriv_.var.evt.e, 0U, // margin &QP::QS::rxPriv_)) { @@ -11904,7 +11959,7 @@ void rxHandleGoodFrame_(std::uint8_t const state) { #if (QF_MAX_EPOOL > 0U) // recycle needed? if ((i & 1U) != 0U) { - QP::QF::gc(l_rx.var.evt.e); + QP::QF::gc(QP::QS::rxPriv_.var.evt.e); } #endif // failure? @@ -11950,7 +12005,7 @@ void rxHandleGoodFrame_(std::uint8_t const state) { QP::QS::tstPriv_.tpNum < (sizeof(QP::QS::tstPriv_.tpBuf) / sizeof(QP::QS::tstPriv_.tpBuf[0]))); - QP::QS::tstPriv_.tpBuf[QP::QS::tstPriv_.tpNum] = l_rx.var.tp; + QP::QS::tstPriv_.tpBuf[QP::QS::tstPriv_.tpNum] = QP::QS::rxPriv_.var.tp; ++QP::QS::tstPriv_.tpNum; // no need to report Done break; @@ -11973,9 +12028,12 @@ static void rxHandleBadFrame_(std::uint8_t const state) noexcept { rxReportError_(0x50U); // error for all bad frames switch (state) { case WAIT4_EVT_FRAME: { - Q_ASSERT_INCRIT(910, l_rx.var.evt.e != nullptr); + QS_CRIT_STAT + QS_CRIT_ENTRY(); + Q_ASSERT_INCRIT(910, QP::QS::rxPriv_.var.evt.e != nullptr); + QS_CRIT_EXIT(); #if (QF_MAX_EPOOL > 0U) - QP::QF::gc(l_rx.var.evt.e); // don't leak an allocated event + QP::QF::gc(QP::QS::rxPriv_.var.evt.e); // don't leak allocated evt #endif break; } @@ -11988,34 +12046,54 @@ static void rxHandleBadFrame_(std::uint8_t const state) noexcept { //............................................................................ static void rxReportAck_(enum QP::QSpyRxRecords const recId) noexcept { + QS_CRIT_STAT + QS_CRIT_ENTRY(); + QS_MEM_SYS(); QP::QS::beginRec_(static_cast<std::uint_fast8_t>(QP::QS_RX_STATUS)); QS_U8_PRE_(recId); // record ID QP::QS::endRec_(); + QS_MEM_APP(); + QS_CRIT_EXIT(); QS_REC_DONE(); // user callback (if defined) } //............................................................................ static void rxReportError_(std::uint8_t const code) noexcept { + QS_CRIT_STAT + QS_CRIT_ENTRY(); + QS_MEM_SYS(); QP::QS::beginRec_(static_cast<std::uint_fast8_t>(QP::QS_RX_STATUS)); QS_U8_PRE_(0x80U | code); // error code QP::QS::endRec_(); + QS_MEM_APP(); + QS_CRIT_EXIT(); QS_REC_DONE(); // user callback (if defined) } //............................................................................ static void rxReportDone_(enum QP::QSpyRxRecords const recId) noexcept { + QS_CRIT_STAT + QS_CRIT_ENTRY(); + QS_MEM_SYS(); QP::QS::beginRec_(static_cast<std::uint_fast8_t>(QP::QS_TARGET_DONE)); QS_TIME_PRE_(); // timestamp QS_U8_PRE_(recId); // record ID QP::QS::endRec_(); + QS_MEM_APP(); + QS_CRIT_EXIT(); QS_REC_DONE(); // user callback (if defined) } //............................................................................ static void queryCurrObj_(std::uint8_t obj_kind) noexcept { - Q_REQUIRE_INCRIT(200, obj_kind < Q_DIM(QP::QS::rxPriv_.currObj)); + QS_CRIT_STAT + QS_CRIT_ENTRY(); + Q_REQUIRE_INCRIT(800, obj_kind < Q_DIM(QP::QS::rxPriv_.currObj)); + QS_CRIT_EXIT(); if (QP::QS::rxPriv_.currObj[obj_kind] != nullptr) { + QS_CRIT_ENTRY(); + QS_MEM_SYS(); QP::QS::beginRec_(static_cast<std::uint_fast8_t>(QP::QS_QUERY_DATA)); QS_TIME_PRE_(); // timestamp QS_U8_PRE_(obj_kind); // object kind @@ -12055,6 +12133,8 @@ static void queryCurrObj_(std::uint8_t obj_kind) noexcept { break; } QP::QS::endRec_(); + QS_MEM_APP(); + QS_CRIT_EXIT(); QS_REC_DONE(); // user callback (if defined) } else { @@ -12066,26 +12146,26 @@ static void queryCurrObj_(std::uint8_t obj_kind) noexcept { static void rxPoke_() noexcept { std::uint8_t * ptr = static_cast<std::uint8_t *>(QP::QS::rxPriv_.currObj[QP::QS::AP_OBJ]); - ptr = &ptr[l_rx.var.poke.offs]; - switch (l_rx.var.poke.size) { + ptr = &ptr[QP::QS::rxPriv_.var.poke.offs]; + switch (QP::QS::rxPriv_.var.poke.size) { case 1: - *ptr = static_cast<std::uint8_t>(l_rx.var.poke.data); + *ptr = static_cast<std::uint8_t>(QP::QS::rxPriv_.var.poke.data); break; case 2: *reinterpret_cast<std::uint16_t *>(ptr) - = static_cast<std::uint16_t>(l_rx.var.poke.data); + = static_cast<std::uint16_t>(QP::QS::rxPriv_.var.poke.data); break; case 4: - *reinterpret_cast<std::uint32_t *>(ptr) = l_rx.var.poke.data; + *reinterpret_cast<std::uint32_t *>(ptr) = QP::QS::rxPriv_.var.poke.data; break; default: Q_ERROR_ID(900); break; } - l_rx.var.poke.data = 0U; - l_rx.var.poke.idx = 0U; - l_rx.var.poke.offs += static_cast<std::uint16_t>(l_rx.var.poke.size); + QP::QS::rxPriv_.var.poke.data = 0U; + QP::QS::rxPriv_.var.poke.idx = 0U; + QP::QS::rxPriv_.var.poke.offs += static_cast<std::uint16_t>(QP::QS::rxPriv_.var.poke.size); } } // unnamed namespace diff --git a/qpcpp_md5.bat b/qpcpp_md5.bat index db4d372a9..f72185532 100644 --- a/qpcpp_md5.bat +++ b/qpcpp_md5.bat @@ -13,6 +13,7 @@ @md5sum qpcpp.qm ^ include/* ^ src/qf/* src/qk/* src/qs/* src/qv/* src/qxk/* ^ + ports/lint-plus/*.lnt ^ ports/arm-cm/qk/armclang/* ports/arm-cm/qk/config/* ports/arm-cm/qk/gnu/* ports/arm-cm/qk/iar/* ^ ports/arm-cm/qv/armclang/* ports/arm-cm/qv/config/* ports/arm-cm/qv/gnu/* ports/arm-cm/qv/iar/* ^ ports/arm-cm/qxk/armclang/* ports/arm-cm/qxk/config/* ports/arm-cm/qxk/gnu/* ports/arm-cm/qxk/iar/* ^ diff --git a/src/qf/qep_hsm.cpp b/src/qf/qep_hsm.cpp index a58775c08..615ef8a2e 100644 --- a/src/qf/qep_hsm.cpp +++ b/src/qf/qep_hsm.cpp @@ -74,24 +74,24 @@ static QP::QEvt const l_reservedEvt_[4] { // helper macro to trace state entry #define QS_STATE_ENTRY_(state_, qsId_) \ - QS_CRIT_ENTRY(); \ - QS_MEM_SYS(); \ + QS_CRIT_ENTRY(); \ + QS_MEM_SYS(); \ QS_BEGIN_PRE_(QS_QEP_STATE_ENTRY, (qsId_)) \ - QS_OBJ_PRE_(this); \ - QS_FUN_PRE_(state_); \ - QS_END_PRE_() \ - QS_MEM_APP(); \ + QS_OBJ_PRE_(this); \ + QS_FUN_PRE_(state_); \ + QS_END_PRE_() \ + QS_MEM_APP(); \ QS_CRIT_EXIT() // helper macro to trace state exit #define QS_STATE_EXIT_(state_, qsId_) \ - QS_CRIT_ENTRY(); \ - QS_MEM_SYS(); \ + QS_CRIT_ENTRY(); \ + QS_MEM_SYS(); \ QS_BEGIN_PRE_(QS_QEP_STATE_EXIT, (qsId_)) \ - QS_OBJ_PRE_(this); \ - QS_FUN_PRE_(state_); \ - QS_END_PRE_() \ - QS_MEM_APP(); \ + QS_OBJ_PRE_(this); \ + QS_FUN_PRE_(state_); \ + QS_END_PRE_() \ + QS_MEM_APP(); \ QS_CRIT_EXIT() //! @endcond @@ -172,20 +172,24 @@ void QHsm::init( QF_CRIT_EXIT(); // drill down into the state hierarchy with initial transitions... + std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit do { QStateHandler path[MAX_NEST_DEPTH_]; // tran entry path array - std::int_fast8_t ip = 0; // entry path index + std::int_fast8_t ip = 0; // tran entry path index path[0] = m_temp.fun; static_cast(QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG)); while (m_temp.fun != t) { ++ip; - QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(220, ip < MAX_NEST_DEPTH_); - QF_CRIT_EXIT(); path[ip] = m_temp.fun; static_cast(QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG)); } + QF_CRIT_ENTRY(); + // The initial transition source state must be reached + // Too many state nesting levels or "malformed" HSM. + Q_ASSERT_INCRIT(220, m_temp.fun == t); + QF_CRIT_EXIT(); + m_temp.fun = path[0]; // retrace the entry path in reverse (desired) order... @@ -217,9 +221,14 @@ void QHsm::init( } #endif // Q_SPY - } while (r == Q_RET_TRAN); + --limit; + } while ((r == Q_RET_TRAN) && (limit > 0)); + + QF_CRIT_ENTRY(); + // Loop limit must not be reached. + // Too many state nesting levels or likely "malformed" HSM + Q_ENSURE_INCRIT(290, limit > 0); - QS_CRIT_ENTRY(); QS_MEM_SYS(); QS_BEGIN_PRE_(QS_QEP_INIT_TRAN, qsId) QS_TIME_PRE_(); // time stamp @@ -227,7 +236,8 @@ void QHsm::init( QS_FUN_PRE_(t); // the new active state QS_END_PRE_() QS_MEM_APP(); - QS_CRIT_EXIT(); + + QF_CRIT_EXIT(); m_state.fun = t; // change the current active state #ifndef Q_UNSAFE @@ -267,6 +277,7 @@ void QHsm::dispatch( // process the event hierarchically... QState r; m_temp.fun = s; + std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit do { s = m_temp.fun; r = (*s)(this, e); // invoke state handler s @@ -285,7 +296,13 @@ void QHsm::dispatch( r = QHSM_RESERVED_EVT_(s, Q_EMPTY_SIG); // superstate of s } - } while (r == Q_RET_SUPER); + + --limit; + } while ((r == Q_RET_SUPER) && (limit > 0)); + + QF_CRIT_ENTRY(); + Q_ASSERT_INCRIT(310, limit > 0); + QF_CRIT_EXIT(); if (r >= Q_RET_TRAN) { // regular tran. taken? QStateHandler path[MAX_NEST_DEPTH_]; @@ -295,14 +312,20 @@ void QHsm::dispatch( path[2] = s; // tran. source // exit current state to tran. source s... - for (; t != s; t = m_temp.fun) { + limit = MAX_NEST_DEPTH_; // loop hard limit + for (; (t != s) && (limit > 0); t = m_temp.fun) { // exit from t if (QHSM_RESERVED_EVT_(t, Q_EXIT_SIG) == Q_RET_HANDLED) { QS_STATE_EXIT_(t, qsId); // find superstate of t static_cast(QHSM_RESERVED_EVT_(t, Q_EMPTY_SIG)); } + --limit; } + QF_CRIT_ENTRY(); + Q_ASSERT_INCRIT(320, limit > 0); + QF_CRIT_EXIT(); + std::int_fast8_t ip = hsm_tran(path, qsId); // take the tran. #ifdef Q_SPY @@ -350,20 +373,21 @@ void QHsm::dispatch( // find superstate static_cast(QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG)); - while (m_temp.fun != t) { + while ((m_temp.fun != t) && (ip < (MAX_NEST_DEPTH_ - 1))) { ++ip; path[ip] = m_temp.fun; // find superstate static_cast( QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG)); } - m_temp.fun = path[0]; - - // entry path must not overflow QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(410, ip < MAX_NEST_DEPTH_); + // The initial transition source state must be reached. + // Too many state nesting levels or "malformed" HSM. + Q_ASSERT_INCRIT(330, m_temp.fun == t); QF_CRIT_EXIT(); + m_temp.fun = path[0]; + // retrace the entry path in reverse (correct) order... do { // enter path[ip] @@ -549,21 +573,18 @@ std::int_fast8_t QHsm::hsm_tran( // and store the entry path along the way std::int_fast8_t iq = 0; // indicate that LCA was found ip = 1; // enter target and its superstate - path[1] = t; // save the superstate of target - t = m_temp.fun; // save source->super + path[1] = t; // save the superstate of target + t = m_temp.fun; // save source->super // find target->super->super... QState r = QHSM_RESERVED_EVT_(path[1], Q_EMPTY_SIG); - while (r == Q_RET_SUPER) { + while ((r == Q_RET_SUPER) + && (ip < (MAX_NEST_DEPTH_ - 1))) + { ++ip; path[ip] = m_temp.fun; // store the entry path if (m_temp.fun == s) { // is it the source? iq = 1; // indicate that the LCA found - - // entry path must not overflow - QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(510, ip < MAX_NEST_DEPTH_); - QF_CRIT_EXIT(); --ip; // do not enter the source r = Q_RET_HANDLED; // terminate the loop } @@ -571,14 +592,14 @@ std::int_fast8_t QHsm::hsm_tran( r = QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG); } } + QF_CRIT_ENTRY(); + // Tran. source must be found within the nesting depth + // Too many state nesting levels or "malformed" HSM. + Q_ASSERT_INCRIT(510, r != Q_RET_SUPER); + QF_CRIT_EXIT(); // the LCA not found yet? if (iq == 0) { - // entry path must not overflow - QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(520, ip < MAX_NEST_DEPTH_); - QF_CRIT_EXIT(); - // exit source s if (QHSM_RESERVED_EVT_(s, Q_EXIT_SIG) == Q_RET_HANDLED) @@ -606,6 +627,7 @@ std::int_fast8_t QHsm::hsm_tran( // (g) check each source->super->... // for each target->super... r = Q_RET_IGNORED; // keep looping + std::int_fast8_t limit = MAX_NEST_DEPTH_; do { // exit from t if (QHSM_RESERVED_EVT_(t, Q_EXIT_SIG) @@ -629,13 +651,21 @@ std::int_fast8_t QHsm::hsm_tran( --iq; } } while (iq >= 0); - } while (r != Q_RET_HANDLED); + + --limit; + } while ((r != Q_RET_HANDLED) && (limit > 0)); + QF_CRIT_ENTRY(); + Q_ASSERT_INCRIT(530, limit > 0); + QF_CRIT_EXIT(); } } } } } } + QF_CRIT_ENTRY(); + Q_ENSURE_INCRIT(590, ip < MAX_NEST_DEPTH_); + QF_CRIT_EXIT(); return ip; } diff --git a/src/qf/qep_msm.cpp b/src/qf/qep_msm.cpp index 288c51399..ac9e4bff5 100644 --- a/src/qf/qep_msm.cpp +++ b/src/qf/qep_msm.cpp @@ -59,6 +59,15 @@ namespace { Q_DEFINE_THIS_MODULE("qep_msm") +// maximum depth of state nesting in a QMsm (including the top level) +static constexpr std::int_fast8_t MAX_NEST_DEPTH_ {6}; + +// maximum length of transition-action array +static constexpr std::int_fast8_t MAX_TRAN_LENGTH_ {3*MAX_NEST_DEPTH_}; + +// maximum depth of entry levels in a MSM for tran. to history. +static constexpr std::int_fast8_t MAX_ENTRY_DEPTH_ {4}; + // top-state object for QMsm-style state machines QP::QMState const l_msm_top_s = { nullptr, @@ -68,8 +77,6 @@ QP::QMState const l_msm_top_s = { nullptr }; -static constexpr std::int_fast8_t MAX_ENTRY_DEPTH_ {4}; - } // unnamed namespace //! @endcond @@ -131,12 +138,16 @@ void QMsm::init( m_state.obj = m_temp.tatbl->target; // drill down into the state hierarchy with initial transitions... + std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit do { // execute the tran. table r = execTatbl_(m_temp.tatbl, qsId); - } while (r >= Q_RET_TRAN_INIT); + --limit; + } while ((r >= Q_RET_TRAN_INIT) && (limit > 0)); + + QF_CRIT_ENTRY(); + Q_ENSURE_INCRIT(290, limit > 0); - QS_CRIT_ENTRY(); QS_MEM_SYS(); QS_BEGIN_PRE_(QS_QEP_INIT_TRAN, qsId) QS_TIME_PRE_(); // time stamp @@ -144,7 +155,8 @@ void QMsm::init( QS_FUN_PRE_(m_state.obj->stateHandler); // the new current state QS_END_PRE_() QS_MEM_APP(); - QS_CRIT_EXIT(); + + QF_CRIT_EXIT(); #ifndef Q_UNSAFE m_temp.uint = ~m_state.uint; @@ -182,6 +194,7 @@ void QMsm::dispatch( // scan the state hierarchy up to the top state... QState r; + std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit do { r = (*t->stateHandler)(this, e); // call state handler function @@ -214,11 +227,15 @@ void QMsm::dispatch( t = t->superstate; // advance to the superstate } - } while (t != nullptr); + --limit; + } while ((t != nullptr) && (limit > 0)); + QF_CRIT_ENTRY(); + Q_ASSERT_INCRIT(310, limit > 0); + QF_CRIT_EXIT(); if (r >= Q_RET_TRAN) { // any kind of tran. taken? #ifdef Q_SPY - QMState const * const ts = t; // transition source for QS tracing + QMState const * const ts = t; // tran. source for QS tracing QF_CRIT_ENTRY(); // the tran. source state must not be nullptr @@ -226,6 +243,7 @@ void QMsm::dispatch( QF_CRIT_EXIT(); #endif // Q_SPY + limit = MAX_NEST_DEPTH_; // loop hard limit do { // save the tran-action table before it gets clobbered QMTranActTable const * const tatbl = m_temp.tatbl; @@ -292,10 +310,12 @@ void QMsm::dispatch( } t = s; // set target to the current state + --limit; + } while ((r >= Q_RET_TRAN) && (limit > 0)); - } while (r >= Q_RET_TRAN); + QF_CRIT_ENTRY(); + Q_ASSERT_INCRIT(320, limit > 0); - QS_CRIT_ENTRY(); QS_MEM_SYS(); QS_BEGIN_PRE_(QS_QEP_TRAN, qsId) QS_TIME_PRE_(); // time stamp @@ -305,7 +325,8 @@ void QMsm::dispatch( QS_FUN_PRE_(s->stateHandler); // the new active state QS_END_PRE_() QS_MEM_APP(); - QS_CRIT_EXIT(); + + QF_CRIT_EXIT(); } #ifdef Q_SPY @@ -351,12 +372,12 @@ void QMsm::dispatch( //${QEP::QMsm::isIn} ......................................................... bool QMsm::isIn(QStateHandler const state) noexcept { - bool inState = false; // assume that this MSM is not in 'state' + bool inState = false; // assume that this SM is not in 'state' QMState const *s = m_state.obj; - std::int_fast8_t limit = 6; // loop hard limit + std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit for (; (s != nullptr) && (limit > 0); --limit) { - if (s->stateHandler == state) { // match found? + if (s->stateHandler == state) { // match found? inState = true; break; } @@ -367,7 +388,7 @@ bool QMsm::isIn(QStateHandler const state) noexcept { QF_CRIT_STAT QF_CRIT_ENTRY(); - Q_ENSURE_INCRIT(690, limit > 0); + Q_ENSURE_INCRIT(490, limit > 0); QF_CRIT_EXIT(); return inState; @@ -375,12 +396,12 @@ bool QMsm::isIn(QStateHandler const state) noexcept { //${QEP::QMsm::isInState} .................................................... bool QMsm::isInState(QMState const * const stateObj) const noexcept { - bool inState = false; // assume that this MSM is not in 'state' + bool inState = false; // assume that this SM is not in 'state' QMState const *s = m_state.obj; - std::int_fast8_t limit = 6; // loop hard limit + std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit for (; (s != nullptr) && (limit > 0); --limit) { - if (s == stateObj) { // match found? + if (s == stateObj) { // match found? inState = true; break; } @@ -391,7 +412,7 @@ bool QMsm::isInState(QMState const * const stateObj) const noexcept { QF_CRIT_STAT QF_CRIT_ENTRY(); - Q_ENSURE_INCRIT(790, limit > 0); + Q_ENSURE_INCRIT(590, limit > 0); QF_CRIT_EXIT(); return inState; @@ -403,7 +424,11 @@ QMState const * QMsm::childStateObj(QMState const * const parent) const noexcept bool isFound = false; // start with the child not found QMState const *s; - for (s = m_state.obj; s != nullptr; s = s->superstate) { + std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit + for (s = m_state.obj; + (s != nullptr) && (limit > 0); + s = s->superstate) + { if (s == parent) { isFound = true; // child is found break; @@ -411,9 +436,19 @@ QMState const * QMsm::childStateObj(QMState const * const parent) const noexcept else { child = s; } + --limit; } + QF_CRIT_STAT + QF_CRIT_ENTRY(); + Q_ASSERT_INCRIT(610, limit > 0); + QF_CRIT_EXIT(); + if (!isFound) { // still not found? - for (s = m_temp.obj; s != nullptr; s = s->superstate) { + limit = MAX_NEST_DEPTH_; // loop hard limit + for (s = m_temp.obj; + (s != nullptr) && (limit > 0); + s = s->superstate) + { if (s == parent) { isFound = true; // child is found break; @@ -421,12 +456,12 @@ QMState const * QMsm::childStateObj(QMState const * const parent) const noexcept else { child = s; } + --limit; } } - QF_CRIT_STAT QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(890, isFound); + Q_ENSURE_INCRIT(690, isFound && (limit > 0)); QF_CRIT_EXIT(); return child; // return the child @@ -445,11 +480,13 @@ QState QMsm::execTatbl_( QF_CRIT_ENTRY(); // precondition: // - the tran-action table pointer must not be NULL - Q_REQUIRE_INCRIT(400, tatbl != nullptr); + Q_REQUIRE_INCRIT(700, tatbl != nullptr); QF_CRIT_EXIT(); QState r = Q_RET_NULL; - for (QActionHandler const *a = &tatbl->act[0]; *a != nullptr; ++a) { + std::int_fast8_t limit = MAX_TRAN_LENGTH_; // loop hard limit + QActionHandler const *a = &tatbl->act[0]; + for (; (*a != nullptr) && (limit > 0); ++a) { r = (*(*a))(this); // call the action through the 'a' pointer #ifdef Q_SPY QS_CRIT_ENTRY(); @@ -493,7 +530,11 @@ QState QMsm::execTatbl_( QS_MEM_APP(); QS_CRIT_EXIT(); #endif // Q_SPY + --limit; } + QF_CRIT_ENTRY(); + Q_ENSURE_INCRIT(790, *a == nullptr); + QF_CRIT_EXIT(); m_state.obj = (r >= Q_RET_TRAN) ? m_temp.tatbl->target @@ -515,7 +556,8 @@ void QMsm::exitToTranSource_( // exit states from the current state to the tran. source state QMState const *s = cs; - while (s != ts) { + std::int_fast8_t limit = MAX_NEST_DEPTH_; // loop hard limit + for (; (s != ts) && (limit > 0); --limit) { // exit action provided in state 's'? if (s->exitAction != nullptr) { // execute the exit action @@ -536,10 +578,13 @@ void QMsm::exitToTranSource_( if (s == nullptr) { // reached the top of a submachine? s = m_temp.obj; // the superstate from QM_SM_EXIT() QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(510, s != nullptr); + Q_ASSERT_INCRIT(810, s != nullptr); // must be valid QF_CRIT_EXIT(); } } + QF_CRIT_ENTRY(); + Q_ENSURE_INCRIT(890, limit > 0); + QF_CRIT_EXIT(); } //${QEP::QMsm::enterHistory_} ................................................ @@ -568,11 +613,8 @@ QState QMsm::enterHistory_( QS_CRIT_EXIT(); std::int_fast8_t i = 0; // tran. entry path index - while (s != ts) { + while ((s != ts) && (i < MAX_ENTRY_DEPTH_)) { if (s->entryAction != nullptr) { - QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(620, i < MAX_ENTRY_DEPTH_); - QF_CRIT_EXIT(); epath[i] = s; ++i; } @@ -581,6 +623,9 @@ QState QMsm::enterHistory_( ts = s; // force exit from the for-loop } } + QF_CRIT_ENTRY(); + Q_ASSERT_INCRIT(910, s == ts); + QF_CRIT_EXIT(); // retrace the entry path in reverse (desired) order... while (i > 0) { diff --git a/src/qf/qf_dyn.cpp b/src/qf/qf_dyn.cpp index cacb236c3..99a37dc27 100644 --- a/src/qf/qf_dyn.cpp +++ b/src/qf/qf_dyn.cpp @@ -65,6 +65,20 @@ Q_DEFINE_THIS_MODULE("qf_dyn") #endif //$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//$define${QEP::QEvt::ctor} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +namespace QP { + +//${QEP::QEvt::ctor} ......................................................... +#ifdef QEVT_DYN_CTOR +QEvt * QEvt::ctor(DynEvt const dummy) noexcept { + Q_UNUSED_PAR(dummy); + return this; +} + +#endif // def QEVT_DYN_CTOR + +} // namespace QP +//$enddef${QEP::QEvt::ctor} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //$define${QF::QF-dyn} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv namespace QP { namespace QF { @@ -110,7 +124,15 @@ void poolInit( //${QF::QF-dyn::poolGetMaxBlockSize} ......................................... std::uint_fast16_t poolGetMaxBlockSize() noexcept { - return QF_EPOOL_EVENT_SIZE_(priv_.ePool_[priv_.maxPool_ - 1U]); + QF_CRIT_STAT + QF_CRIT_ENTRY(); + QF_MEM_SYS(); + std::uint_fast16_t const max_size = + QF_EPOOL_EVENT_SIZE_(priv_.ePool_[priv_.maxPool_ - 1U]); + QF_MEM_APP(); + QF_CRIT_EXIT(); + + return max_size; } //${QF::QF-dyn::getPoolMin} .................................................. diff --git a/src/qs/qs_rx.cpp b/src/qs/qs_rx.cpp index c6a1c7798..b01a6c35b 100644 --- a/src/qs/qs_rx.cpp +++ b/src/qs/qs_rx.cpp @@ -53,85 +53,6 @@ namespace { // unnamed local namespace Q_DEFINE_THIS_MODULE("qs_rx") -//............................................................................ -#if (QS_OBJ_PTR_SIZE == 2U) - using QSObj = std::uint16_t; -#elif (QS_OBJ_PTR_SIZE == 4U) - using QSObj = std::uint32_t; -#elif (QS_OBJ_PTR_SIZE == 8U) - using QSObj = std::uint64_t; -#endif - -struct CmdVar { - std::uint32_t param1; - std::uint32_t param2; - std::uint32_t param3; - std::uint8_t idx; - std::uint8_t cmdId; -}; - -struct TickVar { - std::uint_fast8_t rate; -}; - -struct PeekVar { - std::uint16_t offs; - std::uint8_t size; - std::uint8_t num; - std::uint8_t idx; -}; - -struct PokeVar { - std::uint32_t data; - std::uint16_t offs; - std::uint8_t size; - std::uint8_t num; - std::uint8_t idx; - std::uint8_t fill; -}; - -struct FltVar { - std::uint8_t data[16]; - std::uint8_t idx; - std::uint8_t recId; // global/local -}; - -struct ObjVar { - QSObj addr; - std::uint8_t idx; - std::uint8_t kind; // see qs.hpp, enum QSpyObjKind - std::uint8_t recId; -}; - -struct EvtVar { - QP::QEvt *e; - std::uint8_t *p; - QP::QSignal sig; - std::uint16_t len; - std::uint8_t prio; - std::uint8_t idx; -}; - -// extended-state variables for the current QS-RX state -static struct ExtState { - union Variant { - CmdVar cmd; - TickVar tick; - PeekVar peek; - PokeVar poke; - FltVar flt; - ObjVar obj; - EvtVar evt; -#ifdef Q_UTEST - QP::QS::TProbe tp; -#endif // Q_UTEST - } var; - std::uint8_t state; - std::uint8_t esc; - std::uint8_t seq; - std::uint8_t chksum; -} l_rx; - enum RxStateEnum : std::uint8_t { ERROR_STATE, WAIT4_SEQ, @@ -193,16 +114,18 @@ static void rxPoke_() noexcept; // Internal QS-RX function to take a tran. in the QS-RX FSM static inline void tran_(RxStateEnum const target) noexcept { - l_rx.state = static_cast(target); + QP::QS::rxPriv_.state = static_cast(target); } } // unnamed namespace +#ifndef QF_MEM_ISOLATE namespace QP { namespace QS { RxAttr rxPriv_; } // namespace QS } // namespace QP +#endif // QF_MEM_ISOLATE //! @endcond //============================================================================ @@ -236,9 +159,9 @@ void rxInitBuf( rxPriv_.currObj[QS::AP_OBJ] = nullptr; tran_(WAIT4_SEQ); - l_rx.esc = 0U; - l_rx.seq = 0U; - l_rx.chksum = 0U; + QP::QS::rxPriv_.esc = 0U; + QP::QS::rxPriv_.seq = 0U; + QP::QS::rxPriv_.chksum = 0U; beginRec_(static_cast(QS_OBJ_DICT)); QS_OBJ_PRE_(&rxPriv_); @@ -254,9 +177,6 @@ void rxInitBuf( //${QS::QS-RX::rxParse} ...................................................... void rxParse() { - // NOTE: Must be called IN critical section. - // Also requires system-level memory access (QF_MEM_SYS()). - QSCtr tail = rxPriv_.tail; while (rxPriv_.head != tail) { // QS-RX buffer NOT empty? std::uint8_t b = rxPriv_.buf[tail]; @@ -267,34 +187,34 @@ void rxParse() { } rxPriv_.tail = tail; // update the tail to a *valid* index - if (l_rx.esc != 0U) { // escaped byte arrived? - l_rx.esc = 0U; + if (QP::QS::rxPriv_.esc != 0U) { // escaped byte arrived? + QP::QS::rxPriv_.esc = 0U; b ^= QS_ESC_XOR; - l_rx.chksum += b; + QP::QS::rxPriv_.chksum += b; rxParseData_(b); } else if (b == QS_ESC) { - l_rx.esc = 1U; + QP::QS::rxPriv_.esc = 1U; } else if (b == QS_FRAME) { // get ready for the next frame - b = l_rx.state; // save the current state in b - l_rx.esc = 0U; + b = QP::QS::rxPriv_.state; // save the current state in b + QP::QS::rxPriv_.esc = 0U; tran_(WAIT4_SEQ); - if (l_rx.chksum == QS_GOOD_CHKSUM) { - l_rx.chksum = 0U; + if (QP::QS::rxPriv_.chksum == QS_GOOD_CHKSUM) { + QP::QS::rxPriv_.chksum = 0U; rxHandleGoodFrame_(b); } else { // bad checksum - l_rx.chksum = 0U; + QP::QS::rxPriv_.chksum = 0U; rxReportError_(0x41U); rxHandleBadFrame_(b); } } else { - l_rx.chksum += b; + QP::QS::rxPriv_.chksum += b; rxParseData_(b); } } @@ -347,12 +267,12 @@ namespace { // unnamed local namespace //............................................................................ static void rxParseData_(std::uint8_t const b) noexcept { - switch (l_rx.state) { + switch (QP::QS::rxPriv_.state) { case WAIT4_SEQ: { - ++l_rx.seq; - if (l_rx.seq != b) { // not the expected sequence? + ++QP::QS::rxPriv_.seq; + if (QP::QS::rxPriv_.seq != b) { // not the expected sequence? rxReportError_(0x42U); - l_rx.seq = b; // update the sequence + QP::QS::rxPriv_.seq = b; // update the sequence } tran_(WAIT4_REC); break; @@ -373,8 +293,8 @@ static void rxParseData_(std::uint8_t const b) noexcept { break; case QP::QS_RX_PEEK: if (QP::QS::rxPriv_.currObj[QP::QS::AP_OBJ] != nullptr) { - l_rx.var.peek.offs = 0U; - l_rx.var.peek.idx = 0U; + QP::QS::rxPriv_.var.peek.offs = 0U; + QP::QS::rxPriv_.var.peek.idx = 0U; tran_(WAIT4_PEEK_OFFS); } else { @@ -385,18 +305,17 @@ static void rxParseData_(std::uint8_t const b) noexcept { break; case QP::QS_RX_POKE: case QP::QS_RX_FILL: - l_rx.var.poke.fill = + QP::QS::rxPriv_.var.poke.fill = (b == static_cast(QP::QS_RX_FILL)) - ? 1U - : 0U; + ? 1U : 0U; if (QP::QS::rxPriv_.currObj[QP::QS::AP_OBJ] != nullptr) { - l_rx.var.poke.offs = 0U; - l_rx.var.poke.idx = 0U; + QP::QS::rxPriv_.var.poke.offs = 0U; + QP::QS::rxPriv_.var.poke.idx = 0U; tran_(WAIT4_POKE_OFFS); } else { rxReportError_( - (l_rx.var.poke.fill != 0U) + (QP::QS::rxPriv_.var.poke.fill != 0U) ? static_cast(QP::QS_RX_FILL) : static_cast(QP::QS_RX_POKE)); tran_(ERROR_STATE); @@ -404,16 +323,16 @@ static void rxParseData_(std::uint8_t const b) noexcept { break; case QP::QS_RX_GLB_FILTER: // intentionally fall-through case QP::QS_RX_LOC_FILTER: - l_rx.var.flt.recId = b; + QP::QS::rxPriv_.var.flt.recId = b; tran_(WAIT4_FILTER_LEN); break; case QP::QS_RX_AO_FILTER: // intentionally fall-through case QP::QS_RX_CURR_OBJ: - l_rx.var.obj.recId = b; + QP::QS::rxPriv_.var.obj.recId = b; tran_(WAIT4_OBJ_KIND); break; case QP::QS_RX_QUERY_CURR: - l_rx.var.obj.recId = + QP::QS::rxPriv_.var.obj.recId = static_cast(QP::QS_RX_QUERY_CURR); tran_(WAIT4_QUERY_KIND); break; @@ -437,8 +356,8 @@ static void rxParseData_(std::uint8_t const b) noexcept { (sizeof(QP::QS::tstPriv_.tpBuf) / sizeof(QP::QS::tstPriv_.tpBuf[0])))) { - l_rx.var.tp.data = 0U; - l_rx.var.tp.idx = 0U; + QP::QS::rxPriv_.var.tp.data = 0U; + QP::QS::rxPriv_.var.tp.idx = 0U; tran_(WAIT4_TEST_PROBE_DATA); } else { // the # Test-Probes exceeded @@ -461,40 +380,40 @@ static void rxParseData_(std::uint8_t const b) noexcept { break; } case WAIT4_CMD_ID: { - l_rx.var.cmd.cmdId = b; - l_rx.var.cmd.idx = 0U; - l_rx.var.cmd.param1 = 0U; - l_rx.var.cmd.param2 = 0U; - l_rx.var.cmd.param3 = 0U; + QP::QS::rxPriv_.var.cmd.cmdId = b; + QP::QS::rxPriv_.var.cmd.idx = 0U; + QP::QS::rxPriv_.var.cmd.param1 = 0U; + QP::QS::rxPriv_.var.cmd.param2 = 0U; + QP::QS::rxPriv_.var.cmd.param3 = 0U; tran_(WAIT4_CMD_PARAM1); break; } case WAIT4_CMD_PARAM1: { - l_rx.var.cmd.param1 |= - (static_cast(b) << l_rx.var.cmd.idx); - l_rx.var.cmd.idx += 8U; - if (l_rx.var.cmd.idx == (8U*4U)) { - l_rx.var.cmd.idx = 0U; + QP::QS::rxPriv_.var.cmd.param1 |= + (static_cast(b) << QP::QS::rxPriv_.var.cmd.idx); + QP::QS::rxPriv_.var.cmd.idx += 8U; + if (QP::QS::rxPriv_.var.cmd.idx == (8U * 4U)) { + QP::QS::rxPriv_.var.cmd.idx = 0U; tran_(WAIT4_CMD_PARAM2); } break; } case WAIT4_CMD_PARAM2: { - l_rx.var.cmd.param2 |= - static_cast(b) << l_rx.var.cmd.idx; - l_rx.var.cmd.idx += 8U; - if (l_rx.var.cmd.idx == (8U*4U)) { - l_rx.var.cmd.idx = 0U; + QP::QS::rxPriv_.var.cmd.param2 |= + static_cast(b) << QP::QS::rxPriv_.var.cmd.idx; + QP::QS::rxPriv_.var.cmd.idx += 8U; + if (QP::QS::rxPriv_.var.cmd.idx == (8U * 4U)) { + QP::QS::rxPriv_.var.cmd.idx = 0U; tran_(WAIT4_CMD_PARAM3); } break; } case WAIT4_CMD_PARAM3: { - l_rx.var.cmd.param3 |= - static_cast(b) << l_rx.var.cmd.idx; - l_rx.var.cmd.idx += 8U; - if (l_rx.var.cmd.idx == (8U*4U)) { - l_rx.var.cmd.idx = 0U; + QP::QS::rxPriv_.var.cmd.param3 |= + static_cast(b) << QP::QS::rxPriv_.var.cmd.idx; + QP::QS::rxPriv_.var.cmd.idx += 8U; + if (QP::QS::rxPriv_.var.cmd.idx == (8U * 4U)) { + QP::QS::rxPriv_.var.cmd.idx = 0U; tran_(WAIT4_CMD_FRAME); } break; @@ -508,7 +427,7 @@ static void rxParseData_(std::uint8_t const b) noexcept { break; } case WAIT4_TICK_RATE: { - l_rx.var.tick.rate = static_cast(b); + QP::QS::rxPriv_.var.tick.rate = static_cast(b); tran_(WAIT4_TICK_FRAME); break; } @@ -517,12 +436,12 @@ static void rxParseData_(std::uint8_t const b) noexcept { break; } case WAIT4_PEEK_OFFS: { - if (l_rx.var.peek.idx == 0U) { - l_rx.var.peek.offs = static_cast(b); - l_rx.var.peek.idx += 8U; + if (QP::QS::rxPriv_.var.peek.idx == 0U) { + QP::QS::rxPriv_.var.peek.offs = static_cast(b); + QP::QS::rxPriv_.var.peek.idx += 8U; } else { - l_rx.var.peek.offs |= static_cast( + QP::QS::rxPriv_.var.peek.offs |= static_cast( static_cast(b) << 8U); tran_(WAIT4_PEEK_SIZE); } @@ -530,7 +449,7 @@ static void rxParseData_(std::uint8_t const b) noexcept { } case WAIT4_PEEK_SIZE: { if ((b == 1U) || (b == 2U) || (b == 4U)) { - l_rx.var.peek.size = b; + QP::QS::rxPriv_.var.peek.size = b; tran_(WAIT4_PEEK_NUM); } else { @@ -540,7 +459,7 @@ static void rxParseData_(std::uint8_t const b) noexcept { break; } case WAIT4_PEEK_NUM: { - l_rx.var.peek.num = b; + QP::QS::rxPriv_.var.peek.num = b; tran_(WAIT4_PEEK_FRAME); break; } @@ -549,12 +468,12 @@ static void rxParseData_(std::uint8_t const b) noexcept { break; } case WAIT4_POKE_OFFS: { - if (l_rx.var.poke.idx == 0U) { - l_rx.var.poke.offs = static_cast(b); - l_rx.var.poke.idx = 1U; + if (QP::QS::rxPriv_.var.poke.idx == 0U) { + QP::QS::rxPriv_.var.poke.offs = static_cast(b); + QP::QS::rxPriv_.var.poke.idx = 1U; } else { - l_rx.var.poke.offs |= static_cast( + QP::QS::rxPriv_.var.poke.offs |= static_cast( static_cast(b) << 8U); tran_(WAIT4_POKE_SIZE); } @@ -562,11 +481,11 @@ static void rxParseData_(std::uint8_t const b) noexcept { } case WAIT4_POKE_SIZE: { if ((b == 1U) || (b == 2U) || (b == 4U)) { - l_rx.var.poke.size = b; + QP::QS::rxPriv_.var.poke.size = b; tran_(WAIT4_POKE_NUM); } else { - rxReportError_((l_rx.var.poke.fill != 0U) + rxReportError_((QP::QS::rxPriv_.var.poke.fill != 0U) ? static_cast(QP::QS_RX_FILL) : static_cast(QP::QS_RX_POKE)); tran_(ERROR_STATE); @@ -575,15 +494,15 @@ static void rxParseData_(std::uint8_t const b) noexcept { } case WAIT4_POKE_NUM: { if (b > 0U) { - l_rx.var.poke.num = b; - l_rx.var.poke.data = 0U; - l_rx.var.poke.idx = 0U; - tran_((l_rx.var.poke.fill != 0U) + QP::QS::rxPriv_.var.poke.num = b; + QP::QS::rxPriv_.var.poke.data = 0U; + QP::QS::rxPriv_.var.poke.idx = 0U; + tran_((QP::QS::rxPriv_.var.poke.fill != 0U) ? WAIT4_FILL_DATA : WAIT4_POKE_DATA); } else { - rxReportError_((l_rx.var.poke.fill != 0U) + rxReportError_((QP::QS::rxPriv_.var.poke.fill != 0U) ? static_cast(QP::QS_RX_FILL) : static_cast(QP::QS_RX_POKE)); tran_(ERROR_STATE); @@ -591,22 +510,22 @@ static void rxParseData_(std::uint8_t const b) noexcept { break; } case WAIT4_FILL_DATA: { - l_rx.var.poke.data |= - static_cast(b) << l_rx.var.poke.idx; - l_rx.var.poke.idx += 8U; - if ((l_rx.var.poke.idx >> 3U) == l_rx.var.poke.size) { + QP::QS::rxPriv_.var.poke.data |= + static_cast(b) << QP::QS::rxPriv_.var.poke.idx; + QP::QS::rxPriv_.var.poke.idx += 8U; + if ((QP::QS::rxPriv_.var.poke.idx >> 3U) == QP::QS::rxPriv_.var.poke.size) { tran_(WAIT4_FILL_FRAME); } break; } case WAIT4_POKE_DATA: { - l_rx.var.poke.data |= - static_cast(b) << l_rx.var.poke.idx; - l_rx.var.poke.idx += 8U; - if ((l_rx.var.poke.idx >> 3U) == l_rx.var.poke.size) { + QP::QS::rxPriv_.var.poke.data |= + static_cast(b) << QP::QS::rxPriv_.var.poke.idx; + QP::QS::rxPriv_.var.poke.idx += 8U; + if ((QP::QS::rxPriv_.var.poke.idx >> 3U) == QP::QS::rxPriv_.var.poke.size) { rxPoke_(); - --l_rx.var.poke.num; - if (l_rx.var.poke.num == 0U) { + --QP::QS::rxPriv_.var.poke.num; + if (QP::QS::rxPriv_.var.poke.num == 0U) { tran_(WAIT4_POKE_FRAME); } } @@ -621,20 +540,20 @@ static void rxParseData_(std::uint8_t const b) noexcept { break; } case WAIT4_FILTER_LEN: { - if (b == static_cast(sizeof(l_rx.var.flt.data))) { - l_rx.var.flt.idx = 0U; + if (b == static_cast(sizeof(QP::QS::rxPriv_.var.flt.data))) { + QP::QS::rxPriv_.var.flt.idx = 0U; tran_(WAIT4_FILTER_DATA); } else { - rxReportError_(l_rx.var.flt.recId); + rxReportError_(QP::QS::rxPriv_.var.flt.recId); tran_(ERROR_STATE); } break; } case WAIT4_FILTER_DATA: { - l_rx.var.flt.data[l_rx.var.flt.idx] = b; - ++l_rx.var.flt.idx; - if (l_rx.var.flt.idx == sizeof(l_rx.var.flt.data)) { + QP::QS::rxPriv_.var.flt.data[QP::QS::rxPriv_.var.flt.idx] = b; + ++QP::QS::rxPriv_.var.flt.idx; + if (QP::QS::rxPriv_.var.flt.idx == sizeof(QP::QS::rxPriv_.var.flt.data)) { tran_(WAIT4_FILTER_FRAME); } break; @@ -645,22 +564,22 @@ static void rxParseData_(std::uint8_t const b) noexcept { } case WAIT4_OBJ_KIND: { if (b <= static_cast(QP::QS::SM_AO_OBJ)) { - l_rx.var.obj.kind = b; - l_rx.var.obj.addr = 0U; - l_rx.var.obj.idx = 0U; + QP::QS::rxPriv_.var.obj.kind = b; + QP::QS::rxPriv_.var.obj.addr = 0U; + QP::QS::rxPriv_.var.obj.idx = 0U; tran_(WAIT4_OBJ_ADDR); } else { - rxReportError_(l_rx.var.obj.recId); + rxReportError_(QP::QS::rxPriv_.var.obj.recId); tran_(ERROR_STATE); } break; } case WAIT4_OBJ_ADDR: { - l_rx.var.obj.addr |= - static_cast(b) << l_rx.var.obj.idx; - l_rx.var.obj.idx += 8U; - if (l_rx.var.obj.idx + QP::QS::rxPriv_.var.obj.addr |= + static_cast(b) << QP::QS::rxPriv_.var.obj.idx; + QP::QS::rxPriv_.var.obj.idx += 8U; + if (QP::QS::rxPriv_.var.obj.idx == (8U * static_cast(QS_OBJ_PTR_SIZE))) { tran_(WAIT4_OBJ_FRAME); @@ -673,11 +592,11 @@ static void rxParseData_(std::uint8_t const b) noexcept { } case WAIT4_QUERY_KIND: { if (b < static_cast(QP::QS::MAX_OBJ)) { - l_rx.var.obj.kind = b; + QP::QS::rxPriv_.var.obj.kind = b; tran_(WAIT4_QUERY_FRAME); } else { - rxReportError_(l_rx.var.obj.recId); + rxReportError_(QP::QS::rxPriv_.var.obj.recId); tran_(ERROR_STATE); } break; @@ -687,48 +606,47 @@ static void rxParseData_(std::uint8_t const b) noexcept { break; } case WAIT4_EVT_PRIO: { - l_rx.var.evt.prio = b; - l_rx.var.evt.sig = 0U; - l_rx.var.evt.idx = 0U; + QP::QS::rxPriv_.var.evt.prio = b; + QP::QS::rxPriv_.var.evt.sig = 0U; + QP::QS::rxPriv_.var.evt.idx = 0U; tran_(WAIT4_EVT_SIG); break; } case WAIT4_EVT_SIG: { - l_rx.var.evt.sig |= static_cast( - static_cast(b) << l_rx.var.evt.idx); - l_rx.var.evt.idx += 8U; - if (l_rx.var.evt.idx + QP::QS::rxPriv_.var.evt.sig |= static_cast( + static_cast(b) << QP::QS::rxPriv_.var.evt.idx); + QP::QS::rxPriv_.var.evt.idx += 8U; + if (QP::QS::rxPriv_.var.evt.idx == (8U *static_cast(Q_SIGNAL_SIZE))) { - l_rx.var.evt.len = 0U; - l_rx.var.evt.idx = 0U; + QP::QS::rxPriv_.var.evt.len = 0U; + QP::QS::rxPriv_.var.evt.idx = 0U; tran_(WAIT4_EVT_LEN); } break; } case WAIT4_EVT_LEN: { - l_rx.var.evt.len |= static_cast( - static_cast(b) << l_rx.var.evt.idx); - l_rx.var.evt.idx += 8U; - if (l_rx.var.evt.idx == (8U * 2U)) { - if ((l_rx.var.evt.len + sizeof(QP::QEvt)) - <= static_cast( - QP::QF::poolGetMaxBlockSize())) + QP::QS::rxPriv_.var.evt.len |= static_cast( + static_cast(b) << QP::QS::rxPriv_.var.evt.idx); + QP::QS::rxPriv_.var.evt.idx += 8U; + if (QP::QS::rxPriv_.var.evt.idx == (8U * 2U)) { + if ((QP::QS::rxPriv_.var.evt.len + sizeof(QP::QEvt)) + <= QP::QF::poolGetMaxBlockSize()) { // report Ack before generating any other QS records rxReportAck_(QP::QS_RX_EVENT); - l_rx.var.evt.e = QP::QF::newX_( - (static_cast(l_rx.var.evt.len) + QP::QS::rxPriv_.var.evt.e = QP::QF::newX_( + (static_cast(QP::QS::rxPriv_.var.evt.len) + sizeof(QP::QEvt)), 0U, // margin - static_cast(l_rx.var.evt.sig)); + static_cast(QP::QS::rxPriv_.var.evt.sig)); // event allocated? - if (l_rx.var.evt.e != nullptr) { - l_rx.var.evt.p = - reinterpret_cast(l_rx.var.evt.e); - l_rx.var.evt.p = &l_rx.var.evt.p[sizeof(QP::QEvt)]; - if (l_rx.var.evt.len > 0U) { + if (QP::QS::rxPriv_.var.evt.e != nullptr) { + QP::QS::rxPriv_.var.evt.p = + reinterpret_cast(QP::QS::rxPriv_.var.evt.e); + QP::QS::rxPriv_.var.evt.p = &QP::QS::rxPriv_.var.evt.p[sizeof(QP::QEvt)]; + if (QP::QS::rxPriv_.var.evt.len > 0U) { tran_(WAIT4_EVT_PAR); } else { @@ -750,10 +668,10 @@ static void rxParseData_(std::uint8_t const b) noexcept { break; } case WAIT4_EVT_PAR: { // event parameters - *l_rx.var.evt.p = b; - ++l_rx.var.evt.p; - --l_rx.var.evt.len; - if (l_rx.var.evt.len == 0U) { + *QP::QS::rxPriv_.var.evt.p = b; + ++QP::QS::rxPriv_.var.evt.p; + --QP::QS::rxPriv_.var.evt.len; + if (QP::QS::rxPriv_.var.evt.len == 0U) { tran_(WAIT4_EVT_FRAME); } break; @@ -777,21 +695,21 @@ static void rxParseData_(std::uint8_t const b) noexcept { break; } case WAIT4_TEST_PROBE_DATA: { - l_rx.var.tp.data |= - (static_cast(b) << l_rx.var.tp.idx); - l_rx.var.tp.idx += 8U; - if (l_rx.var.tp.idx == (8U * sizeof(std::uint32_t))) { - l_rx.var.tp.addr = 0U; - l_rx.var.tp.idx = 0U; + QP::QS::rxPriv_.var.tp.data |= + (static_cast(b) << QP::QS::rxPriv_.var.tp.idx); + QP::QS::rxPriv_.var.tp.idx += 8U; + if (QP::QS::rxPriv_.var.tp.idx == (8U * sizeof(std::uint32_t))) { + QP::QS::rxPriv_.var.tp.addr = 0U; + QP::QS::rxPriv_.var.tp.idx = 0U; tran_(WAIT4_TEST_PROBE_ADDR); } break; } case WAIT4_TEST_PROBE_ADDR: { - l_rx.var.tp.addr |= - (static_cast(b) << l_rx.var.tp.idx); - l_rx.var.tp.idx += 8U; - if (l_rx.var.tp.idx + QP::QS::rxPriv_.var.tp.addr |= + (static_cast(b) << QP::QS::rxPriv_.var.tp.idx); + QP::QS::rxPriv_.var.tp.idx += 8U; + if (QP::QS::rxPriv_.var.tp.idx == (8U * static_cast(QS_FUN_PTR_SIZE))) { tran_(WAIT4_TEST_PROBE_FRAME); @@ -820,11 +738,16 @@ static void rxParseData_(std::uint8_t const b) noexcept { void rxHandleGoodFrame_(std::uint8_t const state) { std::uint8_t i; std::uint8_t *ptr; + QS_CRIT_STAT switch (state) { case WAIT4_INFO_FRAME: { // no need to report Ack or Done + QS_CRIT_ENTRY(); + QS_MEM_SYS(); QP::QS::target_info_pre_(0U); // send only Target info + QS_MEM_APP(); + QS_CRIT_EXIT(); break; } case WAIT4_RESET_FRAME: { @@ -837,8 +760,8 @@ void rxHandleGoodFrame_(std::uint8_t const state) { case WAIT4_CMD_PARAM3: // intentionally fall-through case WAIT4_CMD_FRAME: { rxReportAck_(QP::QS_RX_COMMAND); - QP::QS::onCommand(l_rx.var.cmd.cmdId, l_rx.var.cmd.param1, - l_rx.var.cmd.param2, l_rx.var.cmd.param3); + QP::QS::onCommand(QP::QS::rxPriv_.var.cmd.cmdId, QP::QS::rxPriv_.var.cmd.param1, + QP::QS::rxPriv_.var.cmd.param2, QP::QS::rxPriv_.var.cmd.param3); #ifdef Q_UTEST #if Q_UTEST != 0 QP::QS::processTestEvts_(); // process all events produced @@ -851,14 +774,14 @@ void rxHandleGoodFrame_(std::uint8_t const state) { rxReportAck_(QP::QS_RX_TICK); #ifdef Q_UTEST QP::QTimeEvt::tick1_( - static_cast(l_rx.var.tick.rate), + static_cast(QP::QS::rxPriv_.var.tick.rate), &QP::QS::rxPriv_); #if Q_UTEST != 0 QP::QS::processTestEvts_(); // process all events produced #endif // Q_UTEST != 0 #else QP::QTimeEvt::tick( - static_cast(l_rx.var.tick.rate), + static_cast(QP::QS::rxPriv_.var.tick.rate), &QP::QS::rxPriv_); #endif // Q_UTEST rxReportDone_(QP::QS_RX_TICK); @@ -866,17 +789,19 @@ void rxHandleGoodFrame_(std::uint8_t const state) { } case WAIT4_PEEK_FRAME: { // no need to report Ack or Done + QS_CRIT_ENTRY(); + QS_MEM_SYS(); QP::QS::beginRec_(static_cast( QP::QS_PEEK_DATA)); ptr = static_cast( QP::QS::rxPriv_.currObj[QP::QS::AP_OBJ]); - ptr = &ptr[l_rx.var.peek.offs]; + ptr = &ptr[QP::QS::rxPriv_.var.peek.offs]; QS_TIME_PRE_(); // timestamp - QS_U16_PRE_(l_rx.var.peek.offs); // data offset - QS_U8_PRE_(l_rx.var.peek.size); // data size - QS_U8_PRE_(l_rx.var.peek.num); // number of data items - for (i = 0U; i < l_rx.var.peek.num; ++i) { - switch (l_rx.var.peek.size) { + QS_U16_PRE_(QP::QS::rxPriv_.var.peek.offs); // data offset + QS_U8_PRE_(QP::QS::rxPriv_.var.peek.size); // data size + QS_U8_PRE_(QP::QS::rxPriv_.var.peek.num); // number of data items + for (i = 0U; i < QP::QS::rxPriv_.var.peek.num; ++i) { + switch (QP::QS::rxPriv_.var.peek.size) { case 1: QS_U8_PRE_(ptr[i]); break; @@ -894,6 +819,8 @@ void rxHandleGoodFrame_(std::uint8_t const state) { } } QP::QS::endRec_(); + QS_MEM_APP(); + QS_CRIT_EXIT(); QS_REC_DONE(); // user callback (if defined) break; @@ -912,20 +839,20 @@ void rxHandleGoodFrame_(std::uint8_t const state) { rxReportAck_(QP::QS_RX_FILL); ptr = static_cast( QP::QS::rxPriv_.currObj[QP::QS::AP_OBJ]); - ptr = &ptr[l_rx.var.poke.offs]; - for (i = 0U; i < l_rx.var.poke.num; ++i) { - switch (l_rx.var.poke.size) { + ptr = &ptr[QP::QS::rxPriv_.var.poke.offs]; + for (i = 0U; i < QP::QS::rxPriv_.var.poke.num; ++i) { + switch (QP::QS::rxPriv_.var.poke.size) { case 1: ptr[i] = - static_cast(l_rx.var.poke.data); + static_cast(QP::QS::rxPriv_.var.poke.data); break; case 2: reinterpret_cast(ptr)[i] = - static_cast(l_rx.var.poke.data); + static_cast(QP::QS::rxPriv_.var.poke.data); break; case 4: reinterpret_cast(ptr)[i] = - l_rx.var.poke.data; + QP::QS::rxPriv_.var.poke.data; break; default: // intentionally empty @@ -936,17 +863,17 @@ void rxHandleGoodFrame_(std::uint8_t const state) { } case WAIT4_FILTER_FRAME: { rxReportAck_(static_cast( - l_rx.var.flt.recId)); + QP::QS::rxPriv_.var.flt.recId)); // apply the received filters - if (l_rx.var.flt.recId + if (QP::QS::rxPriv_.var.flt.recId == static_cast(QP::QS_RX_GLB_FILTER)) { for (i = 0U; i < static_cast(sizeof(QP::QS::filt_.glb)); ++i) { - QP::QS::filt_.glb[i] = l_rx.var.flt.data[i]; + QP::QS::filt_.glb[i] = QP::QS::rxPriv_.var.flt.data[i]; } // leave the "not maskable" filters enabled, // see qs.hpp, Miscellaneous QS records (not maskable) @@ -957,39 +884,39 @@ void rxHandleGoodFrame_(std::uint8_t const state) { // never enable the last 3 records (0x7D, 0x7E, 0x7F) QP::QS::filt_.glb[15] &= 0x1FU; } - else if (l_rx.var.flt.recId + else if (QP::QS::rxPriv_.var.flt.recId == static_cast(QP::QS_RX_LOC_FILTER)) { for (i = 0U; i < Q_DIM(QP::QS::filt_.loc); ++i) { - QP::QS::filt_.loc[i] = l_rx.var.flt.data[i]; + QP::QS::filt_.loc[i] = QP::QS::rxPriv_.var.flt.data[i]; } // leave QS_ID == 0 always on QP::QS::filt_.loc[0] |= 0x01U; } else { - rxReportError_(l_rx.var.flt.recId); + rxReportError_(QP::QS::rxPriv_.var.flt.recId); } // no need to report Done break; } case WAIT4_OBJ_FRAME: { - i = l_rx.var.obj.kind; + i = QP::QS::rxPriv_.var.obj.kind; if (i < static_cast(QP::QS::MAX_OBJ)) { - if (l_rx.var.obj.recId + if (QP::QS::rxPriv_.var.obj.recId == static_cast(QP::QS_RX_CURR_OBJ)) { QP::QS::rxPriv_.currObj[i] = - reinterpret_cast(l_rx.var.obj.addr); + reinterpret_cast(QP::QS::rxPriv_.var.obj.addr); rxReportAck_(QP::QS_RX_CURR_OBJ); } - else if (l_rx.var.obj.recId + else if (QP::QS::rxPriv_.var.obj.recId == static_cast(QP::QS_RX_AO_FILTER)) { - if (l_rx.var.obj.addr != 0U) { + if (QP::QS::rxPriv_.var.obj.addr != 0U) { std::int_fast16_t const filter = static_cast( reinterpret_cast( - l_rx.var.obj.addr)->getPrio()); + QP::QS::rxPriv_.var.obj.addr)->getPrio()); QP::QS::locFilter_((i == 0) ? filter :-filter); @@ -1001,92 +928,92 @@ void rxHandleGoodFrame_(std::uint8_t const state) { } } else { - rxReportError_(l_rx.var.obj.recId); + rxReportError_(QP::QS::rxPriv_.var.obj.recId); } } // both SM and AO else if (i == static_cast(QP::QS::SM_AO_OBJ)) { - if (l_rx.var.obj.recId + if (QP::QS::rxPriv_.var.obj.recId == static_cast(QP::QS_RX_CURR_OBJ)) { QP::QS::rxPriv_.currObj[QP::QS::SM_OBJ] - = reinterpret_cast(l_rx.var.obj.addr); + = reinterpret_cast(QP::QS::rxPriv_.var.obj.addr); QP::QS::rxPriv_.currObj[QP::QS::AO_OBJ] - = reinterpret_cast(l_rx.var.obj.addr); + = reinterpret_cast(QP::QS::rxPriv_.var.obj.addr); } rxReportAck_( - static_cast(l_rx.var.obj.recId)); + static_cast(QP::QS::rxPriv_.var.obj.recId)); } else { - rxReportError_(l_rx.var.obj.recId); + rxReportError_(QP::QS::rxPriv_.var.obj.recId); } break; } case WAIT4_QUERY_FRAME: { - queryCurrObj_(l_rx.var.obj.kind); + queryCurrObj_(QP::QS::rxPriv_.var.obj.kind); break; } case WAIT4_EVT_FRAME: { // NOTE: Ack was already reported in the WAIT4_EVT_LEN state #ifdef Q_UTEST - QP::QS::onTestEvt(l_rx.var.evt.e); // "massage" the event + QP::QS::onTestEvt(QP::QS::rxPriv_.var.evt.e); // "massage" the event #endif // Q_UTEST // use 'i' as status, 0 == success,no-recycle i = 0U; - if (l_rx.var.evt.prio == 0U) { // publish - QP::QActive::publish_(l_rx.var.evt.e, &QP::QS::rxPriv_, 0U); + if (QP::QS::rxPriv_.var.evt.prio == 0U) { // publish + QP::QActive::publish_(QP::QS::rxPriv_.var.evt.e, &QP::QS::rxPriv_, 0U); } - else if (l_rx.var.evt.prio < QF_MAX_ACTIVE) { - if (!QP::QActive::registry_[l_rx.var.evt.prio]->POST_X( - l_rx.var.evt.e, + else if (QP::QS::rxPriv_.var.evt.prio < QF_MAX_ACTIVE) { + if (!QP::QActive::registry_[QP::QS::rxPriv_.var.evt.prio]->POST_X( + QP::QS::rxPriv_.var.evt.e, 0U, // margin &QP::QS::rxPriv_)) { // failed QACTIVE_POST() recycles the event - i = 0x80U; // failure, no recycle + i = 0x80U; // failure status, no recycle } } - else if (l_rx.var.evt.prio == 255U) { + else if (QP::QS::rxPriv_.var.evt.prio == 255U) { // dispatch to the current SM object if (QP::QS::rxPriv_.currObj[QP::QS::SM_OBJ] != nullptr) { // increment the ref-ctr to simulate the situation // when the event is just retrieved from a queue. // This is expected for the following QF::gc() call. - QP::QEvt_refCtr_inc_(l_rx.var.evt.e); + QP::QEvt_refCtr_inc_(QP::QS::rxPriv_.var.evt.e); static_cast( QP::QS::rxPriv_.currObj[QP::QS::SM_OBJ]) - ->dispatch(l_rx.var.evt.e, 0U); + ->dispatch(QP::QS::rxPriv_.var.evt.e, 0U); i = 0x01U; // success, recycle } else { i = 0x81U; // failure, recycle } } - else if (l_rx.var.evt.prio == 254U) { + else if (QP::QS::rxPriv_.var.evt.prio == 254U) { // init the current SM object" if (QP::QS::rxPriv_.currObj[QP::QS::SM_OBJ] != nullptr) { // increment the ref-ctr to simulate the situation // when the event is just retrieved from a queue. // This is expected for the following QF::gc() call. - QP::QEvt_refCtr_inc_(l_rx.var.evt.e); + QP::QEvt_refCtr_inc_(QP::QS::rxPriv_.var.evt.e); static_cast( QP::QS::rxPriv_.currObj[QP::QS::SM_OBJ]) - ->init(l_rx.var.evt.e, 0U); + ->init(QP::QS::rxPriv_.var.evt.e, 0U); i = 0x01U; // success, recycle } else { i = 0x81U; // failure, recycle } } - else if (l_rx.var.evt.prio == 253U) { + else if (QP::QS::rxPriv_.var.evt.prio == 253U) { // post to the current AO if (QP::QS::rxPriv_.currObj[QP::QS::AO_OBJ] != nullptr) { if (!static_cast( QP::QS::rxPriv_.currObj[QP::QS::AO_OBJ])->POST_X( - l_rx.var.evt.e, + QP::QS::rxPriv_.var.evt.e, 0U, // margin &QP::QS::rxPriv_)) { @@ -1105,7 +1032,7 @@ void rxHandleGoodFrame_(std::uint8_t const state) { #if (QF_MAX_EPOOL > 0U) // recycle needed? if ((i & 1U) != 0U) { - QP::QF::gc(l_rx.var.evt.e); + QP::QF::gc(QP::QS::rxPriv_.var.evt.e); } #endif // failure? @@ -1151,7 +1078,7 @@ void rxHandleGoodFrame_(std::uint8_t const state) { QP::QS::tstPriv_.tpNum < (sizeof(QP::QS::tstPriv_.tpBuf) / sizeof(QP::QS::tstPriv_.tpBuf[0]))); - QP::QS::tstPriv_.tpBuf[QP::QS::tstPriv_.tpNum] = l_rx.var.tp; + QP::QS::tstPriv_.tpBuf[QP::QS::tstPriv_.tpNum] = QP::QS::rxPriv_.var.tp; ++QP::QS::tstPriv_.tpNum; // no need to report Done break; @@ -1174,9 +1101,12 @@ static void rxHandleBadFrame_(std::uint8_t const state) noexcept { rxReportError_(0x50U); // error for all bad frames switch (state) { case WAIT4_EVT_FRAME: { - Q_ASSERT_INCRIT(910, l_rx.var.evt.e != nullptr); + QS_CRIT_STAT + QS_CRIT_ENTRY(); + Q_ASSERT_INCRIT(910, QP::QS::rxPriv_.var.evt.e != nullptr); + QS_CRIT_EXIT(); #if (QF_MAX_EPOOL > 0U) - QP::QF::gc(l_rx.var.evt.e); // don't leak an allocated event + QP::QF::gc(QP::QS::rxPriv_.var.evt.e); // don't leak allocated evt #endif break; } @@ -1189,34 +1119,54 @@ static void rxHandleBadFrame_(std::uint8_t const state) noexcept { //............................................................................ static void rxReportAck_(enum QP::QSpyRxRecords const recId) noexcept { + QS_CRIT_STAT + QS_CRIT_ENTRY(); + QS_MEM_SYS(); QP::QS::beginRec_(static_cast(QP::QS_RX_STATUS)); QS_U8_PRE_(recId); // record ID QP::QS::endRec_(); + QS_MEM_APP(); + QS_CRIT_EXIT(); QS_REC_DONE(); // user callback (if defined) } //............................................................................ static void rxReportError_(std::uint8_t const code) noexcept { + QS_CRIT_STAT + QS_CRIT_ENTRY(); + QS_MEM_SYS(); QP::QS::beginRec_(static_cast(QP::QS_RX_STATUS)); QS_U8_PRE_(0x80U | code); // error code QP::QS::endRec_(); + QS_MEM_APP(); + QS_CRIT_EXIT(); QS_REC_DONE(); // user callback (if defined) } //............................................................................ static void rxReportDone_(enum QP::QSpyRxRecords const recId) noexcept { + QS_CRIT_STAT + QS_CRIT_ENTRY(); + QS_MEM_SYS(); QP::QS::beginRec_(static_cast(QP::QS_TARGET_DONE)); QS_TIME_PRE_(); // timestamp QS_U8_PRE_(recId); // record ID QP::QS::endRec_(); + QS_MEM_APP(); + QS_CRIT_EXIT(); QS_REC_DONE(); // user callback (if defined) } //............................................................................ static void queryCurrObj_(std::uint8_t obj_kind) noexcept { - Q_REQUIRE_INCRIT(200, obj_kind < Q_DIM(QP::QS::rxPriv_.currObj)); + QS_CRIT_STAT + QS_CRIT_ENTRY(); + Q_REQUIRE_INCRIT(800, obj_kind < Q_DIM(QP::QS::rxPriv_.currObj)); + QS_CRIT_EXIT(); if (QP::QS::rxPriv_.currObj[obj_kind] != nullptr) { + QS_CRIT_ENTRY(); + QS_MEM_SYS(); QP::QS::beginRec_(static_cast(QP::QS_QUERY_DATA)); QS_TIME_PRE_(); // timestamp QS_U8_PRE_(obj_kind); // object kind @@ -1256,6 +1206,8 @@ static void queryCurrObj_(std::uint8_t obj_kind) noexcept { break; } QP::QS::endRec_(); + QS_MEM_APP(); + QS_CRIT_EXIT(); QS_REC_DONE(); // user callback (if defined) } else { @@ -1267,26 +1219,26 @@ static void queryCurrObj_(std::uint8_t obj_kind) noexcept { static void rxPoke_() noexcept { std::uint8_t * ptr = static_cast(QP::QS::rxPriv_.currObj[QP::QS::AP_OBJ]); - ptr = &ptr[l_rx.var.poke.offs]; - switch (l_rx.var.poke.size) { + ptr = &ptr[QP::QS::rxPriv_.var.poke.offs]; + switch (QP::QS::rxPriv_.var.poke.size) { case 1: - *ptr = static_cast(l_rx.var.poke.data); + *ptr = static_cast(QP::QS::rxPriv_.var.poke.data); break; case 2: *reinterpret_cast(ptr) - = static_cast(l_rx.var.poke.data); + = static_cast(QP::QS::rxPriv_.var.poke.data); break; case 4: - *reinterpret_cast(ptr) = l_rx.var.poke.data; + *reinterpret_cast(ptr) = QP::QS::rxPriv_.var.poke.data; break; default: Q_ERROR_ID(900); break; } - l_rx.var.poke.data = 0U; - l_rx.var.poke.idx = 0U; - l_rx.var.poke.offs += static_cast(l_rx.var.poke.size); + QP::QS::rxPriv_.var.poke.data = 0U; + QP::QS::rxPriv_.var.poke.idx = 0U; + QP::QS::rxPriv_.var.poke.offs += static_cast(QP::QS::rxPriv_.var.poke.size); } } // unnamed namespace