From 340b6bbd9217b5a081795fc98c6c83a7394218d9 Mon Sep 17 00:00:00 2001 From: MMS Date: Tue, 27 Feb 2024 17:43:27 -0500 Subject: [PATCH] 7.3.4 updated QV, QK for MSP430 removed the unsupported esp-idf port Cmake support --- 3rd_party | 2 +- CMakeLists.txt | 33 +- examples | 2 +- ports/CMakeLists.txt | 1 - ports/arm-cm/CMakeLists.txt | 3 - ports/arm-cr/CMakeLists.txt | 3 +- ports/esp-idf/CMakeLists.txt | 3 - ports/esp-idf/README.md | 29 -- ports/esp-idf/qf_port.c | 805 ------------------------------ ports/esp-idf/qp_port.h | 269 ---------- ports/esp-idf/qs_port.h | 56 --- ports/msp430/CMakeLists.txt | 10 +- ports/pic32/CMakeLists.txt | 20 +- ports/posix-qutest/CMakeLists.txt | 6 +- ports/posix-qv/CMakeLists.txt | 8 +- ports/posix/CMakeLists.txt | 8 +- ports/win32-qutest/CMakeLists.txt | 6 +- ports/win32-qv/CMakeLists.txt | 10 +- ports/win32/CMakeLists.txt | 10 +- qpc.md5 | 26 +- qpc.qm | 54 +- qpc_sdk_init.cmake | 2 +- src/CMakeLists.txt | 2 +- src/qk/CMakeLists.txt | 6 +- src/qk/qk.c | 48 +- src/qs/CMakeLists.txt | 16 +- src/qv/CMakeLists.txt | 6 +- src/qv/qv.c | 6 +- src/qxk/CMakeLists.txt | 12 +- 29 files changed, 137 insertions(+), 1325 deletions(-) delete mode 100644 ports/esp-idf/CMakeLists.txt delete mode 100644 ports/esp-idf/README.md delete mode 100644 ports/esp-idf/qf_port.c delete mode 100644 ports/esp-idf/qp_port.h delete mode 100644 ports/esp-idf/qs_port.h diff --git a/3rd_party b/3rd_party index ebe4896f..db8b6155 160000 --- a/3rd_party +++ b/3rd_party @@ -1 +1 @@ -Subproject commit ebe4896f82bdb7b883f42f930307d243a4cd43d6 +Subproject commit db8b6155e6931d2c55315dfd55b0e1fac0f96e33 diff --git a/CMakeLists.txt b/CMakeLists.txt index b50cbd0e..09d0f1a4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -132,36 +132,25 @@ add_subdirectory(src) add_subdirectory(ports) # set general defines -target_compile_definitions(qpc - PRIVATE - $<$:${ADD_DEBUG_CODE}> - $<$:QWIN_GUI> - $<$:Q_SPY> - $<$,$>:Q_UTEST> +target_compile_definitions(qpc PRIVATE + $<$:${ADD_DEBUG_CODE}> + $<$:QWIN_GUI> + # $<$:Q_SPY> # set via toolchain file + $<$,$>:Q_UTEST> ) -target_compile_options(qpc - PRIVATE - $<$:-v> +target_compile_options(qpc PRIVATE + $<$:-v> ) -target_link_options(qpc - PRIVATE - $<$:-v> +target_link_options(qpc PRIVATE + $<$:-v> ) -target_link_libraries(qpc - PUBLIC - $<$,$>:ws2_32> +target_link_libraries(qpc PUBLIC + $<$,$>:ws2_32> ) -# set position independent code compile/link parameters -if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.14") - include(CheckPIESupported) - check_pie_supported() -endif() -set_property(TARGET qpc PROPERTY POSITION_INDEPENDENT_CODE FALSE) - # print configuration message(STATUS "======================================================== diff --git a/examples b/examples index 9c903f81..5b4edf6f 160000 --- a/examples +++ b/examples @@ -1 +1 @@ -Subproject commit 9c903f815f7690385c69e326fd8c1cc1f100ce4a +Subproject commit 5b4edf6f7a1514169427fa42522d823fb31ee37c diff --git a/ports/CMakeLists.txt b/ports/CMakeLists.txt index 992ae9c3..2c33dc6b 100644 --- a/ports/CMakeLists.txt +++ b/ports/CMakeLists.txt @@ -1,5 +1,4 @@ # CMake the qpc libraries for different targets -# target may be "Windows", "Posix", "TLE984x" set(PORT_DIR ${PORT}) if((PORT STREQUAL win32) OR (PORT STREQUAL posix)) if(QPC_CFG_UNIT_TEST) diff --git a/ports/arm-cm/CMakeLists.txt b/ports/arm-cm/CMakeLists.txt index 38ce7ac0..f5512e95 100644 --- a/ports/arm-cm/CMakeLists.txt +++ b/ports/arm-cm/CMakeLists.txt @@ -15,8 +15,5 @@ else() target_include_directories(qpc PUBLIC ${KERNEL}/${_compiler_}) endif() -if(EXISTS ${KERNEL}/config) - target_include_directories(qpc PRIVATE ${KERNEL}/config) -endif() target_sources(qpc PRIVATE ${KERNEL}/${_compiler_}/${qx_port_c}) diff --git a/ports/arm-cr/CMakeLists.txt b/ports/arm-cr/CMakeLists.txt index 0bd7e638..01b125a1 100644 --- a/ports/arm-cr/CMakeLists.txt +++ b/ports/arm-cr/CMakeLists.txt @@ -11,5 +11,4 @@ if(NOT KERNEL MATCHES "q[vk]") message(WARNING "Kernel ${KERNEL} is not supported! Falling back to QV kernel") set(KERNEL qv) endif() -target_include_directories(qpc PUBLIC ${KERNEL}/${_compiler_} ${KERNEL}/config) - +target_include_directories(qpc PUBLIC ${KERNEL}/${_compiler_}) diff --git a/ports/esp-idf/CMakeLists.txt b/ports/esp-idf/CMakeLists.txt deleted file mode 100644 index ba715b00..00000000 --- a/ports/esp-idf/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -# ports/esp-idf -target_include_directories(qpc PUBLIC .) -target_sources(qpc PRIVATE qf_port.c) diff --git a/ports/esp-idf/README.md b/ports/esp-idf/README.md deleted file mode 100644 index 38911ea1..00000000 --- a/ports/esp-idf/README.md +++ /dev/null @@ -1,29 +0,0 @@ -This directory contains the "experimental" port to the [Espressif ESP-IDF][1] -IoT Framework, which is loosely based on the [FreeRTOS kernel][2]. - - ---------------------------------------------------------------------------- -# About QP/C Port to ESP-IDF -"Experimental" means that the port has not been thoroughly tested at -Quantum Leaps and no working examples are provided. - - ---------------------------------------------------------------------------- -# About Espressif ESP-IDF - -The [Espressif ESP-IDF][1] is based on a -[significantly changed version of the FreeRTOS kernel][3] -developed by Espressif to support the ESP32 multi-core CPUs (see [ESP-IDF][1]). - -The Espressif version of FreeRTOS is __NOT__ compatible with the baseline [FreeRTOS][2] -and it needs to be treated as a separate RTOS kernel. According to the comments -in the Espressif source code, FreeRTOS-ESP-IDF is based on FreeRTOS V8.2.0, but -apparently FreeRTOS-ESP32 has been updated with the newer features introduced to -the original FreeRTOS in the later versions. For example, FreeRTOS-ESP-IDF supports -the "static allocation", first introduced in baseline FreeRTOS V9.x. This QP port -to FreeRTOS-ESP-IDF takes advantage of the "static allocation". - - -[1]: https://www.espressif.com/en/products/sdks/esp-idf -[2]: https://freertos.org -[3]: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/freertos.html diff --git a/ports/esp-idf/qf_port.c b/ports/esp-idf/qf_port.c deleted file mode 100644 index b38743bd..00000000 --- a/ports/esp-idf/qf_port.c +++ /dev/null @@ -1,805 +0,0 @@ -//============================================================================ -// QP/C Real-Time Embedded Framework (RTEF) -// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial -// -// This software is dual-licensed under the terms of the open source GNU -// General Public License version 3 (or any later version), or alternatively, -// under the terms of one of the closed source Quantum Leaps commercial -// licenses. -// -// The terms of the open source GNU General Public License version 3 -// can be found at: -// -// The terms of the closed source Quantum Leaps commercial licenses -// can be found at: -// -// Redistributions in source code must retain this top-level comment block. -// Plagiarizing this software to sidestep the license obligations is illegal. -// -// Contact information: -// -// -//============================================================================ -//! @date Last updated on: 2023-11-15 -//! @version Last updated for: @ref qpc_7_3_1 -//! -//! @file -//! @brief "Experimental" QF/C port to Espressif ESP-IDF (version 4.x) - -#define QP_IMPL // this is QP implementation -#include "qp_port.h" // QP port -#include "qp_pkg.h" // QP package-level interface -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // QS software tracing enabled? - #include "qs_port.h" // QS port - #include "qs_pkg.h" // QS package-scope internal interface -#else - #include "qs_dummy.h" // disable the QS software tracing -#endif // Q_SPY - -Q_DEFINE_THIS_MODULE("qf_port") - -#if ( configSUPPORT_STATIC_ALLOCATION == 0 ) -#error "This QP/C port to FreeRTOS requires configSUPPORT_STATIC_ALLOCATION " -#endif - -#if ( configMAX_PRIORITIES < QF_MAX_ACTIVE ) -#error "FreeRTOS configMAX_PRIORITIES must not be less than QF_MAX_ACTIVE" -#endif - -// Global objects ---------------------------------------------------------- -PRIVILEGED_DATA portMUX_TYPE QF_esp32mux = portMUX_INITIALIZER_UNLOCKED; - -// Local objects ----------------------------------------------------------- -static void task_function(void *pvParameters); // FreeRTOS task signature - -// The following macro provides the number of free slots in the FreeRTOS -// queue. -// -// NOTE1: -// The official FreeRTOS API uxQueueSpacesAvailable() is not used -// here, because that API uses task-level critical section internally. -// Instead, the free slots calculation happens here in already -// established critical section. Unfortunately, the bizarre "information -// obfuscating" policy of FreeRTOS (incorrectly called "information -// hiding") forces the use of the StaticQueue_t with "dummy" members. -// This could potentially break in the future releases of FreeRTOS. -// -// Currently, the correspondence between xQUEUE and StaticQueue_t -// is as follows (see queue.c and FreeRTOS.h, respectively): -// -// xQUEUE.uxMessagesWaiting == StaticQueue_t.uxDummy4[0]; -// xQUEUE.uxLength == StaticQueue_t.uxDummy4[1]; -// -#define FREERTOS_QUEUE_GET_FREE(me_) \ - ((me_)->osObject.uxDummy4[1] - (me_)->osObject.uxDummy4[0]) - -//============================================================================ -void QF_init(void) { - // empty for ESP-IDF -} -//............................................................................ -int_t QF_run(void) { - QF_onStartup(); // the startup callback (configure/enable interrupts) - - // produce the QS_QF_RUN trace record - QF_CRIT_STAT - QF_CRIT_ENTRY(); - QS_BEGIN_PRE_(QS_QF_RUN, 0U) - QS_END_PRE_() - QF_CRIT_EXIT(); - - return 0; // dummy return to make the compiler happy -} -//............................................................................ -void QF_stop(void) { - QF_onCleanup(); // cleanup callback -} - -//............................................................................ -static void task_function(void *pvParameters) { // FreeRTOS task signature - QActive *act = (QActive *)pvParameters; - -#ifdef QACTIVE_CAN_STOP - while (act->eQueue != (QueueHandle_t)0) -#else - for (;;) // for-ever -#endif - { - QEvt const *e = QActive_get_(act); // wait for event - QASM_DISPATCH(&act->super, e, act->prio); // dispatch to the SM - QF_gc(e); // check if the event is garbage, and collect it if so - } -#ifdef QACTIVE_CAN_STOP - QActive_unregister_(act); // remove this object from the framewrok - vTaskDelete((TaskHandle_t)0); // delete this FreeRTOS task -#endif -} - -//............................................................................ -void QActive_start_(QActive * const me, - QPrioSpec const prioSpec, - QEvt const * * const qSto, - uint_fast16_t const qLen, - void * const stkSto, - uint_fast16_t const stkSize, - void const * const par) -{ - QF_CRIT_STAT - QF_CRIT_ENTRY(); - // precondition: - // - queue storage must be provided - // - queue size must be provided - // - stack storage must be provided - // - stack size must be provided - Q_REQUIRE_INCRIT(200, - (qSto != (QEvt const **)0) && (qLen > 0U) - && (stkSto != (void *)0) && (stkSize > 0U)); - QF_CRIT_EXIT(); - - // create FreeRTOS message queue - me->eQueue = xQueueCreateStatic( - (UBaseType_t)qLen, // length of the queue - (UBaseType_t)sizeof(QEvt *), // element size - (uint8_t *)qSto, // storage buffer - &me->osObject); // static queue buffer - QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(210, me->eQueue != (QueueHandle_t)0); - QF_CRIT_EXIT(); - - me->prio = (uint8_t)(prioSpec & 0xFFU); // QF-priority of the AO - me->pthre = 0U; // preemption-threshold (not used for AO registration) - QActive_register_(me); // register this AO - - // top-most initial tran. (virtual call) - (*me->super.vptr->init)(&me->super, par, me->prio); - QS_FLUSH(); // flush the QS trace buffer to the host - - // task name provided by the user in QActive_setAttr() or default name - char const *taskName = (me->thread.pxDummy1 != (void *)0) - ? (char const *)me->thread.pxDummy1 - : (char const *)"AO"; - - // The FreeRTOS priority of the AO thread can be specified in two ways: - // - // 1. Implictily based on the AO's priority (by the formula specified - // in the macro FREERTOS_TASK_PRIO(), see qp_port.h). This option - // is chosen, when the higher-byte of the prioSpec parameter is set - // to zero. - // - // 2. Explicitly as the higher-byte of the prioSpec parameter. - // This option is chosen when the prioSpec parameter is not-zero. - // For example, Q_PRIO(10U, 5U) will explicitly specify AO priority - // as 10 and FreeRTOS priority as 5. - // - // NOTE: The explicit FreeRTOS priority is NOT sanity-checked, - // so it is the responsibility of the application to ensure that - // it is consistent with the AO's priority. An example of - // inconsistent setting would be assigning FreeRTOS priorities that - // would result in a different relative priritization of AO's threads - // than indicated by the AO priorities assigned. - // - UBaseType_t freertos_prio = (prioSpec >> 8U); - if (freertos_prio == 0U) { - freertos_prio = FREERTOS_TASK_PRIO(me->prio); - } - - // statically create the FreeRTOS task for the AO - TaskHandle_t task = xTaskCreateStaticPinnedToCore( - &task_function, // the task function - taskName , // the name of the task - stkSize/sizeof(portSTACK_TYPE), // stack length - (void *)me, // the 'pvParameters' parameter - freertos_prio, // FreeRTOS priority - (StackType_t *)stkSto, // stack storage - &me->thread, // task buffer - QPC_CPU_NUM); // CPU number - - QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(220, task != (TaskHandle_t)0); - QF_CRIT_EXIT(); -} -//............................................................................ -#ifdef QACTIVE_CAN_STOP -void QActive_stop(QActive * const me) { - QActive_unsubscribeAll(me); // unsubscribe from all events - me->eQueue = (QueueHandle_t)0; // stop the thread (see task_function()) -} -#endif -//............................................................................ -void QActive_setAttr(QActive *const me, uint32_t attr1, void const *attr2) { - QF_CRIT_STAT - QF_CRIT_ENTRY(); - // this function must be called before QACTIVE_START(), - // which implies that me->thread.pxDummy1 must not be used yet; - Q_REQUIRE_INCRIT(300, me->thread.pxDummy1 == (void *)0); - switch (attr1) { - case TASK_NAME_ATTR: - // temporarily store the name, cast 'const' away - me->thread.pxDummy1 = (void *)attr2; - break; - // ... - } - QF_CRIT_EXIT(); -} - -//============================================================================ -bool IRAM_ATTR QActive_post_(QActive * const me, QEvt const * const e, - uint_fast16_t const margin, void const * const sender) -{ -#ifndef Q_SPY - Q_UNUSED_PAR(sender); -#endif - - QF_CRIT_STAT - QF_CRIT_ENTRY(); - - // find the number of free slots available in the queue - uint_fast16_t const nFree = (uint_fast16_t)FREERTOS_QUEUE_GET_FREE(me); - - bool status; - if (margin == QF_NO_MARGIN) { - if (nFree > 0U) { - status = true; // can post - } - else { - status = false; // cannot post - Q_ERROR_INCRIT(510); // must be able to post the event - } - } - else if (nFree > margin) { - status = true; // can post - } - else { - status = false; // cannot post - } - - if (status) { // can post the event? - - QS_BEGIN_PRE_(QS_QF_ACTIVE_POST, me->prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(sender); // the sender object - QS_SIG_PRE_(e->sig); // the signal of the event - QS_OBJ_PRE_(me); // this active object (recipient) - QS_2U8_PRE_(QEvt_getPoolNum_(e), e->refCtr_); // poolNum & refCtr - QS_EQC_PRE_((QEQueueCtr)nFree); // # free entries - QS_EQC_PRE_(0U); // min # free entries (unknown) - QS_END_PRE_() - - if (QEvt_getPoolNum_(e) != 0U) { // is it a pool event? - QEvt_refCtr_inc_(e); // increment the reference counter - } - QF_CRIT_EXIT(); - - BaseType_t err = xQueueSendToBack( - me->eQueue, (void const *)&e, (TickType_t)0); - - // posting to the FreeRTOS message queue must succeed, see NOTE3 - QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(520, err == pdPASS); - } - else { - - QS_BEGIN_PRE_(QS_QF_ACTIVE_POST_ATTEMPT, me->prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(sender); // the sender object - QS_SIG_PRE_(e->sig); // the signal of the event - QS_OBJ_PRE_(me); // this active object (recipient) - QS_2U8_PRE_(QEvt_getPoolNum_(e), e->refCtr_); // poolNum & refCtr - QS_EQC_PRE_((QEQueueCtr)nFree); // # free entries - QS_EQC_PRE_(margin); // margin requested - QS_END_PRE_() - } - QF_CRIT_EXIT(); - - return status; -} -//............................................................................ -void IRAM_ATTR QActive_postLIFO_(QActive * const me, QEvt const * const e) { - QF_CRIT_STAT - QF_CRIT_ENTRY(); - - QS_BEGIN_PRE_(QS_QF_ACTIVE_POST_LIFO, me->prio) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of this event - QS_OBJ_PRE_(me); // this active object - QS_2U8_PRE_(QEvt_getPoolNum_(e), e->refCtr_); // poolNum & refCtr - QS_EQC_PRE_((QEQueueCtr)FREERTOS_QUEUE_GET_FREE(me)); // # free - QS_EQC_PRE_(0U); // min # free entries (unknown) - QS_END_PRE_() - - if (QEvt_getPoolNum_(e) != 0U) { // is it a pool event? - QEvt_refCtr_inc_(e); // increment the reference counter - } - QF_CRIT_EXIT(); - - BaseType_t err = xQueueSendToFront( - me->eQueue, (void const *)&e, (TickType_t)0); - - // LIFO posting to the FreeRTOS queue must succeed, see NOTE3 - QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(610, err == pdPASS); - QF_CRIT_EXIT(); -} -//............................................................................ -QEvt const *QActive_get_(QActive * const me) { - QEvt const *e; - xQueueReceive(me->eQueue, (void *)&e, portMAX_DELAY); - - QS_CRIT_STAT - QS_CRIT_ENTRY(); - QS_BEGIN_PRE_(QS_QF_ACTIVE_GET, me->prio) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of this event - QS_OBJ_PRE_(me); // this active object - QS_2U8_PRE_(QEvt_getPoolNum_(e), e->refCtr_); // poolNum & refCtr - QS_EQC_PRE_((QEQueueCtr)FREERTOS_QUEUE_GET_FREE(me)); // # free - QS_END_PRE_() - QS_CRIT_EXIT(); - - return e; -} - -//============================================================================ -// The "FromISR" QP APIs for the FreeRTOS port... -bool IRAM_ATTR QActive_postFromISR_(QActive * const me, QEvt const * const e, - uint_fast16_t const margin, - BaseType_t * const pxHigherPriorityTaskWoken, - void const * const sender) -{ - portENTER_CRITICAL_ISR(&QF_esp32mux); - - // find the number of free slots available in the queue - uint_fast16_t const nFree = (uint_fast16_t)FREERTOS_QUEUE_GET_FREE(me); - - bool status; - if (margin == QF_NO_MARGIN) { - if (nFree > 0U) { - status = true; // can post - } - else { - status = false; // cannot post - Q_ERROR_INCRIT(810); // must be able to post the event - } - } - else if (nFree > margin) { - status = true; // can post - } - else { - status = false; // cannot post - } - - if (status) { // can post the event? - - QS_BEGIN_PRE_(QS_QF_ACTIVE_POST, me->prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(sender); // the sender object - QS_SIG_PRE_(e->sig); // the signal of the event - QS_OBJ_PRE_(me); // this active object (recipient) - QS_2U8_PRE_(QEvt_getPoolNum_(e), e->refCtr_); // poolNum & refCtr - QS_EQC_PRE_(nFree); // # free entries available - QS_EQC_PRE_(0U); // min # free entries (unknown) - QS_END_PRE_() - - if (QEvt_getPoolNum_(e) != 0U) { // is it a pool event? - QEvt_refCtr_inc_(e); // increment the reference counter - } - portEXIT_CRITICAL_ISR(&QF_esp32mux); - - BaseType_t err = xQueueSendToBackFromISR(me->eQueue, - (void const *)&e, - pxHigherPriorityTaskWoken); - - // posting to the FreeRTOS message queue must succeed - portENTER_CRITICAL_ISR(&QF_esp32mux); - Q_ASSERT_INCRIT(820, err == pdPASS); - portEXIT_CRITICAL_ISR(&QF_esp32mux); - } - else { - - QS_BEGIN_PRE_(QS_QF_ACTIVE_POST_ATTEMPT, me->prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(sender); // the sender object - QS_SIG_PRE_(e->sig); // the signal of the event - QS_OBJ_PRE_(me); // this active object (recipient) - QS_2U8_PRE_(QEvt_getPoolNum_(e), e->refCtr_); // poolNum & refCtr - QS_EQC_PRE_(nFree); // # free entries available - QS_EQC_PRE_(margin); // margin requested - QS_END_PRE_() - portEXIT_CRITICAL_ISR(&QF_esp32mux); - - QF_gcFromISR(e); // recycle the event to avoid a leak - } - - return status; -} -//............................................................................ -void IRAM_ATTR QActive_publishFromISR_(QEvt const * const e, - BaseType_t * const pxHigherPriorityTaskWoken, - void const * const sender) -{ - QSignal const sig = e->sig; - - portENTER_CRITICAL_ISR(&QF_esp32mux); - - //! @pre the published signal must be within the configured range - Q_REQUIRE_INCRIT(500, sig < (QSignal)QActive_maxPubSignal_); - Q_REQUIRE_INCRIT(502, - QPSet_verify_(&QActive_subscrList_[sig].set, - &QActive_subscrList_[sig].set_dis)); - - QS_BEGIN_PRE_(QS_QF_PUBLISH, 0U) - QS_TIME_PRE_(); // the timestamp - QS_OBJ_PRE_(sender); // the sender object - QS_SIG_PRE_(sig); // the signal of the event - QS_2U8_PRE_(QEvt_getPoolNum_(e), e->refCtr_);// pool-Id & ref-Count - QS_END_PRE_() - - // is it a dynamic event? - if (QEvt_getPoolNum_(e) != 0U) { - // NOTE: The reference counter of a dynamic event is incremented to - // prevent premature recycling of the event while the multicasting - // is still in progress. At the end of the function, the garbage - // collector step (QF_gcFromISR()) decrements the reference counter - // and recycles the event if the counter drops to zero. This covers - // the case when the event was published without any subscribers. - QEvt_refCtr_inc_(e); - } - - // make a local, modifiable copy of the subscriber list - QPSet subscrSet = QActive_subscrList_[sig].set; - portEXIT_CRITICAL_ISR(&QF_esp32mux); - - if (QPSet_notEmpty(&subscrSet)) { // any subscribers? - // the highest-prio subscriber - uint_fast8_t p = QPSet_findMax(&subscrSet); - - // no need to lock the scheduler in the ISR context - do { // loop over all subscribers - // the prio of the AO must be registered with the framework - portENTER_CRITICAL_ISR(&QF_esp32mux); - Q_ASSERT_INCRIT(510, QActive_registry_[p] != (QActive *)0); - portEXIT_CRITICAL_ISR(&QF_esp32mux); - - // QACTIVE_POST_FROM_ISR() asserts if the queue overflows - QACTIVE_POST_FROM_ISR(QActive_registry_[p], e, - pxHigherPriorityTaskWoken, sender); - - QPSet_remove(&subscrSet, p); // remove the handled subscriber - if (QPSet_notEmpty(&subscrSet)) { // still more subscribers? - p = QPSet_findMax(&subscrSet); // the highest-prio subscriber - } - else { - p = 0U; // no more subscribers - } - } while (p != 0U); - // no need to unlock the scheduler in the ISR context - } - - // The following garbage collection step decrements the reference counter - // and recycles the event if the counter drops to zero. This covers both - // cases when the event was published with or without any subscribers. - QF_gcFromISR(e); -} -//............................................................................ -void IRAM_ATTR QTimeEvt_tickFromISR_(uint_fast8_t const tickRate, - BaseType_t * const pxHigherPriorityTaskWoken, - void const * const sender) -{ - portENTER_CRITICAL_ISR(&QF_esp32mux); - - QTimeEvt *prev = &QTimeEvt_timeEvtHead_[tickRate]; - - QS_BEGIN_PRE_(QS_QF_TICK, 0U) - ++prev->ctr; - QS_TEC_PRE_(prev->ctr); // tick ctr - QS_U8_PRE_(tickRate); // tick rate - QS_END_PRE_() - - // scan the linked-list of time events at this rate... - for (;;) { - QTimeEvt *t = prev->next; // advance down the time evt. list - - // end of the list? - if (t == (QTimeEvt *)0) { - - // any new time events armed since the last QTimeEvt_tick_()? - if (QTimeEvt_timeEvtHead_[tickRate].act != (void *)0) { - - // sanity check - Q_ASSERT_INCRIT(610, prev != (QTimeEvt *)0); - prev->next = (QTimeEvt *)QTimeEvt_timeEvtHead_[tickRate].act; - QTimeEvt_timeEvtHead_[tickRate].act = (void *)0; - t = prev->next; // switch to the new list - } - else { - break; // all currently armed time evts. processed - } - } - - // time event scheduled for removal? - if (t->ctr == 0U) { - prev->next = t->next; - // mark time event 't' as NOT linked - t->super.refCtr_ &= (uint8_t)(~QTE_IS_LINKED); - // do NOT advance the prev pointer - // exit crit. section to reduce latency - portEXIT_CRITICAL_ISR(&QF_esp32mux); - } - else { - --t->ctr; - - // is time evt about to expire? - if (t->ctr == 0U) { - QActive *act = (QActive *)t->act; // temp. for volatile - - // periodic time evt? - if (t->interval != 0U) { - t->ctr = t->interval; // rearm the time event - prev = t; // advance to this time event - } - // one-shot time event: automatically disarm - else { - prev->next = t->next; - // mark time event 't' as NOT linked - t->super.refCtr_ &= (uint8_t)(~QTE_IS_LINKED); - // do NOT advance the prev pointer - - QS_BEGIN_PRE_(QS_QF_TIMEEVT_AUTO_DISARM, act->prio) - QS_OBJ_PRE_(t); // this time event object - QS_OBJ_PRE_(act); // the target AO - QS_U8_PRE_(tickRate); // tick rate - QS_END_PRE_() - } - - QS_BEGIN_PRE_(QS_QF_TIMEEVT_POST, act->prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(t); // the time event object - QS_SIG_PRE_(t->super.sig); // signal of time event - QS_OBJ_PRE_(act); // the target AO - QS_U8_PRE_(tickRate); // tick rate - QS_END_PRE_() - - // exit critical section before posting - portEXIT_CRITICAL_ISR(&QF_esp32mux); - - // QACTIVE_POST_FROM_ISR() asserts if the queue overflows - QACTIVE_POST_FROM_ISR(act, &t->super, - pxHigherPriorityTaskWoken, - sender); - } - else { - prev = t; // advance to this time event - // exit crit. section to reduce latency - portEXIT_CRITICAL_ISR(&QF_esp32mux); - } - } - // re-enter crit. section to continue - portENTER_CRITICAL_ISR(&QF_esp32mux); - } - portEXIT_CRITICAL_ISR(&QF_esp32mux); -} -//............................................................................ -QEvt IRAM_ATTR *QF_newXFromISR_(uint_fast16_t const evtSize, - uint_fast16_t const margin, enum_t const sig) -{ - // find the poolNum that fits the requested event size ... - uint_fast8_t idx; - for (idx = 0U; idx < QF_priv_.maxPool_; ++idx) { - if (evtSize <= QF_EPOOL_EVENT_SIZE_(QF_priv_.ePool_[idx])) { - break; - } - } - // cannot run out of registered pools - portENTER_CRITICAL_ISR(&QF_esp32mux); - Q_REQUIRE_INCRIT(700, idx < QF_priv_.maxPool_); - portEXIT_CRITICAL_ISR(&QF_esp32mux); - - // get e -- platform-dependent -#ifdef Q_SPY - QEvt *e = QMPool_getFromISR(&QF_priv_.ePool_[idx], - ((margin != QF_NO_MARGIN) ? margin : 0U), - (uint_fast8_t)QS_EP_ID + idx + 1U); -#else - QEvt *e = QMPool_getFromISR(&QF_priv_.ePool_[idx], - ((margin != QF_NO_MARGIN) ? margin : 0U), 0U); -#endif - - // was e allocated correctly? - if (e != (QEvt *)0) { - e->sig = (QSignal)sig; // set the signal - e->refCtr_ = 0U; // initialize the reference counter to 0 - e->evtTag_ = (uint8_t)(QEVT_MARKER | (idx + 1U)); // pool ID - -#ifdef Q_SPY - portENTER_CRITICAL_ISR(&QF_esp32mux); - QS_BEGIN_PRE_(QS_QF_NEW, - (uint_fast8_t)QS_EP_ID + idx + 1U) - QS_TIME_PRE_(); // timestamp - QS_EVS_PRE_(evtSize); // the size of the event - QS_SIG_PRE_(sig); // the signal of the event - QS_END_PRE_() - portEXIT_CRITICAL_ISR(&QF_esp32mux); -#endif // Q_SPY - } - else { // event cannot be allocated - // must tolerate bad alloc. - portENTER_CRITICAL_ISR(&QF_esp32mux); - Q_ASSERT_INCRIT(720, margin != QF_NO_MARGIN); - portEXIT_CRITICAL_ISR(&QF_esp32mux); - -#ifdef Q_SPY - portENTER_CRITICAL_ISR(&QF_esp32mux); - QS_BEGIN_PRE_(QS_QF_NEW_ATTEMPT, - (uint_fast8_t)QS_EP_ID + idx + 1U) - QS_TIME_PRE_(); // timestamp - QS_EVS_PRE_(evtSize); // the size of the event - QS_SIG_PRE_(sig); // the signal of the event - QS_END_PRE_() - portEXIT_CRITICAL_ISR(&QF_esp32mux); -#endif // Q_SPY - } - return e; // can't be NULL if we can't tolerate bad allocation -} -//............................................................................ -void IRAM_ATTR QF_gcFromISR(QEvt const * const e) { - // is it a dynamic event? - if (QEvt_getPoolNum_(e) != 0U) { - portENTER_CRITICAL_ISR(&QF_esp32mux); - - // isn't this the last ref? - if (e->refCtr_ > 1U) { - QEvt_refCtr_dec_(e); // decrement the ref counter - - QS_BEGIN_PRE_(QS_QF_GC_ATTEMPT, - (uint_fast8_t)QEvt_getPoolNum_(e)) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of the event - QS_2U8_PRE_(QEvt_getPoolNum_(e), e->refCtr_);//pool-Id&ref-Count - QS_END_PRE_() - - portEXIT_CRITICAL_ISR(&QF_esp32mux); - } - // this is the last reference to this event, recycle it - else { - uint_fast8_t idx = (uint_fast8_t)QEvt_getPoolNum_(e) - 1U; - - QS_BEGIN_PRE_(QS_QF_GC, (uint_fast8_t)QEvt_getPoolNum_(e)) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of the event - QS_2U8_PRE_(QEvt_getPoolNum_(e), e->refCtr_);//pool-Id&ref-Count - QS_END_PRE_() - - // pool ID must be in range - Q_ASSERT_INCRIT(810, idx < QF_priv_.maxPool_); - - portEXIT_CRITICAL_ISR(&QF_esp32mux); - -#ifdef Q_SPY - // cast 'const' away in (QEvt *)e is OK because it's a pool event - QMPool_putFromISR(&QF_priv_.ePool_[idx], (QEvt *)e, - (uint_fast8_t)QS_EP_ID + QEvt_getPoolNum_(e)); -#else - QMPool_putFromISR(&QF_priv_.ePool_[idx], (QEvt *)e, 0U); -#endif - } - } -} -//............................................................................ -void IRAM_ATTR QMPool_putFromISR(QMPool * const me, void *b, - uint_fast8_t const qsId) -{ -#ifndef Q_SPY - Q_UNUSED_PAR(qsId); -#endif - - QFreeBlock * const fb = (QFreeBlock *)block; - - portENTER_CRITICAL_ISR(&QF_esp32mux); - - // precondition: - // - # free blocks cannot exceed the total # blocks and - // - the block pointer must be from this pool. - Q_REQUIRE_INCRIT(900, (me->nFree < me->nTot) - && (me->start <= fb) && (fb <= me->end)); - - fb->next = me->free_head; // link into list -#ifndef Q_UNSAFE - fb->next_dis = (uintptr_t)(~Q_UINTPTR_CAST_(fb->next)); -#endif - - me->free_head = block; // set as new head of the free list - ++me->nFree; // one more free block in this pool - - QS_BEGIN_PRE_(QS_QF_MPOOL_PUT, qsId) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(me); // this memory pool - QS_MPC_PRE_(me->nFree); // the number of free blocks in the pool - QS_END_PRE_() - - portEXIT_CRITICAL_ISR(&QF_esp32mux); -} -//............................................................................ -void *QMPool_getFromISR(QMPool * const me, uint_fast16_t const margin, - uint_fast8_t const qsId) -{ -#ifndef Q_SPY - Q_UNUSED_PAR(qsId); -#endif - - portENTER_CRITICAL_ISR(&QF_esp32mux); - - // have more free blocks than the requested margin? - QFreeBlock *fb; - if (me->nFree > (QMPoolCtr)margin) { - fb = me->free_head; // get a free block - - // the pool has some free blocks, so a free block must be available - Q_ASSERT_INCRIT(900, fb != (QFreeBlock *)0); - - QFreeBlock * const fb_next = fb->next; // fast temporary to avoid UB - - // the free block must have integrity (duplicate inverse storage) - Q_ASSERT_INCRIT(902, Q_UINTPTR_CAST_(fb_next) - == (uintptr_t)~fb->next_dis); - - // is the pool becoming empty? - --me->nFree; // one less free block - if (me->nFree == 0U) { - // pool is becoming empty, so the next free block must be NULL - Q_ASSERT_INCRIT(920, fb_next == (QFreeBlock *)0); - - me->nMin = 0U; // remember that the pool got empty - } - else { - // invariant - // The pool is not empty, so the next free-block pointer, - // so the next free block must be in range. - // - // NOTE: The next free block pointer can fall out of range - // when the client code writes past the memory block, thus - // corrupting the next block. - Q_ASSERT_INCRIT(930, - (me->start <= fb_next) && (fb_next <= me->end)); - - // is the number of free blocks the new minimum so far? - if (me->nMin > me->nFree) { - me->nMin = me->nFree; // remember the new minimum - } - } - - me->free_head = fb_next; // set the head to the next free block - - QS_BEGIN_PRE_(QS_QF_MPOOL_GET, qsId) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(me); // this memory pool - QS_MPC_PRE_(me->nFree); // # free blocks in the pool - QS_MPC_PRE_(me->nMin); // min # free blocks ever in the pool - QS_END_PRE_() - } - else { // don't have enough free blocks at this point - fb = (QFreeBlock *)0; - - QS_BEGIN_PRE_(QS_QF_MPOOL_GET_ATTEMPT, qsId) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(me); // this memory pool - QS_MPC_PRE_(me->nFree); // # free blocks in the pool - QS_MPC_PRE_(margin); // the requested margin - QS_END_PRE_() - } - portEXIT_CRITICAL_ISR(&QF_esp32mux); - - return fb; // return the block or NULL pointer to the caller -} - -//============================================================================ -// NOTE3: -// The event posting to FreeRTOS message queue occurs OUTSIDE critical section, -// which means that the remaining margin of available slots in the queue -// cannot be guaranteed. The problem is that interrupts and other tasks can -// preempt the event posting after checking the margin, but before actually -// posting the event to the queue. -// - diff --git a/ports/esp-idf/qp_port.h b/ports/esp-idf/qp_port.h deleted file mode 100644 index 732abe94..00000000 --- a/ports/esp-idf/qp_port.h +++ /dev/null @@ -1,269 +0,0 @@ -//============================================================================ -// QP/C Real-Time Embedded Framework (RTEF) -// -// Q u a n t u m L e a P s -// ------------------------ -// Modern Embedded Software -// -// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial -// -// This software is dual-licensed under the terms of the open source GNU -// General Public License version 3 (or any later version), or alternatively, -// under the terms of one of the closed source Quantum Leaps commercial -// licenses. -// -// The terms of the open source GNU General Public License version 3 -// can be found at: -// -// The terms of the closed source Quantum Leaps commercial licenses -// can be found at: -// -// Redistributions in source code must retain this top-level comment block. -// Plagiarizing this software to sidestep the license obligations is illegal. -// -// Contact information: -// -// -//============================================================================ -//! @date Last updated on: 2023-09-07 -//! @version Last updated for: @ref qpc_7_3_0 -//! -//! @file -//! @brief QP/C port to Espressif ESP-IDF (version 4.x), Experimental, NOTE0 -//! -#ifndef QP_PORT_H_ -#define QP_PORT_H_ - -#include // Exact-width types. WG14/N843 C99 Standard -#include // Boolean type. WG14/N843 C99 Standard - -#ifdef QP_CONFIG -#include "qp_config.h" // external QP configuration -#endif - -// no-return function specifier (C11 Standard) -#define Q_NORETURN _Noreturn void - -// QActive event queue and thread types for Espressif ESP-IDF -#define QACTIVE_EQUEUE_TYPE QueueHandle_t -#define QACTIVE_OS_OBJ_TYPE StaticQueue_t -#define QACTIVE_THREAD_TYPE StaticTask_t - -// FreeRTOS requires the "FromISR" API in QP/C++ -#define QF_ISR_API 1 - -// QF interrupt disabling for FreeRTOS-ESP32 (task level), see NOTE2 -#define QF_INT_DISABLE() portENTER_CRITICAL(&QF_esp32mux) -#define QF_INT_ENABLE() portEXIT_CRITICAL(&QF_esp32mux) - -// QF critical section for FreeRTOS-ESP32 (task level), see NOTE2 -#define QF_CRIT_STAT -#define QF_CRIT_ENTRY() portENTER_CRITICAL(&QF_esp32mux) -#define QF_CRIT_EXIT() portEXIT_CRITICAL(&QF_esp32mux) - -// include files ------------------------------------------------------------- -#include "freertos/FreeRTOS.h" // FreeRTOS master include file, see NOTE3 -#include "freertos/task.h" // FreeRTOS task management -#include "freertos/queue.h" // FreeRTOS queue management - -#include "qequeue.h" // QP event queue (for deferring events) -#include "qmpool.h" // QP memory pool (for event pools) -#include "qp.h" // QP platform-independent public interface - -// global spinlock "mutex" for all critical sections in QF (see NOTE4) -extern PRIVILEGED_DATA portMUX_TYPE QF_esp32mux; - -#if defined( CONFIG_QPC_PINNED_TO_CORE_0 ) - #define QPC_CPU_NUM PRO_CPU_NUM -#elif defined( CONFIG_QPC_PINNED_TO_CORE_1 ) - #define QPC_CPU_NUM APP_CPU_NUM -#else - // Defaults to APP_CPU - #define QPC_CPU_NUM APP_CPU_NUM -#endif - -// the "FromISR" versions of the QF APIs, see NOTE3 -#ifdef Q_SPY - -#define QACTIVE_POST_FROM_ISR(me_, e_, pxHigherPrioTaskWoken_, sender_) \ - ((void)QActive_postFromISR_((me_), (e_), QF_NO_MARGIN, \ - (pxHigherPrioTaskWoken_), (sender_))) - -#define QACTIVE_POST_X_FROM_ISR(me_, e_, margin_, \ - pxHigherPrioTaskWoken_, sender_) \ - (QActive_postFromISR_((me_), (e_), (margin_), \ - (pxHigherPrioTaskWoken_), (sender_))) - -#define QACTIVE_PUBLISH_FROM_ISR(e_, pxHigherPrioTaskWoken_, sender_) \ - (QActive_publishFromISR_((e_), (pxHigherPrioTaskWoken_), \ - (void const *)(sender_))) - -#define QTIMEEVT_TICK_FROM_ISR(tickRate_, pxHigherPrioTaskWoken_, sender_) \ - (QTimeEvt_tickFromISR_((tickRate_), (pxHigherPrioTaskWoken_), (sender_))) - -#else // ndef Q_SPY - -#define QACTIVE_POST_FROM_ISR(me_, e_, pxHigherPrioTaskWoken_, dummy) \ - ((void)QActive_postFromISR_((me_), (e_), QF_NO_MARGIN, \ - (pxHigherPrioTaskWoken_), (void *)0)) - -#define QACTIVE_POST_X_FROM_ISR(me_, e_, margin_, \ - pxHigherPrioTaskWoken_, dummy) \ - (QActive_postFromISR_((me_), (e_), (margin_), \ - (pxHigherPrioTaskWoken_), (void *)0)) - -#define QACTIVE_PUBLISH_FROM_ISR(e_, pxHigherPrioTaskWoken_, dummy) \ - (QActive_publishFromISR_((e_), (pxHigherPrioTaskWoken_), \ - (void *)0)) - -#define QTIMEEVT_TICK_FROM_ISR(tickRate_, pxHigherPrioTaskWoken_, dummy) \ - (QTimeEvt_tickFromISR_((tickRate_), (pxHigherPrioTaskWoken_), (void *)0)) - -#endif // Q_SPY - -bool IRAM_ATTR QActive_postFromISR_(QActive * const me, QEvt const * const e, - uint_fast16_t const margin, - BaseType_t * const pxHigherPriorityTaskWoken, - void const * const sender); - -void IRAM_ATTR QActive_publishFromISR_(QEvt const * const e, - BaseType_t * const pxHigherPriorityTaskWoken, - void const * const sender); - -void IRAM_ATTR QTimeEvt_tickFromISR_(uint_fast8_t const tickRate, - BaseType_t * const pxHigherPriorityTaskWoken, - void const * const sender); - -#define QF_TICK_FROM_ISR(pxHigherPrioTaskWoken_, sender_) \ - QTIMEEVT_TICK_FROM_ISR(0U, pxHigherPrioTaskWoken_, sender_) - -#ifdef QEVT_DYN_CTOR // Shall the ctor for the ::QEvt class be provided? - - #define Q_NEW_FROM_ISR(evtT_, sig_, ...) \ - (evtT_##_ctor((evtT_ *)QF_newXFromISR_(sizeof(evtT_), \ - QF_NO_MARGIN, (sig_)), __VA_ARGS__)) - - #define Q_NEW_X_FROM_ISR(e_, evtT_, margin_, sig_, ...) do { \ - (e_) = (evtT_ *)QF_newXFromISR_(sizeof(evtT_), \ - (margin_), (sig_)); \ - if ((e_) != (evtT_ *)0) { \ - evtT_##_ctor((e_), __VA_ARGS__); \ - } \ - } while (false) - -#else // no ::QEvt ctor - - #define Q_NEW_FROM_ISR(evtT_, sig_) \ - ((evtT_ *)QF_newXFromISR_((uint_fast16_t)sizeof(evtT_), \ - QF_NO_MARGIN, (sig_))) - - #define Q_NEW_X_FROM_ISR(e_, evtT_, margin_, sig_) ((e_) = \ - (evtT_ *)QF_newXFromISR_((uint_fast16_t)sizeof(evtT_), \ - (margin_), (sig_))) - -#endif // QEVT_DYN_CTOR - -void QF_gcFromISR(QEvt const * const e); - -QEvt *QF_newXFromISR_(uint_fast16_t const evtSize, - uint_fast16_t const margin, enum_t const sig); - -void *QMPool_getFromISR(QMPool * const me, uint_fast16_t const margin, - uint_fast8_t const qsId); -void QMPool_putFromISR(QMPool * const me, void *block, - uint_fast8_t const qsId); - -enum FreeRTOS_TaskAttrs { - TASK_NAME_ATTR -}; - -// FreeRTOS hooks prototypes (not provided by FreeRTOS) -#if (configUSE_IDLE_HOOK > 0) - void vApplicationIdleHook(void); -#endif -#if (configUSE_TICK_HOOK > 0) - void vApplicationTickHook(void); -#endif -#if (configCHECK_FOR_STACK_OVERFLOW > 0) - void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName); -#endif -#if (configSUPPORT_STATIC_ALLOCATION > 0) - void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, - StackType_t **ppxIdleTaskStackBuffer, - uint32_t *pulIdleTaskStackSize); -#endif - -//============================================================================ -// interface used only inside QF, but not in applications - -#ifdef QP_IMPL - #define FREERTOS_TASK_PRIO(qp_prio_) \ - ((UBaseType_t)((qp_prio_) + tskIDLE_PRIORITY)) - - // FreeRTOS scheduler locking for QF_publish_() (task context only) - #define QF_SCHED_STAT_ - #define QF_SCHED_LOCK_(prio_) (vTaskSuspendAll()) - #define QF_SCHED_UNLOCK_() ((void)xTaskResumeAll()) - - // native QF event pool customization - #define QF_EPOOL_TYPE_ QMPool - #define QF_EPOOL_INIT_(p_, poolSto_, poolSize_, evtSize_) \ - (QMPool_init(&(p_), (poolSto_), (poolSize_), (evtSize_))) - #define QF_EPOOL_EVENT_SIZE_(p_) ((uint_fast16_t)(p_).blockSize) - #define QF_EPOOL_GET_(p_, e_, m_, qsId_) \ - ((e_) = (QEvt *)QMPool_get(&(p_), (m_), (qsId_))) - #define QF_EPOOL_PUT_(p_, e_, qsId_) \ - (QMPool_put(&(p_), (e_), (qsId_))) - -#endif // QP_IMPL - -//============================================================================ -// NOTE0: -// This is the "experimental" port to the [Espressif ESP-IDF][1] -// IoT Framework, which is loosely based on the [FreeRTOS kernel][2]. -// -// "Experimental" means that the port has not been thoroughly tested at -// Quantum Leaps and no working examples are provided. -// -// The [Espressif ESP-IDF][1] is based on a significantly changed version -// of the FreeRTOS kernel developed by Espressif to support the ESP32 -// multi-core CPUs (see [ESP-IDF][1]). -// -// The Espressif version of FreeRTOS is **NOT** compatible with the baseline -// FreeRTOS and it needs to be treated as a separate RTOS kernel. -// According to the comments in the Espressif source code, FreeRTOS-ESP-IDF -// is based on FreeRTOS V8.2.0, but apparently FreeRTOS-ESP-IDF has been -// updated with the newer features introduced to the original FreeRTOS in the -// later versions. For example, FreeRTOS-ESP32 supports the "static allocation", -// first introduced in baseline FreeRTOS V9.x. This QP port to FreeRTOS-ESP-IDF -// takes advantage of the "static allocation". -// -// [1]: https://www.espressif.com/en/products/sdks/esp-idf -// [2]: https://freertos.org -// -// NOTE1: -// The maximum number of active objects QF_MAX_ACTIVE can be increased to 64, -// inclusive, but it can be reduced to save some memory. Also, the number of -// active objects cannot exceed the number of FreeRTOS task priorities, -// because each QP active object requires a unique priority level. -// -// NOTE2: -// The critical section definition applies only to the FreeRTOS "task level" -// APIs. The "FromISR" APIs are defined separately. -// -// NOTE3: -// The design of FreeRTOS requires using different APIs inside the ISRs -// (the "FromISR" variant) than at the task level. Accordingly, this port -// provides the "FromISR" variants for QP functions and "FROM_ISR" variants -// for QP macros to be used inside ISRs. ONLY THESE "FROM_ISR" VARIANTS -// ARE ALLOWED INSIDE ISRs AND CALLING THE TASK-LEVEL APIs IS AN ERROR. -// -// NOTE4: -// This QF port to FreeRTOS-ESP32 uses the FreeRTOS-ESP32 spin lock "mutex", -// similar to the internal implementation of FreeRTOS-ESP32 (see tasks.c). -// However, the QF port uses its own "mutex" object QF_esp32mux. - -#endif // QP_PORT_H_ - diff --git a/ports/esp-idf/qs_port.h b/ports/esp-idf/qs_port.h deleted file mode 100644 index 206b7e4c..00000000 --- a/ports/esp-idf/qs_port.h +++ /dev/null @@ -1,56 +0,0 @@ -//============================================================================ -// QP/C Real-Time Embedded Framework (RTEF) -// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -// -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial -// -// This software is dual-licensed under the terms of the open source GNU -// General Public License version 3 (or any later version), or alternatively, -// under the terms of one of the closed source Quantum Leaps commercial -// licenses. -// -// The terms of the open source GNU General Public License version 3 -// can be found at: -// -// The terms of the closed source Quantum Leaps commercial licenses -// can be found at: -// -// Redistributions in source code must retain this top-level comment block. -// Plagiarizing this software to sidestep the license obligations is illegal. -// -// Contact information: -// -// -//============================================================================ -//! @date Last updated on: 2023-08-16 -//! @version Last updated for: @ref qpc_7_3_0 -//! -//! @file -//! @brief QS/C port to a 32-bit CPU and a generic C11 compiler. - -#ifndef QS_PORT_H_ -#define QS_PORT_H_ - -// QS time-stamp size in bytes -#define QS_TIME_SIZE 4U - -// object pointer size in bytes -#define QS_OBJ_PTR_SIZE 4U - -// function pointer size in bytes -#define QS_FUN_PTR_SIZE 4U - -//============================================================================ -// NOTE: QS might be used with or without other QP components, in which -// case the separate definitions of the macros QF_CRIT_STAT, QF_CRIT_ENTRY(), -// and QF_CRIT_EXIT() are needed. In this port QS is configured to be used -// with the other QP component, by simply including "qp_port.h" -//*before* "qs.h". -#ifndef QP_PORT_H_ -#include "qp_port.h" // use QS with QF -#endif - -#include "qs.h" // QS platform-independent public interface - -#endif // QS_PORT_H_ - diff --git a/ports/msp430/CMakeLists.txt b/ports/msp430/CMakeLists.txt index 0737a074..8ecb9c75 100644 --- a/ports/msp430/CMakeLists.txt +++ b/ports/msp430/CMakeLists.txt @@ -1,8 +1,10 @@ # ports/msp430 if(QPC_CFG_UNIT_TEST) target_include_directories(qpc PUBLIC qutest) -elseif(NOT KERNEL MATCHES "q[vk]") - message(WARNING "Kernel ${KERNEL} is not supported! Falling back to QV kernel") - set(KERNEL qv) +else() + if(NOT KERNEL MATCHES "q[vk]") + message(WARNING "Kernel ${KERNEL} is not supported! Falling back to QV kernel") + set(KERNEL qv) + endif() + target_include_directories(qpc PUBLIC ${KERNEL}) endif() -target_include_directories(qpc PUBLIC ${KERNEL}) diff --git a/ports/pic32/CMakeLists.txt b/ports/pic32/CMakeLists.txt index bd93ba10..515408ef 100644 --- a/ports/pic32/CMakeLists.txt +++ b/ports/pic32/CMakeLists.txt @@ -1,11 +1,15 @@ # ports/pic32 if(QPC_CFG_UNIT_TEST) target_include_directories(qpc PUBLIC qutest/xc32) -elseif(NOT KERNEL MATCHES "q[vk]") - message(WARNING "Kernel ${KERNEL} is not supported! Falling back to QV kernel") - set(KERNEL qv) -endif() -target_include_directories(qpc PUBLIC ${KERNEL}/xc32) -if(KERNEL STREQUAL qk) - target_sources(qpc PRIVATE qk_port.c) -endif() +else() + if(NOT KERNEL MATCHES "q[vk]") + message(WARNING "Kernel ${KERNEL} is not supported! Falling back to QV kernel") + set(KERNEL qv) + endif() + + set(KERNEL_PORT_C ${CMAKE_CURRENT_LIST_DIR}/${KERNEL}/xc32/${KERNEL}_port.c) + if(EXISTS ${KERNEL_PORT_C}) + target_sources(qpc PRIVATE ${KERNEL_PORT_C}) + endif() + target_include_directories(qpc PUBLIC ${KERNEL}/xc32) +endif() \ No newline at end of file diff --git a/ports/posix-qutest/CMakeLists.txt b/ports/posix-qutest/CMakeLists.txt index 3b4181ae..79dad1d5 100644 --- a/ports/posix-qutest/CMakeLists.txt +++ b/ports/posix-qutest/CMakeLists.txt @@ -1,7 +1,5 @@ # ports/posix-qutest target_include_directories(qpc PUBLIC .) -target_sources( - qpc - PRIVATE - qutest_port.c +target_sources(qpc PRIVATE + qutest_port.c ) \ No newline at end of file diff --git a/ports/posix-qv/CMakeLists.txt b/ports/posix-qv/CMakeLists.txt index 4ac54bdd..079e3b68 100644 --- a/ports/posix-qv/CMakeLists.txt +++ b/ports/posix-qv/CMakeLists.txt @@ -1,8 +1,6 @@ # ports/posix-qv target_include_directories(qpc PUBLIC .) -target_sources( - qpc - PRIVATE - qf_port.c - $<$:${CMAKE_CURRENT_SOURCE_DIR}/qs_port.c> +target_sources(qpc PRIVATE + qf_port.c + $<$:${CMAKE_CURRENT_SOURCE_DIR}/qs_port.c> ) \ No newline at end of file diff --git a/ports/posix/CMakeLists.txt b/ports/posix/CMakeLists.txt index 14200754..c3b3917e 100644 --- a/ports/posix/CMakeLists.txt +++ b/ports/posix/CMakeLists.txt @@ -1,8 +1,6 @@ # ports/posix target_include_directories(qpc PUBLIC .) -target_sources( - qpc - PRIVATE - qf_port.c - $<$:${CMAKE_CURRENT_SOURCE_DIR}/qs_port.c> +target_sources(qpc PRIVATE + qf_port.c + $<$:${CMAKE_CURRENT_SOURCE_DIR}/qs_port.c> ) \ No newline at end of file diff --git a/ports/win32-qutest/CMakeLists.txt b/ports/win32-qutest/CMakeLists.txt index f8e6ea24..7f537635 100644 --- a/ports/win32-qutest/CMakeLists.txt +++ b/ports/win32-qutest/CMakeLists.txt @@ -1,7 +1,5 @@ # ports/win32-qutest target_include_directories(qpc PUBLIC .) -target_sources( - qpc - PRIVATE - qutest_port.c +target_sources(qpc PRIVATE + qutest_port.c ) \ No newline at end of file diff --git a/ports/win32-qv/CMakeLists.txt b/ports/win32-qv/CMakeLists.txt index 02de3d9a..88bb45f0 100644 --- a/ports/win32-qv/CMakeLists.txt +++ b/ports/win32-qv/CMakeLists.txt @@ -1,9 +1,7 @@ # ports/win32-qv target_include_directories(qpc PUBLIC .) -target_sources( - qpc - PRIVATE - qf_port.c - $<$:${CMAKE_CURRENT_SOURCE_DIR}/qwin_gui.c> - $<$:${CMAKE_CURRENT_SOURCE_DIR}/qs_port.c> +target_sources(qpc PRIVATE + qf_port.c + $<$:${CMAKE_CURRENT_SOURCE_DIR}/qwin_gui.c> + $<$:${CMAKE_CURRENT_SOURCE_DIR}/qs_port.c> ) diff --git a/ports/win32/CMakeLists.txt b/ports/win32/CMakeLists.txt index 4ce6a249..cca82f50 100644 --- a/ports/win32/CMakeLists.txt +++ b/ports/win32/CMakeLists.txt @@ -1,9 +1,7 @@ # ports/win32 target_include_directories(qpc PUBLIC .) -target_sources( - qpc - PRIVATE - qf_port.c - $<$:${CMAKE_CURRENT_SOURCE_DIR}/qwin_gui.c> - $<$:${CMAKE_CURRENT_SOURCE_DIR}/qs_port.c> +target_sources(qpc PRIVATE + qf_port.c + $<$:${CMAKE_CURRENT_SOURCE_DIR}/qwin_gui.c> + $<$:${CMAKE_CURRENT_SOURCE_DIR}/qs_port.c> ) diff --git a/qpc.md5 b/qpc.md5 index 38511a3c..55f80b6b 100644 --- a/qpc.md5 +++ b/qpc.md5 @@ -1,4 +1,4 @@ -13078bbbcfe973eb8adb284ddccb74c7 *qpc.qm +93ecf23cf720e5728920c20ee8d973e6 *qpc.qm f71fdc0261b7d7e1693f7cf92b269fc0 *include/qequeue.h 57b1efebccde23a26f9d11e822ec379f *include/qk.h 807f80a7a39be52083010803f76b4f05 *include/qmpool.h @@ -25,18 +25,18 @@ bc3e5d7fcb172fee6881f993160502eb *src/qf/qf_mem.c a34020507dc261f49eaaaf2062dcb81d *src/qf/qf_qeq.c f9867335faa23f0b57c921c8882e7a52 *src/qf/qf_qmact.c b0531b1989555c6b7d128e112f4f3c39 *src/qf/qf_time.c -a8fb5148cc628738ab7bf073e7fe2cdd *src/qk/CMakeLists.txt -f5b5ef77f45d50a6450efd85995287c7 *src/qk/qk.c -a9fac3a677755efae96fc84c15acd587 *src/qs/CMakeLists.txt +ccd28413fc3a093ca99b03854cf7439b *src/qk/CMakeLists.txt +aa27bde6715639754f8857a46c344442 *src/qk/qk.c +27c155798720d7fb3b2f9cc38e311393 *src/qs/CMakeLists.txt e045ce8b2fc053d068ec3eb10c9f65bf *src/qs/qs.c 9091ffd15f7ec791076091bb17eec5fc *src/qs/qs_64bit.c 730d9bea159722e5d2c225e01b5c7875 *src/qs/qs_fp.c 60453f6d2b1f915e6e477cca68cb7fee *src/qs/qs_rx.c 80a31dfc0e24839342fe193779401e7b *src/qs/qstamp.c 53ab2ae396c90e41045b019cdfea21b5 *src/qs/qutest.c -f2661d91230a78b9c515f53a70dd81a4 *src/qv/CMakeLists.txt -df8818b82672a7b9b2daa6a73e52036f *src/qv/qv.c -893c91432ce0fcf195780e4827aeef25 *src/qxk/CMakeLists.txt +cf8fa24441cb9577288f73bdb4effbff *src/qv/CMakeLists.txt +bb08eae11dacb60099c7ff7a7b3700b3 *src/qv/qv.c +3a9240f29676dea5ce3df8fed587ae52 *src/qxk/CMakeLists.txt 8d2e28ffb1c8c670924de4c987fb35df *src/qxk/qxk.c f65131e2a680cc2f419f43437e1f873a *src/qxk/qxk_mutex.c 214032bca5ddd45690cf3ca67f9f86c3 *src/qxk/qxk_sema.c @@ -128,26 +128,26 @@ b9be2bca2c48d39a43e4b3d059376b6a *ports/uc-os2/qp_port.h 281f9d70e7fb90b4457bee33b544c460 *ports/qep-only/CMakeLists.txt 6ce09e456ded120d13d73a92e022fa3d *ports/qep-only/qp_port.h f26311a1912e214477781255c7c71834 *ports/qep-only/safe_std.h -5de93f2758bcc03c99929af24dbf72c3 *ports/posix/CMakeLists.txt +4577c2c64f7dbb0c81d1e99f20984888 *ports/posix/CMakeLists.txt 0a9db5ee3129a97bd19c433e12f0442e *ports/posix/qf_port.c c1764d38614122b0a02a0172a21906d9 *ports/posix/qp_port.h 5902d6c50e3d3e87c4cbeb66485c01c9 *ports/posix/qs_port.c 306c23ae37e9b02f2f37f2d21331f28d *ports/posix/qs_port.h 6690cf3899e6461ed7604dba13cf7520 *ports/posix/README.md f26311a1912e214477781255c7c71834 *ports/posix/safe_std.h -7df4439ce695a959033556402136cbe8 *ports/posix-qv/CMakeLists.txt +c36532b0e4b1956d9113f6ced25fb47b *ports/posix-qv/CMakeLists.txt 044efad276cba04709c027cc66b7d356 *ports/posix-qv/qf_port.c 46cd7f9bce31d6d519886f31f824fae0 *ports/posix-qv/qp_port.h 94d91c859c62fd464f6ce61c9d4e82b1 *ports/posix-qv/qs_port.c 306c23ae37e9b02f2f37f2d21331f28d *ports/posix-qv/qs_port.h a39965a1d1c41b224c8f328c9e28999b *ports/posix-qv/README.md f26311a1912e214477781255c7c71834 *ports/posix-qv/safe_std.h -e980172aa95e2866309b92269548ce67 *ports/posix-qutest/CMakeLists.txt +51ca57651ed492278fd728d3b94aba4d *ports/posix-qutest/CMakeLists.txt 2ec8125e0cbaf03c06c679d698ec6a32 *ports/posix-qutest/qp_port.h 306c23ae37e9b02f2f37f2d21331f28d *ports/posix-qutest/qs_port.h a7e763528627d662501e8a28ca6321c1 *ports/posix-qutest/qutest_port.c f26311a1912e214477781255c7c71834 *ports/posix-qutest/safe_std.h -3bafe0c408101957b314362e1b22e81c *ports/win32/CMakeLists.txt +5fa44dffb653cecb1d9ea41d154ce852 *ports/win32/CMakeLists.txt cd0040a8cc2c6051b2f8ea42f798d601 *ports/win32/Makefile 20fc7e8b39e32f53aca8e3f08e372957 *ports/win32/qf_port.c dddd41fe592d8832b95179820de552d2 *ports/win32/qp_port.h @@ -157,7 +157,7 @@ a46c047f83877a192b2de24f27238770 *ports/win32/qs_port.c a8f227294c6673a22b050e1165a911e3 *ports/win32/qwin_gui.h 9af4450a3685e578e1774e5b707f6692 *ports/win32/README.md f26311a1912e214477781255c7c71834 *ports/win32/safe_std.h -07088791b0937c530b7fc4a776fbd2de *ports/win32-qv/CMakeLists.txt +c28c6dd7ad5899389e556c8cc61692ce *ports/win32-qv/CMakeLists.txt 7d3aaf7289eb37ac9ef638d092f1d28f *ports/win32-qv/qf_port.c 6e8a4ca279ced37f24ac45e4ff6d4157 *ports/win32-qv/qp_port.h a46c047f83877a192b2de24f27238770 *ports/win32-qv/qs_port.c @@ -166,7 +166,7 @@ c935dbe9f32dd4d0584d4b47bc734d19 *ports/win32-qv/qwin_gui.c 37499e3a99c8c38d52d9b61be19319b7 *ports/win32-qv/qwin_gui.h 4cb22092a4b28d1c1b2efc1e58900b99 *ports/win32-qv/README.md f26311a1912e214477781255c7c71834 *ports/win32-qv/safe_std.h -4eea94cb5efae4bd95187e496d40ad88 *ports/win32-qutest/CMakeLists.txt +f62276b6a322c8fffce657cdb4998ed7 *ports/win32-qutest/CMakeLists.txt f9f1dfd9b7c2f0ce7b2c5928da09b123 *ports/win32-qutest/qp_port.h 018ec5ae698a31c6fb0f2c002194c5bd *ports/win32-qutest/qs_port.h d8259b2bb16d1826806a636c6a3293f8 *ports/win32-qutest/qutest_port.c diff --git a/qpc.qm b/qpc.qm index a3c45e40..da605647 100644 --- a/qpc.qm +++ b/qpc.qm @@ -4849,7 +4849,7 @@ if (ceiling > QV_priv_.schedCeil) { // raising the scheduler ceiling? QV_priv_.schedCeil = ceiling; #ifndef Q_UNSAFE - QV_priv_.schedCeil_dis = (uint_fast16_t)(~ceiling); + QV_priv_.schedCeil_dis = (uint_fast8_t)(~ceiling); #endif } QF_MEM_APP(); @@ -4877,7 +4877,7 @@ if (QV_priv_.schedCeil != 0U) { // actually enabling the scheduler? QV_priv_.schedCeil = 0U; #ifndef Q_UNSAFE - QV_priv_.schedCeil_dis = (uint_fast16_t)(~0U); + QV_priv_.schedCeil_dis = (uint_fast8_t)(~0U); #endif } QF_MEM_APP(); @@ -4903,7 +4903,7 @@ QF_bzero_(&QActive_registry_[0], sizeof(QActive_registry_)); #ifndef Q_UNSAFE QPSet_update_(&QV_priv_.readySet, &QV_priv_.readySet_dis); -QV_priv_.schedCeil_dis = (uint_fast16_t)(~0U); +QV_priv_.schedCeil_dis = (uint_fast8_t)(~0U); #endif for (uint_fast8_t tickRate = 0U; @@ -5199,7 +5199,8 @@ QF_CRIT_ENTRY(); QF_MEM_SYS(); Q_REQUIRE_INCRIT(100, !QK_ISR_CONTEXT_()); -Q_REQUIRE_INCRIT(102, QK_priv_.lockCeil == ~QK_priv_.lockCeil_dis); +Q_REQUIRE_INCRIT(102, QK_priv_.lockCeil + == (uint_fast8_t)(~QK_priv_.lockCeil_dis)); // first store the previous lock prio QSchedStatus stat; @@ -5216,7 +5217,7 @@ if (ceiling > QK_priv_.lockCeil) { // raising the lock ceiling? // new status of the lock QK_priv_.lockCeil = ceiling; #ifndef Q_UNSAFE - QK_priv_.lockCeil_dis = ~ceiling; + QK_priv_.lockCeil_dis = (uint_fast8_t)(~ceiling); #endif } else { @@ -5241,7 +5242,8 @@ if (prevCeil != 0xFFU) { QF_CRIT_ENTRY(); QF_MEM_SYS(); - Q_REQUIRE_INCRIT(202, QK_priv_.lockCeil == ~QK_priv_.lockCeil_dis); + Q_REQUIRE_INCRIT(202, QK_priv_.lockCeil + == (uint_fast8_t)(~QK_priv_.lockCeil_dis)); Q_REQUIRE_INCRIT(210, (!QK_ISR_CONTEXT_()) && (QK_priv_.lockCeil > prevCeil)); @@ -5254,7 +5256,7 @@ if (prevCeil != 0xFFU) { // restore the previous lock ceiling QK_priv_.lockCeil = prevCeil; #ifndef Q_UNSAFE - QK_priv_.lockCeil_dis = ~prevCeil; + QK_priv_.lockCeil_dis = (uint_fast8_t)(~prevCeil); #endif // find if any AOs should be run after unlocking the scheduler @@ -5290,26 +5292,26 @@ else { p = QPSet_findMax(&QK_priv_.readySet); Q_ASSERT_INCRIT(412, - QK_priv_.actThre == ~QK_priv_.actThre_dis); + QK_priv_.actThre == (uint_fast8_t)(~QK_priv_.actThre_dis)); // is the AO's prio. below the active preemption-threshold? if (p <= QK_priv_.actThre) { p = 0U; // no activation needed } else { - Q_ASSERT_INCRIT(422, - QK_priv_.lockCeil == ~QK_priv_.lockCeil_dis); + Q_ASSERT_INCRIT(422, QK_priv_.lockCeil + == (uint_fast8_t)(~QK_priv_.lockCeil_dis)); // is the AO's prio. below the lock-ceiling? if (p <= QK_priv_.lockCeil) { p = 0U; // no activation needed } else { - Q_ASSERT_INCRIT(432, - QK_priv_.nextPrio == ~QK_priv_.nextPrio_dis); + Q_ASSERT_INCRIT(432, QK_priv_.nextPrio + == (uint_fast8_t)(~QK_priv_.nextPrio_dis)); QK_priv_.nextPrio = p; // next AO to run #ifndef Q_UNSAFE - QK_priv_.nextPrio_dis = ~QK_priv_.nextPrio; + QK_priv_.nextPrio_dis = (uint_fast8_t)(~QK_priv_.nextPrio); #endif } } @@ -5328,8 +5330,8 @@ uint_fast8_t const prio_in = QK_priv_.actPrio; // save initial prio. uint_fast8_t p = QK_priv_.nextPrio; // next prio to run Q_REQUIRE_INCRIT(502, - (prio_in == ~QK_priv_.actPrio_dis) - && (p == ~QK_priv_.nextPrio_dis)); + (prio_in == (uint_fast8_t)(~QK_priv_.actPrio_dis)) + && (p == (uint_fast8_t)(~QK_priv_.nextPrio_dis))); Q_REQUIRE_INCRIT(510, (prio_in <= QF_MAX_ACTIVE) && (0U < p) && (p <= QF_MAX_ACTIVE)); @@ -5368,8 +5370,8 @@ do { QK_priv_.actPrio = p; QK_priv_.actThre = pthre; #ifndef Q_UNSAFE - QK_priv_.actPrio_dis = ~p; - QK_priv_.actThre_dis = ~pthre; + QK_priv_.actPrio_dis = (uint_fast8_t)(~p); + QK_priv_.actThre_dis = (uint_fast8_t)(~pthre); #endif #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) @@ -5427,8 +5429,8 @@ do { p = 0U; // no activation needed } else { - Q_ASSERT_INCRIT(542, - QK_priv_.lockCeil == ~QK_priv_.lockCeil_dis); + Q_ASSERT_INCRIT(542, QK_priv_.lockCeil + == (uint_fast8_t)(~QK_priv_.lockCeil_dis)); // is the AO's prio. below the lock preemption-threshold? if (p <= QK_priv_.lockCeil) { @@ -5445,8 +5447,8 @@ do { QK_priv_.actPrio = prio_in; QK_priv_.actThre = pthre_in; #ifndef Q_UNSAFE -QK_priv_.actPrio_dis = ~QK_priv_.actPrio; -QK_priv_.actThre_dis = ~QK_priv_.actThre; +QK_priv_.actPrio_dis = (uint_fast8_t)(~QK_priv_.actPrio); +QK_priv_.actThre_dis = (uint_fast8_t)(~QK_priv_.actThre); #endif #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) @@ -5491,10 +5493,10 @@ QK_priv_.lockCeil = (QF_MAX_ACTIVE + 1U); // scheduler locked #ifndef Q_UNSAFE QPSet_update_(&QK_priv_.readySet, &QK_priv_.readySet_dis); -QK_priv_.actPrio_dis = ~0U; -QK_priv_.nextPrio_dis = ~0U; -QK_priv_.actThre_dis = ~0U; -QK_priv_.lockCeil_dis = ~QK_priv_.lockCeil; +QK_priv_.actPrio_dis = (uint_fast8_t)(~0U); +QK_priv_.nextPrio_dis = (uint_fast8_t)(~0U); +QK_priv_.actThre_dis = (uint_fast8_t)(~0U); +QK_priv_.lockCeil_dis = (uint_fast8_t)(~QK_priv_.lockCeil); #endif for (uint_fast8_t tickRate = 0U; @@ -5543,7 +5545,7 @@ QK_START(); // port-specific startup of the QK kernel QK_priv_.lockCeil = 0U; // unlock the QK scheduler #ifndef Q_UNSAFE -QK_priv_.lockCeil_dis = ~0U; +QK_priv_.lockCeil_dis = (uint_fast8_t)(~0U); #endif // activate AOs to process events posted so far diff --git a/qpc_sdk_init.cmake b/qpc_sdk_init.cmake index b7431cc3..6210f6fe 100644 --- a/qpc_sdk_init.cmake +++ b/qpc_sdk_init.cmake @@ -31,7 +31,7 @@ if (NOT TARGET _qpc_sdk_pre_init_marker) set(QPC_SDK_PATH ${CMAKE_CURRENT_LIST_DIR}) endif () - get_filename_component(QPC_SDK_PATH "${QPC_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}") + file(REAL_PATH "${QPC_SDK_PATH}" QPC_SDK_PATH BASE_DIRECTORY "${CMAKE_BINARY_DIR}") set(QPC_SDK_PATH ${CMAKE_CURRENT_LIST_DIR} CACHE PATH "Path to the QP/C SDK" FORCE) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 877ee626..8d328bb9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,7 +1,7 @@ # qpc/src add_subdirectory(qf) add_subdirectory(qs) -if(${PORT} MATCHES "^(arm-|pic32|risc-v)") +if(${PORT} IN_LIST QPC_BAREMETAL_PORTS) message(STATUS "adding subdir '${KERNEL}' for port '${PORT}'") add_subdirectory(${KERNEL}) endif() diff --git a/src/qk/CMakeLists.txt b/src/qk/CMakeLists.txt index 71795473..5d68fecd 100644 --- a/src/qk/CMakeLists.txt +++ b/src/qk/CMakeLists.txt @@ -1,7 +1,5 @@ # ./src/qf -target_sources( - qpc - PRIVATE - qk.c +target_sources(qpc PRIVATE + qk.c ) diff --git a/src/qk/qk.c b/src/qk/qk.c index 22f38269..e2d3dcc5 100644 --- a/src/qk/qk.c +++ b/src/qk/qk.c @@ -78,7 +78,8 @@ QSchedStatus QK_schedLock(uint_fast8_t const ceiling) { QF_MEM_SYS(); Q_REQUIRE_INCRIT(100, !QK_ISR_CONTEXT_()); - Q_REQUIRE_INCRIT(102, QK_priv_.lockCeil == ~QK_priv_.lockCeil_dis); + Q_REQUIRE_INCRIT(102, QK_priv_.lockCeil + == (uint_fast8_t)(~QK_priv_.lockCeil_dis)); // first store the previous lock prio QSchedStatus stat; @@ -95,7 +96,7 @@ QSchedStatus QK_schedLock(uint_fast8_t const ceiling) { // new status of the lock QK_priv_.lockCeil = ceiling; #ifndef Q_UNSAFE - QK_priv_.lockCeil_dis = ~ceiling; + QK_priv_.lockCeil_dis = (uint_fast8_t)(~ceiling); #endif } else { @@ -117,7 +118,8 @@ void QK_schedUnlock(QSchedStatus const prevCeil) { QF_CRIT_ENTRY(); QF_MEM_SYS(); - Q_REQUIRE_INCRIT(202, QK_priv_.lockCeil == ~QK_priv_.lockCeil_dis); + Q_REQUIRE_INCRIT(202, QK_priv_.lockCeil + == (uint_fast8_t)(~QK_priv_.lockCeil_dis)); Q_REQUIRE_INCRIT(210, (!QK_ISR_CONTEXT_()) && (QK_priv_.lockCeil > prevCeil)); @@ -130,7 +132,7 @@ void QK_schedUnlock(QSchedStatus const prevCeil) { // restore the previous lock ceiling QK_priv_.lockCeil = prevCeil; #ifndef Q_UNSAFE - QK_priv_.lockCeil_dis = ~prevCeil; + QK_priv_.lockCeil_dis = (uint_fast8_t)(~prevCeil); #endif // find if any AOs should be run after unlocking the scheduler @@ -159,26 +161,26 @@ uint_fast8_t QK_sched_(void) { p = QPSet_findMax(&QK_priv_.readySet); Q_ASSERT_INCRIT(412, - QK_priv_.actThre == ~QK_priv_.actThre_dis); + QK_priv_.actThre == (uint_fast8_t)(~QK_priv_.actThre_dis)); // is the AO's prio. below the active preemption-threshold? if (p <= QK_priv_.actThre) { p = 0U; // no activation needed } else { - Q_ASSERT_INCRIT(422, - QK_priv_.lockCeil == ~QK_priv_.lockCeil_dis); + Q_ASSERT_INCRIT(422, QK_priv_.lockCeil + == (uint_fast8_t)(~QK_priv_.lockCeil_dis)); // is the AO's prio. below the lock-ceiling? if (p <= QK_priv_.lockCeil) { p = 0U; // no activation needed } else { - Q_ASSERT_INCRIT(432, - QK_priv_.nextPrio == ~QK_priv_.nextPrio_dis); + Q_ASSERT_INCRIT(432, QK_priv_.nextPrio + == (uint_fast8_t)(~QK_priv_.nextPrio_dis)); QK_priv_.nextPrio = p; // next AO to run #ifndef Q_UNSAFE - QK_priv_.nextPrio_dis = ~QK_priv_.nextPrio; + QK_priv_.nextPrio_dis = (uint_fast8_t)(~QK_priv_.nextPrio); #endif } } @@ -196,8 +198,8 @@ void QK_activate_(void) { uint_fast8_t p = QK_priv_.nextPrio; // next prio to run Q_REQUIRE_INCRIT(502, - (prio_in == ~QK_priv_.actPrio_dis) - && (p == ~QK_priv_.nextPrio_dis)); + (prio_in == (uint_fast8_t)(~QK_priv_.actPrio_dis)) + && (p == (uint_fast8_t)(~QK_priv_.nextPrio_dis))); Q_REQUIRE_INCRIT(510, (prio_in <= QF_MAX_ACTIVE) && (0U < p) && (p <= QF_MAX_ACTIVE)); @@ -236,8 +238,8 @@ void QK_activate_(void) { QK_priv_.actPrio = p; QK_priv_.actThre = pthre; #ifndef Q_UNSAFE - QK_priv_.actPrio_dis = ~p; - QK_priv_.actThre_dis = ~pthre; + QK_priv_.actPrio_dis = (uint_fast8_t)(~p); + QK_priv_.actThre_dis = (uint_fast8_t)(~pthre); #endif #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) @@ -295,8 +297,8 @@ void QK_activate_(void) { p = 0U; // no activation needed } else { - Q_ASSERT_INCRIT(542, - QK_priv_.lockCeil == ~QK_priv_.lockCeil_dis); + Q_ASSERT_INCRIT(542, QK_priv_.lockCeil + == (uint_fast8_t)(~QK_priv_.lockCeil_dis)); // is the AO's prio. below the lock preemption-threshold? if (p <= QK_priv_.lockCeil) { @@ -313,8 +315,8 @@ void QK_activate_(void) { QK_priv_.actPrio = prio_in; QK_priv_.actThre = pthre_in; #ifndef Q_UNSAFE - QK_priv_.actPrio_dis = ~QK_priv_.actPrio; - QK_priv_.actThre_dis = ~QK_priv_.actThre; + QK_priv_.actPrio_dis = (uint_fast8_t)(~QK_priv_.actPrio); + QK_priv_.actThre_dis = (uint_fast8_t)(~QK_priv_.actThre); #endif #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) @@ -358,10 +360,10 @@ void QF_init(void) { #ifndef Q_UNSAFE QPSet_update_(&QK_priv_.readySet, &QK_priv_.readySet_dis); - QK_priv_.actPrio_dis = ~0U; - QK_priv_.nextPrio_dis = ~0U; - QK_priv_.actThre_dis = ~0U; - QK_priv_.lockCeil_dis = ~QK_priv_.lockCeil; + QK_priv_.actPrio_dis = (uint_fast8_t)(~0U); + QK_priv_.nextPrio_dis = (uint_fast8_t)(~0U); + QK_priv_.actThre_dis = (uint_fast8_t)(~0U); + QK_priv_.lockCeil_dis = (uint_fast8_t)(~QK_priv_.lockCeil); #endif for (uint_fast8_t tickRate = 0U; @@ -408,7 +410,7 @@ int_t QF_run(void) { QK_priv_.lockCeil = 0U; // unlock the QK scheduler #ifndef Q_UNSAFE - QK_priv_.lockCeil_dis = ~0U; + QK_priv_.lockCeil_dis = (uint_fast8_t)(~0U); #endif // activate AOs to process events posted so far diff --git a/src/qs/CMakeLists.txt b/src/qs/CMakeLists.txt index 554d1d3c..91af88c7 100644 --- a/src/qs/CMakeLists.txt +++ b/src/qs/CMakeLists.txt @@ -1,11 +1,9 @@ # ./src/qs -target_sources( - qpc - PRIVATE - "$<$:${CMAKE_CURRENT_SOURCE_DIR}/qs_64bit.c>" - "$<$:${CMAKE_CURRENT_SOURCE_DIR}/qs_fp.c>" - "$<$:${CMAKE_CURRENT_SOURCE_DIR}/qs_rx.c>" - "$<$:${CMAKE_CURRENT_SOURCE_DIR}/qstamp.c>" - "$<$:${CMAKE_CURRENT_SOURCE_DIR}/qs.c>" - "$<$:$<$:${CMAKE_CURRENT_SOURCE_DIR}/qutest.c>>" +target_sources(qpc PRIVATE + "$<$:${CMAKE_CURRENT_SOURCE_DIR}/qs_64bit.c>" + "$<$:${CMAKE_CURRENT_SOURCE_DIR}/qs_fp.c>" + "$<$:${CMAKE_CURRENT_SOURCE_DIR}/qs_rx.c>" + "$<$:${CMAKE_CURRENT_SOURCE_DIR}/qstamp.c>" + "$<$:${CMAKE_CURRENT_SOURCE_DIR}/qs.c>" + "$<$,$>:${CMAKE_CURRENT_SOURCE_DIR}/qutest.c>" ) diff --git a/src/qv/CMakeLists.txt b/src/qv/CMakeLists.txt index a0ab8813..1ddcd24b 100644 --- a/src/qv/CMakeLists.txt +++ b/src/qv/CMakeLists.txt @@ -1,6 +1,4 @@ # ./src/qf -target_sources( - qpc - PRIVATE - qv.c +target_sources(qpc PRIVATE + qv.c ) diff --git a/src/qv/qv.c b/src/qv/qv.c index f20d043e..de4db236 100644 --- a/src/qv/qv.c +++ b/src/qv/qv.c @@ -91,7 +91,7 @@ void QV_schedDisable(uint_fast8_t const ceiling) { QV_priv_.schedCeil = ceiling; #ifndef Q_UNSAFE - QV_priv_.schedCeil_dis = (uint_fast16_t)(~ceiling); + QV_priv_.schedCeil_dis = (uint_fast8_t)(~ceiling); #endif } QF_MEM_APP(); @@ -118,7 +118,7 @@ void QV_schedEnable(void) { QV_priv_.schedCeil = 0U; #ifndef Q_UNSAFE - QV_priv_.schedCeil_dis = (uint_fast16_t)(~0U); + QV_priv_.schedCeil_dis = (uint_fast8_t)(~0U); #endif } QF_MEM_APP(); @@ -137,7 +137,7 @@ void QF_init(void) { #ifndef Q_UNSAFE QPSet_update_(&QV_priv_.readySet, &QV_priv_.readySet_dis); - QV_priv_.schedCeil_dis = (uint_fast16_t)(~0U); + QV_priv_.schedCeil_dis = (uint_fast8_t)(~0U); #endif for (uint_fast8_t tickRate = 0U; diff --git a/src/qxk/CMakeLists.txt b/src/qxk/CMakeLists.txt index 5fab5901..cd022edd 100644 --- a/src/qxk/CMakeLists.txt +++ b/src/qxk/CMakeLists.txt @@ -1,9 +1,7 @@ # ./src/qf -target_sources( - qpc - PRIVATE - qxk_mutex.c - qxk_sema.c - qxk_xthr.c - qxk.c +target_sources(qpc PRIVATE + qxk_mutex.c + qxk_sema.c + qxk_xthr.c + qxk.c )