mirror of
https://github.com/QuantumLeaps/qpc.git
synced 2025-01-14 06:43:19 +08:00
8.0.1
added missing <pthread.h> to ports/posix/qp_port.h changed ports to ARM-CM, BASEPRI critical section updated qp_config.h files updated examples fixed arm-cr ports, GNU compiler, ARM mode, QF_INT_ENABLE_ALL() macro
This commit is contained in:
parent
aaa2b2447a
commit
12c924a156
@ -76,7 +76,7 @@ This file is situated in the root directory of qpc. It performs a pre-initializa
|
||||
+ `arm-cm`, `arm-cr` - Arm CortexM or CortexR micro controllers. Tested with GNU cross compiler environments.
|
||||
+ `freertos`, `esp-idf`, `emb-os`, `threadx`, `uc-os2` - real time OS
|
||||
+ `msp430`, `pic32` - TI MSP430 or PIC32 micro controllers
|
||||
+ `riscv`- Risc V µC
|
||||
+ `riscv`- Risc V micro controllers
|
||||
+ `qep-only`, `qube` - test environments
|
||||
+ `win32`, `posix` - host environments MS Winows, Linux (Posix compatible systems)
|
||||
* `QPC-CFG-GUI` - BOOL: set this boolean variable to ON/TRUE, if GUI support (win32) shall be compiled in. Default: OFF
|
||||
|
2
examples
2
examples
@ -1 +1 @@
|
||||
Subproject commit 45b3d03705750696b3281790ed2ab2b0bbf560e1
|
||||
Subproject commit 81a03923724160d56faa0096823c941a3601d68e
|
18
include/qp.h
18
include/qp.h
@ -36,9 +36,9 @@
|
||||
#define QP_H_
|
||||
|
||||
//============================================================================
|
||||
#define QP_VERSION_STR "8.0.0"
|
||||
#define QP_VERSION 800U
|
||||
#define QP_RELEASE 0x7055936FU
|
||||
#define QP_VERSION_STR "8.0.1"
|
||||
#define QP_VERSION 801U
|
||||
#define QP_RELEASE 0x703931CEU
|
||||
|
||||
//============================================================================
|
||||
//! @cond INTERNAL
|
||||
@ -434,18 +434,14 @@ QState QMsm_enterHistory_(
|
||||
|
||||
//${QEP-macros::QASM_INIT} ...................................................
|
||||
#ifdef Q_SPY
|
||||
#define QASM_INIT(me_, par_, qsId_) do { \
|
||||
Q_ASSERT(((QAsm *)(me_))->vptr); \
|
||||
(*((QAsm *)(me_))->vptr->init)((QAsm *)(me_), (par_), (qsId_)); \
|
||||
} while (false)
|
||||
#define QASM_INIT(me_, par_, qsId_) \
|
||||
(*((QAsm *)(me_))->vptr->init)((QAsm *)(me_), (par_), (qsId_))
|
||||
#endif // def Q_SPY
|
||||
|
||||
//${QEP-macros::QASM_INIT} ...................................................
|
||||
#ifndef Q_SPY
|
||||
#define QASM_INIT(me_, par_, dummy) do { \
|
||||
Q_ASSERT(((QAsm *)(me_))->vptr); \
|
||||
(*((QAsm *)(me_))->vptr->init)((QAsm *)(me_), (par_), 0); \
|
||||
} while (false)
|
||||
#define QASM_INIT(me_, par_, dummy) \
|
||||
(*((QAsm *)(me_))->vptr->init)((QAsm *)(me_), (par_), 0U)
|
||||
#endif // ndef Q_SPY
|
||||
|
||||
//${QEP-macros::QASM_DISPATCH} ...............................................
|
||||
|
@ -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,16 +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>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)
|
||||
@ -169,15 +159,69 @@
|
||||
// <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>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.
|
||||
|
||||
@ -199,47 +243,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_H_
|
@ -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.h"
|
||||
#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
|
||||
@ -68,7 +62,6 @@ void NMI_Handler(void);
|
||||
// For best performance, these functions are implemented in assembly,
|
||||
// but they can be implemented in C as well.
|
||||
|
||||
|
||||
//int32_t volatile QF_int_lock_nest_; // not used
|
||||
extern char const QF_port_module_[];
|
||||
char const QF_port_module_[] = "qk_port";
|
||||
@ -77,24 +70,23 @@ char const QF_port_module_[] = "qk_port";
|
||||
// Unconditionally disable interrupts.
|
||||
// NOTE: this function must NOT use the stack.
|
||||
//
|
||||
// description:
|
||||
// On ARMv6-M, interrupts are disabled with the PRIMASK register.
|
||||
// On ARMv7-M and higher, interrupts are disabled *selectively* with the
|
||||
// BASEPRI register.
|
||||
// Description:
|
||||
// When QF_USE_BASEPRI is defined, interrupts are disabled with BASEPRI.
|
||||
// Otherwise interrupts are disabled with the PRIMASK register.
|
||||
// Additionally, the function also asserts that the interrupts are
|
||||
// NOT disabled upon the entry to the function, which means that
|
||||
// this interrupt management policy CANNOT nest.
|
||||
__attribute__ ((naked, weak))
|
||||
void QF_int_disable_(void) {
|
||||
__asm volatile (
|
||||
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
|
||||
#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"
|
||||
@ -109,28 +101,29 @@ __asm volatile (
|
||||
// Unconditionally enable interrupts.
|
||||
// NOTE: this function must NOT use the stack.
|
||||
//
|
||||
// description:
|
||||
// On ARMv6-M, interrupts are enabled with the PRIMASK register.
|
||||
// On ARMv7-M and higher, interrupts are enabled with the BASEPRI register.
|
||||
// Description:
|
||||
// When QF_USE_BASEPRI is defined, interrupts are enabled with BASEPRI.
|
||||
// Otherwise interrupts are enabled with the PRIMASK register.
|
||||
// Additionally, the function also asserts that the interrupts ARE
|
||||
// disabled upon the entry to the function, which means that
|
||||
// this interrupt management policy CANNOT nest.
|
||||
__attribute__ ((naked, weak))
|
||||
void QF_int_enable_(void) {
|
||||
__asm volatile (
|
||||
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
|
||||
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
|
||||
#else //--------- ARMv7-M or higher
|
||||
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for enabling interrupts?
|
||||
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
|
||||
#endif //--------- ARMv7-M or higher
|
||||
#else //--------- use PRIMASK for enabling interrupts
|
||||
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
|
||||
#endif //--------- use PRIMASK for enabling interrupts
|
||||
|
||||
" CMP r0,#0 \n" // assert(PRIMASK/BASEPRI != 0)
|
||||
" BEQ QF_int_enable_error\n"
|
||||
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
|
||||
" CPSIE i \n" // clear PRIMASK
|
||||
#else //--------- ARMv7-M or higher
|
||||
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for enabling interrupts?
|
||||
" MOVS r1,#0 \n"
|
||||
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
|
||||
#endif //--------- ARMv7-M or higher
|
||||
#else //--------- use PRIMASK for enabling interrupts
|
||||
" CPSIE i \n" // clear PRIMASK
|
||||
#endif //--------- use PRIMASK for enabling interrupts
|
||||
" BX lr \n"
|
||||
"QF_int_enable_error: \n"
|
||||
" LDR r0,=QF_port_module_ \n"
|
||||
@ -143,25 +136,23 @@ __asm volatile (
|
||||
// Enter QF critical section.
|
||||
// NOTE: this function must NOT use the stack.
|
||||
//
|
||||
// description:
|
||||
// On ARMv6-M, critical section is entered by disabling interrupts
|
||||
// with the PRIMASK register.
|
||||
// On ARMv7-M and higher, critical section is entered by disabling
|
||||
// interrupts *selectively* with the BASEPRI register.
|
||||
// Description:
|
||||
// When QF_USE_BASEPRI is defined, critical section uses BASEPRI.
|
||||
// Otherwise, critical section uses the PRIMASK register.
|
||||
// Additionally, the function also asserts that the interrupts are
|
||||
// NOT disabled upon the entry to the function, which means that
|
||||
// this critical section CANNOT nest.
|
||||
__attribute__ ((naked, weak))
|
||||
void QF_crit_entry_(void) {
|
||||
__asm volatile (
|
||||
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
|
||||
#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"
|
||||
@ -177,29 +168,27 @@ __asm volatile (
|
||||
// NOTE: this function must NOT use the stack.
|
||||
//
|
||||
// description:
|
||||
// On ARMv6-M, critical section is exited by enabling interrupts
|
||||
// with the PRIMASK register.
|
||||
// On ARMv7-M and higher, critical section is exited by enabling
|
||||
// interrupts with the BASEPRI register.
|
||||
// When QF_USE_BASEPRI is defined, critical section uses BASEPRI.
|
||||
// Otherwise, critical section uses the PRIMASK register.
|
||||
// Additionally, the function also asserts that the interrupts ARE
|
||||
// disabled upon the entry to the function, which means that
|
||||
// this critical section CANNOT nest.
|
||||
__attribute__ ((naked, weak))
|
||||
void QF_crit_exit_(void) {
|
||||
__asm volatile (
|
||||
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
|
||||
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
|
||||
#else //--------- ARMv7-M or higher
|
||||
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
|
||||
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
|
||||
#endif //--------- ARMv7-M or higher
|
||||
#else //--------- use PRIMASK for critical section
|
||||
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
|
||||
#endif //--------- use PRIMASK for critical section
|
||||
" CMP r0,#0 \n" // assert(PRIMASK/BASEPRI != 0)
|
||||
" BEQ QF_crit_exit_error\n"
|
||||
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
|
||||
" CPSIE i \n" // clear PRIMASK
|
||||
#else //--------- ARMv7-M or higher
|
||||
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
|
||||
" MOVS r1,#0 \n"
|
||||
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
|
||||
#endif //--------- ARMv7-M or higher
|
||||
#else //--------- use PRIMASK
|
||||
" CPSIE i \n" // clear PRIMASK
|
||||
#endif //--------- use PRIMASK
|
||||
" BX lr \n"
|
||||
"QF_crit_exit_error: \n"
|
||||
" LDR r0,=QF_port_module_ \n"
|
||||
@ -217,7 +206,7 @@ __asm volatile (
|
||||
// BASEPRI register. However, this method cannot disable interrupt
|
||||
// priority zero, which is the default for all interrupts out of reset.
|
||||
// The following code changes the SysTick priority and all IRQ priorities
|
||||
// to the safe value QF_BASEPRI, which the QF critical section can disable.
|
||||
// to the safe value QF_USE_BASEPRI, which the QF critical section can disable.
|
||||
// This avoids breaching of the QF critical sections in case the
|
||||
// application programmer forgets to explicitly set priorities of all
|
||||
// "kernel aware" interrupts.
|
||||
@ -226,18 +215,18 @@ __asm volatile (
|
||||
// by the application-level code.
|
||||
void QK_init(void) {
|
||||
|
||||
#if (__ARM_ARCH != 6) //--------- if ARMv7-M and higher...
|
||||
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
|
||||
|
||||
// SCB_SYSPRI[2]: SysTick
|
||||
SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_BASEPRI << 24U));
|
||||
SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_USE_BASEPRI << 24U));
|
||||
|
||||
// set all 240 possible IRQ priories to QF_BASEPRI...
|
||||
// set all 240 possible IRQ priories to QF_USE_BASEPRI...
|
||||
for (uint_fast8_t n = 0U; n < (240U/sizeof(uint32_t)); ++n) {
|
||||
NVIC_IP[n] = (QF_BASEPRI << 24U) | (QF_BASEPRI << 16U)
|
||||
| (QF_BASEPRI << 8U) | QF_BASEPRI;
|
||||
NVIC_IP[n] = (QF_USE_BASEPRI << 24U) | (QF_USE_BASEPRI << 16U)
|
||||
| (QF_USE_BASEPRI << 8U) | QF_USE_BASEPRI;
|
||||
}
|
||||
|
||||
#endif //--------- ARMv7-M or higher
|
||||
#endif //--------- use BASEPRI for critical section
|
||||
|
||||
// SCB_SYSPRI[2]: PendSV set to priority 0xFF (lowest)
|
||||
SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (0xFFU << 16U));
|
||||
@ -372,9 +361,12 @@ void QK_thread_ret(void) {
|
||||
#endif //--------- use the NMI
|
||||
|
||||
#else //--------- ARMv7-M and higher...
|
||||
|
||||
#ifdef QF_USE_BASEPRI //--------- QF_USE_BASEPRI
|
||||
" CPSID i \n" // disable interrupts with PRIMASK
|
||||
" LDR r0,=QF_int_enable_ \n"
|
||||
" BLX r0 \n" // enable interrupts with BASEPRI
|
||||
#endif //--------- QF_USE_BASEPRI
|
||||
// NOTE: interrupts remain disabled with PRIMASK
|
||||
|
||||
#ifdef __ARM_FP //--------- if VFP available...
|
||||
@ -390,7 +382,12 @@ void QK_thread_ret(void) {
|
||||
" MOVS r1,#1 \n"
|
||||
" LSLS r1,r1,#" STRINGIFY(QK_USE_IRQ_NUM & 0x1F) "\n" // r1 := IRQ bit
|
||||
" STR r1,[r0] \n" // pend the IRQ
|
||||
#ifdef QF_USE_BASEPRI //--------- QF_USE_BASEPRI
|
||||
" CPSIE i \n" // enable interrupts with PRIMASK
|
||||
#else //--------- interrupt disabling with PRIMASK
|
||||
" LDR r0,=QF_int_enable_ \n"
|
||||
" BLX r0 \n" // enable interrupts with BASEPRI
|
||||
#endif //--------- interrupt disabling with PRIMASK
|
||||
// This code stops here and continues in the IRQ handler
|
||||
|
||||
#else //--------- use the NMI (default)
|
||||
@ -440,15 +437,16 @@ void NMI_Handler(void) {
|
||||
__asm volatile (
|
||||
" ADD sp,sp,#(8*4) \n" // remove one 8-register exception frame
|
||||
|
||||
#if (__ARM_ARCH == 6) //--------- if ARMv6-M...
|
||||
#ifdef QF_USE_BASEPRI //--------- QF_USE_BASEPRI
|
||||
// NOTE: QF_int_enable_() already called
|
||||
" CPSIE i \n" // enable interrupts with PRIMASK
|
||||
#else //--------- interrupt disabling with PRIMASK
|
||||
" LDR r0,=QF_int_enable_ \n"
|
||||
" BLX r0 \n" // enable interrupts with PRIMASK
|
||||
|
||||
// NOTE: calling QF_int_enable_() corrupted the lr (EXC_RETURN), but
|
||||
// it is NOT used to used to return from the exception. (See POP {r0,pc})
|
||||
#else //--------- ARMv7-M and higher...
|
||||
" CPSIE i \n" // enable interrupts with PRIMASK
|
||||
#endif //--------- ARMv7-M and higher
|
||||
#endif //--------- interrupt disabling with PRIMASK
|
||||
" POP {r0,pc} \n" // pop stack aligner and EXC_RETURN to pc
|
||||
);
|
||||
// NOTE: this causes exception-return to the preempted *thread* context
|
||||
|
@ -1,5 +1,6 @@
|
||||
//============================================================================
|
||||
// QP/C Real-Time Embedded Framework (RTEF)
|
||||
//
|
||||
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
|
||||
//
|
||||
// Q u a n t u m L e a P s
|
||||
@ -26,12 +27,6 @@
|
||||
// <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 QP/C port to ARM Cortex-M, preemptive QK kernel, ARM-CLANG
|
||||
|
||||
#ifndef QP_PORT_H_
|
||||
#define QP_PORT_H_
|
||||
|
||||
@ -47,31 +42,9 @@
|
||||
// QK event-queue used for AOs
|
||||
#define QACTIVE_EQUEUE_TYPE QEQueue
|
||||
|
||||
// QF "thread" type used to store the MPU settings in the AO
|
||||
// QActive "thread" type used to store the MPU settings in the AO
|
||||
#define QACTIVE_THREAD_TYPE void const *
|
||||
|
||||
// QF interrupt disable/enable and log2()...
|
||||
#if (__ARM_ARCH == 6) // ARMv6-M?
|
||||
|
||||
// CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4
|
||||
#define QF_AWARE_ISR_CMSIS_PRI 0
|
||||
|
||||
// hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M)
|
||||
#define QF_LOG2(n_) QF_qlog2((uint32_t)(n_))
|
||||
|
||||
#else // ARMv7-M or higher
|
||||
|
||||
// BASEPRI threshold for "QF-aware" interrupts, see NOTE3
|
||||
#define QF_BASEPRI 0x3F
|
||||
|
||||
// CMSIS threshold for "QF-aware" interrupts, see NOTE4
|
||||
#define QF_AWARE_ISR_CMSIS_PRI (QF_BASEPRI >> (8 - __NVIC_PRIO_BITS))
|
||||
|
||||
// ARMv7-M or higher provide the CLZ instruction for fast LOG2
|
||||
#define QF_LOG2(n_) ((uint_fast8_t)(32 - __builtin_clz((unsigned)(n_))))
|
||||
|
||||
#endif
|
||||
|
||||
// interrupt disabling policy, see NOTE2 and NOTE3
|
||||
#define QF_INT_DISABLE() (QF_int_disable_())
|
||||
#define QF_INT_ENABLE() (QF_int_enable_())
|
||||
@ -83,11 +56,27 @@
|
||||
|
||||
#define QF_CRIT_EXIT_NOP() __asm volatile ("isb" ::: "memory")
|
||||
|
||||
// Efficient log2() ----------------------------------------------------------
|
||||
#if (__ARM_ARCH == 6) // ARMv6-M?
|
||||
// hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M)
|
||||
#define QF_LOG2(n_) QF_qlog2((uint32_t)(n_))
|
||||
|
||||
// hand-optimized quick LOG2 in assembly
|
||||
uint_fast8_t QF_qlog2(uint32_t x);
|
||||
#else // ARMv7-M or higher
|
||||
// ARMv7-M or higher provide the CLZ instruction for fast LOG2
|
||||
#define QF_LOG2(n_) ((uint_fast8_t)(32 - __builtin_clz((unsigned)(n_))))
|
||||
#endif // ARMv7-M or higher
|
||||
|
||||
// Critical section policy ---------------------------------------------------
|
||||
#ifdef QF_USE_BASEPRI
|
||||
// CMSIS threshold for "QF-aware" interrupts, see NOTE4
|
||||
#define QF_AWARE_ISR_CMSIS_PRI (QF_USE_BASEPRI >> (8 - __NVIC_PRIO_BITS))
|
||||
#else
|
||||
// CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4
|
||||
#define QF_AWARE_ISR_CMSIS_PRI 0
|
||||
#endif // QF_USE_BASEPRI
|
||||
|
||||
// Memory isolation ----------------------------------------------------------
|
||||
#ifdef QF_MEM_ISOLATE
|
||||
|
||||
@ -104,7 +93,7 @@
|
||||
void QF_onMemSys(void);
|
||||
void QF_onMemApp(void);
|
||||
|
||||
#endif // def QF_MEM_ISOLATE
|
||||
#endif // QF_MEM_ISOLATE
|
||||
|
||||
// determination if the code executes in the ISR context
|
||||
#define QK_ISR_CONTEXT_() (QK_get_IPSR() != 0U)
|
||||
@ -186,7 +175,7 @@ extern int32_t volatile QF_int_lock_nest_;
|
||||
// functions. They are defined as "weak" in the qv_port.c module,
|
||||
// so the application can provide a different implementation.
|
||||
// Please see the definitions of the interrupt and critical-section
|
||||
// funcctions in the qv_port.c module for details.
|
||||
// functions in the qv_port.c module for details.
|
||||
//
|
||||
// NOTE2:
|
||||
// On Cortex-M0/M0+/M1 (architecture ARMv6-M, ARMv6S-M), the interrupt
|
||||
@ -195,15 +184,15 @@ extern int32_t volatile QF_int_lock_nest_;
|
||||
// are "kernel-aware".
|
||||
//
|
||||
// NOTE3:
|
||||
// On ARMv7-M or higher, the interrupt disable/enable policy uses the BASEPRI
|
||||
// register (which is not implemented in ARMv6-M) to disable interrupts only
|
||||
// with priority lower than the threshold specified by the QF_BASEPRI macro.
|
||||
// The interrupts with priorities above QF_BASEPRI (i.e., with numerical
|
||||
// priority values lower than QF_BASEPRI) are NOT disabled in this method.
|
||||
// If macro QF_USE_BASEPRI is defined, the interrupt disable/enable policy
|
||||
// uses BASEPRI register to disable interrupts only with priority lower than
|
||||
// the threshold specified by the QF_USE_BASEPRI macro. The interrupts with
|
||||
// priorities above QF_USE_BASEPRI (i.e., with numerical priority values
|
||||
// lower than QF_USE_BASEPRI) are NOT disabled in this method.
|
||||
// These free-running interrupts have very low ("zero") latency, but they
|
||||
// are NOT allowed to call any QF services, because QF is unaware of them
|
||||
// ("kernel-unaware" interrupts). Consequently, only interrupts with
|
||||
// numerical values of priorities equal to or higher than QF_BASEPRI
|
||||
// numerical values of priorities equal to or higher than QF_USE_BASEPRI
|
||||
// ("kernel-aware" interrupts ), can call QF services.
|
||||
//
|
||||
// NOTE4:
|
||||
|
@ -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.h"
|
||||
#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
|
||||
@ -68,7 +62,6 @@ void NMI_Handler(void);
|
||||
// For best performance, these functions are implemented in assembly,
|
||||
// but they can be implemented in C as well.
|
||||
|
||||
|
||||
//int32_t volatile QF_int_lock_nest_; // not used
|
||||
extern char const QF_port_module_[];
|
||||
char const QF_port_module_[] = "qk_port";
|
||||
@ -77,24 +70,23 @@ char const QF_port_module_[] = "qk_port";
|
||||
// Unconditionally disable interrupts.
|
||||
// NOTE: this function must NOT use the stack.
|
||||
//
|
||||
// description:
|
||||
// On ARMv6-M, interrupts are disabled with the PRIMASK register.
|
||||
// On ARMv7-M and higher, interrupts are disabled *selectively* with the
|
||||
// BASEPRI register.
|
||||
// Description:
|
||||
// When QF_USE_BASEPRI is defined, interrupts are disabled with BASEPRI.
|
||||
// Otherwise interrupts are disabled with the PRIMASK register.
|
||||
// Additionally, the function also asserts that the interrupts are
|
||||
// NOT disabled upon the entry to the function, which means that
|
||||
// this interrupt management policy CANNOT nest.
|
||||
__attribute__ ((naked, weak))
|
||||
void QF_int_disable_(void) {
|
||||
__asm volatile (
|
||||
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
|
||||
#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"
|
||||
@ -109,28 +101,30 @@ __asm volatile (
|
||||
// Unconditionally enable interrupts.
|
||||
// NOTE: this function must NOT use the stack.
|
||||
//
|
||||
// description:
|
||||
// On ARMv6-M, interrupts are enabled with the PRIMASK register.
|
||||
// On ARMv7-M and higher, interrupts are enabled with the BASEPRI register.
|
||||
// Description:
|
||||
// When QF_USE_BASEPRI is defined, interrupts are enabled with BASEPRI.
|
||||
// Otherwise interrupts are enabled with the PRIMASK register.
|
||||
// Additionally, the function also asserts that the interrupts ARE
|
||||
// disabled upon the entry to the function, which means that
|
||||
// this interrupt management policy CANNOT nest.
|
||||
__attribute__ ((naked, weak))
|
||||
void QF_int_enable_(void) {
|
||||
__asm volatile (
|
||||
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
|
||||
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
|
||||
#else //--------- ARMv7-M or higher
|
||||
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for enabling interrupts?
|
||||
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
|
||||
#endif //--------- ARMv7-M or higher
|
||||
#else //--------- use PRIMASK for enabling interrupts
|
||||
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
|
||||
#endif //--------- use PRIMASK for enabling interrupts
|
||||
|
||||
" CMP r0,#0 \n" // assert(PRIMASK/BASEPRI != 0)
|
||||
" BEQ QF_int_enable_error\n"
|
||||
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
|
||||
" CPSIE i \n" // clear PRIMASK
|
||||
#else //--------- ARMv7-M or higher
|
||||
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for enabling interrupts?
|
||||
" MOVS r1,#0 \n"
|
||||
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
|
||||
#endif //--------- ARMv7-M or higher
|
||||
#else //--------- use PRIMASK for enabling interrupts
|
||||
" CPSIE i \n" // clear PRIMASK
|
||||
#endif //--------- use PRIMASK for enabling interrupts
|
||||
|
||||
" BX lr \n"
|
||||
"QF_int_enable_error: \n"
|
||||
" LDR r0,=QF_port_module_ \n"
|
||||
@ -143,25 +137,23 @@ __asm volatile (
|
||||
// Enter QF critical section.
|
||||
// NOTE: this function must NOT use the stack.
|
||||
//
|
||||
// description:
|
||||
// On ARMv6-M, critical section is entered by disabling interrupts
|
||||
// with the PRIMASK register.
|
||||
// On ARMv7-M and higher, critical section is entered by disabling
|
||||
// interrupts *selectively* with the BASEPRI register.
|
||||
// Description:
|
||||
// When QF_USE_BASEPRI is defined, critical section uses BASEPRI.
|
||||
// Otherwise, critical section uses the PRIMASK register.
|
||||
// Additionally, the function also asserts that the interrupts are
|
||||
// NOT disabled upon the entry to the function, which means that
|
||||
// this critical section CANNOT nest.
|
||||
__attribute__ ((naked, weak))
|
||||
void QF_crit_entry_(void) {
|
||||
__asm volatile (
|
||||
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
|
||||
#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"
|
||||
@ -177,29 +169,27 @@ __asm volatile (
|
||||
// NOTE: this function must NOT use the stack.
|
||||
//
|
||||
// description:
|
||||
// On ARMv6-M, critical section is exited by enabling interrupts
|
||||
// with the PRIMASK register.
|
||||
// On ARMv7-M and higher, critical section is exited by enabling
|
||||
// interrupts with the BASEPRI register.
|
||||
// When QF_USE_BASEPRI is defined, critical section uses BASEPRI.
|
||||
// Otherwise, critical section uses the PRIMASK register.
|
||||
// Additionally, the function also asserts that the interrupts ARE
|
||||
// disabled upon the entry to the function, which means that
|
||||
// this critical section CANNOT nest.
|
||||
__attribute__ ((naked, weak))
|
||||
void QF_crit_exit_(void) {
|
||||
__asm volatile (
|
||||
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
|
||||
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
|
||||
#else //--------- ARMv7-M or higher
|
||||
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
|
||||
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
|
||||
#endif //--------- ARMv7-M or higher
|
||||
#else //--------- use PRIMASK for critical section
|
||||
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
|
||||
#endif //--------- use PRIMASK for critical section
|
||||
" CMP r0,#0 \n" // assert(PRIMASK/BASEPRI != 0)
|
||||
" BEQ QF_crit_exit_error\n"
|
||||
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
|
||||
" CPSIE i \n" // clear PRIMASK
|
||||
#else //--------- ARMv7-M or higher
|
||||
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
|
||||
" MOVS r1,#0 \n"
|
||||
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
|
||||
#endif //--------- ARMv7-M or higher
|
||||
#else //--------- use PRIMASK
|
||||
" CPSIE i \n" // clear PRIMASK
|
||||
#endif //--------- use PRIMASK
|
||||
" BX lr \n"
|
||||
"QF_crit_exit_error: \n"
|
||||
" LDR r0,=QF_port_module_ \n"
|
||||
@ -217,7 +207,7 @@ __asm volatile (
|
||||
// BASEPRI register. However, this method cannot disable interrupt
|
||||
// priority zero, which is the default for all interrupts out of reset.
|
||||
// The following code changes the SysTick priority and all IRQ priorities
|
||||
// to the safe value QF_BASEPRI, which the QF critical section can disable.
|
||||
// to the safe value QF_USE_BASEPRI, which the QF critical section can disable.
|
||||
// This avoids breaching of the QF critical sections in case the
|
||||
// application programmer forgets to explicitly set priorities of all
|
||||
// "kernel aware" interrupts.
|
||||
@ -226,18 +216,18 @@ __asm volatile (
|
||||
// by the application-level code.
|
||||
void QK_init(void) {
|
||||
|
||||
#if (__ARM_ARCH != 6) //--------- if ARMv7-M and higher...
|
||||
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
|
||||
|
||||
// SCB_SYSPRI[2]: SysTick
|
||||
SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_BASEPRI << 24U));
|
||||
SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_USE_BASEPRI << 24U));
|
||||
|
||||
// set all 240 possible IRQ priories to QF_BASEPRI...
|
||||
// set all 240 possible IRQ priories to QF_USE_BASEPRI...
|
||||
for (uint_fast8_t n = 0U; n < (240U/sizeof(uint32_t)); ++n) {
|
||||
NVIC_IP[n] = (QF_BASEPRI << 24U) | (QF_BASEPRI << 16U)
|
||||
| (QF_BASEPRI << 8U) | QF_BASEPRI;
|
||||
NVIC_IP[n] = (QF_USE_BASEPRI << 24U) | (QF_USE_BASEPRI << 16U)
|
||||
| (QF_USE_BASEPRI << 8U) | QF_USE_BASEPRI;
|
||||
}
|
||||
|
||||
#endif //--------- ARMv7-M or higher
|
||||
#endif //--------- use BASEPRI for critical section
|
||||
|
||||
// SCB_SYSPRI[2]: PendSV set to priority 0xFF (lowest)
|
||||
SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (0xFFU << 16U));
|
||||
@ -381,9 +371,12 @@ void QK_thread_ret(void) {
|
||||
#endif //--------- use the NMI
|
||||
|
||||
#else //--------- ARMv7-M and higher...
|
||||
|
||||
#ifdef QF_USE_BASEPRI //--------- QF_USE_BASEPRI
|
||||
" CPSID i \n" // disable interrupts with PRIMASK
|
||||
" LDR r0,=QF_int_enable_ \n"
|
||||
" BLX r0 \n" // enable interrupts with BASEPRI
|
||||
#endif //--------- QF_USE_BASEPRI
|
||||
// NOTE: interrupts remain disabled with PRIMASK
|
||||
|
||||
#ifdef __ARM_FP //--------- if VFP available...
|
||||
@ -399,7 +392,12 @@ void QK_thread_ret(void) {
|
||||
" MOV r1,#1 \n"
|
||||
" LSL r1,r1,#" STRINGIFY(QK_USE_IRQ_NUM & 0x1F) "\n" // r1 := IRQ bit
|
||||
" STR r1,[r0] \n" // pend the IRQ
|
||||
#ifdef QF_USE_BASEPRI //--------- QF_USE_BASEPRI
|
||||
" CPSIE i \n" // enable interrupts with PRIMASK
|
||||
#else //--------- interrupt disabling with PRIMASK
|
||||
" LDR r0,=QF_int_enable_ \n"
|
||||
" BLX r0 \n" // enable interrupts with BASEPRI
|
||||
#endif //--------- interrupt disabling with PRIMASK
|
||||
// This code stops here and continues in the IRQ handler
|
||||
|
||||
#else //--------- use the NMI (default)
|
||||
@ -449,15 +447,16 @@ void NMI_Handler(void) {
|
||||
__asm volatile (
|
||||
" ADD sp,sp,#(8*4) \n" // remove one 8-register exception frame
|
||||
|
||||
#if (__ARM_ARCH == 6) //--------- if ARMv6-M...
|
||||
#ifdef QF_USE_BASEPRI //--------- QF_USE_BASEPRI
|
||||
// NOTE: QF_int_enable_() already called
|
||||
" CPSIE i \n" // enable interrupts with PRIMASK
|
||||
#else //--------- interrupt disabling with PRIMASK
|
||||
" LDR r0,=QF_int_enable_ \n"
|
||||
" BLX r0 \n" // enable interrupts with PRIMASK
|
||||
|
||||
// NOTE: calling QF_int_enable_() corrupted the lr (EXC_RETURN), but
|
||||
// it is NOT used to used to return from the exception. (See POP {r0,pc})
|
||||
#else //--------- ARMv7-M and higher...
|
||||
" CPSIE i \n" // enable interrupts with PRIMASK
|
||||
#endif //--------- ARMv7-M and higher
|
||||
#endif //--------- interrupt disabling with PRIMASK
|
||||
" POP {r0,pc} \n" // pop stack aligner and EXC_RETURN to pc
|
||||
);
|
||||
// NOTE: this causes exception-return to the preempted *thread* context
|
||||
|
@ -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 QP/C port to ARM Cortex-M, preemptive QK kernel, GNU-ARM
|
||||
|
||||
#ifndef QP_PORT_H_
|
||||
#define QP_PORT_H_
|
||||
|
||||
@ -47,31 +41,9 @@
|
||||
// QK event-queue used for AOs
|
||||
#define QACTIVE_EQUEUE_TYPE QEQueue
|
||||
|
||||
// QF "thread" type used to store the MPU settings in the AO
|
||||
// QActive "thread" type used to store the MPU settings in the AO
|
||||
#define QACTIVE_THREAD_TYPE void const *
|
||||
|
||||
// QF interrupt disable/enable and log2()...
|
||||
#if (__ARM_ARCH == 6) // ARMv6-M?
|
||||
|
||||
// CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4
|
||||
#define QF_AWARE_ISR_CMSIS_PRI 0
|
||||
|
||||
// hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M)
|
||||
#define QF_LOG2(n_) QF_qlog2((uint32_t)(n_))
|
||||
|
||||
#else // ARMv7-M or higher
|
||||
|
||||
// BASEPRI threshold for "QF-aware" interrupts, see NOTE3
|
||||
#define QF_BASEPRI 0x3F
|
||||
|
||||
// CMSIS threshold for "QF-aware" interrupts, see NOTE4
|
||||
#define QF_AWARE_ISR_CMSIS_PRI (QF_BASEPRI >> (8 - __NVIC_PRIO_BITS))
|
||||
|
||||
// ARMv7-M or higher provide the CLZ instruction for fast LOG2
|
||||
#define QF_LOG2(n_) ((uint_fast8_t)(32 - __builtin_clz((unsigned)(n_))))
|
||||
|
||||
#endif
|
||||
|
||||
// interrupt disabling policy, see NOTE2 and NOTE3
|
||||
#define QF_INT_DISABLE() (QF_int_disable_())
|
||||
#define QF_INT_ENABLE() (QF_int_enable_())
|
||||
@ -83,11 +55,27 @@
|
||||
|
||||
#define QF_CRIT_EXIT_NOP() __asm volatile ("isb" ::: "memory")
|
||||
|
||||
// Efficient log2() ----------------------------------------------------------
|
||||
#if (__ARM_ARCH == 6) // ARMv6-M?
|
||||
// hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M)
|
||||
#define QF_LOG2(n_) QF_qlog2((uint32_t)(n_))
|
||||
|
||||
// hand-optimized quick LOG2 in assembly
|
||||
uint_fast8_t QF_qlog2(uint32_t x);
|
||||
#else // ARMv7-M or higher
|
||||
// ARMv7-M or higher provide the CLZ instruction for fast LOG2
|
||||
#define QF_LOG2(n_) ((uint_fast8_t)(32 - __builtin_clz((unsigned)(n_))))
|
||||
#endif // ARMv7-M or higher
|
||||
|
||||
// Critical section policy ---------------------------------------------------
|
||||
#ifdef QF_USE_BASEPRI
|
||||
// CMSIS threshold for "QF-aware" interrupts, see NOTE4
|
||||
#define QF_AWARE_ISR_CMSIS_PRI (QF_USE_BASEPRI >> (8 - __NVIC_PRIO_BITS))
|
||||
#else
|
||||
// CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4
|
||||
#define QF_AWARE_ISR_CMSIS_PRI 0
|
||||
#endif // QF_USE_BASEPRI
|
||||
|
||||
// Memory isolation ----------------------------------------------------------
|
||||
#ifdef QF_MEM_ISOLATE
|
||||
|
||||
@ -104,7 +92,7 @@
|
||||
void QF_onMemSys(void);
|
||||
void QF_onMemApp(void);
|
||||
|
||||
#endif // def QF_MEM_ISOLATE
|
||||
#endif // QF_MEM_ISOLATE
|
||||
|
||||
// determination if the code executes in the ISR context
|
||||
#define QK_ISR_CONTEXT_() (QK_get_IPSR() != 0U)
|
||||
@ -186,7 +174,7 @@ extern int32_t volatile QF_int_lock_nest_;
|
||||
// functions. They are defined as "weak" in the qv_port.c module,
|
||||
// so the application can provide a different implementation.
|
||||
// Please see the definitions of the interrupt and critical-section
|
||||
// funcctions in the qv_port.c module for details.
|
||||
// functions in the qv_port.c module for details.
|
||||
//
|
||||
// NOTE2:
|
||||
// On Cortex-M0/M0+/M1 (architecture ARMv6-M, ARMv6S-M), the interrupt
|
||||
@ -195,15 +183,15 @@ extern int32_t volatile QF_int_lock_nest_;
|
||||
// are "kernel-aware".
|
||||
//
|
||||
// NOTE3:
|
||||
// On ARMv7-M or higher, the interrupt disable/enable policy uses the BASEPRI
|
||||
// register (which is not implemented in ARMv6-M) to disable interrupts only
|
||||
// with priority lower than the threshold specified by the QF_BASEPRI macro.
|
||||
// The interrupts with priorities above QF_BASEPRI (i.e., with numerical
|
||||
// priority values lower than QF_BASEPRI) are NOT disabled in this method.
|
||||
// If macro QF_USE_BASEPRI is defined, the interrupt disable/enable policy
|
||||
// uses BASEPRI register to disable interrupts only with priority lower than
|
||||
// the threshold specified by the QF_USE_BASEPRI macro. The interrupts with
|
||||
// priorities above QF_USE_BASEPRI (i.e., with numerical priority values
|
||||
// lower than QF_USE_BASEPRI) are NOT disabled in this method.
|
||||
// These free-running interrupts have very low ("zero") latency, but they
|
||||
// are NOT allowed to call any QF services, because QF is unaware of them
|
||||
// ("kernel-unaware" interrupts). Consequently, only interrupts with
|
||||
// numerical values of priorities equal to or higher than QF_BASEPRI
|
||||
// numerical values of priorities equal to or higher than QF_USE_BASEPRI
|
||||
// ("kernel-aware" interrupts ), can call QF services.
|
||||
//
|
||||
// NOTE4:
|
||||
|
@ -1,5 +1,6 @@
|
||||
//============================================================================
|
||||
// QP/C Real-Time Embedded Framework (RTEF)
|
||||
//
|
||||
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
|
||||
//
|
||||
// Q u a n t u m L e a P s
|
||||
@ -26,12 +27,6 @@
|
||||
// <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.h"
|
||||
#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
|
||||
@ -81,24 +76,23 @@ char const QF_port_module_[] = "qk_port";
|
||||
// Unconditionally disable interrupts.
|
||||
// NOTE: this function must NOT use the stack.
|
||||
//
|
||||
// description:
|
||||
// On ARMv6-M, interrupts are disabled with the PRIMASK register.
|
||||
// On ARMv7-M and higher, interrupts are disabled *selectively* with the
|
||||
// BASEPRI register.
|
||||
// Description:
|
||||
// When QF_USE_BASEPRI is defined, interrupts are disabled with BASEPRI.
|
||||
// Otherwise interrupts are disabled with the PRIMASK register.
|
||||
// Additionally, the function also asserts that the interrupts are
|
||||
// NOT disabled upon the entry to the function, which means that
|
||||
// this interrupt management policy CANNOT nest.
|
||||
__stackless
|
||||
void QF_int_disable_(void) {
|
||||
__asm volatile (
|
||||
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
|
||||
#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"
|
||||
@ -113,28 +107,29 @@ __asm volatile (
|
||||
// Unconditionally enable interrupts.
|
||||
// NOTE: this function must NOT use the stack.
|
||||
//
|
||||
// description:
|
||||
// On ARMv6-M, interrupts are enabled with the PRIMASK register.
|
||||
// On ARMv7-M and higher, interrupts are enabled with the BASEPRI register.
|
||||
// Description:
|
||||
// When QF_USE_BASEPRI is defined, interrupts are enabled with BASEPRI.
|
||||
// Otherwise interrupts are enabled with the PRIMASK register.
|
||||
// Additionally, the function also asserts that the interrupts ARE
|
||||
// disabled upon the entry to the function, which means that
|
||||
// this interrupt management policy CANNOT nest.
|
||||
__stackless
|
||||
void QF_int_enable_(void) {
|
||||
__asm volatile (
|
||||
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
|
||||
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
|
||||
#else //--------- ARMv7-M or higher
|
||||
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for enabling interrupts?
|
||||
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
|
||||
#endif //--------- ARMv7-M or higher
|
||||
#else //--------- use PRIMASK for enabling interrupts
|
||||
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
|
||||
#endif //--------- use PRIMASK for enabling interrupts
|
||||
|
||||
" CMP r0,#0 \n" // assert(PRIMASK/BASEPRI != 0)
|
||||
" BEQ QF_int_enable_error\n"
|
||||
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
|
||||
" CPSIE i \n" // clear PRIMASK
|
||||
#else //--------- ARMv7-M or higher
|
||||
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for enabling interrupts?
|
||||
" MOVS r1,#0 \n"
|
||||
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
|
||||
#endif //--------- ARMv7-M or higher
|
||||
#else //--------- use PRIMASK for enabling interrupts
|
||||
" CPSIE i \n" // clear PRIMASK
|
||||
#endif //--------- use PRIMASK for enabling interrupts
|
||||
" BX lr \n"
|
||||
"QF_int_enable_error: \n"
|
||||
" LDR r0,=QF_port_module_ \n"
|
||||
@ -147,25 +142,23 @@ __asm volatile (
|
||||
// Enter QF critical section.
|
||||
// NOTE: this function must NOT use the stack.
|
||||
//
|
||||
// description:
|
||||
// On ARMv6-M, critical section is entered by disabling interrupts
|
||||
// with the PRIMASK register.
|
||||
// On ARMv7-M and higher, critical section is entered by disabling
|
||||
// interrupts *selectively* with the BASEPRI register.
|
||||
// Description:
|
||||
// When QF_USE_BASEPRI is defined, critical section uses BASEPRI.
|
||||
// Otherwise, critical section uses the PRIMASK register.
|
||||
// Additionally, the function also asserts that the interrupts are
|
||||
// NOT disabled upon the entry to the function, which means that
|
||||
// this critical section CANNOT nest.
|
||||
__stackless
|
||||
void QF_crit_entry_(void) {
|
||||
__asm volatile (
|
||||
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
|
||||
#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"
|
||||
@ -181,29 +174,27 @@ __asm volatile (
|
||||
// NOTE: this function must NOT use the stack.
|
||||
//
|
||||
// description:
|
||||
// On ARMv6-M, critical section is exited by enabling interrupts
|
||||
// with the PRIMASK register.
|
||||
// On ARMv7-M and higher, critical section is exited by enabling
|
||||
// interrupts with the BASEPRI register.
|
||||
// When QF_USE_BASEPRI is defined, critical section uses BASEPRI.
|
||||
// Otherwise, critical section uses the PRIMASK register.
|
||||
// Additionally, the function also asserts that the interrupts ARE
|
||||
// disabled upon the entry to the function, which means that
|
||||
// this critical section CANNOT nest.
|
||||
__stackless
|
||||
void QF_crit_exit_(void) {
|
||||
__asm volatile (
|
||||
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
|
||||
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
|
||||
#else //--------- ARMv7-M or higher
|
||||
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
|
||||
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
|
||||
#endif //--------- ARMv7-M or higher
|
||||
#else //--------- use PRIMASK for critical section
|
||||
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
|
||||
#endif //--------- use PRIMASK for critical section
|
||||
" CMP r0,#0 \n" // assert(PRIMASK/BASEPRI != 0)
|
||||
" BEQ QF_crit_exit_error\n"
|
||||
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
|
||||
" CPSIE i \n" // clear PRIMASK
|
||||
#else //--------- ARMv7-M or higher
|
||||
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
|
||||
" MOVS r1,#0 \n"
|
||||
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
|
||||
#endif //--------- ARMv7-M or higher
|
||||
#else //--------- use PRIMASK
|
||||
" CPSIE i \n" // clear PRIMASK
|
||||
#endif //--------- use PRIMASK
|
||||
" BX lr \n"
|
||||
"QF_crit_exit_error: \n"
|
||||
" LDR r0,=QF_port_module_ \n"
|
||||
@ -221,7 +212,7 @@ __asm volatile (
|
||||
// BASEPRI register. However, this method cannot disable interrupt
|
||||
// priority zero, which is the default for all interrupts out of reset.
|
||||
// The following code changes the SysTick priority and all IRQ priorities
|
||||
// to the safe value QF_BASEPRI, which the QF critical section can disable.
|
||||
// to the safe value QF_USE_BASEPRI, which the QF critical section can disable.
|
||||
// This avoids breaching of the QF critical sections in case the
|
||||
// application programmer forgets to explicitly set priorities of all
|
||||
// "kernel aware" interrupts.
|
||||
@ -230,18 +221,18 @@ __asm volatile (
|
||||
// by the application-level code.
|
||||
void QK_init(void) {
|
||||
|
||||
#if (__ARM_ARCH != 6) //--------- if ARMv7-M and higher...
|
||||
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
|
||||
|
||||
// SCB_SYSPRI[2]: SysTick
|
||||
SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_BASEPRI << 24U));
|
||||
SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_USE_BASEPRI << 24U));
|
||||
|
||||
// set all 240 possible IRQ priories to QF_BASEPRI...
|
||||
// set all 240 possible IRQ priories to QF_USE_BASEPRI...
|
||||
for (uint_fast8_t n = 0U; n < (240U/sizeof(uint32_t)); ++n) {
|
||||
NVIC_IP[n] = (QF_BASEPRI << 24U) | (QF_BASEPRI << 16U)
|
||||
| (QF_BASEPRI << 8U) | QF_BASEPRI;
|
||||
NVIC_IP[n] = (QF_USE_BASEPRI << 24U) | (QF_USE_BASEPRI << 16U)
|
||||
| (QF_USE_BASEPRI << 8U) | QF_USE_BASEPRI;
|
||||
}
|
||||
|
||||
#endif //--------- ARMv7-M or higher
|
||||
#endif //--------- use BASEPRI for critical section
|
||||
|
||||
// SCB_SYSPRI[2]: PendSV set to priority 0xFF (lowest)
|
||||
SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (0xFFU << 16U));
|
||||
@ -376,9 +367,12 @@ void QK_thread_ret(void) {
|
||||
#endif //--------- use the NMI
|
||||
|
||||
#else //--------- ARMv7-M and higher...
|
||||
|
||||
#ifdef QF_USE_BASEPRI //--------- QF_USE_BASEPRI
|
||||
" CPSID i \n" // disable interrupts with PRIMASK
|
||||
" LDR r0,=QF_int_enable_ \n"
|
||||
" BLX r0 \n" // enable interrupts with BASEPRI
|
||||
#endif //--------- QF_USE_BASEPRI
|
||||
// NOTE: interrupts remain disabled with PRIMASK
|
||||
|
||||
#ifdef __ARM_FP //--------- if VFP available...
|
||||
@ -394,7 +388,12 @@ void QK_thread_ret(void) {
|
||||
" MOVS r1,#1 \n"
|
||||
" LSLS r1,r1,#" STRINGIFY(QK_USE_IRQ_NUM & 0x1F) "\n" // r1 := IRQ bit
|
||||
" STR r1,[r0] \n" // pend the IRQ
|
||||
#ifdef QF_USE_BASEPRI //--------- QF_USE_BASEPRI
|
||||
" CPSIE i \n" // enable interrupts with PRIMASK
|
||||
#else //--------- interrupt disabling with PRIMASK
|
||||
" LDR r0,=QF_int_enable_ \n"
|
||||
" BLX r0 \n" // enable interrupts with BASEPRI
|
||||
#endif //--------- interrupt disabling with PRIMASK
|
||||
// This code stops here and continues in the IRQ handler
|
||||
|
||||
#else //--------- use the NMI (default)
|
||||
@ -444,15 +443,16 @@ void NMI_Handler(void) {
|
||||
__asm volatile (
|
||||
" ADD sp,sp,#(8*4) \n" // remove one 8-register exception frame
|
||||
|
||||
#if (__ARM_ARCH == 6) //--------- if ARMv6-M...
|
||||
#ifdef QF_USE_BASEPRI //--------- QF_USE_BASEPRI
|
||||
// NOTE: QF_int_enable_() already called
|
||||
" CPSIE i \n" // enable interrupts with PRIMASK
|
||||
#else //--------- interrupt disabling with PRIMASK
|
||||
" LDR r0,=QF_int_enable_ \n"
|
||||
" BLX r0 \n" // enable interrupts with PRIMASK
|
||||
|
||||
// NOTE: calling QF_int_enable_() corrupted the lr (EXC_RETURN), but
|
||||
// it is NOT used to used to return from the exception. (See POP {r0,pc})
|
||||
#else //--------- ARMv7-M and higher...
|
||||
" CPSIE i \n" // enable interrupts with PRIMASK
|
||||
#endif //--------- ARMv7-M and higher
|
||||
#endif //--------- interrupt disabling with PRIMASK
|
||||
" POP {r0,pc} \n" // pop stack aligner and EXC_RETURN to pc
|
||||
);
|
||||
// NOTE: this causes exception-return to the preempted *thread* context
|
||||
|
@ -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 QP/C port to ARM Cortex-M, preemptive QK kernel, IAR-ARM
|
||||
|
||||
#ifndef QP_PORT_H_
|
||||
#define QP_PORT_H_
|
||||
|
||||
@ -48,31 +42,9 @@
|
||||
// QK event-queue used for AOs
|
||||
#define QACTIVE_EQUEUE_TYPE QEQueue
|
||||
|
||||
// QF "thread" type used to store the MPU settings in the AO
|
||||
// QActive "thread" type used to store the MPU settings in the AO
|
||||
#define QACTIVE_THREAD_TYPE void const *
|
||||
|
||||
// QF interrupt disable/enable and log2()...
|
||||
#if (__ARM_ARCH == 6) // ARMv6-M?
|
||||
|
||||
// CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4
|
||||
#define QF_AWARE_ISR_CMSIS_PRI 0
|
||||
|
||||
// hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M)
|
||||
#define QF_LOG2(n_) QF_qlog2((uint32_t)(n_))
|
||||
|
||||
#else // ARMv7-M or higher
|
||||
|
||||
// BASEPRI threshold for "QF-aware" interrupts, see NOTE3
|
||||
#define QF_BASEPRI 0x3F
|
||||
|
||||
// CMSIS threshold for "QF-aware" interrupts, see NOTE4
|
||||
#define QF_AWARE_ISR_CMSIS_PRI (QF_BASEPRI >> (8 - __NVIC_PRIO_BITS))
|
||||
|
||||
// ARMv7-M or higher provide the CLZ instruction for fast LOG2
|
||||
#define QF_LOG2(n_) ((uint_fast8_t)(32U - __CLZ((unsigned long)(n_))))
|
||||
|
||||
#endif
|
||||
|
||||
// interrupt disabling policy, see NOTE2 and NOTE3
|
||||
#define QF_INT_DISABLE() (QF_int_disable_())
|
||||
#define QF_INT_ENABLE() (QF_int_enable_())
|
||||
@ -84,11 +56,27 @@
|
||||
|
||||
#define QF_CRIT_EXIT_NOP() __ISB()
|
||||
|
||||
// Efficient log2() ----------------------------------------------------------
|
||||
#if (__ARM_ARCH == 6) // ARMv6-M?
|
||||
// hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M)
|
||||
#define QF_LOG2(n_) QF_qlog2((uint32_t)(n_))
|
||||
|
||||
// hand-optimized quick LOG2 in assembly
|
||||
uint_fast8_t QF_qlog2(uint32_t x);
|
||||
#else // ARMv7-M or higher
|
||||
// ARMv7-M or higher provide the CLZ instruction for fast LOG2
|
||||
#define QF_LOG2(n_) ((uint_fast8_t)(32U - __CLZ((unsigned long)(n_))))
|
||||
#endif // ARMv7-M or higher
|
||||
|
||||
// Critical section policy ---------------------------------------------------
|
||||
#ifdef QF_USE_BASEPRI
|
||||
// CMSIS threshold for "QF-aware" interrupts, see NOTE4
|
||||
#define QF_AWARE_ISR_CMSIS_PRI (QF_USE_BASEPRI >> (8 - __NVIC_PRIO_BITS))
|
||||
#else
|
||||
// CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4
|
||||
#define QF_AWARE_ISR_CMSIS_PRI 0
|
||||
#endif // QF_USE_BASEPRI
|
||||
|
||||
// Memory isolation ----------------------------------------------------------
|
||||
#ifdef QF_MEM_ISOLATE
|
||||
|
||||
@ -105,7 +93,7 @@
|
||||
void QF_onMemSys(void);
|
||||
void QF_onMemApp(void);
|
||||
|
||||
#endif // def QF_MEM_ISOLATE
|
||||
#endif // QF_MEM_ISOLATE
|
||||
|
||||
// determination if the code executes in the ISR context
|
||||
#define QK_ISR_CONTEXT_() (__get_IPSR() != 0U)
|
||||
@ -180,7 +168,7 @@ extern int32_t volatile QF_int_lock_nest_;
|
||||
// functions. They are defined as "weak" in the qv_port.c module,
|
||||
// so the application can provide a different implementation.
|
||||
// Please see the definitions of the interrupt and critical-section
|
||||
// funcctions in the qv_port.c module for details.
|
||||
// functions in the qv_port.c module for details.
|
||||
//
|
||||
// NOTE2:
|
||||
// On Cortex-M0/M0+/M1 (architecture ARMv6-M, ARMv6S-M), the interrupt
|
||||
@ -189,15 +177,15 @@ extern int32_t volatile QF_int_lock_nest_;
|
||||
// are "kernel-aware".
|
||||
//
|
||||
// NOTE3:
|
||||
// On ARMv7-M or higher, the interrupt disable/enable policy uses the BASEPRI
|
||||
// register (which is not implemented in ARMv6-M) to disable interrupts only
|
||||
// with priority lower than the threshold specified by the QF_BASEPRI macro.
|
||||
// The interrupts with priorities above QF_BASEPRI (i.e., with numerical
|
||||
// priority values lower than QF_BASEPRI) are NOT disabled in this method.
|
||||
// If macro QF_USE_BASEPRI is defined, the interrupt disable/enable policy
|
||||
// uses BASEPRI register to disable interrupts only with priority lower than
|
||||
// the threshold specified by the QF_USE_BASEPRI macro. The interrupts with
|
||||
// priorities above QF_USE_BASEPRI (i.e., with numerical priority values
|
||||
// lower than QF_USE_BASEPRI) are NOT disabled in this method.
|
||||
// These free-running interrupts have very low ("zero") latency, but they
|
||||
// are NOT allowed to call any QF services, because QF is unaware of them
|
||||
// ("kernel-unaware" interrupts). Consequently, only interrupts with
|
||||
// numerical values of priorities equal to or higher than QF_BASEPRI
|
||||
// numerical values of priorities equal to or higher than QF_USE_BASEPRI
|
||||
// ("kernel-aware" interrupts ), can call QF services.
|
||||
//
|
||||
// NOTE4:
|
||||
|
@ -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 QP/C port to ARM Cortex-M, cooperative QV kernel, ARM-CLANG
|
||||
|
||||
#ifndef QP_PORT_H_
|
||||
#define QP_PORT_H_
|
||||
|
||||
@ -47,31 +41,9 @@
|
||||
// QV event-queue used for AOs
|
||||
#define QACTIVE_EQUEUE_TYPE QEQueue
|
||||
|
||||
// QF "thread" type used to store the MPU settings in the AO
|
||||
// QActive "thread" type used to store the MPU settings in the AO
|
||||
#define QACTIVE_THREAD_TYPE void const *
|
||||
|
||||
// QF interrupt disable/enable and log2()...
|
||||
#if (__ARM_ARCH == 6) // ARMv6-M?
|
||||
|
||||
// CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4
|
||||
#define QF_AWARE_ISR_CMSIS_PRI 0
|
||||
|
||||
// hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M)
|
||||
#define QF_LOG2(n_) QF_qlog2((uint32_t)(n_))
|
||||
|
||||
#else // ARMv7-M or higher
|
||||
|
||||
// BASEPRI threshold for "QF-aware" interrupts, see NOTE3
|
||||
#define QF_BASEPRI 0x3F
|
||||
|
||||
// CMSIS threshold for "QF-aware" interrupts, see NOTE4
|
||||
#define QF_AWARE_ISR_CMSIS_PRI (QF_BASEPRI >> (8 - __NVIC_PRIO_BITS))
|
||||
|
||||
// ARMv7-M or higher provide the CLZ instruction for fast LOG2
|
||||
#define QF_LOG2(n_) ((uint_fast8_t)(32 - __builtin_clz((unsigned)(n_))))
|
||||
|
||||
#endif
|
||||
|
||||
// interrupt disabling policy, see NOTE2 and NOTE3
|
||||
#define QF_INT_DISABLE() (QF_int_disable_())
|
||||
#define QF_INT_ENABLE() (QF_int_enable_())
|
||||
@ -83,11 +55,27 @@
|
||||
|
||||
#define QF_CRIT_EXIT_NOP() __asm volatile ("isb" ::: "memory")
|
||||
|
||||
// Efficient log2() ----------------------------------------------------------
|
||||
#if (__ARM_ARCH == 6) // ARMv6-M?
|
||||
// hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M)
|
||||
#define QF_LOG2(n_) QF_qlog2((uint32_t)(n_))
|
||||
|
||||
// hand-optimized quick LOG2 in assembly
|
||||
uint_fast8_t QF_qlog2(uint32_t x);
|
||||
#else // ARMv7-M or higher
|
||||
// ARMv7-M or higher provide the CLZ instruction for fast LOG2
|
||||
#define QF_LOG2(n_) ((uint_fast8_t)(32 - __builtin_clz((unsigned)(n_))))
|
||||
#endif // ARMv7-M or higher
|
||||
|
||||
// Critical section policy ---------------------------------------------------
|
||||
#ifdef QF_USE_BASEPRI
|
||||
// CMSIS threshold for "QF-aware" interrupts, see NOTE4
|
||||
#define QF_AWARE_ISR_CMSIS_PRI (QF_USE_BASEPRI >> (8 - __NVIC_PRIO_BITS))
|
||||
#else
|
||||
// CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4
|
||||
#define QF_AWARE_ISR_CMSIS_PRI 0
|
||||
#endif // QF_USE_BASEPRI
|
||||
|
||||
// Memory isolation ----------------------------------------------------------
|
||||
#ifdef QF_MEM_ISOLATE
|
||||
|
||||
@ -104,20 +92,10 @@
|
||||
void QF_onMemSys(void);
|
||||
void QF_onMemApp(void);
|
||||
|
||||
#endif // def QF_MEM_ISOLATE
|
||||
#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 { \
|
||||
@ -127,6 +105,17 @@
|
||||
__asm volatile ("cpsie i" ::: "memory"); \
|
||||
} while (false)
|
||||
|
||||
#else // no BASEPRI (QV uses PRIMASK)
|
||||
// macro to put the CPU to sleep inside QV_onIdle()
|
||||
#define QV_CPU_SLEEP() do { \
|
||||
__asm volatile ("wfi"::: "memory"); \
|
||||
QF_INT_ENABLE(); \
|
||||
} while (false)
|
||||
#endif // no BASEPRI (QV uses PRIMASK)
|
||||
|
||||
#if (__ARM_ARCH == 6) // ARMv6-M?
|
||||
#define QV_ARM_ERRATUM_838869() ((void)0)
|
||||
#else // ARMv7-M or higher
|
||||
// The following macro implements the recommended workaround for the
|
||||
// ARM Erratum 838869. Specifically, for Cortex-M3/M4/M7 the DSB
|
||||
// (memory barrier) instruction needs to be added before exiting an ISR.
|
||||
@ -168,7 +157,7 @@ extern int32_t volatile QF_int_lock_nest_;
|
||||
// functions. They are defined as "weak" in the qv_port.c module,
|
||||
// so the application can provide a different implementation.
|
||||
// Please see the definitions of the interrupt and critical-section
|
||||
// funcctions in the qv_port.c module for details.
|
||||
// functions in the qv_port.c module for details.
|
||||
//
|
||||
// NOTE2:
|
||||
// On Cortex-M0/M0+/M1 (architecture ARMv6-M, ARMv6S-M), the interrupt
|
||||
@ -177,15 +166,15 @@ extern int32_t volatile QF_int_lock_nest_;
|
||||
// are "kernel-aware".
|
||||
//
|
||||
// NOTE3:
|
||||
// On ARMv7-M or higher, the interrupt disable/enable policy uses the BASEPRI
|
||||
// register (which is not implemented in ARMv6-M) to disable interrupts only
|
||||
// with priority lower than the threshold specified by the QF_BASEPRI macro.
|
||||
// The interrupts with priorities above QF_BASEPRI (i.e., with numerical
|
||||
// priority values lower than QF_BASEPRI) are NOT disabled in this method.
|
||||
// If macro QF_USE_BASEPRI is defined, the interrupt disable/enable policy
|
||||
// uses BASEPRI register to disable interrupts only with priority lower than
|
||||
// the threshold specified by the QF_USE_BASEPRI macro. The interrupts with
|
||||
// priorities above QF_USE_BASEPRI (i.e., with numerical priority values
|
||||
// lower than QF_USE_BASEPRI) are NOT disabled in this method.
|
||||
// These free-running interrupts have very low ("zero") latency, but they
|
||||
// are NOT allowed to call any QF services, because QF is unaware of them
|
||||
// ("kernel-unaware" interrupts). Consequently, only interrupts with
|
||||
// numerical values of priorities equal to or higher than QF_BASEPRI
|
||||
// numerical values of priorities equal to or higher than QF_USE_BASEPRI
|
||||
// ("kernel-aware" interrupts ), can call QF services.
|
||||
//
|
||||
// NOTE4:
|
||||
|
@ -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 QV/C port to ARM Cortex-M, ARM-CLANG
|
||||
|
||||
#define QP_IMPL 1U
|
||||
#include "qp_port.h"
|
||||
#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
|
||||
@ -57,7 +51,6 @@
|
||||
// For best performance, these functions are implemented in assembly,
|
||||
// but they can be implemented in C as well.
|
||||
|
||||
|
||||
//int32_t volatile QF_int_lock_nest_; // not used
|
||||
extern char const QF_port_module_[];
|
||||
char const QF_port_module_[] = "qv_port";
|
||||
@ -66,24 +59,23 @@ char const QF_port_module_[] = "qv_port";
|
||||
// Unconditionally disable interrupts.
|
||||
// NOTE: this function must NOT use the stack.
|
||||
//
|
||||
// description:
|
||||
// On ARMv6-M, interrupts are disabled with the PRIMASK register.
|
||||
// On ARMv7-M and higher, interrupts are disabled *selectively* with the
|
||||
// BASEPRI register.
|
||||
// Description:
|
||||
// When QF_USE_BASEPRI is defined, interrupts are disabled with BASEPRI.
|
||||
// Otherwise interrupts are disabled with the PRIMASK register.
|
||||
// Additionally, the function also asserts that the interrupts are
|
||||
// NOT disabled upon the entry to the function, which means that
|
||||
// this interrupt management policy CANNOT nest.
|
||||
__attribute__ ((naked, weak))
|
||||
void QF_int_disable_(void) {
|
||||
__asm volatile (
|
||||
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
|
||||
#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"
|
||||
@ -98,28 +90,29 @@ __asm volatile (
|
||||
// Unconditionally enable interrupts.
|
||||
// NOTE: this function must NOT use the stack.
|
||||
//
|
||||
// description:
|
||||
// On ARMv6-M, interrupts are enabled with the PRIMASK register.
|
||||
// On ARMv7-M and higher, interrupts are enabled with the BASEPRI register.
|
||||
// Description:
|
||||
// When QF_USE_BASEPRI is defined, interrupts are enabled with BASEPRI.
|
||||
// Otherwise interrupts are enabled with the PRIMASK register.
|
||||
// Additionally, the function also asserts that the interrupts ARE
|
||||
// disabled upon the entry to the function, which means that
|
||||
// this interrupt management policy CANNOT nest.
|
||||
__attribute__ ((naked, weak))
|
||||
void QF_int_enable_(void) {
|
||||
__asm volatile (
|
||||
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
|
||||
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
|
||||
#else //--------- ARMv7-M or higher
|
||||
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for enabling interrupts?
|
||||
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
|
||||
#endif //--------- ARMv7-M or higher
|
||||
#else //--------- use PRIMASK for enabling interrupts
|
||||
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
|
||||
#endif //--------- use PRIMASK for enabling interrupts
|
||||
|
||||
" CMP r0,#0 \n" // assert(PRIMASK/BASEPRI != 0)
|
||||
" BEQ QF_int_enable_error\n"
|
||||
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
|
||||
" CPSIE i \n" // clear PRIMASK
|
||||
#else //--------- ARMv7-M or higher
|
||||
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for enabling interrupts?
|
||||
" MOVS r1,#0 \n"
|
||||
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
|
||||
#endif //--------- ARMv7-M or higher
|
||||
#else //--------- use PRIMASK for enabling interrupts
|
||||
" CPSIE i \n" // clear PRIMASK
|
||||
#endif //--------- use PRIMASK for enabling interrupts
|
||||
" BX lr \n"
|
||||
"QF_int_enable_error: \n"
|
||||
" LDR r0,=QF_port_module_ \n"
|
||||
@ -132,25 +125,23 @@ __asm volatile (
|
||||
// Enter QF critical section.
|
||||
// NOTE: this function must NOT use the stack.
|
||||
//
|
||||
// description:
|
||||
// On ARMv6-M, critical section is entered by disabling interrupts
|
||||
// with the PRIMASK register.
|
||||
// On ARMv7-M and higher, critical section is entered by disabling
|
||||
// interrupts *selectively* with the BASEPRI register.
|
||||
// Description:
|
||||
// When QF_USE_BASEPRI is defined, critical section uses BASEPRI.
|
||||
// Otherwise, critical section uses the PRIMASK register.
|
||||
// Additionally, the function also asserts that the interrupts are
|
||||
// NOT disabled upon the entry to the function, which means that
|
||||
// this critical section CANNOT nest.
|
||||
__attribute__ ((naked, weak))
|
||||
void QF_crit_entry_(void) {
|
||||
__asm volatile (
|
||||
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
|
||||
#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"
|
||||
@ -166,29 +157,27 @@ __asm volatile (
|
||||
// NOTE: this function must NOT use the stack.
|
||||
//
|
||||
// description:
|
||||
// On ARMv6-M, critical section is exited by enabling interrupts
|
||||
// with the PRIMASK register.
|
||||
// On ARMv7-M and higher, critical section is exited by enabling
|
||||
// interrupts with the BASEPRI register.
|
||||
// When QF_USE_BASEPRI is defined, critical section uses BASEPRI.
|
||||
// Otherwise, critical section uses the PRIMASK register.
|
||||
// Additionally, the function also asserts that the interrupts ARE
|
||||
// disabled upon the entry to the function, which means that
|
||||
// this critical section CANNOT nest.
|
||||
__attribute__ ((naked, weak))
|
||||
void QF_crit_exit_(void) {
|
||||
__asm volatile (
|
||||
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
|
||||
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
|
||||
#else //--------- ARMv7-M or higher
|
||||
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
|
||||
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
|
||||
#endif //--------- ARMv7-M or higher
|
||||
#else //--------- use PRIMASK for critical section
|
||||
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
|
||||
#endif //--------- use PRIMASK for critical section
|
||||
" CMP r0,#0 \n" // assert(PRIMASK/BASEPRI != 0)
|
||||
" BEQ QF_crit_exit_error\n"
|
||||
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
|
||||
" CPSIE i \n" // clear PRIMASK
|
||||
#else //--------- ARMv7-M or higher
|
||||
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
|
||||
" MOVS r1,#0 \n"
|
||||
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
|
||||
#endif //--------- ARMv7-M or higher
|
||||
#else //--------- use PRIMASK
|
||||
" CPSIE i \n" // clear PRIMASK
|
||||
#endif //--------- use PRIMASK
|
||||
" BX lr \n"
|
||||
"QF_crit_exit_error: \n"
|
||||
" LDR r0,=QF_port_module_ \n"
|
||||
@ -206,7 +195,7 @@ __asm volatile (
|
||||
// BASEPRI register. However, this method cannot disable interrupt
|
||||
// priority zero, which is the default for all interrupts out of reset.
|
||||
// The following code changes the SysTick priority and all IRQ priorities
|
||||
// to the safe value QF_BASEPRI, which the QF critical section can disable.
|
||||
// to the safe value QF_USE_BASEPRI, which the QF critical section can disable.
|
||||
// This avoids breaching of the QF critical sections in case the
|
||||
// application programmer forgets to explicitly set priorities of all
|
||||
// "kernel aware" interrupts.
|
||||
@ -215,18 +204,18 @@ __asm volatile (
|
||||
// by the application-level code.
|
||||
void QV_init(void) {
|
||||
|
||||
#if (__ARM_ARCH != 6) //--------- if ARMv7-M and higher...
|
||||
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
|
||||
|
||||
// SCB_SYSPRI[2]: SysTick
|
||||
SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_BASEPRI << 24U));
|
||||
SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_USE_BASEPRI << 24U));
|
||||
|
||||
// set all 240 possible IRQ priories to QF_BASEPRI...
|
||||
// set all 240 possible IRQ priories to QF_USE_BASEPRI...
|
||||
for (uint_fast8_t n = 0U; n < (240U/sizeof(uint32_t)); ++n) {
|
||||
NVIC_IP[n] = (QF_BASEPRI << 24U) | (QF_BASEPRI << 16U)
|
||||
| (QF_BASEPRI << 8U) | QF_BASEPRI;
|
||||
NVIC_IP[n] = (QF_USE_BASEPRI << 24U) | (QF_USE_BASEPRI << 16U)
|
||||
| (QF_USE_BASEPRI << 8U) | QF_USE_BASEPRI;
|
||||
}
|
||||
|
||||
#endif //--------- ARMv7-M or higher
|
||||
#endif //--------- use BASEPRI for critical section
|
||||
|
||||
#ifdef __ARM_FP //--------- if VFP available...
|
||||
// make sure that the FPU is enabled by setting CP10 & CP11 Full Access
|
||||
|
@ -1,236 +0,0 @@
|
||||
//============================================================================
|
||||
// QP configuration file (QV on ARM Cortex-M)
|
||||
//
|
||||
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
|
||||
//
|
||||
// Q u a n t u m L e a P s
|
||||
// ------------------------
|
||||
// Modern Embedded Software
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
|
||||
//
|
||||
// The QP/C software is dual-licensed under the terms of the open-source GNU
|
||||
// General Public License (GPL) or under the terms of one of the closed-
|
||||
// source Quantum Leaps commercial licenses.
|
||||
//
|
||||
// Redistributions in source code must retain this top-level comment block.
|
||||
// Plagiarizing this software to sidestep the license obligations is illegal.
|
||||
//
|
||||
// NOTE:
|
||||
// The GPL (see <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_H_
|
||||
#define QP_CONFIG_H_
|
||||
|
||||
//-------- <<< 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>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 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_H_
|
@ -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 QP/C port to ARM Cortex-M, cooperative QV kernel, GNU-ARM
|
||||
|
||||
#ifndef QP_PORT_H_
|
||||
#define QP_PORT_H_
|
||||
|
||||
@ -47,31 +41,9 @@
|
||||
// QV event-queue used for AOs
|
||||
#define QACTIVE_EQUEUE_TYPE QEQueue
|
||||
|
||||
// QF "thread" type used to store the MPU settings in the AO
|
||||
// QActive "thread" type used to store the MPU settings in the AO
|
||||
#define QACTIVE_THREAD_TYPE void const *
|
||||
|
||||
// QF interrupt disable/enable and log2()...
|
||||
#if (__ARM_ARCH == 6) // ARMv6-M?
|
||||
|
||||
// CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4
|
||||
#define QF_AWARE_ISR_CMSIS_PRI 0
|
||||
|
||||
// hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M)
|
||||
#define QF_LOG2(n_) QF_qlog2((uint32_t)(n_))
|
||||
|
||||
#else // ARMv7-M or higher
|
||||
|
||||
// BASEPRI threshold for "QF-aware" interrupts, see NOTE3
|
||||
#define QF_BASEPRI 0x3F
|
||||
|
||||
// CMSIS threshold for "QF-aware" interrupts, see NOTE4
|
||||
#define QF_AWARE_ISR_CMSIS_PRI (QF_BASEPRI >> (8 - __NVIC_PRIO_BITS))
|
||||
|
||||
// ARMv7-M or higher provide the CLZ instruction for fast LOG2
|
||||
#define QF_LOG2(n_) ((uint_fast8_t)(32 - __builtin_clz((unsigned)(n_))))
|
||||
|
||||
#endif
|
||||
|
||||
// interrupt disabling policy, see NOTE2 and NOTE3
|
||||
#define QF_INT_DISABLE() (QF_int_disable_())
|
||||
#define QF_INT_ENABLE() (QF_int_enable_())
|
||||
@ -83,11 +55,27 @@
|
||||
|
||||
#define QF_CRIT_EXIT_NOP() __asm volatile ("isb" ::: "memory")
|
||||
|
||||
// Efficient log2() ----------------------------------------------------------
|
||||
#if (__ARM_ARCH == 6) // ARMv6-M?
|
||||
// hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M)
|
||||
#define QF_LOG2(n_) QF_qlog2((uint32_t)(n_))
|
||||
|
||||
// hand-optimized quick LOG2 in assembly
|
||||
uint_fast8_t QF_qlog2(uint32_t x);
|
||||
#else // ARMv7-M or higher
|
||||
// ARMv7-M or higher provide the CLZ instruction for fast LOG2
|
||||
#define QF_LOG2(n_) ((uint_fast8_t)(32 - __builtin_clz((unsigned)(n_))))
|
||||
#endif // ARMv7-M or higher
|
||||
|
||||
// Critical section policy ---------------------------------------------------
|
||||
#ifdef QF_USE_BASEPRI
|
||||
// CMSIS threshold for "QF-aware" interrupts, see NOTE4
|
||||
#define QF_AWARE_ISR_CMSIS_PRI (QF_USE_BASEPRI >> (8 - __NVIC_PRIO_BITS))
|
||||
#else
|
||||
// CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4
|
||||
#define QF_AWARE_ISR_CMSIS_PRI 0
|
||||
#endif // QF_USE_BASEPRI
|
||||
|
||||
// Memory isolation ----------------------------------------------------------
|
||||
#ifdef QF_MEM_ISOLATE
|
||||
|
||||
@ -104,20 +92,10 @@
|
||||
void QF_onMemSys(void);
|
||||
void QF_onMemApp(void);
|
||||
|
||||
#endif // def QF_MEM_ISOLATE
|
||||
#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 { \
|
||||
@ -127,6 +105,17 @@
|
||||
__asm volatile ("cpsie i" ::: "memory"); \
|
||||
} while (false)
|
||||
|
||||
#else // no BASEPRI (QV uses PRIMASK)
|
||||
// macro to put the CPU to sleep inside QV_onIdle()
|
||||
#define QV_CPU_SLEEP() do { \
|
||||
__asm volatile ("wfi"::: "memory"); \
|
||||
QF_INT_ENABLE(); \
|
||||
} while (false)
|
||||
#endif // no BASEPRI (QV uses PRIMASK)
|
||||
|
||||
#if (__ARM_ARCH == 6) // ARMv6-M?
|
||||
#define QV_ARM_ERRATUM_838869() ((void)0)
|
||||
#else // ARMv7-M or higher
|
||||
// The following macro implements the recommended workaround for the
|
||||
// ARM Erratum 838869. Specifically, for Cortex-M3/M4/M7 the DSB
|
||||
// (memory barrier) instruction needs to be added before exiting an ISR.
|
||||
@ -168,7 +157,7 @@ extern int32_t volatile QF_int_lock_nest_;
|
||||
// functions. They are defined as "weak" in the qv_port.c module,
|
||||
// so the application can provide a different implementation.
|
||||
// Please see the definitions of the interrupt and critical-section
|
||||
// funcctions in the qv_port.c module for details.
|
||||
// functions in the qv_port.c module for details.
|
||||
//
|
||||
// NOTE2:
|
||||
// On Cortex-M0/M0+/M1 (architecture ARMv6-M, ARMv6S-M), the interrupt
|
||||
@ -177,15 +166,15 @@ extern int32_t volatile QF_int_lock_nest_;
|
||||
// are "kernel-aware".
|
||||
//
|
||||
// NOTE3:
|
||||
// On ARMv7-M or higher, the interrupt disable/enable policy uses the BASEPRI
|
||||
// register (which is not implemented in ARMv6-M) to disable interrupts only
|
||||
// with priority lower than the threshold specified by the QF_BASEPRI macro.
|
||||
// The interrupts with priorities above QF_BASEPRI (i.e., with numerical
|
||||
// priority values lower than QF_BASEPRI) are NOT disabled in this method.
|
||||
// If macro QF_USE_BASEPRI is defined, the interrupt disable/enable policy
|
||||
// uses BASEPRI register to disable interrupts only with priority lower than
|
||||
// the threshold specified by the QF_USE_BASEPRI macro. The interrupts with
|
||||
// priorities above QF_USE_BASEPRI (i.e., with numerical priority values
|
||||
// lower than QF_USE_BASEPRI) are NOT disabled in this method.
|
||||
// These free-running interrupts have very low ("zero") latency, but they
|
||||
// are NOT allowed to call any QF services, because QF is unaware of them
|
||||
// ("kernel-unaware" interrupts). Consequently, only interrupts with
|
||||
// numerical values of priorities equal to or higher than QF_BASEPRI
|
||||
// numerical values of priorities equal to or higher than QF_USE_BASEPRI
|
||||
// ("kernel-aware" interrupts ), can call QF services.
|
||||
//
|
||||
// NOTE4:
|
||||
|
@ -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 QV/C port to ARM Cortex-M, GNU-ARM
|
||||
|
||||
#define QP_IMPL 1U
|
||||
#include "qp_port.h"
|
||||
#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
|
||||
@ -57,7 +51,6 @@
|
||||
// For best performance, these functions are implemented in assembly,
|
||||
// but they can be implemented in C as well.
|
||||
|
||||
|
||||
//int32_t volatile QF_int_lock_nest_; // not used
|
||||
extern char const QF_port_module_[];
|
||||
char const QF_port_module_[] = "qv_port";
|
||||
@ -66,24 +59,23 @@ char const QF_port_module_[] = "qv_port";
|
||||
// Unconditionally disable interrupts.
|
||||
// NOTE: this function must NOT use the stack.
|
||||
//
|
||||
// description:
|
||||
// On ARMv6-M, interrupts are disabled with the PRIMASK register.
|
||||
// On ARMv7-M and higher, interrupts are disabled *selectively* with the
|
||||
// BASEPRI register.
|
||||
// Description:
|
||||
// When QF_USE_BASEPRI is defined, interrupts are disabled with BASEPRI.
|
||||
// Otherwise interrupts are disabled with the PRIMASK register.
|
||||
// Additionally, the function also asserts that the interrupts are
|
||||
// NOT disabled upon the entry to the function, which means that
|
||||
// this interrupt management policy CANNOT nest.
|
||||
__attribute__ ((naked, weak))
|
||||
void QF_int_disable_(void) {
|
||||
__asm volatile (
|
||||
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
|
||||
#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"
|
||||
@ -98,28 +90,29 @@ __asm volatile (
|
||||
// Unconditionally enable interrupts.
|
||||
// NOTE: this function must NOT use the stack.
|
||||
//
|
||||
// description:
|
||||
// On ARMv6-M, interrupts are enabled with the PRIMASK register.
|
||||
// On ARMv7-M and higher, interrupts are enabled with the BASEPRI register.
|
||||
// Description:
|
||||
// When QF_USE_BASEPRI is defined, interrupts are enabled with BASEPRI.
|
||||
// Otherwise interrupts are enabled with the PRIMASK register.
|
||||
// Additionally, the function also asserts that the interrupts ARE
|
||||
// disabled upon the entry to the function, which means that
|
||||
// this interrupt management policy CANNOT nest.
|
||||
__attribute__ ((naked, weak))
|
||||
void QF_int_enable_(void) {
|
||||
__asm volatile (
|
||||
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
|
||||
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
|
||||
#else //--------- ARMv7-M or higher
|
||||
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for enabling interrupts?
|
||||
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
|
||||
#endif //--------- ARMv7-M or higher
|
||||
#else //--------- use PRIMASK for enabling interrupts
|
||||
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
|
||||
#endif //--------- use PRIMASK for enabling interrupts
|
||||
|
||||
" CMP r0,#0 \n" // assert(PRIMASK/BASEPRI != 0)
|
||||
" BEQ QF_int_enable_error\n"
|
||||
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
|
||||
" CPSIE i \n" // clear PRIMASK
|
||||
#else //--------- ARMv7-M or higher
|
||||
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for enabling interrupts?
|
||||
" MOVS r1,#0 \n"
|
||||
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
|
||||
#endif //--------- ARMv7-M or higher
|
||||
#else //--------- use PRIMASK for enabling interrupts
|
||||
" CPSIE i \n" // clear PRIMASK
|
||||
#endif //--------- use PRIMASK for enabling interrupts
|
||||
" BX lr \n"
|
||||
"QF_int_enable_error: \n"
|
||||
" LDR r0,=QF_port_module_ \n"
|
||||
@ -132,25 +125,23 @@ __asm volatile (
|
||||
// Enter QF critical section.
|
||||
// NOTE: this function must NOT use the stack.
|
||||
//
|
||||
// description:
|
||||
// On ARMv6-M, critical section is entered by disabling interrupts
|
||||
// with the PRIMASK register.
|
||||
// On ARMv7-M and higher, critical section is entered by disabling
|
||||
// interrupts *selectively* with the BASEPRI register.
|
||||
// Description:
|
||||
// When QF_USE_BASEPRI is defined, critical section uses BASEPRI.
|
||||
// Otherwise, critical section uses the PRIMASK register.
|
||||
// Additionally, the function also asserts that the interrupts are
|
||||
// NOT disabled upon the entry to the function, which means that
|
||||
// this critical section CANNOT nest.
|
||||
__attribute__ ((naked, weak))
|
||||
void QF_crit_entry_(void) {
|
||||
__asm volatile (
|
||||
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
|
||||
#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"
|
||||
@ -166,29 +157,27 @@ __asm volatile (
|
||||
// NOTE: this function must NOT use the stack.
|
||||
//
|
||||
// description:
|
||||
// On ARMv6-M, critical section is exited by enabling interrupts
|
||||
// with the PRIMASK register.
|
||||
// On ARMv7-M and higher, critical section is exited by enabling
|
||||
// interrupts with the BASEPRI register.
|
||||
// When QF_USE_BASEPRI is defined, critical section uses BASEPRI.
|
||||
// Otherwise, critical section uses the PRIMASK register.
|
||||
// Additionally, the function also asserts that the interrupts ARE
|
||||
// disabled upon the entry to the function, which means that
|
||||
// this critical section CANNOT nest.
|
||||
__attribute__ ((naked, weak))
|
||||
void QF_crit_exit_(void) {
|
||||
__asm volatile (
|
||||
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
|
||||
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
|
||||
#else //--------- ARMv7-M or higher
|
||||
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
|
||||
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
|
||||
#endif //--------- ARMv7-M or higher
|
||||
#else //--------- use PRIMASK for critical section
|
||||
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
|
||||
#endif //--------- use PRIMASK for critical section
|
||||
" CMP r0,#0 \n" // assert(PRIMASK/BASEPRI != 0)
|
||||
" BEQ QF_crit_exit_error\n"
|
||||
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
|
||||
" CPSIE i \n" // clear PRIMASK
|
||||
#else //--------- ARMv7-M or higher
|
||||
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
|
||||
" MOVS r1,#0 \n"
|
||||
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
|
||||
#endif //--------- ARMv7-M or higher
|
||||
#else //--------- use PRIMASK
|
||||
" CPSIE i \n" // clear PRIMASK
|
||||
#endif //--------- use PRIMASK
|
||||
" BX lr \n"
|
||||
"QF_crit_exit_error: \n"
|
||||
" LDR r0,=QF_port_module_ \n"
|
||||
@ -206,7 +195,7 @@ __asm volatile (
|
||||
// BASEPRI register. However, this method cannot disable interrupt
|
||||
// priority zero, which is the default for all interrupts out of reset.
|
||||
// The following code changes the SysTick priority and all IRQ priorities
|
||||
// to the safe value QF_BASEPRI, which the QF critical section can disable.
|
||||
// to the safe value QF_USE_BASEPRI, which the QF critical section can disable.
|
||||
// This avoids breaching of the QF critical sections in case the
|
||||
// application programmer forgets to explicitly set priorities of all
|
||||
// "kernel aware" interrupts.
|
||||
@ -215,18 +204,18 @@ __asm volatile (
|
||||
// by the application-level code.
|
||||
void QV_init(void) {
|
||||
|
||||
#if (__ARM_ARCH != 6) //--------- if ARMv7-M and higher...
|
||||
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
|
||||
|
||||
// SCB_SYSPRI[2]: SysTick
|
||||
SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_BASEPRI << 24U));
|
||||
SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_USE_BASEPRI << 24U));
|
||||
|
||||
// set all 240 possible IRQ priories to QF_BASEPRI...
|
||||
// set all 240 possible IRQ priories to QF_USE_BASEPRI...
|
||||
for (uint_fast8_t n = 0U; n < (240U/sizeof(uint32_t)); ++n) {
|
||||
NVIC_IP[n] = (QF_BASEPRI << 24U) | (QF_BASEPRI << 16U)
|
||||
| (QF_BASEPRI << 8U) | QF_BASEPRI;
|
||||
NVIC_IP[n] = (QF_USE_BASEPRI << 24U) | (QF_USE_BASEPRI << 16U)
|
||||
| (QF_USE_BASEPRI << 8U) | QF_USE_BASEPRI;
|
||||
}
|
||||
|
||||
#endif //--------- ARMv7-M or higher
|
||||
#endif //--------- use BASEPRI for critical section
|
||||
|
||||
#ifdef __ARM_FP //--------- if VFP available...
|
||||
// make sure that the FPU is enabled by setting CP10 & CP11 Full Access
|
||||
|
@ -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 QP/C port to ARM Cortex-M, cooperative QV kernel, IAR-ARM
|
||||
|
||||
#ifndef QP_PORT_H_
|
||||
#define QP_PORT_H_
|
||||
|
||||
@ -48,31 +42,9 @@
|
||||
// QV event-queue used for AOs
|
||||
#define QACTIVE_EQUEUE_TYPE QEQueue
|
||||
|
||||
// QF "thread" type used to store the MPU settings in the AO
|
||||
// QActive "thread" type used to store the MPU settings in the AO
|
||||
#define QACTIVE_THREAD_TYPE void const *
|
||||
|
||||
// QF interrupt disable/enable and log2()...
|
||||
#if (__ARM_ARCH == 6) // ARMv6-M?
|
||||
|
||||
// CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4
|
||||
#define QF_AWARE_ISR_CMSIS_PRI 0
|
||||
|
||||
// hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M)
|
||||
#define QF_LOG2(n_) QF_qlog2((uint32_t)(n_))
|
||||
|
||||
#else // ARMv7-M or higher
|
||||
|
||||
// BASEPRI threshold for "QF-aware" interrupts, see NOTE3
|
||||
#define QF_BASEPRI 0x3F
|
||||
|
||||
// CMSIS threshold for "QF-aware" interrupts, see NOTE4
|
||||
#define QF_AWARE_ISR_CMSIS_PRI (QF_BASEPRI >> (8 - __NVIC_PRIO_BITS))
|
||||
|
||||
// ARMv7-M or higher provide the CLZ instruction for fast LOG2
|
||||
#define QF_LOG2(n_) ((uint_fast8_t)(32U - __CLZ((unsigned long)(n_))))
|
||||
|
||||
#endif
|
||||
|
||||
// interrupt disabling policy, see NOTE2 and NOTE3
|
||||
#define QF_INT_DISABLE() (QF_int_disable_())
|
||||
#define QF_INT_ENABLE() (QF_int_enable_())
|
||||
@ -82,13 +54,29 @@
|
||||
#define QF_CRIT_ENTRY() (QF_crit_entry_())
|
||||
#define QF_CRIT_EXIT() (QF_crit_exit_())
|
||||
|
||||
#define QF_CRIT_EXIT_NOP() __asm volatile ("isb" ::: "memory")
|
||||
#define QF_CRIT_EXIT_NOP() __ISB()
|
||||
|
||||
// Efficient log2() ----------------------------------------------------------
|
||||
#if (__ARM_ARCH == 6) // ARMv6-M?
|
||||
// hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M)
|
||||
#define QF_LOG2(n_) QF_qlog2((uint32_t)(n_))
|
||||
|
||||
// hand-optimized quick LOG2 in assembly
|
||||
uint_fast8_t QF_qlog2(uint32_t x);
|
||||
#else // ARMv7-M or higher
|
||||
// ARMv7-M or higher provide the CLZ instruction for fast LOG2
|
||||
#define QF_LOG2(n_) ((uint_fast8_t)(32U - __CLZ((unsigned long)(n_))))
|
||||
#endif // ARMv7-M or higher
|
||||
|
||||
// Critical section policy ---------------------------------------------------
|
||||
#ifdef QF_USE_BASEPRI
|
||||
// CMSIS threshold for "QF-aware" interrupts, see NOTE4
|
||||
#define QF_AWARE_ISR_CMSIS_PRI (QF_USE_BASEPRI >> (8 - __NVIC_PRIO_BITS))
|
||||
#else
|
||||
// CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4
|
||||
#define QF_AWARE_ISR_CMSIS_PRI 0
|
||||
#endif // QF_USE_BASEPRI
|
||||
|
||||
// Memory isolation ----------------------------------------------------------
|
||||
#ifdef QF_MEM_ISOLATE
|
||||
|
||||
@ -105,20 +93,10 @@
|
||||
void QF_onMemSys(void);
|
||||
void QF_onMemApp(void);
|
||||
|
||||
#endif // def QF_MEM_ISOLATE
|
||||
#endif // QF_MEM_ISOLATE
|
||||
|
||||
// determination if the code executes in the ISR context
|
||||
#if (__ARM_ARCH == 6) // ARMv6-M?
|
||||
|
||||
// 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 { \
|
||||
@ -128,6 +106,17 @@
|
||||
__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() ((void)0)
|
||||
#else // ARMv7-M or higher
|
||||
// The following macro implements the recommended workaround for the
|
||||
// ARM Erratum 838869. Specifically, for Cortex-M3/M4/M7 the DSB
|
||||
// (memory barrier) instruction needs to be added before exiting an ISR.
|
||||
@ -169,7 +158,7 @@ extern int32_t volatile QF_int_lock_nest_;
|
||||
// functions. They are defined as "weak" in the qv_port.c module,
|
||||
// so the application can provide a different implementation.
|
||||
// Please see the definitions of the interrupt and critical-section
|
||||
// funcctions in the qv_port.c module for details.
|
||||
// functions in the qv_port.c module for details.
|
||||
//
|
||||
// NOTE2:
|
||||
// On Cortex-M0/M0+/M1 (architecture ARMv6-M, ARMv6S-M), the interrupt
|
||||
@ -178,15 +167,15 @@ extern int32_t volatile QF_int_lock_nest_;
|
||||
// are "kernel-aware".
|
||||
//
|
||||
// NOTE3:
|
||||
// On ARMv7-M or higher, the interrupt disable/enable policy uses the BASEPRI
|
||||
// register (which is not implemented in ARMv6-M) to disable interrupts only
|
||||
// with priority lower than the threshold specified by the QF_BASEPRI macro.
|
||||
// The interrupts with priorities above QF_BASEPRI (i.e., with numerical
|
||||
// priority values lower than QF_BASEPRI) are NOT disabled in this method.
|
||||
// If macro QF_USE_BASEPRI is defined, the interrupt disable/enable policy
|
||||
// uses BASEPRI register to disable interrupts only with priority lower than
|
||||
// the threshold specified by the QF_USE_BASEPRI macro. The interrupts with
|
||||
// priorities above QF_USE_BASEPRI (i.e., with numerical priority values
|
||||
// lower than QF_USE_BASEPRI) are NOT disabled in this method.
|
||||
// These free-running interrupts have very low ("zero") latency, but they
|
||||
// are NOT allowed to call any QF services, because QF is unaware of them
|
||||
// ("kernel-unaware" interrupts). Consequently, only interrupts with
|
||||
// numerical values of priorities equal to or higher than QF_BASEPRI
|
||||
// numerical values of priorities equal to or higher than QF_USE_BASEPRI
|
||||
// ("kernel-aware" interrupts ), can call QF services.
|
||||
//
|
||||
// NOTE4:
|
||||
|
@ -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 QV/C port to ARM Cortex-M, IAR-ARM
|
||||
|
||||
#define QP_IMPL 1U
|
||||
#include "qp_port.h"
|
||||
#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
|
||||
@ -70,24 +64,23 @@ char const QF_port_module_[] = "qv_port";
|
||||
// Unconditionally disable interrupts.
|
||||
// NOTE: this function must NOT use the stack.
|
||||
//
|
||||
// description:
|
||||
// On ARMv6-M, interrupts are disabled with the PRIMASK register.
|
||||
// On ARMv7-M and higher, interrupts are disabled *selectively* with the
|
||||
// BASEPRI register.
|
||||
// Description:
|
||||
// When QF_USE_BASEPRI is defined, interrupts are disabled with BASEPRI.
|
||||
// Otherwise interrupts are disabled with the PRIMASK register.
|
||||
// Additionally, the function also asserts that the interrupts are
|
||||
// NOT disabled upon the entry to the function, which means that
|
||||
// this interrupt management policy CANNOT nest.
|
||||
__stackless
|
||||
void QF_int_disable_(void) {
|
||||
__asm volatile (
|
||||
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
|
||||
#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"
|
||||
@ -102,28 +95,29 @@ __asm volatile (
|
||||
// Unconditionally enable interrupts.
|
||||
// NOTE: this function must NOT use the stack.
|
||||
//
|
||||
// description:
|
||||
// On ARMv6-M, interrupts are enabled with the PRIMASK register.
|
||||
// On ARMv7-M and higher, interrupts are enabled with the BASEPRI register.
|
||||
// Description:
|
||||
// When QF_USE_BASEPRI is defined, interrupts are enabled with BASEPRI.
|
||||
// Otherwise interrupts are enabled with the PRIMASK register.
|
||||
// Additionally, the function also asserts that the interrupts ARE
|
||||
// disabled upon the entry to the function, which means that
|
||||
// this interrupt management policy CANNOT nest.
|
||||
__stackless
|
||||
void QF_int_enable_(void) {
|
||||
__asm volatile (
|
||||
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
|
||||
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
|
||||
#else //--------- ARMv7-M or higher
|
||||
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for enabling interrupts?
|
||||
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
|
||||
#endif //--------- ARMv7-M or higher
|
||||
#else //--------- use PRIMASK for enabling interrupts
|
||||
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
|
||||
#endif //--------- use PRIMASK for enabling interrupts
|
||||
|
||||
" CMP r0,#0 \n" // assert(PRIMASK/BASEPRI != 0)
|
||||
" BEQ QF_int_enable_error\n"
|
||||
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
|
||||
" CPSIE i \n" // clear PRIMASK
|
||||
#else //--------- ARMv7-M or higher
|
||||
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for enabling interrupts?
|
||||
" MOVS r1,#0 \n"
|
||||
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
|
||||
#endif //--------- ARMv7-M or higher
|
||||
#else //--------- use PRIMASK for enabling interrupts
|
||||
" CPSIE i \n" // clear PRIMASK
|
||||
#endif //--------- use PRIMASK for enabling interrupts
|
||||
" BX lr \n"
|
||||
"QF_int_enable_error: \n"
|
||||
" LDR r0,=QF_port_module_ \n"
|
||||
@ -136,25 +130,23 @@ __asm volatile (
|
||||
// Enter QF critical section.
|
||||
// NOTE: this function must NOT use the stack.
|
||||
//
|
||||
// description:
|
||||
// On ARMv6-M, critical section is entered by disabling interrupts
|
||||
// with the PRIMASK register.
|
||||
// On ARMv7-M and higher, critical section is entered by disabling
|
||||
// interrupts *selectively* with the BASEPRI register.
|
||||
// Description:
|
||||
// When QF_USE_BASEPRI is defined, critical section uses BASEPRI.
|
||||
// Otherwise, critical section uses the PRIMASK register.
|
||||
// Additionally, the function also asserts that the interrupts are
|
||||
// NOT disabled upon the entry to the function, which means that
|
||||
// this critical section CANNOT nest.
|
||||
__stackless
|
||||
void QF_crit_entry_(void) {
|
||||
__asm volatile (
|
||||
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
|
||||
#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"
|
||||
@ -170,29 +162,27 @@ __asm volatile (
|
||||
// NOTE: this function must NOT use the stack.
|
||||
//
|
||||
// description:
|
||||
// On ARMv6-M, critical section is exited by enabling interrupts
|
||||
// with the PRIMASK register.
|
||||
// On ARMv7-M and higher, critical section is exited by enabling
|
||||
// interrupts with the BASEPRI register.
|
||||
// When QF_USE_BASEPRI is defined, critical section uses BASEPRI.
|
||||
// Otherwise, critical section uses the PRIMASK register.
|
||||
// Additionally, the function also asserts that the interrupts ARE
|
||||
// disabled upon the entry to the function, which means that
|
||||
// this critical section CANNOT nest.
|
||||
__stackless
|
||||
void QF_crit_exit_(void) {
|
||||
__asm volatile (
|
||||
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
|
||||
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
|
||||
#else //--------- ARMv7-M or higher
|
||||
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
|
||||
" MRS r0,BASEPRI \n" // r0 <- previous BASEPRI
|
||||
#endif //--------- ARMv7-M or higher
|
||||
#else //--------- use PRIMASK for critical section
|
||||
" MRS r0,PRIMASK \n" // r0 <- previous PRIMASK
|
||||
#endif //--------- use PRIMASK for critical section
|
||||
" CMP r0,#0 \n" // assert(PRIMASK/BASEPRI != 0)
|
||||
" BEQ QF_crit_exit_error\n"
|
||||
#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture?
|
||||
" CPSIE i \n" // clear PRIMASK
|
||||
#else //--------- ARMv7-M or higher
|
||||
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
|
||||
" MOVS r1,#0 \n"
|
||||
" MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK
|
||||
#endif //--------- ARMv7-M or higher
|
||||
#else //--------- use PRIMASK
|
||||
" CPSIE i \n" // clear PRIMASK
|
||||
#endif //--------- use PRIMASK
|
||||
" BX lr \n"
|
||||
"QF_crit_exit_error: \n"
|
||||
" LDR r0,=QF_port_module_ \n"
|
||||
@ -210,7 +200,7 @@ __asm volatile (
|
||||
// BASEPRI register. However, this method cannot disable interrupt
|
||||
// priority zero, which is the default for all interrupts out of reset.
|
||||
// The following code changes the SysTick priority and all IRQ priorities
|
||||
// to the safe value QF_BASEPRI, which the QF critical section can disable.
|
||||
// to the safe value QF_USE_BASEPRI, which the QF critical section can disable.
|
||||
// This avoids breaching of the QF critical sections in case the
|
||||
// application programmer forgets to explicitly set priorities of all
|
||||
// "kernel aware" interrupts.
|
||||
@ -219,18 +209,18 @@ __asm volatile (
|
||||
// by the application-level code.
|
||||
void QV_init(void) {
|
||||
|
||||
#if (__ARM_ARCH != 6) //--------- if ARMv7-M and higher...
|
||||
#ifdef QF_USE_BASEPRI //--------- use BASEPRI for critical section?
|
||||
|
||||
// SCB_SYSPRI[2]: SysTick
|
||||
SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_BASEPRI << 24U));
|
||||
SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_USE_BASEPRI << 24U));
|
||||
|
||||
// set all 240 possible IRQ priories to QF_BASEPRI...
|
||||
// set all 240 possible IRQ priories to QF_USE_BASEPRI...
|
||||
for (uint_fast8_t n = 0U; n < (240U/sizeof(uint32_t)); ++n) {
|
||||
NVIC_IP[n] = (QF_BASEPRI << 24U) | (QF_BASEPRI << 16U)
|
||||
| (QF_BASEPRI << 8U) | QF_BASEPRI;
|
||||
NVIC_IP[n] = (QF_USE_BASEPRI << 24U) | (QF_USE_BASEPRI << 16U)
|
||||
| (QF_USE_BASEPRI << 8U) | QF_USE_BASEPRI;
|
||||
}
|
||||
|
||||
#endif //--------- ARMv7-M or higher
|
||||
#endif //--------- use BASEPRI for critical section
|
||||
|
||||
#ifdef __ARM_FP //--------- if VFP available...
|
||||
// make sure that the FPU is enabled by setting CP10 & CP11 Full Access
|
||||
|
@ -1,5 +1,5 @@
|
||||
//============================================================================
|
||||
// QP configuration file (QK on ARM Cortex-R)
|
||||
// QP configuration file (QV/QK/QXK on ARM Cortex-R)
|
||||
//
|
||||
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
|
||||
//
|
||||
@ -59,19 +59,19 @@
|
||||
// <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,16 +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>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)
|
||||
@ -169,15 +159,44 @@
|
||||
// <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>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.
|
||||
|
||||
@ -199,31 +218,6 @@
|
||||
|
||||
// </h>
|
||||
|
||||
//..........................................................................
|
||||
// <h>QK Preemptive 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>
|
||||
|
||||
|
||||
//------------- <<< end of configuration section >>> -----------------------
|
||||
|
||||
#endif // QP_CONFIG_H_
|
@ -27,7 +27,7 @@
|
||||
// <www.state-machine.com/licensing>
|
||||
// <info@state-machine.com>
|
||||
//============================================================================
|
||||
//! @date Last updated on: 2023-09-30
|
||||
//! @date Last updated on: 2024-11-22
|
||||
//! @version Last updated for: @ref qpc_8_0_0
|
||||
//!
|
||||
//! @file
|
||||
@ -62,7 +62,7 @@
|
||||
#define QF_INT_ENABLE() \
|
||||
__asm volatile ("MSR cpsr_c,#(0x1F)" ::: "cc")
|
||||
#define QF_INT_ENABLE_ALL() \
|
||||
__asm volatile ("MSR cpsr_c,#(0x1F | 0x80 | 0x40)" ::: "cc")
|
||||
__asm volatile ("MSR cpsr_c,#(0x1F)" ::: "cc")
|
||||
#else
|
||||
#error Incorrect CPU mode. Must be either __arm__ or __thumb__.
|
||||
#endif
|
||||
|
@ -1,229 +0,0 @@
|
||||
//============================================================================
|
||||
// QP configuration file (QV on ARM Cortex-R)
|
||||
//
|
||||
// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
|
||||
//
|
||||
// Q u a n t u m L e a P s
|
||||
// ------------------------
|
||||
// Modern Embedded Software
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
|
||||
//
|
||||
// The QP/C software is dual-licensed under the terms of the open-source GNU
|
||||
// General Public License (GPL) or under the terms of one of the closed-
|
||||
// source Quantum Leaps commercial licenses.
|
||||
//
|
||||
// Redistributions in source code must retain this top-level comment block.
|
||||
// Plagiarizing this software to sidestep the license obligations is illegal.
|
||||
//
|
||||
// NOTE:
|
||||
// The GPL (see <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_H_
|
||||
#define QP_CONFIG_H_
|
||||
|
||||
//-------- <<< 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>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>
|
||||
|
||||
|
||||
//------------- <<< end of configuration section >>> -----------------------
|
||||
|
||||
#endif // QP_CONFIG_H_
|
@ -27,7 +27,7 @@
|
||||
// <www.state-machine.com/licensing>
|
||||
// <info@state-machine.com>
|
||||
//============================================================================
|
||||
//! @date Last updated on: 2023-09-30
|
||||
//! @date Last updated on: 2024-11-22
|
||||
//! @version Last updated for: @ref qpc_8_0_0
|
||||
//!
|
||||
//! @file
|
||||
@ -62,7 +62,7 @@
|
||||
#define QF_INT_ENABLE() \
|
||||
__asm volatile ("MSR cpsr_c,#(0x1F)" ::: "cc")
|
||||
#define QF_INT_ENABLE_ALL() \
|
||||
__asm volatile ("MSR cpsr_c,#(0x1F | 0x80 | 0x40)" ::: "cc")
|
||||
__asm volatile ("MSR cpsr_c,#(0x1F)" ::: "cc")
|
||||
#else
|
||||
#error Incorrect CPU mode. Must be either __arm__ or __thumb__.
|
||||
#endif
|
||||
|
@ -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,16 +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>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)
|
||||
@ -169,15 +159,44 @@
|
||||
// <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>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.
|
||||
|
||||
|
@ -27,8 +27,8 @@
|
||||
// <www.state-machine.com/licensing>
|
||||
// <info@state-machine.com>
|
||||
//============================================================================
|
||||
//! @date Last updated on: 2023-09-30
|
||||
//! @version Last updated for: @ref qpc_8_0_0
|
||||
//! @date Last updated on: 2024-12-12
|
||||
//! @version Last updated for: @ref qpc_8_0_1
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QP/C port to to POSIX (multithreaded with P-threads)
|
||||
@ -38,6 +38,7 @@
|
||||
|
||||
#include <stdint.h> // Exact-width types. WG14/N843 C99 Standard
|
||||
#include <stdbool.h> // Boolean type. WG14/N843 C99 Standard
|
||||
#include <pthread.h> // POSIX-thread API
|
||||
#include "qp_config.h" // QP configuration from the application
|
||||
|
||||
// no-return function specifier (C11 Standard)
|
||||
|
28
qpc.qm
28
qpc.qm
@ -1677,10 +1677,8 @@ return r;</code>
|
||||
<parameter name="par_" type="void *"/>
|
||||
<!--${QEP-macros::QASM_INIT::qsId_}-->
|
||||
<parameter name="qsId_" type="uint8_t"/>
|
||||
<code>do { \
|
||||
Q_ASSERT(((QAsm *)(me_))->vptr); \
|
||||
(*((QAsm *)(me_))->vptr->init)((QAsm *)(me_), (par_), (qsId_)); \
|
||||
} while (false)</code>
|
||||
<code>\
|
||||
(*((QAsm *)(me_))->vptr->init)((QAsm *)(me_), (par_), (qsId_))</code>
|
||||
</operation>
|
||||
<!--${QEP-macros::QASM_INIT}-->
|
||||
<operation name="QASM_INIT?ndef Q_SPY" type="void" visibility="0x03" properties="0x00">
|
||||
@ -1690,10 +1688,8 @@ return r;</code>
|
||||
<parameter name="par_" type="void *"/>
|
||||
<!--${QEP-macros::QASM_INIT::dummy}-->
|
||||
<parameter name="dummy" type=""/>
|
||||
<code>do { \
|
||||
Q_ASSERT(((QAsm *)(me_))->vptr); \
|
||||
(*((QAsm *)(me_))->vptr->init)((QAsm *)(me_), (par_), 0); \
|
||||
} while (false)</code>
|
||||
<code>\
|
||||
(*((QAsm *)(me_))->vptr->init)((QAsm *)(me_), (par_), 0U)</code>
|
||||
</operation>
|
||||
<!--${QEP-macros::QASM_DISPATCH}-->
|
||||
<operation name="QASM_DISPATCH?def Q_SPY" type="void" visibility="0x03" properties="0x00">
|
||||
@ -3654,12 +3650,12 @@ QF_CRIT_EXIT();</code>
|
||||
//! @static @public @memberof QTimeEvt</documentation>
|
||||
<!--${QF::QTimeEvt::noActive::tickRate}-->
|
||||
<parameter name="tickRate" type="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 < QF_MAX_TICK_RATE);
|
||||
QF_CRIT_EXIT();
|
||||
|
||||
bool inactive;
|
||||
|
||||
QF_MEM_SYS();
|
||||
if (QTimeEvt_timeEvtHead_[tickRate].next != (QTimeEvt *)0) {
|
||||
inactive = false;
|
||||
}
|
||||
@ -3669,6 +3665,8 @@ else if ((QTimeEvt_timeEvtHead_[tickRate].act != (void *)0)) {
|
||||
else {
|
||||
inactive = true;
|
||||
}
|
||||
QF_MEM_APP();
|
||||
|
||||
return inactive;</code>
|
||||
</operation>
|
||||
</class>
|
||||
@ -6172,9 +6170,9 @@ $declare1 ${QP-FuSa}
|
||||
#define QP_H_
|
||||
|
||||
//============================================================================
|
||||
#define QP_VERSION_STR "8.0.0"
|
||||
#define QP_VERSION 800U
|
||||
#define QP_RELEASE 0x7055936FU
|
||||
#define QP_VERSION_STR "8.0.1"
|
||||
#define QP_VERSION 801U
|
||||
#define QP_RELEASE 0x703931CEU
|
||||
|
||||
//============================================================================
|
||||
//! @cond INTERNAL
|
||||
@ -6527,7 +6525,6 @@ static inline void QF_psInit(
|
||||
<file name="qep_hsm.c">
|
||||
<text>#define QP_IMPL // this is QP implementation
|
||||
#include "qp_port.h" // QP port
|
||||
#include "qp_pkg.h" // QP package-scope interface
|
||||
#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
|
||||
#ifdef Q_SPY // QS software tracing enabled?
|
||||
#include "qs_port.h" // QS port
|
||||
@ -6585,7 +6582,6 @@ $define ${QEP::QHsm}</text>
|
||||
<file name="qep_msm.c">
|
||||
<text>#define QP_IMPL // this is QP implementation
|
||||
#include "qp_port.h" // QP port
|
||||
#include "qp_pkg.h" // QP package-scope interface
|
||||
#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
|
||||
#ifdef Q_SPY // QS software tracing enabled?
|
||||
#include "qs_port.h" // QS port
|
||||
|
@ -1,18 +1,21 @@
|
||||
7177cfc37bca450ea06ffc6afe31a61c0008304f *qpc.qm
|
||||
e0aae515ebf157d8993bb03747fdc86cd87604f3 *qpc.qm
|
||||
e3c60b712a27e8f8c11e38711e785ffc4006cda5 *include/qequeue.h
|
||||
a0d30600da64ec7aaadc6b9bd268c217930c3e60 *include/qk.h
|
||||
84c8c1036c38f0f1646cc60e4813a7c8fb89f2d2 *include/qmpool.h
|
||||
080b5860668af8dc54cd429268c24f5629fbe074 *include/qp.h
|
||||
7ecec322b0b31b4175596df3a7968424b21f983e *include/qp.h
|
||||
7a909dd01c0aa3fd7d74b4a4c88b930eeb0b815e *include/qp_pkg.h
|
||||
0a3323af546e1b2320e6745e8e0effa837abdc53 *include/qpc.h
|
||||
6796ebe4b41225fa374d751704e7edd2f95e0484 *include/qs.h
|
||||
5a0c927370d332fc170e84650d980173da2102ae *include/qs_dummy.h
|
||||
d57d1974f64db7e3bf8a9f4468ee84a42ccd4952 *include/qs_pkg.h
|
||||
7458d62031562c2517577b258d47249b7b900dd7 *include/qsafe.h
|
||||
2e0a56edcf460fcd82f6d7277e5fc0876325efeb *include/qstamp.h
|
||||
d0199c9094039e672d85e9198ccff0d4ed9128cc *include/qv.h
|
||||
fdfc7f528989ff3934af977ef9a1ee9fc30cd889 *include/qxk.h
|
||||
5886c3a0831996cfbf7141255efb4e9f5b4d8254 *include/README.md
|
||||
7f54a0933a9dc2fcaca475919fa0067667ed99ed *src/qf/CMakeLists.txt
|
||||
d6aa00cb34e553e951df726fc5db39a6d16bc891 *src/qf/qep_hsm.c
|
||||
67d6f8351a0e9a1df311be681083c73ecf63ea61 *src/qf/qep_msm.c
|
||||
6ff32793932a96e1240b2c9dbbc9516faf206fa6 *src/qf/qep_hsm.c
|
||||
e5d93d4867336209c0d8e74cc4a9add1190b821a *src/qf/qep_msm.c
|
||||
733bc8bf8e08014c20d8354efb98729857edb4cd *src/qf/qf_act.c
|
||||
90e27f32bc8862946bfe4c6c376bf03327de25f7 *src/qf/qf_actq.c
|
||||
8b58d43c5b8fe3b1b846392d1f7d99d5720428d9 *src/qf/qf_defer.c
|
||||
@ -22,41 +25,58 @@ d263e3b91f9e5c61d6a458b5c6023ac68eb07a13 *src/qf/qf_mem.c
|
||||
2ed707166ca625a684c93147aec772dd568e5d9f *src/qf/qf_qact.c
|
||||
e6e7dd46ed4ab7fb3ecd781ca29ea141d13f49d9 *src/qf/qf_qeq.c
|
||||
f975ffcfadfed6856a41587b8275e0ea3bbe63a3 *src/qf/qf_qmact.c
|
||||
b888e05e67e1259ee96d29b244aa8a2a68d0f904 *src/qf/qf_time.c
|
||||
e43dbda05f6fd6cbb8673d8ae5d1f8b183570f29 *src/qf/qf_time.c
|
||||
878a737efe234f40dc8c9374acc351e510b4da1e *src/qk/CMakeLists.txt
|
||||
5f092f2dc82962633e8ff32f736baaf04ef4c5da *src/qk/qk.c
|
||||
68c99a2991d25df7486e57edadaa955b2bda396d *src/qs/CMakeLists.txt
|
||||
8cb434d345ef98a0915eadd97f7959987d66ff89 *src/qs/qs.c
|
||||
e8ee51e5776c38f9dfdc06f87ab2b1f00bb45fd4 *src/qs/qs_64bit.c
|
||||
14e1f08b94f65cc1d043051f829280e7f3ae057a *src/qs/qs_fp.c
|
||||
4e3d64f109f5f8de67799a190f505d1fa29d622a *src/qs/qs_rx.c
|
||||
f055d938dd53c9baf7f5e04ad1bc4f4ec40044e9 *src/qs/qstamp.c
|
||||
afe015fd804a563aedd4080d389ef143a1a9ce40 *src/qs/qutest.c
|
||||
b1d2def9b8f6cde464170af7682ab0f01f4f40f6 *src/qv/CMakeLists.txt
|
||||
f77a3c93938c5ff9a37214bdfe1c7c255f9eed6e *src/qv/qv.c
|
||||
5a77be9e96ab536754188a32a6b6f99b8db9f2ff *ports/arm-cm/qk/armclang/qk_port.c
|
||||
dc00b85b62f9d3dce9c4f0073b9e0c1b0d96d652 *ports/arm-cm/qk/armclang/qp_port.h
|
||||
de32deac900990db561238c22e6961e2c3ca4eac *src/qxk/qxk.c
|
||||
fff73b289cb59e10ae491907e4bb48bbffb90946 *src/qxk/qxk_mutex.c
|
||||
822dafde2328e17531a8c4df752e8e0b29a6f2c8 *src/qxk/qxk_sema.c
|
||||
49b36eef14ecffad5583efb1c7b2208cc0fc055d *src/qxk/qxk_xthr.c
|
||||
09c4447840e6b67c4f6adef68e13013abb87a69e *ports/arm-cm/qk/armclang/qk_port.c
|
||||
4e8a047094569163fc6826ee33435476b55b8b06 *ports/arm-cm/qk/armclang/qp_port.h
|
||||
e48b7af7dff7cfe6742abbb4adb0d1b01b2020cb *ports/arm-cm/qk/armclang/qs_port.h
|
||||
e27abe98e61b175634d3ef10f0b137a2c183b235 *ports/arm-cm/qk/config/qp_config.h
|
||||
404046a50f5c970986b23f9ded48b3aed37738e5 *ports/arm-cm/qk/gnu/qk_port.c
|
||||
1a1c683b243e48651427751f54752ce6f6ee60b0 *ports/arm-cm/qk/gnu/qp_port.h
|
||||
061bb4b5f82fcee28c34441ed22287bcf7b294ab *ports/arm-cm/qk/gnu/qk_port.c
|
||||
df8f0dfeb5b459c0a0da34584ac6f67c3ddcee99 *ports/arm-cm/qk/gnu/qp_port.h
|
||||
e48b7af7dff7cfe6742abbb4adb0d1b01b2020cb *ports/arm-cm/qk/gnu/qs_port.h
|
||||
ba447b9e250b96a4cc5caf901a8643df40737966 *ports/arm-cm/qk/iar/qk_port.c
|
||||
2e4ad9ed30bdec6728a1e1b4cfe52ca96668fb70 *ports/arm-cm/qk/iar/qp_port.h
|
||||
b3bd86c8a739243aad85abb94e992ed83d3fe2cb *ports/arm-cm/qk/iar/qk_port.c
|
||||
9b0833336729666744ac35ca42b85d57756ba8fa *ports/arm-cm/qk/iar/qp_port.h
|
||||
e48b7af7dff7cfe6742abbb4adb0d1b01b2020cb *ports/arm-cm/qk/iar/qs_port.h
|
||||
06909bcb51e7c1dd28e666a12a885500db74c052 *ports/arm-cm/qv/armclang/qp_port.h
|
||||
0a1f794005df1b7c256f52781928f86cb5dd96f9 *ports/arm-cm/qv/armclang/qp_port.h
|
||||
e48b7af7dff7cfe6742abbb4adb0d1b01b2020cb *ports/arm-cm/qv/armclang/qs_port.h
|
||||
1caea977419fbbf8eff95cb4a7a695b168b14bda *ports/arm-cm/qv/armclang/qv_port.c
|
||||
651dedf7266e0da44ce45ddd3cced3782eccda17 *ports/arm-cm/qv/config/qp_config.h
|
||||
0427fc5ce0d727350d39b1bc9dcb081172865be4 *ports/arm-cm/qv/gnu/qp_port.h
|
||||
050f16532d529cac3c20e990f1df40246b04c9ac *ports/arm-cm/qv/armclang/qv_port.c
|
||||
0a1f794005df1b7c256f52781928f86cb5dd96f9 *ports/arm-cm/qv/gnu/qp_port.h
|
||||
e48b7af7dff7cfe6742abbb4adb0d1b01b2020cb *ports/arm-cm/qv/gnu/qs_port.h
|
||||
6dad2e9e8a929e4477f6b071cc05d70638fbb356 *ports/arm-cm/qv/gnu/qv_port.c
|
||||
c63708c0d86bfefb58bf60917fd428dbf29a0a31 *ports/arm-cm/qv/iar/qp_port.h
|
||||
c8289ae7c23524d13f4680a839f9088aa9264200 *ports/arm-cm/qv/gnu/qv_port.c
|
||||
3448a1cff7b1f10239a80e3191953ac018416bfd *ports/arm-cm/qv/iar/qp_port.h
|
||||
e48b7af7dff7cfe6742abbb4adb0d1b01b2020cb *ports/arm-cm/qv/iar/qs_port.h
|
||||
9386d798e1989ff6789f54f5ae33741aad4b1b07 *ports/arm-cm/qv/iar/qv_port.c
|
||||
623d43a6e15634e9c61434625486cd24aaaa949b *ports/arm-cr/qk/config/qp_config.h
|
||||
38e441bb971501ba5118cbd5782b394eee80e660 *ports/arm-cr/qk/gnu/qp_port.h
|
||||
a5ffa52d6c2249bd4a3aaca9f8e4d55553aad374 *ports/arm-cm/qv/iar/qv_port.c
|
||||
030f0e57e8565902d9feaec653b28980dfbb25e2 *ports/arm-cm/qxk/armclang/qp_port.h
|
||||
e48b7af7dff7cfe6742abbb4adb0d1b01b2020cb *ports/arm-cm/qxk/armclang/qs_port.h
|
||||
0134e96053a73cf2deab3f8aee2a253464da473d *ports/arm-cm/qxk/armclang/qxk_port.c
|
||||
7f8806496c7aaa7ee212f00be7a80170d1cfe1c5 *ports/arm-cm/qxk/gnu/qp_port.h
|
||||
e48b7af7dff7cfe6742abbb4adb0d1b01b2020cb *ports/arm-cm/qxk/gnu/qs_port.h
|
||||
ddec778d8a73f663a5d959dec0afb2ced792e0ef *ports/arm-cm/qxk/gnu/qxk_port.c
|
||||
02eee6cc5894c554358c573d7d9e159bb3b3b3a2 *ports/arm-cm/qxk/iar/qp_port.h
|
||||
e48b7af7dff7cfe6742abbb4adb0d1b01b2020cb *ports/arm-cm/qxk/iar/qs_port.h
|
||||
624c3bb9e77359cc1fd8e78b6505bd1246a09f7a *ports/arm-cm/qxk/iar/qxk_port.c
|
||||
663b8e89a0ef61bbdd305984e14f971f889b3592 *ports/arm-cm/qutest/qp_port.h
|
||||
e48b7af7dff7cfe6742abbb4adb0d1b01b2020cb *ports/arm-cm/qutest/qs_port.h
|
||||
a53c0064a8650a9b7217259817a60cd67688606a *ports/arm-cr/qk/gnu/qp_port.h
|
||||
e48b7af7dff7cfe6742abbb4adb0d1b01b2020cb *ports/arm-cr/qk/gnu/qs_port.h
|
||||
88d3ed754f05c43609ecf52767c270fa438ecd03 *ports/arm-cr/qk/iar/qp_port.h
|
||||
e48b7af7dff7cfe6742abbb4adb0d1b01b2020cb *ports/arm-cr/qk/iar/qs_port.h
|
||||
e03d1c780c764e2a323b8423ae5045e226ee98c6 *ports/arm-cr/qk/ti/qp_port.h
|
||||
e48b7af7dff7cfe6742abbb4adb0d1b01b2020cb *ports/arm-cr/qk/ti/qs_port.h
|
||||
84b6adb5703d24e41f5c19982fe797b9a79b38a8 *ports/arm-cr/qv/gnu/qp_port.h
|
||||
a5c1f6cbb41d1884a6bfdaf4ccc1c7facb79c8eb *ports/arm-cr/qv/gnu/qp_port.h
|
||||
e48b7af7dff7cfe6742abbb4adb0d1b01b2020cb *ports/arm-cr/qv/gnu/qs_port.h
|
||||
da079ffa59b518ead25ed8aed82adc1535fc0280 *ports/arm-cr/qv/iar/qp_port.h
|
||||
e48b7af7dff7cfe6742abbb4adb0d1b01b2020cb *ports/arm-cr/qv/iar/qs_port.h
|
||||
@ -68,7 +88,7 @@ a99dfb36c107e6c1b2fcc345792130bbc1ebcc4f *ports/msp430/qk/qs_port.h
|
||||
a99dfb36c107e6c1b2fcc345792130bbc1ebcc4f *ports/msp430/qv/qs_port.h
|
||||
1459908255dbdd581cd38bd5ea33a121fce496b7 *ports/msp430/qutest/qp_port.h
|
||||
a99dfb36c107e6c1b2fcc345792130bbc1ebcc4f *ports/msp430/qutest/qs_port.h
|
||||
77bb26f94e1e9ce0ba617f5a6cc2b921c4b283c7 *ports/config/qp_config.h
|
||||
ecc7c04f015684c71bbaca3e351b8f7cbcdcc550 *ports/config/qp_config.h
|
||||
2ee7f5594f6121705bbc57145175b5c5867e0070 *ports/embos/CMakeLists.txt
|
||||
7cfd0e233fc7ee4c73cccaa58f769f3643325785 *ports/embos/qf_port.c
|
||||
a378ac45d230fc61b4462b3cc17a05d018271ea7 *ports/embos/qp_port.h
|
||||
@ -91,7 +111,7 @@ cdb7c42a17fb3c5f282a55e08f99678e1cd56c0e *ports/qep-only/qp_port.h
|
||||
5189dfad3fea0ccb2218958dd3657f4403674b5e *ports/qep-only/safe_std.h
|
||||
5d7914dfaf44a9c2552afdd5d8de4cfc3ebbc22a *ports/posix/CMakeLists.txt
|
||||
6b9d862537f4823ca83c81d2e8892da9711a69cd *ports/posix/qf_port.c
|
||||
c99d7d3ca180a3f7903fe6948d5cffaf7e8f1996 *ports/posix/qp_port.h
|
||||
78563f44b3d4b7835a75ef9dd3eea00e38f61946 *ports/posix/qp_port.h
|
||||
51d89a3fa8c7a6c5858f6354ea8cc350e42a9d30 *ports/posix/qs_port.c
|
||||
d05889780d358bb1fe02ffad1a9414332f5eb300 *ports/posix/qs_port.h
|
||||
6e33b2e5092d117f58c47b632c59420f382ac39f *ports/posix/README.md
|
||||
@ -103,6 +123,11 @@ b73738f7297d6c023012d98c59c901a1e8951f02 *ports/posix-qv/qp_port.h
|
||||
d05889780d358bb1fe02ffad1a9414332f5eb300 *ports/posix-qv/qs_port.h
|
||||
ab829eb3deed2bc84b3581610f1664777afd3841 *ports/posix-qv/README.md
|
||||
5189dfad3fea0ccb2218958dd3657f4403674b5e *ports/posix-qv/safe_std.h
|
||||
1ecb2095e8de486c8111a420b5511a4ea0cb097c *ports/posix-qutest/CMakeLists.txt
|
||||
d55172d4bb6959349285a06ca6485f1f1a1b756e *ports/posix-qutest/qp_port.h
|
||||
d05889780d358bb1fe02ffad1a9414332f5eb300 *ports/posix-qutest/qs_port.h
|
||||
243941959b1dbf5dfbbe57941104ae202eec57fc *ports/posix-qutest/qutest_port.c
|
||||
5189dfad3fea0ccb2218958dd3657f4403674b5e *ports/posix-qutest/safe_std.h
|
||||
cfea17ea9ab718e9e4f506e90c4b2fc8c1fea858 *ports/win32/CMakeLists.txt
|
||||
a99784fa31b0466af740186bbe96f8d78fc7c17a *ports/win32/qf_port.c
|
||||
d0b7e944e6df828e040ec146f639e42be2c354d5 *ports/win32/qp_port.h
|
||||
@ -121,6 +146,11 @@ b1a67eb489d35d71cf6fb40fc8f087906839f1a7 *ports/win32-qv/qs_port.h
|
||||
be15234e51b8fe3c295ff644e84fbc1cfca89257 *ports/win32-qv/qwin_gui.h
|
||||
b57cec85e2fe5c261270f68acc3ae440802a62bd *ports/win32-qv/README.md
|
||||
5189dfad3fea0ccb2218958dd3657f4403674b5e *ports/win32-qv/safe_std.h
|
||||
a04f13d2d9f24ef71d95f997d87f8a3ba9862e45 *ports/win32-qutest/CMakeLists.txt
|
||||
50be2b5d49345d908290a4660b1bbc5eaeb6b4d6 *ports/win32-qutest/qp_port.h
|
||||
b1a67eb489d35d71cf6fb40fc8f087906839f1a7 *ports/win32-qutest/qs_port.h
|
||||
1d850be2190dd03f528405266ba85f81e9ecff53 *ports/win32-qutest/qutest_port.c
|
||||
5189dfad3fea0ccb2218958dd3657f4403674b5e *ports/win32-qutest/safe_std.h
|
||||
848a30efa3274ff30fb72059f926fe7963ab2321 *zephyr/CMakeLists.txt
|
||||
10764710e545dd4d2ce0ddf032711df7f9191937 *zephyr/Kconfig
|
||||
2eb2a922e18b4760a68151ebee1b6282d20b4692 *zephyr/module.yml
|
12
qpc_sha1.bat
12
qpc_sha1.bat
@ -1,18 +1,20 @@
|
||||
@setlocal
|
||||
|
||||
set VERSION=8.0.1
|
||||
|
||||
:: usage
|
||||
@echo Usage: qpc_sha1 [gen]
|
||||
@echo examples:
|
||||
@echo qpc_sha1 : check the sha1 sums in the file qpcp.sha1
|
||||
@echo qpc_sha1 gen : generate the sha1 file qpc.sha1
|
||||
@echo qpc_sha1 : check the sha1 sums in the file qpc_%VERSION%.sha1
|
||||
@echo qpc_sha1 gen : generate the sha1 file qpc_%VERSION%.sha1
|
||||
@echo.
|
||||
|
||||
@if NOT "%1"=="gen" (
|
||||
sha1sum --check --warn qpc.sha1
|
||||
sha1sum --check --warn qpc_%VERSION%.sha1
|
||||
goto end
|
||||
)
|
||||
|
||||
@echo generating qpc.sha1...
|
||||
@echo generating qpc_%VERSION%.sha1...
|
||||
@sha1sum qpc.qm ^
|
||||
include/* ^
|
||||
src/qf/* src/qk/* src/qs/* src/qv/* src/qxk/* ^
|
||||
@ -33,7 +35,7 @@ goto end
|
||||
ports/posix/* ports/posix-qv/* ports/posix-qutest/* ^
|
||||
ports/win32/* ports/win32-qv/* ports/win32-qutest/* ^
|
||||
zephyr/* ^
|
||||
> qpc.sha1
|
||||
> qpc_%VERSION%.sha1
|
||||
@echo done
|
||||
|
||||
:end
|
||||
|
@ -34,7 +34,6 @@
|
||||
//$endhead${src::qf::qep_hsm.c} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
#define QP_IMPL // this is QP implementation
|
||||
#include "qp_port.h" // QP port
|
||||
#include "qp_pkg.h" // QP package-scope interface
|
||||
#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
|
||||
#ifdef Q_SPY // QS software tracing enabled?
|
||||
#include "qs_port.h" // QS port
|
||||
|
@ -34,7 +34,6 @@
|
||||
//$endhead${src::qf::qep_msm.c} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
#define QP_IMPL // this is QP implementation
|
||||
#include "qp_port.h" // QP port
|
||||
#include "qp_pkg.h" // QP package-scope interface
|
||||
#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
|
||||
#ifdef Q_SPY // QS software tracing enabled?
|
||||
#include "qs_port.h" // QS port
|
||||
|
@ -546,12 +546,12 @@ void QTimeEvt_tick_(
|
||||
//${QF::QTimeEvt::noActive} ..................................................
|
||||
//! @static @public @memberof QTimeEvt
|
||||
bool QTimeEvt_noActive(uint_fast8_t const tickRate) {
|
||||
QF_CRIT_STAT
|
||||
QF_CRIT_ENTRY();
|
||||
// NOTE: this function must be called *inside* critical section
|
||||
Q_REQUIRE_INCRIT(900, tickRate < QF_MAX_TICK_RATE);
|
||||
QF_CRIT_EXIT();
|
||||
|
||||
bool inactive;
|
||||
|
||||
QF_MEM_SYS();
|
||||
if (QTimeEvt_timeEvtHead_[tickRate].next != (QTimeEvt *)0) {
|
||||
inactive = false;
|
||||
}
|
||||
@ -561,6 +561,8 @@ bool QTimeEvt_noActive(uint_fast8_t const tickRate) {
|
||||
else {
|
||||
inactive = true;
|
||||
}
|
||||
QF_MEM_APP();
|
||||
|
||||
return inactive;
|
||||
}
|
||||
//$enddef${QF::QTimeEvt} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
Loading…
x
Reference in New Issue
Block a user