From 12c924a1561ec0f314b7ac8f20af2e326829e63c Mon Sep 17 00:00:00 2001 From: MMS Date: Fri, 22 Nov 2024 09:49:12 -0500 Subject: [PATCH] 8.0.1 added missing to ports/posix/qp_port.h changed ports to ARM-CM, BASEPRI critical section updated qp_config.h files updated examples fixed arm-cr ports, GNU compiler, ARM mode, QF_INT_ENABLE_ALL() macro --- cmakeSupport.md | 2 +- examples | 2 +- include/qp.h | 18 +- ports/arm-cm/{qk => }/config/qp_config.h | 129 +++++++------ ports/arm-cm/qk/armclang/qk_port.c | 122 ++++++------ ports/arm-cm/qk/armclang/qp_port.h | 63 +++--- ports/arm-cm/qk/gnu/qk_port.c | 123 ++++++------ ports/arm-cm/qk/gnu/qp_port.h | 62 +++--- ports/arm-cm/qk/iar/qk_port.c | 122 ++++++------ ports/arm-cm/qk/iar/qp_port.h | 62 +++--- ports/arm-cm/qv/armclang/qp_port.h | 87 ++++----- ports/arm-cm/qv/armclang/qv_port.c | 105 +++++----- ports/arm-cm/qv/config/qp_config.h | 236 ----------------------- ports/arm-cm/qv/gnu/qp_port.h | 87 ++++----- ports/arm-cm/qv/gnu/qv_port.c | 105 +++++----- ports/arm-cm/qv/iar/qp_port.h | 85 ++++---- ports/arm-cm/qv/iar/qv_port.c | 104 +++++----- ports/arm-cr/{qk => }/config/qp_config.h | 88 ++++----- ports/arm-cr/qk/gnu/qp_port.h | 4 +- ports/arm-cr/qv/config/qp_config.h | 229 ---------------------- ports/arm-cr/qv/gnu/qp_port.h | 4 +- ports/config/qp_config.h | 61 ++++-- ports/posix/qp_port.h | 5 +- qpc.qm | 28 ++- qpc.sha1 => qpc_8.0.1.sha1 | 78 +++++--- qpc_sha1.bat | 12 +- src/qf/qep_hsm.c | 1 - src/qf/qep_msm.c | 1 - src/qf/qf_time.c | 8 +- 29 files changed, 753 insertions(+), 1280 deletions(-) rename ports/arm-cm/{qk => }/config/qp_config.h (76%) delete mode 100644 ports/arm-cm/qv/config/qp_config.h rename ports/arm-cr/{qk => }/config/qp_config.h (83%) delete mode 100644 ports/arm-cr/qv/config/qp_config.h rename qpc.sha1 => qpc_8.0.1.sha1 (66%) diff --git a/cmakeSupport.md b/cmakeSupport.md index 601b2ecc..87699eb8 100644 --- a/cmakeSupport.md +++ b/cmakeSupport.md @@ -76,7 +76,7 @@ This file is situated in the root directory of qpc. It performs a pre-initializa + `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 Winows, Linux (Posix compatible systems) * `QPC-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 45b3d037..81a03923 160000 --- a/examples +++ b/examples @@ -1 +1 @@ -Subproject commit 45b3d03705750696b3281790ed2ab2b0bbf560e1 +Subproject commit 81a03923724160d56faa0096823c941a3601d68e diff --git a/include/qp.h b/include/qp.h index bb878de7..43197a72 100644 --- a/include/qp.h +++ b/include/qp.h @@ -36,9 +36,9 @@ #define QP_H_ //============================================================================ -#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 @@ -434,18 +434,14 @@ QState QMsm_enterHistory_( //${QEP-macros::QASM_INIT} ................................................... #ifdef Q_SPY -#define QASM_INIT(me_, par_, qsId_) do { \ - Q_ASSERT(((QAsm *)(me_))->vptr); \ - (*((QAsm *)(me_))->vptr->init)((QAsm *)(me_), (par_), (qsId_)); \ -} while (false) +#define QASM_INIT(me_, par_, qsId_) \ + (*((QAsm *)(me_))->vptr->init)((QAsm *)(me_), (par_), (qsId_)) #endif // def Q_SPY //${QEP-macros::QASM_INIT} ................................................... #ifndef Q_SPY -#define QASM_INIT(me_, par_, dummy) do { \ - Q_ASSERT(((QAsm *)(me_))->vptr); \ - (*((QAsm *)(me_))->vptr->init)((QAsm *)(me_), (par_), 0); \ -} while (false) +#define QASM_INIT(me_, par_, dummy) \ + (*((QAsm *)(me_))->vptr->init)((QAsm *)(me_), (par_), 0U) #endif // ndef Q_SPY //${QEP-macros::QASM_DISPATCH} ............................................... diff --git a/ports/arm-cm/qk/config/qp_config.h b/ports/arm-cm/config/qp_config.h similarity index 76% rename from ports/arm-cm/qk/config/qp_config.h rename to ports/arm-cm/config/qp_config.h index ac58c0ef..42dcef3c 100644 --- a/ports/arm-cm/qk/config/qp_config.h +++ b/ports/arm-cm/config/qp_config.h @@ -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,16 +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 -// - -// 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) @@ -169,15 +159,69 @@ // 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 +// + +// 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. @@ -199,47 +243,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_H_ diff --git a/ports/arm-cm/qk/armclang/qk_port.c b/ports/arm-cm/qk/armclang/qk_port.c index 67715269..24b87e02 100644 --- a/ports/arm-cm/qk/armclang/qk_port.c +++ b/ports/arm-cm/qk/armclang/qk_port.c @@ -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.h" #include "qsafe.h" // QP Functional Safety (FuSa) Subsystem @@ -68,7 +62,6 @@ void NMI_Handler(void); // For best performance, these functions are implemented in assembly, // but they can be implemented in C as well. - //int32_t volatile QF_int_lock_nest_; // not used extern char const QF_port_module_[]; char const QF_port_module_[] = "qk_port"; @@ -77,24 +70,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" @@ -109,28 +101,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" @@ -143,25 +136,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" @@ -177,29 +168,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" @@ -217,7 +206,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. @@ -226,18 +215,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)); @@ -372,9 +361,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... @@ -390,7 +382,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) @@ -440,15 +437,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.h b/ports/arm-cm/qk/armclang/qp_port.h index c3b2196e..6ffa552d 100644 --- a/ports/arm-cm/qk/armclang/qp_port.h +++ b/ports/arm-cm/qk/armclang/qp_port.h @@ -1,5 +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 @@ -26,12 +27,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 -//! @version Last updated for: @ref qpc_8_0_0 -//! -//! @file -//! @brief QP/C port to ARM Cortex-M, preemptive QK kernel, ARM-CLANG - #ifndef QP_PORT_H_ #define QP_PORT_H_ @@ -47,31 +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((uint32_t)(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_) ((uint_fast8_t)(32 - __builtin_clz((unsigned)(n_)))) - -#endif - // interrupt disabling policy, see NOTE2 and NOTE3 #define QF_INT_DISABLE() (QF_int_disable_()) #define QF_INT_ENABLE() (QF_int_enable_()) @@ -83,11 +56,27 @@ #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((uint32_t)(n_)) + // hand-optimized quick LOG2 in assembly uint_fast8_t QF_qlog2(uint32_t x); +#else // ARMv7-M or higher + // ARMv7-M or higher provide the CLZ instruction for fast LOG2 + #define QF_LOG2(n_) ((uint_fast8_t)(32 - __builtin_clz((unsigned)(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 @@ -104,7 +93,7 @@ void QF_onMemSys(void); 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) @@ -186,7 +175,7 @@ extern int32_t volatile QF_int_lock_nest_; // 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 @@ -195,15 +184,15 @@ extern int32_t volatile QF_int_lock_nest_; // 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.c b/ports/arm-cm/qk/gnu/qk_port.c index a350e873..c65204e9 100644 --- a/ports/arm-cm/qk/gnu/qk_port.c +++ b/ports/arm-cm/qk/gnu/qk_port.c @@ -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.h" #include "qsafe.h" // QP Functional Safety (FuSa) Subsystem @@ -68,7 +62,6 @@ void NMI_Handler(void); // For best performance, these functions are implemented in assembly, // but they can be implemented in C as well. - //int32_t volatile QF_int_lock_nest_; // not used extern char const QF_port_module_[]; char const QF_port_module_[] = "qk_port"; @@ -77,24 +70,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" @@ -109,28 +101,30 @@ __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" @@ -143,25 +137,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" @@ -177,29 +169,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" @@ -217,7 +207,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. @@ -226,18 +216,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)); @@ -381,9 +371,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... @@ -399,7 +392,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) @@ -449,15 +447,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.h b/ports/arm-cm/qk/gnu/qp_port.h index 519527a2..23e6491e 100644 --- a/ports/arm-cm/qk/gnu/qp_port.h +++ b/ports/arm-cm/qk/gnu/qp_port.h @@ -26,12 +26,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 -//! @version Last updated for: @ref qpc_8_0_0 -//! -//! @file -//! @brief QP/C port to ARM Cortex-M, preemptive QK kernel, GNU-ARM - #ifndef QP_PORT_H_ #define QP_PORT_H_ @@ -47,31 +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((uint32_t)(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_) ((uint_fast8_t)(32 - __builtin_clz((unsigned)(n_)))) - -#endif - // interrupt disabling policy, see NOTE2 and NOTE3 #define QF_INT_DISABLE() (QF_int_disable_()) #define QF_INT_ENABLE() (QF_int_enable_()) @@ -83,11 +55,27 @@ #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((uint32_t)(n_)) + // hand-optimized quick LOG2 in assembly uint_fast8_t QF_qlog2(uint32_t x); +#else // ARMv7-M or higher + // ARMv7-M or higher provide the CLZ instruction for fast LOG2 + #define QF_LOG2(n_) ((uint_fast8_t)(32 - __builtin_clz((unsigned)(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 @@ -104,7 +92,7 @@ void QF_onMemSys(void); 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) @@ -186,7 +174,7 @@ extern int32_t volatile QF_int_lock_nest_; // 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 @@ -195,15 +183,15 @@ extern int32_t volatile QF_int_lock_nest_; // 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/iar/qk_port.c b/ports/arm-cm/qk/iar/qk_port.c index 360be31a..5a9a63c2 100644 --- a/ports/arm-cm/qk/iar/qk_port.c +++ b/ports/arm-cm/qk/iar/qk_port.c @@ -1,5 +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 @@ -26,12 +27,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.h" #include "qsafe.h" // QP Functional Safety (FuSa) Subsystem @@ -81,24 +76,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" @@ -113,28 +107,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" @@ -147,25 +142,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" @@ -181,29 +174,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" @@ -221,7 +212,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. @@ -230,18 +221,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)); @@ -376,9 +367,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... @@ -394,7 +388,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) @@ -444,15 +443,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/iar/qp_port.h b/ports/arm-cm/qk/iar/qp_port.h index 5dc7c297..ae9c3046 100644 --- a/ports/arm-cm/qk/iar/qp_port.h +++ b/ports/arm-cm/qk/iar/qp_port.h @@ -26,12 +26,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 -//! @version Last updated for: @ref qpc_8_0_0 -//! -//! @file -//! @brief QP/C port to ARM Cortex-M, preemptive QK kernel, IAR-ARM - #ifndef QP_PORT_H_ #define QP_PORT_H_ @@ -48,31 +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((uint32_t)(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_) ((uint_fast8_t)(32U - __CLZ((unsigned long)(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 +56,27 @@ #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((uint32_t)(n_)) + // hand-optimized quick LOG2 in assembly uint_fast8_t QF_qlog2(uint32_t x); +#else // ARMv7-M or higher + // ARMv7-M or higher provide the CLZ instruction for fast LOG2 + #define QF_LOG2(n_) ((uint_fast8_t)(32U - __CLZ((unsigned long)(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 @@ void QF_onMemSys(void); 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) @@ -180,7 +168,7 @@ extern int32_t volatile QF_int_lock_nest_; // 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 @@ -189,15 +177,15 @@ extern int32_t volatile QF_int_lock_nest_; // 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/qv/armclang/qp_port.h b/ports/arm-cm/qv/armclang/qp_port.h index 07d6d0aa..cd92c929 100644 --- a/ports/arm-cm/qv/armclang/qp_port.h +++ b/ports/arm-cm/qv/armclang/qp_port.h @@ -26,12 +26,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 -//! @version Last updated for: @ref qpc_8_0_0 -//! -//! @file -//! @brief QP/C port to ARM Cortex-M, cooperative QV kernel, ARM-CLANG - #ifndef QP_PORT_H_ #define QP_PORT_H_ @@ -47,31 +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((uint32_t)(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_) ((uint_fast8_t)(32 - __builtin_clz((unsigned)(n_)))) - -#endif - // interrupt disabling policy, see NOTE2 and NOTE3 #define QF_INT_DISABLE() (QF_int_disable_()) #define QF_INT_ENABLE() (QF_int_enable_()) @@ -83,11 +55,27 @@ #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((uint32_t)(n_)) + // hand-optimized quick LOG2 in assembly uint_fast8_t QF_qlog2(uint32_t x); +#else // ARMv7-M or higher + // ARMv7-M or higher provide the CLZ instruction for fast LOG2 + #define QF_LOG2(n_) ((uint_fast8_t)(32 - __builtin_clz((unsigned)(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 @@ -104,20 +92,10 @@ void QF_onMemSys(void); 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 { \ @@ -127,6 +105,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. @@ -168,7 +157,7 @@ extern int32_t volatile QF_int_lock_nest_; // 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 @@ -177,15 +166,15 @@ extern int32_t volatile QF_int_lock_nest_; // 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/qv/armclang/qv_port.c b/ports/arm-cm/qv/armclang/qv_port.c index 8644d433..d30ebd24 100644 --- a/ports/arm-cm/qv/armclang/qv_port.c +++ b/ports/arm-cm/qv/armclang/qv_port.c @@ -26,12 +26,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 -//! @version Last updated for: @ref qpc_8_0_0 -//! -//! @file -//! @brief QV/C port to ARM Cortex-M, ARM-CLANG - #define QP_IMPL 1U #include "qp_port.h" #include "qsafe.h" // QP Functional Safety (FuSa) Subsystem @@ -57,7 +51,6 @@ // For best performance, these functions are implemented in assembly, // but they can be implemented in C as well. - //int32_t volatile QF_int_lock_nest_; // not used extern char const QF_port_module_[]; char const QF_port_module_[] = "qv_port"; @@ -66,24 +59,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" @@ -98,28 +90,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" @@ -132,25 +125,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" @@ -166,29 +157,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" @@ -206,7 +195,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. @@ -215,18 +204,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.h b/ports/arm-cm/qv/config/qp_config.h deleted file mode 100644 index 14ed0755..00000000 --- a/ports/arm-cm/qv/config/qp_config.h +++ /dev/null @@ -1,236 +0,0 @@ -//============================================================================ -// QP configuration file (QV on ARM Cortex-M) -// -// 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_H_ -#define QP_CONFIG_H_ - -//-------- <<< 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 -// - -// 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 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_H_ diff --git a/ports/arm-cm/qv/gnu/qp_port.h b/ports/arm-cm/qv/gnu/qp_port.h index 7ad61011..cd92c929 100644 --- a/ports/arm-cm/qv/gnu/qp_port.h +++ b/ports/arm-cm/qv/gnu/qp_port.h @@ -26,12 +26,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 -//! @version Last updated for: @ref qpc_8_0_0 -//! -//! @file -//! @brief QP/C port to ARM Cortex-M, cooperative QV kernel, GNU-ARM - #ifndef QP_PORT_H_ #define QP_PORT_H_ @@ -47,31 +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((uint32_t)(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_) ((uint_fast8_t)(32 - __builtin_clz((unsigned)(n_)))) - -#endif - // interrupt disabling policy, see NOTE2 and NOTE3 #define QF_INT_DISABLE() (QF_int_disable_()) #define QF_INT_ENABLE() (QF_int_enable_()) @@ -83,11 +55,27 @@ #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((uint32_t)(n_)) + // hand-optimized quick LOG2 in assembly uint_fast8_t QF_qlog2(uint32_t x); +#else // ARMv7-M or higher + // ARMv7-M or higher provide the CLZ instruction for fast LOG2 + #define QF_LOG2(n_) ((uint_fast8_t)(32 - __builtin_clz((unsigned)(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 @@ -104,20 +92,10 @@ void QF_onMemSys(void); 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 { \ @@ -127,6 +105,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. @@ -168,7 +157,7 @@ extern int32_t volatile QF_int_lock_nest_; // 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 @@ -177,15 +166,15 @@ extern int32_t volatile QF_int_lock_nest_; // 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/qv/gnu/qv_port.c b/ports/arm-cm/qv/gnu/qv_port.c index ff0e83df..60b7ed2f 100644 --- a/ports/arm-cm/qv/gnu/qv_port.c +++ b/ports/arm-cm/qv/gnu/qv_port.c @@ -26,12 +26,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 -//! @version Last updated for: @ref qpc_8_0_0 -//! -//! @file -//! @brief QV/C port to ARM Cortex-M, GNU-ARM - #define QP_IMPL 1U #include "qp_port.h" #include "qsafe.h" // QP Functional Safety (FuSa) Subsystem @@ -57,7 +51,6 @@ // For best performance, these functions are implemented in assembly, // but they can be implemented in C as well. - //int32_t volatile QF_int_lock_nest_; // not used extern char const QF_port_module_[]; char const QF_port_module_[] = "qv_port"; @@ -66,24 +59,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" @@ -98,28 +90,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" @@ -132,25 +125,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" @@ -166,29 +157,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" @@ -206,7 +195,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. @@ -215,18 +204,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.h b/ports/arm-cm/qv/iar/qp_port.h index 4f749ac8..efa8b501 100644 --- a/ports/arm-cm/qv/iar/qp_port.h +++ b/ports/arm-cm/qv/iar/qp_port.h @@ -26,12 +26,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 -//! @version Last updated for: @ref qpc_8_0_0 -//! -//! @file -//! @brief QP/C port to ARM Cortex-M, cooperative QV kernel, IAR-ARM - #ifndef QP_PORT_H_ #define QP_PORT_H_ @@ -48,31 +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((uint32_t)(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_) ((uint_fast8_t)(32U - __CLZ((unsigned long)(n_)))) - -#endif - // interrupt disabling policy, see NOTE2 and NOTE3 #define QF_INT_DISABLE() (QF_int_disable_()) #define QF_INT_ENABLE() (QF_int_enable_()) @@ -82,13 +54,29 @@ #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((uint32_t)(n_)) + // hand-optimized quick LOG2 in assembly uint_fast8_t QF_qlog2(uint32_t x); +#else // ARMv7-M or higher + // ARMv7-M or higher provide the CLZ instruction for fast LOG2 + #define QF_LOG2(n_) ((uint_fast8_t)(32U - __CLZ((unsigned long)(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,29 +93,30 @@ void QF_onMemSys(void); 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() ((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. @@ -169,7 +158,7 @@ extern int32_t volatile QF_int_lock_nest_; // 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 @@ -178,15 +167,15 @@ extern int32_t volatile QF_int_lock_nest_; // 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/qv/iar/qv_port.c b/ports/arm-cm/qv/iar/qv_port.c index 8ec7af61..129cc18a 100644 --- a/ports/arm-cm/qv/iar/qv_port.c +++ b/ports/arm-cm/qv/iar/qv_port.c @@ -26,12 +26,6 @@ // // //============================================================================ -//! @date Last updated on: 2024-09-30 -//! @version Last updated for: @ref qpc_8_0_0 -//! -//! @file -//! @brief QV/C port to ARM Cortex-M, IAR-ARM - #define QP_IMPL 1U #include "qp_port.h" #include "qsafe.h" // QP Functional Safety (FuSa) Subsystem @@ -70,24 +64,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" @@ -102,28 +95,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" @@ -136,25 +130,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" @@ -170,29 +162,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" @@ -210,7 +200,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. @@ -219,18 +209,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-cr/qk/config/qp_config.h b/ports/arm-cr/config/qp_config.h similarity index 83% rename from ports/arm-cr/qk/config/qp_config.h rename to ports/arm-cr/config/qp_config.h index b5299776..b7be8f6a 100644 --- a/ports/arm-cr/qk/config/qp_config.h +++ b/ports/arm-cr/config/qp_config.h @@ -1,5 +1,5 @@ //============================================================================ -// QP configuration file (QK on ARM Cortex-R) +// 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,16 +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 -// - -// 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) @@ -169,15 +159,44 @@ // 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 +// + +// 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. @@ -199,31 +218,6 @@ // -//.......................................................................... -// QK Preemptive 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_H_ diff --git a/ports/arm-cr/qk/gnu/qp_port.h b/ports/arm-cr/qk/gnu/qp_port.h index 7ed13cd4..6ce0735d 100644 --- a/ports/arm-cr/qk/gnu/qp_port.h +++ b/ports/arm-cr/qk/gnu/qp_port.h @@ -27,7 +27,7 @@ // // //============================================================================ -//! @date Last updated on: 2023-09-30 +//! @date Last updated on: 2024-11-22 //! @version Last updated for: @ref qpc_8_0_0 //! //! @file @@ -62,7 +62,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.h b/ports/arm-cr/qv/config/qp_config.h deleted file mode 100644 index 1f549be1..00000000 --- a/ports/arm-cr/qv/config/qp_config.h +++ /dev/null @@ -1,229 +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_H_ -#define QP_CONFIG_H_ - -//-------- <<< 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 -// - -// 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_H_ diff --git a/ports/arm-cr/qv/gnu/qp_port.h b/ports/arm-cr/qv/gnu/qp_port.h index 21bbd1e1..4d565efc 100644 --- a/ports/arm-cr/qv/gnu/qp_port.h +++ b/ports/arm-cr/qv/gnu/qp_port.h @@ -27,7 +27,7 @@ // // //============================================================================ -//! @date Last updated on: 2023-09-30 +//! @date Last updated on: 2024-11-22 //! @version Last updated for: @ref qpc_8_0_0 //! //! @file @@ -62,7 +62,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.h b/ports/config/qp_config.h index 9e503a9e..57af5365 100644 --- a/ports/config/qp_config.h +++ b/ports/config/qp_config.h @@ -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,16 +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 -// - -// 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) @@ -169,15 +159,44 @@ // 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 +// + +// 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/ports/posix/qp_port.h b/ports/posix/qp_port.h index 8b11cb47..f193d57d 100644 --- a/ports/posix/qp_port.h +++ b/ports/posix/qp_port.h @@ -27,8 +27,8 @@ // // //============================================================================ -//! @date Last updated on: 2023-09-30 -//! @version Last updated for: @ref qpc_8_0_0 +//! @date Last updated on: 2024-12-12 +//! @version Last updated for: @ref qpc_8_0_1 //! //! @file //! @brief QP/C port to to POSIX (multithreaded with P-threads) @@ -38,6 +38,7 @@ #include // Exact-width types. WG14/N843 C99 Standard #include // Boolean type. WG14/N843 C99 Standard +#include // POSIX-thread API #include "qp_config.h" // QP configuration from the application // no-return function specifier (C11 Standard) diff --git a/qpc.qm b/qpc.qm index 40a513f4..b80938e0 100644 --- a/qpc.qm +++ b/qpc.qm @@ -1677,10 +1677,8 @@ return r; - do { \ - Q_ASSERT(((QAsm *)(me_))->vptr); \ - (*((QAsm *)(me_))->vptr->init)((QAsm *)(me_), (par_), (qsId_)); \ -} while (false) + \ + (*((QAsm *)(me_))->vptr->init)((QAsm *)(me_), (par_), (qsId_)) @@ -1690,10 +1688,8 @@ return r; - do { \ - Q_ASSERT(((QAsm *)(me_))->vptr); \ - (*((QAsm *)(me_))->vptr->init)((QAsm *)(me_), (par_), 0); \ -} while (false) + \ + (*((QAsm *)(me_))->vptr->init)((QAsm *)(me_), (par_), 0U) @@ -3654,12 +3650,12 @@ QF_CRIT_EXIT(); //! @static @public @memberof QTimeEvt - 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 (QTimeEvt_timeEvtHead_[tickRate].next != (QTimeEvt *)0) { inactive = false; } @@ -3669,6 +3665,8 @@ else if ((QTimeEvt_timeEvtHead_[tickRate].act != (void *)0)) { else { inactive = true; } +QF_MEM_APP(); + return inactive; @@ -6172,9 +6170,9 @@ $declare1 ${QP-FuSa} #define QP_H_ //============================================================================ -#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 @@ -6527,7 +6525,6 @@ static inline void QF_psInit( #define QP_IMPL // this is QP implementation #include "qp_port.h" // QP port -#include "qp_pkg.h" // QP package-scope interface #include "qsafe.h" // QP Functional Safety (FuSa) Subsystem #ifdef Q_SPY // QS software tracing enabled? #include "qs_port.h" // QS port @@ -6585,7 +6582,6 @@ $define ${QEP::QHsm} #define QP_IMPL // this is QP implementation #include "qp_port.h" // QP port -#include "qp_pkg.h" // QP package-scope interface #include "qsafe.h" // QP Functional Safety (FuSa) Subsystem #ifdef Q_SPY // QS software tracing enabled? #include "qs_port.h" // QS port diff --git a/qpc.sha1 b/qpc_8.0.1.sha1 similarity index 66% rename from qpc.sha1 rename to qpc_8.0.1.sha1 index df959ca8..3044d24d 100644 --- a/qpc.sha1 +++ b/qpc_8.0.1.sha1 @@ -1,18 +1,21 @@ -7177cfc37bca450ea06ffc6afe31a61c0008304f *qpc.qm +e0aae515ebf157d8993bb03747fdc86cd87604f3 *qpc.qm e3c60b712a27e8f8c11e38711e785ffc4006cda5 *include/qequeue.h a0d30600da64ec7aaadc6b9bd268c217930c3e60 *include/qk.h 84c8c1036c38f0f1646cc60e4813a7c8fb89f2d2 *include/qmpool.h -080b5860668af8dc54cd429268c24f5629fbe074 *include/qp.h +7ecec322b0b31b4175596df3a7968424b21f983e *include/qp.h 7a909dd01c0aa3fd7d74b4a4c88b930eeb0b815e *include/qp_pkg.h 0a3323af546e1b2320e6745e8e0effa837abdc53 *include/qpc.h +6796ebe4b41225fa374d751704e7edd2f95e0484 *include/qs.h 5a0c927370d332fc170e84650d980173da2102ae *include/qs_dummy.h +d57d1974f64db7e3bf8a9f4468ee84a42ccd4952 *include/qs_pkg.h 7458d62031562c2517577b258d47249b7b900dd7 *include/qsafe.h 2e0a56edcf460fcd82f6d7277e5fc0876325efeb *include/qstamp.h d0199c9094039e672d85e9198ccff0d4ed9128cc *include/qv.h +fdfc7f528989ff3934af977ef9a1ee9fc30cd889 *include/qxk.h 5886c3a0831996cfbf7141255efb4e9f5b4d8254 *include/README.md 7f54a0933a9dc2fcaca475919fa0067667ed99ed *src/qf/CMakeLists.txt -d6aa00cb34e553e951df726fc5db39a6d16bc891 *src/qf/qep_hsm.c -67d6f8351a0e9a1df311be681083c73ecf63ea61 *src/qf/qep_msm.c +6ff32793932a96e1240b2c9dbbc9516faf206fa6 *src/qf/qep_hsm.c +e5d93d4867336209c0d8e74cc4a9add1190b821a *src/qf/qep_msm.c 733bc8bf8e08014c20d8354efb98729857edb4cd *src/qf/qf_act.c 90e27f32bc8862946bfe4c6c376bf03327de25f7 *src/qf/qf_actq.c 8b58d43c5b8fe3b1b846392d1f7d99d5720428d9 *src/qf/qf_defer.c @@ -22,41 +25,58 @@ d263e3b91f9e5c61d6a458b5c6023ac68eb07a13 *src/qf/qf_mem.c 2ed707166ca625a684c93147aec772dd568e5d9f *src/qf/qf_qact.c e6e7dd46ed4ab7fb3ecd781ca29ea141d13f49d9 *src/qf/qf_qeq.c f975ffcfadfed6856a41587b8275e0ea3bbe63a3 *src/qf/qf_qmact.c -b888e05e67e1259ee96d29b244aa8a2a68d0f904 *src/qf/qf_time.c +e43dbda05f6fd6cbb8673d8ae5d1f8b183570f29 *src/qf/qf_time.c 878a737efe234f40dc8c9374acc351e510b4da1e *src/qk/CMakeLists.txt 5f092f2dc82962633e8ff32f736baaf04ef4c5da *src/qk/qk.c 68c99a2991d25df7486e57edadaa955b2bda396d *src/qs/CMakeLists.txt +8cb434d345ef98a0915eadd97f7959987d66ff89 *src/qs/qs.c +e8ee51e5776c38f9dfdc06f87ab2b1f00bb45fd4 *src/qs/qs_64bit.c +14e1f08b94f65cc1d043051f829280e7f3ae057a *src/qs/qs_fp.c +4e3d64f109f5f8de67799a190f505d1fa29d622a *src/qs/qs_rx.c f055d938dd53c9baf7f5e04ad1bc4f4ec40044e9 *src/qs/qstamp.c +afe015fd804a563aedd4080d389ef143a1a9ce40 *src/qs/qutest.c b1d2def9b8f6cde464170af7682ab0f01f4f40f6 *src/qv/CMakeLists.txt f77a3c93938c5ff9a37214bdfe1c7c255f9eed6e *src/qv/qv.c -5a77be9e96ab536754188a32a6b6f99b8db9f2ff *ports/arm-cm/qk/armclang/qk_port.c -dc00b85b62f9d3dce9c4f0073b9e0c1b0d96d652 *ports/arm-cm/qk/armclang/qp_port.h +de32deac900990db561238c22e6961e2c3ca4eac *src/qxk/qxk.c +fff73b289cb59e10ae491907e4bb48bbffb90946 *src/qxk/qxk_mutex.c +822dafde2328e17531a8c4df752e8e0b29a6f2c8 *src/qxk/qxk_sema.c +49b36eef14ecffad5583efb1c7b2208cc0fc055d *src/qxk/qxk_xthr.c +09c4447840e6b67c4f6adef68e13013abb87a69e *ports/arm-cm/qk/armclang/qk_port.c +4e8a047094569163fc6826ee33435476b55b8b06 *ports/arm-cm/qk/armclang/qp_port.h e48b7af7dff7cfe6742abbb4adb0d1b01b2020cb *ports/arm-cm/qk/armclang/qs_port.h -e27abe98e61b175634d3ef10f0b137a2c183b235 *ports/arm-cm/qk/config/qp_config.h -404046a50f5c970986b23f9ded48b3aed37738e5 *ports/arm-cm/qk/gnu/qk_port.c -1a1c683b243e48651427751f54752ce6f6ee60b0 *ports/arm-cm/qk/gnu/qp_port.h +061bb4b5f82fcee28c34441ed22287bcf7b294ab *ports/arm-cm/qk/gnu/qk_port.c +df8f0dfeb5b459c0a0da34584ac6f67c3ddcee99 *ports/arm-cm/qk/gnu/qp_port.h e48b7af7dff7cfe6742abbb4adb0d1b01b2020cb *ports/arm-cm/qk/gnu/qs_port.h -ba447b9e250b96a4cc5caf901a8643df40737966 *ports/arm-cm/qk/iar/qk_port.c -2e4ad9ed30bdec6728a1e1b4cfe52ca96668fb70 *ports/arm-cm/qk/iar/qp_port.h +b3bd86c8a739243aad85abb94e992ed83d3fe2cb *ports/arm-cm/qk/iar/qk_port.c +9b0833336729666744ac35ca42b85d57756ba8fa *ports/arm-cm/qk/iar/qp_port.h e48b7af7dff7cfe6742abbb4adb0d1b01b2020cb *ports/arm-cm/qk/iar/qs_port.h -06909bcb51e7c1dd28e666a12a885500db74c052 *ports/arm-cm/qv/armclang/qp_port.h +0a1f794005df1b7c256f52781928f86cb5dd96f9 *ports/arm-cm/qv/armclang/qp_port.h e48b7af7dff7cfe6742abbb4adb0d1b01b2020cb *ports/arm-cm/qv/armclang/qs_port.h -1caea977419fbbf8eff95cb4a7a695b168b14bda *ports/arm-cm/qv/armclang/qv_port.c -651dedf7266e0da44ce45ddd3cced3782eccda17 *ports/arm-cm/qv/config/qp_config.h -0427fc5ce0d727350d39b1bc9dcb081172865be4 *ports/arm-cm/qv/gnu/qp_port.h +050f16532d529cac3c20e990f1df40246b04c9ac *ports/arm-cm/qv/armclang/qv_port.c +0a1f794005df1b7c256f52781928f86cb5dd96f9 *ports/arm-cm/qv/gnu/qp_port.h e48b7af7dff7cfe6742abbb4adb0d1b01b2020cb *ports/arm-cm/qv/gnu/qs_port.h -6dad2e9e8a929e4477f6b071cc05d70638fbb356 *ports/arm-cm/qv/gnu/qv_port.c -c63708c0d86bfefb58bf60917fd428dbf29a0a31 *ports/arm-cm/qv/iar/qp_port.h +c8289ae7c23524d13f4680a839f9088aa9264200 *ports/arm-cm/qv/gnu/qv_port.c +3448a1cff7b1f10239a80e3191953ac018416bfd *ports/arm-cm/qv/iar/qp_port.h e48b7af7dff7cfe6742abbb4adb0d1b01b2020cb *ports/arm-cm/qv/iar/qs_port.h -9386d798e1989ff6789f54f5ae33741aad4b1b07 *ports/arm-cm/qv/iar/qv_port.c -623d43a6e15634e9c61434625486cd24aaaa949b *ports/arm-cr/qk/config/qp_config.h -38e441bb971501ba5118cbd5782b394eee80e660 *ports/arm-cr/qk/gnu/qp_port.h +a5ffa52d6c2249bd4a3aaca9f8e4d55553aad374 *ports/arm-cm/qv/iar/qv_port.c +030f0e57e8565902d9feaec653b28980dfbb25e2 *ports/arm-cm/qxk/armclang/qp_port.h +e48b7af7dff7cfe6742abbb4adb0d1b01b2020cb *ports/arm-cm/qxk/armclang/qs_port.h +0134e96053a73cf2deab3f8aee2a253464da473d *ports/arm-cm/qxk/armclang/qxk_port.c +7f8806496c7aaa7ee212f00be7a80170d1cfe1c5 *ports/arm-cm/qxk/gnu/qp_port.h +e48b7af7dff7cfe6742abbb4adb0d1b01b2020cb *ports/arm-cm/qxk/gnu/qs_port.h +ddec778d8a73f663a5d959dec0afb2ced792e0ef *ports/arm-cm/qxk/gnu/qxk_port.c +02eee6cc5894c554358c573d7d9e159bb3b3b3a2 *ports/arm-cm/qxk/iar/qp_port.h +e48b7af7dff7cfe6742abbb4adb0d1b01b2020cb *ports/arm-cm/qxk/iar/qs_port.h +624c3bb9e77359cc1fd8e78b6505bd1246a09f7a *ports/arm-cm/qxk/iar/qxk_port.c +663b8e89a0ef61bbdd305984e14f971f889b3592 *ports/arm-cm/qutest/qp_port.h +e48b7af7dff7cfe6742abbb4adb0d1b01b2020cb *ports/arm-cm/qutest/qs_port.h +a53c0064a8650a9b7217259817a60cd67688606a *ports/arm-cr/qk/gnu/qp_port.h e48b7af7dff7cfe6742abbb4adb0d1b01b2020cb *ports/arm-cr/qk/gnu/qs_port.h 88d3ed754f05c43609ecf52767c270fa438ecd03 *ports/arm-cr/qk/iar/qp_port.h e48b7af7dff7cfe6742abbb4adb0d1b01b2020cb *ports/arm-cr/qk/iar/qs_port.h e03d1c780c764e2a323b8423ae5045e226ee98c6 *ports/arm-cr/qk/ti/qp_port.h e48b7af7dff7cfe6742abbb4adb0d1b01b2020cb *ports/arm-cr/qk/ti/qs_port.h -84b6adb5703d24e41f5c19982fe797b9a79b38a8 *ports/arm-cr/qv/gnu/qp_port.h +a5c1f6cbb41d1884a6bfdaf4ccc1c7facb79c8eb *ports/arm-cr/qv/gnu/qp_port.h e48b7af7dff7cfe6742abbb4adb0d1b01b2020cb *ports/arm-cr/qv/gnu/qs_port.h da079ffa59b518ead25ed8aed82adc1535fc0280 *ports/arm-cr/qv/iar/qp_port.h e48b7af7dff7cfe6742abbb4adb0d1b01b2020cb *ports/arm-cr/qv/iar/qs_port.h @@ -68,7 +88,7 @@ a99dfb36c107e6c1b2fcc345792130bbc1ebcc4f *ports/msp430/qk/qs_port.h a99dfb36c107e6c1b2fcc345792130bbc1ebcc4f *ports/msp430/qv/qs_port.h 1459908255dbdd581cd38bd5ea33a121fce496b7 *ports/msp430/qutest/qp_port.h a99dfb36c107e6c1b2fcc345792130bbc1ebcc4f *ports/msp430/qutest/qs_port.h -77bb26f94e1e9ce0ba617f5a6cc2b921c4b283c7 *ports/config/qp_config.h +ecc7c04f015684c71bbaca3e351b8f7cbcdcc550 *ports/config/qp_config.h 2ee7f5594f6121705bbc57145175b5c5867e0070 *ports/embos/CMakeLists.txt 7cfd0e233fc7ee4c73cccaa58f769f3643325785 *ports/embos/qf_port.c a378ac45d230fc61b4462b3cc17a05d018271ea7 *ports/embos/qp_port.h @@ -91,7 +111,7 @@ cdb7c42a17fb3c5f282a55e08f99678e1cd56c0e *ports/qep-only/qp_port.h 5189dfad3fea0ccb2218958dd3657f4403674b5e *ports/qep-only/safe_std.h 5d7914dfaf44a9c2552afdd5d8de4cfc3ebbc22a *ports/posix/CMakeLists.txt 6b9d862537f4823ca83c81d2e8892da9711a69cd *ports/posix/qf_port.c -c99d7d3ca180a3f7903fe6948d5cffaf7e8f1996 *ports/posix/qp_port.h +78563f44b3d4b7835a75ef9dd3eea00e38f61946 *ports/posix/qp_port.h 51d89a3fa8c7a6c5858f6354ea8cc350e42a9d30 *ports/posix/qs_port.c d05889780d358bb1fe02ffad1a9414332f5eb300 *ports/posix/qs_port.h 6e33b2e5092d117f58c47b632c59420f382ac39f *ports/posix/README.md @@ -103,6 +123,11 @@ b73738f7297d6c023012d98c59c901a1e8951f02 *ports/posix-qv/qp_port.h d05889780d358bb1fe02ffad1a9414332f5eb300 *ports/posix-qv/qs_port.h ab829eb3deed2bc84b3581610f1664777afd3841 *ports/posix-qv/README.md 5189dfad3fea0ccb2218958dd3657f4403674b5e *ports/posix-qv/safe_std.h +1ecb2095e8de486c8111a420b5511a4ea0cb097c *ports/posix-qutest/CMakeLists.txt +d55172d4bb6959349285a06ca6485f1f1a1b756e *ports/posix-qutest/qp_port.h +d05889780d358bb1fe02ffad1a9414332f5eb300 *ports/posix-qutest/qs_port.h +243941959b1dbf5dfbbe57941104ae202eec57fc *ports/posix-qutest/qutest_port.c +5189dfad3fea0ccb2218958dd3657f4403674b5e *ports/posix-qutest/safe_std.h cfea17ea9ab718e9e4f506e90c4b2fc8c1fea858 *ports/win32/CMakeLists.txt a99784fa31b0466af740186bbe96f8d78fc7c17a *ports/win32/qf_port.c d0b7e944e6df828e040ec146f639e42be2c354d5 *ports/win32/qp_port.h @@ -121,6 +146,11 @@ b1a67eb489d35d71cf6fb40fc8f087906839f1a7 *ports/win32-qv/qs_port.h be15234e51b8fe3c295ff644e84fbc1cfca89257 *ports/win32-qv/qwin_gui.h b57cec85e2fe5c261270f68acc3ae440802a62bd *ports/win32-qv/README.md 5189dfad3fea0ccb2218958dd3657f4403674b5e *ports/win32-qv/safe_std.h +a04f13d2d9f24ef71d95f997d87f8a3ba9862e45 *ports/win32-qutest/CMakeLists.txt +50be2b5d49345d908290a4660b1bbc5eaeb6b4d6 *ports/win32-qutest/qp_port.h +b1a67eb489d35d71cf6fb40fc8f087906839f1a7 *ports/win32-qutest/qs_port.h +1d850be2190dd03f528405266ba85f81e9ecff53 *ports/win32-qutest/qutest_port.c +5189dfad3fea0ccb2218958dd3657f4403674b5e *ports/win32-qutest/safe_std.h 848a30efa3274ff30fb72059f926fe7963ab2321 *zephyr/CMakeLists.txt 10764710e545dd4d2ce0ddf032711df7f9191937 *zephyr/Kconfig 2eb2a922e18b4760a68151ebee1b6282d20b4692 *zephyr/module.yml diff --git a/qpc_sha1.bat b/qpc_sha1.bat index 2de6cc1a..8d5bf659 100644 --- a/qpc_sha1.bat +++ b/qpc_sha1.bat @@ -1,18 +1,20 @@ @setlocal +set VERSION=8.0.1 + :: usage @echo Usage: qpc_sha1 [gen] @echo examples: -@echo qpc_sha1 : check the sha1 sums in the file qpcp.sha1 -@echo qpc_sha1 gen : generate the sha1 file qpc.sha1 +@echo qpc_sha1 : check the sha1 sums in the file qpc_%VERSION%.sha1 +@echo qpc_sha1 gen : generate the sha1 file qpc_%VERSION%.sha1 @echo. @if NOT "%1"=="gen" ( -sha1sum --check --warn qpc.sha1 +sha1sum --check --warn qpc_%VERSION%.sha1 goto end ) -@echo generating qpc.sha1... +@echo generating qpc_%VERSION%.sha1... @sha1sum qpc.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/* ^ - > qpc.sha1 + > qpc_%VERSION%.sha1 @echo done :end diff --git a/src/qf/qep_hsm.c b/src/qf/qep_hsm.c index 104c8492..69234de5 100644 --- a/src/qf/qep_hsm.c +++ b/src/qf/qep_hsm.c @@ -34,7 +34,6 @@ //$endhead${src::qf::qep_hsm.c} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #define QP_IMPL // this is QP implementation #include "qp_port.h" // QP port -#include "qp_pkg.h" // QP package-scope interface #include "qsafe.h" // QP Functional Safety (FuSa) Subsystem #ifdef Q_SPY // QS software tracing enabled? #include "qs_port.h" // QS port diff --git a/src/qf/qep_msm.c b/src/qf/qep_msm.c index f911fd3a..8c274132 100644 --- a/src/qf/qep_msm.c +++ b/src/qf/qep_msm.c @@ -34,7 +34,6 @@ //$endhead${src::qf::qep_msm.c} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #define QP_IMPL // this is QP implementation #include "qp_port.h" // QP port -#include "qp_pkg.h" // QP package-scope interface #include "qsafe.h" // QP Functional Safety (FuSa) Subsystem #ifdef Q_SPY // QS software tracing enabled? #include "qs_port.h" // QS port diff --git a/src/qf/qf_time.c b/src/qf/qf_time.c index 5477e254..4138c2a3 100644 --- a/src/qf/qf_time.c +++ b/src/qf/qf_time.c @@ -546,12 +546,12 @@ void QTimeEvt_tick_( //${QF::QTimeEvt::noActive} .................................................. //! @static @public @memberof QTimeEvt bool QTimeEvt_noActive(uint_fast8_t const tickRate) { - 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 (QTimeEvt_timeEvtHead_[tickRate].next != (QTimeEvt *)0) { inactive = false; } @@ -561,6 +561,8 @@ bool QTimeEvt_noActive(uint_fast8_t const tickRate) { else { inactive = true; } + QF_MEM_APP(); + return inactive; } //$enddef${QF::QTimeEvt} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^