diff --git a/3rd_party b/3rd_party index db8b6155..054cd1ab 160000 --- a/3rd_party +++ b/3rd_party @@ -1 +1 @@ -Subproject commit db8b6155e6931d2c55315dfd55b0e1fac0f96e33 +Subproject commit 054cd1abe4b4abef5e45f36b1ce8f2aff4575494 diff --git a/README.md b/README.md index 0ae412f2..309bcb21 100644 --- a/README.md +++ b/README.md @@ -13,16 +13,16 @@ it is recommended that you clone this repo like that: git clone https://github.com/QuantumLeaps/qpc --recurse-submodules --depth 1 ``` -Alternatively, you can also download the latest -[QP/C Release](https://github.com/QuantumLeaps/qpc/releases). +Alternatively, you can also download one of the stable +[QP/C Releases][QP-Rel]. # Getting Started with QP/C The most recommended way of obtaining QP/C is by downloading the [QP-bundle](https://www.state-machine.com/#Downloads), which includes QP/C -as well as the QM modeling tool and the QTools collection. The main advantage of -obtaining QP/C bundled together like that is that you get all components, -tools and examples ready to go. +as well as the [QM modeling tool][QM] and the [QTools collection][QTools]. +The main advantage of obtaining QP/C bundled together like that is +that you get all components, tools and examples ready to go. ### Getting Started Resources - ["QP/C Tutorial"][Tutorial] @@ -34,82 +34,96 @@ provides instructions on how to download, install, and get started with QP. - [AppNote: "Getting Started with QP Real-Time Embedded Frameworks"][AN] contains also a tutorial, in which you build a simple "Blinky" application. +## Licensing +The QP frameworks (QP/C and QP/C++) are licensed under the +[dual licensing model](https://www.state-machine.com/licensing), with +the following licensing options: + +1. [Open-source licensing](https://www.state-machine.com/licensing#Open) under the +[GNU General Public License (GPLv3)](https://www.gnu.org/licenses/gpl-3.0.en.html). + +> NOTE: GPL requires that all modifications to the original code +as well as your application code (Derivative Works as defined in the +Copyright Law) must also be released under the terms of the GPL +open source license. + +2. [Closed-source licensing](https://www.state-machine.com/licensing#Closed) under one of +[Quantum Leaps commercial licenses](https://www.state-machine.com/licensing#Commercial), +which are specifically designed for users interested in retaining the +proprietary status of their code. + +> NOTE: If your company has a policy forbidding open source in your product, +all QP frameworks can be licensed commercially, in which case you don't use +any open source license and you do not violate your policy. + # About QP/C QP/C (Quantum Platform in C) is a lightweight, open source [Real-Time Embedded Framework (RTEF)][RTEF] for building modern embedded -software as systems of asynchronous, event-driven [active objects][Active] +software as systems of asynchronous, event-driven [Active Objects][Active] (actors). The [QP/C] framework is a member of a [QP] family consisting of [QP/C] and [QP/C++] frameworks, which are strictly quality controlled, thoroughly documented, and [commercially licensable][Lic]. ## Safer Model of Concurrency -The [QP] framework family is based on the [Active Object][Active] (**actor**) -design pattern, which inherently supports and automatically enforces the -following best practices of concurrent programming: +The [QP] framework family implements the +[Active Object model of computation][AO_model], which is **inherently safer** +than the traditional "shared state concurrency" based on explicit mutual +exclusion and managing RTOS threads by blocking. The Active Object model +supports and automatically enforces the following best practices +of concurrent programming: -- Keep data isolated and bound to active objects' threads. Threads should +- Keep data isolated and bound to Active Objects' threads. Threads should hide (**encapsulate**) their private data and other resources, and not share them with the rest of the system. -- Communicate among active object threads **asynchronously** via event -objects. Using asynchronous events keeps the threads running truly +- Communicate among Active Object threads **asynchronously** via [Event +objects][Event]. Using asynchronous events keeps the threads running truly independently, **without blocking** on each other. -- Active object threads should spend their lifetime responding to incoming +- Active Object threads should spend their lifetime responding to incoming events, so their mainline should consist of an **event-loop** that handles events one at a time (to completion), thus avoiding any concurrency hazards -within an active object thread itself. +within an Active Object thread itself. -This architecture is generally **safer**, more responsive and easier to -understand and maintain than the shared-state concurrency of a conventional -RTOS. It also provides higher level of abstraction and the *correct* -abstractions to effectively apply **modeling** and **code generation** to -deeply embedded real-time systems. +This architecture also provides higher level of abstraction and the *correct* +abstractions to effectively apply [Hierarchical State Machines][HSM], +**modeling** and **code generation** to deeply embedded real-time systems. ## Hierarchical State Machines -The behavior of active objects is specified in QP/C by means of +The behavior of Active Objects is specified in QP/C by means of [Hierarchical State Machines][HSM] (UML statecharts). The framework supports manual coding of UML state machines in C as well as automatic **code generation** by means of the free [QM modeling tool][QM]. ## Built-in Real-Time Kernels -The QP/C framework can run on bare-metal single-chip microcontrollers, -completely replacing a traditional RTOS. The framework contains a selection -of **built-in real-time kernels**, such as the cooperative QV kernel, the -preemptive non-blocking QK kernel, and the preemptive, blocking QXK kernel -that provides all the features you might expect from a traditional RTOS. -Native QP ports and ready-to-use examples are provided for major CPUs, such -as ARM Cortex-M (M0/M0+/M3/M4/M7). +The QP/C framework can run on standalone on single-chip microcontrollers, +without any traditional RTOS. The framework contains a selection of +**built-in real-time kernels**, such as the [non-preemptive QV kernel][QV], +the [preemptive non-blocking QK kernel][QK], and the preemptive, +[dual-mode QXK kernel][QXK] that provides all the features you might expect +from a traditional RTOS. Native QP ports and ready-to-use examples are provided +for major CPUs, such as ARM Cortex-M (M0/M0+/M3/M4/M7/M23/M33/M85). ## Traditional RTOS/OS -QP/C can also work with a traditional RTOS, such as ThreadX, FreeRTOS, embOS, -uC/OS-II and TI-RTOS, as well as with (embedded) Linux (POSIX) and Windows. +QP/C can also work with a traditional RTOS, such as ThreadX, embOS, FreeRTOS, +uC/OS-II and Zephyr, as well as with (embedded) Linux (POSIX) and Windows. ## Popularity and Maturity -With 20 years of continuous development, over [350 commercial licensees][Cust], -and many times more open source users worldwide, the QP™ frameworks are the +With 20 years of continuous development, [400+ commercial licensees][Cust], +and many times more open source users worldwide, the QP frameworks are the most popular such offering on the market. They power countless electronic products ranging from implantable medical devices to complex weapon systems. -# QP/C Licensing -QP/C is licensed under the sustainable [dual licensing model][Lic], -in which both the open source software distribution mechanism and -traditional closed source software distribution models are combined. - -> **NOTE:** If your company has a policy forbidding open source in your -product, all QP frameworks can be [licensed commercially][Lic], in which case -you don't use any open source license and you do not violate your policy. - - # QP/C Documentation The online HTML documentation for the **latest** version of QP/C is located at: https://www.state-machine.com/qpc The offline HTML documentation for **this** particular version of QP/C -is located in the sub-folder [html](html). To view the offline documentation, -open the file [html/index.html](html/index.html) in your web browser. +is located in the sub-folder [html](html) (included in the [QP/C releases][QP-Rel]). +To view the offline documentation, open the file [html/index.html](html/index.html) +in your web browser. # How to Get Help? @@ -126,16 +140,19 @@ If you like this project, please give it a star (in the upper-right corner of yo ![GitHub star](https://www.state-machine.com/img/github-star.jpg) - - [RTEF]: - [QP]: - [QP/C]: - [QP/C++]: - [QM]: - [Active]: - [HSM]: - [Lic]: - [Cust]: - [AN]: + [RTEF]: + [QP]: + [QP/C]: + [QP/C++]: + [QM]: + [QTools]: + [QP-Rel]: + [Active]: + [AO_model]: + [Event]: + [HSM]: + [Lic]: + [Cust]: + [AN]: [Tutorial]: - [Video]: + [Video]: diff --git a/examples b/examples index 5b4edf6f..5e7c7e64 160000 --- a/examples +++ b/examples @@ -1 +1 @@ -Subproject commit 5b4edf6f7a1514169427fa42522d823fb31ee37c +Subproject commit 5e7c7e64d3a6b1c3fde11cb03252bfb37bbf1149 diff --git a/include/qp.h b/include/qp.h index 4b9e51c3..1540502b 100644 --- a/include/qp.h +++ b/include/qp.h @@ -44,11 +44,9 @@ #define QP_H_ //============================================================================ -#define QP_VERSION 733U -#define QP_VERSION_STR "7.3.3" - -//! Encrypted current QP release (7.3.3) and date (2024-03-01) -#define QP_RELEASE 0x70C4F752U +#define QP_VERSION_STR "7.3.5-rc.1" +#define QP_VERSION 735U +#define QP_RELEASE 0x70A1DEF0U //============================================================================ //! @cond INTERNAL @@ -117,9 +115,9 @@ typedef double float64_t; //$declare${QEP} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -//${QEP::QP_versionStr[8]} ................................................... +//${QEP::QP_versionStr[16]} .................................................. //! the current QP version number string in ROM, based on #QP_VERSION_STR -extern char const QP_versionStr[8]; +extern char const QP_versionStr[16]; //${QEP::QSignal} ............................................................ #if (Q_SIGNAL_SIZE == 1U) diff --git a/include/qpc.h b/include/qpc.h index 8349cd04..f9d7c1b5 100644 --- a/include/qpc.h +++ b/include/qpc.h @@ -43,10 +43,6 @@ #ifndef QPC_H_ #define QPC_H_ -#ifdef __cplusplus -extern "C" { -#endif - //============================================================================ #include "qp_port.h" // QP port from the port directory #include "qsafe.h" // QP Functional Safety (FuSa) Subsystem @@ -205,8 +201,4 @@ static inline void QF_psInit( #endif // QP_API_VERSION < 691 #endif // QP_API_VERSION < 700 -#ifdef __cplusplus -} -#endif - #endif // QPC_H_ diff --git a/include/qsafe.h b/include/qsafe.h index 0540a96b..43e772ac 100644 --- a/include/qsafe.h +++ b/include/qsafe.h @@ -150,6 +150,9 @@ extern "C" { //${QP-FuSa::Q_INVARIANT} .................................................... #define Q_INVARIANT(expr_) Q_ASSERT(expr_) +//${QP-FuSa::Q_INVARIANT_INCRIT} ............................................. +#define Q_INVARIANT_INCRIT(id_, expr_) Q_ASSERT_INCRIT((id_), (expr_)) + //${QP-FuSa::Q_ASSERT_STATIC} ................................................ #define Q_ASSERT_STATIC(expr_) extern char Q_static_assert_[(expr_) ? 1 : -1] diff --git a/ports/arm-cm/qxk/armclang/qxk_port.c b/ports/arm-cm/qxk/armclang/qxk_port.c index e5e308eb..f602b0fd 100644 --- a/ports/arm-cm/qxk/armclang/qxk_port.c +++ b/ports/arm-cm/qxk/armclang/qxk_port.c @@ -27,8 +27,8 @@ // // //============================================================================ -//! @date Last updated on: 2023-12-04 -//! @version Last updated for: @ref qpc_7_3_1 +//! @date Last updated on: 2024-05-28 +//! @version Last updated for: @ref qpc_7_3_5 //! //! @file //! @brief QXK/C port to ARM Cortex-M, ARM-CLANG @@ -376,10 +376,10 @@ __asm volatile ( " MOVS r1,#1 \n" " LSLS r1,r1,#27 \n" // r1 := (1 << 27) (UNPENDSVSET bit) " LDR r2,=" STRINGIFY(SCB_ICSR) "\n" // Interrupt Control and State - " STR r1,[r2] \n" // ICSR[27] := 1 (unpend PendSV) + " STR r1,[r2] \n" // ICSR[27] := 1 (un-pend PendSV) // Check QXK_priv_.next, which contains the pointer to the next thread - // to run, which is set in QXK_ISR_EXIT(). This pointer must not be NULL. + // to run, which is set in QXK_ISR_EXIT(). Return if QXK_priv_.next == 0 " LDR r3,=QXK_priv_ \n" " LDR r0,[r3,#" STRINGIFY(QXK_NEXT) "]\n" // r1 := QXK_priv_.next " CMP r0,#0 \n" // is (QXK_priv_.next == 0)? @@ -489,7 +489,7 @@ __asm volatile ( " MOV lr,r2 \n" // make sure MSP is used #else // ARMv7-M or higher #ifdef __ARM_FP //--------- if VFP available... - " POP {r0,lr} \n" // restore alighner and EXC_RETURN into lr + " POP {r0,lr} \n" // restore aligner and EXC_RETURN into lr " DSB \n" // ARM Erratum 838869 " TST lr,#(1 << 4) \n" // is it return to the VFP exception frame? " IT EQ \n" // if EXC_RETURN[4] is zero... @@ -508,19 +508,18 @@ __asm volatile ( " BCC PendSV_activate \n" // if (next->prio > actPrio) activate the next AO // otherwise no activation needed... - " MOVS r0,#0 \n" - " STR r0,[r3,#" STRINGIFY(QXK_CURR) "]\n" // QXK_priv_.curr := 0 - " STR r0,[r3,#" STRINGIFY(QXK_NEXT) "]\n" // QXK_priv_.next := 0 + " MOVS r2,#0 \n" + " STR r2,[r3,#" STRINGIFY(QXK_CURR) "]\n" // QXK_priv_.curr := 0 + " STR r2,[r3,#" STRINGIFY(QXK_NEXT) "]\n" // QXK_priv_.next := 0 " PUSH {r0,lr} \n" // save the aligner + EXC_RETURN #if defined(Q_SPY) || defined(QF_ON_CONTEXT_SW) - // r0 is still 0 (parameter next) for QXK_contextSw_() + " CMP r0,#0 \n" // r0 == QXK_priv_.next->prio + " BEQ PendSV_idle \n" // if (QXK_priv_.next->prio != 0) + " MOV r0,r12 \n" // r0 := parameter 'next' for QXK_contextSw_() + "PendSV_idle: \n" " LDR r3,=QXK_contextSw_ \n" " BLX r3 \n" // call QXK_contextSw_() -#ifdef QF_MEM_ISOLATE - " LDR r3,=QF_onMemApp \n" - " BLX r3 \n" // call QF_onMemApp() -#endif #endif // defined(Q_SPY) || defined(QF_ON_CONTEXT_SW) " B PendSV_return1 \n" // skip over saving aligner + EXC_RETURN @@ -529,6 +528,10 @@ __asm volatile ( " PUSH {r0,lr} \n" // save the aligner + EXC_RETURN "PendSV_return1: \n" +#ifdef QF_MEM_ISOLATE + " LDR r3,=QF_onMemApp \n" + " BLX r3 \n" // call QF_onMemApp() +#endif " LDR r0,=QF_int_enable_ \n" " BLX r0 \n" // call QF_int_enable_() //>>>>>>>>>>>>>>>>>>>>>>>> CRITICAL SECTION END >>>>>>>>>>>>>>>>>>>>>>>>> @@ -591,7 +594,7 @@ __asm volatile ( " PUSH {r0-r2,lr} \n" // save next, osObject, EXC_RETURN #if defined(Q_SPY) || defined(QF_ON_CONTEXT_SW) - " MOV r0,r12 \n" // parameter next + " MOV r0,r12 \n" // r0 := parameter 'next' for QXK_contextSw_() " LDR r3,=QXK_contextSw_ \n" " BLX r3 \n" // call QXK_contextSw_() #ifdef QF_MEM_ISOLATE @@ -744,7 +747,7 @@ __asm volatile ( " ADD sp,sp,#(8*4) \n" // remove one 8-register exception frame #ifdef __ARM_FP //--------- if VFP available... - " POP {r0,lr} \n" // restore alighner and EXC_RETURN into lr + " POP {r0,lr} \n" // restore aligher and EXC_RETURN into lr " DSB \n" // ARM Erratum 838869 " TST lr,#(1 << 4) \n" // is it return to the VFP exception frame? " IT EQ \n" // if EXC_RETURN[4] is zero... diff --git a/ports/arm-cm/qxk/gnu/qxk_port.c b/ports/arm-cm/qxk/gnu/qxk_port.c index c7638291..9152d9ff 100644 --- a/ports/arm-cm/qxk/gnu/qxk_port.c +++ b/ports/arm-cm/qxk/gnu/qxk_port.c @@ -27,8 +27,8 @@ // // //============================================================================ -//! @date Last updated on: 2024-01-30 -//! @version Last updated for: @ref qpc_7_3_3 +//! @date Last updated on: 2024-05-28 +//! @version Last updated for: @ref qpc_7_3_5 //! //! @file //! @brief QXK/C port to ARM Cortex-M, GNU-ARM @@ -381,10 +381,10 @@ __asm volatile ( " MOV r1,#1 \n" " LSL r1,r1,#27 \n" // r1 := (1 << 27) (UNPENDSVSET bit) " LDR r2,=" STRINGIFY(SCB_ICSR) "\n" // Interrupt Control and State - " STR r1,[r2] \n" // ICSR[27] := 1 (unpend PendSV) + " STR r1,[r2] \n" // ICSR[27] := 1 (un-pend PendSV) // Check QXK_priv_.next, which contains the pointer to the next thread - // to run, which is set in QXK_ISR_EXIT(). This pointer must not be NULL. + // to run, which is set in QXK_ISR_EXIT(). Return if QXK_priv_.next == 0 " LDR r3,=QXK_priv_ \n" " LDR r0,[r3,#" STRINGIFY(QXK_NEXT) "]\n" // r1 := QXK_priv_.next " CMP r0,#0 \n" // is (QXK_priv_.next == 0)? @@ -494,7 +494,7 @@ __asm volatile ( " MOV lr,r2 \n" // make sure MSP is used #else // ARMv7-M or higher #ifdef __ARM_FP //--------- if VFP available... - " POP {r0,lr} \n" // restore alighner and EXC_RETURN into lr + " POP {r0,lr} \n" // restore aligner and EXC_RETURN into lr " DSB \n" // ARM Erratum 838869 " TST lr,#(1 << 4) \n" // is it return to the VFP exception frame? " IT EQ \n" // if EXC_RETURN[4] is zero... @@ -513,19 +513,18 @@ __asm volatile ( " BCC PendSV_activate \n" // if (next->prio > actPrio) activate the next AO // otherwise no activation needed... - " MOV r0,#0 \n" - " STR r0,[r3,#" STRINGIFY(QXK_CURR) "]\n" // QXK_priv_.curr := 0 - " STR r0,[r3,#" STRINGIFY(QXK_NEXT) "]\n" // QXK_priv_.next := 0 + " MOV r2,#0 \n" + " STR r2,[r3,#" STRINGIFY(QXK_CURR) "]\n" // QXK_priv_.curr := 0 + " STR r2,[r3,#" STRINGIFY(QXK_NEXT) "]\n" // QXK_priv_.next := 0 " PUSH {r0,lr} \n" // save the aligner + EXC_RETURN #if defined(Q_SPY) || defined(QF_ON_CONTEXT_SW) - // r0 is still 0 (parameter next) for QXK_contextSw_() + " CMP r0,#0 \n" // r0 == QXK_priv_.next->prio + " BEQ PendSV_idle \n" // if (QXK_priv_.next->prio != 0) + " MOV r0,r12 \n" // r0 := parameter 'next' for QXK_contextSw_() + "PendSV_idle: \n" " LDR r3,=QXK_contextSw_ \n" " BLX r3 \n" // call QXK_contextSw_() -#ifdef QF_MEM_ISOLATE - " LDR r3,=QF_onMemApp \n" - " BLX r3 \n" // call QF_onMemApp() -#endif #endif // defined(Q_SPY) || defined(QF_ON_CONTEXT_SW) " B PendSV_return1 \n" // skip over saving aligner + EXC_RETURN @@ -534,6 +533,10 @@ __asm volatile ( " PUSH {r0,lr} \n" // save the aligner + EXC_RETURN "PendSV_return1: \n" +#ifdef QF_MEM_ISOLATE + " LDR r3,=QF_onMemApp \n" + " BLX r3 \n" // call QF_onMemApp() +#endif " LDR r0,=QF_int_enable_ \n" " BLX r0 \n" // call QF_int_enable_() //>>>>>>>>>>>>>>>>>>>>>>>> CRITICAL SECTION END >>>>>>>>>>>>>>>>>>>>>>>>> @@ -596,7 +599,7 @@ __asm volatile ( " PUSH {r0-r2,lr} \n" // save next, osObject, EXC_RETURN #if defined(Q_SPY) || defined(QF_ON_CONTEXT_SW) - " MOV r0,r12 \n" // parameter next + " MOV r0,r12 \n" // r0 := parameter 'next' for QXK_contextSw_() " LDR r3,=QXK_contextSw_ \n" " BLX r3 \n" // call QXK_contextSw_() #ifdef QF_MEM_ISOLATE @@ -749,7 +752,7 @@ __asm volatile ( " ADD sp,sp,#(8*4) \n" // remove one 8-register exception frame #ifdef __ARM_FP //--------- if VFP available... - " POP {r0,lr} \n" // restore alighner and EXC_RETURN into lr + " POP {r0,lr} \n" // restore aligher and EXC_RETURN into lr " DSB \n" // ARM Erratum 838869 " TST lr,#(1 << 4) \n" // is it return to the VFP exception frame? " IT EQ \n" // if EXC_RETURN[4] is zero... diff --git a/ports/arm-cm/qxk/iar/qxk_port.c b/ports/arm-cm/qxk/iar/qxk_port.c index 207fdc16..71473d98 100644 --- a/ports/arm-cm/qxk/iar/qxk_port.c +++ b/ports/arm-cm/qxk/iar/qxk_port.c @@ -27,8 +27,8 @@ // // //============================================================================ -//! @date Last updated on: 2023-12-10 -//! @version Last updated for: @ref qpc_7_3_1 +//! @date Last updated on: 2024-05-28 +//! @version Last updated for: @ref qpc_7_3_5 //! //! @file //! @brief QXK/C port to ARM Cortex-M, IAR-ARM @@ -48,11 +48,11 @@ // make sure that the offsets match the QXK declaration in "qxk.h" _Static_assert(QXK_CURR == offsetof(QXK_Attr, curr), - "QXK_Attr.curr at unexpected offset"); + "QXK_Attr.curr at unexpected offset"); _Static_assert(QXK_NEXT == offsetof(QXK_Attr, next), - "QXK_Attr.next at unexpected offset"); + "QXK_Attr.next at unexpected offset"); _Static_assert(QXK_ACT_PRIO == offsetof(QXK_Attr, actPrio), - "QXK_Attr.actPrio at unexpected offset"); + "QXK_Attr.actPrio at unexpected offset"); // offsets within struct QActive; NOTE: keep in synch with "qp.h" !!! #define QACTIVE_PRIO 12 @@ -380,10 +380,10 @@ __asm volatile ( " MOVS r1,#1 \n" " LSLS r1,r1,#27 \n" // r1 := (1 << 27) (UNPENDSVSET bit) " LDR r2,=" STRINGIFY(SCB_ICSR) "\n" // Interrupt Control and State - " STR r1,[r2] \n" // ICSR[27] := 1 (unpend PendSV) + " STR r1,[r2] \n" // ICSR[27] := 1 (un-pend PendSV) // Check QXK_priv_.next, which contains the pointer to the next thread - // to run, which is set in QXK_ISR_EXIT(). This pointer must not be NULL. + // to run, which is set in QXK_ISR_EXIT(). Return if QXK_priv_.next == 0 " LDR r3,=QXK_priv_ \n" " LDR r0,[r3,#" STRINGIFY(QXK_NEXT) "]\n" // r1 := QXK_priv_.next " CMP r0,#0 \n" // is (QXK_priv_.next == 0)? @@ -493,7 +493,7 @@ __asm volatile ( " MOV lr,r2 \n" // make sure MSP is used #else // ARMv7-M or higher #ifdef __ARM_FP //--------- if VFP available... - " POP {r0,lr} \n" // restore alighner and EXC_RETURN into lr + " POP {r0,lr} \n" // restore aligner and EXC_RETURN into lr " DSB \n" // ARM Erratum 838869 " TST lr,#(1 << 4) \n" // is it return to the VFP exception frame? " IT EQ \n" // if EXC_RETURN[4] is zero... @@ -512,19 +512,18 @@ __asm volatile ( " BCC PendSV_activate \n" // if (next->prio > actPrio) activate the next AO // otherwise no activation needed... - " MOVS r0,#0 \n" - " STR r0,[r3,#" STRINGIFY(QXK_CURR) "]\n" // QXK_priv_.curr := 0 - " STR r0,[r3,#" STRINGIFY(QXK_NEXT) "]\n" // QXK_priv_.next := 0 + " MOVS r2,#0 \n" + " STR r2,[r3,#" STRINGIFY(QXK_CURR) "]\n" // QXK_priv_.curr := 0 + " STR r2,[r3,#" STRINGIFY(QXK_NEXT) "]\n" // QXK_priv_.next := 0 " PUSH {r0,lr} \n" // save the aligner + EXC_RETURN #if defined(Q_SPY) || defined(QF_ON_CONTEXT_SW) - // r0 is still 0 (parameter next) for QXK_contextSw_() + " CMP r0,#0 \n" // r0 == QXK_priv_.next->prio + " BEQ PendSV_idle \n" // if (QXK_priv_.next->prio != 0) + " MOV r0,r12 \n" // r0 := parameter 'next' for QXK_contextSw_() + "PendSV_idle: \n" " LDR r3,=QXK_contextSw_ \n" " BLX r3 \n" // call QXK_contextSw_() -#ifdef QF_MEM_ISOLATE - " LDR r3,=QF_onMemApp \n" - " BLX r3 \n" // call QF_onMemApp() -#endif #endif // defined(Q_SPY) || defined(QF_ON_CONTEXT_SW) " B PendSV_return1 \n" // skip over saving aligner + EXC_RETURN @@ -533,6 +532,10 @@ __asm volatile ( " PUSH {r0,lr} \n" // save the aligner + EXC_RETURN "PendSV_return1: \n" +#ifdef QF_MEM_ISOLATE + " LDR r3,=QF_onMemApp \n" + " BLX r3 \n" // call QF_onMemApp() +#endif " LDR r0,=QF_int_enable_ \n" " BLX r0 \n" // call QF_int_enable_() //>>>>>>>>>>>>>>>>>>>>>>>> CRITICAL SECTION END >>>>>>>>>>>>>>>>>>>>>>>>> @@ -595,7 +598,7 @@ __asm volatile ( " PUSH {r0-r2,lr} \n" // save next, osObject, EXC_RETURN #if defined(Q_SPY) || defined(QF_ON_CONTEXT_SW) - " MOV r0,r12 \n" // parameter next + " MOV r0,r12 \n" // r0 := parameter 'next' for QXK_contextSw_() " LDR r3,=QXK_contextSw_ \n" " BLX r3 \n" // call QXK_contextSw_() #ifdef QF_MEM_ISOLATE @@ -748,7 +751,7 @@ __asm volatile ( " ADD sp,sp,#(8*4) \n" // remove one 8-register exception frame #ifdef __ARM_FP //--------- if VFP available... - " POP {r0,lr} \n" // restore alighner and EXC_RETURN into lr + " POP {r0,lr} \n" // restore aligher and EXC_RETURN into lr " DSB \n" // ARM Erratum 838869 " TST lr,#(1 << 4) \n" // is it return to the VFP exception frame? " IT EQ \n" // if EXC_RETURN[4] is zero... diff --git a/ports/lint-plus/options.lnt b/ports/lint-plus/options.lnt index a4a10996..977f0c9b 100644 --- a/ports/lint-plus/options.lnt +++ b/ports/lint-plus/options.lnt @@ -22,8 +22,8 @@ // // //============================================================================ -//! @date Last updated on: 2023-12-12 -//! @version Last updated for version: 7.3.1 +//! @date Last updated on: 2024-05-14 +//! @version Last updated for version: 7.3.4 //! //! @file //! @brief PC-Lint-Plus option file for linting QP/C source code @@ -44,7 +44,7 @@ au-misra4.lnt // MISRA-C:2023 (MC4) compliance // customized BARR-C:2018 style guidelines -au-barr.lnt // BARR-C:2018 style guidelines +au-barr.lnt // BARR-C:2018 style guidelines -e8505 // suppress [Rule 6.1e] function contains uppercase letters -e8511 // suppress [Rule 7.1f] variable contains uppercase letters -e8512 // suppress [Rule 7.1j] global variable should have 'g' prefix @@ -58,10 +58,7 @@ au-barr.lnt // BARR-C:2018 style guidelines -e8522 // suppress [Rule 8.6a] variable should appear on RHS of '==' operator au-ds.lnt // Dan Saks recommendations - - -// size/alignment options -cpu.lnt // for the chosen CPU +cpu.lnt // size/alignment options for the chosen CPU // defined macros (might be undefined on command-line with -u) -dQ_SPY @@ -69,7 +66,7 @@ cpu.lnt // for the chosen CPU //============================================================================ // QP/C options for QP/C Applications -qpc.lnt // QP/C options +qpc.lnt // QP/C options //============================================================================ // additional suppression rules for building QP/C source code... @@ -112,8 +109,9 @@ qpc.lnt // QP/C options QF_CRIT_EXIT, Q_ASSERT_INCRIT, Q_REQUIRE_INCRIT, - Q_ERROR_INCRIT, Q_ENSURE_INCRIT, + Q_INVARIANT_INCRIT, + Q_ERROR_INCRIT, QF_SCHED_LOCK_, QF_SCHED_UNLOCK_, QF_ISR_CONTEXT_, diff --git a/ports/lint-plus2/16bit/cpu.lnt b/ports/lint-plus2/16bit/cpu.lnt new file mode 100644 index 00000000..d5cc76b1 --- /dev/null +++ b/ports/lint-plus2/16bit/cpu.lnt @@ -0,0 +1,6 @@ +// Size Options for 16bit CPU (e.g., MSP430) +-si2 -sl4 -sll8 -ss2 -sw2 -sp2 -sf4 -sd8 -sld8 + +// Alignment options for 16bit CPU +-ai2 -al2 -all2 -as2 -af4 -ad8 -ald8 + diff --git a/ports/lint-plus2/16bit/qs_port.h b/ports/lint-plus2/16bit/qs_port.h new file mode 100644 index 00000000..e2dc3231 --- /dev/null +++ b/ports/lint-plus2/16bit/qs_port.h @@ -0,0 +1,58 @@ +//============================================================================ +// QP/C Real-Time Embedded Framework (RTEF) +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. +// +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial +// +// This software is dual-licensed under the terms of the open source GNU +// General Public License version 3 (or any later version), or alternatively, +// under the terms of one of the closed source Quantum Leaps commercial +// licenses. +// +// The terms of the open source GNU General Public License version 3 +// can be found at: +// +// The terms of the closed source Quantum Leaps commercial licenses +// can be found at: +// +// Redistributions in source code must retain this top-level comment block. +// Plagiarizing this software to sidestep the license obligations is illegal. +// +// Contact information: +// +// +//============================================================================ +//! @date Last updated on: 2023-08-16 +//! @version Last updated for: @ref qpc_7_3_0 +//! +//! @file +//! @brief QS/C port to a 16-bit CPU and a generic C11 compiler. +//! @description +//! This is an example of a QP/C port with the documentation for the +//! configuration macros and includes. +//! +#ifndef QS_PORT_H_ +#define QS_PORT_H_ + +// QS time-stamp size in bytes +#define QS_TIME_SIZE 4U + +// object pointer size in bytes +#define QS_OBJ_PTR_SIZE 2U + +// function pointer size in bytes +#define QS_FUN_PTR_SIZE 2U + +//============================================================================ +// NOTE: QS might be used with or without other QP components, in which +// case the separate definitions of the macros QF_CRIT_STAT, QF_CRIT_ENTRY(), +// and QF_CRIT_EXIT() are needed. In this port QS is configured to be used +// with the other QP component, by simply including "qp_port.h" +// *before* "qs.h". +#ifndef QP_PORT_H_ +#include "qp_port.h" // use QS with QP +#endif + +#include "qs.h" // QS platform-independent public interface + +#endif // QS_PORT_H_ diff --git a/ports/lint-plus2/16bit/stdint.h b/ports/lint-plus2/16bit/stdint.h new file mode 100644 index 00000000..c1b99efc --- /dev/null +++ b/ports/lint-plus2/16bit/stdint.h @@ -0,0 +1,47 @@ +//! @file +//! @brief Selected exact-width and fast minimum-width integer types +//! for 16-bit CPU architecture (e.g., MSP430). +//! +//! @description +//! This header is part of the ANSI C99 standard library to define the +//! standard exact-width integer types (see C99 Section 7.18.1.1). +//! If the compiler does not provide the stdint.h header file, you can +//! either create one in the QP port directory, or you can typedef the +//! 8 exact-width integer types directly in the qep_port.h header file. +//! +//! @note The version included in the QP documentation contains only the 8 +//! exact-width types and 6 fast minimum-width types actually used in QP. +//! The actual definition of the integer types is platform dependent. +#ifndef STDINT_H_ +#define STDINT_H_ + +//lint -save +//lint -e9093 M3:R21.2(R) name matches a pattern reserved to the compiler +//lint -e586 B18:R5.2(b) keyword 'short'/'long' is deprecated + +// Exact-width types. WG14/N843 C99 Standard, Section 7.18.1.1 +typedef signed char int8_t; //!< exact-width 8-bit signed int +typedef signed int int16_t; //!< exact-width 16-bit signed int +typedef signed long int int32_t; //!< exact-width 32-bit signed int +typedef signed long long int64_t; //!< exact-width 64-bit signed int + +typedef unsigned char uint8_t; //!< exact-width 8-bit unsigned int +typedef unsigned int uint16_t; //!< exact-width 16-bit unsigned int +typedef unsigned long int uint32_t; //!< exact-width 32-bit unsigned int +typedef unsigned long long uint64_t; //!< exact-width 64-bit unsigned int + +// Fastest minimum-width types. WG14/N843 C99 Standard, Section 7.18.1.3 +typedef signed int int_fast8_t; //!< fast at-least 8-bit signed int +typedef unsigned int uint_fast8_t; //!< fast at-least 8-bit unsigned int +typedef signed int int_fast16_t; //!< fast at-least 16-bit signed int +typedef unsigned int uint_fast16_t; //!< fast at-least 16-bit unsigned int +typedef signed long int_fast32_t; //!< fast at-least 32-bit signed int +typedef unsigned long uint_fast32_t; //!< fast at-least 32-bit unsigned int + +// unsigned integer type capable of holding a pointer to void. +typedef unsigned uintptr_t; //!< unsigned int capable of holding void* + +//lint -restore + +#endif // STDINT_H_ + diff --git a/ports/lint-plus2/32bit/cpu.lnt b/ports/lint-plus2/32bit/cpu.lnt new file mode 100644 index 00000000..9281e892 --- /dev/null +++ b/ports/lint-plus2/32bit/cpu.lnt @@ -0,0 +1,3 @@ +// Size Options for 32bit CPU (e.g., ARM Cortex-M) +-si4 -sl4 -sll8 -ss2 -sw4 -sp4 -sf4 -sd8 -sld8 + diff --git a/ports/lint-plus2/32bit/qs_port.h b/ports/lint-plus2/32bit/qs_port.h new file mode 100644 index 00000000..dc2d7fbd --- /dev/null +++ b/ports/lint-plus2/32bit/qs_port.h @@ -0,0 +1,58 @@ +//============================================================================ +// QP/C Real-Time Embedded Framework (RTEF) +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. +// +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial +// +// This software is dual-licensed under the terms of the open source GNU +// General Public License version 3 (or any later version), or alternatively, +// under the terms of one of the closed source Quantum Leaps commercial +// licenses. +// +// The terms of the open source GNU General Public License version 3 +// can be found at: +// +// The terms of the closed source Quantum Leaps commercial licenses +// can be found at: +// +// Redistributions in source code must retain this top-level comment block. +// Plagiarizing this software to sidestep the license obligations is illegal. +// +// Contact information: +// +// +//============================================================================ +//! @date Last updated on: 2023-08-16 +//! @version Last updated for: @ref qpc_7_3_0 +//! +//! @file +//! @brief QS/C port to a 32-bit CPU and a generic C11 compiler. +//! @description +//! This is an example of a QP/C port with the documentation for the +//! configuration macros and includes. +//! +#ifndef QS_PORT_H_ +#define QS_PORT_H_ + +// QS time-stamp size in bytes +#define QS_TIME_SIZE 4U + +// object pointer size in bytes +#define QS_OBJ_PTR_SIZE 4U + +// function pointer size in bytes +#define QS_FUN_PTR_SIZE 4U + +//============================================================================ +// NOTE: QS might be used with or without other QP components, in which +// case the separate definitions of the macros QF_CRIT_STAT, QF_CRIT_ENTRY(), +// and QF_CRIT_EXIT() are needed. In this port QS is configured to be used +// with the other QP component, by simply including "qp_port.h" +// *before* "qs.h". +#ifndef QP_PORT_H_ +#include "qp_port.h" // use QS with QP +#endif + +#include "qs.h" // QS platform-independent public interface + +#endif // QS_PORT_H_ diff --git a/ports/lint-plus2/32bit/stdint.h b/ports/lint-plus2/32bit/stdint.h new file mode 100644 index 00000000..96e3af0c --- /dev/null +++ b/ports/lint-plus2/32bit/stdint.h @@ -0,0 +1,47 @@ +//! @file +//! @brief Selected exact-width and fast minimum-width integer types +//! for 32-bit CPU architecture (e.g., ARM Cortex-M). +//! +//! @description +//! This header is part of the ANSI C99 standard library to define the +//! standard exact-width integer types (see C99 Section 7.18.1.1). +//! If the compiler does not provide the stdint.h header file, you can +//! either create one in the QP port directory, or you can typedef the +//! 8 exact-width integer types directly in the qep_port.h header file. +//! +//! @note The version included in the QP documentation contains only the 8 +//! exact-width types and 6 fast minimum-width types actually used in QP. +//! The actual definition of the integer types is platform dependent. +#ifndef STDINT_H_ +#define STDINT_H_ + +//lint -save +//lint -e9093 M3:R21.2(R) name matches a pattern reserved to the compiler +//lint -e586 B18:R5.2(b) keyword 'short'/'long' is deprecated + +// Exact-width types. WG14/N843 C99 Standard, Section 7.18.1.1 +typedef signed char int8_t; //!< exact-width 8-bit signed int +typedef signed short int16_t; //!< exact-width 16-bit signed int +typedef signed int int32_t; //!< exact-width 32-bit signed int +typedef signed long long int64_t; //!< exact-width 64-bit signed int + +typedef unsigned char uint8_t; //!< exact-width 8-bit unsigned int +typedef unsigned short uint16_t; //!< exact-width 16-bit unsigned int +typedef unsigned int uint32_t; //!< exact-width 32-bit unsigned int +typedef unsigned long long uint64_t; //!< exact-width 64-bit unsigned int + +// Fastest minimum-width types. WG14/N843 C99 Standard, Section 7.18.1.3 +typedef signed int int_fast8_t; //!< fast at-least 8-bit signed int +typedef unsigned int uint_fast8_t; //!< fast at-least 8-bit unsigned int +typedef signed int int_fast16_t; //!< fast at-least 16-bit signed int +typedef unsigned int uint_fast16_t; //!< fast at-least 16-bit unsigned int +typedef signed long int_fast32_t; //!< fast at-least 32-bit signed int +typedef unsigned long uint_fast32_t; //!< fast at-least 32-bit unsigned int + +// unsigned integer type capable of holding a pointer to void. +typedef unsigned uintptr_t; //!< unsigned int capable of holding void* + +//lint -restore + +#endif // STDINT_H_ + diff --git a/ports/lint-plus2/au-ds.lnt b/ports/lint-plus2/au-ds.lnt new file mode 100644 index 00000000..38fcd673 --- /dev/null +++ b/ports/lint-plus2/au-ds.lnt @@ -0,0 +1,21 @@ +// au-ds.lnt -- Author options - Dan Saks + +/* + This options file can be used to explicitly activate those + checks advocated by Dan Saks in his series of presentations on + "C++ Gotchas". + + You can use this file directly when linting your programs as in: + + lin au-ds files + + */ + ++fsc // consider string constants as const char * ++e1933 // turn on "virtual call from member detection" + +// The rationale for the following two options are fully described +// in Dan Saks' article "const T vs. T const". Visit his web site +// at www.dansaks.com and click "Published Articles". +// +-fqb +e963 // require T const rather than const T diff --git a/ports/lint-plus2/make.bat b/ports/lint-plus2/make.bat new file mode 100644 index 00000000..32a1c8f5 --- /dev/null +++ b/ports/lint-plus2/make.bat @@ -0,0 +1,70 @@ +@echo off +:: =========================================================================== +:: Batch script for linting QP/C with PC-Lint-Plus2 +:: Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. +:: +:: SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial +:: +:: This software is dual-licensed under the terms of the open source GNU +:: General Public License version 3 (or any later version), or alternatively, +:: under the terms of one of the closed source Quantum Leaps commercial +:: licenses. +:: +:: The terms of the open source GNU General Public License version 3 +:: can be found at: +:: +:: The terms of the closed source Quantum Leaps commercial licenses +:: can be found at: +:: +:: Redistributions in source code must retain this top-level comment block. +:: Plagiarizing this software to sidestep the license obligations is illegal. +:: +:: Contact information: +:: +:: +:: =========================================================================== +@setlocal + +:: usage of make.bat +@echo Usage: make [16bit] [-u...] files +@echo examples: +@echo make -uQ_SPY -uQ_UTEST : use 32bit CPU (default) and undefine Q_SPY/Q_UTEST +@echo make 16bit -uQ_SPY : use 16bit CPU includes and undefine Q_SPY +@echo. + +:: NOTE: adjust to for your installation directory of PC-Lint-Plus +@set PCLP=C:\tools\lint-plus2.2-beta\windows +@set PCLP_EXE=%PCLP%\pclp64.exe + +if NOT exist "%PCLP%" ( + @echo The PC-Lint-Plus toolset not found. Please adjust make.bat + @goto end +) + +:: set the QP/C directory +@set QPC=..\.. + +if "%1"=="16bit" ( + set LINTFLAGS=-i16bit options.lnt %1 %2 %3 %4 + @echo 16bit CPU +) else ( + set LINTFLAGS=-i32bit options.lnt %1 %2 %3 %4 + @echo 32bit CPU default +) + +:: cleanup +@del *.log + +:: linting ------------------------------------------------------------------- +%PCLP_EXE% -os(lint_qf.log) std.lnt %LINTFLAGS% -iqv ..\..\src\qf\*.c + +%PCLP_EXE% -os(lint_qv.log) std.lnt %LINTFLAGS% -iqv ..\..\src\qv\*.c + +%PCLP_EXE% -os(lint_qk.log) std.lnt %LINTFLAGS% -iqk ..\..\src\qk\*.c + +%PCLP_EXE% -os(lint_qxk.log) std.lnt %LINTFLAGS% -iqxk ..\..\src\qxk\*.c + +%PCLP_EXE% -os(lint_qs.log) std.lnt %LINTFLAGS% -iqv ..\..\src\qs\*.c + +:end +@endlocal diff --git a/ports/lint-plus2/options.lnt b/ports/lint-plus2/options.lnt new file mode 100644 index 00000000..ab0473dd --- /dev/null +++ b/ports/lint-plus2/options.lnt @@ -0,0 +1,368 @@ +//============================================================================ +// QP/C Real-Time Embedded Framework (RTEF) +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. +// +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial +// +// This software is dual-licensed under the terms of the open source GNU +// General Public License version 3 (or any later version), or alternatively, +// under the terms of one of the closed source Quantum Leaps commercial +// licenses. +// +// The terms of the open source GNU General Public License version 3 +// can be found at: +// +// The terms of the closed source Quantum Leaps commercial licenses +// can be found at: +// +// Redistributions in source code must retain this top-level comment block. +// Plagiarizing this software to sidestep the license obligations is illegal. +// +// Contact information: +// +// +//============================================================================ +//! @date Last updated on: 2024-05-14 +//! @version Last updated for version: 7.3.4 +//! +//! @file +//! @brief PC-Lint-Plus option file for linting QP/C source code + +//============================================================================ +// general options +-unit_check // perform only subset check (suppresses Global Wrapup) +-max_threads=1 // suppress message "no '-max_threads=N' option" +++efreeze(686) // never suppress (see PC-Lint-Plus in Safety-Critical) +//-vf // print names of all source files (for debugging linting) + +// include directories +-i%PCLP%/lnt // PC-Lint-Plus standard .lnt files +-i. // QP/C port includes (see also qk/ and qv/) +-i%QPC%/include // QP/C public includes + +// standards +// language standard... +au-misra3.lnt // MISRA-C:2023 (MC4) compliance +au-misra3-amd1.lnt // MISRA-C:2023 (MC4) compliance +au-misra3-amd2.lnt // MISRA-C:2023 (MC4) compliance +au-misra3-amd3.lnt // MISRA-C:2023 (MC4) compliance +au-misra3-amd4.lnt // MISRA-C:2023 (MC4) compliance + +// customized BARR-C:2018 style guidelines +au-barr.lnt // BARR-C:2018 style guidelines +-e8505 // suppress [Rule 6.1e] function contains uppercase letters +-e8511 // suppress [Rule 7.1f] variable contains uppercase letters +-e8512 // suppress [Rule 7.1j] global variable should have 'g' prefix +-e8510 // suppress [Rule 7.1e] variable contains less than 3 characters +-e8513 // suppress [Rule 7.1k] variable should have 'pp' prefix +-e8514 // suppress [Rule 7.1l] variable should have 'p' prefix +-e8515 // suppress [Rule 7.1m] boolean variable should have 'b' prefix +-e8526 // suppress [Rule 5.1a] typedef name should consist of lowercase letters +-e8527 // suppress [Rule 5.1a] typedef name should end with '_t' suffix +-e9209 // suppress [Rule 5.2c] plain char data used with prohibited operator & +-e8522 // suppress [Rule 8.6a] variable should appear on RHS of '==' operator + +au-ds.lnt // Dan Saks recommendations +cpu.lnt // size/alignment options for the chosen CPU + +// defined macros (might be undefined on command-line with -u) +-dQ_SPY +-dQ_UTEST + +//============================================================================ +// QP/C options for QP/C Applications +qpc.lnt // QP/C options + +//============================================================================ +// additional suppression rules for building QP/C source code... + +// QEP ----------------------------------------------------------------------- + +//! M4-D4.9(A) function-like macro +//! @tr{DVP-QP-MC4-D04_09A} +-esym(9026, + QACTIVE_CAST_) + +//! M4-D4.9(A) function-like macro +//! @tr{DVP-QP-MC4-D04_09B} +-esym(9026, + QHSM_RESERVED_EVT_, + QS_STATE_ENTRY_, + QS_STATE_EXIT_) + +//! M4-R11.5(A) conversion from pointer to void to other pointer +//! @tr{DVR-QP-MC4-R11_05} +-emacro(9079, + Q_EVT_CAST) + +//! M4-R8.13(A) parameter of function could be pointer to const +//! @tr{DVR-QP-MC4-R08_13} +-efunc(818, + QMsm_isIn_) + +// QF ------------------------------------------------------------------------ + +//! M4-D4.8(A) complete definition is unnecessary in this translation unit +//! @tr{DVP-QP-MC4-D04_08} +-efile(9045, + -qp_pkg.h) + +//! M4-D4.9(A) function-like macro +//! @tr{DVP-QP-MC4-D04_09A} +-esym(9026, + QF_CRIT_ENTRY, + QF_CRIT_EXIT, + Q_ASSERT_INCRIT, + Q_REQUIRE_INCRIT, + Q_ENSURE_INCRIT, + Q_INVARIANT_INCRIT, + Q_ERROR_INCRIT, + QF_SCHED_LOCK_, + QF_SCHED_UNLOCK_, + QF_ISR_CONTEXT_, + QF_MPOOL_EL, + Q_UINTPTR_CAST_) + +//! M4-R8.13(A) parameter of function could be pointer to const +//! @tr{DVR-QP-MC4-R08_13} +-efunc(818, + QActive_start_) + +//! M4-R11.3(R) cast from pointer to object type +//! @tr{DVP-QP-MC4-R11_03B} +-emacro(9087, + QACTIVE_CAST_) + +//! M4-R11.3(R) cast from pointer to object type +//! @tr{DVP-QP-MC4-R11_03B} +-efunc(9087, + QActive_ctor, + QMActive_ctor) + +//! M4-R11.4(A) conversion between object pointer type and integer type +//! @tr{DVR-QP-MC4-R11_04} +-emacro(9078, + Q_UINTPTR_CAST_) + +//! M4-R11.5(A) conversion from pointer to void to other pointer type +//! @tr{DVR-QP-MC4-R11_05} +-emacro(9079, + QACTIVE_CAST_, + QF_EPOOL_GET_) +-efunc(9079, + QF_bzero_, + QF_deleteRef_, + QMPool_get, + QMPool_put, + QMPool_init, + QTimeEvt_tick_, + QTimeEvt_armX, + QTimeEvt_rearm) + +//! M4-R11.8(R) cast drops const qualifier +//! @tr{DVR-QP-MC4-R11_08} +-emacro(9005, + QACTIVE_CAST_) +-efunc(9005, + QEvt_refCtr_inc_, + QEvt_refCtr_dec_, + QF_gc) + +//! M4-R15.5(A) return statement before end of function +//! @tr{DVP-QS-MC4-R15_05} +-efunc(904, + QActive_post_, + QActive_postLIFO_) + +//! M4-R18.3(R) relational operator <= applied to pointers +//! @tr{DVR-QP-MC4-R18_03} +-efunc(946, + QMPool_get, + QMPool_put) + +//! definition of macro ends in semicolon +//! @tr{DVR-QP-PCLP-823} +-esym(823, + QF_CRIT_STAT, + QF_SCHED_STAT_) + +//! suspicious pointer-to-pointer conversion (area too small) +//! @tr{DVP-QP-PCLP-826} +-emacro(826, + QACTIVE_CAST_) + + +// QV ------------------------------------------------------------------------ + +// QK ------------------------------------------------------------------------ + +//! M4-D4.9(A) function-like macro +//! @tr{DVP-QP-MC4-D04_09A} +-esym(9026, + QK_ISR_CONTEXT_, + QK_ISR_ENTRY, + QK_ISR_EXIT) + +// QXK ----------------------------------------------------------------------- + +//! M4-D4.9(A) function-like macro +//! @tr{DVP-QP-MC4-D04_09A} +-esym(9026, + QXK_ISR_CONTEXT_, + QXK_CONTEXT_SWITCH_, + QXK_PTR_CAST_, + QXTHREAD_CAST_, + QXTHREAD_EQUEUE_SIGNAL_) + +//! M4-R11.3(R) cast from pointer to object type +//! @tr{DVP-QP-MC4-R11_03B} +-emacro(9087, + QXTHREAD_CAST_) + +//! M4-R11.3(R) cast from pointer to object type +//! @tr{DVR-QP-MC4-R11_03C} +-emacro(9087, + QXK_PTR_CAST_) + +//! M4-R11.5(A) conversion from pointer to void to other pointer type +//! @tr{DVR-QP-MC4-R11_05} +-emacro(9079, + QXK_PTR_CAST_) + +//! MC3-R8.13(A) could be pointer to const +//! @tr{DVR-QP-MC4-R08_13} +-efunc(818, + QXThread_init_, + QXThread_dispatch_, + QXThread_postLIFO_) + +//! @tr{DVP-QP-PCLP-826} +-emacro(826, + QXK_PTR_CAST_, + QXTHREAD_CAST_) + +//! cast increases required alignment from 2 to 4 +//! @tr{DVR-QP-PCLP-2445} +-emacro(2445, + QXK_PTR_CAST_) + +// QS ------------------------------------------------------------------------ +// the following options are needed only when Q_SPY is defined... + +//! M4-D4.9(A) function-like macro +//! @tr{DVP-QS-MC4-D04_09A} +-esym(9026, + QS_INSERT_BYTE_, + QS_INSERT_ESC_BYTE_, + QS_RX_TRAN_, + QS_CRIT_ENTRY, + QS_CRIT_EXIT) + +//! M4-R8.13(A) parameter ... of function could be pointer to const +//! @tr{DVR-QS-MC4-R08_13} +-efunc(818, + QHsmDummy_init_, + QHsmDummy_dispatch_, + QActiveDummy_start_, + QActiveDummy_init_, + QActiveDummy_dispatch_) + +//! M4-R11.1(R) conversion between pointer to function and differing type +//! @tr{DVP-QS-MC4-R11_01} +-emacro(9074, + QS_FUN_PRE_) +-efunc(9074, + QS_getTestProbe_) + +//! M4-R11.3(R) cast from pointer to object type +//! @tr{DVR-QS-MC4-R11_03C} +-efile(9087, + -qs_rx.c, + -qutest.c) + +//! M4-R11.4(A) conversion between object pointer type and integer type +//! @tr{DVR-QS-MC4-R11_04} +-emacro(9078, + QS_OBJ_PRE_, + QS_FUN_PRE_) +-efunc(9078, + QS_rxHandleGoodFrame_, + QS_getTestProbe_) + +//! M4-R11.5(A) conversion from pointer to void to other pointer type +//! @tr{DVR-QS-MC4-R11_05} +-efile(9079, + -qs_rx.c, + -qutest.c) + +//! M4-R11.6(R) explicit cast from integer to 'void *' +//! @tr{DVR-QS-MC4-R11_06} +-emacro(923, + QS_OBJ_PRE_, + QS_FUN_PRE_) +-efunc(923, + QS_rxHandleGoodFrame_, + QS_getTestProbe_) + +//! M4-R14.3(R) boolean condition for 'if' always evaluates to 'false' +//! @tr{DVR-QS-MC4-R14_03} +-emacro(774, + QS_BEGIN_PRE_) + +//! M4-R19.2(A) union declared +//! @tr{DVR-QS-MC4-R19_02} +-efunc(9018, + QS_target_info_pre_, + QS_f32_fmt_, + QS_f64_fmt_) + +//! constant value used in Boolean context (left operand to || operator) +//! @tr{DVR-QS-PCLP-506} +-emacro(506, + QS_BEGIN_PRE_) + +//! excessive shift value (precision 0 shifted right by ...) +//! @tr{DVR-QS-PCLP-572} +-emacro(572, + QS_BEGIN_PRE_) + +//! union initialization +//! @tr{DVR-QS-PCLP-708} +-efunc(708, + QS_f64_fmt_) + +//! union member not referenced +//! @tr{DVR-QS-PCLP-754} +-esym(754, + Variant::aFlt, + AFltVar::prio, + *U32Rep::u32) + +//! Constant expression evaluates to 0 in 'binary' operation '>>' +//! @tr{DVR-QS-PCLP-778} +-emacro(778, + QS_BEGIN_PRE_) + +//! suspicious pointer-to-pointer conversion (area too small) +//! @tr{DVR-QS-PCLP-818} +-efile(826, + -qs_rx.c, + -qutest.c) + +//! definition of macro ends in semicolon +//! @tr{DVR-QS-PCLP-823} +-esym(823, + QS_CRIT_STAT, + QS_BEGIN_PRE_) + +//! the right operand to << always evaluates to 0 +//! @tr{DVR-QS-PCLP-845} +-emacro(845, + QS_BEGIN_PRE_) + +//! cast increases required alignment +//! @tr{DVP-QS-PCLP-2445} +-efunc(2445, + QS_rxHandleGoodFrame_, + QS_rxPoke_) + diff --git a/ports/lint-plus2/qk/qp_port.h b/ports/lint-plus2/qk/qp_port.h new file mode 100644 index 00000000..ce5a3878 --- /dev/null +++ b/ports/lint-plus2/qk/qp_port.h @@ -0,0 +1,94 @@ +//============================================================================ +// QP/C Real-Time Embedded Framework (RTEF) +// +// Q u a n t u m L e a P s +// ------------------------ +// Modern Embedded Software +// +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. +// +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial +// +// This software is dual-licensed under the terms of the open source GNU +// General Public License version 3 (or any later version), or alternatively, +// under the terms of one of the closed source Quantum Leaps commercial +// licenses. +// +// The terms of the open source GNU General Public License version 3 +// can be found at: +// +// The terms of the closed source Quantum Leaps commercial licenses +// can be found at: +// +// Redistributions in source code must retain this top-level comment block. +// Plagiarizing this software to sidestep the license obligations is illegal. +// +// Contact information: +// +// +//============================================================================ +//! @date Last updated on: 2024-05-01 +//! @version Last updated for: @ref qpc_7_3_4 +//! +//! @file +//! @brief QP/C "port" to PC-Lint-Plus, QK kernel, generic C99 + +#ifndef QP_PORT_H_ +#define QP_PORT_H_ + +#include // Exact-width types. WG14/N843 C99 Standard +#include // Boolean type. WG14/N843 C99 Standard + +#ifdef QP_CONFIG +#include "qp_config.h" // external QP configuration +#endif + +// no-return function specifier (C11 Standard) +#define Q_NORETURN [[noreturn]] void + +// QF configuration for QK -- data members of the QActive class... + +// QK event-queue used for AOs +#define QACTIVE_EQUEUE_TYPE QEQueue + +// QF "thread" type used to store the MPU settings in the AO +#define QACTIVE_THREAD_TYPE void const * + +// interrupt disabling mechanism +#define QF_INT_DISABLE() intDisable() +#define QF_INT_ENABLE() intEnable() + +// QF critical section mechanism +#define QF_CRIT_STAT uint32_t crit_stat_; +#define QF_CRIT_ENTRY() (crit_stat_ = critEntry()) +#define QF_CRIT_EXIT() critExit(crit_stat_) + +// Check if the code executes in the ISR context +#define QK_ISR_CONTEXT_() (QK_get_IPSR() != 0U) + +// Define the ISR entry sequence +#define QK_ISR_ENTRY() ((void)0) + +// Define the ISR exit sequence +#define QK_ISR_EXIT() do { \ + QF_INT_DISABLE(); \ + if (QK_sched_() != 0U) { \ + *Q_UINT2PTR_CAST(uint32_t, 0xE000ED04U) = (1U << 28U);\ + } \ + QF_INT_ENABLE(); \ +} while (false) + +void intDisable(void); +void intEnable(void); +uint32_t critEntry(void); +void critExit(uint32_t stat); +uint32_t QK_get_IPSR(void); + +// include files ------------------------------------------------------------- +#include "qequeue.h" // QK kernel uses the native QP event queue +#include "qmpool.h" // QK kernel uses the native QP memory pool +#include "qp.h" // QP framework +#include "qk.h" // QK kernel + +#endif // QP_PORT_H_ + diff --git a/ports/lint-plus2/ql-style.lnt b/ports/lint-plus2/ql-style.lnt new file mode 100644 index 00000000..c4e6efaa --- /dev/null +++ b/ports/lint-plus2/ql-style.lnt @@ -0,0 +1,562 @@ +// --------------------------------------------------------------------------- +// Copyright Gimpel Software LLC 2019. All rights reserved. +// +// This file is provided by Gimpel Software LLC (https://www.gimpel.com) for +// use with PC-lint Plus. Redistribution is permitted but any redistribution +// must preserve this notice and, if the redistributed file has been modified, +// provide notice that the file has been modified from the original. +// --------------------------------------------------------------------------- + +// Adapted by Quantum Leaps from au-barr.lnt +// +// ql-style.lnt.lnt -- Author options - Quantum-Leaps:2018 +// +// This options file contains options to help enforce the +// checks advocated by the Quantum Leaps Coding Standard +// https://barrgroup.com/Embedded-Systems/Books/Embedded-C-Coding-Standard + +//========== GENERAL RULES ========== + +// 1.2 Line Widths + + /* not currently supported */ + +// 1.3 Braces + + /* 9012 - body should be a compound statement */ + +e9012 + -append(9012,[BARR-C:2018 Rule 1.3a]) + +// 1.4 Parentheses + + /* 9050 - dependence placed on precedence */ + +e9050 + -append(9050,[BARR-C:2018 Rule 1.4a]) + + /* 9097 - unparenthesized argument to sizeof */ + +e9097 + -append(9097,[BARR-C:2018 Rule 1.4a]) + + /* 821 - right hand side of assignment not parenthesized */ + +e821 + -append(821,[BARR-C:2018 Rule 1.4a]) + + /* 834 - operator op1 followed by operator op2 could be confusing */ + +e834 + -append(834,[BARR-C:2018 Rule 1.4a]) + + /* 9240 - left/right side of logical operator is not a primary expression */ + +e9240 + -append(9240,[BARR-C:2018 Rule 1.4b]) + +// 1.5 Common Abbreviations + + /* not currently supported */ + +// 1.6 Casts + + /* not currently supported */ + +// 1.7 Keywords to Avoid + + /* 586 - keyword is deprecated */ + -deprecate(keyword, auto,[BARR-C:2018 Rule 1.7a]) + -deprecate(keyword, register,[BARR-C:2018 Rule 1.7b]) + -deprecate(keyword, continue,[BARR-C:2018 Rule 1.7d]) + + /* 801 - goto statement used */ + +e801 + -append(801,[BARR-C:2018 Rule 1.7c]) + + /* 9041 - goto appears in block which is not nested in block containing label */ + +e9041 + -append(9041,[BARR-C:2018 Rule 1.7c]) + + /* 9064 - goto references earlier label */ + +e9064 + -append(9064,[BARR-C:2018 Rule 1.7c]) + +// 1.8 Keywords to Frequent + + /* 765 - external symbol could be made static */ + +e765 + -append(765,[BARR-C:2018 Rule 1.8a]) + + /* 818 - parameter of function could be pointer to const */ + +e818 + -append(818,[BARR-C:2018 Rule 1.8b]) + + /* 843 - static storage duration variable could be made const */ + +e843 + -append(843,[BARR-C:2018 Rule 1.8b]) + + /* 844 - static storage duration variable could be made pointer to const */ + +e844 + -append(844,[BARR-C:2018 Rule 1.8b]) + + /* 952 - parameter of function could be const */ + +e952 + -append(952,[BARR-C:2018 Rule 1.8b]) + + /* 953 - local variable could be const */ + +e953 + -append(953,[BARR-C:2018 Rule 1.8b]) + + /* 954 - local variable could be pointer to const */ + +e954 + -append(954,[BARR-C:2018 Rule 1.8b]) + + /* 2765 - reference to variable which is neither atomic nor volatile sig_atomic_t within signal handler */ + +e2765 + -append(2765,[BARR-C:2018 Rule 1.8c]) + +//========== COMMENTS ========== + +// 2.1 Acceptable Formats + + /* 427 - C++ comment continued via back-slash */ + +e427 + -append(427,[BARR-C:2018 Rule 2.1b]) + + /* 602 - nested block comment */ + +e602 + -append(602,[BARR-C:2018 Rule 2.1b]) + + /* 9059 - C comment contains C++ comment */ + +e9059 + -append(9059,[BARR-C:2018 Rule 2.1b]) + + // 9259 - C comment contains '://' sequence + +e9259 + -append(9259,[BARR-C:2018 Rule 2.1b]) + + /* 9066 - C++ comment contains C comment */ + +e9066 + -append(9066,[BARR-C:2018 Rule 2.1b]) + +// 2.2 Locations and Comments + + /* not statically checkable */ + +//========== WHITE SPACE RULES ========== + +// 3.1 Spaces + + /* not currently supported */ + +// 3.2 Alignment + + /* not currently supported */ + +// 3.3 Black Lines + + /* 783 - line does not end with a newline */ + +e783 + -append(783,[BARR-C:2018 Rule 3.3c]) + +// 3.4 Indentation + + /* 525 - unexpected negative indentation */ + +e525 + -append(525,[BARR-C:2018 Rule 3.4a]) + + /* 539 - unexpected positive indentation */ + +e539 + -append(539,[BARR-C:2018 Rule 3.4a]) + + /* 725 - unexpected lack of indentation */ + +e725 + -append(725,[BARR-C:2018 Rule 3.4a]) + +// 3.5 Tabs + + /* not currently supported */ + +// 3.6 Non-Printing Characters + + /* not currently supported */ + +//========== MODULE RULES ========== + +// 4.1 Naming Conventions + + /* 8517 - module does not end with '.c' */ + -hook(module_open, -cond(!('%[file_name]' ~ '[.]c$'), + +message(8517, "module '%[file_name]' should have '.c' extension"))) + +e8517 + -append(8517,[BARR-C:2018 Rule 4.1b]) + + /* 8518 - header does not end with '.h' */ + -hook(header_open, -cond(!('%[file_name]' ~ '[.]h$'), + +message(8517, "header '%[file_name]' should have '.h' extension"))) + +e8518 + -append(8518,[BARR-C:2018 Rule 4.1b]) + + /* 8519 - 'main' function defined in file that does not contain the word 'main' */ + -hook(func_decl, -cond('%[qual_name]' == 'main' && %[is_definition] && !('%[file]' ~ 'main'), + +message(8519, "main function defined in file '%[file]' which does not have the word 'main' in its name"))) + +e8519 + -append(8519,[BARR-C:2018 Rule 4.1d]) + +// 4.2 Header Files + + /* 451 - header file repeatedly included but has no header guard */ + +e451 + -append(451,[BARR-C:2018 Rule 4.2b]) + + /* 967 - header file does not have a standard include guard */ + +e967 + -append(967,[BARR-C:2018 Rule 4.2b]) + + /* 9107 - header cannot be included in more than one translation unit because of the definition of symbol */ + +e9107 + -append(9107,[BARR-C:2018 Rule 4.2c]) + + /* 755 - global macro not referenced */ + +e755 + -append(755,[BARR-C:2018 Rule 4.2c]) + + /* 756 - global typedef not referenced */ + +e756 + -append(756,[BARR-C:2018 Rule 4.2c]) + + /* 757 - global declarator not referenced */ + +e757 + -append(757,[BARR-C:2018 Rule 4.2c]) + + /* 758 - global tag not referenced */ + +e758 + -append(758,[BARR-C:2018 Rule 4.2c]) + + /* 759 - header declaration for symbol could be moved from header to module */ + +e759 + -append(759,[BARR-C:2018 Rule 4.2c]) + + /* 768 - global field not referenced */ + +e768 + -append(768,[BARR-C:2018 Rule 4.2c]) + + /* 769 - global enumeration constant not referenced */ + +e769 + -append(769,[BARR-C:2018 Rule 4.2c]) + +// 4.3 Source Files + + /* 9019 - declaration of symbol before #include */ + -append(9019,[BARR-C:2018 Rule 4.3b]) + + /* 8520 - #include used with absolute path */ + -hook(header_open, -cond('%[file_name]' ~ '^([[:alpha:]]:)?[/\\\\]', + +message(8520, "#include directive uses absolute path to include file '%[file_name]'"))) + +e8520 + -append(8520,[BARR-C:2018 Rule 4.3d]) + + /* 8521 - #include used to include module file */ + -hook(header_open, -cond('%[file_name]' ~ '[.]c$', + +message(8521, "#include directive used to include module file '%[file_name]'"))) + +e8521 + -append(8521,[BARR-C:2018 Rule 4.3f]) + +// 4.4 File Templates + + /* not statically checkable */ + +//========== DATA TYPE RULES ========== + + /* 8528 - non-anonymous struct/union/enum declared outside of typedef */ + -hook(record_decl, -cond(%[is_freestanding] && !%[is_anonymous], + +message(8528, "non-anonymous struct/union declared outside of a typedef"))) + -hook(enum_decl, -cond(%[is_freestanding] && '%[name]' != '', + +message(8528, "non-anonymous enum declared outside of a typedef"))) + +e8528 + -append(8528,[BARR-C:2018 Rule 5.1b]) + +// 5.2 Fixed-Width Integers + + /* 586 - keyword/type is deprecated */ + +e586 + + -deprecate(type,signed char,[BARR-C:2018 Rule 5.2a]) + -deprecate(type,unsigned char,[BARR-C:2018 Rule 5.2a]) + -deprecate(type,signed short,[BARR-C:2018 Rule 5.2a]) + -deprecate(type,unsigned short,[BARR-C:2018 Rule 5.2a]) + -deprecate(type,signed int,[BARR-C:2018 Rule 5.2a]) + -deprecate(type,unsigned int,[BARR-C:2018 Rule 5.2a]) + -deprecate(type,signed long,[BARR-C:2018 Rule 5.2a]) + -deprecate(type,unsigned long,[BARR-C:2018 Rule 5.2a]) + -deprecate(type,signed long long,[BARR-C:2018 Rule 5.2a]) + -deprecate(type,unsigned long long,[BARR-C:2018 Rule 5.2a]) + + -deprecate(keyword, short,[BARR-C:2018 Rule 5.2b]) + -deprecate(keyword, long,[BARR-C:2018 Rule 5.2b]) + +// 5.3 Signed and Unsigned Integers + + /* 9420 - bitfield does not have unsigned type */ + +e9420 + -append(9420,[BARR-C:2018 Rule 5.3a]) + + /* 9130 - bitwise operator applied to signed underlying type */ + +e9130 + -append(9130,[BARR-C:2018 Rule 5.3b]) + + /* 570 - negative value loses sign during implicit conversion */ + +e570 + -append(570,[BARR-C:2018 Rule 5.3c]) + + /* 713 - implicit conversion from unsigned to signed may lose precision */ + +e713 + -append(713,[BARR-C:2018 Rule 5.3c]) + + /* 8524 - combining signed and unsigned types with operator op1 */ + -hook(binary_expr, -cond(%[walk_lhs_expr{false}.walk_type.is_integer] && + %[walk_rhs_expr{false}.walk_type.is_integer] && + !%[walk_lhs_expr.walk_past_paren_imp.walk_type.is_enumeral] && + !%[walk_rhs_expr.walk_past_paren_imp.walk_type.is_enumeral] && + !%[walk_lhs_expr.walk_past_paren_imp.walk_type.is_boolean] && + !%[walk_rhs_expr.walk_past_paren_imp.walk_type.is_boolean] && + '%[walk_lhs_expr.walk_past_paren_imp.walk_type.is_unsigned_int_enum]' != + '%[walk_rhs_expr.walk_past_paren_imp.walk_type.is_unsigned_int_enum]', + +message(8524, "combining signed and unsigned types with operator '%[opcode]'"))) + +e8524 + -append(8524,[BARR-C:2018 Rule 5.3c]) + +// 5.4 Floating Point + + /* 586 - type is deprecated */ + -deprecate(type,float,[BARR-C:2018 Rule 5.4b]) + -deprecate(type,double,[BARR-C:2018 Rule 5.4b]) + -deprecate(type,long double,[BARR-C:2018 Rule 5.4b]) + + /* 777 - testing floating point values for equality */ + +e777 + -append(777,[BARR-C:2018 Rule 5.4b]) + + /* 9252 - testing floating point for equality using exact value */ + +e9252 + -append(9252,[BARR-C:2018 Rule 5.4b]) + +// 5.5 Structures and Unions + + /* not currently supported */ + +// 5.6 Booleans + + /* 8523 - cast to boolean */ + -hook(cast_expr, -cond(%[is_cstyle_cast] && %[walk_type.is_boolean], + +message(8523, "cast to boolean"))) + +e8523 + -append(8523,[BARR-C:2018 Rule 5.6b]) + +//========== PROCEDURE RULES ========== + +// 6.1 Naming Conventions + + /* 8501 - function has name that matches a keyword in C or C++ */ + -hook(func_decl, -cond('%[name]' ~ '^(?Palignas|alignof|and|and_eq|asm|auto|bitand|bitor|bool|break|case|catch|char|char8_t|char16_t|char32_t|class|compl|concept|const|consteval|constexpr|const_cast|continue|co_await|co_return|co_yield|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|false|float|for|friend|goto|if|inline|int|long|mutable|namespace|new|noexcept|not|not_eq|nullptr|operator|or|or_eq|private|protected|public|register|reinterpret_cast|requires|restrict|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|true|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while|xor|xor_eq|_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local)$', +message(8501, "function '%[name]' matches the name of a C/C++ keyword"))) + +e8501 + -append(8501,[BARR-C:2018 Rule 6.1a]) + + /* 8502 - function has same name as standard library function */ + -hook(func_decl, -cond('%[name]' ~ '^(?:abort|abs|acos|acosf|acosh|acoshf|acoshl|acosl|asctime|asin|asinf|asinh|asinhf|asinhl|asinl|assert|atan|atan2|atan2f|atan2l|atanf|atanh|atanhf|atanhl|atanl|atexit|atof|atoi|atol|atoll|bsearch|btowc|cabs|cabsf|cabsl|cacos|cacosf|cacosh|cacoshf|cacoshl|cacosl|calloc|carg|cargf|cargl|casin|casinf|casinh|casinhf|casinhl|casinl|catan|catanf|catanh|catanhf|catanhl|catanl|cbrt|cbrtf|cbrtl|ccos|ccosf|ccosh|ccoshf|ccoshl|ccosl|ceil|ceilf|ceill|cexp|cexpf|cexpl|cimag|cimagf|cimagl|clearerr|clock|clog|clogf|clogl|conj|conjf|conjl|copysign|copysignf|copysignl|cos|cosf|cosh|coshf|coshl|cosl|cpow|cpowf|cpowl|cproj|cprojf|cprojl|creal|crealf|creall|csin|csinf|csinh|csinhf|csinhl|csinl|csqrt|csqrtf|csqrtl|ctan|ctanf|ctanh|ctanhf|ctanhl|ctanl|ctime|difftime|div|erf|erfc|erfcf|erfcl|erff|erfl|exit|_Exit|exp|exp2|exp2f|exp2l|expf|expl|expm1|expm1f|expm1l|fabs|fabsf|fabsl|fclose|fdim|fdimf|fdiml|feclearexcept|fegetenv|fegetexceptflag|fegetround|feholdexcept|feof|feraiseexcept|ferror|fesetenv|fesetexceptflag|fesetround|fetestexcept|feupdateenv|fflush|fgetc|fgetpos|fgets|fgetwc|fgetws|floor|floorf|floorl|fma|fmaf|fmal|fmax|fmaxf|fmaxl|fmin|fminf|fminl|fmod|fmodf|fmodl|fopen|fpclassify|fprintf|fputc|fputs|fputwc|fputws|fread|free|freopen|frexp|frexpf|frexpl|fscanf|fseek|fsetpos|ftell|fwide|fwprintf|fwrite|fwscanf|getc|getchar|getenv|gets|getwc|getwchar|gmtime|hypot|hypotf|hypotl|ilogb|ilogbf|ilogbl|imaxabs|imaxdiv|isalnum|isalpha|isblank|iscntrl|isdigit|isfinite|isgraph|isgreater|isgreaterequal|isinf|isless|islessequal|islessgreater|islower|isnan|isnormal|isprint|ispunct|isspace|isunordered|isupper|iswalnum|iswalpha|iswblank|iswcntrl|iswctype|iswdigit|iswgraph|iswlower|iswprint|iswpunct|iswspace|iswupper|iswxdigit|isxdigit|labs|ldexp|ldexpf|ldexpl|ldiv|lgamma|lgammaf|lgammal|llabs|lldiv|llrint|llrintf|llrintl|llround|llroundf|llroundl|localeconv|localtime|log|log10|log10f|log10l|log1p|log1pf|log1pl|log2|log2f|log2l|logb|logbf|logbl|logf|logl|longjmp|lrint|lrintf|lrintl|lround|lroundf|lroundl|malloc|mblen|mbrlen|mbrtowc|mbsinit|mbsrtowcs|mbstowcs|mbtowc|memchr|memcmp|memcpy|memmove|memset|mktime|modf|modff|modfl|nan|nanf|nanl|nearbyint|nearbyintf|nearbyintl|nextafter|nextafterf|nextafterl|nexttoward|nexttowardf|nexttowardl|perror|pow|powf|powl|printf|putc|putchar|puts|putwc|putwchar|qsort|raise|rand|realloc|remainder|remainderf|remainderl|remove|remquo|remquof|remquol|rename|rewind|rint|rintf|rintl|round|roundf|roundl|scalbln|scalblnf|scalblnl|scalbn|scalbnf|scalbnl|scanf|setbuf|setjmp|setlocale|setvbuf|signal|signbit|sin|sinf|sinh|sinhf|sinhl|sinl|snprintf|sprintf|sqrt|sqrtf|sqrtl|srand|sscanf|strcat|strchr|strcmp|strcoll|strcpy|strcspn|strerror|strftime|strlen|strncat|strncmp|strncpy|strpbrk|strrchr|strspn|strstr|strtod|strtof|strtoimax|strtok|strtol|strtold|strtoll|strtoul|strtoull|strtoumax|strxfrm|swprintf|swscanf|system|tan|tanf|tanh|tanhf|tanhl|tanl|tgamma|tgammaf|tgammal|time|tmpfile|tmpnam|tolower|toupper|towctrans|towlower|towupper|trunc|truncf|truncl|ungetc|ungetwc|va_arg|va_copy|va_end|va_start|vfprintf|vfscanf|vfwprintf|vfwscanf|vprintf|vscanf|vsnprintf|vsprintf|vsscanf|vswprintf|vswscanf|vwprintf|vwscanf|wcrtomb|wcscat|wcschr|wcscmp|wcscoll|wcscpy|wcscspn|wcsftime|wcslen|wcsncat|wcsncmp|wcsncpy|wcspbrk|wcsrchr|wcsrtombs|wcsspn|wcsstr|wcstod|wcstof|wcstoimax|wcstok|wcstol|wcstold|wcstoll|wcstombs|wcstoul|wcstoull|wcstoumax|wcsxfrm|wctob|wctomb|wctrans|wctype|wmemchr|wmemcmp|wmemcpy|wmemmove|wmemset|wprintf|wscanf)$', +message(8502, "function '%[name]' matches the name of a standard library function"))) + +e8502 + -append(8502,[BARR-C:2018 Rule 6.1b]) + + /* 8503 - function has name that begins with an underscore */ + -hook(func_decl, -cond('%[name]' ~ '^_', +message(8503, "function '%[name]' begins with an underscore"))) + +e8503 + -append(8503,[BARR-C:2018 Rule 6.1c]) + + /* 8504 - function name is longer than 31 characters */ + -hook(func_decl, -cond('%[name]' ~ '.{32,}', +message(8504, "function '%[name]' is longer than 31 characters"))) + +e8504 + -append(8504,[BARR-C:2018 Rule 6.1d]) + + /* 8506 - macro name contains lowercase letter(s) */ + -hook(macro_define, -cond(!%[is_builtin] && '%[name]' ~ '[[:lower:]]', +message(8506, "macro '%[name]' contains lowercase letters"))) + +e8506 + -append(8506,[BARR-C:2018 Rule 6.1f]) + +// 6.2 Functions + + /* 904 - return statement before end of function */ + +e904 + -append(904,[BARR-C:2018 Rule 6.2c]) + + /* 937 - old-style function declaration for function */ + +e937 + -append(937,[BARR-C:2018 Rule 6.2f]) + + /* 957 - function defined without a prototype in scope */ + +e957 + -append(957,[BARR-C:2018 Rule 6.2f]) + + /* 832 - parameter not explicitly declared, int assumed */ + +e832 + -append(832,[BARR-C:2018 Rule 6.2f]) + +// 6.3 Function-Like Macros + + /* 9026 - function-like macro defined */ + +e9026 + -append(9026,[BARR-C:2018 Rule 6.3a]) + + /* 665 - unparenthesized parameter in macro is passed an expression */ + +e665 + -append(665,[BARR-C:2018 Rule 6.3b]) + + /* 666 - expression with side effects passed to repeated parameter */ + +e666 + -append(666,[BARR-C:2018 Rule 6.3b]) + + /* 773 - expression-like macro not parenthesized */ + +e773 + -append(773,[BARR-C:2018 Rule 6.3b]) + + /* 9022 - unparenthesized macro parameter in definition of macro */ + +e9022 + -append(9022,[BARR-C:2018 Rule 6.3b]) + +// 6.4 Threads of Execution + + /* not currently supported */ + +// 6.5 Interrupt Service Routines + + /* not currently supported */ + +//========== VARIABLES ========== + +// 7.1 Naming Conventions + + /* 8507 - variable has name that matches a keyword in C or C++ */ + -hook(var_decl, -cond('%[name]' ~ '^(?Palignas|alignof|and|and_eq|asm|auto|bitand|bitor|bool|break|case|catch|char|char8_t|char16_t|char32_t|class|compl|concept|const|consteval|constexpr|const_cast|continue|co_await|co_return|co_yield|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|false|float|for|fortran|friend|goto|if|inline|int|interrupt|long|mutable|namespace|new|noexcept|not|not_eq|nullptr|operator|or|or_eq|private|protected|public|register|reinterpret_cast|requires|restrict|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|true|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while|xor|xor_eq|_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local)$', +message(8507, "variable '%[name]' matches the name of a C/C++ keyword"))) + +e8507 + -append(8507,[BARR-C:2018 Rule 7.1a]) + + /* 8525 - variable has same name as standard library variable */ + -hook(var_decl, -cond('%[name]' ~ '^(?:errno|stderr|stdin|stdout)$', + +message(8525, "variale '%[name]' matches the same name of a standard library variable"))) + +e8525 + -append(8525,[BARR-C:2018 Rule 7.1b]) + + /* 8508 - variable has name that begins with an underscore */ + -hook(var_decl, -cond('%[name]' ~ '^_', +message(8508, "variable '%[name]' begins with an underscore"))) + +e8508 + -append(8508,[BARR-C:2018 Rule 7.1c]) + + /* 8509 - variable name is longer than 31 characters */ + -hook(var_decl, -cond('%[name]' ~ '.{32,}', +message(8509, "variable '%[name]' is longer than 31 characters"))) + +e8509 + -append(8509,[BARR-C:2018 Rule 6.1d]) + + +// 7.2 Initialization + + /* 530 - likely using an uninitialized value */ + +e530 + -append(530,[BARR-C:2018 Rule 7.2a]) + + /* 603 - argument to parameter of type pointer to const may be a pointer to uninitialized memory */ + +e603 + -append(603,[BARR-C:2018 Rule 7.2a]) + + /* 644 - potentially using an uninitialized value */ + +e644 + -append(644,[BARR-C:2018 Rule 7.2a]) + + /* 708 - union initialization */ + +e708 + -append(708,[BARR-C:2018 Rule 7.2a]) + + /* 727 - static local symbol not explicitly initialized */ + +e727 + -append(727,[BARR-C:2018 Rule 7.2a]) + + /* 728 - file scope static variable not explicitly initialized */ + +e728 + -append(728,[BARR-C:2018 Rule 7.2a]) + + /* 729 - external variable not explicitly initialized */ + +e729 + -append(729,[BARR-C:2018 Rule 7.2a]) + + /* 738 - address of static local symbol not explicitly initialized before passed to a function */ + +e738 + -append(738,[BARR-C:2018 Rule 7.2a]) + + /* 784 - nul character truncated from string */ + +e784 + -append(784,[BARR-C:2018 Rule 7.2a]) + + /* 785 - too few initializers for aggregate */ + +e785 + -append(785,[BARR-C:2018 Rule 7.2a]) + +//========== STATEMENT RULES ========== + +// 8.1 Variable Declarations + + /* 9146 - multiple declarators in a declaration */ + +e9146 + -append(9146,[BARR-C:2018 Rule 8.1a]) + +// 8.2 Conditional Statements + + /* 720 - boolean test of assignment */ + +e720 + -append(720,[BARR-C:2018 Rule 8.2c]) + + /* 820 - boolean test of parenthesized assignment */ + +e820 + -append(820,[BARR-C:2018 Rule 8.2c]) + + /* 9013 - no 'else' at end of 'if ... else if' chain */ + +e9013 + -append(9013,[BARR-C:2018 Rule 8.2d]) + +// 8.3 Switch Statements + + /* 9014 - switch without default */ + +e9014 + -append(9014,[BARR-C:2018 Rule 8.3b]) + + /* 616 - control flow falls through to next case without an intervening comment */ + +e616 + -append(616,[BARR-C:2018 Rule 8.3c]) + +// 8.4 Loops + + /* 850 - for statement index variable modified in body */ + +e850 + -append(850,[BARR-C:2018 Rule 8.4b]) + + /* 716 - infinite loop via while */ + +e716 + -append(716,[BARR-C:2018 Rule 8.4c]) + +// 8.5 Jumps + + /* 9041 - goto appears in block which is not nested in block containing label */ + +e9041 + -append(9041,[BARR-C:2018 Rule 8.5a]) + + /* 9064 - goto references earlier label */ + +e9064 + -append(9064,[BARR-C:2018 Rule 8.5a]) + + /* 586 - function/macro is deprecated */ + -deprecate(function,abort,[BARR-C:2018 Rule 8.5b]) + -deprecate(function,exit,[BARR-C:2018 Rule 8.5b]) + -deprecate(function,longjmp,[BARR-C:2018 Rule 8.5b]) + -deprecate(macro,setjmp,[BARR-C:2018 Rule 8.5b]) + +// 8.6 Equivalence Test + + /* 8522 - variable should appear on RHS of '==' operator */ + -hook(binary_expr, -cond('%[opcode]' == '==' && + '%[walk_lhs_expr.walk_past_paren_cast.set_msg_loc.is_decl_ref_expr]' == 'true' && + '%[walk_rhs_expr.is_constant_expr]' == 'true', + +message(8522, "variable '%[walk_lhs_expr.walk_past_paren_cast.walk_decl.qual_name]' should appear on RHS of '==' operator"))) + +e8522 + -append(8522,[BARR-C:2018 Rule 8.6a]) diff --git a/ports/lint-plus2/qpc.lnt b/ports/lint-plus2/qpc.lnt new file mode 100644 index 00000000..cb9681b8 --- /dev/null +++ b/ports/lint-plus2/qpc.lnt @@ -0,0 +1,427 @@ +//============================================================================ +// QP/C Real-Time Embedded Framework (RTEF) +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. +// +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial +// +// This software is dual-licensed under the terms of the open source GNU +// General Public License version 3 (or any later version), or alternatively, +// under the terms of one of the closed source Quantum Leaps commercial +// licenses. +// +// The terms of the open source GNU General Public License version 3 +// can be found at: +// +// The terms of the closed source Quantum Leaps commercial licenses +// can be found at: +// +// Redistributions in source code must retain this top-level comment block. +// Plagiarizing this software to sidestep the license obligations is illegal. +// +// Contact information: +// +// +//============================================================================ +//! @date Last updated on: 2023-12-12 +//! @version Last updated for version: 7.3.1 +//! +//! @file +//! @brief PC-Lint-Plus option file for analysing both **QP/C** +//! and **QP/C Applications** + +// C Language Standard +-std=c99 // apply the C99 Language Standard + +//! M4-D4.8(A) complete definition is unnecessary in this translation unit +//! @tr{DVP-QP-MC4-D04_08} +-efile(9045, + -qp.h, + -qequeue.h, + -qmpool.h, + -qv.h, + -qk.h, + -qxk.h, + -qs.h) + +// Functional Safety (FuSa) System -------------------------------------------- + +// "no return" semantics for error/failure callbacks +-sem(Q_onError, r_no) +-sem(assert_failed, r_no) + +//! M4-D4.9(A) function-like macro +//! @tr{DVP-QP-MC4-D04_09A} (false-positive) +-esym(9026, + Q_DEFINE_THIS_MODULE, + Q_ASSERT_STATIC, + Q_ASSERT, + Q_ASSERT_ID, + Q_ERROR, + Q_ERROR_ID, + Q_REQUIRE, + Q_REQUIRE_ID, + Q_ENSURE, + Q_ENSURE_ID, + Q_INVARIANT, + Q_INVARIANT_ID, + Q_DIM) + +//! PCLP definition of macro ends in semicolon +//! @tr{DVP-QP-PCLP-823} +-esym(823, + Q_DEFINE_THIS_MODULE, + Q_DEFINE_THIS_FILE) + +//! BARR-C(R1.8b) parameter of function could be const +-efunc(952, + Q_onError +) + +// QEP ----------------------------------------------------------------------- +//! M4-D4.9(A) function-like macro +//! @tr{DVP-QP-MC4-D04_09A} (false-positive) +-esym(9026, + Q_UNUSED_PAR, + Q_TRAN, + Q_TRAN_HIST, + Q_SUPER, + Q_HANDLED, + Q_UNHANDLED, + Q_IGNORED, + Q_ASM_UPCAST, + Q_HSM_UPCAST, + Q_MSM_UPCAST, + Q_EVT_CAST, + QEVT_INITIALIZER, + Q_UINT2PTR_CAST, + Q_STATE_CAST, + Q_ACTION_CAST, + QASM_INIT, + QASM_DISPATCH, + QASM_IS_IN) + +//! M4-D4.9(A) function-like macro +//! @tr{DVP-QP-MC4-D04_09B} (correct identification) +-esym(9026, + QM_ENTRY, + QM_EXIT, + QM_SM_EXIT, + QM_TRAN, + QM_TRAN_INIT, + QM_TRAN_HIST, + QM_TRAN_EP, + QM_TRAN_XP, + QM_SUPER, + QM_SUPER_SUB, + QM_HANDLED, + QM_UNHANDLED, + QMSM_INIT, + QMSM_DISPATCH) + +//! M4-R11.1(R) conversion between pointer to function type +//! @tr{DVP-QP-MC4-R11_01} +-emacro(9074, + Q_STATE_CAST, + Q_ACTION_CAST, + Q_TRAN, + Q_TRAN_HIST, + Q_SUPER, + QM_ENTRY, + QM_EXIT, + QM_SM_EXIT, + QM_TRAN, + QM_TRAN_INIT, + QM_TRAN_HIST, + QM_TRAN_EP, + QM_TRAN_XP) + +//! M4-R11.3(R) cast from pointer to pointer (upcast) +//! @tr{DVP-QP-MC4-R11_03A} +-emacro(9087, + Q_ASM_UPCAST, + Q_HSM_UPCAST, + Q_MSM_UPCAST, + QM_TRAN, + QM_TRAN_EP, + QM_TRAN_INIT) + +//! M4-R11.3(R) cast from pointer to pointer (downcast) +//! @tr{DVP-QP-MC4-R11_03B} +-emacro(9087, + Q_EVT_CAST) + +//! M4-R12.3(A) comma operator used +//! @tr{DVP-QP-MC4-R12_03} +-emacro(9008, + Q_SUPER, + Q_TRAN, + Q_TRAN_HIST, + QM_ENTRY, + QM_EXIT, + QM_SUPER_SUB, + QM_TRAN, + QM_TRAN_INIT, + QM_TRAN_EP, + QM_TRAN_XP, + QM_SM_EXIT, + QM_SUPER_SUB) + +//! M4-R13.4(A) result of assignment used in left operand to ',' operator +//! @tr{DVP-QP-MC4-R13_04} +-emacro(9084, + Q_SUPER, + Q_TRAN, + QM_ENTRY, + QM_EXIT, + QM_TRAN, + QM_TRAN_INIT, + QM_TRAN_HIST, + QM_TRAN_EP, + QM_TRAN_XP, + QM_SM_EXIT, + QM_SUPER_SUB) + +//! M4-R19.2(A) union declared +//! @tr{DVP-QP-MC4-R19_02} +-esym(9018, + QAsmAttr) + +//! '' not referenced in QM-style state machines +//! @tr{DVP-QP-PCLP-754} +-esym(754, + *(anonymous struct)::act, + *(anonymous struct)::target) + +//! suspicious pointer-to-pointer conversion (area too small) +//! @tr{DVP-QP-PCLP-826} +-emacro(826, + Q_EVT_CAST) + +// deprecated QEP facilities... +-deprecate( type, QFsm, QP/C API pre 5.4.x) +-deprecate( function, QFsm_ctor, QP/C API pre 5.4.x) +-deprecate( function, QF_onIdle, QP/C API pre 5.4.x) +-deprecate( macro, Q_IGNORED, QP/C API pre 5.4.x) +-deprecate( macro, QMSM_INIT, QP/C API pre 5.8.x) +-deprecate( macro, QMSM_DISPATCH, QP/C API pre 5.8.x) + +// QF ------------------------------------------------------------------------ + +//! M4-D4.9(A) function-like macro +//! @tr{DVP-QP-MC4-D04_09B} +-esym(9026, + QF_INT_DISABLE, + QF_INT_ENABLE, + Q_PRIO, + QF_LOG2, + Q_NEW, + Q_NEW_X, + Q_NEW_REF, + Q_DELETE_REF, + QF_PUBLISH, + QF_CRIT_ENTRY, + QF_CRIT_EXIT, + QF_CRIT_EXIT_NOP, + QF_MEM_SYS, + QF_MEM_APP, + QF_MPOOL_EL, + QF_LOG2, + QF_EPOOL_INIT_, + QF_EPOOL_EVENT_SIZE_, + QF_EPOOL_GET_, + QF_EPOOL_PUT_, + QF_PTR_INC_, + QACTIVE_START, + QACTIVE_POST, + QACTIVE_POST_X, + QACTIVE_POST_LIFO, + QACTIVE_PUBLISH, + QACTIVE_EQUEUE_WAIT_, + QACTIVE_EQUEUE_SIGNAL_, + QACTIVE_EQUEUE_ONEMPTY_, + QTIMEEVT_TICK, + QTIMEEVT_TICK_X, + QTICKER_TRIG, + QF_TICK, + QF_TICK_X) + +//! M4-R11.3(R) cast to pointer to different object type (upcast) +//! @tr{DVP-QP-MC4-R11_03A} +-emacro(9087, + QACTIVE_POST, + QACTIVE_POST_LIFO) + +//! M4-R11.3(R) cast to pointer to different object type (downcast) +//! @tr{DVP-QP-MC4-R11_03B} +-emacro(9087, + Q_NEW, + Q_NEW_X) + +//! suspicious pointer-to-pointer conversion (area too small) +//! @tr{DVP-QP-PCLP-826} +-emacro(826, + QACTIVE_POST, + QACTIVE_POST_X, + QACTIVE_POST_LIFO, + Q_NEW, + Q_NEW_X) + +// deprecated QF facilities... +-deprecate( macro,QTimeEvt_ctor, QP/C API pre 5.8.x) +-deprecate( macro,QTimeEvt_postIn, QP/C API pre 5.8.x) +-deprecate( macro,QTimeEvt_postEvery, QP/C API pre 5.8.x) + +// QV ------------------------------------------------------------------------ +//! M4-D4.9(A) function-like macro +//! @tr{DVP-QP-MC4-D04_09A} +-esym(9026, + QV_CPU_SLEEP) + +// QK ------------------------------------------------------------------------ +// M4-D4.9(A) function-like macro +//! @tr{DVP-QP-MC4-D04_09A} +-esym(9026, + QK_ISR_ENTRY, + QK_ISR_EXIT, + QK_ISR_CONTEXT_) + +// QXK ----------------------------------------------------------------------- +//! M4-D4.9(A) function-like macro +//! @tr{DVP-QP-MC4-D04_09A} +-esym(9026, + QXK_ISR_ENTRY, + QXK_ISR_EXIT, + QXK_TLS, + QXTHREAD_START, + QXTHREAD_POST_X) + +// deprecated QXK facilities... +-deprecate( macro, Q_XTHREAD_CAST, QP/C API pre 6.7.x) + +// QS ------------------------------------------------------------------------ + +//! M4-D4.9(A) function-like macro +//! @tr{DVP-QS-MC4-D04_09A} +-esym(9026, + QS_INIT, + QS_EXIT, + QS_DUMP, + QS_RESET, + QS_GLB_FILTER, + QS_LOC_FILTER, + QS_FILTER_ON, + QS_FILTER_OFF, + QS_FILTER_SM_OBJ, + QS_FILTER_AO_OBJ, + QS_FILTER_MP_OBJ, + QS_FILTER_EQ_OBJ, + QS_FILTER_TE_OBJ, + QS_FILTER_AP_OBJ, + QS_GET_BYTE, + QS_GET_BLOCK, + QS_BEGIN, + QS_BEGIN_ID, + QS_END, + QS_BEGIN_INCRIT, + QS_END_INCRIT, + QS_TR_CRIT_ENTRY, + QS_TR_CRIT_EXIT, + QS_TR_ISR_ENTRY, + QS_TR_ISR_EXIT, + QS_ONLY, + QS_REC_DONE, + QS_I8, + QS_U8, + QS_I16, + QS_U16, + QS_I32, + QS_I64, + QS_U32, + QS_F32, + QS_F64, + QS_U64, + QS_U32_HEX, + QS_STR, + QS_OBJ, + QS_FUN, + QS_SIG_DICTIONARY, + QS_OBJ_DICTIONARY, + QS_OBJ_ARR_DICTIONARY, + QS_FUN_DICTIONARY, + QS_USR_DICTIONARY, + QS_ENUM_DICTIONARY, + QS_ASSERTION, + QS_FLUSH, + QS_MEM, + QS_SIG, + QS_ENUM, + QS_PTR_AT_, + QS_RX_PUT, + QS_OUTPUT, + QS_RX_INPUT, + QS_TEST_PAUSE, + QS_TEST_PROBE_DEF, + QS_TEST_PROBE, + QS_TEST_PROBE_ID) + +//! M4-D4.9(A) function-like macro +//! @tr{DVP-QS-MC4-D04_09A} +-esym(9026, + QS_CRIT_ENTRY, + QS_CRIT_EXIT, + QS_MEM_SYS, + QS_MEM_APP, + QS_GLB_CHECK_, + QS_LOC_CHECK_, + QS_BEGIN_PRE_, + QS_END_PRE_, + QS_U8_PRE_, + QS_2U8_PRE_, + QS_U16_PRE_, + QS_U32_PRE_, + QS_STR_PRE_, + QS_TIME_PRE_, + QS_SIG_PRE_, + QS_EVS_PRE_, + QS_OBJ_PRE_, + QS_FUN_PRE_, + QS_EQC_PRE_, + QS_MPC_PRE_, + QS_MPS_PRE_, + QS_TEC_PRE_) + +//! M4-R11.1(R) conversion between pointer to function type +//! @tr{DVP-QS-MC4-R11_01} +-emacro(9074, + QS_FUN_DICTIONARY, + QS_TEST_PROBE_DEF) + +// M4-R15.5(A) return statement before end of function +//! @tr{DVP-QS-MC4-R15_05} +-emacro(904, + QS_TEST_PROBE) + +//! M4-R19.2(A) union declared +//! @tr{DVR-QS-MC4-R19_02} +-esym(9018, + Variant) + +//! M4-R20.10(A) stringize operator +//! @tr{DVP-QS-MC4-R20_10} +-esym(9024, + QS_OBJ_DICTIONARY, + QS_OBJ_ARR_DICTIONARY, + QS_FUN_DICTIONARY, + QS_SIG_DICTIONARY, + QS_USR_DICTIONARY, + QS_ENUM_DICTIONARY) + +//! implicit conversion of enum to integral type 'int' +//! @tr{DVP-QS-PCLP-641} +-emacro(641, + QS_SIG_DICTIONARY) + +//! definition of macro ends in semicolon +//! @tr{DVP-QS-PCLP-823} +-esym(823, + QS_TEST_PROBE_DEF) diff --git a/ports/lint-plus2/qv/qp_port.h b/ports/lint-plus2/qv/qp_port.h new file mode 100644 index 00000000..536fe652 --- /dev/null +++ b/ports/lint-plus2/qv/qp_port.h @@ -0,0 +1,86 @@ +//============================================================================ +// QP/C Real-Time Embedded Framework (RTEF) +// +// Q u a n t u m L e a P s +// ------------------------ +// Modern Embedded Software +// +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. +// +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial +// +// This software is dual-licensed under the terms of the open source GNU +// General Public License version 3 (or any later version), or alternatively, +// under the terms of one of the closed source Quantum Leaps commercial +// licenses. +// +// The terms of the open source GNU General Public License version 3 +// can be found at: +// +// The terms of the closed source Quantum Leaps commercial licenses +// can be found at: +// +// Redistributions in source code must retain this top-level comment block. +// Plagiarizing this software to sidestep the license obligations is illegal. +// +// Contact information: +// +// +//============================================================================ +//! @date Last updated on: 2024-05-01 +//! @version Last updated for: @ref qpc_7_3_4 +//! +//! @file +//! @brief QP/C "port" to PC-Lint-Plus, QV kernel, generic C99 + +#ifndef QP_PORT_H_ +#define QP_PORT_H_ + +#include // Exact-width types. WG14/N843 C99 Standard +#include // Boolean type. WG14/N843 C99 Standard + +#ifdef QP_CONFIG +#include "qp_config.h" // external QP configuration +#endif + +// no-return function specifier (C11 Standard) +#define Q_NORETURN [[noreturn]] void + +// QF configuration for QV -- data members of the QActive class... + +// QV event-queue used for AOs +#define QACTIVE_EQUEUE_TYPE QEQueue + +// QF "thread" type used to store the MPU settings in the AO +#define QACTIVE_THREAD_TYPE void const * + +// interrupt disabling mechanism +#define QF_INT_DISABLE() intDisable() +#define QF_INT_ENABLE() intEnable() + +// QF critical section mechanism +#define QF_CRIT_STAT uint32_t crit_stat_; +#define QF_CRIT_ENTRY() (crit_stat_ = critEntry()) +#define QF_CRIT_EXIT() critExit(crit_stat_) + +#define QV_CPU_SLEEP() \ +do { \ + __disable_interrupt(); \ + QF_INT_ENABLE(); \ + __WFI(); \ + __enable_interrupt(); \ +} while (false) + +void intDisable(void); +void intEnable(void); +uint32_t critEntry(void); +void critExit(uint32_t stat); + +// include files ------------------------------------------------------------- +#include "qequeue.h" // QV kernel uses the native QP event queue +#include "qmpool.h" // QV kernel uses the native QP memory pool +#include "qp.h" // QP framework +#include "qv.h" // QV kernel + +#endif // QP_PORT_H_ + diff --git a/ports/lint-plus2/qxk/qp_port.h b/ports/lint-plus2/qxk/qp_port.h new file mode 100644 index 00000000..375d137c --- /dev/null +++ b/ports/lint-plus2/qxk/qp_port.h @@ -0,0 +1,101 @@ +//============================================================================ +// QP/C Real-Time Embedded Framework (RTEF) +// +// Q u a n t u m L e a P s +// ------------------------ +// Modern Embedded Software +// +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. +// +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial +// +// This software is dual-licensed under the terms of the open source GNU +// General Public License version 3 (or any later version), or alternatively, +// under the terms of one of the closed source Quantum Leaps commercial +// licenses. +// +// The terms of the open source GNU General Public License version 3 +// can be found at: +// +// The terms of the closed source Quantum Leaps commercial licenses +// can be found at: +// +// Redistributions in source code must retain this top-level comment block. +// Plagiarizing this software to sidestep the license obligations is illegal. +// +// Contact information: +// +// +//============================================================================ +//! @date Last updated on: 2024-05-01 +//! @version Last updated for: @ref qpc_7_3_4 +//! +//! @file +//! @brief QP/C "port" to PC-Lint-Plus, QXK kernel, generic C99 + +#ifndef QP_PORT_H_ +#define QP_PORT_H_ + +#include // Exact-width types. WG14/N843 C99 Standard +#include // Boolean type. WG14/N843 C99 Standard + +#ifdef QP_CONFIG +#include "qp_config.h" // external QP configuration +#endif + +// no-return function specifier (C11 Standard) +#define Q_NORETURN [[noreturn]] void + +// QF configuration for QXK -- data members of the QActive class... + +// QXK event-queue type used for AOs and eXtended threads. +#define QACTIVE_EQUEUE_TYPE QEQueue + +// QXK OS-Object type used for the private stack pointer for eXtended threads. +// (The private stack pointer is NULL for basic-threads). +#define QACTIVE_OS_OBJ_TYPE void* + +// QF "thread" type used to store the MPU settings in the AO +#define QACTIVE_THREAD_TYPE void const * + +// interrupt disabling mechanism +#define QF_INT_DISABLE() intDisable() +#define QF_INT_ENABLE() intEnable() + +// QF critical section mechanism +#define QF_CRIT_STAT uint32_t crit_stat_; +#define QF_CRIT_ENTRY() (crit_stat_ = critEntry()) +#define QF_CRIT_EXIT() critExit(crit_stat_) + +// Check if the code executes in the ISR context +#define QXK_ISR_CONTEXT_() (QXK_get_IPSR() != 0U) + +// Define the ISR entry sequence +#define QXK_ISR_ENTRY() ((void)0) + +// Define the ISR exit sequence +#define QXK_ISR_EXIT() do { \ + QF_INT_DISABLE(); \ + if (QXK_sched_() != 0U) { \ + *Q_UINT2PTR_CAST(uint32_t, 0xE000ED04U) = (1U << 28U);\ + } \ + QF_INT_ENABLE(); \ +} while (false) + +#define QXK_CONTEXT_SWITCH_() (QXK_trigPendSV()) + +void intDisable(void); +void intEnable(void); +uint32_t critEntry(void); +void critExit(uint32_t stat); +uint32_t QXK_get_IPSR(void); +void QXK_trigPendSV(void); + +// include files ------------------------------------------------------------- +#include "qequeue.h" // QXK kernel uses the native QP event queue +#include "qmpool.h" // QXK kernel uses the native QP memory pool +#include "qp.h" // QP framework +#include "qxk.h" // QXK kernel + +#endif // QP_PORT_H_ + diff --git a/ports/lint-plus2/std.lnt b/ports/lint-plus2/std.lnt new file mode 100644 index 00000000..722f7106 --- /dev/null +++ b/ports/lint-plus2/std.lnt @@ -0,0 +1,44 @@ +//============================================================================ +// QP/C Real-Time Embedded Framework (RTEF) +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. +// +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial +// +// This software is dual-licensed under the terms of the open source GNU +// General Public License version 3 (or any later version), or alternatively, +// under the terms of one of the closed source Quantum Leaps commercial +// licenses. +// +// The terms of the open source GNU General Public License version 3 +// can be found at: +// +// The terms of the closed source Quantum Leaps commercial licenses +// can be found at: +// +// Redistributions in source code must retain this top-level comment block. +// Plagiarizing this software to sidestep the license obligations is illegal. +// +// Contact information: +// +// +//============================================================================ +//! @date Last updated on: 2023-06-06 +//! @version Last updated for version: 7.3.0 +//! +//! @file +//! @brief PC-Lint-Plus standard option file + +// message formatting options... +-hF1 // output: a single line ++ffn // use full path names +-width(120,4) // break lines after 99 characters with 4 characters indent ++flm // make sure no foreign includes change the format + +-zero(99) // don't stop because of warnings +-passes(2) // make two passes (for better error messages) +-restore_at_end // don't let -e options bleed to other files +-summary() // output a summary of all produced messages + +// globally suppress the following warnings: +-e546 // explicitly taking address of function +-e717 // monocarpic do-while used to group statements diff --git a/ports/lint-plus2/stdbool.h b/ports/lint-plus2/stdbool.h new file mode 100644 index 00000000..acefc5f2 --- /dev/null +++ b/ports/lint-plus2/stdbool.h @@ -0,0 +1,30 @@ +//! @file +//! @brief Boolean type and constansts. WG14/N843 C99 Standard, Section 7.16 +//! +//! @description +//! This header is part of the ANSI C99 standard library to define the +//! standard Boolean type as well as the 'true' and 'false' constansts. +#ifndef STDBOOL_H_ +#define STDBOOL_H_ + +//lint -save +//lint -e9071 M3-R21.1(r), defined macro is reserved to the compiler +//lint -e9093 the name is reserved to the compiler +//lint -emacro(8523, false, true) cast to boolean + +#ifndef __cplusplus + +typedef _Bool bool; //!< standard Boolean data type + +//! standard 'false' constant +#define false ((bool)0) + +//! standard 'true' constant +#define true ((bool)1) + +#endif // !__cplusplus + +//lint -restore + +#endif // STDBOOL_H_ + diff --git a/ports/win32/Makefile b/ports/win32/Makefile deleted file mode 100644 index ecf06057..00000000 --- a/ports/win32/Makefile +++ /dev/null @@ -1,226 +0,0 @@ -############################################################################## -# QP/C Real-Time Embedded Framework (RTEF) -# -# Q u a n t u m L e a P s -# ------------------------ -# Modern Embedded Software -# -# Copyright (C) 2005 Quantum Leaps, LLC, . -# -# SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial -# -# This software is dual-licensed under the terms of the open source GNU -# General Public License version 3 (or any later version), or alternatively, -# under the terms of one of the closed source Quantum Leaps commercial -# licenses. -# -# The terms of the open source GNU General Public License version 3 -# can be found at: -# -# The terms of the closed source Quantum Leaps commercial licenses -# can be found at: -# -# Redistributions in source code must retain this top-level comment block. -# Plagiarizing this software to sidestep the license obligations is illegal. -# -# Contact information: -# -# -############################################################################## -# examples of invoking this Makefile: -# building configurations: Debug (default), Release and Spy -# make -# make CONF=rel -# make CONF=spy -# -# cleaning configurations: Debug (default), Release, and Spy -# make clean -# make CONF=rel clean -# make CONF=spy clean -# -# NOTE: -# To use this Makefile on Windows, you will need the GNU make utility, which -# is included in the QTools collection for Windows, see: -# https://github.com/QuantumLeaps/qtools -# - -#----------------------------------------------------------------------------- -# project name: -# -PROJECT := qp - -#----------------------------------------------------------------------------- -# project directories: -# - -# location of the QP/C framework -QPC := ../.. - -# QP port used in this project -QP_PORT_DIR := . - -# list of all source directories used by this project -VPATH = \ - $(QPC)/src/qf \ - $(QPC)/src/qs \ - $(QP_PORT_DIR) - -# list of all include directories needed by this project -INCLUDES = \ - -I$(QPC)/include \ - -I$(QPC)/src \ - -I$(QP_PORT_DIR) - -#----------------------------------------------------------------------------- -# files -# - -# C source files -C_SRCS := \ - qep_hsm.c \ - qep_msm.c \ - qf_act.c \ - qf_actq.c \ - qf_defer.c \ - qf_dyn.c \ - qf_mem.c \ - qf_ps.c \ - qf_qact.c \ - qf_qeq.c \ - qf_qmact.c \ - qf_time.c \ - qwin_gui.c \ - qf_port.c - -C_QS_SRCS := \ - qs.c \ - qs_rx.c \ - qs_fp.c \ - qs_64bit.c \ - qs_port.c - -# C++ source files -CPP_SRCS := - -# defines: -DEFINES := -DQWIN_GUI -DQP_API_VERSION=9999 - -#----------------------------------------------------------------------------- -# MinGW toolset (NOTE: assumed to be on your PATH) -# -# NOTE: -# MinGW toolset is included in the Qtools collection for Windows, see: -# https://github.com/QuantumLeaps/qtools - -CC := gcc -CPP := g++ -LIB := ar - - -############################################################################## -# Typically, you should not need to change anything below this line - -# basic utilities (included in Qtools for Windows), see: -# https://github.com/QuantumLeaps/qtools - -MKDIR := mkdir -RM := rm - -#----------------------------------------------------------------------------- -# build options for various configurations -# - -LIBFLAGS := rs - -ifeq (rel, $(CONF)) # Release configuration ................................. - -BIN_DIR := rel - -# gcc options: -CFLAGS := -c -O3 -fno-pie -std=c11 -pedantic -Wall -Wextra -W \ - $(INCLUDES) $(DEFINES) -DNDEBUG - -CPPFLAGS := -c -O3 -fno-pie -std=c++11 -pedantic -Wall -Wextra \ - -fno-rtti -fno-exceptions \ - $(INCLUDES) $(DEFINES) -DNDEBUG - -else ifeq (spy, $(CONF)) # Spy configuration ................................ - -BIN_DIR := spy - -# add the QS sources... -C_SRCS += $(C_QS_SRCS) - -# gcc options: -CFLAGS := -c -g -O -fno-pie -std=c11 -pedantic -Wall -Wextra -W \ - $(INCLUDES) $(DEFINES) -DQ_SPY - -CPPFLAGS := -c -g -O -fno-pie -std=c++11 -pedantic -Wall -Wextra \ - -fno-rtti -fno-exceptions \ - $(INCLUDES) $(DEFINES) -DQ_SPY - -else # default Debug configuration ......................................... - -BIN_DIR := dbg - -# gcc options: -CFLAGS := -c -g -O -fno-pie -std=c11 -pedantic -Wall -Wextra -W \ - $(INCLUDES) $(DEFINES) - -CPPFLAGS := -c -g -O -fno-pie -std=c++11 -pedantic -Wall -Wextra \ - -fno-rtti -fno-exceptions \ - $(INCLUDES) $(DEFINES) - -endif - -#----------------------------------------------------------------------------- -C_OBJS := $(patsubst %.c,%.o, $(notdir $(C_SRCS))) -CPP_OBJS := $(patsubst %.cpp,%.o,$(notdir $(CPP_SRCS))) - -TARGET_LIB := $(BIN_DIR)/lib$(PROJECT).a -C_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(C_OBJS)) -C_DEPS_EXT := $(patsubst %.o,%.d, $(C_OBJS_EXT)) -CPP_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(CPP_OBJS)) -CPP_DEPS_EXT := $(patsubst %.o,%.d, $(CPP_OBJS_EXT)) - -# create $(BIN_DIR) if it does not exist -ifeq ("$(wildcard $(BIN_DIR))","") -$(shell $(MKDIR) $(BIN_DIR)) -endif - -#----------------------------------------------------------------------------- -# rules -# - -all: $(TARGET_LIB) - -$(RM) $(BIN_DIR)/*.o - -$(TARGET_LIB) : $(ASM_OBJS_EXT) $(C_OBJS_EXT) $(CPP_OBJS_EXT) - $(LIB) $(LIBFLAGS) $@ $^ - -$(BIN_DIR)/%.o : %.c - $(CC) $(CFLAGS) $< -o $@ - -$(BIN_DIR)/%.o : %.cpp - $(CPP) $(CPPFLAGS) $< -o $@ - -#----------------------------------------------------------------------------- -# the clean target -# -.PHONY : clean -clean: - -$(RM) $(BIN_DIR)/*.o $(TARGET_LIB) - -#----------------------------------------------------------------------------- -# the show target for debugging -# -show: - @echo PROJECT = $(PROJECT) - @echo CONF = $(CONF) - @echo TARGET_LIB = $(TARGET_LIB) - @echo C_SRCS = $(C_SRCS) - @echo CPP_SRCS = $(CPP_SRCS) - @echo C_OBJS_EXT = $(C_OBJS_EXT) - @echo C_DEPS_EXT = $(C_DEPS_EXT) - @echo CPP_OBJS_EXT = $(CPP_OBJS_EXT) - @echo CPP_DEPS_EXT = $(CPP_DEPS_EXT) diff --git a/qpc.md5 b/qpc.md5 index 55f80b6b..07b8cb5b 100644 --- a/qpc.md5 +++ b/qpc.md5 @@ -1,51 +1,51 @@ -93ecf23cf720e5728920c20ee8d973e6 *qpc.qm +4d275cf16910927c20f700d54e13435e *qpc.qm f71fdc0261b7d7e1693f7cf92b269fc0 *include/qequeue.h 57b1efebccde23a26f9d11e822ec379f *include/qk.h 807f80a7a39be52083010803f76b4f05 *include/qmpool.h -48125adc82b65fdfa09dfbddd2621ec3 *include/qp.h +e8f2c2b5f22fedb0e344ea8aa3f71055 *include/qp.h e7b6c999b10d91f5c1adf1fde500e452 *include/qp_pkg.h -78847559ac0addc557e6984c6cb93474 *include/qpc.h +2ae619716b9a6c948ba2b3431d00c03b *include/qpc.h 2f2ed281e63d5803738ab0c92a77171f *include/qs.h 66f8bd1303a72346f52fbcccfd363586 *include/qs_dummy.h fad2d5ccd173e6374f4bce243709eef7 *include/qs_pkg.h -c33f022827668e991f2b9f212493036e *include/qsafe.h +f59bf88705afe5b0acc999f8b47a6745 *include/qsafe.h 990a963045e6485091658b0eea0a9dbd *include/qstamp.h 431c6e320c14f0b02dbc78e2d49f6431 *include/qv.h 7845e9391f7a94311fd849da56abd8a1 *include/qxk.h a25152f319178420b5b5140ca51ea4ae *src/qf/CMakeLists.txt -1c4dad5956b62c793eb9b92e2043bdf7 *src/qf/qep_hsm.c -25374a80a064e6f7199e19285543f2fd *src/qf/qep_msm.c +b4ade402584ddb981fe5967e1a4418c7 *src/qf/qep_hsm.c +72756ebffc4809e6b934b8189170852f *src/qf/qep_msm.c 762cba96738f7e3fe4ebd66659542b30 *src/qf/qf_act.c -78ad6e00669d2888ceef6e6d84e83e55 *src/qf/qf_actq.c +091c7f1f25217df387119df63ee51dd1 *src/qf/qf_actq.c 858f4abf264ab69734b4df56b0bfa739 *src/qf/qf_defer.c -3f25992d60f701951f0d20c1c2e3ad5a *src/qf/qf_dyn.c -bc3e5d7fcb172fee6881f993160502eb *src/qf/qf_mem.c -4642cd0eaf88ca3012439bb95a43d8b8 *src/qf/qf_ps.c +29309e868460c232ef237a666b6d02b4 *src/qf/qf_dyn.c +83aff99fd71e3383f700d3dd5b712c4e *src/qf/qf_mem.c +e090893c0f33678c6bf267c637c6cb48 *src/qf/qf_ps.c 5a1d0999864f48a688d34e9273868e8b *src/qf/qf_qact.c a34020507dc261f49eaaaf2062dcb81d *src/qf/qf_qeq.c f9867335faa23f0b57c921c8882e7a52 *src/qf/qf_qmact.c -b0531b1989555c6b7d128e112f4f3c39 *src/qf/qf_time.c +d457172637ab14cf42f99071bc7b8e7a *src/qf/qf_time.c ccd28413fc3a093ca99b03854cf7439b *src/qk/CMakeLists.txt -aa27bde6715639754f8857a46c344442 *src/qk/qk.c +af0330a6f55fe4cffc70f27fa95baebc *src/qk/qk.c 27c155798720d7fb3b2f9cc38e311393 *src/qs/CMakeLists.txt -e045ce8b2fc053d068ec3eb10c9f65bf *src/qs/qs.c +274720fa9a3b5015951b39a6159f6773 *src/qs/qs.c 9091ffd15f7ec791076091bb17eec5fc *src/qs/qs_64bit.c 730d9bea159722e5d2c225e01b5c7875 *src/qs/qs_fp.c 60453f6d2b1f915e6e477cca68cb7fee *src/qs/qs_rx.c 80a31dfc0e24839342fe193779401e7b *src/qs/qstamp.c 53ab2ae396c90e41045b019cdfea21b5 *src/qs/qutest.c cf8fa24441cb9577288f73bdb4effbff *src/qv/CMakeLists.txt -bb08eae11dacb60099c7ff7a7b3700b3 *src/qv/qv.c +a428b106b6a95c80077a156ebe764622 *src/qv/qv.c 3a9240f29676dea5ce3df8fed587ae52 *src/qxk/CMakeLists.txt -8d2e28ffb1c8c670924de4c987fb35df *src/qxk/qxk.c -f65131e2a680cc2f419f43437e1f873a *src/qxk/qxk_mutex.c +a2ea8a8890449cf7686988c5e6631148 *src/qxk/qxk.c +c098be23217a3aa757bc2e2d96ace49a *src/qxk/qxk_mutex.c 214032bca5ddd45690cf3ca67f9f86c3 *src/qxk/qxk_sema.c c72e1cc89263ebda9462ca6fb8b04326 *src/qxk/qxk_xthr.c 74f494c8854313253a4353f649e707ae *ports/lint-plus/au-barr.lnt 2a8fea61bccbe5e8c7536a29f2ec8e98 *ports/lint-plus/au-ds.lnt 115b283af0eeeae9fdbd91836710e228 *ports/lint-plus/au-misra4.lnt 63418574679007d8ec13815cbff46f84 *ports/lint-plus/au-ql-c99.lnt -33eef33bdbf5a1bc7922d469ec57b2d8 *ports/lint-plus/options.lnt +be52f283a42b5b277097b5984181f204 *ports/lint-plus/options.lnt 02803e47d485980bdabc4a5d271288bd *ports/lint-plus/ql-style.lnt 7780e1ccc98afe4077689e31c639a862 *ports/lint-plus/qpc.lnt ecca2c20a6e0dc29a1f62aeb500ed165 *ports/lint-plus/std.lnt @@ -71,14 +71,14 @@ f6c251ec335af215b842ff2ef686e93f *ports/arm-cm/qv/iar/qs_port.h 867217f77f0c6cdb0a82a964a7027510 *ports/arm-cm/qv/iar/qv_port.c 40058ac0609321670e6e7816670e97af *ports/arm-cm/qxk/armclang/qp_port.h f6c251ec335af215b842ff2ef686e93f *ports/arm-cm/qxk/armclang/qs_port.h -666a153de8cd8b7747531199d1bcbde1 *ports/arm-cm/qxk/armclang/qxk_port.c +157999f7597ee32773fcfc13e7ef61fd *ports/arm-cm/qxk/armclang/qxk_port.c 31c4cd8ad90ea6517df1d4054033fe03 *ports/arm-cm/qxk/config/qp_config.h 35ec850c15f42e2eab924d06bf2d4165 *ports/arm-cm/qxk/gnu/qp_port.h a0699895649b5d644e4068794b0e94dc *ports/arm-cm/qxk/gnu/qs_port.h -d31561dc804f1394bc19ef218bd491f9 *ports/arm-cm/qxk/gnu/qxk_port.c +9bc69ca01a321ce71216552af9493b60 *ports/arm-cm/qxk/gnu/qxk_port.c 9145c3ae665b20e224bd91406668754c *ports/arm-cm/qxk/iar/qp_port.h f6c251ec335af215b842ff2ef686e93f *ports/arm-cm/qxk/iar/qs_port.h -9ac3d417ea66352f7ab8dd724e448ff5 *ports/arm-cm/qxk/iar/qxk_port.c +6a047634910a10c3c2bc82f28551b5aa *ports/arm-cm/qxk/iar/qxk_port.c b08b183d0275dbf6b55c46b94523a1a2 *ports/arm-cm/qutest/qp_port.h c755db99d10db142bcb98018f55e2b7a *ports/arm-cm/qutest/qs_port.h 829261756c701d26e742005c59cd25f7 *ports/arm-cr/qk/config/qp_config.h @@ -148,7 +148,6 @@ f26311a1912e214477781255c7c71834 *ports/posix-qv/safe_std.h a7e763528627d662501e8a28ca6321c1 *ports/posix-qutest/qutest_port.c f26311a1912e214477781255c7c71834 *ports/posix-qutest/safe_std.h 5fa44dffb653cecb1d9ea41d154ce852 *ports/win32/CMakeLists.txt -cd0040a8cc2c6051b2f8ea42f798d601 *ports/win32/Makefile 20fc7e8b39e32f53aca8e3f08e372957 *ports/win32/qf_port.c dddd41fe592d8832b95179820de552d2 *ports/win32/qp_port.h a46c047f83877a192b2de24f27238770 *ports/win32/qs_port.c diff --git a/qpc.qm b/qpc.qm index da605647..2a49b1b0 100644 --- a/qpc.qm +++ b/qpc.qm @@ -186,6 +186,14 @@ Contact information: Q_ASSERT(expr_) + + + + + + + Q_ASSERT_INCRIT((id_), (expr_)) + @@ -225,8 +233,8 @@ Contact information: - - + + //! the current QP version number string in ROM, based on #QP_VERSION_STR = QP_VERSION_STR; @@ -513,27 +521,27 @@ QS_MEM_APP(); QF_CRIT_EXIT(); // drill down into the state hierarchy with initial transitions... -int_fast8_t limit = QHSM_MAX_NEST_DEPTH_; // loop hard limit do { QStateHandler path[QHSM_MAX_NEST_DEPTH_]; // tran entry path array int_fast8_t ip = 0; // tran entry path index path[0] = me->temp.fun; (void)QHSM_RESERVED_EVT_(me->temp.fun, Q_EMPTY_SIG); + // note: ip is the fixed upper loop bound while ((me->temp.fun != t) && (ip < (QHSM_MAX_NEST_DEPTH_ - 1))) { ++ip; path[ip] = me->temp.fun; (void)QHSM_RESERVED_EVT_(me->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, me->temp.fun == t); + // too many state nesting levels or "malformed" HSM + Q_ENSURE_INCRIT(220, ip < QHSM_MAX_NEST_DEPTH_); QF_CRIT_EXIT(); me->temp.fun = path[0]; // retrace the entry path in reverse (desired) order... + // note: ip is the fixed upper loop bound do { // enter path[ip] if (QHSM_RESERVED_EVT_(path[ip], Q_ENTRY_SIG) @@ -561,14 +569,9 @@ do { QS_CRIT_EXIT(); } #endif // Q_SPY - - --limit; -} while ((r == Q_RET_TRAN) && (limit > 0)); +} while (r == Q_RET_TRAN); 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_MEM_SYS(); QS_BEGIN_PRE_(QS_QEP_INIT_TRAN, qsId) @@ -605,9 +608,9 @@ QStateHandler t = s; QF_CRIT_STAT QF_CRIT_ENTRY(); -Q_REQUIRE_INCRIT(300, (s != Q_STATE_CAST(0)) +Q_REQUIRE_INCRIT(300, QEvt_verify_(e)); +Q_INVARIANT_INCRIT(302, (s != Q_STATE_CAST(0)) && (me->state.uint == (uintptr_t)(~me->temp.uint))); -Q_REQUIRE_INCRIT(302, QEvt_verify_(e)); QS_MEM_SYS(); QS_BEGIN_PRE_(QS_QEP_DISPATCH, qsId) @@ -623,7 +626,7 @@ QF_CRIT_EXIT(); // process the event hierarchically... QState r; me->temp.fun = s; -int_fast8_t limit = QHSM_MAX_NEST_DEPTH_; // loop hard limit +int_fast8_t ip = QHSM_MAX_NEST_DEPTH_; // fixed upper loop bound do { s = me->temp.fun; r = (*s)(me, e); // invoke state handler s @@ -643,11 +646,11 @@ do { r = QHSM_RESERVED_EVT_(s, Q_EMPTY_SIG); // superstate of s } - --limit; -} while ((r == Q_RET_SUPER) && (limit > 0)); + --ip; +} while ((r == Q_RET_SUPER) && (ip > 0)); QF_CRIT_ENTRY(); -Q_ASSERT_INCRIT(310, limit > 0); +Q_ENSURE_INCRIT(310, ip > 0); QF_CRIT_EXIT(); if (r >= Q_RET_TRAN) { // regular tran. taken? @@ -658,21 +661,21 @@ if (r >= Q_RET_TRAN) { // regular tran. taken? path[2] = s; // tran. source // exit current state to tran. source s... - limit = QHSM_MAX_NEST_DEPTH_; // loop hard limit - for (; (t != s) && (limit > 0); t = me->temp.fun) { + ip = QHSM_MAX_NEST_DEPTH_; // fixed upper loop bound + for (; (t != s) && (ip > 0); t = me->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 (void)QHSM_RESERVED_EVT_(t, Q_EMPTY_SIG); } - --limit; + --ip; } QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(320, limit > 0); + Q_ENSURE_INCRIT(320, ip > 0); QF_CRIT_EXIT(); - int_fast8_t ip = QHsm_tran_(me, path, qsId); // take the tran. + ip = QHsm_tran_(me, path, qsId); // take the tran. #ifdef Q_SPY if (r == Q_RET_TRAN_HIST) { @@ -689,6 +692,7 @@ if (r >= Q_RET_TRAN) { // regular tran. taken? #endif // Q_SPY // execute state entry actions in the desired order... + // note: ip is the fixed upper loop bound for (; ip >= 0; --ip) { // enter path[ip] if (QHSM_RESERVED_EVT_(path[ip], Q_ENTRY_SIG) @@ -719,6 +723,7 @@ if (r >= Q_RET_TRAN) { // regular tran. taken? // find superstate (void)QHSM_RESERVED_EVT_(me->temp.fun, Q_EMPTY_SIG); + // note: ip is the fixed upper loop bound while ((me->temp.fun != t) && (ip < (QHSM_MAX_NEST_DEPTH_ - 1))) { ++ip; path[ip] = me->temp.fun; @@ -726,14 +731,14 @@ if (r >= Q_RET_TRAN) { // regular tran. taken? (void)QHSM_RESERVED_EVT_(me->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(330, me->temp.fun == t); + // too many state nesting levels or "malformed" HSM + Q_ENSURE_INCRIT(330, ip < QHSM_MAX_NEST_DEPTH_); QF_CRIT_EXIT(); me->temp.fun = path[0]; // retrace the entry path in reverse (correct) order... + // note: ip is the fixed upper loop bound do { // enter path[ip] if (QHSM_RESERVED_EVT_(path[ip], Q_ENTRY_SIG) @@ -812,17 +817,17 @@ me->temp.uint = ~me->state.uint; QF_CRIT_STAT QF_CRIT_ENTRY(); -Q_REQUIRE_INCRIT(602, me->state.uint - == (uintptr_t)(~me->temp.uint)); +Q_INVARIANT_INCRIT(602, me->state.uint + == (uintptr_t)(~me->temp.uint)); QF_CRIT_EXIT(); bool inState = false; // assume that this HSM is not in 'state' // scan the state hierarchy bottom-up QStateHandler s = me->state.fun; -int_fast8_t limit = QHSM_MAX_NEST_DEPTH_ + 1; // loop hard limit +int_fast8_t lbound = QHSM_MAX_NEST_DEPTH_ + 1; // fixed upper loop bound QState r = Q_RET_SUPER; -for (; (r != Q_RET_IGNORED) && (limit > 0); --limit) { +for (; (r != Q_RET_IGNORED) && (lbound > 0); --lbound) { if (s == state) { // do the states match? inState = true; // 'true' means that match found break; // break out of the for-loop @@ -834,7 +839,7 @@ for (; (r != Q_RET_IGNORED) && (limit > 0); --limit) { } QF_CRIT_ENTRY(); -Q_ENSURE_INCRIT(690, limit > 0); +Q_ENSURE_INCRIT(690, lbound > 0); QF_CRIT_EXIT(); #ifndef Q_UNSAFE @@ -864,6 +869,7 @@ bool isFound = false; // start with the child not found // establish stable state configuration me->super.temp.fun = child; QState r; +int_fast8_t lbound = QHSM_MAX_NEST_DEPTH_; // fixed upper loop bound do { // is this the parent of the current child? if (me->super.temp.fun == parent) { @@ -874,7 +880,9 @@ do { child = me->super.temp.fun; r = QHSM_RESERVED_EVT_(me->super.temp.fun, Q_EMPTY_SIG); } -} while (r != Q_RET_IGNORED); // the top state not reached + --lbound; +} while ((r != Q_RET_IGNORED) // the top state not reached + && (lbound > 0)); #ifndef Q_UNSAFE me->super.temp.uint = ~me->super.state.uint; @@ -882,10 +890,12 @@ me->super.temp.uint = ~me->super.state.uint; QF_CRIT_STAT QF_CRIT_ENTRY(); -Q_ASSERT_INCRIT(890, isFound); +// NOTE: the following postcondition can only succeed when +// (lbound > 0), so no extra check is necessary. +Q_ENSURE_INCRIT(890, isFound); QF_CRIT_EXIT(); -return child; // return the child +return child; @@ -954,6 +964,7 @@ else { t = me->temp.fun; // save source->super // find target->super->super... + // note: ip is the fixed upper loop bound QState r = QHSM_RESERVED_EVT_(path[1], Q_EMPTY_SIG); while ((r == Q_RET_SUPER) && (ip < (QHSM_MAX_NEST_DEPTH_ - 1))) @@ -970,9 +981,10 @@ else { } } 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); + // NOTE: The following postcondition succeeds only when + // ip < QHSM_MAX_NEST_DEPTH, so no additional check is necessary + // too many state nesting levels or "malformed" HSM. + Q_ENSURE_INCRIT(510, r != Q_RET_SUPER); QF_CRIT_EXIT(); // the LCA not found yet? @@ -988,6 +1000,7 @@ else { // == target->super->super... iq = ip; r = Q_RET_IGNORED; // indicate that the LCA NOT found + // note: iq is the fixed upper loop bound do { if (t == path[iq]) { // is this the LCA? r = Q_RET_HANDLED; // indicate the LCA found @@ -1004,7 +1017,7 @@ else { // (g) check each source->super->... // for each target->super... r = Q_RET_IGNORED; // keep looping - int_fast8_t limit = QHSM_MAX_NEST_DEPTH_; + int_fast8_t lbound = QHSM_MAX_NEST_DEPTH_; do { // exit from t if (QHSM_RESERVED_EVT_(t, Q_EXIT_SIG) @@ -1028,10 +1041,10 @@ else { } } while (iq >= 0); - --limit; - } while ((r != Q_RET_HANDLED) && (limit > 0)); + --lbound; + } while ((r != Q_RET_HANDLED) && (lbound > 0)); QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(530, limit > 0); + Q_ENSURE_INCRIT(530, lbound > 0); QF_CRIT_EXIT(); } } @@ -1128,15 +1141,15 @@ QF_CRIT_EXIT(); me->state.obj = me->temp.tatbl->target; // drill down into the state hierarchy with initial transitions... -int_fast8_t limit = QMSM_MAX_NEST_DEPTH_; // loop hard limit +int_fast8_t lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound do { // execute the tran. table r = QMsm_execTatbl_(me, me->temp.tatbl, qsId); - --limit; -} while ((r >= Q_RET_TRAN_INIT) && (limit > 0)); + --lbound; +} while ((r >= Q_RET_TRAN_INIT) && (lbound > 0)); QF_CRIT_ENTRY(); -Q_ENSURE_INCRIT(290, limit > 0); +Q_ENSURE_INCRIT(290, lbound > 0); QS_MEM_SYS(); QS_BEGIN_PRE_(QS_QEP_INIT_TRAN, qsId) @@ -1172,9 +1185,9 @@ QMState const *t = s; QF_CRIT_STAT QF_CRIT_ENTRY(); -Q_REQUIRE_INCRIT(300, (s != (QMState *)0) +Q_REQUIRE_INCRIT(300, QEvt_verify_(e)); +Q_INVARIANT_INCRIT(302, (s != (QMState *)0) && (me->state.uint == (uintptr_t)(~me->temp.uint))); -Q_REQUIRE_INCRIT(302, QEvt_verify_(e)); QS_MEM_SYS(); QS_BEGIN_PRE_(QS_QEP_DISPATCH, qsId) @@ -1189,7 +1202,7 @@ QF_CRIT_EXIT(); // scan the state hierarchy up to the top state... QState r; -int_fast8_t limit = QMSM_MAX_NEST_DEPTH_; // loop hard limit +int_fast8_t lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound do { r = (*t->stateHandler)(me, e); // call state handler function @@ -1222,10 +1235,10 @@ do { t = t->superstate; // advance to the superstate } - --limit; -} while ((t != (QMState *)0) && (limit > 0)); + --lbound; +} while ((t != (QMState *)0) && (lbound > 0)); QF_CRIT_ENTRY(); -Q_ASSERT_INCRIT(310, limit > 0); +Q_ENSURE_INCRIT(310, lbound > 0); QF_CRIT_EXIT(); if (r >= Q_RET_TRAN) { // any kind of tran. taken? @@ -1238,7 +1251,7 @@ if (r >= Q_RET_TRAN) { // any kind of tran. taken? QF_CRIT_EXIT(); #endif // Q_SPY - limit = QMSM_MAX_NEST_DEPTH_; // loop hard limit + lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound do { // save the tran-action table before it gets clobbered struct QMTranActTable const * const tatbl = me->temp.tatbl; @@ -1303,11 +1316,11 @@ 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)); + --lbound; + } while ((r >= Q_RET_TRAN) && (lbound > 0)); QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(320, limit > 0); + Q_ENSURE_INCRIT(320, lbound > 0); QS_MEM_SYS(); QS_BEGIN_PRE_(QS_QEP_TRAN, qsId) @@ -1383,8 +1396,8 @@ me->temp.uint = ~me->state.uint; bool inState = false; // assume that this SM is not in 'state' QMState const *s = me->state.obj; -int_fast8_t limit = QMSM_MAX_NEST_DEPTH_; // loop hard limit -for (; (s != (QMState *)0) && (limit > 0); --limit) { +int_fast8_t lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound +for (; (s != (QMState *)0) && (lbound > 0); --lbound) { if (s->stateHandler == state) { // match found? inState = true; break; @@ -1396,7 +1409,7 @@ for (; (s != (QMState *)0) && (limit > 0); --limit) { QF_CRIT_STAT QF_CRIT_ENTRY(); -Q_ENSURE_INCRIT(490, limit > 0); +Q_ENSURE_INCRIT(490, lbound > 0); QF_CRIT_EXIT(); return inState; @@ -1410,8 +1423,8 @@ return inState; bool inState = false; // assume that this SM is not in 'state' QMState const *s = me->super.state.obj; -int_fast8_t limit = QMSM_MAX_NEST_DEPTH_; // loop hard limit -for (; (s != (QMState *)0) && (limit > 0); --limit) { +int_fast8_t lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound +for (; (s != (QMState *)0) && (lbound > 0); --lbound) { if (s == stateObj) { // match found? inState = true; break; @@ -1423,7 +1436,7 @@ for (; (s != (QMState *)0) && (limit > 0); --limit) { QF_CRIT_STAT QF_CRIT_ENTRY(); -Q_ENSURE_INCRIT(590, limit > 0); +Q_ENSURE_INCRIT(590, lbound > 0); QF_CRIT_EXIT(); return inState; @@ -1447,9 +1460,9 @@ return inState; bool isFound = false; // start with the child not found QMState const *s; -int_fast8_t limit = QMSM_MAX_NEST_DEPTH_; // loop hard limit +int_fast8_t lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound for (s = me->super.state.obj; - (s != (QMState *)0) && (limit > 0); + (s != (QMState *)0) && (lbound > 0); s = s->superstate) { if (s == parent) { @@ -1459,17 +1472,17 @@ for (s = me->super.state.obj; else { child = s; } - --limit; + --lbound; } QF_CRIT_STAT QF_CRIT_ENTRY(); -Q_ASSERT_INCRIT(610, limit > 0); +Q_ENSURE_INCRIT(610, lbound > 0); QF_CRIT_EXIT(); if (!isFound) { // still not found? - limit = QMSM_MAX_NEST_DEPTH_; // loop hard limit + lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound for (s = me->super.temp.obj; - (s != (QMState *)0) && (limit > 0); + (s != (QMState *)0) && (lbound > 0); s = s->superstate) { if (s == parent) { @@ -1479,12 +1492,14 @@ if (!isFound) { // still not found? else { child = s; } - --limit; + --lbound; } } QF_CRIT_ENTRY(); -Q_ENSURE_INCRIT(690, isFound && (limit > 0)); +// NOTE: the following postcondition can only succeed when +// (lbound > 0), so no extra check is necessary. +Q_ENSURE_INCRIT(690, isFound); QF_CRIT_EXIT(); return child; // return the child @@ -1512,10 +1527,11 @@ Q_REQUIRE_INCRIT(700, tatbl != (struct QMTranActTable *)0); QF_CRIT_EXIT(); QState r = Q_RET_NULL; -int_fast8_t limit = QMSM_MAX_TRAN_LENGTH_; // loop hard limit +int_fast8_t lbound = QMSM_MAX_TRAN_LENGTH_; // fixed upper loop bound QActionHandler const *a = &tatbl->act[0]; -for (; (*a != Q_ACTION_CAST(0)) && (limit > 0); ++a) { +for (; (*a != Q_ACTION_CAST(0)) && (lbound > 0); ++a) { r = (*(*a))(me); // call the action through the 'a' pointer + --lbound; #ifdef Q_SPY QS_CRIT_ENTRY(); QS_MEM_SYS(); @@ -1558,9 +1574,10 @@ for (; (*a != Q_ACTION_CAST(0)) && (limit > 0); ++a) { QS_MEM_APP(); QS_CRIT_EXIT(); #endif // Q_SPY - --limit; } QF_CRIT_ENTRY(); +// NOTE: the following postcondition can only succeed when +// (lbound > 0), so no extra check is necessary. Q_ENSURE_INCRIT(790, *a == Q_ACTION_CAST(0)); QF_CRIT_EXIT(); @@ -1590,8 +1607,8 @@ QF_CRIT_STAT // exit states from the current state to the tran. source state QMState const *s = cs; -int_fast8_t limit = QMSM_MAX_NEST_DEPTH_; // loop hard limit -for (; (s != ts) && (limit > 0); --limit) { +int_fast8_t lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound +for (; (s != ts) && (lbound > 0); --lbound) { // exit action provided in state 's'? if (s->exitAction != Q_ACTION_CAST(0)) { // execute the exit action @@ -1617,7 +1634,7 @@ for (; (s != ts) && (limit > 0); --limit) { } } QF_CRIT_ENTRY(); -Q_ENSURE_INCRIT(890, limit > 0); +Q_ENSURE_INCRIT(890, lbound > 0); QF_CRIT_EXIT(); @@ -2381,7 +2398,7 @@ QF_MEM_SYS(); #ifndef Q_UNSAFE uint8_t const pcopy = (uint8_t)(~me->prio_dis); -Q_REQUIRE_INCRIT(102, (QEvt_verify_(e)) && (me->prio == pcopy)); +Q_INVARIANT_INCRIT(102, (QEvt_verify_(e)) && (me->prio == pcopy)); #endif QEQueueCtr nFree = me->eQueue.nFree; // get volatile into temporary @@ -2522,7 +2539,7 @@ QF_MEM_SYS(); #ifndef Q_UNSAFE uint8_t const pcopy = (uint8_t)(~me->prio_dis); -Q_REQUIRE_INCRIT(202, (QEvt_verify_(e)) && (me->prio == pcopy)); +Q_INVARIANT_INCRIT(202, (QEvt_verify_(e)) && (me->prio == pcopy)); #endif #ifdef QXK_H_ @@ -2679,7 +2696,7 @@ QF_CRIT_ENTRY(); QF_MEM_SYS(); Q_REQUIRE_INCRIT(200, sig < (QSignal)QActive_maxPubSignal_); -Q_REQUIRE_INCRIT(202, +Q_INVARIANT_INCRIT(202, QPSet_verify_(&QActive_subscrList_[sig].set, &QActive_subscrList_[sig].set_dis)); @@ -2723,9 +2740,9 @@ if (QPSet_notEmpty(&subscrSet)) { // any subscribers? QF_SCHED_STAT_ QF_SCHED_LOCK_(p); // lock the scheduler up to AO's prio - uint_fast8_t limit = QF_MAX_ACTIVE + 1U; + uint_fast8_t lbound = QF_MAX_ACTIVE + 1U; // fixed upper loop bound do { // loop over all subscribers - --limit; + --lbound; // QACTIVE_POST() asserts internally if the queue overflows QACTIVE_POST(a, e, sender); @@ -2747,10 +2764,12 @@ if (QPSet_notEmpty(&subscrSet)) { // any subscribers? else { p = 0U; // no more subscribers } - } while ((p != 0U) && (limit > 0U)); + } while ((p != 0U) && (lbound > 0U)); QF_CRIT_ENTRY(); - Q_ENSURE_INCRIT(290, p == 0U); + // NOTE: the following postcondition can only succeed when + // (lbound > 0), so no extra check for lbound is necessary. + Q_ENSURE_INCRIT(290, p == 0U); // all subscribers processed QF_CRIT_EXIT(); QF_SCHED_UNLOCK_(); // unlock the scheduler @@ -2781,7 +2800,7 @@ Q_REQUIRE_INCRIT(300, ((enum_t)Q_USER_SIG <= sig) && (sig < QActive_maxPubSignal_) && (0U < p) && (p <= QF_MAX_ACTIVE) && (QActive_registry_[p] == me)); -Q_REQUIRE_INCRIT(302, +Q_INVARIANT_INCRIT(302, QPSet_verify_(&QActive_subscrList_[sig].set, &QActive_subscrList_[sig].set_dis)); @@ -2819,7 +2838,7 @@ Q_REQUIRE_INCRIT(400, ((enum_t)Q_USER_SIG <= sig) && (sig < QActive_maxPubSignal_) && (0U < p) && (p <= QF_MAX_ACTIVE) && (QActive_registry_[p] == me)); -Q_REQUIRE_INCRIT(402, +Q_INVARIANT_INCRIT(402, QPSet_verify_(&QActive_subscrList_[sig].set, &QActive_subscrList_[sig].set_dis)); @@ -3323,8 +3342,8 @@ QS_BEGIN_PRE_(QS_QF_TICK, 0U) QS_END_PRE_() // scan the linked-list of time events at this rate... -uint_fast8_t limit = 2U*QF_MAX_ACTIVE; // loop hard limit -for (; limit > 0U; --limit) { +uint_fast8_t lbound = 2U*QF_MAX_ACTIVE; // fixed upper loop bound +for (; lbound > 0U; --lbound) { QTimeEvt *e = prev->next; // advance down the time evt. list if (e == (QTimeEvt *)0) { // end of the list? @@ -3344,7 +3363,7 @@ for (; limit > 0U; --limit) { } // the time event 'e' must be valid - Q_ASSERT_INCRIT(112, QEvt_verify_(Q_EVT_CAST(QEvt))); + Q_INVARIANT_INCRIT(112, QEvt_verify_(Q_EVT_CAST(QEvt))); if (e->ctr == 0U) { // time event scheduled for removal? prev->next = e->next; @@ -3431,7 +3450,7 @@ for (; limit > 0U; --limit) { QF_MEM_SYS(); } -Q_ENSURE_INCRIT(190, limit > 0U); +Q_ENSURE_INCRIT(190, lbound > 0U); QF_MEM_APP(); QF_CRIT_EXIT(); @@ -3957,14 +3976,14 @@ for (uint_fast32_t size = poolSize - me->blockSize; ++me->nTot; // one more free block in the pool } -fb->next = (QFreeBlock *)0; // the last link points to NULL +fb->next = (QFreeBlock *)0; // the last link points to NULL #ifndef Q_UNSAFE fb->next_dis = (uintptr_t)(~Q_UINTPTR_CAST_(fb->next)); #endif me->nFree = me->nTot; // all blocks are free me->nMin = me->nTot; // the minimum # free blocks -me->start = poolSto; // the original start this pool buffer +me->start = (QFreeBlock *)poolSto; // the original start this pool buffer me->end = fb; // the last block in this pool QF_MEM_APP(); @@ -3998,8 +4017,8 @@ if (me->nFree > (QMPoolCtr)margin) { QFreeBlock * const fb_next = fb->next; // fast temporary // the free block must have integrity (duplicate inverse storage) - Q_ASSERT_INCRIT(302, Q_UINTPTR_CAST_(fb_next) - == (uintptr_t)~fb->next_dis); + Q_INVARIANT_INCRIT(302, Q_UINTPTR_CAST_(fb_next) + == (uintptr_t)~fb->next_dis); --me->nFree; // one less free block if (me->nFree == 0U) { // is the pool becoming empty? @@ -4078,7 +4097,7 @@ fb->next_dis = (uintptr_t)(~Q_UINTPTR_CAST_(fb->next)); #endif // set as new head of the free list -me->free_head = block; +me->free_head = fb; ++me->nFree; // one more free block in this pool @@ -4360,7 +4379,7 @@ return e; QF_CRIT_STAT QF_CRIT_ENTRY(); -Q_REQUIRE_INCRIT(402, QEvt_verify_(e)); +Q_INVARIANT_INCRIT(402, QEvt_verify_(e)); uint_fast8_t const poolNum = QEvt_getPoolNum_(e); @@ -4427,7 +4446,7 @@ Q_UNUSED_PAR(evtRef); QF_CRIT_STAT QF_CRIT_ENTRY(); -Q_REQUIRE_INCRIT(502, QEvt_verify_(e)); +Q_INVARIANT_INCRIT(502, QEvt_verify_(e)); uint_fast8_t const poolNum = QEvt_getPoolNum_(e); @@ -4456,11 +4475,11 @@ return e; //! @static @private @memberof QF - QEvt const * const e = evtRef; + QEvt const * const e = (QEvt const *)evtRef; QF_CRIT_STAT QF_CRIT_ENTRY(); -Q_REQUIRE_INCRIT(602, QEvt_verify_(e)); +Q_INVARIANT_INCRIT(602, QEvt_verify_(e)); #ifdef Q_SPY uint_fast8_t const poolNum = QEvt_getPoolNum_(e); @@ -4835,8 +4854,8 @@ QF_gc(e); // recycle the referenced event QF_CRIT_ENTRY(); QF_MEM_SYS(); -Q_ASSERT_INCRIT(102, QV_priv_.schedCeil - == (uint_fast8_t)(~QV_priv_.schedCeil_dis)); +Q_INVARIANT_INCRIT(102, QV_priv_.schedCeil + == (uint_fast8_t)(~QV_priv_.schedCeil_dis)); if (ceiling > QV_priv_.schedCeil) { // raising the scheduler ceiling? @@ -4864,8 +4883,8 @@ QF_CRIT_EXIT(); QF_CRIT_ENTRY(); QF_MEM_SYS(); -Q_ASSERT_INCRIT(202, QV_priv_.schedCeil - == (uint_fast8_t)(~QV_priv_.schedCeil_dis)); +Q_INVARIANT_INCRIT(202, QV_priv_.schedCeil + == (uint_fast8_t)(~QV_priv_.schedCeil_dis)); if (QV_priv_.schedCeil != 0U) { // actually enabling the scheduler? @@ -4924,7 +4943,7 @@ QV_INIT(); // port-specific initialization of the QV kernel //! @static @public @memberof QF QF_onCleanup(); // application-specific cleanup callback -// nothing else to do for the cooperative QV kernel +// nothing else to do for the QV kernel @@ -4957,11 +4976,11 @@ uint_fast8_t pprev = 0U; // previously used prio. for (;;) { // QV event loop... // check internal integrity (duplicate inverse storage) - Q_ASSERT_INCRIT(302, QPSet_verify_(&QV_priv_.readySet, - &QV_priv_.readySet_dis)); + Q_INVARIANT_INCRIT(302, QPSet_verify_(&QV_priv_.readySet, + &QV_priv_.readySet_dis)); // check internal integrity (duplicate inverse storage) - Q_ASSERT_INCRIT(303, QV_priv_.schedCeil - == (uint_fast8_t)(~QV_priv_.schedCeil_dis)); + Q_INVARIANT_INCRIT(303, QV_priv_.schedCeil + == (uint_fast8_t)(~QV_priv_.schedCeil_dis)); // find the maximum prio. AO ready to run uint_fast8_t const p = (QPSet_notEmpty(&QV_priv_.readySet) @@ -5199,8 +5218,8 @@ QF_CRIT_ENTRY(); QF_MEM_SYS(); Q_REQUIRE_INCRIT(100, !QK_ISR_CONTEXT_()); -Q_REQUIRE_INCRIT(102, QK_priv_.lockCeil - == (uint_fast8_t)(~QK_priv_.lockCeil_dis)); +Q_INVARIANT_INCRIT(102, QK_priv_.lockCeil + == (uint_fast8_t)(~QK_priv_.lockCeil_dis)); // first store the previous lock prio QSchedStatus stat; @@ -5242,8 +5261,8 @@ if (prevCeil != 0xFFU) { QF_CRIT_ENTRY(); QF_MEM_SYS(); - Q_REQUIRE_INCRIT(202, QK_priv_.lockCeil - == (uint_fast8_t)(~QK_priv_.lockCeil_dis)); + Q_INVARIANT_INCRIT(202, QK_priv_.lockCeil + == (uint_fast8_t)(~QK_priv_.lockCeil_dis)); Q_REQUIRE_INCRIT(210, (!QK_ISR_CONTEXT_()) && (QK_priv_.lockCeil > prevCeil)); @@ -5281,8 +5300,8 @@ if (prevCeil != 0xFFU) { //! @static @private @memberof QK // NOTE: this function is entered with interrupts DISABLED -Q_REQUIRE_INCRIT(402, QPSet_verify_(&QK_priv_.readySet, - &QK_priv_.readySet_dis)); +Q_INVARIANT_INCRIT(402, QPSet_verify_(&QK_priv_.readySet, + &QK_priv_.readySet_dis)); uint_fast8_t p; if (QPSet_isEmpty(&QK_priv_.readySet)) { p = 0U; // no activation needed @@ -5291,7 +5310,7 @@ else { // find the highest-prio AO with non-empty event queue p = QPSet_findMax(&QK_priv_.readySet); - Q_ASSERT_INCRIT(412, + Q_INVARIANT_INCRIT(412, QK_priv_.actThre == (uint_fast8_t)(~QK_priv_.actThre_dis)); // is the AO's prio. below the active preemption-threshold? @@ -5299,16 +5318,16 @@ else { p = 0U; // no activation needed } else { - Q_ASSERT_INCRIT(422, QK_priv_.lockCeil - == (uint_fast8_t)(~QK_priv_.lockCeil_dis)); + Q_INVARIANT_INCRIT(422, QK_priv_.lockCeil + == (uint_fast8_t)(~QK_priv_.lockCeil_dis)); // is the AO's prio. below the lock-ceiling? if (p <= QK_priv_.lockCeil) { p = 0U; // no activation needed } else { - Q_ASSERT_INCRIT(432, QK_priv_.nextPrio - == (uint_fast8_t)(~QK_priv_.nextPrio_dis)); + Q_INVARIANT_INCRIT(432, QK_priv_.nextPrio + == (uint_fast8_t)(~QK_priv_.nextPrio_dis)); QK_priv_.nextPrio = p; // next AO to run #ifndef Q_UNSAFE QK_priv_.nextPrio_dis = (uint_fast8_t)(~QK_priv_.nextPrio); @@ -5329,7 +5348,7 @@ return p; uint_fast8_t const prio_in = QK_priv_.actPrio; // save initial prio. uint_fast8_t p = QK_priv_.nextPrio; // next prio to run -Q_REQUIRE_INCRIT(502, +Q_INVARIANT_INCRIT(502, (prio_in == (uint_fast8_t)(~QK_priv_.actPrio_dis)) && (p == (uint_fast8_t)(~QK_priv_.nextPrio_dis))); Q_REQUIRE_INCRIT(510, (prio_in <= QF_MAX_ACTIVE) @@ -5354,7 +5373,7 @@ else { Q_ASSERT_INCRIT(510, a != (QActive *)0); pthre_in = (uint_fast8_t)a->pthre; - Q_ASSERT_INCRIT(511, pthre_in == + Q_INVARIANT_INCRIT(511, pthre_in == (uint_fast8_t)(~(uint_fast8_t)a->pthre_dis & 0xFFU)); } @@ -5363,7 +5382,7 @@ do { a = QActive_registry_[p]; // obtain the pointer to the AO Q_ASSERT_INCRIT(520, a != (QActive *)0); // the AO must be registered uint_fast8_t const pthre = (uint_fast8_t)a->pthre; - Q_ASSERT_INCRIT(522, pthre == + Q_INVARIANT_INCRIT(522, pthre == (uint_fast8_t)(~(uint_fast8_t)a->pthre_dis & 0xFFU)); // set new active prio. and preemption-threshold @@ -5391,6 +5410,7 @@ do { } #endif // QF_ON_CONTEXT_SW || Q_SPY + QF_MEM_APP(); QF_INT_ENABLE(); // unconditionally enable interrupts QEvt const * const e = QActive_get_(a); @@ -5407,8 +5427,8 @@ do { QF_MEM_SYS(); // internal integrity check (duplicate inverse storage) - Q_ASSERT_INCRIT(532, QPSet_verify_(&QK_priv_.readySet, - &QK_priv_.readySet_dis)); + Q_INVARIANT_INCRIT(532, QPSet_verify_(&QK_priv_.readySet, + &QK_priv_.readySet_dis)); if (a->eQueue.frontEvt == (QEvt *)0) { // empty queue? QPSet_remove(&QK_priv_.readySet, p); @@ -5429,8 +5449,8 @@ do { p = 0U; // no activation needed } else { - Q_ASSERT_INCRIT(542, QK_priv_.lockCeil - == (uint_fast8_t)(~QK_priv_.lockCeil_dis)); + Q_INVARIANT_INCRIT(542, QK_priv_.lockCeil + == (uint_fast8_t)(~QK_priv_.lockCeil_dis)); // is the AO's prio. below the lock preemption-threshold? if (p <= QK_priv_.lockCeil) { @@ -5849,8 +5869,8 @@ return curr; //! @static @private @memberof QXK //! @static @private @memberof QXK - Q_REQUIRE_INCRIT(402, QPSet_verify_(&QXK_priv_.readySet, - &QXK_priv_.readySet_dis)); + Q_INVARIANT_INCRIT(402, QPSet_verify_(&QXK_priv_.readySet, + &QXK_priv_.readySet_dis)); QActive const * const curr = QXK_priv_.curr; uint_fast8_t p; @@ -5926,6 +5946,7 @@ uint_fast8_t p = (uint_fast8_t)next->prio; do { QXK_priv_.actPrio = p; // next active prio + QF_MEM_APP(); QF_INT_ENABLE(); // unconditionally enable interrupts QEvt const * const e = QActive_get_(next); @@ -5941,8 +5962,8 @@ do { QF_MEM_SYS(); // check internal integrity (duplicate inverse storage) - Q_ASSERT_INCRIT(502, QPSet_verify_(&QXK_priv_.readySet, - &QXK_priv_.readySet_dis)); + Q_INVARIANT_INCRIT(502, QPSet_verify_(&QXK_priv_.readySet, + &QXK_priv_.readySet_dis)); if (next->eQueue.frontEvt == (QEvt *)0) { // empty queue? QPSet_remove(&QXK_priv_.readySet, p); @@ -6926,7 +6947,7 @@ if (me->ao.eQueue.nFree == 0U) { // is the mutex locked by this thread already (nested locking)? else if (me->ao.osObject == &curr->super) { - // the nesting level beyond the arbitrary but high limit + // the nesting level beyond the arbitrary but high bound // most likely means cyclic or recursive locking of a mutex. Q_ASSERT_INCRIT(220, me->ao.eQueue.nFree < 0xFFU); @@ -7073,7 +7094,7 @@ if (me->ao.eQueue.nFree == 0U) { } // is the mutex locked by this thread already (nested locking)? else if (me->ao.osObject == curr) { - // the nesting level must not exceed the specified limit + // the nesting level must not exceed the specified bound Q_ASSERT_INCRIT(320, me->ao.eQueue.nFree < 0xFFU); ++me->ao.eQueue.nFree; // lock one more level @@ -8935,11 +8956,9 @@ $declare1 ${QP-FuSa} #define QP_H_ //============================================================================ -#define QP_VERSION 733U -#define QP_VERSION_STR "7.3.3" - -//! Encrypted current QP release (7.3.3) and date (2024-03-01) -#define QP_RELEASE 0x70C4F752U +#define QP_VERSION_STR "7.3.5-rc.1" +#define QP_VERSION 735U +#define QP_RELEASE 0x70A1DEF0U //============================================================================ //! @cond INTERNAL @@ -9678,10 +9697,6 @@ extern char const Q_BUILD_TIME[9]; #ifndef QPC_H_ #define QPC_H_ -#ifdef __cplusplus -extern "C" { -#endif - //============================================================================ #include "qp_port.h" // QP port from the port directory #include "qsafe.h" // QP Functional Safety (FuSa) Subsystem @@ -9840,10 +9855,6 @@ static inline void QF_psInit( #endif // QP_API_VERSION < 691 #endif // QP_API_VERSION < 700 -#ifdef __cplusplus -} -#endif - #endif // QPC_H_ @@ -9866,7 +9877,7 @@ static inline void QF_psInit( Q_DEFINE_THIS_MODULE("qep_hsm") -$define ${QEP::QP_versionStr[8]} +$define ${QEP::QP_versionStr[16]} //============================================================================ //! @cond INTERNAL @@ -11094,7 +11105,7 @@ void QS_target_info_pre_(uint8_t const isReset) { QS_U8_PRE_(QS_OBJ_PTR_SIZE | (QS_FUN_PTR_SIZE << 4U)); QS_U8_PRE_(QS_TIME_SIZE); - // send the limits... + // send the bounds... QS_U8_PRE_(QF_MAX_ACTIVE); QS_U8_PRE_(QF_MAX_EPOOL | (QF_MAX_TICK_RATE << 4U)); diff --git a/src/qf/qep_hsm.c b/src/qf/qep_hsm.c index 01a6b718..00d753ff 100644 --- a/src/qf/qep_hsm.c +++ b/src/qf/qep_hsm.c @@ -60,11 +60,11 @@ Q_DEFINE_THIS_MODULE("qep_hsm") #endif //$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//$define${QEP::QP_versionStr[8]} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +//$define${QEP::QP_versionStr[16]} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -//${QEP::QP_versionStr[8]} ................................................... -char const QP_versionStr[8] = QP_VERSION_STR; -//$enddef${QEP::QP_versionStr[8]} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//${QEP::QP_versionStr[16]} .................................................. +char const QP_versionStr[16] = QP_VERSION_STR; +//$enddef${QEP::QP_versionStr[16]} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //============================================================================ //! @cond INTERNAL @@ -188,27 +188,27 @@ void QHsm_init_( QF_CRIT_EXIT(); // drill down into the state hierarchy with initial transitions... - int_fast8_t limit = QHSM_MAX_NEST_DEPTH_; // loop hard limit do { QStateHandler path[QHSM_MAX_NEST_DEPTH_]; // tran entry path array int_fast8_t ip = 0; // tran entry path index path[0] = me->temp.fun; (void)QHSM_RESERVED_EVT_(me->temp.fun, Q_EMPTY_SIG); + // note: ip is the fixed upper loop bound while ((me->temp.fun != t) && (ip < (QHSM_MAX_NEST_DEPTH_ - 1))) { ++ip; path[ip] = me->temp.fun; (void)QHSM_RESERVED_EVT_(me->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, me->temp.fun == t); + // too many state nesting levels or "malformed" HSM + Q_ENSURE_INCRIT(220, ip < QHSM_MAX_NEST_DEPTH_); QF_CRIT_EXIT(); me->temp.fun = path[0]; // retrace the entry path in reverse (desired) order... + // note: ip is the fixed upper loop bound do { // enter path[ip] if (QHSM_RESERVED_EVT_(path[ip], Q_ENTRY_SIG) @@ -236,14 +236,9 @@ void QHsm_init_( QS_CRIT_EXIT(); } #endif // Q_SPY - - --limit; - } while ((r == Q_RET_TRAN) && (limit > 0)); + } while (r == Q_RET_TRAN); 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_MEM_SYS(); QS_BEGIN_PRE_(QS_QEP_INIT_TRAN, qsId) @@ -277,9 +272,9 @@ void QHsm_dispatch_( QF_CRIT_STAT QF_CRIT_ENTRY(); - Q_REQUIRE_INCRIT(300, (s != Q_STATE_CAST(0)) + Q_REQUIRE_INCRIT(300, QEvt_verify_(e)); + Q_INVARIANT_INCRIT(302, (s != Q_STATE_CAST(0)) && (me->state.uint == (uintptr_t)(~me->temp.uint))); - Q_REQUIRE_INCRIT(302, QEvt_verify_(e)); QS_MEM_SYS(); QS_BEGIN_PRE_(QS_QEP_DISPATCH, qsId) @@ -295,7 +290,7 @@ void QHsm_dispatch_( // process the event hierarchically... QState r; me->temp.fun = s; - int_fast8_t limit = QHSM_MAX_NEST_DEPTH_; // loop hard limit + int_fast8_t ip = QHSM_MAX_NEST_DEPTH_; // fixed upper loop bound do { s = me->temp.fun; r = (*s)(me, e); // invoke state handler s @@ -315,11 +310,11 @@ void QHsm_dispatch_( r = QHSM_RESERVED_EVT_(s, Q_EMPTY_SIG); // superstate of s } - --limit; - } while ((r == Q_RET_SUPER) && (limit > 0)); + --ip; + } while ((r == Q_RET_SUPER) && (ip > 0)); QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(310, limit > 0); + Q_ENSURE_INCRIT(310, ip > 0); QF_CRIT_EXIT(); if (r >= Q_RET_TRAN) { // regular tran. taken? @@ -330,21 +325,21 @@ void QHsm_dispatch_( path[2] = s; // tran. source // exit current state to tran. source s... - limit = QHSM_MAX_NEST_DEPTH_; // loop hard limit - for (; (t != s) && (limit > 0); t = me->temp.fun) { + ip = QHSM_MAX_NEST_DEPTH_; // fixed upper loop bound + for (; (t != s) && (ip > 0); t = me->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 (void)QHSM_RESERVED_EVT_(t, Q_EMPTY_SIG); } - --limit; + --ip; } QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(320, limit > 0); + Q_ENSURE_INCRIT(320, ip > 0); QF_CRIT_EXIT(); - int_fast8_t ip = QHsm_tran_(me, path, qsId); // take the tran. + ip = QHsm_tran_(me, path, qsId); // take the tran. #ifdef Q_SPY if (r == Q_RET_TRAN_HIST) { @@ -361,6 +356,7 @@ void QHsm_dispatch_( #endif // Q_SPY // execute state entry actions in the desired order... + // note: ip is the fixed upper loop bound for (; ip >= 0; --ip) { // enter path[ip] if (QHSM_RESERVED_EVT_(path[ip], Q_ENTRY_SIG) @@ -391,6 +387,7 @@ void QHsm_dispatch_( // find superstate (void)QHSM_RESERVED_EVT_(me->temp.fun, Q_EMPTY_SIG); + // note: ip is the fixed upper loop bound while ((me->temp.fun != t) && (ip < (QHSM_MAX_NEST_DEPTH_ - 1))) { ++ip; path[ip] = me->temp.fun; @@ -398,14 +395,14 @@ void QHsm_dispatch_( (void)QHSM_RESERVED_EVT_(me->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(330, me->temp.fun == t); + // too many state nesting levels or "malformed" HSM + Q_ENSURE_INCRIT(330, ip < QHSM_MAX_NEST_DEPTH_); QF_CRIT_EXIT(); me->temp.fun = path[0]; // retrace the entry path in reverse (correct) order... + // note: ip is the fixed upper loop bound do { // enter path[ip] if (QHSM_RESERVED_EVT_(path[ip], Q_ENTRY_SIG) @@ -481,17 +478,17 @@ bool QHsm_isIn_( { QF_CRIT_STAT QF_CRIT_ENTRY(); - Q_REQUIRE_INCRIT(602, me->state.uint - == (uintptr_t)(~me->temp.uint)); + Q_INVARIANT_INCRIT(602, me->state.uint + == (uintptr_t)(~me->temp.uint)); QF_CRIT_EXIT(); bool inState = false; // assume that this HSM is not in 'state' // scan the state hierarchy bottom-up QStateHandler s = me->state.fun; - int_fast8_t limit = QHSM_MAX_NEST_DEPTH_ + 1; // loop hard limit + int_fast8_t lbound = QHSM_MAX_NEST_DEPTH_ + 1; // fixed upper loop bound QState r = Q_RET_SUPER; - for (; (r != Q_RET_IGNORED) && (limit > 0); --limit) { + for (; (r != Q_RET_IGNORED) && (lbound > 0); --lbound) { if (s == state) { // do the states match? inState = true; // 'true' means that match found break; // break out of the for-loop @@ -503,7 +500,7 @@ bool QHsm_isIn_( } QF_CRIT_ENTRY(); - Q_ENSURE_INCRIT(690, limit > 0); + Q_ENSURE_INCRIT(690, lbound > 0); QF_CRIT_EXIT(); #ifndef Q_UNSAFE @@ -524,6 +521,7 @@ QStateHandler QHsm_childState(QHsm * const me, // establish stable state configuration me->super.temp.fun = child; QState r; + int_fast8_t lbound = QHSM_MAX_NEST_DEPTH_; // fixed upper loop bound do { // is this the parent of the current child? if (me->super.temp.fun == parent) { @@ -534,7 +532,9 @@ QStateHandler QHsm_childState(QHsm * const me, child = me->super.temp.fun; r = QHSM_RESERVED_EVT_(me->super.temp.fun, Q_EMPTY_SIG); } - } while (r != Q_RET_IGNORED); // the top state not reached + --lbound; + } while ((r != Q_RET_IGNORED) // the top state not reached + && (lbound > 0)); #ifndef Q_UNSAFE me->super.temp.uint = ~me->super.state.uint; @@ -542,10 +542,12 @@ QStateHandler QHsm_childState(QHsm * const me, QF_CRIT_STAT QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(890, isFound); + // NOTE: the following postcondition can only succeed when + // (lbound > 0), so no extra check is necessary. + Q_ENSURE_INCRIT(890, isFound); QF_CRIT_EXIT(); - return child; // return the child + return child; } //${QEP::QHsm::tran_} ........................................................ @@ -611,6 +613,7 @@ int_fast8_t QHsm_tran_( t = me->temp.fun; // save source->super // find target->super->super... + // note: ip is the fixed upper loop bound QState r = QHSM_RESERVED_EVT_(path[1], Q_EMPTY_SIG); while ((r == Q_RET_SUPER) && (ip < (QHSM_MAX_NEST_DEPTH_ - 1))) @@ -627,9 +630,10 @@ int_fast8_t QHsm_tran_( } } 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); + // NOTE: The following postcondition succeeds only when + // ip < QHSM_MAX_NEST_DEPTH, so no additional check is necessary + // too many state nesting levels or "malformed" HSM. + Q_ENSURE_INCRIT(510, r != Q_RET_SUPER); QF_CRIT_EXIT(); // the LCA not found yet? @@ -645,6 +649,7 @@ int_fast8_t QHsm_tran_( // == target->super->super... iq = ip; r = Q_RET_IGNORED; // indicate that the LCA NOT found + // note: iq is the fixed upper loop bound do { if (t == path[iq]) { // is this the LCA? r = Q_RET_HANDLED; // indicate the LCA found @@ -661,7 +666,7 @@ int_fast8_t QHsm_tran_( // (g) check each source->super->... // for each target->super... r = Q_RET_IGNORED; // keep looping - int_fast8_t limit = QHSM_MAX_NEST_DEPTH_; + int_fast8_t lbound = QHSM_MAX_NEST_DEPTH_; do { // exit from t if (QHSM_RESERVED_EVT_(t, Q_EXIT_SIG) @@ -685,10 +690,10 @@ int_fast8_t QHsm_tran_( } } while (iq >= 0); - --limit; - } while ((r != Q_RET_HANDLED) && (limit > 0)); + --lbound; + } while ((r != Q_RET_HANDLED) && (lbound > 0)); QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(530, limit > 0); + Q_ENSURE_INCRIT(530, lbound > 0); QF_CRIT_EXIT(); } } diff --git a/src/qf/qep_msm.c b/src/qf/qep_msm.c index 90b17e1e..47f7805a 100644 --- a/src/qf/qep_msm.c +++ b/src/qf/qep_msm.c @@ -148,15 +148,15 @@ void QMsm_init_( me->state.obj = me->temp.tatbl->target; // drill down into the state hierarchy with initial transitions... - int_fast8_t limit = QMSM_MAX_NEST_DEPTH_; // loop hard limit + int_fast8_t lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound do { // execute the tran. table r = QMsm_execTatbl_(me, me->temp.tatbl, qsId); - --limit; - } while ((r >= Q_RET_TRAN_INIT) && (limit > 0)); + --lbound; + } while ((r >= Q_RET_TRAN_INIT) && (lbound > 0)); QF_CRIT_ENTRY(); - Q_ENSURE_INCRIT(290, limit > 0); + Q_ENSURE_INCRIT(290, lbound > 0); QS_MEM_SYS(); QS_BEGIN_PRE_(QS_QEP_INIT_TRAN, qsId) @@ -189,9 +189,9 @@ void QMsm_dispatch_( QF_CRIT_STAT QF_CRIT_ENTRY(); - Q_REQUIRE_INCRIT(300, (s != (QMState *)0) + Q_REQUIRE_INCRIT(300, QEvt_verify_(e)); + Q_INVARIANT_INCRIT(302, (s != (QMState *)0) && (me->state.uint == (uintptr_t)(~me->temp.uint))); - Q_REQUIRE_INCRIT(302, QEvt_verify_(e)); QS_MEM_SYS(); QS_BEGIN_PRE_(QS_QEP_DISPATCH, qsId) @@ -206,7 +206,7 @@ void QMsm_dispatch_( // scan the state hierarchy up to the top state... QState r; - int_fast8_t limit = QMSM_MAX_NEST_DEPTH_; // loop hard limit + int_fast8_t lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound do { r = (*t->stateHandler)(me, e); // call state handler function @@ -239,10 +239,10 @@ void QMsm_dispatch_( t = t->superstate; // advance to the superstate } - --limit; - } while ((t != (QMState *)0) && (limit > 0)); + --lbound; + } while ((t != (QMState *)0) && (lbound > 0)); QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(310, limit > 0); + Q_ENSURE_INCRIT(310, lbound > 0); QF_CRIT_EXIT(); if (r >= Q_RET_TRAN) { // any kind of tran. taken? @@ -255,7 +255,7 @@ void QMsm_dispatch_( QF_CRIT_EXIT(); #endif // Q_SPY - limit = QMSM_MAX_NEST_DEPTH_; // loop hard limit + lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound do { // save the tran-action table before it gets clobbered struct QMTranActTable const * const tatbl = me->temp.tatbl; @@ -320,11 +320,11 @@ void QMsm_dispatch_( } t = s; // set target to the current state - --limit; - } while ((r >= Q_RET_TRAN) && (limit > 0)); + --lbound; + } while ((r >= Q_RET_TRAN) && (lbound > 0)); QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(320, limit > 0); + Q_ENSURE_INCRIT(320, lbound > 0); QS_MEM_SYS(); QS_BEGIN_PRE_(QS_QEP_TRAN, qsId) @@ -389,8 +389,8 @@ bool QMsm_isIn_( bool inState = false; // assume that this SM is not in 'state' QMState const *s = me->state.obj; - int_fast8_t limit = QMSM_MAX_NEST_DEPTH_; // loop hard limit - for (; (s != (QMState *)0) && (limit > 0); --limit) { + int_fast8_t lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound + for (; (s != (QMState *)0) && (lbound > 0); --lbound) { if (s->stateHandler == state) { // match found? inState = true; break; @@ -402,7 +402,7 @@ bool QMsm_isIn_( QF_CRIT_STAT QF_CRIT_ENTRY(); - Q_ENSURE_INCRIT(490, limit > 0); + Q_ENSURE_INCRIT(490, lbound > 0); QF_CRIT_EXIT(); return inState; @@ -415,8 +415,8 @@ bool QMsm_isInState(QMsm const * const me, bool inState = false; // assume that this SM is not in 'state' QMState const *s = me->super.state.obj; - int_fast8_t limit = QMSM_MAX_NEST_DEPTH_; // loop hard limit - for (; (s != (QMState *)0) && (limit > 0); --limit) { + int_fast8_t lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound + for (; (s != (QMState *)0) && (lbound > 0); --lbound) { if (s == stateObj) { // match found? inState = true; break; @@ -428,7 +428,7 @@ bool QMsm_isInState(QMsm const * const me, QF_CRIT_STAT QF_CRIT_ENTRY(); - Q_ENSURE_INCRIT(590, limit > 0); + Q_ENSURE_INCRIT(590, lbound > 0); QF_CRIT_EXIT(); return inState; @@ -443,9 +443,9 @@ QMState const * QMsm_childStateObj(QMsm const * const me, bool isFound = false; // start with the child not found QMState const *s; - int_fast8_t limit = QMSM_MAX_NEST_DEPTH_; // loop hard limit + int_fast8_t lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound for (s = me->super.state.obj; - (s != (QMState *)0) && (limit > 0); + (s != (QMState *)0) && (lbound > 0); s = s->superstate) { if (s == parent) { @@ -455,17 +455,17 @@ QMState const * QMsm_childStateObj(QMsm const * const me, else { child = s; } - --limit; + --lbound; } QF_CRIT_STAT QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(610, limit > 0); + Q_ENSURE_INCRIT(610, lbound > 0); QF_CRIT_EXIT(); if (!isFound) { // still not found? - limit = QMSM_MAX_NEST_DEPTH_; // loop hard limit + lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound for (s = me->super.temp.obj; - (s != (QMState *)0) && (limit > 0); + (s != (QMState *)0) && (lbound > 0); s = s->superstate) { if (s == parent) { @@ -475,12 +475,14 @@ QMState const * QMsm_childStateObj(QMsm const * const me, else { child = s; } - --limit; + --lbound; } } QF_CRIT_ENTRY(); - Q_ENSURE_INCRIT(690, isFound && (limit > 0)); + // NOTE: the following postcondition can only succeed when + // (lbound > 0), so no extra check is necessary. + Q_ENSURE_INCRIT(690, isFound); QF_CRIT_EXIT(); return child; // return the child @@ -505,10 +507,11 @@ QState QMsm_execTatbl_( QF_CRIT_EXIT(); QState r = Q_RET_NULL; - int_fast8_t limit = QMSM_MAX_TRAN_LENGTH_; // loop hard limit + int_fast8_t lbound = QMSM_MAX_TRAN_LENGTH_; // fixed upper loop bound QActionHandler const *a = &tatbl->act[0]; - for (; (*a != Q_ACTION_CAST(0)) && (limit > 0); ++a) { + for (; (*a != Q_ACTION_CAST(0)) && (lbound > 0); ++a) { r = (*(*a))(me); // call the action through the 'a' pointer + --lbound; #ifdef Q_SPY QS_CRIT_ENTRY(); QS_MEM_SYS(); @@ -551,9 +554,10 @@ QState QMsm_execTatbl_( QS_MEM_APP(); QS_CRIT_EXIT(); #endif // Q_SPY - --limit; } QF_CRIT_ENTRY(); + // NOTE: the following postcondition can only succeed when + // (lbound > 0), so no extra check is necessary. Q_ENSURE_INCRIT(790, *a == Q_ACTION_CAST(0)); QF_CRIT_EXIT(); @@ -579,8 +583,8 @@ void QMsm_exitToTranSource_( // exit states from the current state to the tran. source state QMState const *s = cs; - int_fast8_t limit = QMSM_MAX_NEST_DEPTH_; // loop hard limit - for (; (s != ts) && (limit > 0); --limit) { + int_fast8_t lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound + for (; (s != ts) && (lbound > 0); --lbound) { // exit action provided in state 's'? if (s->exitAction != Q_ACTION_CAST(0)) { // execute the exit action @@ -606,7 +610,7 @@ void QMsm_exitToTranSource_( } } QF_CRIT_ENTRY(); - Q_ENSURE_INCRIT(890, limit > 0); + Q_ENSURE_INCRIT(890, lbound > 0); QF_CRIT_EXIT(); } diff --git a/src/qf/qf_actq.c b/src/qf/qf_actq.c index 26fca881..9ac61449 100644 --- a/src/qf/qf_actq.c +++ b/src/qf/qf_actq.c @@ -88,7 +88,7 @@ bool QActive_post_(QActive * const me, #ifndef Q_UNSAFE uint8_t const pcopy = (uint8_t)(~me->prio_dis); - Q_REQUIRE_INCRIT(102, (QEvt_verify_(e)) && (me->prio == pcopy)); + Q_INVARIANT_INCRIT(102, (QEvt_verify_(e)) && (me->prio == pcopy)); #endif QEQueueCtr nFree = me->eQueue.nFree; // get volatile into temporary @@ -230,7 +230,7 @@ void QActive_postLIFO_(QActive * const me, #ifndef Q_UNSAFE uint8_t const pcopy = (uint8_t)(~me->prio_dis); - Q_REQUIRE_INCRIT(202, (QEvt_verify_(e)) && (me->prio == pcopy)); + Q_INVARIANT_INCRIT(202, (QEvt_verify_(e)) && (me->prio == pcopy)); #endif #ifdef QXK_H_ diff --git a/src/qf/qf_dyn.c b/src/qf/qf_dyn.c index 9638ba62..dd7934fe 100644 --- a/src/qf/qf_dyn.c +++ b/src/qf/qf_dyn.c @@ -218,7 +218,7 @@ QEvt * QF_newX_( void QF_gc(QEvt const * const e) { QF_CRIT_STAT QF_CRIT_ENTRY(); - Q_REQUIRE_INCRIT(402, QEvt_verify_(e)); + Q_INVARIANT_INCRIT(402, QEvt_verify_(e)); uint_fast8_t const poolNum = QEvt_getPoolNum_(e); @@ -283,7 +283,7 @@ QEvt const * QF_newRef_( QF_CRIT_STAT QF_CRIT_ENTRY(); - Q_REQUIRE_INCRIT(502, QEvt_verify_(e)); + Q_INVARIANT_INCRIT(502, QEvt_verify_(e)); uint_fast8_t const poolNum = QEvt_getPoolNum_(e); @@ -309,11 +309,11 @@ QEvt const * QF_newRef_( //${QF::QF-dyn::deleteRef_} .................................................. //! @static @private @memberof QF void QF_deleteRef_(void const * const evtRef) { - QEvt const * const e = evtRef; + QEvt const * const e = (QEvt const *)evtRef; QF_CRIT_STAT QF_CRIT_ENTRY(); - Q_REQUIRE_INCRIT(602, QEvt_verify_(e)); + Q_INVARIANT_INCRIT(602, QEvt_verify_(e)); #ifdef Q_SPY uint_fast8_t const poolNum = QEvt_getPoolNum_(e); diff --git a/src/qf/qf_mem.c b/src/qf/qf_mem.c index 85789c4d..e0384858 100644 --- a/src/qf/qf_mem.c +++ b/src/qf/qf_mem.c @@ -109,14 +109,14 @@ void QMPool_init(QMPool * const me, ++me->nTot; // one more free block in the pool } - fb->next = (QFreeBlock *)0; // the last link points to NULL + fb->next = (QFreeBlock *)0; // the last link points to NULL #ifndef Q_UNSAFE fb->next_dis = (uintptr_t)(~Q_UINTPTR_CAST_(fb->next)); #endif me->nFree = me->nTot; // all blocks are free me->nMin = me->nTot; // the minimum # free blocks - me->start = poolSto; // the original start this pool buffer + me->start = (QFreeBlock *)poolSto; // the original start this pool buffer me->end = fb; // the last block in this pool QF_MEM_APP(); @@ -148,8 +148,8 @@ void * QMPool_get(QMPool * const me, QFreeBlock * const fb_next = fb->next; // fast temporary // the free block must have integrity (duplicate inverse storage) - Q_ASSERT_INCRIT(302, Q_UINTPTR_CAST_(fb_next) - == (uintptr_t)~fb->next_dis); + Q_INVARIANT_INCRIT(302, Q_UINTPTR_CAST_(fb_next) + == (uintptr_t)~fb->next_dis); --me->nFree; // one less free block if (me->nFree == 0U) { // is the pool becoming empty? @@ -226,7 +226,7 @@ void QMPool_put(QMPool * const me, #endif // set as new head of the free list - me->free_head = block; + me->free_head = fb; ++me->nFree; // one more free block in this pool diff --git a/src/qf/qf_ps.c b/src/qf/qf_ps.c index 294b4a51..685a2483 100644 --- a/src/qf/qf_ps.c +++ b/src/qf/qf_ps.c @@ -110,7 +110,7 @@ void QActive_publish_( QF_MEM_SYS(); Q_REQUIRE_INCRIT(200, sig < (QSignal)QActive_maxPubSignal_); - Q_REQUIRE_INCRIT(202, + Q_INVARIANT_INCRIT(202, QPSet_verify_(&QActive_subscrList_[sig].set, &QActive_subscrList_[sig].set_dis)); @@ -154,9 +154,9 @@ void QActive_publish_( QF_SCHED_STAT_ QF_SCHED_LOCK_(p); // lock the scheduler up to AO's prio - uint_fast8_t limit = QF_MAX_ACTIVE + 1U; + uint_fast8_t lbound = QF_MAX_ACTIVE + 1U; // fixed upper loop bound do { // loop over all subscribers - --limit; + --lbound; // QACTIVE_POST() asserts internally if the queue overflows QACTIVE_POST(a, e, sender); @@ -178,10 +178,12 @@ void QActive_publish_( else { p = 0U; // no more subscribers } - } while ((p != 0U) && (limit > 0U)); + } while ((p != 0U) && (lbound > 0U)); QF_CRIT_ENTRY(); - Q_ENSURE_INCRIT(290, p == 0U); + // NOTE: the following postcondition can only succeed when + // (lbound > 0), so no extra check for lbound is necessary. + Q_ENSURE_INCRIT(290, p == 0U); // all subscribers processed QF_CRIT_EXIT(); QF_SCHED_UNLOCK_(); // unlock the scheduler @@ -213,7 +215,7 @@ void QActive_subscribe(QActive const * const me, && (sig < QActive_maxPubSignal_) && (0U < p) && (p <= QF_MAX_ACTIVE) && (QActive_registry_[p] == me)); - Q_REQUIRE_INCRIT(302, + Q_INVARIANT_INCRIT(302, QPSet_verify_(&QActive_subscrList_[sig].set, &QActive_subscrList_[sig].set_dis)); @@ -252,7 +254,7 @@ void QActive_unsubscribe(QActive const * const me, && (sig < QActive_maxPubSignal_) && (0U < p) && (p <= QF_MAX_ACTIVE) && (QActive_registry_[p] == me)); - Q_REQUIRE_INCRIT(402, + Q_INVARIANT_INCRIT(402, QPSet_verify_(&QActive_subscrList_[sig].set, &QActive_subscrList_[sig].set_dis)); diff --git a/src/qf/qf_time.c b/src/qf/qf_time.c index 7688c4cb..18c3214d 100644 --- a/src/qf/qf_time.c +++ b/src/qf/qf_time.c @@ -316,8 +316,8 @@ void QTimeEvt_tick_( QS_END_PRE_() // scan the linked-list of time events at this rate... - uint_fast8_t limit = 2U*QF_MAX_ACTIVE; // loop hard limit - for (; limit > 0U; --limit) { + uint_fast8_t lbound = 2U*QF_MAX_ACTIVE; // fixed upper loop bound + for (; lbound > 0U; --lbound) { QTimeEvt *e = prev->next; // advance down the time evt. list if (e == (QTimeEvt *)0) { // end of the list? @@ -337,7 +337,7 @@ void QTimeEvt_tick_( } // the time event 'e' must be valid - Q_ASSERT_INCRIT(112, QEvt_verify_(Q_EVT_CAST(QEvt))); + Q_INVARIANT_INCRIT(112, QEvt_verify_(Q_EVT_CAST(QEvt))); if (e->ctr == 0U) { // time event scheduled for removal? prev->next = e->next; @@ -424,7 +424,7 @@ void QTimeEvt_tick_( QF_MEM_SYS(); } - Q_ENSURE_INCRIT(190, limit > 0U); + Q_ENSURE_INCRIT(190, lbound > 0U); QF_MEM_APP(); QF_CRIT_EXIT(); } diff --git a/src/qk/qk.c b/src/qk/qk.c index e2d3dcc5..7ce07988 100644 --- a/src/qk/qk.c +++ b/src/qk/qk.c @@ -78,8 +78,8 @@ QSchedStatus QK_schedLock(uint_fast8_t const ceiling) { QF_MEM_SYS(); Q_REQUIRE_INCRIT(100, !QK_ISR_CONTEXT_()); - Q_REQUIRE_INCRIT(102, QK_priv_.lockCeil - == (uint_fast8_t)(~QK_priv_.lockCeil_dis)); + Q_INVARIANT_INCRIT(102, QK_priv_.lockCeil + == (uint_fast8_t)(~QK_priv_.lockCeil_dis)); // first store the previous lock prio QSchedStatus stat; @@ -118,8 +118,8 @@ void QK_schedUnlock(QSchedStatus const prevCeil) { QF_CRIT_ENTRY(); QF_MEM_SYS(); - Q_REQUIRE_INCRIT(202, QK_priv_.lockCeil - == (uint_fast8_t)(~QK_priv_.lockCeil_dis)); + Q_INVARIANT_INCRIT(202, QK_priv_.lockCeil + == (uint_fast8_t)(~QK_priv_.lockCeil_dis)); Q_REQUIRE_INCRIT(210, (!QK_ISR_CONTEXT_()) && (QK_priv_.lockCeil > prevCeil)); @@ -150,8 +150,8 @@ void QK_schedUnlock(QSchedStatus const prevCeil) { uint_fast8_t QK_sched_(void) { // NOTE: this function is entered with interrupts DISABLED - Q_REQUIRE_INCRIT(402, QPSet_verify_(&QK_priv_.readySet, - &QK_priv_.readySet_dis)); + Q_INVARIANT_INCRIT(402, QPSet_verify_(&QK_priv_.readySet, + &QK_priv_.readySet_dis)); uint_fast8_t p; if (QPSet_isEmpty(&QK_priv_.readySet)) { p = 0U; // no activation needed @@ -160,7 +160,7 @@ uint_fast8_t QK_sched_(void) { // find the highest-prio AO with non-empty event queue p = QPSet_findMax(&QK_priv_.readySet); - Q_ASSERT_INCRIT(412, + Q_INVARIANT_INCRIT(412, QK_priv_.actThre == (uint_fast8_t)(~QK_priv_.actThre_dis)); // is the AO's prio. below the active preemption-threshold? @@ -168,16 +168,16 @@ uint_fast8_t QK_sched_(void) { p = 0U; // no activation needed } else { - Q_ASSERT_INCRIT(422, QK_priv_.lockCeil - == (uint_fast8_t)(~QK_priv_.lockCeil_dis)); + Q_INVARIANT_INCRIT(422, QK_priv_.lockCeil + == (uint_fast8_t)(~QK_priv_.lockCeil_dis)); // is the AO's prio. below the lock-ceiling? if (p <= QK_priv_.lockCeil) { p = 0U; // no activation needed } else { - Q_ASSERT_INCRIT(432, QK_priv_.nextPrio - == (uint_fast8_t)(~QK_priv_.nextPrio_dis)); + Q_INVARIANT_INCRIT(432, QK_priv_.nextPrio + == (uint_fast8_t)(~QK_priv_.nextPrio_dis)); QK_priv_.nextPrio = p; // next AO to run #ifndef Q_UNSAFE QK_priv_.nextPrio_dis = (uint_fast8_t)(~QK_priv_.nextPrio); @@ -197,7 +197,7 @@ void QK_activate_(void) { uint_fast8_t const prio_in = QK_priv_.actPrio; // save initial prio. uint_fast8_t p = QK_priv_.nextPrio; // next prio to run - Q_REQUIRE_INCRIT(502, + Q_INVARIANT_INCRIT(502, (prio_in == (uint_fast8_t)(~QK_priv_.actPrio_dis)) && (p == (uint_fast8_t)(~QK_priv_.nextPrio_dis))); Q_REQUIRE_INCRIT(510, (prio_in <= QF_MAX_ACTIVE) @@ -222,7 +222,7 @@ void QK_activate_(void) { Q_ASSERT_INCRIT(510, a != (QActive *)0); pthre_in = (uint_fast8_t)a->pthre; - Q_ASSERT_INCRIT(511, pthre_in == + Q_INVARIANT_INCRIT(511, pthre_in == (uint_fast8_t)(~(uint_fast8_t)a->pthre_dis & 0xFFU)); } @@ -231,7 +231,7 @@ void QK_activate_(void) { a = QActive_registry_[p]; // obtain the pointer to the AO Q_ASSERT_INCRIT(520, a != (QActive *)0); // the AO must be registered uint_fast8_t const pthre = (uint_fast8_t)a->pthre; - Q_ASSERT_INCRIT(522, pthre == + Q_INVARIANT_INCRIT(522, pthre == (uint_fast8_t)(~(uint_fast8_t)a->pthre_dis & 0xFFU)); // set new active prio. and preemption-threshold @@ -259,6 +259,7 @@ void QK_activate_(void) { } #endif // QF_ON_CONTEXT_SW || Q_SPY + QF_MEM_APP(); QF_INT_ENABLE(); // unconditionally enable interrupts QEvt const * const e = QActive_get_(a); @@ -275,8 +276,8 @@ void QK_activate_(void) { QF_MEM_SYS(); // internal integrity check (duplicate inverse storage) - Q_ASSERT_INCRIT(532, QPSet_verify_(&QK_priv_.readySet, - &QK_priv_.readySet_dis)); + Q_INVARIANT_INCRIT(532, QPSet_verify_(&QK_priv_.readySet, + &QK_priv_.readySet_dis)); if (a->eQueue.frontEvt == (QEvt *)0) { // empty queue? QPSet_remove(&QK_priv_.readySet, p); @@ -297,8 +298,8 @@ void QK_activate_(void) { p = 0U; // no activation needed } else { - Q_ASSERT_INCRIT(542, QK_priv_.lockCeil - == (uint_fast8_t)(~QK_priv_.lockCeil_dis)); + Q_INVARIANT_INCRIT(542, QK_priv_.lockCeil + == (uint_fast8_t)(~QK_priv_.lockCeil_dis)); // is the AO's prio. below the lock preemption-threshold? if (p <= QK_priv_.lockCeil) { diff --git a/src/qs/qs.c b/src/qs/qs.c index a1f63710..f7200b16 100644 --- a/src/qs/qs.c +++ b/src/qs/qs.c @@ -919,7 +919,7 @@ void QS_target_info_pre_(uint8_t const isReset) { QS_U8_PRE_(QS_OBJ_PTR_SIZE | (QS_FUN_PTR_SIZE << 4U)); QS_U8_PRE_(QS_TIME_SIZE); - // send the limits... + // send the bounds... QS_U8_PRE_(QF_MAX_ACTIVE); QS_U8_PRE_(QF_MAX_EPOOL | (QF_MAX_TICK_RATE << 4U)); diff --git a/src/qv/qv.c b/src/qv/qv.c index de4db236..3ec686a2 100644 --- a/src/qv/qv.c +++ b/src/qv/qv.c @@ -77,8 +77,8 @@ void QV_schedDisable(uint_fast8_t const ceiling) { QF_CRIT_ENTRY(); QF_MEM_SYS(); - Q_ASSERT_INCRIT(102, QV_priv_.schedCeil - == (uint_fast8_t)(~QV_priv_.schedCeil_dis)); + Q_INVARIANT_INCRIT(102, QV_priv_.schedCeil + == (uint_fast8_t)(~QV_priv_.schedCeil_dis)); if (ceiling > QV_priv_.schedCeil) { // raising the scheduler ceiling? @@ -105,8 +105,8 @@ void QV_schedEnable(void) { QF_CRIT_ENTRY(); QF_MEM_SYS(); - Q_ASSERT_INCRIT(202, QV_priv_.schedCeil - == (uint_fast8_t)(~QV_priv_.schedCeil_dis)); + Q_INVARIANT_INCRIT(202, QV_priv_.schedCeil + == (uint_fast8_t)(~QV_priv_.schedCeil_dis)); if (QV_priv_.schedCeil != 0U) { // actually enabling the scheduler? @@ -157,7 +157,7 @@ void QF_init(void) { //! @static @public @memberof QF void QF_stop(void) { QF_onCleanup(); // application-specific cleanup callback - // nothing else to do for the cooperative QV kernel + // nothing else to do for the QV kernel } //${QV::QF-cust::run} ........................................................ @@ -189,11 +189,11 @@ int_t QF_run(void) { for (;;) { // QV event loop... // check internal integrity (duplicate inverse storage) - Q_ASSERT_INCRIT(302, QPSet_verify_(&QV_priv_.readySet, - &QV_priv_.readySet_dis)); + Q_INVARIANT_INCRIT(302, QPSet_verify_(&QV_priv_.readySet, + &QV_priv_.readySet_dis)); // check internal integrity (duplicate inverse storage) - Q_ASSERT_INCRIT(303, QV_priv_.schedCeil - == (uint_fast8_t)(~QV_priv_.schedCeil_dis)); + Q_INVARIANT_INCRIT(303, QV_priv_.schedCeil + == (uint_fast8_t)(~QV_priv_.schedCeil_dis)); // find the maximum prio. AO ready to run uint_fast8_t const p = (QPSet_notEmpty(&QV_priv_.readySet) diff --git a/src/qxk/qxk.c b/src/qxk/qxk.c index 155f069c..004f5527 100644 --- a/src/qxk/qxk.c +++ b/src/qxk/qxk.c @@ -166,8 +166,8 @@ QActive * QXK_current(void) { //${QXK::QXK-base::sched_} ................................................... //! @static @private @memberof QXK uint_fast8_t QXK_sched_(void) { - Q_REQUIRE_INCRIT(402, QPSet_verify_(&QXK_priv_.readySet, - &QXK_priv_.readySet_dis)); + Q_INVARIANT_INCRIT(402, QPSet_verify_(&QXK_priv_.readySet, + &QXK_priv_.readySet_dis)); QActive const * const curr = QXK_priv_.curr; uint_fast8_t p; @@ -242,6 +242,7 @@ void QXK_activate_(void) { do { QXK_priv_.actPrio = p; // next active prio + QF_MEM_APP(); QF_INT_ENABLE(); // unconditionally enable interrupts QEvt const * const e = QActive_get_(next); @@ -257,8 +258,8 @@ void QXK_activate_(void) { QF_MEM_SYS(); // check internal integrity (duplicate inverse storage) - Q_ASSERT_INCRIT(502, QPSet_verify_(&QXK_priv_.readySet, - &QXK_priv_.readySet_dis)); + Q_INVARIANT_INCRIT(502, QPSet_verify_(&QXK_priv_.readySet, + &QXK_priv_.readySet_dis)); if (next->eQueue.frontEvt == (QEvt *)0) { // empty queue? QPSet_remove(&QXK_priv_.readySet, p); diff --git a/src/qxk/qxk_mutex.c b/src/qxk/qxk_mutex.c index 6be2032a..59aebaed 100644 --- a/src/qxk/qxk_mutex.c +++ b/src/qxk/qxk_mutex.c @@ -163,7 +163,7 @@ bool QXMutex_lock(QXMutex * const me, // is the mutex locked by this thread already (nested locking)? else if (me->ao.osObject == &curr->super) { - // the nesting level beyond the arbitrary but high limit + // the nesting level beyond the arbitrary but high bound // most likely means cyclic or recursive locking of a mutex. Q_ASSERT_INCRIT(220, me->ao.eQueue.nFree < 0xFFU); @@ -309,7 +309,7 @@ bool QXMutex_tryLock(QXMutex * const me) { } // is the mutex locked by this thread already (nested locking)? else if (me->ao.osObject == curr) { - // the nesting level must not exceed the specified limit + // the nesting level must not exceed the specified bound Q_ASSERT_INCRIT(320, me->ao.eQueue.nFree < 0xFFU); ++me->ao.eQueue.nFree; // lock one more level