changed ports to ARM-CM, BASEPRI critical section
updated qp_config.hpp files
updated examples
fixed arm-cr ports, GNU compiler, ARM mode, QF_INT_ENABLE_ALL() macro
This commit is contained in:
MMS 2024-11-22 09:49:39 -05:00
parent c1a9c485b7
commit 2b1661fdce
29 changed files with 772 additions and 1311 deletions

View File

@ -76,7 +76,7 @@ This file is situated in the root directory of qpcpp. It performs a pre-initiali
+ `arm-cm`, `arm-cr` - Arm CortexM or CortexR micro controllers. Tested with GNU cross compiler environments.
+ `freertos`, `esp-idf`, `emb-os`, `threadx`, `uc-os2` - real time OS
+ `msp430`, `pic32` - TI MSP430 or PIC32 micro controllers
+ `riscv`- Risc V µC
+ `riscv`- Risc V micro controllers
+ `qep-only`, `qube` - test environments
+ `win32`, `posix` - host environments MS Windows, Linux (Posix compatible systems)
* `QPCPP-CFG-GUI` - BOOL: set this Boolean variable to ON/TRUE, if GUI support (win32) shall be compiled in. Default: OFF

@ -1 +1 @@
Subproject commit 4325bfa22d9b9335c3baf4bd7acc95f6c1a8fec7
Subproject commit 01aad80e4c6f69089ecf7ddc328cad2870505a6e

View File

@ -36,9 +36,9 @@
#define QP_HPP_
//============================================================================
#define QP_VERSION_STR "8.0.0"
#define QP_VERSION 800U
#define QP_RELEASE 0x7055936FU
#define QP_VERSION_STR "8.0.1"
#define QP_VERSION 801U
#define QP_RELEASE 0x703931CEU
//============================================================================
//! @cond INTERNAL

View File

@ -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 @@
// <i> * Hard-limits for all loops
// <i> * Memory Isolation by means of Memory Protection Unit (MPU)
// <c3>Disable QP FuSa in development
// <c3>Disable QP FuSa in development (NOT recommended)
// <i>Disable assertions and other self monitoring features
// <i>in development build configurations (NDEBUG undefined).
// <i>VIOLATES functional safety standards. NOT recommended !!!
// <i>NOTE: Disabling safety *violates* functional safety standards.
//#ifndef NDEBUG
//#define Q_UNSAFE
//#endif
// </c>
// <c3>Disable QP FuSa in production release
// <i>Disable assertions and other self monitoring features
// <c3>Disable QP FuSa in production release (NOT recommended)
// <i>Disable assertions and other safety features
// <i>in the release build configurations (NDEBUG defined).
// <i>VIOLATES functional safety standards. NOT recommended !!!
// <i>NOTE: Disabling safety *violates* functional safety standards.
//#ifdef NDEBUG
//#define Q_UNSAFE
//#endif
@ -80,7 +80,7 @@
// </h>
//..........................................................................
// <h>QEP Event Processor
// <h>QEP Event Processor (Events)
// <i>Events and state machines.
// <o>Event signal size (Q_SIGNAL_SIZE)
@ -94,7 +94,7 @@
// </h>
//..........................................................................
// <h>QF Framework
// <h>QF Framework (Active Objects)
// <i>Active Object framework
// <o>Maximum # Active Objects (QF_MAX_ACTIVE) <1-64>
@ -120,21 +120,6 @@
// <i>Default: 1
#define QF_MAX_TICK_RATE 1U
// <c1>Event parameter initialization (QEVT_PAR_INIT)
// <i>Resource Acquisition Is Initialization (RAII) for dynamic events
//#define QEVT_PAR_INIT
// </c>
// <c1>Provide destructors for QP classes
// <i>Destructors for classes
//#define Q_XTOR
// </c>
// <c1>Active Object stop API (QACTIVE_CAN_STOP)
// <i>Enable Active Object stop API (Not recommended)
//#define QACTIVE_CAN_STOP
// </c>
// <o>Event size (QF_EVENT_SIZ_SIZE)
// <1U=>1
// <2U=>2 (default)
@ -174,15 +159,75 @@
// <i>Default: 2 (64K bytes maximum block size)
#define QF_MPOOL_SIZ_SIZE 2U
// <c2>Enable event parameter initialization (QEVT_PAR_INIT)
// <i>Initialize parameters of dynamic events at allocation
// <i>(Resource Acquisition Is Initialization (RAII) for dynamic events)
//#define QEVT_PAR_INIT
// </c>
// <c1>Provide destructors for QP classes
// <i>Presence of destructors pulls in the C++ delete() opeator
// <i>NOTE: Not recommended
//#define Q_XTOR
// </c>
// <c1>Enable active object stop API (QACTIVE_CAN_STOP)
// <i>NOTE: Not recommended
//#define QACTIVE_CAN_STOP
// </c>
// <c1>Enable context switch callback *without* QS (QF_ON_CONTEXT_SW)
// <i>Context switch callback QF_onContextSw() when Q_SPY is undefined.
//#ifndef Q_SPY
//#define QF_ON_CONTEXT_SW
//#endif
// </c>
// <c1>Enable context switch callback *with* QS (QF_ON_CONTEXT_SW)
// <i>Context switch callback QF_onContextSw() when Q_SPY is defined.
//#ifdef Q_SPY
//#define QF_ON_CONTEXT_SW
//#endif
// </c>
// <c2>Enable memory isolation (QF_MEM_ISOLATE)
// <i>Memory isolation (requires MPU)
// <i>NOTE: implies QF_ON_CONTEXT_SW.
//#define QF_MEM_ISOLATE
// </c>
// </h>
//..........................................................................
// <h>QS Software Tracing
// <h>QV/QK/QXK built-in kernels (ARM Cortex-M)
// <c2>Kernel uses critical section based on BASEPRI (QF_USE_BASEPRI)
// <i>If not selected, critical section will be based on PRIMASK
// <i>NOTE: The BASEPRI threshold can be adjusted in the "Text Editor" mode.
//#define QF_USE_BASEPRI 0x3F
// </c>
// <c2>QK Kernel uses IRQ for return-from-preemption
// <i>NOTE: Use "editor mode" to edit QK_USE_IRQ_NUM
// <i>NOTE: Use "editor mode" to edit QK_USE_IRQ_HANDLER
//#define QK_USE_IRQ_NUM NNN
//#define QK_USE_IRQ_HANDLER XXX_IRQHandler
// </c>
// <c2>QXK Kernel uses IRQ for return-from-preemption
// <i>NOTE: Use "editor mode" to edit QXK_USE_IRQ_NUM
// <i>NOTE: Use "editor mode" to edit QXK_USE_IRQ_HANDLER
//#define QXK_USE_IRQ_NUM NNN
//#define QXK_USE_IRQ_HANDLER XXX_IRQHandler
// </c>
// </h>
//..........................................................................
// <h>QS Software Tracing (Q_SPY)
// <i>Target-resident component of QP/Spy software tracing system
// <i>(tracing instrumentation and command-input).
// <n>NOTE: Requires command-line macro: Q_SPY
// <i>The QS software tracing instrumentation is activated only when
// <i>NOTE: The QS software tracing instrumentation is activated only when
// <i>the macro Q_SPY is defined on the command-line to the compiler.
// <i>Typically, Q_SPY is defined only in the "spy" build configuration.
@ -204,47 +249,6 @@
// </h>
//..........................................................................
// <h>QK Preemptive Non-Blocking Kernel
// <i>Preemptive non-blocking/blocking RTOS kernel.
// <h>Context switch callback (QF_ON_CONTEXT_SW)
// <c2>Context switch callback WITHOUT QS
// <i>Enable context switch callback QF_onContextSw()
// <i>When Q_SPY is undefined.
//#ifndef Q_SPY
//#define QF_ON_CONTEXT_SW
//#endif
// </c>
// <c2>Context switch callback WITH QS
// <i>Enable context switch callback QF_onContextSw()
// <i>When Q_SPY is defined.
//#ifdef Q_SPY
//#define QF_ON_CONTEXT_SW
//#endif
// </c>
// </h>
// <c2>MPU memory isolation (QF_MEM_ISOLATE)
// <i>Enable memory isolation (requires MPU)
// <i>NOTE: implies QF_ON_CONTEXT_SW.
//#define QF_MEM_ISOLATE
// </c>
// <c4>Use IRQ handler for QK return-from-preemption
// <i>Enable this option only if the NMI handler is used in the project.
// <i>If enabled, provide the otherwise unused IRQ number (QK_USE_IRQ_NUM)
// <i>and the corresponding IRQ handler name (QK_USE_IRQ_HANDLER)
// <i>in the "Text Editor" mode.
//#define QK_USE_IRQ_NUM <adjust to your MCU>
//#define QK_USE_IRQ_HANDLER <adjust to your MCU>
// </c>
// </h>
//------------- <<< end of configuration section >>> -----------------------
#endif // QP_CONFIG_HPP_

View File

