diff --git a/cmakeSupport.md b/cmakeSupport.md index 27745df5..0b73c977 100644 --- a/cmakeSupport.md +++ b/cmakeSupport.md @@ -76,7 +76,7 @@ This file is situated in the root directory of qpcpp. It performs a pre-initiali + `arm-cm`, `arm-cr` - Arm CortexM or CortexR micro controllers. Tested with GNU cross compiler environments. + `freertos`, `esp-idf`, `emb-os`, `threadx`, `uc-os2` - real time OS + `msp430`, `pic32` - TI MSP430 or PIC32 micro controllers - + `riscv`- Risc V µC + + `riscv`- Risc V micro controllers + `qep-only`, `qube` - test environments + `win32`, `posix` - host environments MS Windows, Linux (Posix compatible systems) * `QPCPP-CFG-GUI` - BOOL: set this Boolean variable to ON/TRUE, if GUI support (win32) shall be compiled in. Default: OFF diff --git a/examples b/examples index 4325bfa2..01aad80e 160000 --- a/examples +++ b/examples @@ -1 +1 @@ -Subproject commit 4325bfa22d9b9335c3baf4bd7acc95f6c1a8fec7 +Subproject commit 01aad80e4c6f69089ecf7ddc328cad2870505a6e diff --git a/include/qp.hpp b/include/qp.hpp index e141c4ba..78714694 100644 --- a/include/qp.hpp +++ b/include/qp.hpp @@ -36,9 +36,9 @@ #define QP_HPP_ //============================================================================ -#define QP_VERSION_STR "8.0.0" -#define QP_VERSION 800U -#define QP_RELEASE 0x7055936FU +#define QP_VERSION_STR "8.0.1" +#define QP_VERSION 801U +#define QP_RELEASE 0x703931CEU //============================================================================ //! @cond INTERNAL diff --git a/ports/arm-cm/qk/config/qp_config.hpp b/ports/arm-cm/config/qp_config.hpp similarity index 75% rename from ports/arm-cm/qk/config/qp_config.hpp rename to ports/arm-cm/config/qp_config.hpp index ca1f1825..c1beeede 100644 --- a/ports/arm-cm/qk/config/qp_config.hpp +++ b/ports/arm-cm/config/qp_config.hpp @@ -1,5 +1,5 @@ //============================================================================ -// QP configuration file (QK on ARM Cortex-M) +// QP configuration file (QV/QK/QXK on ARM Cortex-M) // // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // @@ -59,19 +59,19 @@ // * Hard-limits for all loops // * Memory Isolation by means of Memory Protection Unit (MPU) -// Disable QP FuSa in development +// Disable QP FuSa in development (NOT recommended) // Disable assertions and other self monitoring features // in development build configurations (NDEBUG undefined). -// VIOLATES functional safety standards. NOT recommended !!! +// NOTE: Disabling safety *violates* functional safety standards. //#ifndef NDEBUG //#define Q_UNSAFE //#endif // -// Disable QP FuSa in production release -// Disable assertions and other self monitoring features +// Disable QP FuSa in production release (NOT recommended) +// Disable assertions and other safety features // in the release build configurations (NDEBUG defined). -// VIOLATES functional safety standards. NOT recommended !!! +// NOTE: Disabling safety *violates* functional safety standards. //#ifdef NDEBUG //#define Q_UNSAFE //#endif @@ -80,7 +80,7 @@ // //.......................................................................... -// QEP Event Processor +// QEP Event Processor (Events) // Events and state machines. // Event signal size (Q_SIGNAL_SIZE) @@ -94,7 +94,7 @@ // //.......................................................................... -// QF Framework +// QF Framework (Active Objects) // Active Object framework // Maximum # Active Objects (QF_MAX_ACTIVE) <1-64> @@ -120,21 +120,6 @@ // Default: 1 #define QF_MAX_TICK_RATE 1U -// Event parameter initialization (QEVT_PAR_INIT) -// Resource Acquisition Is Initialization (RAII) for dynamic events -//#define QEVT_PAR_INIT -// - -// Provide destructors for QP classes -// Destructors for classes -//#define Q_XTOR -// - -// Active Object stop API (QACTIVE_CAN_STOP) -// Enable Active Object stop API (Not recommended) -//#define QACTIVE_CAN_STOP -// - // Event size (QF_EVENT_SIZ_SIZE) // <1U=>1 // <2U=>2 (default) @@ -174,15 +159,75 @@ // Default: 2 (64K bytes maximum block size) #define QF_MPOOL_SIZ_SIZE 2U +// Enable event parameter initialization (QEVT_PAR_INIT) +// Initialize parameters of dynamic events at allocation +// (Resource Acquisition Is Initialization (RAII) for dynamic events) +//#define QEVT_PAR_INIT +// + +// Provide destructors for QP classes +// Presence of destructors pulls in the C++ delete() opeator +// NOTE: Not recommended +//#define Q_XTOR +// + +// Enable active object stop API (QACTIVE_CAN_STOP) +// NOTE: Not recommended +//#define QACTIVE_CAN_STOP +// + +// Enable context switch callback *without* QS (QF_ON_CONTEXT_SW) +// Context switch callback QF_onContextSw() when Q_SPY is undefined. +//#ifndef Q_SPY +//#define QF_ON_CONTEXT_SW +//#endif +// + +// Enable context switch callback *with* QS (QF_ON_CONTEXT_SW) +// Context switch callback QF_onContextSw() when Q_SPY is defined. +//#ifdef Q_SPY +//#define QF_ON_CONTEXT_SW +//#endif +// + +// Enable memory isolation (QF_MEM_ISOLATE) +// Memory isolation (requires MPU) +// NOTE: implies QF_ON_CONTEXT_SW. +//#define QF_MEM_ISOLATE +// + // //.......................................................................... -// QS Software Tracing +// QV/QK/QXK built-in kernels (ARM Cortex-M) + +// Kernel uses critical section based on BASEPRI (QF_USE_BASEPRI) +// If not selected, critical section will be based on PRIMASK +// NOTE: The BASEPRI threshold can be adjusted in the "Text Editor" mode. +//#define QF_USE_BASEPRI 0x3F +// + +// QK Kernel uses IRQ for return-from-preemption +// NOTE: Use "editor mode" to edit QK_USE_IRQ_NUM +// NOTE: Use "editor mode" to edit QK_USE_IRQ_HANDLER +//#define QK_USE_IRQ_NUM NNN +//#define QK_USE_IRQ_HANDLER XXX_IRQHandler +// + +// QXK Kernel uses IRQ for return-from-preemption +// NOTE: Use "editor mode" to edit QXK_USE_IRQ_NUM +// NOTE: Use "editor mode" to edit QXK_USE_IRQ_HANDLER +//#define QXK_USE_IRQ_NUM NNN +//#define QXK_USE_IRQ_HANDLER XXX_IRQHandler +// + +// + +//.......................................................................... +// QS Software Tracing (Q_SPY) // Target-resident component of QP/Spy software tracing system // (tracing instrumentation and command-input). - -// NOTE: Requires command-line macro: Q_SPY -// The QS software tracing instrumentation is activated only when +// NOTE: The QS software tracing instrumentation is activated only when // the macro Q_SPY is defined on the command-line to the compiler. // Typically, Q_SPY is defined only in the "spy" build configuration. @@ -204,47 +249,6 @@ // -//.......................................................................... -// QK Preemptive Non-Blocking Kernel -// Preemptive non-blocking/blocking RTOS kernel. - -// Context switch callback (QF_ON_CONTEXT_SW) - -// Context switch callback WITHOUT QS -// Enable context switch callback QF_onContextSw() -// When Q_SPY is undefined. -//#ifndef Q_SPY -//#define QF_ON_CONTEXT_SW -//#endif -// - -// Context switch callback WITH QS -// Enable context switch callback QF_onContextSw() -// When Q_SPY is defined. -//#ifdef Q_SPY -//#define QF_ON_CONTEXT_SW -//#endif -// - -// - -// MPU memory isolation (QF_MEM_ISOLATE) -// Enable memory isolation (requires MPU) -// NOTE: implies QF_ON_CONTEXT_SW. -//#define QF_MEM_ISOLATE -// - -// Use IRQ handler for QK return-from-preemption -// Enable this option only if the NMI handler is used in the project. -// If enabled, provide the otherwise unused IRQ number (QK_USE_IRQ_NUM) -// and the corresponding IRQ handler name (QK_USE_IRQ_HANDLER) -// in the "Text Editor" mode. -//#define QK_USE_IRQ_NUM -//#define QK_USE_IRQ_HANDLER -// - -// - //------------- <<< end of configuration section >>> ----------------------- #endif // QP_CONFIG_HPP_ diff --git a/ports/arm-cm/qk/armclang/qk_port.cpp b/ports/arm-cm/qk/armclang/qk_port.cpp index 23aad6d6..d592a6a2 100644 --- a/ports/arm-cm/qk/armclang/qk_port.cpp +++ b/ports/arm-cm/qk/armclang/qk_port.cpp @@ -26,12 +26,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 -//! @version Last updated for: @ref qpc_8_0_0 -//! -//! @file -//! @brief QK/C++ port to ARM Cortex-M, ARM-CLANG - #define QP_IMPL 1U #include "qp_port.hpp" #include "qsafe.h" // QP Functional Safety (FuSa) Subsystem @@ -70,7 +64,6 @@ void NMI_Handler(void); // For best performance, these functions are implemented in assembly, // but they can be implemented in C as well. - //std::int32_t volatile QF_int_lock_nest_; // not used extern char const QF_port_module_[]; char const QF_port_module_[] = "qk_port"; @@ -79,24 +72,23 @@ char const QF_port_module_[] = "qk_port"; // Unconditionally disable interrupts. // NOTE: this function must NOT use the stack. // -// description: -// On ARMv6-M, interrupts are disabled with the PRIMASK register. -// On ARMv7-M and higher, interrupts are disabled *selectively* with the -// BASEPRI register. +// Description: +// When QF_USE_BASEPRI is defined, interrupts are disabled with BASEPRI. +// Otherwise interrupts are disabled with the PRIMASK register. // Additionally, the function also asserts that the interrupts are // NOT disabled upon the entry to the function, which means that // this interrupt management policy CANNOT nest. __attribute__ ((naked, weak)) void QF_int_disable_(void) { __asm volatile ( -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK - " CPSID i \n" // set PRIMASK -#else //--------- ARMv7-M or higher +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for interrupt disabling? " MRS r0,BASEPRI \n" // r0 <- previous BASEPRI - " MOVS r1,#" STRINGIFY(QF_BASEPRI) "\n" + " MOVS r1,#" STRINGIFY(QF_USE_BASEPRI) "\n" " MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK -#endif //--------- ARMv7-M or higher +#else //--------- use PRIMASK for disabling interrupts + " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK + " CPSID i \n" // set PRIMASK +#endif //--------- use PRIMASK for disabling interrupts " CMP r0,#0 \n" // assert(PRIMASK/BASEPRI == 0) " BNE QF_int_disable_error\n" " BX lr \n" @@ -111,28 +103,29 @@ __asm volatile ( // Unconditionally enable interrupts. // NOTE: this function must NOT use the stack. // -// description: -// On ARMv6-M, interrupts are enabled with the PRIMASK register. -// On ARMv7-M and higher, interrupts are enabled with the BASEPRI register. +// Description: +// When QF_USE_BASEPRI is defined, interrupts are enabled with BASEPRI. +// Otherwise interrupts are enabled with the PRIMASK register. // Additionally, the function also asserts that the interrupts ARE // disabled upon the entry to the function, which means that // this interrupt management policy CANNOT nest. __attribute__ ((naked, weak)) void QF_int_enable_(void) { __asm volatile ( -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK -#else //--------- ARMv7-M or higher +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for enabling interrupts? " MRS r0,BASEPRI \n" // r0 <- previous BASEPRI -#endif //--------- ARMv7-M or higher +#else //--------- use PRIMASK for enabling interrupts + " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK +#endif //--------- use PRIMASK for enabling interrupts + " CMP r0,#0 \n" // assert(PRIMASK/BASEPRI != 0) " BEQ QF_int_enable_error\n" -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " CPSIE i \n" // clear PRIMASK -#else //--------- ARMv7-M or higher +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for enabling interrupts? " MOVS r1,#0 \n" " MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK -#endif //--------- ARMv7-M or higher +#else //--------- use PRIMASK for enabling interrupts + " CPSIE i \n" // clear PRIMASK +#endif //--------- use PRIMASK for enabling interrupts " BX lr \n" "QF_int_enable_error: \n" " LDR r0,=QF_port_module_ \n" @@ -145,25 +138,23 @@ __asm volatile ( // Enter QF critical section. // NOTE: this function must NOT use the stack. // -// description: -// On ARMv6-M, critical section is entered by disabling interrupts -// with the PRIMASK register. -// On ARMv7-M and higher, critical section is entered by disabling -// interrupts *selectively* with the BASEPRI register. +// Description: +// When QF_USE_BASEPRI is defined, critical section uses BASEPRI. +// Otherwise, critical section uses the PRIMASK register. // Additionally, the function also asserts that the interrupts are // NOT disabled upon the entry to the function, which means that // this critical section CANNOT nest. __attribute__ ((naked, weak)) void QF_crit_entry_(void) { __asm volatile ( -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK - " CPSID i \n" // set PRIMASK -#else //--------- ARMv7-M or higher +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section? " MRS r0,BASEPRI \n" // r0 <- previous BASEPRI - " MOVS r1,#" STRINGIFY(QF_BASEPRI) "\n" + " MOVS r1,#" STRINGIFY(QF_USE_BASEPRI) "\n" " MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK -#endif //--------- ARMv7-M or higher +#else //--------- use PRIMASK for critical section + " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK + " CPSID i \n" // set PRIMASK +#endif //--------- use PRIMASK for critical section " CMP r0,#0 \n" // assert(PRIMASK/BASEPRI == 0) " BNE QF_crit_entry_error\n" " BX lr \n" @@ -179,29 +170,27 @@ __asm volatile ( // NOTE: this function must NOT use the stack. // // description: -// On ARMv6-M, critical section is exited by enabling interrupts -// with the PRIMASK register. -// On ARMv7-M and higher, critical section is exited by enabling -// interrupts with the BASEPRI register. +// When QF_USE_BASEPRI is defined, critical section uses BASEPRI. +// Otherwise, critical section uses the PRIMASK register. // Additionally, the function also asserts that the interrupts ARE // disabled upon the entry to the function, which means that // this critical section CANNOT nest. __attribute__ ((naked, weak)) void QF_crit_exit_(void) { __asm volatile ( -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK -#else //--------- ARMv7-M or higher +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section? " MRS r0,BASEPRI \n" // r0 <- previous BASEPRI -#endif //--------- ARMv7-M or higher +#else //--------- use PRIMASK for critical section + " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK +#endif //--------- use PRIMASK for critical section " CMP r0,#0 \n" // assert(PRIMASK/BASEPRI != 0) " BEQ QF_crit_exit_error\n" -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " CPSIE i \n" // clear PRIMASK -#else //--------- ARMv7-M or higher +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section? " MOVS r1,#0 \n" " MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK -#endif //--------- ARMv7-M or higher +#else //--------- use PRIMASK + " CPSIE i \n" // clear PRIMASK +#endif //--------- use PRIMASK " BX lr \n" "QF_crit_exit_error: \n" " LDR r0,=QF_port_module_ \n" @@ -219,7 +208,7 @@ __asm volatile ( // BASEPRI register. However, this method cannot disable interrupt // priority zero, which is the default for all interrupts out of reset. // The following code changes the SysTick priority and all IRQ priorities -// to the safe value QF_BASEPRI, which the QF critical section can disable. +// to the safe value QF_USE_BASEPRI, which the QF critical section can disable. // This avoids breaching of the QF critical sections in case the // application programmer forgets to explicitly set priorities of all // "kernel aware" interrupts. @@ -228,18 +217,18 @@ __asm volatile ( // by the application-level code. void QK_init(void) { -#if (__ARM_ARCH != 6) //--------- if ARMv7-M and higher... +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section? // SCB_SYSPRI[2]: SysTick - SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_BASEPRI << 24U)); + SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_USE_BASEPRI << 24U)); - // set all 240 possible IRQ priories to QF_BASEPRI... + // set all 240 possible IRQ priories to QF_USE_BASEPRI... for (uint_fast8_t n = 0U; n < (240U/sizeof(uint32_t)); ++n) { - NVIC_IP[n] = (QF_BASEPRI << 24U) | (QF_BASEPRI << 16U) - | (QF_BASEPRI << 8U) | QF_BASEPRI; + NVIC_IP[n] = (QF_USE_BASEPRI << 24U) | (QF_USE_BASEPRI << 16U) + | (QF_USE_BASEPRI << 8U) | QF_USE_BASEPRI; } -#endif //--------- ARMv7-M or higher +#endif //--------- use BASEPRI for critical section // SCB_SYSPRI[2]: PendSV set to priority 0xFF (lowest) SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (0xFFU << 16U)); @@ -374,9 +363,12 @@ void QK_thread_ret(void) { #endif //--------- use the NMI #else //--------- ARMv7-M and higher... + +#ifdef QF_USE_BASEPRI //--------- QF_USE_BASEPRI " CPSID i \n" // disable interrupts with PRIMASK " LDR r0,=QF_int_enable_ \n" " BLX r0 \n" // enable interrupts with BASEPRI +#endif //--------- QF_USE_BASEPRI // NOTE: interrupts remain disabled with PRIMASK #ifdef __ARM_FP //--------- if VFP available... @@ -392,7 +384,12 @@ void QK_thread_ret(void) { " MOVS r1,#1 \n" " LSLS r1,r1,#" STRINGIFY(QK_USE_IRQ_NUM & 0x1F) "\n" // r1 := IRQ bit " STR r1,[r0] \n" // pend the IRQ +#ifdef QF_USE_BASEPRI //--------- QF_USE_BASEPRI " CPSIE i \n" // enable interrupts with PRIMASK +#else //--------- interrupt disabling with PRIMASK + " LDR r0,=QF_int_enable_ \n" + " BLX r0 \n" // enable interrupts with BASEPRI +#endif //--------- interrupt disabling with PRIMASK // This code stops here and continues in the IRQ handler #else //--------- use the NMI (default) @@ -442,15 +439,16 @@ void NMI_Handler(void) { __asm volatile ( " ADD sp,sp,#(8*4) \n" // remove one 8-register exception frame -#if (__ARM_ARCH == 6) //--------- if ARMv6-M... +#ifdef QF_USE_BASEPRI //--------- QF_USE_BASEPRI + // NOTE: QF_int_enable_() already called + " CPSIE i \n" // enable interrupts with PRIMASK +#else //--------- interrupt disabling with PRIMASK " LDR r0,=QF_int_enable_ \n" " BLX r0 \n" // enable interrupts with PRIMASK // NOTE: calling QF_int_enable_() corrupted the lr (EXC_RETURN), but // it is NOT used to used to return from the exception. (See POP {r0,pc}) -#else //--------- ARMv7-M and higher... - " CPSIE i \n" // enable interrupts with PRIMASK -#endif //--------- ARMv7-M and higher +#endif //--------- interrupt disabling with PRIMASK " POP {r0,pc} \n" // pop stack aligner and EXC_RETURN to pc ); // NOTE: this causes exception-return to the preempted *thread* context diff --git a/ports/arm-cm/qk/armclang/qp_port.hpp b/ports/arm-cm/qk/armclang/qp_port.hpp index ecea1f76..c0e37fd1 100644 --- a/ports/arm-cm/qk/armclang/qp_port.hpp +++ b/ports/arm-cm/qk/armclang/qp_port.hpp @@ -27,12 +27,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QP/C++ port to ARM Cortex-M, preemptive QK kernel, ARM-CLANG - #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ @@ -47,32 +41,9 @@ // QK event-queue used for AOs #define QACTIVE_EQUEUE_TYPE QEQueue -// QF "thread" type used to store the MPU settings in the AO +// QActive "thread" type used to store the MPU settings in the AO #define QACTIVE_THREAD_TYPE void const * -// QF interrupt disable/enable and log2()... -#if (__ARM_ARCH == 6) // ARMv6-M? - - // CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4 - #define QF_AWARE_ISR_CMSIS_PRI 0 - - // hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M) - #define QF_LOG2(n_) QF_qlog2(static_cast(n_)) - -#else // ARMv7-M or higher - - // BASEPRI threshold for "QF-aware" interrupts, see NOTE3 - #define QF_BASEPRI 0x3F - - // CMSIS threshold for "QF-aware" interrupts, see NOTE4 - #define QF_AWARE_ISR_CMSIS_PRI (QF_BASEPRI >> (8 - __NVIC_PRIO_BITS)) - - // ARMv7-M or higher provide the CLZ instruction for fast LOG2 - #define QF_LOG2(n_) \ - (static_cast(32 - __builtin_clz((n_)))) - -#endif - // interrupt disabling policy, see NOTE2 and NOTE3 #define QF_INT_DISABLE() (QF_int_disable_()) #define QF_INT_ENABLE() (QF_int_enable_()) @@ -84,11 +55,28 @@ #define QF_CRIT_EXIT_NOP() __asm volatile ("isb" ::: "memory") +// Efficient log2() ---------------------------------------------------------- #if (__ARM_ARCH == 6) // ARMv6-M? + // hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M) + #define QF_LOG2(n_) QF_qlog2(static_cast(n_)) + // hand-optimized quick LOG2 in assembly extern "C" std::uint_fast8_t QF_qlog2(std::uint32_t x); +#else // ARMv7-M or higher + // ARMv7-M or higher provide the CLZ instruction for fast LOG2 + #define QF_LOG2(n_) \ + (static_cast(32 - __builtin_clz((n_)))) #endif // ARMv7-M or higher +// Critical section policy --------------------------------------------------- +#ifdef QF_USE_BASEPRI + // CMSIS threshold for "QF-aware" interrupts, see NOTE4 + #define QF_AWARE_ISR_CMSIS_PRI (QF_USE_BASEPRI >> (8 - __NVIC_PRIO_BITS)) +#else + // CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4 + #define QF_AWARE_ISR_CMSIS_PRI 0 +#endif // QF_USE_BASEPRI + // Memory isolation ---------------------------------------------------------- #ifdef QF_MEM_ISOLATE @@ -105,7 +93,7 @@ extern "C" void QF_onMemSys(void); extern "C" void QF_onMemApp(void); -#endif // def QF_MEM_ISOLATE +#endif // QF_MEM_ISOLATE // determination if the code executes in the ISR context #define QK_ISR_CONTEXT_() (QK_get_IPSR() != 0U) @@ -154,7 +142,7 @@ static inline uint32_t QK_get_IPSR(void) { #endif // ARMv6-M // initialization of the QK kernel -#define QK_INIT() QK_init() +#define QK_INIT() QK_init() extern "C" void QK_init(void); extern "C" void QK_thread_ret(void); @@ -189,7 +177,7 @@ extern "C" { // functions. They are defined as "weak" in the qv_port.c module, // so the application can provide a different implementation. // Please see the definitions of the interrupt and critical-section -// funcctions in the qv_port.c module for details. +// functions in the qv_port.c module for details. // // NOTE2: // On Cortex-M0/M0+/M1 (architecture ARMv6-M, ARMv6S-M), the interrupt @@ -198,15 +186,15 @@ extern "C" { // are "kernel-aware". // // NOTE3: -// On ARMv7-M or higher, the interrupt disable/enable policy uses the BASEPRI -// register (which is not implemented in ARMv6-M) to disable interrupts only -// with priority lower than the threshold specified by the QF_BASEPRI macro. -// The interrupts with priorities above QF_BASEPRI (i.e., with numerical -// priority values lower than QF_BASEPRI) are NOT disabled in this method. +// If macro QF_USE_BASEPRI is defined, the interrupt disable/enable policy +// uses BASEPRI register to disable interrupts only with priority lower than +// the threshold specified by the QF_USE_BASEPRI macro. The interrupts with +// priorities above QF_USE_BASEPRI (i.e., with numerical priority values +// lower than QF_USE_BASEPRI) are NOT disabled in this method. // These free-running interrupts have very low ("zero") latency, but they // are NOT allowed to call any QF services, because QF is unaware of them // ("kernel-unaware" interrupts). Consequently, only interrupts with -// numerical values of priorities equal to or higher than QF_BASEPRI +// numerical values of priorities equal to or higher than QF_USE_BASEPRI // ("kernel-aware" interrupts ), can call QF services. // // NOTE4: diff --git a/ports/arm-cm/qk/gnu/qk_port.cpp b/ports/arm-cm/qk/gnu/qk_port.cpp index 92e7d461..ff8a77a8 100644 --- a/ports/arm-cm/qk/gnu/qk_port.cpp +++ b/ports/arm-cm/qk/gnu/qk_port.cpp @@ -26,12 +26,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 -//! @version Last updated for: @ref qpc_8_0_0 -//! -//! @file -//! @brief QK/C++ port to ARM Cortex-M, GNU-ARM - #define QP_IMPL 1U #include "qp_port.hpp" #include "qsafe.h" // QP Functional Safety (FuSa) Subsystem @@ -70,7 +64,6 @@ void NMI_Handler(void); // For best performance, these functions are implemented in assembly, // but they can be implemented in C as well. - //std::int32_t volatile QF_int_lock_nest_; // not used extern char const QF_port_module_[]; char const QF_port_module_[] = "qk_port"; @@ -79,24 +72,23 @@ char const QF_port_module_[] = "qk_port"; // Unconditionally disable interrupts. // NOTE: this function must NOT use the stack. // -// description: -// On ARMv6-M, interrupts are disabled with the PRIMASK register. -// On ARMv7-M and higher, interrupts are disabled *selectively* with the -// BASEPRI register. +// Description: +// When QF_USE_BASEPRI is defined, interrupts are disabled with BASEPRI. +// Otherwise interrupts are disabled with the PRIMASK register. // Additionally, the function also asserts that the interrupts are // NOT disabled upon the entry to the function, which means that // this interrupt management policy CANNOT nest. __attribute__ ((naked, weak)) void QF_int_disable_(void) { __asm volatile ( -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK - " CPSID i \n" // set PRIMASK -#else //--------- ARMv7-M or higher +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for interrupt disabling? " MRS r0,BASEPRI \n" // r0 <- previous BASEPRI - " MOVS r1,#" STRINGIFY(QF_BASEPRI) "\n" + " MOVS r1,#" STRINGIFY(QF_USE_BASEPRI) "\n" " MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK -#endif //--------- ARMv7-M or higher +#else //--------- use PRIMASK for disabling interrupts + " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK + " CPSID i \n" // set PRIMASK +#endif //--------- use PRIMASK for disabling interrupts " CMP r0,#0 \n" // assert(PRIMASK/BASEPRI == 0) " BNE QF_int_disable_error\n" " BX lr \n" @@ -111,28 +103,29 @@ __asm volatile ( // Unconditionally enable interrupts. // NOTE: this function must NOT use the stack. // -// description: -// On ARMv6-M, interrupts are enabled with the PRIMASK register. -// On ARMv7-M and higher, interrupts are enabled with the BASEPRI register. +// Description: +// When QF_USE_BASEPRI is defined, interrupts are enabled with BASEPRI. +// Otherwise interrupts are enabled with the PRIMASK register. // Additionally, the function also asserts that the interrupts ARE // disabled upon the entry to the function, which means that // this interrupt management policy CANNOT nest. __attribute__ ((naked, weak)) void QF_int_enable_(void) { __asm volatile ( -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK -#else //--------- ARMv7-M or higher +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for enabling interrupts? " MRS r0,BASEPRI \n" // r0 <- previous BASEPRI -#endif //--------- ARMv7-M or higher +#else //--------- use PRIMASK for enabling interrupts + " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK +#endif //--------- use PRIMASK for enabling interrupts + " CMP r0,#0 \n" // assert(PRIMASK/BASEPRI != 0) " BEQ QF_int_enable_error\n" -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " CPSIE i \n" // clear PRIMASK -#else //--------- ARMv7-M or higher +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for enabling interrupts? " MOVS r1,#0 \n" " MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK -#endif //--------- ARMv7-M or higher +#else //--------- use PRIMASK for enabling interrupts + " CPSIE i \n" // clear PRIMASK +#endif //--------- use PRIMASK for enabling interrupts " BX lr \n" "QF_int_enable_error: \n" " LDR r0,=QF_port_module_ \n" @@ -145,25 +138,23 @@ __asm volatile ( // Enter QF critical section. // NOTE: this function must NOT use the stack. // -// description: -// On ARMv6-M, critical section is entered by disabling interrupts -// with the PRIMASK register. -// On ARMv7-M and higher, critical section is entered by disabling -// interrupts *selectively* with the BASEPRI register. +// Description: +// When QF_USE_BASEPRI is defined, critical section uses BASEPRI. +// Otherwise, critical section uses the PRIMASK register. // Additionally, the function also asserts that the interrupts are // NOT disabled upon the entry to the function, which means that // this critical section CANNOT nest. __attribute__ ((naked, weak)) void QF_crit_entry_(void) { __asm volatile ( -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK - " CPSID i \n" // set PRIMASK -#else //--------- ARMv7-M or higher +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section? " MRS r0,BASEPRI \n" // r0 <- previous BASEPRI - " MOVS r1,#" STRINGIFY(QF_BASEPRI) "\n" + " MOVS r1,#" STRINGIFY(QF_USE_BASEPRI) "\n" " MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK -#endif //--------- ARMv7-M or higher +#else //--------- use PRIMASK for critical section + " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK + " CPSID i \n" // set PRIMASK +#endif //--------- use PRIMASK for critical section " CMP r0,#0 \n" // assert(PRIMASK/BASEPRI == 0) " BNE QF_crit_entry_error\n" " BX lr \n" @@ -179,29 +170,27 @@ __asm volatile ( // NOTE: this function must NOT use the stack. // // description: -// On ARMv6-M, critical section is exited by enabling interrupts -// with the PRIMASK register. -// On ARMv7-M and higher, critical section is exited by enabling -// interrupts with the BASEPRI register. +// When QF_USE_BASEPRI is defined, critical section uses BASEPRI. +// Otherwise, critical section uses the PRIMASK register. // Additionally, the function also asserts that the interrupts ARE // disabled upon the entry to the function, which means that // this critical section CANNOT nest. __attribute__ ((naked, weak)) void QF_crit_exit_(void) { __asm volatile ( -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK -#else //--------- ARMv7-M or higher +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section? " MRS r0,BASEPRI \n" // r0 <- previous BASEPRI -#endif //--------- ARMv7-M or higher +#else //--------- use PRIMASK for critical section + " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK +#endif //--------- use PRIMASK for critical section " CMP r0,#0 \n" // assert(PRIMASK/BASEPRI != 0) " BEQ QF_crit_exit_error\n" -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " CPSIE i \n" // clear PRIMASK -#else //--------- ARMv7-M or higher +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section? " MOVS r1,#0 \n" " MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK -#endif //--------- ARMv7-M or higher +#else //--------- use PRIMASK + " CPSIE i \n" // clear PRIMASK +#endif //--------- use PRIMASK " BX lr \n" "QF_crit_exit_error: \n" " LDR r0,=QF_port_module_ \n" @@ -219,7 +208,7 @@ __asm volatile ( // BASEPRI register. However, this method cannot disable interrupt // priority zero, which is the default for all interrupts out of reset. // The following code changes the SysTick priority and all IRQ priorities -// to the safe value QF_BASEPRI, which the QF critical section can disable. +// to the safe value QF_USE_BASEPRI, which the QF critical section can disable. // This avoids breaching of the QF critical sections in case the // application programmer forgets to explicitly set priorities of all // "kernel aware" interrupts. @@ -228,18 +217,18 @@ __asm volatile ( // by the application-level code. void QK_init(void) { -#if (__ARM_ARCH != 6) //--------- if ARMv7-M and higher... +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section? // SCB_SYSPRI[2]: SysTick - SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_BASEPRI << 24U)); + SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_USE_BASEPRI << 24U)); - // set all 240 possible IRQ priories to QF_BASEPRI... + // set all 240 possible IRQ priories to QF_USE_BASEPRI... for (uint_fast8_t n = 0U; n < (240U/sizeof(uint32_t)); ++n) { - NVIC_IP[n] = (QF_BASEPRI << 24U) | (QF_BASEPRI << 16U) - | (QF_BASEPRI << 8U) | QF_BASEPRI; + NVIC_IP[n] = (QF_USE_BASEPRI << 24U) | (QF_USE_BASEPRI << 16U) + | (QF_USE_BASEPRI << 8U) | QF_USE_BASEPRI; } -#endif //--------- ARMv7-M or higher +#endif //--------- use BASEPRI for critical section // SCB_SYSPRI[2]: PendSV set to priority 0xFF (lowest) SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (0xFFU << 16U)); @@ -383,9 +372,12 @@ void QK_thread_ret(void) { #endif //--------- use the NMI #else //--------- ARMv7-M and higher... + +#ifdef QF_USE_BASEPRI //--------- QF_USE_BASEPRI " CPSID i \n" // disable interrupts with PRIMASK " LDR r0,=QF_int_enable_ \n" " BLX r0 \n" // enable interrupts with BASEPRI +#endif //--------- QF_USE_BASEPRI // NOTE: interrupts remain disabled with PRIMASK #ifdef __ARM_FP //--------- if VFP available... @@ -401,7 +393,12 @@ void QK_thread_ret(void) { " MOV r1,#1 \n" " LSL r1,r1,#" STRINGIFY(QK_USE_IRQ_NUM & 0x1F) "\n" // r1 := IRQ bit " STR r1,[r0] \n" // pend the IRQ +#ifdef QF_USE_BASEPRI //--------- QF_USE_BASEPRI " CPSIE i \n" // enable interrupts with PRIMASK +#else //--------- interrupt disabling with PRIMASK + " LDR r0,=QF_int_enable_ \n" + " BLX r0 \n" // enable interrupts with BASEPRI +#endif //--------- interrupt disabling with PRIMASK // This code stops here and continues in the IRQ handler #else //--------- use the NMI (default) @@ -451,15 +448,16 @@ void NMI_Handler(void) { __asm volatile ( " ADD sp,sp,#(8*4) \n" // remove one 8-register exception frame -#if (__ARM_ARCH == 6) //--------- if ARMv6-M... +#ifdef QF_USE_BASEPRI //--------- QF_USE_BASEPRI + // NOTE: QF_int_enable_() already called + " CPSIE i \n" // enable interrupts with PRIMASK +#else //--------- interrupt disabling with PRIMASK " LDR r0,=QF_int_enable_ \n" " BLX r0 \n" // enable interrupts with PRIMASK // NOTE: calling QF_int_enable_() corrupted the lr (EXC_RETURN), but // it is NOT used to used to return from the exception. (See POP {r0,pc}) -#else //--------- ARMv7-M and higher... - " CPSIE i \n" // enable interrupts with PRIMASK -#endif //--------- ARMv7-M and higher +#endif //--------- interrupt disabling with PRIMASK " POP {r0,pc} \n" // pop stack aligner and EXC_RETURN to pc ); // NOTE: this causes exception-return to the preempted *thread* context diff --git a/ports/arm-cm/qk/gnu/qp_port.hpp b/ports/arm-cm/qk/gnu/qp_port.hpp index a10a94ce..c0e37fd1 100644 --- a/ports/arm-cm/qk/gnu/qp_port.hpp +++ b/ports/arm-cm/qk/gnu/qp_port.hpp @@ -27,12 +27,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QP/C++ port to ARM Cortex-M, preemptive QK kernel, GNU-ARM - #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ @@ -47,32 +41,9 @@ // QK event-queue used for AOs #define QACTIVE_EQUEUE_TYPE QEQueue -// QF "thread" type used to store the MPU settings in the AO +// QActive "thread" type used to store the MPU settings in the AO #define QACTIVE_THREAD_TYPE void const * -// QF interrupt disable/enable and log2()... -#if (__ARM_ARCH == 6) // ARMv6-M? - - // CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4 - #define QF_AWARE_ISR_CMSIS_PRI 0 - - // hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M) - #define QF_LOG2(n_) QF_qlog2(static_cast(n_)) - -#else // ARMv7-M or higher - - // BASEPRI threshold for "QF-aware" interrupts, see NOTE3 - #define QF_BASEPRI 0x3F - - // CMSIS threshold for "QF-aware" interrupts, see NOTE4 - #define QF_AWARE_ISR_CMSIS_PRI (QF_BASEPRI >> (8 - __NVIC_PRIO_BITS)) - - // ARMv7-M or higher provide the CLZ instruction for fast LOG2 - #define QF_LOG2(n_) \ - (static_cast(32 - __builtin_clz((n_)))) - -#endif - // interrupt disabling policy, see NOTE2 and NOTE3 #define QF_INT_DISABLE() (QF_int_disable_()) #define QF_INT_ENABLE() (QF_int_enable_()) @@ -84,11 +55,28 @@ #define QF_CRIT_EXIT_NOP() __asm volatile ("isb" ::: "memory") +// Efficient log2() ---------------------------------------------------------- #if (__ARM_ARCH == 6) // ARMv6-M? + // hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M) + #define QF_LOG2(n_) QF_qlog2(static_cast(n_)) + // hand-optimized quick LOG2 in assembly extern "C" std::uint_fast8_t QF_qlog2(std::uint32_t x); +#else // ARMv7-M or higher + // ARMv7-M or higher provide the CLZ instruction for fast LOG2 + #define QF_LOG2(n_) \ + (static_cast(32 - __builtin_clz((n_)))) #endif // ARMv7-M or higher +// Critical section policy --------------------------------------------------- +#ifdef QF_USE_BASEPRI + // CMSIS threshold for "QF-aware" interrupts, see NOTE4 + #define QF_AWARE_ISR_CMSIS_PRI (QF_USE_BASEPRI >> (8 - __NVIC_PRIO_BITS)) +#else + // CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4 + #define QF_AWARE_ISR_CMSIS_PRI 0 +#endif // QF_USE_BASEPRI + // Memory isolation ---------------------------------------------------------- #ifdef QF_MEM_ISOLATE @@ -105,7 +93,7 @@ extern "C" void QF_onMemSys(void); extern "C" void QF_onMemApp(void); -#endif // def QF_MEM_ISOLATE +#endif // QF_MEM_ISOLATE // determination if the code executes in the ISR context #define QK_ISR_CONTEXT_() (QK_get_IPSR() != 0U) @@ -189,7 +177,7 @@ extern "C" { // functions. They are defined as "weak" in the qv_port.c module, // so the application can provide a different implementation. // Please see the definitions of the interrupt and critical-section -// funcctions in the qv_port.c module for details. +// functions in the qv_port.c module for details. // // NOTE2: // On Cortex-M0/M0+/M1 (architecture ARMv6-M, ARMv6S-M), the interrupt @@ -198,15 +186,15 @@ extern "C" { // are "kernel-aware". // // NOTE3: -// On ARMv7-M or higher, the interrupt disable/enable policy uses the BASEPRI -// register (which is not implemented in ARMv6-M) to disable interrupts only -// with priority lower than the threshold specified by the QF_BASEPRI macro. -// The interrupts with priorities above QF_BASEPRI (i.e., with numerical -// priority values lower than QF_BASEPRI) are NOT disabled in this method. +// If macro QF_USE_BASEPRI is defined, the interrupt disable/enable policy +// uses BASEPRI register to disable interrupts only with priority lower than +// the threshold specified by the QF_USE_BASEPRI macro. The interrupts with +// priorities above QF_USE_BASEPRI (i.e., with numerical priority values +// lower than QF_USE_BASEPRI) are NOT disabled in this method. // These free-running interrupts have very low ("zero") latency, but they // are NOT allowed to call any QF services, because QF is unaware of them // ("kernel-unaware" interrupts). Consequently, only interrupts with -// numerical values of priorities equal to or higher than QF_BASEPRI +// numerical values of priorities equal to or higher than QF_USE_BASEPRI // ("kernel-aware" interrupts ), can call QF services. // // NOTE4: @@ -221,8 +209,6 @@ extern "C" { // is intended only for applications and is not used inside the QF port, which // remains generic and not dependent on the number of implemented priority bits // implemented in the NVIC. -// -// #endif // QP_PORT_HPP_ diff --git a/ports/arm-cm/qk/iar/qk_port.cpp b/ports/arm-cm/qk/iar/qk_port.cpp index d26ab448..3fb52a88 100644 --- a/ports/arm-cm/qk/iar/qk_port.cpp +++ b/ports/arm-cm/qk/iar/qk_port.cpp @@ -26,12 +26,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 -//! @version Last updated for: @ref qpc_8_0_0 -//! -//! @file -//! @brief QK/C++ port to ARM Cortex-M, IAR-ARM - #define QP_IMPL 1U #include "qp_port.hpp" #include "qsafe.h" // QP Functional Safety (FuSa) Subsystem @@ -83,24 +77,23 @@ char const QF_port_module_[] = "qk_port"; // Unconditionally disable interrupts. // NOTE: this function must NOT use the stack. // -// description: -// On ARMv6-M, interrupts are disabled with the PRIMASK register. -// On ARMv7-M and higher, interrupts are disabled *selectively* with the -// BASEPRI register. +// Description: +// When QF_USE_BASEPRI is defined, interrupts are disabled with BASEPRI. +// Otherwise interrupts are disabled with the PRIMASK register. // Additionally, the function also asserts that the interrupts are // NOT disabled upon the entry to the function, which means that // this interrupt management policy CANNOT nest. __stackless void QF_int_disable_(void) { __asm volatile ( -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK - " CPSID i \n" // set PRIMASK -#else //--------- ARMv7-M or higher +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for interrupt disabling? " MRS r0,BASEPRI \n" // r0 <- previous BASEPRI - " MOVS r1,#" STRINGIFY(QF_BASEPRI) "\n" + " MOVS r1,#" STRINGIFY(QF_USE_BASEPRI) "\n" " MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK -#endif //--------- ARMv7-M or higher +#else //--------- use PRIMASK for disabling interrupts + " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK + " CPSID i \n" // set PRIMASK +#endif //--------- use PRIMASK for disabling interrupts " CMP r0,#0 \n" // assert(PRIMASK/BASEPRI == 0) " BNE QF_int_disable_error\n" " BX lr \n" @@ -115,28 +108,29 @@ __asm volatile ( // Unconditionally enable interrupts. // NOTE: this function must NOT use the stack. // -// description: -// On ARMv6-M, interrupts are enabled with the PRIMASK register. -// On ARMv7-M and higher, interrupts are enabled with the BASEPRI register. +// Description: +// When QF_USE_BASEPRI is defined, interrupts are enabled with BASEPRI. +// Otherwise interrupts are enabled with the PRIMASK register. // Additionally, the function also asserts that the interrupts ARE // disabled upon the entry to the function, which means that // this interrupt management policy CANNOT nest. __stackless void QF_int_enable_(void) { __asm volatile ( -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK -#else //--------- ARMv7-M or higher +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for enabling interrupts? " MRS r0,BASEPRI \n" // r0 <- previous BASEPRI -#endif //--------- ARMv7-M or higher +#else //--------- use PRIMASK for enabling interrupts + " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK +#endif //--------- use PRIMASK for enabling interrupts + " CMP r0,#0 \n" // assert(PRIMASK/BASEPRI != 0) " BEQ QF_int_enable_error\n" -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " CPSIE i \n" // clear PRIMASK -#else //--------- ARMv7-M or higher +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for enabling interrupts? " MOVS r1,#0 \n" " MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK -#endif //--------- ARMv7-M or higher +#else //--------- use PRIMASK for enabling interrupts + " CPSIE i \n" // clear PRIMASK +#endif //--------- use PRIMASK for enabling interrupts " BX lr \n" "QF_int_enable_error: \n" " LDR r0,=QF_port_module_ \n" @@ -149,25 +143,23 @@ __asm volatile ( // Enter QF critical section. // NOTE: this function must NOT use the stack. // -// description: -// On ARMv6-M, critical section is entered by disabling interrupts -// with the PRIMASK register. -// On ARMv7-M and higher, critical section is entered by disabling -// interrupts *selectively* with the BASEPRI register. +// Description: +// When QF_USE_BASEPRI is defined, critical section uses BASEPRI. +// Otherwise, critical section uses the PRIMASK register. // Additionally, the function also asserts that the interrupts are // NOT disabled upon the entry to the function, which means that // this critical section CANNOT nest. __stackless void QF_crit_entry_(void) { __asm volatile ( -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK - " CPSID i \n" // set PRIMASK -#else //--------- ARMv7-M or higher +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section? " MRS r0,BASEPRI \n" // r0 <- previous BASEPRI - " MOVS r1,#" STRINGIFY(QF_BASEPRI) "\n" + " MOVS r1,#" STRINGIFY(QF_USE_BASEPRI) "\n" " MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK -#endif //--------- ARMv7-M or higher +#else //--------- use PRIMASK for critical section + " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK + " CPSID i \n" // set PRIMASK +#endif //--------- use PRIMASK for critical section " CMP r0,#0 \n" // assert(PRIMASK/BASEPRI == 0) " BNE QF_crit_entry_error\n" " BX lr \n" @@ -183,29 +175,27 @@ __asm volatile ( // NOTE: this function must NOT use the stack. // // description: -// On ARMv6-M, critical section is exited by enabling interrupts -// with the PRIMASK register. -// On ARMv7-M and higher, critical section is exited by enabling -// interrupts with the BASEPRI register. +// When QF_USE_BASEPRI is defined, critical section uses BASEPRI. +// Otherwise, critical section uses the PRIMASK register. // Additionally, the function also asserts that the interrupts ARE // disabled upon the entry to the function, which means that // this critical section CANNOT nest. __stackless void QF_crit_exit_(void) { __asm volatile ( -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK -#else //--------- ARMv7-M or higher +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section? " MRS r0,BASEPRI \n" // r0 <- previous BASEPRI -#endif //--------- ARMv7-M or higher +#else //--------- use PRIMASK for critical section + " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK +#endif //--------- use PRIMASK for critical section " CMP r0,#0 \n" // assert(PRIMASK/BASEPRI != 0) " BEQ QF_crit_exit_error\n" -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " CPSIE i \n" // clear PRIMASK -#else //--------- ARMv7-M or higher +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section? " MOVS r1,#0 \n" " MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK -#endif //--------- ARMv7-M or higher +#else //--------- use PRIMASK + " CPSIE i \n" // clear PRIMASK +#endif //--------- use PRIMASK " BX lr \n" "QF_crit_exit_error: \n" " LDR r0,=QF_port_module_ \n" @@ -223,7 +213,7 @@ __asm volatile ( // BASEPRI register. However, this method cannot disable interrupt // priority zero, which is the default for all interrupts out of reset. // The following code changes the SysTick priority and all IRQ priorities -// to the safe value QF_BASEPRI, which the QF critical section can disable. +// to the safe value QF_USE_BASEPRI, which the QF critical section can disable. // This avoids breaching of the QF critical sections in case the // application programmer forgets to explicitly set priorities of all // "kernel aware" interrupts. @@ -232,18 +222,18 @@ __asm volatile ( // by the application-level code. void QK_init(void) { -#if (__ARM_ARCH != 6) //--------- if ARMv7-M and higher... +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section? // SCB_SYSPRI[2]: SysTick - SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_BASEPRI << 24U)); + SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_USE_BASEPRI << 24U)); - // set all 240 possible IRQ priories to QF_BASEPRI... + // set all 240 possible IRQ priories to QF_USE_BASEPRI... for (uint_fast8_t n = 0U; n < (240U/sizeof(uint32_t)); ++n) { - NVIC_IP[n] = (QF_BASEPRI << 24U) | (QF_BASEPRI << 16U) - | (QF_BASEPRI << 8U) | QF_BASEPRI; + NVIC_IP[n] = (QF_USE_BASEPRI << 24U) | (QF_USE_BASEPRI << 16U) + | (QF_USE_BASEPRI << 8U) | QF_USE_BASEPRI; } -#endif //--------- ARMv7-M or higher +#endif //--------- use BASEPRI for critical section // SCB_SYSPRI[2]: PendSV set to priority 0xFF (lowest) SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (0xFFU << 16U)); @@ -378,9 +368,12 @@ void QK_thread_ret(void) { #endif //--------- use the NMI #else //--------- ARMv7-M and higher... + +#ifdef QF_USE_BASEPRI //--------- QF_USE_BASEPRI " CPSID i \n" // disable interrupts with PRIMASK " LDR r0,=QF_int_enable_ \n" " BLX r0 \n" // enable interrupts with BASEPRI +#endif //--------- QF_USE_BASEPRI // NOTE: interrupts remain disabled with PRIMASK #ifdef __ARM_FP //--------- if VFP available... @@ -396,7 +389,12 @@ void QK_thread_ret(void) { " MOVS r1,#1 \n" " LSLS r1,r1,#" STRINGIFY(QK_USE_IRQ_NUM & 0x1F) "\n" // r1 := IRQ bit " STR r1,[r0] \n" // pend the IRQ +#ifdef QF_USE_BASEPRI //--------- QF_USE_BASEPRI " CPSIE i \n" // enable interrupts with PRIMASK +#else //--------- interrupt disabling with PRIMASK + " LDR r0,=QF_int_enable_ \n" + " BLX r0 \n" // enable interrupts with BASEPRI +#endif //--------- interrupt disabling with PRIMASK // This code stops here and continues in the IRQ handler #else //--------- use the NMI (default) @@ -446,15 +444,16 @@ void NMI_Handler(void) { __asm volatile ( " ADD sp,sp,#(8*4) \n" // remove one 8-register exception frame -#if (__ARM_ARCH == 6) //--------- if ARMv6-M... +#ifdef QF_USE_BASEPRI //--------- QF_USE_BASEPRI + // NOTE: QF_int_enable_() already called + " CPSIE i \n" // enable interrupts with PRIMASK +#else //--------- interrupt disabling with PRIMASK " LDR r0,=QF_int_enable_ \n" " BLX r0 \n" // enable interrupts with PRIMASK // NOTE: calling QF_int_enable_() corrupted the lr (EXC_RETURN), but // it is NOT used to used to return from the exception. (See POP {r0,pc}) -#else //--------- ARMv7-M and higher... - " CPSIE i \n" // enable interrupts with PRIMASK -#endif //--------- ARMv7-M and higher +#endif //--------- interrupt disabling with PRIMASK " POP {r0,pc} \n" // pop stack aligner and EXC_RETURN to pc ); // NOTE: this causes exception-return to the preempted *thread* context @@ -475,7 +474,7 @@ uint_fast8_t QF_qlog2(uint32_t x) { uint_fast8_t n; __asm volatile ( - " MOVS %[n],#0 \n" + " MOVS %[n],#0 \n" #if (QF_MAX_ACTIVE > 16U) " LSRS r2,r0,#16 \n" " BEQ QF_qlog2_1 \n" @@ -495,7 +494,7 @@ __asm volatile ( " ADDS %[n],%[n],#4 \n" " MOVS r0,r2 \n" "QF_qlog2_3:" : [n]"=r"(n) -); + ); return n + log2LUT[x]; } diff --git a/ports/arm-cm/qk/iar/qp_port.hpp b/ports/arm-cm/qk/iar/qp_port.hpp index d9e90215..c028aa57 100644 --- a/ports/arm-cm/qk/iar/qp_port.hpp +++ b/ports/arm-cm/qk/iar/qp_port.hpp @@ -27,12 +27,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QP/C++ port to ARM Cortex-M, preemptive QK kernel, IAR-ARM - #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ @@ -48,32 +42,9 @@ // QK event-queue used for AOs #define QACTIVE_EQUEUE_TYPE QEQueue -// QF "thread" type used to store the MPU settings in the AO +// QActive "thread" type used to store the MPU settings in the AO #define QACTIVE_THREAD_TYPE void const * -// QF interrupt disable/enable and log2()... -#if (__ARM_ARCH == 6) // ARMv6-M? - - // CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4 - #define QF_AWARE_ISR_CMSIS_PRI 0 - - // hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M) - #define QF_LOG2(n_) QF_qlog2(static_cast(n_)) - -#else // ARMv7-M or higher - - // BASEPRI threshold for "QF-aware" interrupts, see NOTE3 - #define QF_BASEPRI 0x3F - - // CMSIS threshold for "QF-aware" interrupts, see NOTE4 - #define QF_AWARE_ISR_CMSIS_PRI (QF_BASEPRI >> (8 - __NVIC_PRIO_BITS)) - - // ARMv7-M or higher provide the CLZ instruction for fast LOG2 - #define QF_LOG2(n_) \ - (static_cast(32U - __CLZ((n_)))) - -#endif - // interrupt disabling policy, see NOTE2 and NOTE3 #define QF_INT_DISABLE() (QF_int_disable_()) #define QF_INT_ENABLE() (QF_int_enable_()) @@ -85,11 +56,28 @@ #define QF_CRIT_EXIT_NOP() __ISB() +// Efficient log2() ---------------------------------------------------------- #if (__ARM_ARCH == 6) // ARMv6-M? + // hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M) + #define QF_LOG2(n_) QF_qlog2(static_cast(n_)) + // hand-optimized quick LOG2 in assembly extern "C" std::uint_fast8_t QF_qlog2(std::uint32_t x); +#else // ARMv7-M or higher + // ARMv7-M or higher provide the CLZ instruction for fast LOG2 + #define QF_LOG2(n_) \ + (static_cast(32U - __CLZ((n_)))) #endif // ARMv7-M or higher +// Critical section policy --------------------------------------------------- +#ifdef QF_USE_BASEPRI + // CMSIS threshold for "QF-aware" interrupts, see NOTE4 + #define QF_AWARE_ISR_CMSIS_PRI (QF_USE_BASEPRI >> (8 - __NVIC_PRIO_BITS)) +#else + // CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4 + #define QF_AWARE_ISR_CMSIS_PRI 0 +#endif // QF_USE_BASEPRI + // Memory isolation ---------------------------------------------------------- #ifdef QF_MEM_ISOLATE @@ -106,7 +94,7 @@ extern "C" void QF_onMemSys(void); extern "C" void QF_onMemApp(void); -#endif // def QF_MEM_ISOLATE +#endif // QF_MEM_ISOLATE // determination if the code executes in the ISR context #define QK_ISR_CONTEXT_() (__get_IPSR() != 0U) @@ -183,7 +171,7 @@ extern "C" { // functions. They are defined as "weak" in the qv_port.c module, // so the application can provide a different implementation. // Please see the definitions of the interrupt and critical-section -// funcctions in the qv_port.c module for details. +// functions in the qv_port.c module for details. // // NOTE2: // On Cortex-M0/M0+/M1 (architecture ARMv6-M, ARMv6S-M), the interrupt @@ -192,15 +180,15 @@ extern "C" { // are "kernel-aware". // // NOTE3: -// On ARMv7-M or higher, the interrupt disable/enable policy uses the BASEPRI -// register (which is not implemented in ARMv6-M) to disable interrupts only -// with priority lower than the threshold specified by the QF_BASEPRI macro. -// The interrupts with priorities above QF_BASEPRI (i.e., with numerical -// priority values lower than QF_BASEPRI) are NOT disabled in this method. +// If macro QF_USE_BASEPRI is defined, the interrupt disable/enable policy +// uses BASEPRI register to disable interrupts only with priority lower than +// the threshold specified by the QF_USE_BASEPRI macro. The interrupts with +// priorities above QF_USE_BASEPRI (i.e., with numerical priority values +// lower than QF_USE_BASEPRI) are NOT disabled in this method. // These free-running interrupts have very low ("zero") latency, but they // are NOT allowed to call any QF services, because QF is unaware of them // ("kernel-unaware" interrupts). Consequently, only interrupts with -// numerical values of priorities equal to or higher than QF_BASEPRI +// numerical values of priorities equal to or higher than QF_USE_BASEPRI // ("kernel-aware" interrupts ), can call QF services. // // NOTE4: @@ -215,8 +203,6 @@ extern "C" { // is intended only for applications and is not used inside the QF port, which // remains generic and not dependent on the number of implemented priority bits // implemented in the NVIC. -// -// #endif // QP_PORT_HPP_ diff --git a/ports/arm-cm/qv/armclang/qp_port.hpp b/ports/arm-cm/qv/armclang/qp_port.hpp index ace56dd2..76997b93 100644 --- a/ports/arm-cm/qv/armclang/qp_port.hpp +++ b/ports/arm-cm/qv/armclang/qp_port.hpp @@ -27,12 +27,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QF/C++ port to ARM Cortex-M, cooperative QV kernel, ARM-CLANG - #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ @@ -47,32 +41,9 @@ // QV event-queue used for AOs #define QACTIVE_EQUEUE_TYPE QEQueue -// QF "thread" type used to store the MPU settings in the AO +// QActive "thread" type used to store the MPU settings in the AO #define QACTIVE_THREAD_TYPE void const * -// QF interrupt disable/enable and log2()... -#if (__ARM_ARCH == 6) // ARMv6-M? - - // CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4 - #define QF_AWARE_ISR_CMSIS_PRI 0 - - // hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M) - #define QF_LOG2(n_) QF_qlog2(static_cast(n_)) - -#else // ARMv7-M or higher - - // BASEPRI threshold for "QF-aware" interrupts, see NOTE3 - #define QF_BASEPRI 0x3F - - // CMSIS threshold for "QF-aware" interrupts, see NOTE4 - #define QF_AWARE_ISR_CMSIS_PRI (QF_BASEPRI >> (8 - __NVIC_PRIO_BITS)) - - // ARMv7-M or higher provide the CLZ instruction for fast LOG2 - #define QF_LOG2(n_) \ - (static_cast(32 - __builtin_clz((n_)))) - -#endif - // interrupt disabling policy, see NOTE2 and NOTE3 #define QF_INT_DISABLE() (QF_int_disable_()) #define QF_INT_ENABLE() (QF_int_enable_()) @@ -84,11 +55,28 @@ #define QF_CRIT_EXIT_NOP() __asm volatile ("isb" ::: "memory") +// Efficient log2() ---------------------------------------------------------- #if (__ARM_ARCH == 6) // ARMv6-M? + // hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M) + #define QF_LOG2(n_) QF_qlog2(static_cast(n_)) + // hand-optimized quick LOG2 in assembly extern "C" std::uint_fast8_t QF_qlog2(std::uint32_t x); +#else // ARMv7-M or higher + // ARMv7-M or higher provide the CLZ instruction for fast LOG2 + #define QF_LOG2(n_) \ + (static_cast(32 - __builtin_clz((n_)))) #endif // ARMv7-M or higher +// Critical section policy --------------------------------------------------- +#ifdef QF_USE_BASEPRI + // CMSIS threshold for "QF-aware" interrupts, see NOTE4 + #define QF_AWARE_ISR_CMSIS_PRI (QF_USE_BASEPRI >> (8 - __NVIC_PRIO_BITS)) +#else + // CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4 + #define QF_AWARE_ISR_CMSIS_PRI 0 +#endif // QF_USE_BASEPRI + // Memory isolation ---------------------------------------------------------- #ifdef QF_MEM_ISOLATE @@ -105,20 +93,10 @@ extern "C" void QF_onMemSys(void); extern "C" void QF_onMemApp(void); -#endif // def QF_MEM_ISOLATE +#endif // QF_MEM_ISOLATE -// determination if the code executes in the ISR context -#if (__ARM_ARCH == 6) // ARMv6-M? - - // macro to put the CPU to sleep inside QV_onIdle() - #define QV_CPU_SLEEP() do { \ - __asm volatile ("wfi"::: "memory"); \ - QF_INT_ENABLE(); \ - } while (false) - - #define QV_ARM_ERRATUM_838869() ((void)0) - -#else // ARMv7-M or higher +// QV kernel sleep mode transition +#ifdef QF_USE_BASEPRI // macro to put the CPU to sleep inside QV_onIdle() #define QV_CPU_SLEEP() do { \ @@ -128,6 +106,17 @@ __asm volatile ("cpsie i" ::: "memory"); \ } while (false) +#else // no BASEPRI (QV uses PRIMASK) + // macro to put the CPU to sleep inside QV_onIdle() + #define QV_CPU_SLEEP() do { \ + __asm volatile ("wfi"::: "memory"); \ + QF_INT_ENABLE(); \ + } while (false) +#endif // no BASEPRI (QV uses PRIMASK) + +#if (__ARM_ARCH == 6) // ARMv6-M? + #define QV_ARM_ERRATUM_838869() (static_cast(0)) +#else // ARMv7-M or higher // The following macro implements the recommended workaround for the // ARM Erratum 838869. Specifically, for Cortex-M3/M4/M7 the DSB // (memory barrier) instruction needs to be added before exiting an ISR. @@ -171,7 +160,7 @@ extern "C" { // functions. They are defined as "weak" in the qv_port.c module, // so the application can provide a different implementation. // Please see the definitions of the interrupt and critical-section -// funcctions in the qv_port.c module for details. +// functions in the qv_port.c module for details. // // NOTE2: // On Cortex-M0/M0+/M1 (architecture ARMv6-M, ARMv6S-M), the interrupt @@ -180,15 +169,15 @@ extern "C" { // are "kernel-aware". // // NOTE3: -// On ARMv7-M or higher, the interrupt disable/enable policy uses the BASEPRI -// register (which is not implemented in ARMv6-M) to disable interrupts only -// with priority lower than the threshold specified by the QF_BASEPRI macro. -// The interrupts with priorities above QF_BASEPRI (i.e., with numerical -// priority values lower than QF_BASEPRI) are NOT disabled in this method. +// If macro QF_USE_BASEPRI is defined, the interrupt disable/enable policy +// uses BASEPRI register to disable interrupts only with priority lower than +// the threshold specified by the QF_USE_BASEPRI macro. The interrupts with +// priorities above QF_USE_BASEPRI (i.e., with numerical priority values +// lower than QF_USE_BASEPRI) are NOT disabled in this method. // These free-running interrupts have very low ("zero") latency, but they // are NOT allowed to call any QF services, because QF is unaware of them // ("kernel-unaware" interrupts). Consequently, only interrupts with -// numerical values of priorities equal to or higher than QF_BASEPRI +// numerical values of priorities equal to or higher than QF_USE_BASEPRI // ("kernel-aware" interrupts ), can call QF services. // // NOTE4: @@ -203,8 +192,6 @@ extern "C" { // is intended only for applications and is not used inside the QF port, which // remains generic and not dependent on the number of implemented priority bits // implemented in the NVIC. -// -// #endif // QP_PORT_HPP_ diff --git a/ports/arm-cm/qv/armclang/qv_port.cpp b/ports/arm-cm/qv/armclang/qv_port.cpp index de263587..ecc44ad4 100644 --- a/ports/arm-cm/qv/armclang/qv_port.cpp +++ b/ports/arm-cm/qv/armclang/qv_port.cpp @@ -1,5 +1,5 @@ //============================================================================ -// QP/C Real-Time Embedded Framework (RTEF) +// QP/C++ Real-Time Embedded Framework (RTEF) // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // Q u a n t u m L e a P s @@ -26,12 +26,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QV/C++ port to ARM Cortex-M, ARM-CLANG - #define QP_IMPL 1U #include "qp_port.hpp" #include "qsafe.h" // QP Functional Safety (FuSa) Subsystem @@ -67,24 +61,23 @@ char const QF_port_module_[] = "qv_port"; // Unconditionally disable interrupts. // NOTE: this function must NOT use the stack. // -// description: -// On ARMv6-M, interrupts are disabled with the PRIMASK register. -// On ARMv7-M and higher, interrupts are disabled *selectively* with the -// BASEPRI register. +// Description: +// When QF_USE_BASEPRI is defined, interrupts are disabled with BASEPRI. +// Otherwise interrupts are disabled with the PRIMASK register. // Additionally, the function also asserts that the interrupts are // NOT disabled upon the entry to the function, which means that // this interrupt management policy CANNOT nest. __attribute__ ((naked, weak)) void QF_int_disable_(void) { __asm volatile ( -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK - " CPSID i \n" // set PRIMASK -#else //--------- ARMv7-M or higher +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for interrupt disabling? " MRS r0,BASEPRI \n" // r0 <- previous BASEPRI - " MOVS r1,#" STRINGIFY(QF_BASEPRI) "\n" + " MOVS r1,#" STRINGIFY(QF_USE_BASEPRI) "\n" " MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK -#endif //--------- ARMv7-M or higher +#else //--------- use PRIMASK for disabling interrupts + " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK + " CPSID i \n" // set PRIMASK +#endif //--------- use PRIMASK for disabling interrupts " CMP r0,#0 \n" // assert(PRIMASK/BASEPRI == 0) " BNE QF_int_disable_error\n" " BX lr \n" @@ -99,28 +92,29 @@ __asm volatile ( // Unconditionally enable interrupts. // NOTE: this function must NOT use the stack. // -// description: -// On ARMv6-M, interrupts are enabled with the PRIMASK register. -// On ARMv7-M and higher, interrupts are enabled with the BASEPRI register. +// Description: +// When QF_USE_BASEPRI is defined, interrupts are enabled with BASEPRI. +// Otherwise interrupts are enabled with the PRIMASK register. // Additionally, the function also asserts that the interrupts ARE // disabled upon the entry to the function, which means that // this interrupt management policy CANNOT nest. __attribute__ ((naked, weak)) void QF_int_enable_(void) { __asm volatile ( -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK -#else //--------- ARMv7-M or higher +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for enabling interrupts? " MRS r0,BASEPRI \n" // r0 <- previous BASEPRI -#endif //--------- ARMv7-M or higher +#else //--------- use PRIMASK for enabling interrupts + " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK +#endif //--------- use PRIMASK for enabling interrupts + " CMP r0,#0 \n" // assert(PRIMASK/BASEPRI != 0) " BEQ QF_int_enable_error\n" -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " CPSIE i \n" // clear PRIMASK -#else //--------- ARMv7-M or higher +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for enabling interrupts? " MOVS r1,#0 \n" " MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK -#endif //--------- ARMv7-M or higher +#else //--------- use PRIMASK for enabling interrupts + " CPSIE i \n" // clear PRIMASK +#endif //--------- use PRIMASK for enabling interrupts " BX lr \n" "QF_int_enable_error: \n" " LDR r0,=QF_port_module_ \n" @@ -133,25 +127,23 @@ __asm volatile ( // Enter QF critical section. // NOTE: this function must NOT use the stack. // -// description: -// On ARMv6-M, critical section is entered by disabling interrupts -// with the PRIMASK register. -// On ARMv7-M and higher, critical section is entered by disabling -// interrupts *selectively* with the BASEPRI register. +// Description: +// When QF_USE_BASEPRI is defined, critical section uses BASEPRI. +// Otherwise, critical section uses the PRIMASK register. // Additionally, the function also asserts that the interrupts are // NOT disabled upon the entry to the function, which means that // this critical section CANNOT nest. __attribute__ ((naked, weak)) void QF_crit_entry_(void) { __asm volatile ( -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK - " CPSID i \n" // set PRIMASK -#else //--------- ARMv7-M or higher +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section? " MRS r0,BASEPRI \n" // r0 <- previous BASEPRI - " MOVS r1,#" STRINGIFY(QF_BASEPRI) "\n" + " MOVS r1,#" STRINGIFY(QF_USE_BASEPRI) "\n" " MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK -#endif //--------- ARMv7-M or higher +#else //--------- use PRIMASK for critical section + " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK + " CPSID i \n" // set PRIMASK +#endif //--------- use PRIMASK for critical section " CMP r0,#0 \n" // assert(PRIMASK/BASEPRI == 0) " BNE QF_crit_entry_error\n" " BX lr \n" @@ -167,29 +159,27 @@ __asm volatile ( // NOTE: this function must NOT use the stack. // // description: -// On ARMv6-M, critical section is exited by enabling interrupts -// with the PRIMASK register. -// On ARMv7-M and higher, critical section is exited by enabling -// interrupts with the BASEPRI register. +// When QF_USE_BASEPRI is defined, critical section uses BASEPRI. +// Otherwise, critical section uses the PRIMASK register. // Additionally, the function also asserts that the interrupts ARE // disabled upon the entry to the function, which means that // this critical section CANNOT nest. __attribute__ ((naked, weak)) void QF_crit_exit_(void) { __asm volatile ( -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK -#else //--------- ARMv7-M or higher +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section? " MRS r0,BASEPRI \n" // r0 <- previous BASEPRI -#endif //--------- ARMv7-M or higher +#else //--------- use PRIMASK for critical section + " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK +#endif //--------- use PRIMASK for critical section " CMP r0,#0 \n" // assert(PRIMASK/BASEPRI != 0) " BEQ QF_crit_exit_error\n" -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " CPSIE i \n" // clear PRIMASK -#else //--------- ARMv7-M or higher +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section? " MOVS r1,#0 \n" " MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK -#endif //--------- ARMv7-M or higher +#else //--------- use PRIMASK + " CPSIE i \n" // clear PRIMASK +#endif //--------- use PRIMASK " BX lr \n" "QF_crit_exit_error: \n" " LDR r0,=QF_port_module_ \n" @@ -207,7 +197,7 @@ __asm volatile ( // BASEPRI register. However, this method cannot disable interrupt // priority zero, which is the default for all interrupts out of reset. // The following code changes the SysTick priority and all IRQ priorities -// to the safe value QF_BASEPRI, which the QF critical section can disable. +// to the safe value QF_USE_BASEPRI, which the QF critical section can disable. // This avoids breaching of the QF critical sections in case the // application programmer forgets to explicitly set priorities of all // "kernel aware" interrupts. @@ -216,18 +206,18 @@ __asm volatile ( // by the application-level code. void QV_init(void) { -#if (__ARM_ARCH != 6) //--------- if ARMv7-M and higher... +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section? // SCB_SYSPRI[2]: SysTick - SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_BASEPRI << 24U)); + SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_USE_BASEPRI << 24U)); - // set all 240 possible IRQ priories to QF_BASEPRI... + // set all 240 possible IRQ priories to QF_USE_BASEPRI... for (uint_fast8_t n = 0U; n < (240U/sizeof(uint32_t)); ++n) { - NVIC_IP[n] = (QF_BASEPRI << 24U) | (QF_BASEPRI << 16U) - | (QF_BASEPRI << 8U) | QF_BASEPRI; + NVIC_IP[n] = (QF_USE_BASEPRI << 24U) | (QF_USE_BASEPRI << 16U) + | (QF_USE_BASEPRI << 8U) | QF_USE_BASEPRI; } -#endif //--------- ARMv7-M or higher +#endif //--------- use BASEPRI for critical section #ifdef __ARM_FP //--------- if VFP available... // make sure that the FPU is enabled by setting CP10 & CP11 Full Access diff --git a/ports/arm-cm/qv/gnu/qp_port.hpp b/ports/arm-cm/qv/gnu/qp_port.hpp index f10499b9..5b8ee2ac 100644 --- a/ports/arm-cm/qv/gnu/qp_port.hpp +++ b/ports/arm-cm/qv/gnu/qp_port.hpp @@ -27,12 +27,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief Qp/C++ port to ARM Cortex-M, cooperative QV kernel, GNU-ARM - #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ @@ -47,32 +41,9 @@ // QV event-queue used for AOs #define QACTIVE_EQUEUE_TYPE QEQueue -// QF "thread" type used to store the MPU settings in the AO +// QActive "thread" type used to store the MPU settings in the AO #define QACTIVE_THREAD_TYPE void const * -// QF interrupt disable/enable and log2()... -#if (__ARM_ARCH == 6) // ARMv6-M? - - // CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4 - #define QF_AWARE_ISR_CMSIS_PRI 0 - - // hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M) - #define QF_LOG2(n_) QF_qlog2(static_cast(n_)) - -#else // ARMv7-M or higher - - // BASEPRI threshold for "QF-aware" interrupts, see NOTE3 - #define QF_BASEPRI 0x3F - - // CMSIS threshold for "QF-aware" interrupts, see NOTE4 - #define QF_AWARE_ISR_CMSIS_PRI (QF_BASEPRI >> (8 - __NVIC_PRIO_BITS)) - - // ARMv7-M or higher provide the CLZ instruction for fast LOG2 - #define QF_LOG2(n_) \ - (static_cast(32 - __builtin_clz((n_)))) - -#endif - // interrupt disabling policy, see NOTE2 and NOTE3 #define QF_INT_DISABLE() (QF_int_disable_()) #define QF_INT_ENABLE() (QF_int_enable_()) @@ -84,11 +55,28 @@ #define QF_CRIT_EXIT_NOP() __asm volatile ("isb" ::: "memory") +// Efficient log2() ---------------------------------------------------------- #if (__ARM_ARCH == 6) // ARMv6-M? + // hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M) + #define QF_LOG2(n_) QF_qlog2(static_cast(n_)) + // hand-optimized quick LOG2 in assembly extern "C" std::uint_fast8_t QF_qlog2(std::uint32_t x); +#else // ARMv7-M or higher + // ARMv7-M or higher provide the CLZ instruction for fast LOG2 + #define QF_LOG2(n_) \ + (static_cast(32 - __builtin_clz((n_)))) #endif // ARMv7-M or higher +// Critical section policy --------------------------------------------------- +#ifdef QF_USE_BASEPRI + // CMSIS threshold for "QF-aware" interrupts, see NOTE4 + #define QF_AWARE_ISR_CMSIS_PRI (QF_USE_BASEPRI >> (8 - __NVIC_PRIO_BITS)) +#else + // CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4 + #define QF_AWARE_ISR_CMSIS_PRI 0 +#endif // QF_USE_BASEPRI + // Memory isolation ---------------------------------------------------------- #ifdef QF_MEM_ISOLATE @@ -105,20 +93,10 @@ extern "C" void QF_onMemSys(void); extern "C" void QF_onMemApp(void); -#endif // def QF_MEM_ISOLATE - -// determination if the code executes in the ISR context -#if (__ARM_ARCH == 6) // ARMv6-M? - - // macro to put the CPU to sleep inside QV_onIdle() - #define QV_CPU_SLEEP() do { \ - __asm volatile ("wfi"::: "memory"); \ - QF_INT_ENABLE(); \ - } while (false) - - #define QV_ARM_ERRATUM_838869() ((void)0) +#endif // QF_MEM_ISOLATE -#else // ARMv7-M or higher +// QV kernel sleep mode transition +#ifdef QF_USE_BASEPRI // macro to put the CPU to sleep inside QV_onIdle() #define QV_CPU_SLEEP() do { \ @@ -128,6 +106,17 @@ __asm volatile ("cpsie i" ::: "memory"); \ } while (false) +#else // no BASEPRI (QV uses PRIMASK) + // macro to put the CPU to sleep inside QV_onIdle() + #define QV_CPU_SLEEP() do { \ + __asm volatile ("wfi"::: "memory"); \ + QF_INT_ENABLE(); \ + } while (false) +#endif // no BASEPRI (QV uses PRIMASK) + +#if (__ARM_ARCH == 6) // ARMv6-M? + #define QV_ARM_ERRATUM_838869() ((void)0) +#else // ARMv7-M or higher // The following macro implements the recommended workaround for the // ARM Erratum 838869. Specifically, for Cortex-M3/M4/M7 the DSB // (memory barrier) instruction needs to be added before exiting an ISR. @@ -171,7 +160,7 @@ extern "C" { // functions. They are defined as "weak" in the qv_port.c module, // so the application can provide a different implementation. // Please see the definitions of the interrupt and critical-section -// funcctions in the qv_port.c module for details. +// functions in the qv_port.c module for details. // // NOTE2: // On Cortex-M0/M0+/M1 (architecture ARMv6-M, ARMv6S-M), the interrupt @@ -180,15 +169,15 @@ extern "C" { // are "kernel-aware". // // NOTE3: -// On ARMv7-M or higher, the interrupt disable/enable policy uses the BASEPRI -// register (which is not implemented in ARMv6-M) to disable interrupts only -// with priority lower than the threshold specified by the QF_BASEPRI macro. -// The interrupts with priorities above QF_BASEPRI (i.e., with numerical -// priority values lower than QF_BASEPRI) are NOT disabled in this method. +// If macro QF_USE_BASEPRI is defined, the interrupt disable/enable policy +// uses BASEPRI register to disable interrupts only with priority lower than +// the threshold specified by the QF_USE_BASEPRI macro. The interrupts with +// priorities above QF_USE_BASEPRI (i.e., with numerical priority values +// lower than QF_USE_BASEPRI) are NOT disabled in this method. // These free-running interrupts have very low ("zero") latency, but they // are NOT allowed to call any QF services, because QF is unaware of them // ("kernel-unaware" interrupts). Consequently, only interrupts with -// numerical values of priorities equal to or higher than QF_BASEPRI +// numerical values of priorities equal to or higher than QF_USE_BASEPRI // ("kernel-aware" interrupts ), can call QF services. // // NOTE4: @@ -203,8 +192,6 @@ extern "C" { // is intended only for applications and is not used inside the QF port, which // remains generic and not dependent on the number of implemented priority bits // implemented in the NVIC. -// -// #endif // QP_PORT_HPP_ diff --git a/ports/arm-cm/qv/gnu/qv_port.cpp b/ports/arm-cm/qv/gnu/qv_port.cpp index 04e8a132..4ff3c9dc 100644 --- a/ports/arm-cm/qv/gnu/qv_port.cpp +++ b/ports/arm-cm/qv/gnu/qv_port.cpp @@ -1,5 +1,5 @@ //============================================================================ -// QP/C Real-Time Embedded Framework (RTEF) +// QP/C++ Real-Time Embedded Framework (RTEF) // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // Q u a n t u m L e a P s @@ -26,12 +26,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QV/C++ port to ARM Cortex-M, GNU-ARM - #define QP_IMPL 1U #include "qp_port.hpp" #include "qsafe.h" // QP Functional Safety (FuSa) Subsystem @@ -67,24 +61,23 @@ char const QF_port_module_[] = "qv_port"; // Unconditionally disable interrupts. // NOTE: this function must NOT use the stack. // -// description: -// On ARMv6-M, interrupts are disabled with the PRIMASK register. -// On ARMv7-M and higher, interrupts are disabled *selectively* with the -// BASEPRI register. +// Description: +// When QF_USE_BASEPRI is defined, interrupts are disabled with BASEPRI. +// Otherwise interrupts are disabled with the PRIMASK register. // Additionally, the function also asserts that the interrupts are // NOT disabled upon the entry to the function, which means that // this interrupt management policy CANNOT nest. __attribute__ ((naked, weak)) void QF_int_disable_(void) { __asm volatile ( -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK - " CPSID i \n" // set PRIMASK -#else //--------- ARMv7-M or higher +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for interrupt disabling? " MRS r0,BASEPRI \n" // r0 <- previous BASEPRI - " MOVS r1,#" STRINGIFY(QF_BASEPRI) "\n" + " MOVS r1,#" STRINGIFY(QF_USE_BASEPRI) "\n" " MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK -#endif //--------- ARMv7-M or higher +#else //--------- use PRIMASK for disabling interrupts + " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK + " CPSID i \n" // set PRIMASK +#endif //--------- use PRIMASK for disabling interrupts " CMP r0,#0 \n" // assert(PRIMASK/BASEPRI == 0) " BNE QF_int_disable_error\n" " BX lr \n" @@ -99,28 +92,29 @@ __asm volatile ( // Unconditionally enable interrupts. // NOTE: this function must NOT use the stack. // -// description: -// On ARMv6-M, interrupts are enabled with the PRIMASK register. -// On ARMv7-M and higher, interrupts are enabled with the BASEPRI register. +// Description: +// When QF_USE_BASEPRI is defined, interrupts are enabled with BASEPRI. +// Otherwise interrupts are enabled with the PRIMASK register. // Additionally, the function also asserts that the interrupts ARE // disabled upon the entry to the function, which means that // this interrupt management policy CANNOT nest. __attribute__ ((naked, weak)) void QF_int_enable_(void) { __asm volatile ( -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK -#else //--------- ARMv7-M or higher +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for enabling interrupts? " MRS r0,BASEPRI \n" // r0 <- previous BASEPRI -#endif //--------- ARMv7-M or higher +#else //--------- use PRIMASK for enabling interrupts + " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK +#endif //--------- use PRIMASK for enabling interrupts + " CMP r0,#0 \n" // assert(PRIMASK/BASEPRI != 0) " BEQ QF_int_enable_error\n" -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " CPSIE i \n" // clear PRIMASK -#else //--------- ARMv7-M or higher +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for enabling interrupts? " MOVS r1,#0 \n" " MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK -#endif //--------- ARMv7-M or higher +#else //--------- use PRIMASK for enabling interrupts + " CPSIE i \n" // clear PRIMASK +#endif //--------- use PRIMASK for enabling interrupts " BX lr \n" "QF_int_enable_error: \n" " LDR r0,=QF_port_module_ \n" @@ -133,25 +127,23 @@ __asm volatile ( // Enter QF critical section. // NOTE: this function must NOT use the stack. // -// description: -// On ARMv6-M, critical section is entered by disabling interrupts -// with the PRIMASK register. -// On ARMv7-M and higher, critical section is entered by disabling -// interrupts *selectively* with the BASEPRI register. +// Description: +// When QF_USE_BASEPRI is defined, critical section uses BASEPRI. +// Otherwise, critical section uses the PRIMASK register. // Additionally, the function also asserts that the interrupts are // NOT disabled upon the entry to the function, which means that // this critical section CANNOT nest. __attribute__ ((naked, weak)) void QF_crit_entry_(void) { __asm volatile ( -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK - " CPSID i \n" // set PRIMASK -#else //--------- ARMv7-M or higher +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section? " MRS r0,BASEPRI \n" // r0 <- previous BASEPRI - " MOVS r1,#" STRINGIFY(QF_BASEPRI) "\n" + " MOVS r1,#" STRINGIFY(QF_USE_BASEPRI) "\n" " MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK -#endif //--------- ARMv7-M or higher +#else //--------- use PRIMASK for critical section + " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK + " CPSID i \n" // set PRIMASK +#endif //--------- use PRIMASK for critical section " CMP r0,#0 \n" // assert(PRIMASK/BASEPRI == 0) " BNE QF_crit_entry_error\n" " BX lr \n" @@ -167,29 +159,27 @@ __asm volatile ( // NOTE: this function must NOT use the stack. // // description: -// On ARMv6-M, critical section is exited by enabling interrupts -// with the PRIMASK register. -// On ARMv7-M and higher, critical section is exited by enabling -// interrupts with the BASEPRI register. +// When QF_USE_BASEPRI is defined, critical section uses BASEPRI. +// Otherwise, critical section uses the PRIMASK register. // Additionally, the function also asserts that the interrupts ARE // disabled upon the entry to the function, which means that // this critical section CANNOT nest. __attribute__ ((naked, weak)) void QF_crit_exit_(void) { __asm volatile ( -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK -#else //--------- ARMv7-M or higher +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section? " MRS r0,BASEPRI \n" // r0 <- previous BASEPRI -#endif //--------- ARMv7-M or higher +#else //--------- use PRIMASK for critical section + " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK +#endif //--------- use PRIMASK for critical section " CMP r0,#0 \n" // assert(PRIMASK/BASEPRI != 0) " BEQ QF_crit_exit_error\n" -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " CPSIE i \n" // clear PRIMASK -#else //--------- ARMv7-M or higher +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section? " MOVS r1,#0 \n" " MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK -#endif //--------- ARMv7-M or higher +#else //--------- use PRIMASK + " CPSIE i \n" // clear PRIMASK +#endif //--------- use PRIMASK " BX lr \n" "QF_crit_exit_error: \n" " LDR r0,=QF_port_module_ \n" @@ -207,7 +197,7 @@ __asm volatile ( // BASEPRI register. However, this method cannot disable interrupt // priority zero, which is the default for all interrupts out of reset. // The following code changes the SysTick priority and all IRQ priorities -// to the safe value QF_BASEPRI, which the QF critical section can disable. +// to the safe value QF_USE_BASEPRI, which the QF critical section can disable. // This avoids breaching of the QF critical sections in case the // application programmer forgets to explicitly set priorities of all // "kernel aware" interrupts. @@ -216,18 +206,18 @@ __asm volatile ( // by the application-level code. void QV_init(void) { -#if (__ARM_ARCH != 6) //--------- if ARMv7-M and higher... +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section? // SCB_SYSPRI[2]: SysTick - SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_BASEPRI << 24U)); + SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_USE_BASEPRI << 24U)); - // set all 240 possible IRQ priories to QF_BASEPRI... + // set all 240 possible IRQ priories to QF_USE_BASEPRI... for (uint_fast8_t n = 0U; n < (240U/sizeof(uint32_t)); ++n) { - NVIC_IP[n] = (QF_BASEPRI << 24U) | (QF_BASEPRI << 16U) - | (QF_BASEPRI << 8U) | QF_BASEPRI; + NVIC_IP[n] = (QF_USE_BASEPRI << 24U) | (QF_USE_BASEPRI << 16U) + | (QF_USE_BASEPRI << 8U) | QF_USE_BASEPRI; } -#endif //--------- ARMv7-M or higher +#endif //--------- use BASEPRI for critical section #ifdef __ARM_FP //--------- if VFP available... // make sure that the FPU is enabled by setting CP10 & CP11 Full Access diff --git a/ports/arm-cm/qv/iar/qp_port.hpp b/ports/arm-cm/qv/iar/qp_port.hpp index 11aa635c..ef520f3f 100644 --- a/ports/arm-cm/qv/iar/qp_port.hpp +++ b/ports/arm-cm/qv/iar/qp_port.hpp @@ -1,6 +1,6 @@ //============================================================================ // QP/C++ Real-Time Embedded Framework (RTEF) -/// +// // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // Q u a n t u m L e a P s @@ -27,12 +27,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QP/C++ port to ARM Cortex-M, cooperative QV kernel, IAR-ARM - #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ @@ -48,32 +42,9 @@ // QV event-queue used for AOs #define QACTIVE_EQUEUE_TYPE QEQueue -// QF "thread" type used to store the MPU settings in the AO +// QActive "thread" type used to store the MPU settings in the AO #define QACTIVE_THREAD_TYPE void const * -// QF interrupt disable/enable and log2()... -#if (__ARM_ARCH == 6) // ARMv6-M? - - // CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4 - #define QF_AWARE_ISR_CMSIS_PRI 0 - - // hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M) - #define QF_LOG2(n_) QF_qlog2(static_cast(n_)) - -#else // ARMv7-M or higher - - // BASEPRI threshold for "QF-aware" interrupts, see NOTE3 - #define QF_BASEPRI 0x3F - - // CMSIS threshold for "QF-aware" interrupts, see NOTE4 - #define QF_AWARE_ISR_CMSIS_PRI (QF_BASEPRI >> (8 - __NVIC_PRIO_BITS)) - - // ARMv7-M or higher provide the CLZ instruction for fast LOG2 - #define QF_LOG2(n_) \ - (static_cast(32U - __CLZ((n_)))) - -#endif - // interrupt disabling policy, see NOTE2 and NOTE3 #define QF_INT_DISABLE() (QF_int_disable_()) #define QF_INT_ENABLE() (QF_int_enable_()) @@ -83,13 +54,30 @@ #define QF_CRIT_ENTRY() (QF_crit_entry_()) #define QF_CRIT_EXIT() (QF_crit_exit_()) -#define QF_CRIT_EXIT_NOP() __asm volatile ("isb" ::: "memory") +#define QF_CRIT_EXIT_NOP() __ISB() +// Efficient log2() ---------------------------------------------------------- #if (__ARM_ARCH == 6) // ARMv6-M? + // hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M) + #define QF_LOG2(n_) QF_qlog2(static_cast(n_)) + // hand-optimized quick LOG2 in assembly extern "C" std::uint_fast8_t QF_qlog2(std::uint32_t x); +#else // ARMv7-M or higher + // ARMv7-M or higher provide the CLZ instruction for fast LOG2 + #define QF_LOG2(n_) \ + (static_cast(32U - __CLZ((n_)))) #endif // ARMv7-M or higher +// Critical section policy --------------------------------------------------- +#ifdef QF_USE_BASEPRI + // CMSIS threshold for "QF-aware" interrupts, see NOTE4 + #define QF_AWARE_ISR_CMSIS_PRI (QF_USE_BASEPRI >> (8 - __NVIC_PRIO_BITS)) +#else + // CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4 + #define QF_AWARE_ISR_CMSIS_PRI 0 +#endif // QF_USE_BASEPRI + // Memory isolation ---------------------------------------------------------- #ifdef QF_MEM_ISOLATE @@ -106,29 +94,31 @@ extern "C" void QF_onMemSys(void); extern "C" void QF_onMemApp(void); -#endif // def QF_MEM_ISOLATE +#endif // QF_MEM_ISOLATE -// determination if the code executes in the ISR context -#if (__ARM_ARCH == 6) // ARMv6-M? +// QV kernel sleep mode transition +#ifdef QF_USE_BASEPRI // macro to put the CPU to sleep inside QV_onIdle() #define QV_CPU_SLEEP() do { \ - __WFI(); \ + __disable_interrupt(); \ QF_INT_ENABLE(); \ + __WFI(); \ + __enable_interrupt(); \ } while (false) - #define QV_ARM_ERRATUM_838869() ((void)0) - -#else // ARMv7-M or higher - +#else // no BASEPRI (QV uses PRIMASK) // macro to put the CPU to sleep inside QV_onIdle() + #define QV_CPU_SLEEP() do { \ - __disable_interrupt(); \ - QF_INT_ENABLE(); \ __WFI(); \ - __enable_interrupt(); \ + QF_INT_ENABLE(); \ } while (false) +#endif // no BASEPRI (QV uses PRIMASK) +#if (__ARM_ARCH == 6) // ARMv6-M? + #define QV_ARM_ERRATUM_838869() (static_cast(0)) +#else // ARMv7-M or higher // The following macro implements the recommended workaround for the // ARM Erratum 838869. Specifically, for Cortex-M3/M4/M7 the DSB // (memory barrier) instruction needs to be added before exiting an ISR. @@ -172,7 +162,7 @@ extern "C" { // functions. They are defined as "weak" in the qv_port.c module, // so the application can provide a different implementation. // Please see the definitions of the interrupt and critical-section -// funcctions in the qv_port.c module for details. +// functions in the qv_port.c module for details. // // NOTE2: // On Cortex-M0/M0+/M1 (architecture ARMv6-M, ARMv6S-M), the interrupt @@ -181,15 +171,15 @@ extern "C" { // are "kernel-aware". // // NOTE3: -// On ARMv7-M or higher, the interrupt disable/enable policy uses the BASEPRI -// register (which is not implemented in ARMv6-M) to disable interrupts only -// with priority lower than the threshold specified by the QF_BASEPRI macro. -// The interrupts with priorities above QF_BASEPRI (i.e., with numerical -// priority values lower than QF_BASEPRI) are NOT disabled in this method. +// If macro QF_USE_BASEPRI is defined, the interrupt disable/enable policy +// uses BASEPRI register to disable interrupts only with priority lower than +// the threshold specified by the QF_USE_BASEPRI macro. The interrupts with +// priorities above QF_USE_BASEPRI (i.e., with numerical priority values +// lower than QF_USE_BASEPRI) are NOT disabled in this method. // These free-running interrupts have very low ("zero") latency, but they // are NOT allowed to call any QF services, because QF is unaware of them // ("kernel-unaware" interrupts). Consequently, only interrupts with -// numerical values of priorities equal to or higher than QF_BASEPRI +// numerical values of priorities equal to or higher than QF_USE_BASEPRI // ("kernel-aware" interrupts ), can call QF services. // // NOTE4: @@ -204,8 +194,6 @@ extern "C" { // is intended only for applications and is not used inside the QF port, which // remains generic and not dependent on the number of implemented priority bits // implemented in the NVIC. -// -// #endif // QP_PORT_HPP_ diff --git a/ports/arm-cm/qv/iar/qv_port.cpp b/ports/arm-cm/qv/iar/qv_port.cpp index d6e6b7c9..6f8aa16f 100644 --- a/ports/arm-cm/qv/iar/qv_port.cpp +++ b/ports/arm-cm/qv/iar/qv_port.cpp @@ -26,12 +26,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 -//! @version Last updated for: @ref qpcpp_8_0_0 -//! -//! @file -//! @brief QV/C++ port to ARM Cortex-M, IAR-ARM toolset - #define QP_IMPL 1U #include "qp_port.hpp" #include "qsafe.h" // QP Functional Safety (FuSa) Subsystem @@ -72,24 +66,23 @@ char const QF_port_module_[] = "qv_port"; // Unconditionally disable interrupts. // NOTE: this function must NOT use the stack. // -// description: -// On ARMv6-M, interrupts are disabled with the PRIMASK register. -// On ARMv7-M and higher, interrupts are disabled *selectively* with the -// BASEPRI register. +// Description: +// When QF_USE_BASEPRI is defined, interrupts are disabled with BASEPRI. +// Otherwise interrupts are disabled with the PRIMASK register. // Additionally, the function also asserts that the interrupts are // NOT disabled upon the entry to the function, which means that // this interrupt management policy CANNOT nest. __stackless void QF_int_disable_(void) { __asm volatile ( -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK - " CPSID i \n" // set PRIMASK -#else //--------- ARMv7-M or higher +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for interrupt disabling? " MRS r0,BASEPRI \n" // r0 <- previous BASEPRI - " MOVS r1,#" STRINGIFY(QF_BASEPRI) "\n" + " MOVS r1,#" STRINGIFY(QF_USE_BASEPRI) "\n" " MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK -#endif //--------- ARMv7-M or higher +#else //--------- use PRIMASK for disabling interrupts + " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK + " CPSID i \n" // set PRIMASK +#endif //--------- use PRIMASK for disabling interrupts " CMP r0,#0 \n" // assert(PRIMASK/BASEPRI == 0) " BNE QF_int_disable_error\n" " BX lr \n" @@ -104,28 +97,29 @@ __asm volatile ( // Unconditionally enable interrupts. // NOTE: this function must NOT use the stack. // -// description: -// On ARMv6-M, interrupts are enabled with the PRIMASK register. -// On ARMv7-M and higher, interrupts are enabled with the BASEPRI register. +// Description: +// When QF_USE_BASEPRI is defined, interrupts are enabled with BASEPRI. +// Otherwise interrupts are enabled with the PRIMASK register. // Additionally, the function also asserts that the interrupts ARE // disabled upon the entry to the function, which means that // this interrupt management policy CANNOT nest. __stackless void QF_int_enable_(void) { __asm volatile ( -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK -#else //--------- ARMv7-M or higher +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for enabling interrupts? " MRS r0,BASEPRI \n" // r0 <- previous BASEPRI -#endif //--------- ARMv7-M or higher +#else //--------- use PRIMASK for enabling interrupts + " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK +#endif //--------- use PRIMASK for enabling interrupts + " CMP r0,#0 \n" // assert(PRIMASK/BASEPRI != 0) " BEQ QF_int_enable_error\n" -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " CPSIE i \n" // clear PRIMASK -#else //--------- ARMv7-M or higher +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for enabling interrupts? " MOVS r1,#0 \n" " MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK -#endif //--------- ARMv7-M or higher +#else //--------- use PRIMASK for enabling interrupts + " CPSIE i \n" // clear PRIMASK +#endif //--------- use PRIMASK for enabling interrupts " BX lr \n" "QF_int_enable_error: \n" " LDR r0,=QF_port_module_ \n" @@ -138,25 +132,23 @@ __asm volatile ( // Enter QF critical section. // NOTE: this function must NOT use the stack. // -// description: -// On ARMv6-M, critical section is entered by disabling interrupts -// with the PRIMASK register. -// On ARMv7-M and higher, critical section is entered by disabling -// interrupts *selectively* with the BASEPRI register. +// Description: +// When QF_USE_BASEPRI is defined, critical section uses BASEPRI. +// Otherwise, critical section uses the PRIMASK register. // Additionally, the function also asserts that the interrupts are // NOT disabled upon the entry to the function, which means that // this critical section CANNOT nest. __stackless void QF_crit_entry_(void) { __asm volatile ( -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK - " CPSID i \n" // set PRIMASK -#else //--------- ARMv7-M or higher +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section? " MRS r0,BASEPRI \n" // r0 <- previous BASEPRI - " MOVS r1,#" STRINGIFY(QF_BASEPRI) "\n" + " MOVS r1,#" STRINGIFY(QF_USE_BASEPRI) "\n" " MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK -#endif //--------- ARMv7-M or higher +#else //--------- use PRIMASK for critical section + " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK + " CPSID i \n" // set PRIMASK +#endif //--------- use PRIMASK for critical section " CMP r0,#0 \n" // assert(PRIMASK/BASEPRI == 0) " BNE QF_crit_entry_error\n" " BX lr \n" @@ -172,29 +164,27 @@ __asm volatile ( // NOTE: this function must NOT use the stack. // // description: -// On ARMv6-M, critical section is exited by enabling interrupts -// with the PRIMASK register. -// On ARMv7-M and higher, critical section is exited by enabling -// interrupts with the BASEPRI register. +// When QF_USE_BASEPRI is defined, critical section uses BASEPRI. +// Otherwise, critical section uses the PRIMASK register. // Additionally, the function also asserts that the interrupts ARE // disabled upon the entry to the function, which means that // this critical section CANNOT nest. __stackless void QF_crit_exit_(void) { __asm volatile ( -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK -#else //--------- ARMv7-M or higher +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section? " MRS r0,BASEPRI \n" // r0 <- previous BASEPRI -#endif //--------- ARMv7-M or higher +#else //--------- use PRIMASK for critical section + " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK +#endif //--------- use PRIMASK for critical section " CMP r0,#0 \n" // assert(PRIMASK/BASEPRI != 0) " BEQ QF_crit_exit_error\n" -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " CPSIE i \n" // clear PRIMASK -#else //--------- ARMv7-M or higher +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section? " MOVS r1,#0 \n" " MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK -#endif //--------- ARMv7-M or higher +#else //--------- use PRIMASK + " CPSIE i \n" // clear PRIMASK +#endif //--------- use PRIMASK " BX lr \n" "QF_crit_exit_error: \n" " LDR r0,=QF_port_module_ \n" @@ -212,7 +202,7 @@ __asm volatile ( // BASEPRI register. However, this method cannot disable interrupt // priority zero, which is the default for all interrupts out of reset. // The following code changes the SysTick priority and all IRQ priorities -// to the safe value QF_BASEPRI, which the QF critical section can disable. +// to the safe value QF_USE_BASEPRI, which the QF critical section can disable. // This avoids breaching of the QF critical sections in case the // application programmer forgets to explicitly set priorities of all // "kernel aware" interrupts. @@ -221,18 +211,18 @@ __asm volatile ( // by the application-level code. void QV_init(void) { -#if (__ARM_ARCH != 6) //--------- if ARMv7-M and higher... +#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section? // SCB_SYSPRI[2]: SysTick - SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_BASEPRI << 24U)); + SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_USE_BASEPRI << 24U)); - // set all 240 possible IRQ priories to QF_BASEPRI... + // set all 240 possible IRQ priories to QF_USE_BASEPRI... for (uint_fast8_t n = 0U; n < (240U/sizeof(uint32_t)); ++n) { - NVIC_IP[n] = (QF_BASEPRI << 24U) | (QF_BASEPRI << 16U) - | (QF_BASEPRI << 8U) | QF_BASEPRI; + NVIC_IP[n] = (QF_USE_BASEPRI << 24U) | (QF_USE_BASEPRI << 16U) + | (QF_USE_BASEPRI << 8U) | QF_USE_BASEPRI; } -#endif //--------- ARMv7-M or higher +#endif //--------- use BASEPRI for critical section #ifdef __ARM_FP //--------- if VFP available... // make sure that the FPU is enabled by setting CP10 & CP11 Full Access diff --git a/ports/arm-cm/qv/config/qp_config.hpp b/ports/arm-cr/config/qp_config.hpp similarity index 82% rename from ports/arm-cm/qv/config/qp_config.hpp rename to ports/arm-cr/config/qp_config.hpp index 5c713189..1a50a5f8 100644 --- a/ports/arm-cm/qv/config/qp_config.hpp +++ b/ports/arm-cr/config/qp_config.hpp @@ -1,5 +1,5 @@ //============================================================================ -// QP configuration file (QV on ARM Cortex-M) +// QP configuration file (QV/QK/QXK on ARM Cortex-R) // // Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // @@ -59,19 +59,19 @@ // * Hard-limits for all loops // * Memory Isolation by means of Memory Protection Unit (MPU) -// Disable QP FuSa in development +// Disable QP FuSa in development (NOT recommended) // Disable assertions and other self monitoring features // in development build configurations (NDEBUG undefined). -// VIOLATES functional safety standards. NOT recommended !!! +// NOTE: Disabling safety *violates* functional safety standards. //#ifndef NDEBUG //#define Q_UNSAFE //#endif // -// Disable QP FuSa in production release -// Disable assertions and other self monitoring features +// Disable QP FuSa in production release (NOT recommended) +// Disable assertions and other safety features // in the release build configurations (NDEBUG defined). -// VIOLATES functional safety standards. NOT recommended !!! +// NOTE: Disabling safety *violates* functional safety standards. //#ifdef NDEBUG //#define Q_UNSAFE //#endif @@ -80,7 +80,7 @@ // //.......................................................................... -// QEP Event Processor +// QEP Event Processor (Events) // Events and state machines. // Event signal size (Q_SIGNAL_SIZE) @@ -94,7 +94,7 @@ // //.......................................................................... -// QF Framework +// QF Framework (Active Objects) // Active Object framework // Maximum # Active Objects (QF_MAX_ACTIVE) <1-64> @@ -120,21 +120,6 @@ // Default: 1 #define QF_MAX_TICK_RATE 1U -// Event parameter initialization (QEVT_PAR_INIT) -// Resource Acquisition Is Initialization (RAII) for dynamic events -//#define QEVT_PAR_INIT -// - -// Provide destructors for QP classes -// Destructors for classes -//#define Q_XTOR -// - -// Active Object stop API (QACTIVE_CAN_STOP) -// Enable Active Object stop API (Not recommended) -//#define QACTIVE_CAN_STOP -// - // Event size (QF_EVENT_SIZ_SIZE) // <1U=>1 // <2U=>2 (default) @@ -174,15 +159,50 @@ // Default: 2 (64K bytes maximum block size) #define QF_MPOOL_SIZ_SIZE 2U +// Enable event parameter initialization (QEVT_PAR_INIT) +// Initialize parameters of dynamic events at allocation +// (Resource Acquisition Is Initialization (RAII) for dynamic events) +//#define QEVT_PAR_INIT +// + +// Provide destructors for QP classes +// Presence of destructors pulls in the C++ delete() opeator +// NOTE: Not recommended +//#define Q_XTOR +// + +// Enable active object stop API (QACTIVE_CAN_STOP) +// NOTE: Not recommended +//#define QACTIVE_CAN_STOP +// + +// Enable context switch callback *without* QS (QF_ON_CONTEXT_SW) +// Context switch callback QF_onContextSw() when Q_SPY is undefined. +//#ifndef Q_SPY +//#define QF_ON_CONTEXT_SW +//#endif +// + +// Enable context switch callback *with* QS (QF_ON_CONTEXT_SW) +// Context switch callback QF_onContextSw() when Q_SPY is defined. +//#ifdef Q_SPY +//#define QF_ON_CONTEXT_SW +//#endif +// + +// Enable memory isolation (QF_MEM_ISOLATE) +// Memory isolation (requires MPU) +// NOTE: implies QF_ON_CONTEXT_SW. +//#define QF_MEM_ISOLATE +// + // //.......................................................................... -// QS Software Tracing +// QS Software Tracing (Q_SPY) // Target-resident component of QP/Spy software tracing system // (tracing instrumentation and command-input). - -// NOTE: Requires command-line macro: Q_SPY -// The QS software tracing instrumentation is activated only when +// NOTE: The QS software tracing instrumentation is activated only when // the macro Q_SPY is defined on the command-line to the compiler. // Typically, Q_SPY is defined only in the "spy" build configuration. @@ -204,38 +224,6 @@ // -//.......................................................................... -// QV Cooperative Kernel -// Cooperative run-to-completion kernel. - -// Context switch callback (QF_ON_CONTEXT_SW) - -// Context switch callback WITHOUT QS -// Enable context switch callback QF_onContextSw() -// When Q_SPY is undefined. -//#ifndef Q_SPY -//#define QF_ON_CONTEXT_SW -//#endif -// - -// Context switch callback WITH QS -// Enable context switch callback QF_onContextSw() -// When Q_SPY is defined. -//#ifdef Q_SPY -//#define QF_ON_CONTEXT_SW -//#endif -// - -// - -// MPU memory isolation (QF_MEM_ISOLATE) -// Enable memory isolation (requires MPU) -// NOTE: implies QF_ON_CONTEXT_SW. -//#define QF_MEM_ISOLATE -// - -// - //------------- <<< end of configuration section >>> ----------------------- #endif // QP_CONFIG_HPP_ diff --git a/ports/arm-cr/qk/config/qp_config.hpp b/ports/arm-cr/qk/config/qp_config.hpp deleted file mode 100644 index b2621dfc..00000000 --- a/ports/arm-cr/qk/config/qp_config.hpp +++ /dev/null @@ -1,235 +0,0 @@ -//============================================================================ -// QP configuration file (QK on ARM Cortex-R) -// -// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -// -// Q u a n t u m L e a P s -// ------------------------ -// Modern Embedded Software -// -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial -// -// The QP/C software is dual-licensed under the terms of the open-source GNU -// General Public License (GPL) or under the terms of one of the closed- -// source Quantum Leaps commercial licenses. -// -// Redistributions in source code must retain this top-level comment block. -// Plagiarizing this software to sidestep the license obligations is illegal. -// -// NOTE: -// The GPL (see ) does NOT permit the -// incorporation of the QP/C software into proprietary programs. Please -// contact Quantum Leaps for commercial licensing options, which expressly -// supersede the GPL and are designed explicitly for licensees interested -// in using QP/C in closed-source proprietary applications. -// -// Quantum Leaps contact information: -// -// -//============================================================================ -#ifndef QP_CONFIG_HPP_ -#define QP_CONFIG_HPP_ - -//-------- <<< Use Configuration Wizard in Context Menu >>> ----------------- - -// QP API compatibility version (QP_API_VERSION) -// <0=> 0 (Maximum compatibility) -// <691=>691 (QP 6.9.1 or newer) -// <734=>7.3.4 (QP 7.3.4 or newer) -// <9999=>9999 (Latest only) -// QP API backwards compatibility with the QP/C API version. -// Lower QP_API_VERSION values enable backwards compatibility -// with lower (older) QP API versions. -// For example, QP_API_VERSION==691 will enable the compatibility -// layer with QP version 6.9.1 and newer, but not older than 6.9.1. -// QP_API_VERSION==0 enables the maximum currently supported -// backwards compatibility. Conversely, QP_API_VERSION==9999 means -// that no backwards compatibility layer should be enabled. -// Default: 0 (All supported) -#define QP_API_VERSION 0 - -//.......................................................................... -// QP Functional Safety (FuSa) Subsystem (Q_UNSAFE) -// The QP FuSa Subsystem consists of the following facilities: -// - Software assertions as a recommended technique -// (called Failure Assertion Programming (FAP) in IEC 61508) -// - Software Self-Monitoring (SSM), which encompasses such techniques: -// * Duplicate Inverse Storage for critical variables -// * Memory Markers for critical objects (e.g., events) -// * Hard-limits for all loops -// * Memory Isolation by means of Memory Protection Unit (MPU) - -// Disable QP FuSa in development -// Disable assertions and other self monitoring features -// in development build configurations (NDEBUG undefined). -// VIOLATES functional safety standards. NOT recommended !!! -//#ifndef NDEBUG -//#define Q_UNSAFE -//#endif -// - -// Disable QP FuSa in production release -// Disable assertions and other self monitoring features -// in the release build configurations (NDEBUG defined). -// VIOLATES functional safety standards. NOT recommended !!! -//#ifdef NDEBUG -//#define Q_UNSAFE -//#endif -// - -// - -//.......................................................................... -// QEP Event Processor -// Events and state machines. - -// Event signal size (Q_SIGNAL_SIZE) -// <1U=>1 -// <2U=>2 (default) -// <4U=>4 -// Size of the QEvt signal for QEP/QF [bytes] -// Default: 2 -#define Q_SIGNAL_SIZE 2U - -// - -//.......................................................................... -// QF Framework -// Active Object framework - -// Maximum # Active Objects (QF_MAX_ACTIVE) <1-64> -// Maximum # Active Objects in the system <1..64> -// Default: 32 -#define QF_MAX_ACTIVE 32U - -// Maximum # event pools (QF_MAX_EPOOL) -// <0=>0 no event pools -// <1=>1 <2=>2 <3=>3 (default) <4=>4 <5=>5 -// <6=>6 <7=>7 <8=>8 <9=>9 <10=>10 <11=>11 -// <12=>12 <13=>13 <14=>14 <15=>15 -// Maximum # Event Pools <1..15> -// Default: 3 -#define QF_MAX_EPOOL 3U - -// Maximum # clock tick rates (QF_MAX_TICK_RATE) -// <0=>0 no time events -// <1=>1 (default) <2=>2 <3=>3 <4=>4 <5=>5 -// <6=>6 <7=>7 <8=>8 <9=>9 <10=>10 <11=>11 -// <12=>12 <13=>13 <14=>14 <15=>15 -// Maximum # clock tick rates for time events <1..15> -// Default: 1 -#define QF_MAX_TICK_RATE 1U - -// Event parameter initialization (QEVT_PAR_INIT) -// Resource Acquisition Is Initialization (RAII) for dynamic events -//#define QEVT_PAR_INIT -// - -// Provide destructors for QP classes -// Destructors for classes -//#define Q_XTOR -// - -// Active Object stop API (QACTIVE_CAN_STOP) -// Enable Active Object stop API (Not recommended) -//#define QACTIVE_CAN_STOP -// - -// Event size (QF_EVENT_SIZ_SIZE) -// <1U=>1 -// <2U=>2 (default) -// <4U=>4 -// Size of the dynamic events for QF [bytes] -// Default: 2 (64K bytes maximum event size) -#define QF_EVENT_SIZ_SIZE 2U - -// Time event counter size (QF_TIMEEVT_CTR_SIZE) -// <1U=>1 -// <2U=>2 -// <4U=>4 (default) -// Size of the QTimeEvt counter [bytes] -// Default: 4 (2^32 dynamic range) -#define QF_TIMEEVT_CTR_SIZE 4U - -// Event queue counter size (QF_EQUEUE_CTR_SIZE) -// <1U=>1 (default) -// <2U=>2 -// Size of event queue counter [bytes] -// Default: 1 (255 events maximum in a queue) -#define QF_EQUEUE_CTR_SIZE 1U - -// Memory pool counter size (QF_MPOOL_CTR_SIZE) -// <1U=>1 -// <2U=>2 (default) -// <4U=>4 -// Size of memory pool counter [bytes] -// Default: 2 (64K blocks maximum in a pool) -#define QF_MPOOL_CTR_SIZE 2U - -// Memory block size (QF_MPOOL_SIZ_SIZE) -// <1U=>1 -// <2U=>2 (default) -// <4U=>4 -// Size of memory pool block [bytes] -// Default: 2 (64K bytes maximum block size) -#define QF_MPOOL_SIZ_SIZE 2U - -// - -//.......................................................................... -// QS Software Tracing -// Target-resident component of QP/Spy software tracing system -// (tracing instrumentation and command-input). - -// NOTE: Requires command-line macro: Q_SPY -// The QS software tracing instrumentation is activated only when -// the macro Q_SPY is defined on the command-line to the compiler. -// Typically, Q_SPY is defined only in the "spy" build configuration. - -// QS timestamp size (QS_TIME_SIZE) -// <1U=>1 -// <2U=>2 -// <4U=>4 (default) -// Size of the timestamp in QS [bytes] -// Default: 4 (2^32 dynamic range) -#define QS_TIME_SIZE 4U - -// QS buffer counter size (QS_CTR_SIZE) -// <1U=>1 -// <2U=>2 (default) -// <4U=>4 -// Size of the counter in the internal QS buffer [bytes] -// Default: 2 (64K bytes in QS buffer) -#define QS_CTR_SIZE 2U - -// - -//.......................................................................... -// QK Preemptive Non-Blocking Kernel -// Preemptive non-blocking RTOS kernel. - -// Context switch callback (QF_ON_CONTEXT_SW) - -// Context switch callback WITHOUT QS -// Enable context switch callback QF_onContextSw() -// When Q_SPY is undefined. -//#ifndef Q_SPY -//#define QF_ON_CONTEXT_SW -//#endif -// - -// Context switch callback WITH QS -// Enable context switch callback QF_onContextSw() -// When Q_SPY is defined. -//#ifdef Q_SPY -//#define QF_ON_CONTEXT_SW -//#endif -// - -// - -// - -//------------- <<< end of configuration section >>> ----------------------- - -#endif // QP_CONFIG_HPP_ diff --git a/ports/arm-cr/qk/gnu/qp_port.hpp b/ports/arm-cr/qk/gnu/qp_port.hpp index 8a9f82fa..2b25d6f0 100644 --- a/ports/arm-cr/qk/gnu/qp_port.hpp +++ b/ports/arm-cr/qk/gnu/qp_port.hpp @@ -27,7 +27,7 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 +//! @date Last updated on: 2024-11-22 //! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file @@ -61,7 +61,7 @@ #define QF_INT_ENABLE() \ __asm volatile ("MSR cpsr_c,#(0x1F)" ::: "cc") #define QF_INT_ENABLE_ALL() \ - __asm volatile ("MSR cpsr_c,#(0x1F | 0x80 | 0x40)" ::: "cc") + __asm volatile ("MSR cpsr_c,#(0x1F)" ::: "cc") #else #error Incorrect CPU mode. Must be either __arm__ or __thumb__. #endif diff --git a/ports/arm-cr/qv/config/qp_config.hpp b/ports/arm-cr/qv/config/qp_config.hpp deleted file mode 100644 index 8e5152c5..00000000 --- a/ports/arm-cr/qv/config/qp_config.hpp +++ /dev/null @@ -1,235 +0,0 @@ -//============================================================================ -// QP configuration file (QV on ARM Cortex-R) -// -// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -// -// Q u a n t u m L e a P s -// ------------------------ -// Modern Embedded Software -// -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial -// -// The QP/C software is dual-licensed under the terms of the open-source GNU -// General Public License (GPL) or under the terms of one of the closed- -// source Quantum Leaps commercial licenses. -// -// Redistributions in source code must retain this top-level comment block. -// Plagiarizing this software to sidestep the license obligations is illegal. -// -// NOTE: -// The GPL (see ) does NOT permit the -// incorporation of the QP/C software into proprietary programs. Please -// contact Quantum Leaps for commercial licensing options, which expressly -// supersede the GPL and are designed explicitly for licensees interested -// in using QP/C in closed-source proprietary applications. -// -// Quantum Leaps contact information: -// -// -//============================================================================ -#ifndef QP_CONFIG_HPP_ -#define QP_CONFIG_HPP_ - -//-------- <<< Use Configuration Wizard in Context Menu >>> ----------------- - -// QP API compatibility version (QP_API_VERSION) -// <0=> 0 (Maximum compatibility) -// <691=>691 (QP 6.9.1 or newer) -// <734=>7.3.4 (QP 7.3.4 or newer) -// <9999=>9999 (Latest only) -// QP API backwards compatibility with the QP/C API version. -// Lower QP_API_VERSION values enable backwards compatibility -// with lower (older) QP API versions. -// For example, QP_API_VERSION==691 will enable the compatibility -// layer with QP version 6.9.1 and newer, but not older than 6.9.1. -// QP_API_VERSION==0 enables the maximum currently supported -// backwards compatibility. Conversely, QP_API_VERSION==9999 means -// that no backwards compatibility layer should be enabled. -// Default: 0 (All supported) -#define QP_API_VERSION 0 - -//.......................................................................... -// QP Functional Safety (FuSa) Subsystem (Q_UNSAFE) -// The QP FuSa Subsystem consists of the following facilities: -// - Software assertions as a recommended technique -// (called Failure Assertion Programming (FAP) in IEC 61508) -// - Software Self-Monitoring (SSM), which encompasses such techniques: -// * Duplicate Inverse Storage for critical variables -// * Memory Markers for critical objects (e.g., events) -// * Hard-limits for all loops -// * Memory Isolation by means of Memory Protection Unit (MPU) - -// Disable QP FuSa in development -// Disable assertions and other self monitoring features -// in development build configurations (NDEBUG undefined). -// VIOLATES functional safety standards. NOT recommended !!! -//#ifndef NDEBUG -//#define Q_UNSAFE -//#endif -// - -// Disable QP FuSa in production release -// Disable assertions and other self monitoring features -// in the release build configurations (NDEBUG defined). -// VIOLATES functional safety standards. NOT recommended !!! -//#ifdef NDEBUG -//#define Q_UNSAFE -//#endif -// - -// - -//.......................................................................... -// QEP Event Processor -// Events and state machines. - -// Event signal size (Q_SIGNAL_SIZE) -// <1U=>1 -// <2U=>2 (default) -// <4U=>4 -// Size of the QEvt signal for QEP/QF [bytes] -// Default: 2 -#define Q_SIGNAL_SIZE 2U - -// - -//.......................................................................... -// QF Framework -// Active Object framework - -// Maximum # Active Objects (QF_MAX_ACTIVE) <1-64> -// Maximum # Active Objects in the system <1..64> -// Default: 32 -#define QF_MAX_ACTIVE 32U - -// Maximum # event pools (QF_MAX_EPOOL) -// <0=>0 no event pools -// <1=>1 <2=>2 <3=>3 (default) <4=>4 <5=>5 -// <6=>6 <7=>7 <8=>8 <9=>9 <10=>10 <11=>11 -// <12=>12 <13=>13 <14=>14 <15=>15 -// Maximum # Event Pools <1..15> -// Default: 3 -#define QF_MAX_EPOOL 3U - -// Maximum # clock tick rates (QF_MAX_TICK_RATE) -// <0=>0 no time events -// <1=>1 (default) <2=>2 <3=>3 <4=>4 <5=>5 -// <6=>6 <7=>7 <8=>8 <9=>9 <10=>10 <11=>11 -// <12=>12 <13=>13 <14=>14 <15=>15 -// Maximum # clock tick rates for time events <1..15> -// Default: 1 -#define QF_MAX_TICK_RATE 1U - -// Event parameter initialization (QEVT_PAR_INIT) -// Resource Acquisition Is Initialization (RAII) for dynamic events -//#define QEVT_PAR_INIT -// - -// Provide destructors for QP classes -// Destructors for classes -//#define Q_XTOR -// - -// Active Object stop API (QACTIVE_CAN_STOP) -// Enable Active Object stop API (Not recommended) -//#define QACTIVE_CAN_STOP -// - -// Event size (QF_EVENT_SIZ_SIZE) -// <1U=>1 -// <2U=>2 (default) -// <4U=>4 -// Size of the dynamic events for QF [bytes] -// Default: 2 (64K bytes maximum event size) -#define QF_EVENT_SIZ_SIZE 2U - -// Time event counter size (QF_TIMEEVT_CTR_SIZE) -// <1U=>1 -// <2U=>2 -// <4U=>4 (default) -// Size of the QTimeEvt counter [bytes] -// Default: 4 (2^32 dynamic range) -#define QF_TIMEEVT_CTR_SIZE 4U - -// Event queue counter size (QF_EQUEUE_CTR_SIZE) -// <1U=>1 (default) -// <2U=>2 -// Size of event queue counter [bytes] -// Default: 1 (255 events maximum in a queue) -#define QF_EQUEUE_CTR_SIZE 1U - -// Memory pool counter size (QF_MPOOL_CTR_SIZE) -// <1U=>1 -// <2U=>2 (default) -// <4U=>4 -// Size of memory pool counter [bytes] -// Default: 2 (64K blocks maximum in a pool) -#define QF_MPOOL_CTR_SIZE 2U - -// Memory block size (QF_MPOOL_SIZ_SIZE) -// <1U=>1 -// <2U=>2 (default) -// <4U=>4 -// Size of memory pool block [bytes] -// Default: 2 (64K bytes maximum block size) -#define QF_MPOOL_SIZ_SIZE 2U - -// - -//.......................................................................... -// QS Software Tracing -// Target-resident component of QP/Spy software tracing system -// (tracing instrumentation and command-input). - -// NOTE: Requires command-line macro: Q_SPY -// The QS software tracing instrumentation is activated only when -// the macro Q_SPY is defined on the command-line to the compiler. -// Typically, Q_SPY is defined only in the "spy" build configuration. - -// QS timestamp size (QS_TIME_SIZE) -// <1U=>1 -// <2U=>2 -// <4U=>4 (default) -// Size of the timestamp in QS [bytes] -// Default: 4 (2^32 dynamic range) -#define QS_TIME_SIZE 4U - -// QS buffer counter size (QS_CTR_SIZE) -// <1U=>1 -// <2U=>2 (default) -// <4U=>4 -// Size of the counter in the internal QS buffer [bytes] -// Default: 2 (64K bytes in QS buffer) -#define QS_CTR_SIZE 2U - -// - -//.......................................................................... -// QV Cooperative Kernel -// Cooperative run-to-completion RTOS kernel. - -// Context switch callback (QF_ON_CONTEXT_SW) - -// Context switch callback WITHOUT QS -// Enable context switch callback QF_onContextSw() -// When Q_SPY is undefined. -//#ifndef Q_SPY -//#define QF_ON_CONTEXT_SW -//#endif -// - -// Context switch callback WITH QS -// Enable context switch callback QF_onContextSw() -// When Q_SPY is defined. -//#ifdef Q_SPY -//#define QF_ON_CONTEXT_SW -//#endif -// - -// - -// - -//------------- <<< end of configuration section >>> ----------------------- - -#endif // QP_CONFIG_HPP_ diff --git a/ports/arm-cr/qv/gnu/qp_port.hpp b/ports/arm-cr/qv/gnu/qp_port.hpp index b243c54f..ef332ef0 100644 --- a/ports/arm-cr/qv/gnu/qp_port.hpp +++ b/ports/arm-cr/qv/gnu/qp_port.hpp @@ -27,7 +27,7 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 +//! @date Last updated on: 2024-11-22 //! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file @@ -61,7 +61,7 @@ #define QF_INT_ENABLE() \ __asm volatile ("MSR cpsr_c,#(0x1F)" ::: "cc") #define QF_INT_ENABLE_ALL() \ - __asm volatile ("MSR cpsr_c,#(0x1F | 0x80 | 0x40)" ::: "cc") + __asm volatile ("MSR cpsr_c,#(0x1F)" ::: "cc") #else #error Incorrect CPU mode. Must be either __arm__ or __thumb__. #endif diff --git a/ports/config/qp_config.hpp b/ports/config/qp_config.hpp index e7c67eee..193b5bf8 100644 --- a/ports/config/qp_config.hpp +++ b/ports/config/qp_config.hpp @@ -59,19 +59,19 @@ // * Hard-limits for all loops // * Memory Isolation by means of Memory Protection Unit (MPU) -// Disable QP FuSa in development +// Disable QP FuSa in development (NOT recommended) // Disable assertions and other self monitoring features // in development build configurations (NDEBUG undefined). -// VIOLATES functional safety standards. NOT recommended !!! +// NOTE: Disabling safety *violates* functional safety standards. //#ifndef NDEBUG //#define Q_UNSAFE //#endif // -// Disable QP FuSa in production release -// Disable assertions and other self monitoring features +// Disable QP FuSa in production release (NOT recommended) +// Disable assertions and other safety features // in the release build configurations (NDEBUG defined). -// VIOLATES functional safety standards. NOT recommended !!! +// NOTE: Disabling safety *violates* functional safety standards. //#ifdef NDEBUG //#define Q_UNSAFE //#endif @@ -80,7 +80,7 @@ // //.......................................................................... -// QEP Event Processor +// QEP Event Processor (Events) // Events and state machines. // Event signal size (Q_SIGNAL_SIZE) @@ -94,7 +94,7 @@ // //.......................................................................... -// QF Framework +// QF Framework (Active Objects) // Active Object framework // Maximum # Active Objects (QF_MAX_ACTIVE) <1-64> @@ -120,21 +120,6 @@ // Default: 1 #define QF_MAX_TICK_RATE 1U -// Event parameter initialization (QEVT_PAR_INIT) -// Resource Acquisition Is Initialization (RAII) for dynamic events -//#define QEVT_PAR_INIT -// - -// Provide destructors for QP classes -// Destructors for classes -//#define Q_XTOR -// - -// Active Object stop API (QACTIVE_CAN_STOP) -// Enable Active Object stop API (Not recommended) -//#define QACTIVE_CAN_STOP -// - // Event size (QF_EVENT_SIZ_SIZE) // <1U=>1 // <2U=>2 (default) @@ -174,15 +159,50 @@ // Default: 2 (64K bytes maximum block size) #define QF_MPOOL_SIZ_SIZE 2U +// Enable event parameter initialization (QEVT_PAR_INIT) +// Initialize parameters of dynamic events at allocation +// (Resource Acquisition Is Initialization (RAII) for dynamic events) +//#define QEVT_PAR_INIT +// + +// Provide destructors for QP classes +// Presence of destructors pulls in the C++ delete() opeator +// NOTE: Not recommended +//#define Q_XTOR +// + +// Enable active object stop API (QACTIVE_CAN_STOP) +// NOTE: Not recommended +//#define QACTIVE_CAN_STOP +// + +// Enable context switch callback *without* QS (QF_ON_CONTEXT_SW) +// Context switch callback QF_onContextSw() when Q_SPY is undefined. +//#ifndef Q_SPY +//#define QF_ON_CONTEXT_SW +//#endif +// + +// Enable context switch callback *with* QS (QF_ON_CONTEXT_SW) +// Context switch callback QF_onContextSw() when Q_SPY is defined. +//#ifdef Q_SPY +//#define QF_ON_CONTEXT_SW +//#endif +// + +// Enable memory isolation (QF_MEM_ISOLATE) +// Memory isolation (requires MPU) +// NOTE: implies QF_ON_CONTEXT_SW. +//#define QF_MEM_ISOLATE +// + // //.......................................................................... -// QS Software Tracing +// QS Software Tracing (Q_SPY) // Target-resident component of QP/Spy software tracing system // (tracing instrumentation and command-input). - -// NOTE: Requires command-line macro: Q_SPY -// The QS software tracing instrumentation is activated only when +// NOTE: The QS software tracing instrumentation is activated only when // the macro Q_SPY is defined on the command-line to the compiler. // Typically, Q_SPY is defined only in the "spy" build configuration. diff --git a/qpcpp.qm b/qpcpp.qm index 59e1714b..9e7f4e5f 100644 --- a/qpcpp.qm +++ b/qpcpp.qm @@ -3431,12 +3431,12 @@ QF_CRIT_EXIT(); noexcept - QF_CRIT_STAT -QF_CRIT_ENTRY(); + // NOTE: this function must be called *inside* critical section Q_REQUIRE_INCRIT(900, tickRate < QF_MAX_TICK_RATE); -QF_CRIT_EXIT(); bool inactive; + +QF_MEM_SYS(); if (timeEvtHead_[tickRate].m_next != nullptr) { inactive = false; } @@ -3446,6 +3446,8 @@ else if (timeEvtHead_[tickRate].m_act != nullptr) { else { inactive = true; } +QF_MEM_APP(); + return inactive; @@ -5840,9 +5842,9 @@ QF_onContextSw(QP::QActive::registry_[pprev], a); #define QP_HPP_ //============================================================================ -#define QP_VERSION_STR "8.0.0" -#define QP_VERSION 800U -#define QP_RELEASE 0x7055936FU +#define QP_VERSION_STR "8.0.1" +#define QP_VERSION 801U +#define QP_RELEASE 0x703931CEU //============================================================================ //! @cond INTERNAL @@ -6299,7 +6301,6 @@ using char_t = char; #define QP_IMPL // this is QP implementation #include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface #include "qsafe.h" // QP Functional Safety (FuSa) Subsystem #ifdef Q_SPY // QS software tracing enabled? #include "qs_port.hpp" // QS port @@ -6367,7 +6368,6 @@ $define ${QEP::QHsm} #define QP_IMPL // this is QP implementation #include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface #include "qsafe.h" // QP Functional Safety (FuSa) Subsystem #ifdef Q_SPY // QS software tracing enabled? #include "qs_port.hpp" // QS port diff --git a/qpcpp.sha1 b/qpcpp_8.0.1.sha1 similarity index 67% rename from qpcpp.sha1 rename to qpcpp_8.0.1.sha1 index 35a61dd6..7fe10a29 100644 --- a/qpcpp.sha1 +++ b/qpcpp_8.0.1.sha1 @@ -1,18 +1,21 @@ -a37f690d75dac83d45b5da3082d28f188191fd9a *qpcpp.qm +bda783a346fb750c7a1fe32dc0a8ca52609cb5f4 *qpcpp.qm 46578fc304c597329289978acee1027c8c533335 *include/qequeue.hpp 1a8e0b05536b89c1cd3806782ae1a21dd4ceca69 *include/qk.hpp cb1c39aabacb619060924356f7c8e900686538e0 *include/qmpool.hpp -e0d974faef6b60cc455e49abb32d43128b8c79cf *include/qp.hpp +559a9ca895f97f38c5d3bb0511675f321e041911 *include/qp.hpp bf47a939e525fa575673f89b8106bcee166240a2 *include/qp_pkg.hpp e5b0d14c9e6994b82a5cd9200bde46bd179bfb20 *include/qpcpp.hpp +d4f14d2ed18ef725ea17d0a97b78ae22a283c96b *include/qs.hpp 88220a7d892fee54053b467b596dc6b536aaf8be *include/qs_dummy.hpp +9694f10e44d53563599410d37dd1c5a19cf1788b *include/qs_pkg.hpp 49d2620b0afa9e74d73680495c3e8a931e5d8f73 *include/qsafe.h 09e9ffe95120ba17a49d7039b5316f2614710dab *include/qstamp.hpp 73749ed396bbc0419971769a47069448c8136960 *include/qv.hpp +05b617dad20f07f07b64dccf84f9b7cd9b8d2bb7 *include/qxk.hpp 0199f3eeb6c02b8cc890ee4c6f6d344569a0858f *include/README.md 71899ce74eeb04f333ed00d53f87719f722a39ab *src/qf/CMakeLists.txt -81b54ca9a4dff44d24c0f3cd687aaa58afe634ab *src/qf/qep_hsm.cpp -13cb63db437dd4f176dd846eda49bda9827ca571 *src/qf/qep_msm.cpp +864d627f2600987a2194c57093e1f210e0de2a7a *src/qf/qep_hsm.cpp +d3242def2b23df5b9704bb3b0411fd01de6c0a67 *src/qf/qep_msm.cpp 62f87a60d04e1c98f40162a166ec14a1f2f1252f *src/qf/qf_act.cpp 07671fb85e9b2492b0ea37b853d7e0eea42bf637 *src/qf/qf_actq.cpp ed83f5f8b3533cc97ffc2a85aeeb63f29b4f1dd8 *src/qf/qf_defer.cpp @@ -22,41 +25,58 @@ ef51e4840107b0ed6ec97e170ac2689e1b1fdb95 *src/qf/qf_ps.cpp 08b490d7505a7ff6fe493058975eb9f0a82daa3d *src/qf/qf_qact.cpp 23892cde4fd7226e899026884e07b01e32d0aef4 *src/qf/qf_qeq.cpp 5fc4874b74779641454e2d8e7960a5bf3d130115 *src/qf/qf_qmact.cpp -7aedf35884943f3add9f39e57e5ea4ad7344d110 *src/qf/qf_time.cpp +04dd9fbddc336f096bd214f8e7368d7a6dce43c8 *src/qf/qf_time.cpp 7cdab433e81612862fd27f0cf792d38e1197d064 *src/qk/CMakeLists.txt 1be4743dc14186779abb96b4bd16ba9a99d3314d *src/qk/qk.cpp eb28260d471fc752ca54b2c1e2d763f28432c2c1 *src/qs/CMakeLists.txt +66fd2a553c8ae6709dfe286b6ccce002208251f1 *src/qs/qs.cpp +2ca73a0d38dd7b544864d72fd337f29c7dae2a85 *src/qs/qs_64bit.cpp +349c18625bd2cceda297e1c98a85a9fa9538cef9 *src/qs/qs_fp.cpp +ad4e3a9faacc038cb51a7773ffc42903be947a22 *src/qs/qs_rx.cpp 8008d9c24757b2bb02e85123aa89a3a33090921d *src/qs/qstamp.cpp +92338453dc612419b0e16e0560e761312d0f3900 *src/qs/qutest.cpp b6d93a16f5b176d3da4888a7efb265730337f46d *src/qv/CMakeLists.txt f530563e062ff7ea84763f6e799bf4ca1cb73054 *src/qv/qv.cpp -8456ce45995423dd872685229539618abaa9c580 *ports/arm-cm/qk/armclang/qk_port.cpp -94a289a5f900afaeb47b5454824bc4911df8014f *ports/arm-cm/qk/armclang/qp_port.hpp +2d0c3d3d93e4d4ac8e2218b9ed68e6269b02419e *src/qxk/qxk.cpp +e0e633a980e4c04a85f877e810ce77ad51903e87 *src/qxk/qxk_mutex.cpp +8e15812d14f250866dfa8a96fe5b14638ca2c4ae *src/qxk/qxk_sema.cpp +58e6a9354a1c7c4d53204b7ad2fad05d6eb3117c *src/qxk/qxk_xthr.cpp +81f1a6dbcebd0b5df9e437902ffbe0fecdd03d25 *ports/arm-cm/qk/armclang/qk_port.cpp +7119fc94c0b5560ab8e3197a83917667e311e415 *ports/arm-cm/qk/armclang/qp_port.hpp 5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qk/armclang/qs_port.hpp -fafeded481e004677bfa6eb7cce7e4c4dbd5fd2f *ports/arm-cm/qk/config/qp_config.hpp -f94a3fb033b87de04efec19e25c5630b82e9d749 *ports/arm-cm/qk/gnu/qk_port.cpp -1c35b7f6a992d0a4755080903d2a2fd5aa06c923 *ports/arm-cm/qk/gnu/qp_port.hpp +5f2353117f9940b0ea891d2e0bd486e0d024b67c *ports/arm-cm/qk/gnu/qk_port.cpp +7119fc94c0b5560ab8e3197a83917667e311e415 *ports/arm-cm/qk/gnu/qp_port.hpp 5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qk/gnu/qs_port.hpp -f52bee74512d5c2016eaf20996eee10e52a5d71f *ports/arm-cm/qk/iar/qk_port.cpp -458994edab3235f9d9a9faf78485ecb4edc3bdd1 *ports/arm-cm/qk/iar/qp_port.hpp +2b9c1112e3e5be79ce2b1799adfd5e812467765b *ports/arm-cm/qk/iar/qk_port.cpp +f54416674c33ffd19408f02af60f7d69b8613797 *ports/arm-cm/qk/iar/qp_port.hpp 5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qk/iar/qs_port.hpp -f59663361efec401c02436eabfe6931729d98b1d *ports/arm-cm/qv/armclang/qp_port.hpp +9cc71aed12d57408252019035aff449ce028372c *ports/arm-cm/qv/armclang/qp_port.hpp 5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qv/armclang/qs_port.hpp -c225966c8601a651196e3e30af7d0dce6079d610 *ports/arm-cm/qv/armclang/qv_port.cpp -d7f22b95fc3b2228a669c5b9167bc3021156a8c7 *ports/arm-cm/qv/config/qp_config.hpp -fffed0cc5c1180df7550f579268ab7c528f3afda *ports/arm-cm/qv/gnu/qp_port.hpp +90b14adcd8f8b29de3358073c39bd4161f5ce2eb *ports/arm-cm/qv/armclang/qv_port.cpp +bed3687b29555f6fa9c721cf34a098218f64e1ad *ports/arm-cm/qv/gnu/qp_port.hpp 5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qv/gnu/qs_port.hpp -bd87c7c78142119968ae65dda01ba75b3170ca08 *ports/arm-cm/qv/gnu/qv_port.cpp -cf46244c7dfb6185f2c01cfdba4d699bf01388e7 *ports/arm-cm/qv/iar/qp_port.hpp +b2d5e72b65813bdc37bcab3c8cd9107bda009131 *ports/arm-cm/qv/gnu/qv_port.cpp +424864680661227e4ab418b2af905d4bd92767ad *ports/arm-cm/qv/iar/qp_port.hpp 5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qv/iar/qs_port.hpp -421f4bc740a150dae18672f22633bef822119071 *ports/arm-cm/qv/iar/qv_port.cpp -7341172192afc119dc3188b51e64b6cb33dc4f23 *ports/arm-cr/qk/config/qp_config.hpp -53378c89dd07cdf1b5fc1428938a2bf33ef9c897 *ports/arm-cr/qk/gnu/qp_port.hpp +15fb0660dff33295bad38facfc7aacca928133a3 *ports/arm-cm/qv/iar/qv_port.cpp +9e248cb426d8495e5cd677ff79cd3b9ced2a76a5 *ports/arm-cm/qxk/armclang/qp_port.hpp +5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qxk/armclang/qs_port.hpp +16423aebab91be16d8c2c7b128d8494709a6a746 *ports/arm-cm/qxk/armclang/qxk_port.cpp +9ec8ed9717f9130b23252d2c381f779617165932 *ports/arm-cm/qxk/gnu/qp_port.hpp +5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qxk/gnu/qs_port.hpp +75fc7a6c1b0775832f3e0e0e2bbacc19f56ddc94 *ports/arm-cm/qxk/gnu/qxk_port.cpp +f40b0ea4761d187ac7d4460a161efb9b4f3e6ef6 *ports/arm-cm/qxk/iar/qp_port.hpp +5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qxk/iar/qs_port.hpp +44509ff079ba173a28076f3fa1488582a6ef48a1 *ports/arm-cm/qxk/iar/qxk_port.cpp +69256fd1a5b81db3e3174cba9196bf9da925e098 *ports/arm-cm/qutest/qp_port.hpp +5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qutest/qs_port.hpp +1194c26fdfc9665a04cc3d01e6de49afe1698376 *ports/arm-cr/qk/gnu/qp_port.hpp 5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cr/qk/gnu/qs_port.hpp a8f4351725564e449206909176d09bc58cd6f45d *ports/arm-cr/qk/iar/qp_port.hpp 5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cr/qk/iar/qs_port.hpp 7203200deaa5dbb4746434d4a3d79a160d4ccf4b *ports/arm-cr/qk/ti/qp_port.hpp 5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cr/qk/ti/qs_port.hpp -b79ee5fda27709554b5dbdc3162d59787af85ecb *ports/arm-cr/qv/gnu/qp_port.hpp +fd3e4b882efb671f2522ae83bfde016ea416d4a7 *ports/arm-cr/qv/gnu/qp_port.hpp 5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cr/qv/gnu/qs_port.hpp fafbe56ae4266a412cb1b6db6e146fbfe5022b4a *ports/arm-cr/qv/iar/qp_port.hpp 5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cr/qv/iar/qs_port.hpp @@ -68,7 +88,7 @@ bc080e68d0edfc28da2df882ed3661cf99f2942c *ports/msp430/qk/qp_port.hpp 197ec45394793b79a29afe5bb31b6de1ad78ad00 *ports/msp430/qv/qs_port.hpp 650f628d87a39c559a87c6f849c58fb9a8e777a7 *ports/msp430/qutest/qp_port.hpp 197ec45394793b79a29afe5bb31b6de1ad78ad00 *ports/msp430/qutest/qs_port.hpp -59011c6a3cbf07a38f1a74139cef1a82f22cc475 *ports/config/qp_config.hpp +8614593b911e6db6f634d972e79093e964756556 *ports/config/qp_config.hpp b6b5d23c618976a6fbed51dc5a13e227928e1d4b *ports/embos/CMakeLists.txt 0b5ad806f47800c1481c9af3d88c1bff3cb1d784 *ports/embos/qf_port.cpp 5e28aa0e89239f970e4b5e85be4e5c3b6a34dd69 *ports/embos/qp_port.hpp @@ -103,6 +123,11 @@ f458af1511007d6ba2a4a0a0e40d74e03719ceb1 *ports/posix-qv/qp_port.hpp f38e2f9bfe4df4d44a8f9a5fa2c0b2dfd79f35ae *ports/posix-qv/qs_port.hpp e2e295c371bc14f0089a888b07d98c657dea07bf *ports/posix-qv/README.md 7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/posix-qv/safe_std.h +c9969a454b540a3b1abd3dd5cc46fb211663310e *ports/posix-qutest/CMakeLists.txt +edfa2baff22735f98a094e315db11c40ed07e5e8 *ports/posix-qutest/qp_port.hpp +f38e2f9bfe4df4d44a8f9a5fa2c0b2dfd79f35ae *ports/posix-qutest/qs_port.hpp +772fdcf6a4ca3e3303016384de92874ec06c11fe *ports/posix-qutest/qutest_port.cpp +7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/posix-qutest/safe_std.h 06b76c6c30ea880876b47ee27115178ff62ea66b *ports/win32/CMakeLists.txt 48dfd18fce993f237138d5d99f2fb0e385efbe93 *ports/win32/qf_port.cpp ea88910c991455756433cff5338a62ed3d181bf2 *ports/win32/qp_port.hpp @@ -121,6 +146,11 @@ f38e2f9bfe4df4d44a8f9a5fa2c0b2dfd79f35ae *ports/win32-qv/qs_port.hpp ddc62932b46bbc0ad147193d0dd7efa28127c6c4 *ports/win32-qv/qwin_gui.h ddd27415c3d1df6d8c210966e8915c407b15bf58 *ports/win32-qv/README.md 7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/win32-qv/safe_std.h +3c23c06f425a8d8dbb18d1f191ac6cab483a8e51 *ports/win32-qutest/CMakeLists.txt +edfa2baff22735f98a094e315db11c40ed07e5e8 *ports/win32-qutest/qp_port.hpp +f38e2f9bfe4df4d44a8f9a5fa2c0b2dfd79f35ae *ports/win32-qutest/qs_port.hpp +5bda26c8c82914e6cc16685e4adc02cbc32c5291 *ports/win32-qutest/qutest_port.cpp +7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/win32-qutest/safe_std.h 76dd9078dc4311d53d3862d44177a8660258da6d *zephyr/CMakeLists.txt 36a0252cf0bfd6be0d345c48c00b2300f8917f05 *zephyr/Kconfig 2eb2a922e18b4760a68151ebee1b6282d20b4692 *zephyr/module.yml diff --git a/qpcpp_sha1.bat b/qpcpp_sha1.bat index 427925f8..c4282691 100644 --- a/qpcpp_sha1.bat +++ b/qpcpp_sha1.bat @@ -1,18 +1,20 @@ @setlocal +set VERSION=8.0.1 + :: usage @echo Usage: qppcp_sha1 [gen] @echo examples: -@echo qppcp_sha1 : check the sha1 sums in the file qpcpp.sha1 -@echo qpcpp_sha1 gen : generate the sha1 file qpcpp.sha1 +@echo qppcp_sha1 : check the sha1 sums in the file qpcpp_%VERSION%.sha1 +@echo qpcpp_sha1 gen : generate the sha1 file qpcpp_%VERSION%.sha1 @echo. @if NOT "%1"=="gen" ( -sha1sum --check --warn qpcpp.sha1 +sha1sum --check --warn qpcpp_%VERSION%.sha1 goto end ) -@echo generating qpcpp.sha1... +@echo generating qpcpp_%VERSION%.sha1... @sha1sum qpcpp.qm ^ include/* ^ src/qf/* src/qk/* src/qs/* src/qv/* src/qxk/* ^ @@ -33,7 +35,7 @@ goto end ports/posix/* ports/posix-qv/* ports/posix-qutest/* ^ ports/win32/* ports/win32-qv/* ports/win32-qutest/* ^ zephyr/* ^ - > qpcpp.sha1 + > qpcpp_%VERSION%.sha1 @echo done :end diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 24e53384..e41bd9f0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,7 +1,7 @@ # qpcpp/src add_subdirectory(qf) add_subdirectory(qs) -if(${PORT} IN_LIST QPC_BAREMETAL_PORTS) +if(${PORT} IN_LIST QPCPP_BAREMETAL_PORTS) message(STATUS "adding subdir '${KERNEL}' for port '${PORT}'") add_subdirectory(${KERNEL}) endif() diff --git a/src/qf/qep_hsm.cpp b/src/qf/qep_hsm.cpp index 5879b8c7..e00adb97 100644 --- a/src/qf/qep_hsm.cpp +++ b/src/qf/qep_hsm.cpp @@ -34,7 +34,6 @@ //$endhead${src::qf::qep_hsm.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #define QP_IMPL // this is QP implementation #include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface #include "qsafe.h" // QP Functional Safety (FuSa) Subsystem #ifdef Q_SPY // QS software tracing enabled? #include "qs_port.hpp" // QS port diff --git a/src/qf/qep_msm.cpp b/src/qf/qep_msm.cpp index 0a6c30e3..160f3196 100644 --- a/src/qf/qep_msm.cpp +++ b/src/qf/qep_msm.cpp @@ -34,7 +34,6 @@ //$endhead${src::qf::qep_msm.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #define QP_IMPL // this is QP implementation #include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface #include "qsafe.h" // QP Functional Safety (FuSa) Subsystem #ifdef Q_SPY // QS software tracing enabled? #include "qs_port.hpp" // QS port diff --git a/src/qf/qf_time.cpp b/src/qf/qf_time.cpp index 6f3cf51c..c2c49e75 100644 --- a/src/qf/qf_time.cpp +++ b/src/qf/qf_time.cpp @@ -519,12 +519,12 @@ void QTimeEvt::tick( //${QF::QTimeEvt::noActive} .................................................. bool QTimeEvt::noActive(std::uint_fast8_t const tickRate) noexcept { - QF_CRIT_STAT - QF_CRIT_ENTRY(); + // NOTE: this function must be called *inside* critical section Q_REQUIRE_INCRIT(900, tickRate < QF_MAX_TICK_RATE); - QF_CRIT_EXIT(); bool inactive; + + QF_MEM_SYS(); if (timeEvtHead_[tickRate].m_next != nullptr) { inactive = false; } @@ -534,6 +534,8 @@ bool QTimeEvt::noActive(std::uint_fast8_t const tickRate) noexcept { else { inactive = true; } + QF_MEM_APP(); + return inactive; }