@ -26,12 +26,6 @@
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-09-30
//! @version Last updated for: @ref qpc_8_0_0
//!
//! @file
//! @brief QK/C++ port to ARM Cortex-M, ARM-CLANG
#define QP_IMPL 1U
#include "qp_port.hpp"
#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
@ -70,7 +64,6 @@ void NMI_Handler(void);
// For best performance, these functions are implemented in assembly,
// but they can be implemented in C as well.
//std::int32_t volatile QF_int_lock_nest_; // not used
extern char const QF_port_module_[];
char const QF_port_module_[] = "qk_port";
@ -79,24 +72,23 @@ char const QF_port_module_[] = "qk_port";
// Unconditionally disable interrupts.
// NOTE: this function must NOT use the stack.
//
// description:
// On ARMv6-M, interrupts are disabled with the PRIMASK register.
// On ARMv7-M and higher, interrupts are disabled *selectively* with the
// BASEPRI register.
// Description:
// When QF_USE_BASEPRI is defined, interrupts are disabled with BASEPRI.
// Otherwise interrupts are disabled with the PRIMASK register.
// Additionally, the function also asserts that the interrupts are
// NOT disabled upon the entry to the function, which means that
// this interrupt management policy CANNOT nest.
__attribute__ ((naked, weak))
void QF_int_disable_(void) {
__asm volatile (
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for interrupt disabling?
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
" MOVS r1,#" STRINGIFY(QF_USE_BASEPRI) "\n"
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
#else //--------- use PRIMASK for disabling interrupts
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
" CPSID i \n" // set PRIMASK
#else //--------- ARMv7-M or higher
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
" MOVS r1,#" STRINGIFY(QF_BASEPRI) "\n"
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
#endif //--------- ARMv7-M or higher
#endif //--------- use PRIMASK for disabling interrupts
" CMP r0,#0 \n" // assert(PRIMASK/BASEPRI == 0)
" BNE QF_int_disable_error\n"
" BX lr \n"
@ -111,28 +103,29 @@ __asm volatile (
// Unconditionally enable interrupts.
// NOTE: this function must NOT use the stack.
//
// description:
// On ARMv6-M, interrupts are enabled with the PRIMASK register.
// On ARMv7-M and higher, interrupts are enabled with the BASEPRI register.
// Description:
// When QF_USE_BASEPRI is defined, interrupts are enabled with BASEPRI.
// Otherwise interrupts are enabled with the PRIMASK register.
// Additionally, the function also asserts that the interrupts ARE
// disabled upon the entry to the function, which means that
// this interrupt management policy CANNOT nest.
__attribute__ ((naked, weak))
void QF_int_enable_(void) {
__asm volatile (
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
#else //--------- ARMv7-M or higher
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for enabling interrupts?
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
#endif //--------- ARMv7-M or higher
#else //--------- use PRIMASK for enabling interrupts
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
#endif //--------- use PRIMASK for enabling interrupts
" CMP r0,#0 \n" // assert(PRIMASK/BASEPRI != 0)
" BEQ QF_int_enable_error\n"
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
" CPSIE i \n" // clear PRIMASK
#else //--------- ARMv7-M or higher
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for enabling interrupts?
" MOVS r1,#0 \n"
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
#endif //--------- ARMv7-M or higher
#else //--------- use PRIMASK for enabling interrupts
" CPSIE i \n" // clear PRIMASK
#endif //--------- use PRIMASK for enabling interrupts
" BX lr \n"
"QF_int_enable_error: \n"
" LDR r0,=QF_port_module_ \n"
@ -145,25 +138,23 @@ __asm volatile (
// Enter QF critical section.
// NOTE: this function must NOT use the stack.
//
// description:
// On ARMv6-M, critical section is entered by disabling interrupts
// with the PRIMASK register.
// On ARMv7-M and higher, critical section is entered by disabling
// interrupts *selectively* with the BASEPRI register.
// Description:
// When QF_USE_BASEPRI is defined, critical section uses BASEPRI.
// Otherwise, critical section uses the PRIMASK register.
// Additionally, the function also asserts that the interrupts are
// NOT disabled upon the entry to the function, which means that
// this critical section CANNOT nest.
__attribute__ ((naked, weak))
void QF_crit_entry_(void) {
__asm volatile (
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
" MOVS r1,#" STRINGIFY(QF_USE_BASEPRI) "\n"
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
#else //--------- use PRIMASK for critical section
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
" CPSID i \n" // set PRIMASK
#else //--------- ARMv7-M or higher
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
" MOVS r1,#" STRINGIFY(QF_BASEPRI) "\n"
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
#endif //--------- ARMv7-M or higher
#endif //--------- use PRIMASK for critical section
" CMP r0,#0 \n" // assert(PRIMASK/BASEPRI == 0)
" BNE QF_crit_entry_error\n"
" BX lr \n"
@ -179,29 +170,27 @@ __asm volatile (
// NOTE: this function must NOT use the stack.
//
// description:
// On ARMv6-M, critical section is exited by enabling interrupts
// with the PRIMASK register.
// On ARMv7-M and higher, critical section is exited by enabling
// interrupts with the BASEPRI register.
// When QF_USE_BASEPRI is defined, critical section uses BASEPRI.
// Otherwise, critical section uses the PRIMASK register.
// Additionally, the function also asserts that the interrupts ARE
// disabled upon the entry to the function, which means that
// this critical section CANNOT nest.
__attribute__ ((naked, weak))
void QF_crit_exit_(void) {
__asm volatile (
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
#else //--------- ARMv7-M or higher
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
#endif //--------- ARMv7-M or higher
#else //--------- use PRIMASK for critical section
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
#endif //--------- use PRIMASK for critical section
" CMP r0,#0 \n" // assert(PRIMASK/BASEPRI != 0)
" BEQ QF_crit_exit_error\n"
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
" CPSIE i \n" // clear PRIMASK
#else //--------- ARMv7-M or higher
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
" MOVS r1,#0 \n"
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
#endif //--------- ARMv7-M or higher
#else //--------- use PRIMASK
" CPSIE i \n" // clear PRIMASK
#endif //--------- use PRIMASK
" BX lr \n"
"QF_crit_exit_error: \n"
" LDR r0,=QF_port_module_ \n"
@ -219,7 +208,7 @@ __asm volatile (
// BASEPRI register. However, this method cannot disable interrupt
// priority zero, which is the default for all interrupts out of reset.
// The following code changes the SysTick priority and all IRQ priorities
// to the safe value QF_BASEPRI, which the QF critical section can disable.
// to the safe value QF_USE_BASEPRI, which the QF critical section can disable.
// This avoids breaching of the QF critical sections in case the
// application programmer forgets to explicitly set priorities of all
// "kernel aware" interrupts.
@ -228,18 +217,18 @@ __asm volatile (
// by the application-level code.
void QK_init(void) {
#if (__ARM_ARCH != 6) //--------- if ARMv7-M and higher...
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
// SCB_SYSPRI[2]: SysTick
SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_BASEPRI << 24U));
SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_USE_BASEPRI << 24U));
// set all 240 possible IRQ priories to QF_BASEPRI...
// set all 240 possible IRQ priories to QF_USE_BASEPRI...
for (uint_fast8_t n = 0U; n < (240U/sizeof(uint32_t)); ++n) {
NVIC_IP[n] = (QF_BASEPRI << 24U) | (QF_BASEPRI << 16U)
| (QF_BASEPRI << 8U) | QF_BASEPRI;
NVIC_IP[n] = (QF_USE_BASEPRI << 24U) | (QF_USE_BASEPRI << 16U)
| (QF_USE_BASEPRI << 8U) | QF_USE_BASEPRI;
}
#endif //--------- ARMv7-M or higher
#endif //--------- use BASEPRI for critical section
// SCB_SYSPRI[2]: PendSV set to priority 0xFF (lowest)
SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (0xFFU << 16U));
@ -374,9 +363,12 @@ void QK_thread_ret(void) {
#endif //--------- use the NMI
#else //--------- ARMv7-M and higher...
#ifdef QF_USE_BASEPRI //--------- QF_USE_BASEPRI
" CPSID i \n" // disable interrupts with PRIMASK
" LDR r0,=QF_int_enable_ \n"
" BLX r0 \n" // enable interrupts with BASEPRI
#endif //--------- QF_USE_BASEPRI
// NOTE: interrupts remain disabled with PRIMASK
#ifdef __ARM_FP //--------- if VFP available...
@ -392,7 +384,12 @@ void QK_thread_ret(void) {
" MOVS r1,#1 \n"
" LSLS r1,r1,#" STRINGIFY(QK_USE_IRQ_NUM & 0x1F) "\n" // r1 := IRQ bit
" STR r1,[r0] \n" // pend the IRQ
#ifdef QF_USE_BASEPRI //--------- QF_USE_BASEPRI
" CPSIE i \n" // enable interrupts with PRIMASK
#else //--------- interrupt disabling with PRIMASK
" LDR r0,=QF_int_enable_ \n"
" BLX r0 \n" // enable interrupts with BASEPRI
#endif //--------- interrupt disabling with PRIMASK
// This code stops here and continues in the IRQ handler
#else //--------- use the NMI (default)
@ -442,15 +439,16 @@ void NMI_Handler(void) {
__asm volatile (
" ADD sp,sp,#(8*4) \n" // remove one 8-register exception frame
#if (__ARM_ARCH == 6) //--------- if ARMv6-M...
#ifdef QF_USE_BASEPRI //--------- QF_USE_BASEPRI
// NOTE: QF_int_enable_() already called
" CPSIE i \n" // enable interrupts with PRIMASK
#else //--------- interrupt disabling with PRIMASK
" LDR r0,=QF_int_enable_ \n"
" BLX r0 \n" // enable interrupts with PRIMASK
// NOTE: calling QF_int_enable_() corrupted the lr (EXC_RETURN), but
// it is NOT used to used to return from the exception. (See POP {r0,pc})
#else //--------- ARMv7-M and higher...
" CPSIE i \n" // enable interrupts with PRIMASK
#endif //--------- ARMv7-M and higher
#endif //--------- interrupt disabling with PRIMASK
" POP {r0,pc} \n" // pop stack aligner and EXC_RETURN to pc
);
// NOTE: this causes exception-return to the preempted *thread* context

View File

@ -27,12 +27,6 @@
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-09-30
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QP/C++ port to ARM Cortex-M, preemptive QK kernel, ARM-CLANG
#ifndef QP_PORT_HPP_
#define QP_PORT_HPP_
@ -47,32 +41,9 @@
// QK event-queue used for AOs
#define QACTIVE_EQUEUE_TYPE QEQueue
// QF "thread" type used to store the MPU settings in the AO
// QActive "thread" type used to store the MPU settings in the AO
#define QACTIVE_THREAD_TYPE void const *
// QF interrupt disable/enable and log2()...
#if (__ARM_ARCH == 6) // ARMv6-M?
// CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4
#define QF_AWARE_ISR_CMSIS_PRI 0
// hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M)
#define QF_LOG2(n_) QF_qlog2(static_cast<std::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_) \
(static_cast<std::uint32_t>(32 - __builtin_clz((n_))))
#endif
// interrupt disabling policy, see NOTE2 and NOTE3
#define QF_INT_DISABLE() (QF_int_disable_())
#define QF_INT_ENABLE() (QF_int_enable_())
@ -84,11 +55,28 @@
#define QF_CRIT_EXIT_NOP() __asm volatile ("isb" ::: "memory")
// Efficient log2() ----------------------------------------------------------
#if (__ARM_ARCH == 6) // ARMv6-M?
// hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M)
#define QF_LOG2(n_) QF_qlog2(static_cast<std::uint32_t>(n_))
// hand-optimized quick LOG2 in assembly
extern "C" std::uint_fast8_t QF_qlog2(std::uint32_t x);
#else // ARMv7-M or higher
// ARMv7-M or higher provide the CLZ instruction for fast LOG2
#define QF_LOG2(n_) \
(static_cast<std::uint32_t>(32 - __builtin_clz((n_))))
#endif // ARMv7-M or higher
// Critical section policy ---------------------------------------------------
#ifdef QF_USE_BASEPRI
// CMSIS threshold for "QF-aware" interrupts, see NOTE4
#define QF_AWARE_ISR_CMSIS_PRI (QF_USE_BASEPRI >> (8 - __NVIC_PRIO_BITS))
#else
// CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4
#define QF_AWARE_ISR_CMSIS_PRI 0
#endif // QF_USE_BASEPRI
// Memory isolation ----------------------------------------------------------
#ifdef QF_MEM_ISOLATE
@ -105,7 +93,7 @@
extern "C" void QF_onMemSys(void);
extern "C" void QF_onMemApp(void);
#endif // def QF_MEM_ISOLATE
#endif // QF_MEM_ISOLATE
// determination if the code executes in the ISR context
#define QK_ISR_CONTEXT_() (QK_get_IPSR() != 0U)
@ -154,7 +142,7 @@ static inline uint32_t QK_get_IPSR(void) {
#endif // ARMv6-M
// initialization of the QK kernel
#define QK_INIT() QK_init()
#define QK_INIT() QK_init()
extern "C" void QK_init(void);
extern "C" void QK_thread_ret(void);
@ -189,7 +177,7 @@ extern "C" {
// functions. They are defined as "weak" in the qv_port.c module,
// so the application can provide a different implementation.
// Please see the definitions of the interrupt and critical-section
// funcctions in the qv_port.c module for details.
// functions in the qv_port.c module for details.
//
// NOTE2:
// On Cortex-M0/M0+/M1 (architecture ARMv6-M, ARMv6S-M), the interrupt
@ -198,15 +186,15 @@ extern "C" {
// are "kernel-aware".
//
// NOTE3:
// On ARMv7-M or higher, the interrupt disable/enable policy uses the BASEPRI
// register (which is not implemented in ARMv6-M) to disable interrupts only
// with priority lower than the threshold specified by the QF_BASEPRI macro.
// The interrupts with priorities above QF_BASEPRI (i.e., with numerical
// priority values lower than QF_BASEPRI) are NOT disabled in this method.
// If macro QF_USE_BASEPRI is defined, the interrupt disable/enable policy
// uses BASEPRI register to disable interrupts only with priority lower than
// the threshold specified by the QF_USE_BASEPRI macro. The interrupts with
// priorities above QF_USE_BASEPRI (i.e., with numerical priority values
// lower than QF_USE_BASEPRI) are NOT disabled in this method.
// These free-running interrupts have very low ("zero") latency, but they
// are NOT allowed to call any QF services, because QF is unaware of them
// ("kernel-unaware" interrupts). Consequently, only interrupts with
// numerical values of priorities equal to or higher than QF_BASEPRI
// numerical values of priorities equal to or higher than QF_USE_BASEPRI
// ("kernel-aware" interrupts ), can call QF services.
//
// NOTE4:

View File

@ -26,12 +26,6 @@
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-09-30
//! @version Last updated for: @ref qpc_8_0_0
//!
//! @file
//! @brief QK/C++ port to ARM Cortex-M, GNU-ARM
#define QP_IMPL 1U
#include "qp_port.hpp"
#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
@ -70,7 +64,6 @@ void NMI_Handler(void);
// For best performance, these functions are implemented in assembly,
// but they can be implemented in C as well.
//std::int32_t volatile QF_int_lock_nest_; // not used
extern char const QF_port_module_[];
char const QF_port_module_[] = "qk_port";
@ -79,24 +72,23 @@ char const QF_port_module_[] = "qk_port";
// Unconditionally disable interrupts.
// NOTE: this function must NOT use the stack.
//
// description:
// On ARMv6-M, interrupts are disabled with the PRIMASK register.
// On ARMv7-M and higher, interrupts are disabled *selectively* with the
// BASEPRI register.
// Description:
// When QF_USE_BASEPRI is defined, interrupts are disabled with BASEPRI.
// Otherwise interrupts are disabled with the PRIMASK register.
// Additionally, the function also asserts that the interrupts are
// NOT disabled upon the entry to the function, which means that
// this interrupt management policy CANNOT nest.
__attribute__ ((naked, weak))
void QF_int_disable_(void) {
__asm volatile (
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for interrupt disabling?
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
" MOVS r1,#" STRINGIFY(QF_USE_BASEPRI) "\n"
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
#else //--------- use PRIMASK for disabling interrupts
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
" CPSID i \n" // set PRIMASK
#else //--------- ARMv7-M or higher
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
" MOVS r1,#" STRINGIFY(QF_BASEPRI) "\n"
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
#endif //--------- ARMv7-M or higher
#endif //--------- use PRIMASK for disabling interrupts
" CMP r0,#0 \n" // assert(PRIMASK/BASEPRI == 0)
" BNE QF_int_disable_error\n"
" BX lr \n"
@ -111,28 +103,29 @@ __asm volatile (
// Unconditionally enable interrupts.
// NOTE: this function must NOT use the stack.
//
// description:
// On ARMv6-M, interrupts are enabled with the PRIMASK register.
// On ARMv7-M and higher, interrupts are enabled with the BASEPRI register.
// Description:
// When QF_USE_BASEPRI is defined, interrupts are enabled with BASEPRI.
// Otherwise interrupts are enabled with the PRIMASK register.
// Additionally, the function also asserts that the interrupts ARE
// disabled upon the entry to the function, which means that
// this interrupt management policy CANNOT nest.
__attribute__ ((naked, weak))
void QF_int_enable_(void) {
__asm volatile (
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
#else //--------- ARMv7-M or higher
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for enabling interrupts?
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
#endif //--------- ARMv7-M or higher
#else //--------- use PRIMASK for enabling interrupts
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
#endif //--------- use PRIMASK for enabling interrupts
" CMP r0,#0 \n" // assert(PRIMASK/BASEPRI != 0)
" BEQ QF_int_enable_error\n"
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
" CPSIE i \n" // clear PRIMASK
#else //--------- ARMv7-M or higher
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for enabling interrupts?
" MOVS r1,#0 \n"
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
#endif //--------- ARMv7-M or higher
#else //--------- use PRIMASK for enabling interrupts
" CPSIE i \n" // clear PRIMASK
#endif //--------- use PRIMASK for enabling interrupts
" BX lr \n"
"QF_int_enable_error: \n"
" LDR r0,=QF_port_module_ \n"
@ -145,25 +138,23 @@ __asm volatile (
// Enter QF critical section.
// NOTE: this function must NOT use the stack.
//
// description:
// On ARMv6-M, critical section is entered by disabling interrupts
// with the PRIMASK register.
// On ARMv7-M and higher, critical section is entered by disabling
// interrupts *selectively* with the BASEPRI register.
// Description:
// When QF_USE_BASEPRI is defined, critical section uses BASEPRI.
// Otherwise, critical section uses the PRIMASK register.
// Additionally, the function also asserts that the interrupts are
// NOT disabled upon the entry to the function, which means that
// this critical section CANNOT nest.
__attribute__ ((naked, weak))
void QF_crit_entry_(void) {
__asm volatile (
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
" MOVS r1,#" STRINGIFY(QF_USE_BASEPRI) "\n"
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
#else //--------- use PRIMASK for critical section
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
" CPSID i \n" // set PRIMASK
#else //--------- ARMv7-M or higher
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
" MOVS r1,#" STRINGIFY(QF_BASEPRI) "\n"
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
#endif //--------- ARMv7-M or higher
#endif //--------- use PRIMASK for critical section
" CMP r0,#0 \n" // assert(PRIMASK/BASEPRI == 0)
" BNE QF_crit_entry_error\n"
" BX lr \n"
@ -179,29 +170,27 @@ __asm volatile (
// NOTE: this function must NOT use the stack.
//
// description:
// On ARMv6-M, critical section is exited by enabling interrupts
// with the PRIMASK register.
// On ARMv7-M and higher, critical section is exited by enabling
// interrupts with the BASEPRI register.
// When QF_USE_BASEPRI is defined, critical section uses BASEPRI.
// Otherwise, critical section uses the PRIMASK register.
// Additionally, the function also asserts that the interrupts ARE
// disabled upon the entry to the function, which means that
// this critical section CANNOT nest.
__attribute__ ((naked, weak))
void QF_crit_exit_(void) {
__asm volatile (
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
#else //--------- ARMv7-M or higher
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
#endif //--------- ARMv7-M or higher
#else //--------- use PRIMASK for critical section
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
#endif //--------- use PRIMASK for critical section
" CMP r0,#0 \n" // assert(PRIMASK/BASEPRI != 0)
" BEQ QF_crit_exit_error\n"
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
" CPSIE i \n" // clear PRIMASK
#else //--------- ARMv7-M or higher
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
" MOVS r1,#0 \n"
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
#endif //--------- ARMv7-M or higher
#else //--------- use PRIMASK
" CPSIE i \n" // clear PRIMASK
#endif //--------- use PRIMASK
" BX lr \n"
"QF_crit_exit_error: \n"
" LDR r0,=QF_port_module_ \n"
@ -219,7 +208,7 @@ __asm volatile (
// BASEPRI register. However, this method cannot disable interrupt
// priority zero, which is the default for all interrupts out of reset.
// The following code changes the SysTick priority and all IRQ priorities
// to the safe value QF_BASEPRI, which the QF critical section can disable.
// to the safe value QF_USE_BASEPRI, which the QF critical section can disable.
// This avoids breaching of the QF critical sections in case the
// application programmer forgets to explicitly set priorities of all
// "kernel aware" interrupts.
@ -228,18 +217,18 @@ __asm volatile (
// by the application-level code.
void QK_init(void) {
#if (__ARM_ARCH != 6) //--------- if ARMv7-M and higher...
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
// SCB_SYSPRI[2]: SysTick
SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_BASEPRI << 24U));
SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_USE_BASEPRI << 24U));
// set all 240 possible IRQ priories to QF_BASEPRI...
// set all 240 possible IRQ priories to QF_USE_BASEPRI...
for (uint_fast8_t n = 0U; n < (240U/sizeof(uint32_t)); ++n) {
NVIC_IP[n] = (QF_BASEPRI << 24U) | (QF_BASEPRI << 16U)
| (QF_BASEPRI << 8U) | QF_BASEPRI;
NVIC_IP[n] = (QF_USE_BASEPRI << 24U) | (QF_USE_BASEPRI << 16U)
| (QF_USE_BASEPRI << 8U) | QF_USE_BASEPRI;
}
#endif //--------- ARMv7-M or higher
#endif //--------- use BASEPRI for critical section
// SCB_SYSPRI[2]: PendSV set to priority 0xFF (lowest)
SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (0xFFU << 16U));
@ -383,9 +372,12 @@ void QK_thread_ret(void) {
#endif //--------- use the NMI
#else //--------- ARMv7-M and higher...
#ifdef QF_USE_BASEPRI //--------- QF_USE_BASEPRI
" CPSID i \n" // disable interrupts with PRIMASK
" LDR r0,=QF_int_enable_ \n"
" BLX r0 \n" // enable interrupts with BASEPRI
#endif //--------- QF_USE_BASEPRI
// NOTE: interrupts remain disabled with PRIMASK
#ifdef __ARM_FP //--------- if VFP available...
@ -401,7 +393,12 @@ void QK_thread_ret(void) {
" MOV r1,#1 \n"
" LSL r1,r1,#" STRINGIFY(QK_USE_IRQ_NUM & 0x1F) "\n" // r1 := IRQ bit
" STR r1,[r0] \n" // pend the IRQ
#ifdef QF_USE_BASEPRI //--------- QF_USE_BASEPRI
" CPSIE i \n" // enable interrupts with PRIMASK
#else //--------- interrupt disabling with PRIMASK
" LDR r0,=QF_int_enable_ \n"
" BLX r0 \n" // enable interrupts with BASEPRI
#endif //--------- interrupt disabling with PRIMASK
// This code stops here and continues in the IRQ handler
#else //--------- use the NMI (default)
@ -451,15 +448,16 @@ void NMI_Handler(void) {
__asm volatile (
" ADD sp,sp,#(8*4) \n" // remove one 8-register exception frame
#if (__ARM_ARCH == 6) //--------- if ARMv6-M...
#ifdef QF_USE_BASEPRI //--------- QF_USE_BASEPRI
// NOTE: QF_int_enable_() already called
" CPSIE i \n" // enable interrupts with PRIMASK
#else //--------- interrupt disabling with PRIMASK
" LDR r0,=QF_int_enable_ \n"
" BLX r0 \n" // enable interrupts with PRIMASK
// NOTE: calling QF_int_enable_() corrupted the lr (EXC_RETURN), but
// it is NOT used to used to return from the exception. (See POP {r0,pc})
#else //--------- ARMv7-M and higher...
" CPSIE i \n" // enable interrupts with PRIMASK
#endif //--------- ARMv7-M and higher
#endif //--------- interrupt disabling with PRIMASK
" POP {r0,pc} \n" // pop stack aligner and EXC_RETURN to pc
);
// NOTE: this causes exception-return to the preempted *thread* context

View File

@ -27,12 +27,6 @@
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-09-30
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QP/C++ port to ARM Cortex-M, preemptive QK kernel, GNU-ARM
#ifndef QP_PORT_HPP_
#define QP_PORT_HPP_
@ -47,32 +41,9 @@
// QK event-queue used for AOs
#define QACTIVE_EQUEUE_TYPE QEQueue
// QF "thread" type used to store the MPU settings in the AO
// QActive "thread" type used to store the MPU settings in the AO
#define QACTIVE_THREAD_TYPE void const *
// QF interrupt disable/enable and log2()...
#if (__ARM_ARCH == 6) // ARMv6-M?
// CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4
#define QF_AWARE_ISR_CMSIS_PRI 0
// hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M)
#define QF_LOG2(n_) QF_qlog2(static_cast<std::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_) \
(static_cast<std::uint32_t>(32 - __builtin_clz((n_))))
#endif
// interrupt disabling policy, see NOTE2 and NOTE3
#define QF_INT_DISABLE() (QF_int_disable_())
#define QF_INT_ENABLE() (QF_int_enable_())
@ -84,11 +55,28 @@
#define QF_CRIT_EXIT_NOP() __asm volatile ("isb" ::: "memory")
// Efficient log2() ----------------------------------------------------------
#if (__ARM_ARCH == 6) // ARMv6-M?
// hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M)
#define QF_LOG2(n_) QF_qlog2(static_cast<std::uint32_t>(n_))
// hand-optimized quick LOG2 in assembly
extern "C" std::uint_fast8_t QF_qlog2(std::uint32_t x);
#else // ARMv7-M or higher
// ARMv7-M or higher provide the CLZ instruction for fast LOG2
#define QF_LOG2(n_) \
(static_cast<std::uint32_t>(32 - __builtin_clz((n_))))
#endif // ARMv7-M or higher
// Critical section policy ---------------------------------------------------
#ifdef QF_USE_BASEPRI
// CMSIS threshold for "QF-aware" interrupts, see NOTE4
#define QF_AWARE_ISR_CMSIS_PRI (QF_USE_BASEPRI >> (8 - __NVIC_PRIO_BITS))
#else
// CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4
#define QF_AWARE_ISR_CMSIS_PRI 0
#endif // QF_USE_BASEPRI
// Memory isolation ----------------------------------------------------------
#ifdef QF_MEM_ISOLATE
@ -105,7 +93,7 @@
extern "C" void QF_onMemSys(void);
extern "C" void QF_onMemApp(void);
#endif // def QF_MEM_ISOLATE
#endif // QF_MEM_ISOLATE
// determination if the code executes in the ISR context
#define QK_ISR_CONTEXT_() (QK_get_IPSR() != 0U)
@ -189,7 +177,7 @@ extern "C" {
// functions. They are defined as "weak" in the qv_port.c module,
// so the application can provide a different implementation.
// Please see the definitions of the interrupt and critical-section
// funcctions in the qv_port.c module for details.
// functions in the qv_port.c module for details.
//
// NOTE2:
// On Cortex-M0/M0+/M1 (architecture ARMv6-M, ARMv6S-M), the interrupt
@ -198,15 +186,15 @@ extern "C" {
// are "kernel-aware".
//
// NOTE3:
// On ARMv7-M or higher, the interrupt disable/enable policy uses the BASEPRI
// register (which is not implemented in ARMv6-M) to disable interrupts only
// with priority lower than the threshold specified by the QF_BASEPRI macro.
// The interrupts with priorities above QF_BASEPRI (i.e., with numerical
// priority values lower than QF_BASEPRI) are NOT disabled in this method.
// If macro QF_USE_BASEPRI is defined, the interrupt disable/enable policy
// uses BASEPRI register to disable interrupts only with priority lower than
// the threshold specified by the QF_USE_BASEPRI macro. The interrupts with
// priorities above QF_USE_BASEPRI (i.e., with numerical priority values
// lower than QF_USE_BASEPRI) are NOT disabled in this method.
// These free-running interrupts have very low ("zero") latency, but they
// are NOT allowed to call any QF services, because QF is unaware of them
// ("kernel-unaware" interrupts). Consequently, only interrupts with
// numerical values of priorities equal to or higher than QF_BASEPRI
// numerical values of priorities equal to or higher than QF_USE_BASEPRI
// ("kernel-aware" interrupts ), can call QF services.
//
// NOTE4:
@ -221,8 +209,6 @@ extern "C" {
// is intended only for applications and is not used inside the QF port, which
// remains generic and not dependent on the number of implemented priority bits
// implemented in the NVIC.
//
//
#endif // QP_PORT_HPP_

View File

@ -26,12 +26,6 @@
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-09-30
//! @version Last updated for: @ref qpc_8_0_0
//!
//! @file
//! @brief QK/C++ port to ARM Cortex-M, IAR-ARM
#define QP_IMPL 1U
#include "qp_port.hpp"
#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
@ -83,24 +77,23 @@ char const QF_port_module_[] = "qk_port";
// Unconditionally disable interrupts.
// NOTE: this function must NOT use the stack.
//
// description:
// On ARMv6-M, interrupts are disabled with the PRIMASK register.
// On ARMv7-M and higher, interrupts are disabled *selectively* with the
// BASEPRI register.
// Description:
// When QF_USE_BASEPRI is defined, interrupts are disabled with BASEPRI.
// Otherwise interrupts are disabled with the PRIMASK register.
// Additionally, the function also asserts that the interrupts are
// NOT disabled upon the entry to the function, which means that
// this interrupt management policy CANNOT nest.
__stackless
void QF_int_disable_(void) {
__asm volatile (
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for interrupt disabling?
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
" MOVS r1,#" STRINGIFY(QF_USE_BASEPRI) "\n"
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
#else //--------- use PRIMASK for disabling interrupts
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
" CPSID i \n" // set PRIMASK
#else //--------- ARMv7-M or higher
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
" MOVS r1,#" STRINGIFY(QF_BASEPRI) "\n"
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
#endif //--------- ARMv7-M or higher
#endif //--------- use PRIMASK for disabling interrupts
" CMP r0,#0 \n" // assert(PRIMASK/BASEPRI == 0)
" BNE QF_int_disable_error\n"
" BX lr \n"
@ -115,28 +108,29 @@ __asm volatile (
// Unconditionally enable interrupts.
// NOTE: this function must NOT use the stack.
//
// description:
// On ARMv6-M, interrupts are enabled with the PRIMASK register.
// On ARMv7-M and higher, interrupts are enabled with the BASEPRI register.
// Description:
// When QF_USE_BASEPRI is defined, interrupts are enabled with BASEPRI.
// Otherwise interrupts are enabled with the PRIMASK register.
// Additionally, the function also asserts that the interrupts ARE
// disabled upon the entry to the function, which means that
// this interrupt management policy CANNOT nest.
__stackless
void QF_int_enable_(void) {
__asm volatile (
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
#else //--------- ARMv7-M or higher
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for enabling interrupts?
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
#endif //--------- ARMv7-M or higher
#else //--------- use PRIMASK for enabling interrupts
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
#endif //--------- use PRIMASK for enabling interrupts
" CMP r0,#0 \n" // assert(PRIMASK/BASEPRI != 0)
" BEQ QF_int_enable_error\n"
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
" CPSIE i \n" // clear PRIMASK
#else //--------- ARMv7-M or higher
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for enabling interrupts?
" MOVS r1,#0 \n"
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
#endif //--------- ARMv7-M or higher
#else //--------- use PRIMASK for enabling interrupts
" CPSIE i \n" // clear PRIMASK
#endif //--------- use PRIMASK for enabling interrupts
" BX lr \n"
"QF_int_enable_error: \n"
" LDR r0,=QF_port_module_ \n"
@ -149,25 +143,23 @@ __asm volatile (
// Enter QF critical section.
// NOTE: this function must NOT use the stack.
//
// description:
// On ARMv6-M, critical section is entered by disabling interrupts
// with the PRIMASK register.
// On ARMv7-M and higher, critical section is entered by disabling
// interrupts *selectively* with the BASEPRI register.
// Description:
// When QF_USE_BASEPRI is defined, critical section uses BASEPRI.
// Otherwise, critical section uses the PRIMASK register.
// Additionally, the function also asserts that the interrupts are
// NOT disabled upon the entry to the function, which means that
// this critical section CANNOT nest.
__stackless
void QF_crit_entry_(void) {
__asm volatile (
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
" MOVS r1,#" STRINGIFY(QF_USE_BASEPRI) "\n"
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
#else //--------- use PRIMASK for critical section
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
" CPSID i \n" // set PRIMASK
#else //--------- ARMv7-M or higher
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
" MOVS r1,#" STRINGIFY(QF_BASEPRI) "\n"
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
#endif //--------- ARMv7-M or higher
#endif //--------- use PRIMASK for critical section
" CMP r0,#0 \n" // assert(PRIMASK/BASEPRI == 0)
" BNE QF_crit_entry_error\n"
" BX lr \n"
@ -183,29 +175,27 @@ __asm volatile (
// NOTE: this function must NOT use the stack.
//
// description:
// On ARMv6-M, critical section is exited by enabling interrupts
// with the PRIMASK register.
// On ARMv7-M and higher, critical section is exited by enabling
// interrupts with the BASEPRI register.
// When QF_USE_BASEPRI is defined, critical section uses BASEPRI.
// Otherwise, critical section uses the PRIMASK register.
// Additionally, the function also asserts that the interrupts ARE
// disabled upon the entry to the function, which means that
// this critical section CANNOT nest.
__stackless
void QF_crit_exit_(void) {
__asm volatile (
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
#else //--------- ARMv7-M or higher
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
#endif //--------- ARMv7-M or higher
#else //--------- use PRIMASK for critical section
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
#endif //--------- use PRIMASK for critical section
" CMP r0,#0 \n" // assert(PRIMASK/BASEPRI != 0)
" BEQ QF_crit_exit_error\n"
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
" CPSIE i \n" // clear PRIMASK
#else //--------- ARMv7-M or higher
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
" MOVS r1,#0 \n"
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
#endif //--------- ARMv7-M or higher
#else //--------- use PRIMASK
" CPSIE i \n" // clear PRIMASK
#endif //--------- use PRIMASK
" BX lr \n"
"QF_crit_exit_error: \n"
" LDR r0,=QF_port_module_ \n"
@ -223,7 +213,7 @@ __asm volatile (
// BASEPRI register. However, this method cannot disable interrupt
// priority zero, which is the default for all interrupts out of reset.
// The following code changes the SysTick priority and all IRQ priorities
// to the safe value QF_BASEPRI, which the QF critical section can disable.
// to the safe value QF_USE_BASEPRI, which the QF critical section can disable.
// This avoids breaching of the QF critical sections in case the
// application programmer forgets to explicitly set priorities of all
// "kernel aware" interrupts.
@ -232,18 +222,18 @@ __asm volatile (
// by the application-level code.
void QK_init(void) {
#if (__ARM_ARCH != 6) //--------- if ARMv7-M and higher...
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
// SCB_SYSPRI[2]: SysTick
SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_BASEPRI << 24U));
SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_USE_BASEPRI << 24U));
// set all 240 possible IRQ priories to QF_BASEPRI...
// set all 240 possible IRQ priories to QF_USE_BASEPRI...
for (uint_fast8_t n = 0U; n < (240U/sizeof(uint32_t)); ++n) {
NVIC_IP[n] = (QF_BASEPRI << 24U) | (QF_BASEPRI << 16U)
| (QF_BASEPRI << 8U) | QF_BASEPRI;
NVIC_IP[n] = (QF_USE_BASEPRI << 24U) | (QF_USE_BASEPRI << 16U)
| (QF_USE_BASEPRI << 8U) | QF_USE_BASEPRI;
}
#endif //--------- ARMv7-M or higher
#endif //--------- use BASEPRI for critical section
// SCB_SYSPRI[2]: PendSV set to priority 0xFF (lowest)
SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (0xFFU << 16U));
@ -378,9 +368,12 @@ void QK_thread_ret(void) {
#endif //--------- use the NMI
#else //--------- ARMv7-M and higher...
#ifdef QF_USE_BASEPRI //--------- QF_USE_BASEPRI
" CPSID i \n" // disable interrupts with PRIMASK
" LDR r0,=QF_int_enable_ \n"
" BLX r0 \n" // enable interrupts with BASEPRI
#endif //--------- QF_USE_BASEPRI
// NOTE: interrupts remain disabled with PRIMASK
#ifdef __ARM_FP //--------- if VFP available...
@ -396,7 +389,12 @@ void QK_thread_ret(void) {
" MOVS r1,#1 \n"
" LSLS r1,r1,#" STRINGIFY(QK_USE_IRQ_NUM & 0x1F) "\n" // r1 := IRQ bit
" STR r1,[r0] \n" // pend the IRQ
#ifdef QF_USE_BASEPRI //--------- QF_USE_BASEPRI
" CPSIE i \n" // enable interrupts with PRIMASK
#else //--------- interrupt disabling with PRIMASK
" LDR r0,=QF_int_enable_ \n"
" BLX r0 \n" // enable interrupts with BASEPRI
#endif //--------- interrupt disabling with PRIMASK
// This code stops here and continues in the IRQ handler
#else //--------- use the NMI (default)
@ -446,15 +444,16 @@ void NMI_Handler(void) {
__asm volatile (
" ADD sp,sp,#(8*4) \n" // remove one 8-register exception frame
#if (__ARM_ARCH == 6) //--------- if ARMv6-M...
#ifdef QF_USE_BASEPRI //--------- QF_USE_BASEPRI
// NOTE: QF_int_enable_() already called
" CPSIE i \n" // enable interrupts with PRIMASK
#else //--------- interrupt disabling with PRIMASK
" LDR r0,=QF_int_enable_ \n"
" BLX r0 \n" // enable interrupts with PRIMASK
// NOTE: calling QF_int_enable_() corrupted the lr (EXC_RETURN), but
// it is NOT used to used to return from the exception. (See POP {r0,pc})
#else //--------- ARMv7-M and higher...
" CPSIE i \n" // enable interrupts with PRIMASK
#endif //--------- ARMv7-M and higher
#endif //--------- interrupt disabling with PRIMASK
" POP {r0,pc} \n" // pop stack aligner and EXC_RETURN to pc
);
// NOTE: this causes exception-return to the preempted *thread* context
@ -475,7 +474,7 @@ uint_fast8_t QF_qlog2(uint32_t x) {
uint_fast8_t n;
__asm volatile (
" MOVS %[n],#0 \n"
" MOVS %[n],#0 \n"
#if (QF_MAX_ACTIVE > 16U)
" LSRS r2,r0,#16 \n"
" BEQ QF_qlog2_1 \n"
@ -495,7 +494,7 @@ __asm volatile (
" ADDS %[n],%[n],#4 \n"
" MOVS r0,r2 \n"
"QF_qlog2_3:" : [n]"=r"(n)
);
);
return n + log2LUT[x];
}

View File

@ -27,12 +27,6 @@
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-09-30
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QP/C++ port to ARM Cortex-M, preemptive QK kernel, IAR-ARM
#ifndef QP_PORT_HPP_
#define QP_PORT_HPP_
@ -48,32 +42,9 @@
// QK event-queue used for AOs
#define QACTIVE_EQUEUE_TYPE QEQueue
// QF "thread" type used to store the MPU settings in the AO
// QActive "thread" type used to store the MPU settings in the AO
#define QACTIVE_THREAD_TYPE void const *
// QF interrupt disable/enable and log2()...
#if (__ARM_ARCH == 6) // ARMv6-M?
// CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4
#define QF_AWARE_ISR_CMSIS_PRI 0
// hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M)
#define QF_LOG2(n_) QF_qlog2(static_cast<std::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_) \
(static_cast<std::uint32_t>(32U - __CLZ((n_))))
#endif
// interrupt disabling policy, see NOTE2 and NOTE3
#define QF_INT_DISABLE() (QF_int_disable_())
#define QF_INT_ENABLE() (QF_int_enable_())
@ -85,11 +56,28 @@
#define QF_CRIT_EXIT_NOP() __ISB()
// Efficient log2() ----------------------------------------------------------
#if (__ARM_ARCH == 6) // ARMv6-M?
// hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M)
#define QF_LOG2(n_) QF_qlog2(static_cast<std::uint32_t>(n_))
// hand-optimized quick LOG2 in assembly
extern "C" std::uint_fast8_t QF_qlog2(std::uint32_t x);
#else // ARMv7-M or higher
// ARMv7-M or higher provide the CLZ instruction for fast LOG2
#define QF_LOG2(n_) \
(static_cast<std::uint32_t>(32U - __CLZ((n_))))
#endif // ARMv7-M or higher
// Critical section policy ---------------------------------------------------
#ifdef QF_USE_BASEPRI
// CMSIS threshold for "QF-aware" interrupts, see NOTE4
#define QF_AWARE_ISR_CMSIS_PRI (QF_USE_BASEPRI >> (8 - __NVIC_PRIO_BITS))
#else
// CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4
#define QF_AWARE_ISR_CMSIS_PRI 0
#endif // QF_USE_BASEPRI
// Memory isolation ----------------------------------------------------------
#ifdef QF_MEM_ISOLATE
@ -106,7 +94,7 @@
extern "C" void QF_onMemSys(void);
extern "C" void QF_onMemApp(void);
#endif // def QF_MEM_ISOLATE
#endif // QF_MEM_ISOLATE
// determination if the code executes in the ISR context
#define QK_ISR_CONTEXT_() (__get_IPSR() != 0U)
@ -183,7 +171,7 @@ extern "C" {
// functions. They are defined as "weak" in the qv_port.c module,
// so the application can provide a different implementation.
// Please see the definitions of the interrupt and critical-section
// funcctions in the qv_port.c module for details.
// functions in the qv_port.c module for details.
//
// NOTE2:
// On Cortex-M0/M0+/M1 (architecture ARMv6-M, ARMv6S-M), the interrupt
@ -192,15 +180,15 @@ extern "C" {
// are "kernel-aware".
//
// NOTE3:
// On ARMv7-M or higher, the interrupt disable/enable policy uses the BASEPRI
// register (which is not implemented in ARMv6-M) to disable interrupts only
// with priority lower than the threshold specified by the QF_BASEPRI macro.
// The interrupts with priorities above QF_BASEPRI (i.e., with numerical
// priority values lower than QF_BASEPRI) are NOT disabled in this method.
// If macro QF_USE_BASEPRI is defined, the interrupt disable/enable policy
// uses BASEPRI register to disable interrupts only with priority lower than
// the threshold specified by the QF_USE_BASEPRI macro. The interrupts with
// priorities above QF_USE_BASEPRI (i.e., with numerical priority values
// lower than QF_USE_BASEPRI) are NOT disabled in this method.
// These free-running interrupts have very low ("zero") latency, but they
// are NOT allowed to call any QF services, because QF is unaware of them
// ("kernel-unaware" interrupts). Consequently, only interrupts with
// numerical values of priorities equal to or higher than QF_BASEPRI
// numerical values of priorities equal to or higher than QF_USE_BASEPRI
// ("kernel-aware" interrupts ), can call QF services.
//
// NOTE4:
@ -215,8 +203,6 @@ extern "C" {
// is intended only for applications and is not used inside the QF port, which
// remains generic and not dependent on the number of implemented priority bits
// implemented in the NVIC.
//
//
#endif // QP_PORT_HPP_

View File

@ -27,12 +27,6 @@
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-09-30
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QF/C++ port to ARM Cortex-M, cooperative QV kernel, ARM-CLANG
#ifndef QP_PORT_HPP_
#define QP_PORT_HPP_
@ -47,32 +41,9 @@
// QV event-queue used for AOs
#define QACTIVE_EQUEUE_TYPE QEQueue
// QF "thread" type used to store the MPU settings in the AO
// QActive "thread" type used to store the MPU settings in the AO
#define QACTIVE_THREAD_TYPE void const *
// QF interrupt disable/enable and log2()...
#if (__ARM_ARCH == 6) // ARMv6-M?
// CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4
#define QF_AWARE_ISR_CMSIS_PRI 0
// hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M)
#define QF_LOG2(n_) QF_qlog2(static_cast<std::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_) \
(static_cast<std::uint32_t>(32 - __builtin_clz((n_))))
#endif
// interrupt disabling policy, see NOTE2 and NOTE3
#define QF_INT_DISABLE() (QF_int_disable_())
#define QF_INT_ENABLE() (QF_int_enable_())
@ -84,11 +55,28 @@
#define QF_CRIT_EXIT_NOP() __asm volatile ("isb" ::: "memory")
// Efficient log2() ----------------------------------------------------------
#if (__ARM_ARCH == 6) // ARMv6-M?
// hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M)
#define QF_LOG2(n_) QF_qlog2(static_cast<std::uint32_t>(n_))
// hand-optimized quick LOG2 in assembly
extern "C" std::uint_fast8_t QF_qlog2(std::uint32_t x);
#else // ARMv7-M or higher
// ARMv7-M or higher provide the CLZ instruction for fast LOG2
#define QF_LOG2(n_) \
(static_cast<std::uint32_t>(32 - __builtin_clz((n_))))
#endif // ARMv7-M or higher
// Critical section policy ---------------------------------------------------
#ifdef QF_USE_BASEPRI
// CMSIS threshold for "QF-aware" interrupts, see NOTE4
#define QF_AWARE_ISR_CMSIS_PRI (QF_USE_BASEPRI >> (8 - __NVIC_PRIO_BITS))
#else
// CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4
#define QF_AWARE_ISR_CMSIS_PRI 0
#endif // QF_USE_BASEPRI
// Memory isolation ----------------------------------------------------------
#ifdef QF_MEM_ISOLATE
@ -105,20 +93,10 @@
extern "C" void QF_onMemSys(void);
extern "C" void QF_onMemApp(void);
#endif // def QF_MEM_ISOLATE
#endif // QF_MEM_ISOLATE
// determination if the code executes in the ISR context
#if (__ARM_ARCH == 6) // ARMv6-M?
// macro to put the CPU to sleep inside QV_onIdle()
#define QV_CPU_SLEEP() do { \
__asm volatile ("wfi"::: "memory"); \
QF_INT_ENABLE(); \
} while (false)
#define QV_ARM_ERRATUM_838869() ((void)0)
#else // ARMv7-M or higher
// QV kernel sleep mode transition
#ifdef QF_USE_BASEPRI
// macro to put the CPU to sleep inside QV_onIdle()
#define QV_CPU_SLEEP() do { \
@ -128,6 +106,17 @@
__asm volatile ("cpsie i" ::: "memory"); \
} while (false)
#else // no BASEPRI (QV uses PRIMASK)
// macro to put the CPU to sleep inside QV_onIdle()
#define QV_CPU_SLEEP() do { \
__asm volatile ("wfi"::: "memory"); \
QF_INT_ENABLE(); \
} while (false)
#endif // no BASEPRI (QV uses PRIMASK)
#if (__ARM_ARCH == 6) // ARMv6-M?
#define QV_ARM_ERRATUM_838869() (static_cast<void>(0))
#else // ARMv7-M or higher
// The following macro implements the recommended workaround for the
// ARM Erratum 838869. Specifically, for Cortex-M3/M4/M7 the DSB
// (memory barrier) instruction needs to be added before exiting an ISR.
@ -171,7 +160,7 @@ extern "C" {
// functions. They are defined as "weak" in the qv_port.c module,
// so the application can provide a different implementation.
// Please see the definitions of the interrupt and critical-section
// funcctions in the qv_port.c module for details.
// functions in the qv_port.c module for details.
//
// NOTE2:
// On Cortex-M0/M0+/M1 (architecture ARMv6-M, ARMv6S-M), the interrupt
@ -180,15 +169,15 @@ extern "C" {
// are "kernel-aware".
//
// NOTE3:
// On ARMv7-M or higher, the interrupt disable/enable policy uses the BASEPRI
// register (which is not implemented in ARMv6-M) to disable interrupts only
// with priority lower than the threshold specified by the QF_BASEPRI macro.
// The interrupts with priorities above QF_BASEPRI (i.e., with numerical
// priority values lower than QF_BASEPRI) are NOT disabled in this method.
// If macro QF_USE_BASEPRI is defined, the interrupt disable/enable policy
// uses BASEPRI register to disable interrupts only with priority lower than
// the threshold specified by the QF_USE_BASEPRI macro. The interrupts with
// priorities above QF_USE_BASEPRI (i.e., with numerical priority values
// lower than QF_USE_BASEPRI) are NOT disabled in this method.
// These free-running interrupts have very low ("zero") latency, but they
// are NOT allowed to call any QF services, because QF is unaware of them
// ("kernel-unaware" interrupts). Consequently, only interrupts with
// numerical values of priorities equal to or higher than QF_BASEPRI
// numerical values of priorities equal to or higher than QF_USE_BASEPRI
// ("kernel-aware" interrupts ), can call QF services.
//
// NOTE4:
@ -203,8 +192,6 @@ extern "C" {
// is intended only for applications and is not used inside the QF port, which
// remains generic and not dependent on the number of implemented priority bits
// implemented in the NVIC.
//
//
#endif // QP_PORT_HPP_

View File

@ -1,5 +1,5 @@
//============================================================================
// QP/C Real-Time Embedded Framework (RTEF)
// QP/C++ Real-Time Embedded Framework (RTEF)
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
@ -26,12 +26,6 @@
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-09-30
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QV/C++ port to ARM Cortex-M, ARM-CLANG
#define QP_IMPL 1U
#include "qp_port.hpp"
#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
@ -67,24 +61,23 @@ char const QF_port_module_[] = "qv_port";
// Unconditionally disable interrupts.
// NOTE: this function must NOT use the stack.
//
// description:
// On ARMv6-M, interrupts are disabled with the PRIMASK register.
// On ARMv7-M and higher, interrupts are disabled *selectively* with the
// BASEPRI register.
// Description:
// When QF_USE_BASEPRI is defined, interrupts are disabled with BASEPRI.
// Otherwise interrupts are disabled with the PRIMASK register.
// Additionally, the function also asserts that the interrupts are
// NOT disabled upon the entry to the function, which means that
// this interrupt management policy CANNOT nest.
__attribute__ ((naked, weak))
void QF_int_disable_(void) {
__asm volatile (
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for interrupt disabling?
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
" MOVS r1,#" STRINGIFY(QF_USE_BASEPRI) "\n"
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
#else //--------- use PRIMASK for disabling interrupts
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
" CPSID i \n" // set PRIMASK
#else //--------- ARMv7-M or higher
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
" MOVS r1,#" STRINGIFY(QF_BASEPRI) "\n"
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
#endif //--------- ARMv7-M or higher
#endif //--------- use PRIMASK for disabling interrupts
" CMP r0,#0 \n" // assert(PRIMASK/BASEPRI == 0)
" BNE QF_int_disable_error\n"
" BX lr \n"
@ -99,28 +92,29 @@ __asm volatile (
// Unconditionally enable interrupts.
// NOTE: this function must NOT use the stack.
//
// description:
// On ARMv6-M, interrupts are enabled with the PRIMASK register.
// On ARMv7-M and higher, interrupts are enabled with the BASEPRI register.
// Description:
// When QF_USE_BASEPRI is defined, interrupts are enabled with BASEPRI.
// Otherwise interrupts are enabled with the PRIMASK register.
// Additionally, the function also asserts that the interrupts ARE
// disabled upon the entry to the function, which means that
// this interrupt management policy CANNOT nest.
__attribute__ ((naked, weak))
void QF_int_enable_(void) {
__asm volatile (
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
#else //--------- ARMv7-M or higher
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for enabling interrupts?
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
#endif //--------- ARMv7-M or higher
#else //--------- use PRIMASK for enabling interrupts
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
#endif //--------- use PRIMASK for enabling interrupts
" CMP r0,#0 \n" // assert(PRIMASK/BASEPRI != 0)
" BEQ QF_int_enable_error\n"
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
" CPSIE i \n" // clear PRIMASK
#else //--------- ARMv7-M or higher
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for enabling interrupts?
" MOVS r1,#0 \n"
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
#endif //--------- ARMv7-M or higher
#else //--------- use PRIMASK for enabling interrupts
" CPSIE i \n" // clear PRIMASK
#endif //--------- use PRIMASK for enabling interrupts
" BX lr \n"
"QF_int_enable_error: \n"
" LDR r0,=QF_port_module_ \n"
@ -133,25 +127,23 @@ __asm volatile (
// Enter QF critical section.
// NOTE: this function must NOT use the stack.
//
// description:
// On ARMv6-M, critical section is entered by disabling interrupts
// with the PRIMASK register.
// On ARMv7-M and higher, critical section is entered by disabling
// interrupts *selectively* with the BASEPRI register.
// Description:
// When QF_USE_BASEPRI is defined, critical section uses BASEPRI.
// Otherwise, critical section uses the PRIMASK register.
// Additionally, the function also asserts that the interrupts are
// NOT disabled upon the entry to the function, which means that
// this critical section CANNOT nest.
__attribute__ ((naked, weak))
void QF_crit_entry_(void) {
__asm volatile (
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
" MOVS r1,#" STRINGIFY(QF_USE_BASEPRI) "\n"
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
#else //--------- use PRIMASK for critical section
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
" CPSID i \n" // set PRIMASK
#else //--------- ARMv7-M or higher
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
" MOVS r1,#" STRINGIFY(QF_BASEPRI) "\n"
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
#endif //--------- ARMv7-M or higher
#endif //--------- use PRIMASK for critical section
" CMP r0,#0 \n" // assert(PRIMASK/BASEPRI == 0)
" BNE QF_crit_entry_error\n"
" BX lr \n"
@ -167,29 +159,27 @@ __asm volatile (
// NOTE: this function must NOT use the stack.
//
// description:
// On ARMv6-M, critical section is exited by enabling interrupts
// with the PRIMASK register.
// On ARMv7-M and higher, critical section is exited by enabling
// interrupts with the BASEPRI register.
// When QF_USE_BASEPRI is defined, critical section uses BASEPRI.
// Otherwise, critical section uses the PRIMASK register.
// Additionally, the function also asserts that the interrupts ARE
// disabled upon the entry to the function, which means that
// this critical section CANNOT nest.
__attribute__ ((naked, weak))
void QF_crit_exit_(void) {
__asm volatile (
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
#else //--------- ARMv7-M or higher
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
#endif //--------- ARMv7-M or higher
#else //--------- use PRIMASK for critical section
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
#endif //--------- use PRIMASK for critical section
" CMP r0,#0 \n" // assert(PRIMASK/BASEPRI != 0)
" BEQ QF_crit_exit_error\n"
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
" CPSIE i \n" // clear PRIMASK
#else //--------- ARMv7-M or higher
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
" MOVS r1,#0 \n"
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
#endif //--------- ARMv7-M or higher
#else //--------- use PRIMASK
" CPSIE i \n" // clear PRIMASK
#endif //--------- use PRIMASK
" BX lr \n"
"QF_crit_exit_error: \n"
" LDR r0,=QF_port_module_ \n"
@ -207,7 +197,7 @@ __asm volatile (
// BASEPRI register. However, this method cannot disable interrupt
// priority zero, which is the default for all interrupts out of reset.
// The following code changes the SysTick priority and all IRQ priorities
// to the safe value QF_BASEPRI, which the QF critical section can disable.
// to the safe value QF_USE_BASEPRI, which the QF critical section can disable.
// This avoids breaching of the QF critical sections in case the
// application programmer forgets to explicitly set priorities of all
// "kernel aware" interrupts.
@ -216,18 +206,18 @@ __asm volatile (
// by the application-level code.
void QV_init(void) {
#if (__ARM_ARCH != 6) //--------- if ARMv7-M and higher...
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
// SCB_SYSPRI[2]: SysTick
SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_BASEPRI << 24U));
SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_USE_BASEPRI << 24U));
// set all 240 possible IRQ priories to QF_BASEPRI...
// set all 240 possible IRQ priories to QF_USE_BASEPRI...
for (uint_fast8_t n = 0U; n < (240U/sizeof(uint32_t)); ++n) {
NVIC_IP[n] = (QF_BASEPRI << 24U) | (QF_BASEPRI << 16U)
| (QF_BASEPRI << 8U) | QF_BASEPRI;
NVIC_IP[n] = (QF_USE_BASEPRI << 24U) | (QF_USE_BASEPRI << 16U)
| (QF_USE_BASEPRI << 8U) | QF_USE_BASEPRI;
}
#endif //--------- ARMv7-M or higher
#endif //--------- use BASEPRI for critical section
#ifdef __ARM_FP //--------- if VFP available...
// make sure that the FPU is enabled by setting CP10 & CP11 Full Access

View File

@ -27,12 +27,6 @@
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-09-30
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief Qp/C++ port to ARM Cortex-M, cooperative QV kernel, GNU-ARM
#ifndef QP_PORT_HPP_
#define QP_PORT_HPP_
@ -47,32 +41,9 @@
// QV event-queue used for AOs
#define QACTIVE_EQUEUE_TYPE QEQueue
// QF "thread" type used to store the MPU settings in the AO
// QActive "thread" type used to store the MPU settings in the AO
#define QACTIVE_THREAD_TYPE void const *
// QF interrupt disable/enable and log2()...
#if (__ARM_ARCH == 6) // ARMv6-M?
// CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4
#define QF_AWARE_ISR_CMSIS_PRI 0
// hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M)
#define QF_LOG2(n_) QF_qlog2(static_cast<std::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_) \
(static_cast<std::uint32_t>(32 - __builtin_clz((n_))))
#endif
// interrupt disabling policy, see NOTE2 and NOTE3
#define QF_INT_DISABLE() (QF_int_disable_())
#define QF_INT_ENABLE() (QF_int_enable_())
@ -84,11 +55,28 @@
#define QF_CRIT_EXIT_NOP() __asm volatile ("isb" ::: "memory")
// Efficient log2() ----------------------------------------------------------
#if (__ARM_ARCH == 6) // ARMv6-M?
// hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M)
#define QF_LOG2(n_) QF_qlog2(static_cast<std::uint32_t>(n_))
// hand-optimized quick LOG2 in assembly
extern "C" std::uint_fast8_t QF_qlog2(std::uint32_t x);
#else // ARMv7-M or higher
// ARMv7-M or higher provide the CLZ instruction for fast LOG2
#define QF_LOG2(n_) \
(static_cast<std::uint32_t>(32 - __builtin_clz((n_))))
#endif // ARMv7-M or higher
// Critical section policy ---------------------------------------------------
#ifdef QF_USE_BASEPRI
// CMSIS threshold for "QF-aware" interrupts, see NOTE4
#define QF_AWARE_ISR_CMSIS_PRI (QF_USE_BASEPRI >> (8 - __NVIC_PRIO_BITS))
#else
// CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4
#define QF_AWARE_ISR_CMSIS_PRI 0
#endif // QF_USE_BASEPRI
// Memory isolation ----------------------------------------------------------
#ifdef QF_MEM_ISOLATE
@ -105,20 +93,10 @@
extern "C" void QF_onMemSys(void);
extern "C" void QF_onMemApp(void);
#endif // def QF_MEM_ISOLATE
#endif // QF_MEM_ISOLATE
// determination if the code executes in the ISR context
#if (__ARM_ARCH == 6) // ARMv6-M?
// macro to put the CPU to sleep inside QV_onIdle()
#define QV_CPU_SLEEP() do { \
__asm volatile ("wfi"::: "memory"); \
QF_INT_ENABLE(); \
} while (false)
#define QV_ARM_ERRATUM_838869() ((void)0)
#else // ARMv7-M or higher
// QV kernel sleep mode transition
#ifdef QF_USE_BASEPRI
// macro to put the CPU to sleep inside QV_onIdle()
#define QV_CPU_SLEEP() do { \
@ -128,6 +106,17 @@
__asm volatile ("cpsie i" ::: "memory"); \
} while (false)
#else // no BASEPRI (QV uses PRIMASK)
// macro to put the CPU to sleep inside QV_onIdle()
#define QV_CPU_SLEEP() do { \
__asm volatile ("wfi"::: "memory"); \
QF_INT_ENABLE(); \
} while (false)
#endif // no BASEPRI (QV uses PRIMASK)
#if (__ARM_ARCH == 6) // ARMv6-M?
#define QV_ARM_ERRATUM_838869() ((void)0)
#else // ARMv7-M or higher
// The following macro implements the recommended workaround for the
// ARM Erratum 838869. Specifically, for Cortex-M3/M4/M7 the DSB
// (memory barrier) instruction needs to be added before exiting an ISR.
@ -171,7 +160,7 @@ extern "C" {
// functions. They are defined as "weak" in the qv_port.c module,
// so the application can provide a different implementation.
// Please see the definitions of the interrupt and critical-section
// funcctions in the qv_port.c module for details.
// functions in the qv_port.c module for details.
//
// NOTE2:
// On Cortex-M0/M0+/M1 (architecture ARMv6-M, ARMv6S-M), the interrupt
@ -180,15 +169,15 @@ extern "C" {
// are "kernel-aware".
//
// NOTE3:
// On ARMv7-M or higher, the interrupt disable/enable policy uses the BASEPRI
// register (which is not implemented in ARMv6-M) to disable interrupts only
// with priority lower than the threshold specified by the QF_BASEPRI macro.
// The interrupts with priorities above QF_BASEPRI (i.e., with numerical
// priority values lower than QF_BASEPRI) are NOT disabled in this method.
// If macro QF_USE_BASEPRI is defined, the interrupt disable/enable policy
// uses BASEPRI register to disable interrupts only with priority lower than
// the threshold specified by the QF_USE_BASEPRI macro. The interrupts with
// priorities above QF_USE_BASEPRI (i.e., with numerical priority values
// lower than QF_USE_BASEPRI) are NOT disabled in this method.
// These free-running interrupts have very low ("zero") latency, but they
// are NOT allowed to call any QF services, because QF is unaware of them
// ("kernel-unaware" interrupts). Consequently, only interrupts with
// numerical values of priorities equal to or higher than QF_BASEPRI
// numerical values of priorities equal to or higher than QF_USE_BASEPRI
// ("kernel-aware" interrupts ), can call QF services.
//
// NOTE4:
@ -203,8 +192,6 @@ extern "C" {
// is intended only for applications and is not used inside the QF port, which
// remains generic and not dependent on the number of implemented priority bits
// implemented in the NVIC.
//
//
#endif // QP_PORT_HPP_

View File

@ -1,5 +1,5 @@
//============================================================================
// QP/C Real-Time Embedded Framework (RTEF)
// QP/C++ Real-Time Embedded Framework (RTEF)
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
@ -26,12 +26,6 @@
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-09-30
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QV/C++ port to ARM Cortex-M, GNU-ARM
#define QP_IMPL 1U
#include "qp_port.hpp"
#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
@ -67,24 +61,23 @@ char const QF_port_module_[] = "qv_port";
// Unconditionally disable interrupts.
// NOTE: this function must NOT use the stack.
//
// description:
// On ARMv6-M, interrupts are disabled with the PRIMASK register.
// On ARMv7-M and higher, interrupts are disabled *selectively* with the
// BASEPRI register.
// Description:
// When QF_USE_BASEPRI is defined, interrupts are disabled with BASEPRI.
// Otherwise interrupts are disabled with the PRIMASK register.
// Additionally, the function also asserts that the interrupts are
// NOT disabled upon the entry to the function, which means that
// this interrupt management policy CANNOT nest.
__attribute__ ((naked, weak))
void QF_int_disable_(void) {
__asm volatile (
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for interrupt disabling?
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
" MOVS r1,#" STRINGIFY(QF_USE_BASEPRI) "\n"
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
#else //--------- use PRIMASK for disabling interrupts
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
" CPSID i \n" // set PRIMASK
#else //--------- ARMv7-M or higher
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
" MOVS r1,#" STRINGIFY(QF_BASEPRI) "\n"
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
#endif //--------- ARMv7-M or higher
#endif //--------- use PRIMASK for disabling interrupts
" CMP r0,#0 \n" // assert(PRIMASK/BASEPRI == 0)
" BNE QF_int_disable_error\n"
" BX lr \n"
@ -99,28 +92,29 @@ __asm volatile (
// Unconditionally enable interrupts.
// NOTE: this function must NOT use the stack.
//
// description:
// On ARMv6-M, interrupts are enabled with the PRIMASK register.
// On ARMv7-M and higher, interrupts are enabled with the BASEPRI register.
// Description:
// When QF_USE_BASEPRI is defined, interrupts are enabled with BASEPRI.
// Otherwise interrupts are enabled with the PRIMASK register.
// Additionally, the function also asserts that the interrupts ARE
// disabled upon the entry to the function, which means that
// this interrupt management policy CANNOT nest.
__attribute__ ((naked, weak))
void QF_int_enable_(void) {
__asm volatile (
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
#else //--------- ARMv7-M or higher
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for enabling interrupts?
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
#endif //--------- ARMv7-M or higher
#else //--------- use PRIMASK for enabling interrupts
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
#endif //--------- use PRIMASK for enabling interrupts
" CMP r0,#0 \n" // assert(PRIMASK/BASEPRI != 0)
" BEQ QF_int_enable_error\n"
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
" CPSIE i \n" // clear PRIMASK
#else //--------- ARMv7-M or higher
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for enabling interrupts?
" MOVS r1,#0 \n"
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
#endif //--------- ARMv7-M or higher
#else //--------- use PRIMASK for enabling interrupts
" CPSIE i \n" // clear PRIMASK
#endif //--------- use PRIMASK for enabling interrupts
" BX lr \n"
"QF_int_enable_error: \n"
" LDR r0,=QF_port_module_ \n"
@ -133,25 +127,23 @@ __asm volatile (
// Enter QF critical section.
// NOTE: this function must NOT use the stack.
//
// description:
// On ARMv6-M, critical section is entered by disabling interrupts
// with the PRIMASK register.
// On ARMv7-M and higher, critical section is entered by disabling
// interrupts *selectively* with the BASEPRI register.
// Description:
// When QF_USE_BASEPRI is defined, critical section uses BASEPRI.
// Otherwise, critical section uses the PRIMASK register.
// Additionally, the function also asserts that the interrupts are
// NOT disabled upon the entry to the function, which means that
// this critical section CANNOT nest.
__attribute__ ((naked, weak))
void QF_crit_entry_(void) {
__asm volatile (
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
" MOVS r1,#" STRINGIFY(QF_USE_BASEPRI) "\n"
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
#else //--------- use PRIMASK for critical section
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
" CPSID i \n" // set PRIMASK
#else //--------- ARMv7-M or higher
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
" MOVS r1,#" STRINGIFY(QF_BASEPRI) "\n"
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
#endif //--------- ARMv7-M or higher
#endif //--------- use PRIMASK for critical section
" CMP r0,#0 \n" // assert(PRIMASK/BASEPRI == 0)
" BNE QF_crit_entry_error\n"
" BX lr \n"
@ -167,29 +159,27 @@ __asm volatile (
// NOTE: this function must NOT use the stack.
//
// description:
// On ARMv6-M, critical section is exited by enabling interrupts
// with the PRIMASK register.
// On ARMv7-M and higher, critical section is exited by enabling
// interrupts with the BASEPRI register.
// When QF_USE_BASEPRI is defined, critical section uses BASEPRI.
// Otherwise, critical section uses the PRIMASK register.
// Additionally, the function also asserts that the interrupts ARE
// disabled upon the entry to the function, which means that
// this critical section CANNOT nest.
__attribute__ ((naked, weak))
void QF_crit_exit_(void) {
__asm volatile (
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
#else //--------- ARMv7-M or higher
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
#endif //--------- ARMv7-M or higher
#else //--------- use PRIMASK for critical section
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
#endif //--------- use PRIMASK for critical section
" CMP r0,#0 \n" // assert(PRIMASK/BASEPRI != 0)
" BEQ QF_crit_exit_error\n"
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
" CPSIE i \n" // clear PRIMASK
#else //--------- ARMv7-M or higher
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
" MOVS r1,#0 \n"
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
#endif //--------- ARMv7-M or higher
#else //--------- use PRIMASK
" CPSIE i \n" // clear PRIMASK
#endif //--------- use PRIMASK
" BX lr \n"
"QF_crit_exit_error: \n"
" LDR r0,=QF_port_module_ \n"
@ -207,7 +197,7 @@ __asm volatile (
// BASEPRI register. However, this method cannot disable interrupt
// priority zero, which is the default for all interrupts out of reset.
// The following code changes the SysTick priority and all IRQ priorities
// to the safe value QF_BASEPRI, which the QF critical section can disable.
// to the safe value QF_USE_BASEPRI, which the QF critical section can disable.
// This avoids breaching of the QF critical sections in case the
// application programmer forgets to explicitly set priorities of all
// "kernel aware" interrupts.
@ -216,18 +206,18 @@ __asm volatile (
// by the application-level code.
void QV_init(void) {
#if (__ARM_ARCH != 6) //--------- if ARMv7-M and higher...
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
// SCB_SYSPRI[2]: SysTick
SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_BASEPRI << 24U));
SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_USE_BASEPRI << 24U));
// set all 240 possible IRQ priories to QF_BASEPRI...
// set all 240 possible IRQ priories to QF_USE_BASEPRI...
for (uint_fast8_t n = 0U; n < (240U/sizeof(uint32_t)); ++n) {
NVIC_IP[n] = (QF_BASEPRI << 24U) | (QF_BASEPRI << 16U)
| (QF_BASEPRI << 8U) | QF_BASEPRI;
NVIC_IP[n] = (QF_USE_BASEPRI << 24U) | (QF_USE_BASEPRI << 16U)
| (QF_USE_BASEPRI << 8U) | QF_USE_BASEPRI;
}
#endif //--------- ARMv7-M or higher
#endif //--------- use BASEPRI for critical section
#ifdef __ARM_FP //--------- if VFP available...
// make sure that the FPU is enabled by setting CP10 & CP11 Full Access

View File

@ -1,6 +1,6 @@
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
///
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
@ -27,12 +27,6 @@
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-09-30
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QP/C++ port to ARM Cortex-M, cooperative QV kernel, IAR-ARM
#ifndef QP_PORT_HPP_
#define QP_PORT_HPP_
@ -48,32 +42,9 @@
// QV event-queue used for AOs
#define QACTIVE_EQUEUE_TYPE QEQueue
// QF "thread" type used to store the MPU settings in the AO
// QActive "thread" type used to store the MPU settings in the AO
#define QACTIVE_THREAD_TYPE void const *
// QF interrupt disable/enable and log2()...
#if (__ARM_ARCH == 6) // ARMv6-M?
// CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4
#define QF_AWARE_ISR_CMSIS_PRI 0
// hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M)
#define QF_LOG2(n_) QF_qlog2(static_cast<std::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_) \
(static_cast<std::uint32_t>(32U - __CLZ((n_))))
#endif
// interrupt disabling policy, see NOTE2 and NOTE3
#define QF_INT_DISABLE() (QF_int_disable_())
#define QF_INT_ENABLE() (QF_int_enable_())
@ -83,13 +54,30 @@
#define QF_CRIT_ENTRY() (QF_crit_entry_())
#define QF_CRIT_EXIT() (QF_crit_exit_())
#define QF_CRIT_EXIT_NOP() __asm volatile ("isb" ::: "memory")
#define QF_CRIT_EXIT_NOP() __ISB()
// Efficient log2() ----------------------------------------------------------
#if (__ARM_ARCH == 6) // ARMv6-M?
// hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M)
#define QF_LOG2(n_) QF_qlog2(static_cast<std::uint32_t>(n_))
// hand-optimized quick LOG2 in assembly
extern "C" std::uint_fast8_t QF_qlog2(std::uint32_t x);
#else // ARMv7-M or higher
// ARMv7-M or higher provide the CLZ instruction for fast LOG2
#define QF_LOG2(n_) \
(static_cast<std::uint32_t>(32U - __CLZ((n_))))
#endif // ARMv7-M or higher
// Critical section policy ---------------------------------------------------
#ifdef QF_USE_BASEPRI
// CMSIS threshold for "QF-aware" interrupts, see NOTE4
#define QF_AWARE_ISR_CMSIS_PRI (QF_USE_BASEPRI >> (8 - __NVIC_PRIO_BITS))
#else
// CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4
#define QF_AWARE_ISR_CMSIS_PRI 0
#endif // QF_USE_BASEPRI
// Memory isolation ----------------------------------------------------------
#ifdef QF_MEM_ISOLATE
@ -106,20 +94,10 @@
extern "C" void QF_onMemSys(void);
extern "C" void QF_onMemApp(void);
#endif // def QF_MEM_ISOLATE
#endif // QF_MEM_ISOLATE
// determination if the code executes in the ISR context
#if (__ARM_ARCH == 6) // ARMv6-M?
// macro to put the CPU to sleep inside QV_onIdle()
#define QV_CPU_SLEEP() do { \
__WFI(); \
QF_INT_ENABLE(); \
} while (false)
#define QV_ARM_ERRATUM_838869() ((void)0)
#else // ARMv7-M or higher
// QV kernel sleep mode transition
#ifdef QF_USE_BASEPRI
// macro to put the CPU to sleep inside QV_onIdle()
#define QV_CPU_SLEEP() do { \
@ -129,6 +107,18 @@
__enable_interrupt(); \
} while (false)
#else // no BASEPRI (QV uses PRIMASK)
// macro to put the CPU to sleep inside QV_onIdle()
#define QV_CPU_SLEEP() do { \
__WFI(); \
QF_INT_ENABLE(); \
} while (false)
#endif // no BASEPRI (QV uses PRIMASK)
#if (__ARM_ARCH == 6) // ARMv6-M?
#define QV_ARM_ERRATUM_838869() (static_cast<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.
@ -172,7 +162,7 @@ extern "C" {
// functions. They are defined as "weak" in the qv_port.c module,
// so the application can provide a different implementation.
// Please see the definitions of the interrupt and critical-section
// funcctions in the qv_port.c module for details.
// functions in the qv_port.c module for details.
//
// NOTE2:
// On Cortex-M0/M0+/M1 (architecture ARMv6-M, ARMv6S-M), the interrupt
@ -181,15 +171,15 @@ extern "C" {
// are "kernel-aware".
//
// NOTE3:
// On ARMv7-M or higher, the interrupt disable/enable policy uses the BASEPRI
// register (which is not implemented in ARMv6-M) to disable interrupts only
// with priority lower than the threshold specified by the QF_BASEPRI macro.
// The interrupts with priorities above QF_BASEPRI (i.e., with numerical
// priority values lower than QF_BASEPRI) are NOT disabled in this method.
// If macro QF_USE_BASEPRI is defined, the interrupt disable/enable policy
// uses BASEPRI register to disable interrupts only with priority lower than
// the threshold specified by the QF_USE_BASEPRI macro. The interrupts with
// priorities above QF_USE_BASEPRI (i.e., with numerical priority values
// lower than QF_USE_BASEPRI) are NOT disabled in this method.
// These free-running interrupts have very low ("zero") latency, but they
// are NOT allowed to call any QF services, because QF is unaware of them
// ("kernel-unaware" interrupts). Consequently, only interrupts with
// numerical values of priorities equal to or higher than QF_BASEPRI
// numerical values of priorities equal to or higher than QF_USE_BASEPRI
// ("kernel-aware" interrupts ), can call QF services.
//
// NOTE4:
@ -204,8 +194,6 @@ extern "C" {
// is intended only for applications and is not used inside the QF port, which
// remains generic and not dependent on the number of implemented priority bits
// implemented in the NVIC.
//
//
#endif // QP_PORT_HPP_

View File

@ -26,12 +26,6 @@
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-09-30
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
//! @brief QV/C++ port to ARM Cortex-M, IAR-ARM toolset
#define QP_IMPL 1U
#include "qp_port.hpp"
#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
@ -72,24 +66,23 @@ char const QF_port_module_[] = "qv_port";
// Unconditionally disable interrupts.
// NOTE: this function must NOT use the stack.
//
// description:
// On ARMv6-M, interrupts are disabled with the PRIMASK register.
// On ARMv7-M and higher, interrupts are disabled *selectively* with the
// BASEPRI register.
// Description:
// When QF_USE_BASEPRI is defined, interrupts are disabled with BASEPRI.
// Otherwise interrupts are disabled with the PRIMASK register.
// Additionally, the function also asserts that the interrupts are
// NOT disabled upon the entry to the function, which means that
// this interrupt management policy CANNOT nest.
__stackless
void QF_int_disable_(void) {
__asm volatile (
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for interrupt disabling?
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
" MOVS r1,#" STRINGIFY(QF_USE_BASEPRI) "\n"
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
#else //--------- use PRIMASK for disabling interrupts
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
" CPSID i \n" // set PRIMASK
#else //--------- ARMv7-M or higher
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
" MOVS r1,#" STRINGIFY(QF_BASEPRI) "\n"
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
#endif //--------- ARMv7-M or higher
#endif //--------- use PRIMASK for disabling interrupts
" CMP r0,#0 \n" // assert(PRIMASK/BASEPRI == 0)
" BNE QF_int_disable_error\n"
" BX lr \n"
@ -104,28 +97,29 @@ __asm volatile (
// Unconditionally enable interrupts.
// NOTE: this function must NOT use the stack.
//
// description:
// On ARMv6-M, interrupts are enabled with the PRIMASK register.
// On ARMv7-M and higher, interrupts are enabled with the BASEPRI register.
// Description:
// When QF_USE_BASEPRI is defined, interrupts are enabled with BASEPRI.
// Otherwise interrupts are enabled with the PRIMASK register.
// Additionally, the function also asserts that the interrupts ARE
// disabled upon the entry to the function, which means that
// this interrupt management policy CANNOT nest.
__stackless
void QF_int_enable_(void) {
__asm volatile (
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
#else //--------- ARMv7-M or higher
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for enabling interrupts?
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
#endif //--------- ARMv7-M or higher
#else //--------- use PRIMASK for enabling interrupts
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
#endif //--------- use PRIMASK for enabling interrupts
" CMP r0,#0 \n" // assert(PRIMASK/BASEPRI != 0)
" BEQ QF_int_enable_error\n"
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
" CPSIE i \n" // clear PRIMASK
#else //--------- ARMv7-M or higher
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for enabling interrupts?
" MOVS r1,#0 \n"
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
#endif //--------- ARMv7-M or higher
#else //--------- use PRIMASK for enabling interrupts
" CPSIE i \n" // clear PRIMASK
#endif //--------- use PRIMASK for enabling interrupts
" BX lr \n"
"QF_int_enable_error: \n"
" LDR r0,=QF_port_module_ \n"
@ -138,25 +132,23 @@ __asm volatile (
// Enter QF critical section.
// NOTE: this function must NOT use the stack.
//
// description:
// On ARMv6-M, critical section is entered by disabling interrupts
// with the PRIMASK register.
// On ARMv7-M and higher, critical section is entered by disabling
// interrupts *selectively* with the BASEPRI register.
// Description:
// When QF_USE_BASEPRI is defined, critical section uses BASEPRI.
// Otherwise, critical section uses the PRIMASK register.
// Additionally, the function also asserts that the interrupts are
// NOT disabled upon the entry to the function, which means that
// this critical section CANNOT nest.
__stackless
void QF_crit_entry_(void) {
__asm volatile (
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
" MOVS r1,#" STRINGIFY(QF_USE_BASEPRI) "\n"
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
#else //--------- use PRIMASK for critical section
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
" CPSID i \n" // set PRIMASK
#else //--------- ARMv7-M or higher
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
" MOVS r1,#" STRINGIFY(QF_BASEPRI) "\n"
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
#endif //--------- ARMv7-M or higher
#endif //--------- use PRIMASK for critical section
" CMP r0,#0 \n" // assert(PRIMASK/BASEPRI == 0)
" BNE QF_crit_entry_error\n"
" BX lr \n"
@ -172,29 +164,27 @@ __asm volatile (
// NOTE: this function must NOT use the stack.
//
// description:
// On ARMv6-M, critical section is exited by enabling interrupts
// with the PRIMASK register.
// On ARMv7-M and higher, critical section is exited by enabling
// interrupts with the BASEPRI register.
// When QF_USE_BASEPRI is defined, critical section uses BASEPRI.
// Otherwise, critical section uses the PRIMASK register.
// Additionally, the function also asserts that the interrupts ARE
// disabled upon the entry to the function, which means that
// this critical section CANNOT nest.
__stackless
void QF_crit_exit_(void) {
__asm volatile (
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
#else //--------- ARMv7-M or higher
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
#endif //--------- ARMv7-M or higher
#else //--------- use PRIMASK for critical section
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
#endif //--------- use PRIMASK for critical section
" CMP r0,#0 \n" // assert(PRIMASK/BASEPRI != 0)
" BEQ QF_crit_exit_error\n"
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
" CPSIE i \n" // clear PRIMASK
#else //--------- ARMv7-M or higher
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
" MOVS r1,#0 \n"
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
#endif //--------- ARMv7-M or higher
#else //--------- use PRIMASK
" CPSIE i \n" // clear PRIMASK
#endif //--------- use PRIMASK
" BX lr \n"
"QF_crit_exit_error: \n"
" LDR r0,=QF_port_module_ \n"
@ -212,7 +202,7 @@ __asm volatile (
// BASEPRI register. However, this method cannot disable interrupt
// priority zero, which is the default for all interrupts out of reset.
// The following code changes the SysTick priority and all IRQ priorities
// to the safe value QF_BASEPRI, which the QF critical section can disable.
// to the safe value QF_USE_BASEPRI, which the QF critical section can disable.
// This avoids breaching of the QF critical sections in case the
// application programmer forgets to explicitly set priorities of all
// "kernel aware" interrupts.
@ -221,18 +211,18 @@ __asm volatile (
// by the application-level code.
void QV_init(void) {
#if (__ARM_ARCH != 6) //--------- if ARMv7-M and higher...
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
// SCB_SYSPRI[2]: SysTick
SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_BASEPRI << 24U));
SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_USE_BASEPRI << 24U));
// set all 240 possible IRQ priories to QF_BASEPRI...
// set all 240 possible IRQ priories to QF_USE_BASEPRI...
for (uint_fast8_t n = 0U; n < (240U/sizeof(uint32_t)); ++n) {
NVIC_IP[n] = (QF_BASEPRI << 24U) | (QF_BASEPRI << 16U)
| (QF_BASEPRI << 8U) | QF_BASEPRI;
NVIC_IP[n] = (QF_USE_BASEPRI << 24U) | (QF_USE_BASEPRI << 16U)
| (QF_USE_BASEPRI << 8U) | QF_USE_BASEPRI;
}
#endif //--------- ARMv7-M or higher
#endif //--------- use BASEPRI for critical section
#ifdef __ARM_FP //--------- if VFP available...
// make sure that the FPU is enabled by setting CP10 & CP11 Full Access

View File

@ -1,5 +1,5 @@
//============================================================================
// QP configuration file (QV on ARM Cortex-M)
// QP configuration file (QV/QK/QXK on ARM Cortex-R)
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
@ -59,19 +59,19 @@
// <i> * Hard-limits for all loops
// <i> * Memory Isolation by means of Memory Protection Unit (MPU)
// <c3>Disable QP FuSa in development
// <c3>Disable QP FuSa in development (NOT recommended)
// <i>Disable assertions and other self monitoring features
// <i>in development build configurations (NDEBUG undefined).
// <i>VIOLATES functional safety standards. NOT recommended !!!
// <i>NOTE: Disabling safety *violates* functional safety standards.
//#ifndef NDEBUG
//#define Q_UNSAFE
//#endif
// </c>
// <c3>Disable QP FuSa in production release
// <i>Disable assertions and other self monitoring features
// <c3>Disable QP FuSa in production release (NOT recommended)
// <i>Disable assertions and other safety features
// <i>in the release build configurations (NDEBUG defined).
// <i>VIOLATES functional safety standards. NOT recommended !!!
// <i>NOTE: Disabling safety *violates* functional safety standards.
//#ifdef NDEBUG
//#define Q_UNSAFE
//#endif
@ -80,7 +80,7 @@
// </h>
//..........................................................................
// <h>QEP Event Processor
// <h>QEP Event Processor (Events)
// <i>Events and state machines.
// <o>Event signal size (Q_SIGNAL_SIZE)
@ -94,7 +94,7 @@
// </h>
//..........................................................................
// <h>QF Framework
// <h>QF Framework (Active Objects)
// <i>Active Object framework
// <o>Maximum # Active Objects (QF_MAX_ACTIVE) <1-64>
@ -120,21 +120,6 @@
// <i>Default: 1
#define QF_MAX_TICK_RATE 1U
// <c1>Event parameter initialization (QEVT_PAR_INIT)
// <i>Resource Acquisition Is Initialization (RAII) for dynamic events
//#define QEVT_PAR_INIT
// </c>
// <c1>Provide destructors for QP classes
// <i>Destructors for classes
//#define Q_XTOR
// </c>
// <c1>Active Object stop API (QACTIVE_CAN_STOP)
// <i>Enable Active Object stop API (Not recommended)
//#define QACTIVE_CAN_STOP
// </c>
// <o>Event size (QF_EVENT_SIZ_SIZE)
// <1U=>1
// <2U=>2 (default)
@ -174,15 +159,50 @@
// <i>Default: 2 (64K bytes maximum block size)
#define QF_MPOOL_SIZ_SIZE 2U
// <c2>Enable event parameter initialization (QEVT_PAR_INIT)
// <i>Initialize parameters of dynamic events at allocation
// <i>(Resource Acquisition Is Initialization (RAII) for dynamic events)
//#define QEVT_PAR_INIT
// </c>
// <c1>Provide destructors for QP classes
// <i>Presence of destructors pulls in the C++ delete() opeator
// <i>NOTE: Not recommended
//#define Q_XTOR
// </c>
// <c1>Enable active object stop API (QACTIVE_CAN_STOP)
// <i>NOTE: Not recommended
//#define QACTIVE_CAN_STOP
// </c>
// <c1>Enable context switch callback *without* QS (QF_ON_CONTEXT_SW)
// <i>Context switch callback QF_onContextSw() when Q_SPY is undefined.
//#ifndef Q_SPY
//#define QF_ON_CONTEXT_SW
//#endif
// </c>
// <c1>Enable context switch callback *with* QS (QF_ON_CONTEXT_SW)
// <i>Context switch callback QF_onContextSw() when Q_SPY is defined.
//#ifdef Q_SPY
//#define QF_ON_CONTEXT_SW
//#endif
// </c>
// <c2>Enable memory isolation (QF_MEM_ISOLATE)
// <i>Memory isolation (requires MPU)
// <i>NOTE: implies QF_ON_CONTEXT_SW.
//#define QF_MEM_ISOLATE
// </c>
// </h>
//..........................................................................
// <h>QS Software Tracing
// <h>QS Software Tracing (Q_SPY)
// <i>Target-resident component of QP/Spy software tracing system
// <i>(tracing instrumentation and command-input).
// <n>NOTE: Requires command-line macro: Q_SPY
// <i>The QS software tracing instrumentation is activated only when
// <i>NOTE: The QS software tracing instrumentation is activated only when
// <i>the macro Q_SPY is defined on the command-line to the compiler.
// <i>Typically, Q_SPY is defined only in the "spy" build configuration.
@ -204,38 +224,6 @@
// </h>
//..........................................................................
// <h>QV Cooperative Kernel
// <i>Cooperative run-to-completion kernel.
// <h>Context switch callback (QF_ON_CONTEXT_SW)
// <c2>Context switch callback WITHOUT QS
// <i>Enable context switch callback QF_onContextSw()
// <i>When Q_SPY is undefined.
//#ifndef Q_SPY
//#define QF_ON_CONTEXT_SW
//#endif
// </c>
// <c2>Context switch callback WITH QS
// <i>Enable context switch callback QF_onContextSw()
// <i>When Q_SPY is defined.
//#ifdef Q_SPY
//#define QF_ON_CONTEXT_SW
//#endif
// </c>
// </h>
// <c2>MPU memory isolation (QF_MEM_ISOLATE)
// <i>Enable memory isolation (requires MPU)
// <i>NOTE: implies QF_ON_CONTEXT_SW.
//#define QF_MEM_ISOLATE
// </c>
// </h>
//------------- <<< end of configuration section >>> -----------------------
#endif // QP_CONFIG_HPP_

View File

@ -1,235 +0,0 @@
//============================================================================
// QP configuration file (QK on ARM Cortex-R)
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
// ------------------------
// Modern Embedded Software
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// NOTE:
// The GPL (see <www.gnu.org/licenses/gpl-3.0>) 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:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
#ifndef QP_CONFIG_HPP_
#define QP_CONFIG_HPP_
//-------- <<< Use Configuration Wizard in Context Menu >>> -----------------
// <o>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)
// <i>QP API backwards compatibility with the QP/C API version.
// <i>Lower QP_API_VERSION values enable backwards compatibility
// <i>with lower (older) QP API versions.
// <i>For example, QP_API_VERSION==691 will enable the compatibility
// <i>layer with QP version 6.9.1 and newer, but not older than 6.9.1.
// <i>QP_API_VERSION==0 enables the maximum currently supported
// <i>backwards compatibility. Conversely, QP_API_VERSION==9999 means
// <i>that no backwards compatibility layer should be enabled.
// <i>Default: 0 (All supported)
#define QP_API_VERSION 0
//..........................................................................
// <h>QP Functional Safety (FuSa) Subsystem (Q_UNSAFE)
// <i>The QP FuSa Subsystem consists of the following facilities:
// <i>- Software assertions as a recommended technique
// <i> (called Failure Assertion Programming (FAP) in IEC 61508)
// <i>- Software Self-Monitoring (SSM), which encompasses such techniques:
// <i> * Duplicate Inverse Storage for critical variables
// <i> * Memory Markers for critical objects (e.g., events)
// <i> * Hard-limits for all loops
// <i> * Memory Isolation by means of Memory Protection Unit (MPU)
// <c3>Disable QP FuSa in development
// <i>Disable assertions and other self monitoring features
// <i>in development build configurations (NDEBUG undefined).
// <i>VIOLATES functional safety standards. NOT recommended !!!
//#ifndef NDEBUG
//#define Q_UNSAFE
//#endif
// </c>
// <c3>Disable QP FuSa in production release
// <i>Disable assertions and other self monitoring features
// <i>in the release build configurations (NDEBUG defined).
// <i>VIOLATES functional safety standards. NOT recommended !!!
//#ifdef NDEBUG
//#define Q_UNSAFE
//#endif
// </c>
// </h>
//..........................................................................
// <h>QEP Event Processor
// <i>Events and state machines.
// <o>Event signal size (Q_SIGNAL_SIZE)
// <1U=>1
// <2U=>2 (default)
// <4U=>4
// <i>Size of the QEvt signal for QEP/QF [bytes]
// <i>Default: 2
#define Q_SIGNAL_SIZE 2U
// </h>
//..........................................................................
// <h>QF Framework
// <i>Active Object framework
// <o>Maximum # Active Objects (QF_MAX_ACTIVE) <1-64>
// <i>Maximum # Active Objects in the system <1..64>
// <i>Default: 32
#define QF_MAX_ACTIVE 32U
// <o>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
// <i>Maximum # Event Pools <1..15>
// <i>Default: 3
#define QF_MAX_EPOOL 3U
// <o>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
// <i>Maximum # clock tick rates for time events <1..15>
// <i>Default: 1
#define QF_MAX_TICK_RATE 1U
// <c1>Event parameter initialization (QEVT_PAR_INIT)
// <i>Resource Acquisition Is Initialization (RAII) for dynamic events
//#define QEVT_PAR_INIT
// </c>
// <c1>Provide destructors for QP classes
// <i>Destructors for classes
//#define Q_XTOR
// </c>
// <c1>Active Object stop API (QACTIVE_CAN_STOP)
// <i>Enable Active Object stop API (Not recommended)
//#define QACTIVE_CAN_STOP
// </c>
// <o>Event size (QF_EVENT_SIZ_SIZE)
// <1U=>1
// <2U=>2 (default)
// <4U=>4
// <i>Size of the dynamic events for QF [bytes]
// <i>Default: 2 (64K bytes maximum event size)
#define QF_EVENT_SIZ_SIZE 2U
// <o>Time event counter size (QF_TIMEEVT_CTR_SIZE)
// <1U=>1
// <2U=>2
// <4U=>4 (default)
// <i>Size of the QTimeEvt counter [bytes]
// <i>Default: 4 (2^32 dynamic range)
#define QF_TIMEEVT_CTR_SIZE 4U
// <o>Event queue counter size (QF_EQUEUE_CTR_SIZE)
// <1U=>1 (default)
// <2U=>2
// <i>Size of event queue counter [bytes]
// <i>Default: 1 (255 events maximum in a queue)
#define QF_EQUEUE_CTR_SIZE 1U
// <o>Memory pool counter size (QF_MPOOL_CTR_SIZE)
// <1U=>1
// <2U=>2 (default)
// <4U=>4
// <i>Size of memory pool counter [bytes]
// <i>Default: 2 (64K blocks maximum in a pool)
#define QF_MPOOL_CTR_SIZE 2U
// <o>Memory block size (QF_MPOOL_SIZ_SIZE)
// <1U=>1
// <2U=>2 (default)
// <4U=>4
// <i>Size of memory pool block [bytes]
// <i>Default: 2 (64K bytes maximum block size)
#define QF_MPOOL_SIZ_SIZE 2U
// </h>
//..........................................................................
// <h>QS Software Tracing
// <i>Target-resident component of QP/Spy software tracing system
// <i>(tracing instrumentation and command-input).
// <n>NOTE: Requires command-line macro: Q_SPY
// <i>The QS software tracing instrumentation is activated only when
// <i>the macro Q_SPY is defined on the command-line to the compiler.
// <i>Typically, Q_SPY is defined only in the "spy" build configuration.
// <o>QS timestamp size (QS_TIME_SIZE)
// <1U=>1
// <2U=>2
// <4U=>4 (default)
// <i>Size of the timestamp in QS [bytes]
// <i>Default: 4 (2^32 dynamic range)
#define QS_TIME_SIZE 4U
// <o>QS buffer counter size (QS_CTR_SIZE)
// <1U=>1
// <2U=>2 (default)
// <4U=>4
// <i>Size of the counter in the internal QS buffer [bytes]
// <i>Default: 2 (64K bytes in QS buffer)
#define QS_CTR_SIZE 2U
// </h>
//..........................................................................
// <h>QK Preemptive Non-Blocking Kernel
// <i>Preemptive non-blocking RTOS kernel.
// <h>Context switch callback (QF_ON_CONTEXT_SW)
// <c2>Context switch callback WITHOUT QS
// <i>Enable context switch callback QF_onContextSw()
// <i>When Q_SPY is undefined.
//#ifndef Q_SPY
//#define QF_ON_CONTEXT_SW
//#endif
// </c>
// <c2>Context switch callback WITH QS
// <i>Enable context switch callback QF_onContextSw()
// <i>When Q_SPY is defined.
//#ifdef Q_SPY
//#define QF_ON_CONTEXT_SW
//#endif
// </c>
// </h>
// </h>
//------------- <<< end of configuration section >>> -----------------------
#endif // QP_CONFIG_HPP_

View File

@ -27,7 +27,7 @@
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-09-30
//! @date Last updated on: 2024-11-22
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
@ -61,7 +61,7 @@
#define QF_INT_ENABLE() \
__asm volatile ("MSR cpsr_c,#(0x1F)" ::: "cc")
#define QF_INT_ENABLE_ALL() \
__asm volatile ("MSR cpsr_c,#(0x1F | 0x80 | 0x40)" ::: "cc")
__asm volatile ("MSR cpsr_c,#(0x1F)" ::: "cc")
#else
#error Incorrect CPU mode. Must be either __arm__ or __thumb__.
#endif

View File

@ -1,235 +0,0 @@
//============================================================================
// QP configuration file (QV on ARM Cortex-R)
//
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
//
// Q u a n t u m L e a P s
// ------------------------
// Modern Embedded Software
//
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
//
// The QP/C software is dual-licensed under the terms of the open-source GNU
// General Public License (GPL) or under the terms of one of the closed-
// source Quantum Leaps commercial licenses.
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// NOTE:
// The GPL (see <www.gnu.org/licenses/gpl-3.0>) 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:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
#ifndef QP_CONFIG_HPP_
#define QP_CONFIG_HPP_
//-------- <<< Use Configuration Wizard in Context Menu >>> -----------------
// <o>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)
// <i>QP API backwards compatibility with the QP/C API version.
// <i>Lower QP_API_VERSION values enable backwards compatibility
// <i>with lower (older) QP API versions.
// <i>For example, QP_API_VERSION==691 will enable the compatibility
// <i>layer with QP version 6.9.1 and newer, but not older than 6.9.1.
// <i>QP_API_VERSION==0 enables the maximum currently supported
// <i>backwards compatibility. Conversely, QP_API_VERSION==9999 means
// <i>that no backwards compatibility layer should be enabled.
// <i>Default: 0 (All supported)
#define QP_API_VERSION 0
//..........................................................................
// <h>QP Functional Safety (FuSa) Subsystem (Q_UNSAFE)
// <i>The QP FuSa Subsystem consists of the following facilities:
// <i>- Software assertions as a recommended technique
// <i> (called Failure Assertion Programming (FAP) in IEC 61508)
// <i>- Software Self-Monitoring (SSM), which encompasses such techniques:
// <i> * Duplicate Inverse Storage for critical variables
// <i> * Memory Markers for critical objects (e.g., events)
// <i> * Hard-limits for all loops
// <i> * Memory Isolation by means of Memory Protection Unit (MPU)
// <c3>Disable QP FuSa in development
// <i>Disable assertions and other self monitoring features
// <i>in development build configurations (NDEBUG undefined).
// <i>VIOLATES functional safety standards. NOT recommended !!!
//#ifndef NDEBUG
//#define Q_UNSAFE
//#endif
// </c>
// <c3>Disable QP FuSa in production release
// <i>Disable assertions and other self monitoring features
// <i>in the release build configurations (NDEBUG defined).
// <i>VIOLATES functional safety standards. NOT recommended !!!
//#ifdef NDEBUG
//#define Q_UNSAFE
//#endif
// </c>
// </h>
//..........................................................................
// <h>QEP Event Processor
// <i>Events and state machines.
// <o>Event signal size (Q_SIGNAL_SIZE)
// <1U=>1
// <2U=>2 (default)
// <4U=>4
// <i>Size of the QEvt signal for QEP/QF [bytes]
// <i>Default: 2
#define Q_SIGNAL_SIZE 2U
// </h>
//..........................................................................
// <h>QF Framework
// <i>Active Object framework
// <o>Maximum # Active Objects (QF_MAX_ACTIVE) <1-64>
// <i>Maximum # Active Objects in the system <1..64>
// <i>Default: 32
#define QF_MAX_ACTIVE 32U
// <o>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
// <i>Maximum # Event Pools <1..15>
// <i>Default: 3
#define QF_MAX_EPOOL 3U
// <o>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
// <i>Maximum # clock tick rates for time events <1..15>
// <i>Default: 1
#define QF_MAX_TICK_RATE 1U
// <c1>Event parameter initialization (QEVT_PAR_INIT)
// <i>Resource Acquisition Is Initialization (RAII) for dynamic events
//#define QEVT_PAR_INIT
// </c>
// <c1>Provide destructors for QP classes
// <i>Destructors for classes
//#define Q_XTOR
// </c>
// <c1>Active Object stop API (QACTIVE_CAN_STOP)
// <i>Enable Active Object stop API (Not recommended)
//#define QACTIVE_CAN_STOP
// </c>
// <o>Event size (QF_EVENT_SIZ_SIZE)
// <1U=>1
// <2U=>2 (default)
// <4U=>4
// <i>Size of the dynamic events for QF [bytes]
// <i>Default: 2 (64K bytes maximum event size)
#define QF_EVENT_SIZ_SIZE 2U
// <o>Time event counter size (QF_TIMEEVT_CTR_SIZE)
// <1U=>1
// <2U=>2
// <4U=>4 (default)
// <i>Size of the QTimeEvt counter [bytes]
// <i>Default: 4 (2^32 dynamic range)
#define QF_TIMEEVT_CTR_SIZE 4U
// <o>Event queue counter size (QF_EQUEUE_CTR_SIZE)
// <1U=>1 (default)
// <2U=>2
// <i>Size of event queue counter [bytes]
// <i>Default: 1 (255 events maximum in a queue)
#define QF_EQUEUE_CTR_SIZE 1U
// <o>Memory pool counter size (QF_MPOOL_CTR_SIZE)
// <1U=>1
// <2U=>2 (default)
// <4U=>4
// <i>Size of memory pool counter [bytes]
// <i>Default: 2 (64K blocks maximum in a pool)
#define QF_MPOOL_CTR_SIZE 2U
// <o>Memory block size (QF_MPOOL_SIZ_SIZE)
// <1U=>1
// <2U=>2 (default)
// <4U=>4
// <i>Size of memory pool block [bytes]
// <i>Default: 2 (64K bytes maximum block size)
#define QF_MPOOL_SIZ_SIZE 2U
// </h>
//..........................................................................
// <h>QS Software Tracing
// <i>Target-resident component of QP/Spy software tracing system
// <i>(tracing instrumentation and command-input).
// <n>NOTE: Requires command-line macro: Q_SPY
// <i>The QS software tracing instrumentation is activated only when
// <i>the macro Q_SPY is defined on the command-line to the compiler.
// <i>Typically, Q_SPY is defined only in the "spy" build configuration.
// <o>QS timestamp size (QS_TIME_SIZE)
// <1U=>1
// <2U=>2
// <4U=>4 (default)
// <i>Size of the timestamp in QS [bytes]
// <i>Default: 4 (2^32 dynamic range)
#define QS_TIME_SIZE 4U
// <o>QS buffer counter size (QS_CTR_SIZE)
// <1U=>1
// <2U=>2 (default)
// <4U=>4
// <i>Size of the counter in the internal QS buffer [bytes]
// <i>Default: 2 (64K bytes in QS buffer)
#define QS_CTR_SIZE 2U
// </h>
//..........................................................................
// <h>QV Cooperative Kernel
// <i>Cooperative run-to-completion RTOS kernel.
// <h>Context switch callback (QF_ON_CONTEXT_SW)
// <c2>Context switch callback WITHOUT QS
// <i>Enable context switch callback QF_onContextSw()
// <i>When Q_SPY is undefined.
//#ifndef Q_SPY
//#define QF_ON_CONTEXT_SW
//#endif
// </c>
// <c2>Context switch callback WITH QS
// <i>Enable context switch callback QF_onContextSw()
// <i>When Q_SPY is defined.
//#ifdef Q_SPY
//#define QF_ON_CONTEXT_SW
//#endif
// </c>
// </h>
// </h>
//------------- <<< end of configuration section >>> -----------------------
#endif // QP_CONFIG_HPP_

View File

@ -27,7 +27,7 @@
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @date Last updated on: 2024-09-30
//! @date Last updated on: 2024-11-22
//! @version Last updated for: @ref qpcpp_8_0_0
//!
//! @file
@ -61,7 +61,7 @@
#define QF_INT_ENABLE() \
__asm volatile ("MSR cpsr_c,#(0x1F)" ::: "cc")
#define QF_INT_ENABLE_ALL() \
__asm volatile ("MSR cpsr_c,#(0x1F | 0x80 | 0x40)" ::: "cc")
__asm volatile ("MSR cpsr_c,#(0x1F)" ::: "cc")
#else
#error Incorrect CPU mode. Must be either __arm__ or __thumb__.
#endif

View File

@ -59,19 +59,19 @@
// <i> * Hard-limits for all loops
// <i> * Memory Isolation by means of Memory Protection Unit (MPU)
// <c3>Disable QP FuSa in development
// <c3>Disable QP FuSa in development (NOT recommended)
// <i>Disable assertions and other self monitoring features
// <i>in development build configurations (NDEBUG undefined).
// <i>VIOLATES functional safety standards. NOT recommended !!!
// <i>NOTE: Disabling safety *violates* functional safety standards.
//#ifndef NDEBUG
//#define Q_UNSAFE
//#endif
// </c>
// <c3>Disable QP FuSa in production release
// <i>Disable assertions and other self monitoring features
// <c3>Disable QP FuSa in production release (NOT recommended)
// <i>Disable assertions and other safety features
// <i>in the release build configurations (NDEBUG defined).
// <i>VIOLATES functional safety standards. NOT recommended !!!
// <i>NOTE: Disabling safety *violates* functional safety standards.
//#ifdef NDEBUG
//#define Q_UNSAFE
//#endif
@ -80,7 +80,7 @@
// </h>
//..........................................................................
// <h>QEP Event Processor
// <h>QEP Event Processor (Events)
// <i>Events and state machines.
// <o>Event signal size (Q_SIGNAL_SIZE)
@ -94,7 +94,7 @@
// </h>
//..........................................................................
// <h>QF Framework
// <h>QF Framework (Active Objects)
// <i>Active Object framework
// <o>Maximum # Active Objects (QF_MAX_ACTIVE) <1-64>
@ -120,21 +120,6 @@
// <i>Default: 1
#define QF_MAX_TICK_RATE 1U
// <c1>Event parameter initialization (QEVT_PAR_INIT)
// <i>Resource Acquisition Is Initialization (RAII) for dynamic events
//#define QEVT_PAR_INIT
// </c>
// <c1>Provide destructors for QP classes
// <i>Destructors for classes
//#define Q_XTOR
// </c>
// <c1>Active Object stop API (QACTIVE_CAN_STOP)
// <i>Enable Active Object stop API (Not recommended)
//#define QACTIVE_CAN_STOP
// </c>
// <o>Event size (QF_EVENT_SIZ_SIZE)
// <1U=>1
// <2U=>2 (default)
@ -174,15 +159,50 @@
// <i>Default: 2 (64K bytes maximum block size)
#define QF_MPOOL_SIZ_SIZE 2U
// <c2>Enable event parameter initialization (QEVT_PAR_INIT)
// <i>Initialize parameters of dynamic events at allocation
// <i>(Resource Acquisition Is Initialization (RAII) for dynamic events)
//#define QEVT_PAR_INIT
// </c>
// <c1>Provide destructors for QP classes
// <i>Presence of destructors pulls in the C++ delete() opeator
// <i>NOTE: Not recommended
//#define Q_XTOR
// </c>
// <c1>Enable active object stop API (QACTIVE_CAN_STOP)
// <i>NOTE: Not recommended
//#define QACTIVE_CAN_STOP
// </c>
// <c1>Enable context switch callback *without* QS (QF_ON_CONTEXT_SW)
// <i>Context switch callback QF_onContextSw() when Q_SPY is undefined.
//#ifndef Q_SPY
//#define QF_ON_CONTEXT_SW
//#endif
// </c>
// <c1>Enable context switch callback *with* QS (QF_ON_CONTEXT_SW)
// <i>Context switch callback QF_onContextSw() when Q_SPY is defined.
//#ifdef Q_SPY
//#define QF_ON_CONTEXT_SW
//#endif
// </c>
// <c2>Enable memory isolation (QF_MEM_ISOLATE)
// <i>Memory isolation (requires MPU)
// <i>NOTE: implies QF_ON_CONTEXT_SW.
//#define QF_MEM_ISOLATE
// </c>
// </h>
//..........................................................................
// <h>QS Software Tracing
// <h>QS Software Tracing (Q_SPY)
// <i>Target-resident component of QP/Spy software tracing system
// <i>(tracing instrumentation and command-input).
// <n>NOTE: Requires command-line macro: Q_SPY
// <i>The QS software tracing instrumentation is activated only when
// <i>NOTE: The QS software tracing instrumentation is activated only when
// <i>the macro Q_SPY is defined on the command-line to the compiler.
// <i>Typically, Q_SPY is defined only in the "spy" build configuration.

View File

@ -3431,12 +3431,12 @@ QF_CRIT_EXIT();</code>
<specifiers>noexcept</specifiers>
<!--${QF::QTimeEvt::noActive::tickRate}-->
<parameter name="tickRate" type="std::uint_fast8_t const"/>
<code>QF_CRIT_STAT
QF_CRIT_ENTRY();
<code>// NOTE: this function must be called *inside* critical section
Q_REQUIRE_INCRIT(900, tickRate &lt; QF_MAX_TICK_RATE);
QF_CRIT_EXIT();
bool inactive;
QF_MEM_SYS();
if (timeEvtHead_[tickRate].m_next != nullptr) {
inactive = false;
}
@ -3446,6 +3446,8 @@ else if (timeEvtHead_[tickRate].m_act != nullptr) {
else {
inactive = true;
}
QF_MEM_APP();
return inactive;</code>
</operation>
<!--${QF::QTimeEvt::toActive}-->
@ -5840,9 +5842,9 @@ QF_onContextSw(QP::QActive::registry_[pprev], a);
#define QP_HPP_
//============================================================================
#define QP_VERSION_STR &quot;8.0.0&quot;
#define QP_VERSION 800U
#define QP_RELEASE 0x7055936FU
#define QP_VERSION_STR &quot;8.0.1&quot;
#define QP_VERSION 801U
#define QP_RELEASE 0x703931CEU
//============================================================================
//! @cond INTERNAL
@ -6299,7 +6301,6 @@ using char_t = char;
<file name="qep_hsm.cpp">
<text>#define QP_IMPL // this is QP implementation
#include &quot;qp_port.hpp&quot; // QP port
#include &quot;qp_pkg.hpp&quot; // QP package-scope interface
#include &quot;qsafe.h&quot; // QP Functional Safety (FuSa) Subsystem
#ifdef Q_SPY // QS software tracing enabled?
#include &quot;qs_port.hpp&quot; // QS port
@ -6367,7 +6368,6 @@ $define ${QEP::QHsm}</text>
<file name="qep_msm.cpp">
<text>#define QP_IMPL // this is QP implementation
#include &quot;qp_port.hpp&quot; // QP port
#include &quot;qp_pkg.hpp&quot; // QP package-scope interface
#include &quot;qsafe.h&quot; // QP Functional Safety (FuSa) Subsystem
#ifdef Q_SPY // QS software tracing enabled?
#include &quot;qs_port.hpp&quot; // QS port

View File

@ -1,18 +1,21 @@
a37f690d75dac83d45b5da3082d28f188191fd9a *qpcpp.qm
bda783a346fb750c7a1fe32dc0a8ca52609cb5f4 *qpcpp.qm
46578fc304c597329289978acee1027c8c533335 *include/qequeue.hpp
1a8e0b05536b89c1cd3806782ae1a21dd4ceca69 *include/qk.hpp
cb1c39aabacb619060924356f7c8e900686538e0 *include/qmpool.hpp
e0d974faef6b60cc455e49abb32d43128b8c79cf *include/qp.hpp
559a9ca895f97f38c5d3bb0511675f321e041911 *include/qp.hpp
bf47a939e525fa575673f89b8106bcee166240a2 *include/qp_pkg.hpp
e5b0d14c9e6994b82a5cd9200bde46bd179bfb20 *include/qpcpp.hpp
d4f14d2ed18ef725ea17d0a97b78ae22a283c96b *include/qs.hpp
88220a7d892fee54053b467b596dc6b536aaf8be *include/qs_dummy.hpp
9694f10e44d53563599410d37dd1c5a19cf1788b *include/qs_pkg.hpp
49d2620b0afa9e74d73680495c3e8a931e5d8f73 *include/qsafe.h
09e9ffe95120ba17a49d7039b5316f2614710dab *include/qstamp.hpp
73749ed396bbc0419971769a47069448c8136960 *include/qv.hpp
05b617dad20f07f07b64dccf84f9b7cd9b8d2bb7 *include/qxk.hpp
0199f3eeb6c02b8cc890ee4c6f6d344569a0858f *include/README.md
71899ce74eeb04f333ed00d53f87719f722a39ab *src/qf/CMakeLists.txt
81b54ca9a4dff44d24c0f3cd687aaa58afe634ab *src/qf/qep_hsm.cpp
13cb63db437dd4f176dd846eda49bda9827ca571 *src/qf/qep_msm.cpp
864d627f2600987a2194c57093e1f210e0de2a7a *src/qf/qep_hsm.cpp
d3242def2b23df5b9704bb3b0411fd01de6c0a67 *src/qf/qep_msm.cpp
62f87a60d04e1c98f40162a166ec14a1f2f1252f *src/qf/qf_act.cpp
07671fb85e9b2492b0ea37b853d7e0eea42bf637 *src/qf/qf_actq.cpp
ed83f5f8b3533cc97ffc2a85aeeb63f29b4f1dd8 *src/qf/qf_defer.cpp
@ -22,41 +25,58 @@ ef51e4840107b0ed6ec97e170ac2689e1b1fdb95 *src/qf/qf_ps.cpp
08b490d7505a7ff6fe493058975eb9f0a82daa3d *src/qf/qf_qact.cpp
23892cde4fd7226e899026884e07b01e32d0aef4 *src/qf/qf_qeq.cpp
5fc4874b74779641454e2d8e7960a5bf3d130115 *src/qf/qf_qmact.cpp
7aedf35884943f3add9f39e57e5ea4ad7344d110 *src/qf/qf_time.cpp
04dd9fbddc336f096bd214f8e7368d7a6dce43c8 *src/qf/qf_time.cpp
7cdab433e81612862fd27f0cf792d38e1197d064 *src/qk/CMakeLists.txt
1be4743dc14186779abb96b4bd16ba9a99d3314d *src/qk/qk.cpp
eb28260d471fc752ca54b2c1e2d763f28432c2c1 *src/qs/CMakeLists.txt
66fd2a553c8ae6709dfe286b6ccce002208251f1 *src/qs/qs.cpp
2ca73a0d38dd7b544864d72fd337f29c7dae2a85 *src/qs/qs_64bit.cpp
349c18625bd2cceda297e1c98a85a9fa9538cef9 *src/qs/qs_fp.cpp
ad4e3a9faacc038cb51a7773ffc42903be947a22 *src/qs/qs_rx.cpp
8008d9c24757b2bb02e85123aa89a3a33090921d *src/qs/qstamp.cpp
92338453dc612419b0e16e0560e761312d0f3900 *src/qs/qutest.cpp
b6d93a16f5b176d3da4888a7efb265730337f46d *src/qv/CMakeLists.txt
f530563e062ff7ea84763f6e799bf4ca1cb73054 *src/qv/qv.cpp
8456ce45995423dd872685229539618abaa9c580 *ports/arm-cm/qk/armclang/qk_port.cpp
94a289a5f900afaeb47b5454824bc4911df8014f *ports/arm-cm/qk/armclang/qp_port.hpp
2d0c3d3d93e4d4ac8e2218b9ed68e6269b02419e *src/qxk/qxk.cpp
e0e633a980e4c04a85f877e810ce77ad51903e87 *src/qxk/qxk_mutex.cpp
8e15812d14f250866dfa8a96fe5b14638ca2c4ae *src/qxk/qxk_sema.cpp
58e6a9354a1c7c4d53204b7ad2fad05d6eb3117c *src/qxk/qxk_xthr.cpp
81f1a6dbcebd0b5df9e437902ffbe0fecdd03d25 *ports/arm-cm/qk/armclang/qk_port.cpp
7119fc94c0b5560ab8e3197a83917667e311e415 *ports/arm-cm/qk/armclang/qp_port.hpp
5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qk/armclang/qs_port.hpp
fafeded481e004677bfa6eb7cce7e4c4dbd5fd2f *ports/arm-cm/qk/config/qp_config.hpp
f94a3fb033b87de04efec19e25c5630b82e9d749 *ports/arm-cm/qk/gnu/qk_port.cpp
1c35b7f6a992d0a4755080903d2a2fd5aa06c923 *ports/arm-cm/qk/gnu/qp_port.hpp
5f2353117f9940b0ea891d2e0bd486e0d024b67c *ports/arm-cm/qk/gnu/qk_port.cpp
7119fc94c0b5560ab8e3197a83917667e311e415 *ports/arm-cm/qk/gnu/qp_port.hpp
5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qk/gnu/qs_port.hpp
f52bee74512d5c2016eaf20996eee10e52a5d71f *ports/arm-cm/qk/iar/qk_port.cpp
458994edab3235f9d9a9faf78485ecb4edc3bdd1 *ports/arm-cm/qk/iar/qp_port.hpp
2b9c1112e3e5be79ce2b1799adfd5e812467765b *ports/arm-cm/qk/iar/qk_port.cpp
f54416674c33ffd19408f02af60f7d69b8613797 *ports/arm-cm/qk/iar/qp_port.hpp
5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qk/iar/qs_port.hpp
f59663361efec401c02436eabfe6931729d98b1d *ports/arm-cm/qv/armclang/qp_port.hpp
9cc71aed12d57408252019035aff449ce028372c *ports/arm-cm/qv/armclang/qp_port.hpp
5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qv/armclang/qs_port.hpp
c225966c8601a651196e3e30af7d0dce6079d610 *ports/arm-cm/qv/armclang/qv_port.cpp
d7f22b95fc3b2228a669c5b9167bc3021156a8c7 *ports/arm-cm/qv/config/qp_config.hpp
fffed0cc5c1180df7550f579268ab7c528f3afda *ports/arm-cm/qv/gnu/qp_port.hpp
90b14adcd8f8b29de3358073c39bd4161f5ce2eb *ports/arm-cm/qv/armclang/qv_port.cpp
bed3687b29555f6fa9c721cf34a098218f64e1ad *ports/arm-cm/qv/gnu/qp_port.hpp
5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qv/gnu/qs_port.hpp
bd87c7c78142119968ae65dda01ba75b3170ca08 *ports/arm-cm/qv/gnu/qv_port.cpp
cf46244c7dfb6185f2c01cfdba4d699bf01388e7 *ports/arm-cm/qv/iar/qp_port.hpp
b2d5e72b65813bdc37bcab3c8cd9107bda009131 *ports/arm-cm/qv/gnu/qv_port.cpp
424864680661227e4ab418b2af905d4bd92767ad *ports/arm-cm/qv/iar/qp_port.hpp
5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qv/iar/qs_port.hpp
421f4bc740a150dae18672f22633bef822119071 *ports/arm-cm/qv/iar/qv_port.cpp
7341172192afc119dc3188b51e64b6cb33dc4f23 *ports/arm-cr/qk/config/qp_config.hpp
53378c89dd07cdf1b5fc1428938a2bf33ef9c897 *ports/arm-cr/qk/gnu/qp_port.hpp
15fb0660dff33295bad38facfc7aacca928133a3 *ports/arm-cm/qv/iar/qv_port.cpp
9e248cb426d8495e5cd677ff79cd3b9ced2a76a5 *ports/arm-cm/qxk/armclang/qp_port.hpp
5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qxk/armclang/qs_port.hpp
16423aebab91be16d8c2c7b128d8494709a6a746 *ports/arm-cm/qxk/armclang/qxk_port.cpp
9ec8ed9717f9130b23252d2c381f779617165932 *ports/arm-cm/qxk/gnu/qp_port.hpp
5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qxk/gnu/qs_port.hpp
75fc7a6c1b0775832f3e0e0e2bbacc19f56ddc94 *ports/arm-cm/qxk/gnu/qxk_port.cpp
f40b0ea4761d187ac7d4460a161efb9b4f3e6ef6 *ports/arm-cm/qxk/iar/qp_port.hpp
5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qxk/iar/qs_port.hpp
44509ff079ba173a28076f3fa1488582a6ef48a1 *ports/arm-cm/qxk/iar/qxk_port.cpp
69256fd1a5b81db3e3174cba9196bf9da925e098 *ports/arm-cm/qutest/qp_port.hpp
5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qutest/qs_port.hpp
1194c26fdfc9665a04cc3d01e6de49afe1698376 *ports/arm-cr/qk/gnu/qp_port.hpp
5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cr/qk/gnu/qs_port.hpp
a8f4351725564e449206909176d09bc58cd6f45d *ports/arm-cr/qk/iar/qp_port.hpp
5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cr/qk/iar/qs_port.hpp
7203200deaa5dbb4746434d4a3d79a160d4ccf4b *ports/arm-cr/qk/ti/qp_port.hpp
5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cr/qk/ti/qs_port.hpp
b79ee5fda27709554b5dbdc3162d59787af85ecb *ports/arm-cr/qv/gnu/qp_port.hpp
fd3e4b882efb671f2522ae83bfde016ea416d4a7 *ports/arm-cr/qv/gnu/qp_port.hpp
5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cr/qv/gnu/qs_port.hpp
fafbe56ae4266a412cb1b6db6e146fbfe5022b4a *ports/arm-cr/qv/iar/qp_port.hpp
5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cr/qv/iar/qs_port.hpp
@ -68,7 +88,7 @@ bc080e68d0edfc28da2df882ed3661cf99f2942c *ports/msp430/qk/qp_port.hpp
197ec45394793b79a29afe5bb31b6de1ad78ad00 *ports/msp430/qv/qs_port.hpp
650f628d87a39c559a87c6f849c58fb9a8e777a7 *ports/msp430/qutest/qp_port.hpp
197ec45394793b79a29afe5bb31b6de1ad78ad00 *ports/msp430/qutest/qs_port.hpp
59011c6a3cbf07a38f1a74139cef1a82f22cc475 *ports/config/qp_config.hpp
8614593b911e6db6f634d972e79093e964756556 *ports/config/qp_config.hpp
b6b5d23c618976a6fbed51dc5a13e227928e1d4b *ports/embos/CMakeLists.txt
0b5ad806f47800c1481c9af3d88c1bff3cb1d784 *ports/embos/qf_port.cpp
5e28aa0e89239f970e4b5e85be4e5c3b6a34dd69 *ports/embos/qp_port.hpp
@ -103,6 +123,11 @@ f458af1511007d6ba2a4a0a0e40d74e03719ceb1 *ports/posix-qv/qp_port.hpp
f38e2f9bfe4df4d44a8f9a5fa2c0b2dfd79f35ae *ports/posix-qv/qs_port.hpp
e2e295c371bc14f0089a888b07d98c657dea07bf *ports/posix-qv/README.md
7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/posix-qv/safe_std.h
c9969a454b540a3b1abd3dd5cc46fb211663310e *ports/posix-qutest/CMakeLists.txt
edfa2baff22735f98a094e315db11c40ed07e5e8 *ports/posix-qutest/qp_port.hpp
f38e2f9bfe4df4d44a8f9a5fa2c0b2dfd79f35ae *ports/posix-qutest/qs_port.hpp
772fdcf6a4ca3e3303016384de92874ec06c11fe *ports/posix-qutest/qutest_port.cpp
7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/posix-qutest/safe_std.h
06b76c6c30ea880876b47ee27115178ff62ea66b *ports/win32/CMakeLists.txt
48dfd18fce993f237138d5d99f2fb0e385efbe93 *ports/win32/qf_port.cpp
ea88910c991455756433cff5338a62ed3d181bf2 *ports/win32/qp_port.hpp
@ -121,6 +146,11 @@ f38e2f9bfe4df4d44a8f9a5fa2c0b2dfd79f35ae *ports/win32-qv/qs_port.hpp
ddc62932b46bbc0ad147193d0dd7efa28127c6c4 *ports/win32-qv/qwin_gui.h
ddd27415c3d1df6d8c210966e8915c407b15bf58 *ports/win32-qv/README.md
7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/win32-qv/safe_std.h
3c23c06f425a8d8dbb18d1f191ac6cab483a8e51 *ports/win32-qutest/CMakeLists.txt
edfa2baff22735f98a094e315db11c40ed07e5e8 *ports/win32-qutest/qp_port.hpp
f38e2f9bfe4df4d44a8f9a5fa2c0b2dfd79f35ae *ports/win32-qutest/qs_port.hpp
5bda26c8c82914e6cc16685e4adc02cbc32c5291 *ports/win32-qutest/qutest_port.cpp
7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/win32-qutest/safe_std.h
76dd9078dc4311d53d3862d44177a8660258da6d *zephyr/CMakeLists.txt
36a0252cf0bfd6be0d345c48c00b2300f8917f05 *zephyr/Kconfig
2eb2a922e18b4760a68151ebee1b6282d20b4692 *zephyr/module.yml

View File

@ -1,18 +1,20 @@
@setlocal
set VERSION=8.0.1
:: usage
@echo Usage: qppcp_sha1 [gen]
@echo examples:
@echo qppcp_sha1 : check the sha1 sums in the file qpcpp.sha1
@echo qpcpp_sha1 gen : generate the sha1 file qpcpp.sha1
@echo qppcp_sha1 : check the sha1 sums in the file qpcpp_%VERSION%.sha1
@echo qpcpp_sha1 gen : generate the sha1 file qpcpp_%VERSION%.sha1
@echo.
@if NOT "%1"=="gen" (
sha1sum --check --warn qpcpp.sha1
sha1sum --check --warn qpcpp_%VERSION%.sha1
goto end
)
@echo generating qpcpp.sha1...
@echo generating qpcpp_%VERSION%.sha1...
@sha1sum qpcpp.qm ^
include/* ^
src/qf/* src/qk/* src/qs/* src/qv/* src/qxk/* ^
@ -33,7 +35,7 @@ goto end
ports/posix/* ports/posix-qv/* ports/posix-qutest/* ^
ports/win32/* ports/win32-qv/* ports/win32-qutest/* ^
zephyr/* ^
> qpcpp.sha1
> qpcpp_%VERSION%.sha1
@echo done
:end

View File

@ -1,7 +1,7 @@
# qpcpp/src
add_subdirectory(qf)
add_subdirectory(qs)
if(${PORT} IN_LIST QPC_BAREMETAL_PORTS)
if(${PORT} IN_LIST QPCPP_BAREMETAL_PORTS)
message(STATUS "adding subdir '${KERNEL}' for port '${PORT}'")
add_subdirectory(${KERNEL})
endif()

View File

@ -34,7 +34,6 @@
//$endhead${src::qf::qep_hsm.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#define QP_IMPL // this is QP implementation
#include "qp_port.hpp" // QP port
#include "qp_pkg.hpp" // QP package-scope interface
#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
#ifdef Q_SPY // QS software tracing enabled?
#include "qs_port.hpp" // QS port

View File

@ -34,7 +34,6 @@
//$endhead${src::qf::qep_msm.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#define QP_IMPL // this is QP implementation
#include "qp_port.hpp" // QP port
#include "qp_pkg.hpp" // QP package-scope interface
#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
#ifdef Q_SPY // QS software tracing enabled?
#include "qs_port.hpp" // QS port

View File

@ -519,12 +519,12 @@ void QTimeEvt::tick(
//${QF::QTimeEvt::noActive} ..................................................
bool QTimeEvt::noActive(std::uint_fast8_t const tickRate) noexcept {
QF_CRIT_STAT
QF_CRIT_ENTRY();
// NOTE: this function must be called *inside* critical section
Q_REQUIRE_INCRIT(900, tickRate < QF_MAX_TICK_RATE);
QF_CRIT_EXIT();
bool inactive;
QF_MEM_SYS();
if (timeEvtHead_[tickRate].m_next != nullptr) {
inactive = false;
}
@ -534,6 +534,8 @@ bool QTimeEvt::noActive(std::uint_fast8_t const tickRate) noexcept {
else {
inactive = true;
}
QF_MEM_APP();
return inactive;
}