From 33aa75cfa9dbbe088db2ed3abfd3621f19d32b48 Mon Sep 17 00:00:00 2001 From: MMS Date: Tue, 15 Oct 2024 13:15:28 -0400 Subject: [PATCH] 8.0.0 --- .gitignore | 24 +- 3rd_party | 2 +- LICENSES/License.txt | 4 +- LICENSES/LicenseRef-QL-dual.qlc | 28 +- README.md | 32 +- cmakeSupport.md | 49 +- examples | 2 +- include/README.md | 45 + include/qequeue.hpp | 64 +- include/qk.hpp | 35 +- include/qmpool.hpp | 60 +- include/qp.hpp | 138 +- include/qp_pkg.hpp | 57 +- include/qpcpp.hpp | 81 +- include/qs.hpp | 1058 --- include/qs_dummy.hpp | 150 +- include/qs_pkg.hpp | 215 - include/qstamp.hpp | 32 +- include/qv.hpp | 35 +- include/qxk.hpp | 342 - ports/CMakeLists.txt | 4 + ports/README.md | 63 + ports/arm-cm/qk/armclang/qk_port.cpp | 222 +- ports/arm-cm/qk/armclang/qp_port.hpp | 39 +- ports/arm-cm/qk/armclang/qs_port.hpp | 2 +- ports/arm-cm/qk/config/qp_config.hpp | 47 +- ports/arm-cm/qk/gnu/qk_port.cpp | 231 +- ports/arm-cm/qk/gnu/qp_port.hpp | 39 +- ports/arm-cm/qk/gnu/qs_port.hpp | 2 +- ports/arm-cm/qk/iar/qk_port.cpp | 215 +- ports/arm-cm/qk/iar/qp_port.hpp | 41 +- ports/arm-cm/qk/iar/qs_port.hpp | 2 +- ports/arm-cm/qutest/qp_port.hpp | 100 - ports/arm-cm/qutest/qs_port.hpp | 57 - ports/arm-cm/qv/armclang/qp_port.hpp | 51 +- ports/arm-cm/qv/armclang/qs_port.hpp | 2 +- ports/arm-cm/qv/armclang/qv_port.cpp | 69 +- ports/arm-cm/qv/config/qp_config.hpp | 41 +- ports/arm-cm/qv/gnu/qp_port.hpp | 51 +- ports/arm-cm/qv/gnu/qs_port.hpp | 2 +- ports/arm-cm/qv/gnu/qv_port.cpp | 69 +- ports/arm-cm/qv/iar/qp_port.hpp | 47 +- ports/arm-cm/qv/iar/qs_port.hpp | 2 +- ports/arm-cm/qv/iar/qv_port.cpp | 66 +- ports/arm-cm/qxk/armclang/qp_port.hpp | 237 - ports/arm-cm/qxk/armclang/qs_port.hpp | 57 - ports/arm-cm/qxk/armclang/qxk_port.cpp | 809 -- ports/arm-cm/qxk/config/qp_config.hpp | 259 - ports/arm-cm/qxk/gnu/qp_port.hpp | 237 - ports/arm-cm/qxk/gnu/qs_port.hpp | 57 - ports/arm-cm/qxk/gnu/qxk_port.cpp | 819 -- ports/arm-cm/qxk/iar/qp_port.hpp | 230 - ports/arm-cm/qxk/iar/qs_port.hpp | 57 - ports/arm-cm/qxk/iar/qxk_port.cpp | 812 -- ports/arm-cm/qxk/llvm/README.txt | 2 - ports/arm-cr/qk/config/qp_config.hpp | 41 +- ports/arm-cr/qk/gnu/qp_port.hpp | 39 +- ports/arm-cr/qk/gnu/qs_port.hpp | 2 +- ports/arm-cr/qk/iar/qp_port.hpp | 41 +- ports/arm-cr/qk/iar/qs_port.hpp | 2 +- ports/arm-cr/qk/ti/qp_port.hpp | 39 +- ports/arm-cr/qk/ti/qs_port.hpp | 2 +- ports/arm-cr/qv/config/qp_config.hpp | 43 +- ports/arm-cr/qv/gnu/qp_port.hpp | 39 +- ports/arm-cr/qv/gnu/qs_port.hpp | 2 +- ports/arm-cr/qv/iar/qp_port.hpp | 41 +- ports/arm-cr/qv/iar/qs_port.hpp | 2 +- ports/arm-cr/qv/ti/qp_port.hpp | 39 +- ports/arm-cr/qv/ti/qs_port.hpp | 2 +- ports/config/qp_config.hpp | 41 +- ports/embos/qf_port.cpp | 144 +- ports/embos/qp_port.hpp | 39 +- ports/embos/qs_port.hpp | 2 +- ports/freertos/qf_port.cpp | 744 +- ports/freertos/qp_port.hpp | 41 +- ports/freertos/qs_port.hpp | 2 +- ports/lint-plus/16bit/cpu.lnt | 6 - ports/lint-plus/16bit/cstdint | 39 - ports/lint-plus/16bit/qs_port.hpp | 57 - ports/lint-plus/32bit/cpu.lnt | 3 - ports/lint-plus/32bit/cstdint | 39 - ports/lint-plus/32bit/qs_port.hpp | 57 - ports/lint-plus/au-autosar.lnt | 2773 ------ ports/lint-plus/au-autosar19.lnt | 3074 ------- ports/lint-plus/au-ds.lnt | 21 - ports/lint-plus/au-ql-cpp11.lnt | 635 -- ports/lint-plus/cstddef | 42 - ports/lint-plus/make.bat | 69 - ports/lint-plus/options.lnt | 405 - ports/lint-plus/qk/qp_port.hpp | 101 - ports/lint-plus/qpcpp.lnt | 458 - ports/lint-plus/qv/qp_port.hpp | 89 - ports/lint-plus/qxk/qp_port.hpp | 104 - ports/lint-plus/std.lnt | 45 - ports/lint-plus2/16bit/cpu.lnt | 6 - ports/lint-plus2/16bit/cstdint | 39 - ports/lint-plus2/16bit/qs_port.hpp | 57 - ports/lint-plus2/32bit/cpu.lnt | 3 - ports/lint-plus2/32bit/cstdint | 39 - ports/lint-plus2/32bit/qs_port.hpp | 57 - ports/lint-plus2/au-ds.lnt | 21 - ports/lint-plus2/cstddef | 42 - ports/lint-plus2/make.bat | 70 - ports/lint-plus2/options.lnt | 406 - ports/lint-plus2/qk/qp_port.hpp | 101 - ports/lint-plus2/qpcpp.lnt | 459 - ports/lint-plus2/qv/qp_port.hpp | 89 - ports/lint-plus2/qxk/qp_port.hpp | 104 - ports/lint-plus2/std.lnt | 45 - ports/msp430/qk/qp_port.hpp | 37 +- ports/msp430/qk/qs_port.hpp | 2 +- ports/msp430/qutest/qp_port.hpp | 41 +- ports/msp430/qutest/qs_port.hpp | 2 +- ports/msp430/qv/qp_port.hpp | 37 +- ports/msp430/qv/qs_port.hpp | 2 +- ports/posix-qutest/CMakeLists.txt | 5 - ports/posix-qutest/README.md | 5 - ports/posix-qutest/qp_port.hpp | 109 - ports/posix-qutest/qs_port.hpp | 64 - ports/posix-qutest/qutest_port.cpp | 310 - ports/posix-qutest/safe_std.h | 115 - ports/posix-qv/qf_port.cpp | 10 +- ports/posix-qv/qp_port.hpp | 40 +- ports/posix-qv/qs_port.cpp | 2 +- ports/posix-qv/qs_port.hpp | 2 +- ports/posix/qf_port.cpp | 10 +- ports/posix/qp_port.hpp | 41 +- ports/posix/qs_port.cpp | 2 +- ports/posix/qs_port.hpp | 2 +- ports/qep-only/qp_port.hpp | 50 +- ports/threadx/qf_port.cpp | 212 +- ports/threadx/qp_port.hpp | 90 +- ports/threadx/qs_port.hpp | 2 +- ports/uc-os2/qf_port.cpp | 169 +- ports/uc-os2/qp_port.hpp | 39 +- ports/uc-os2/qs_port.hpp | 2 +- ports/win32-qutest/CMakeLists.txt | 5 - ports/win32-qutest/qp_port.hpp | 109 - ports/win32-qutest/qs_port.hpp | 64 - ports/win32-qutest/qutest_port.cpp | 299 - ports/win32-qutest/safe_std.h | 115 - ports/win32-qv/qf_port.cpp | 14 +- ports/win32-qv/qp_port.hpp | 40 +- ports/win32-qv/qs_port.cpp | 2 +- ports/win32-qv/qs_port.hpp | 2 +- ports/win32/qf_port.cpp | 10 +- ports/win32/qp_port.hpp | 38 +- ports/win32/qs_port.cpp | 2 +- ports/win32/qs_port.hpp | 2 +- qpcpp.qm | 9629 +++++---------------- qpcpp.sha1 | 240 +- qpcpp_sha1.bat | 1 - src/README.md | 45 + src/qf/qep_hsm.cpp | 218 +- src/qf/qep_msm.cpp | 341 +- src/qf/qf_act.cpp | 47 +- src/qf/qf_actq.cpp | 430 +- src/qf/qf_defer.cpp | 70 +- src/qf/qf_dyn.cpp | 103 +- src/qf/qf_mem.cpp | 186 +- src/qf/qf_ps.cpp | 74 +- src/qf/qf_qact.cpp | 32 +- src/qf/qf_qeq.cpp | 296 +- src/qf/qf_qmact.cpp | 32 +- src/qf/qf_time.cpp | 488 +- src/qk/qk.cpp | 79 +- src/qs/CMakeLists.txt | 22 +- src/qs/qs.cpp | 1072 --- src/qs/qs_64bit.cpp | 97 - src/qs/qs_fp.cpp | 134 - src/qs/qs_rx.cpp | 1245 --- src/qs/qstamp.cpp | 32 +- src/qs/qutest.cpp | 590 -- src/qv/qv.cpp | 74 +- src/qxk/CMakeLists.txt | 7 - src/qxk/qxk.cpp | 554 -- src/qxk/qxk_mutex.cpp | 489 -- src/qxk/qxk_sema.cpp | 287 - src/qxk/qxk_xthr.cpp | 374 - test/et/et.c | 174 - test/et/et.h | 92 - test/et/et_host.c | 48 - test/qk/README.txt | 13 - test/qk/test_sched/bsp.hpp | 66 - test/qk/test_sched/bsp_efm32pg1b.cpp | 375 - test/qk/test_sched/bsp_nucleo-c031c6.cpp | 362 - test/qk/test_sched/bsp_nucleo-h743zi.cpp | 307 - test/qk/test_sched/bsp_nucleo-l053r8.cpp | 381 - test/qk/test_sched/bsp_nucleo-u545re.cpp | 315 - test/qk/test_sched/efm32pg1b.mak | 333 - test/qk/test_sched/nucleo-c031c6.mak | 336 - test/qk/test_sched/nucleo-h743zi.mak | 347 - test/qk/test_sched/nucleo-l053r8.mak | 333 - test/qk/test_sched/nucleo-u545re.mak | 334 - test/qk/test_sched/test_mpu.py | 100 - test/qk/test_sched/test_sched.cpp | 258 - test/qk/test_sched/test_sched.py | 188 - test/qk/test_sched/uvision_efm32.uvoptx | 730 -- test/qk/test_sched/uvision_efm32.uvprojx | 587 -- test/qs/qs_rx/Makefile | 222 - test/qs/qs_rx/qp_port.hpp | 103 - test/qs/qs_rx/qs_port.hpp | 61 - test/qs/qs_rx/test.cpp | 144 - test/qs/qs_rx/test.sln | 21 - test/qs/qs_rx/test.vcxproj | 75 - test/qs/qs_rx/test.vcxproj.filters | 22 - test/qxk/README.txt | 13 - test/qxk/test_sched/bsp.hpp | 66 - test/qxk/test_sched/bsp_efm32pg1b.cpp | 375 - test/qxk/test_sched/bsp_nucleo-c031c6.cpp | 362 - test/qxk/test_sched/bsp_nucleo-h743zi.cpp | 307 - test/qxk/test_sched/bsp_nucleo-l053r8.cpp | 382 - test/qxk/test_sched/efm32pg1b.mak | 336 - test/qxk/test_sched/nucleo-c031c6.mak | 339 - test/qxk/test_sched/nucleo-h743zi.mak | 350 - test/qxk/test_sched/nucleo-l053r8.mak | 336 - test/qxk/test_sched/test_mpu.py | 99 - test/qxk/test_sched/test_sched.cpp | 317 - test/qxk/test_sched/test_sched.py | 148 - test/qxk/test_sched/uvision_efm32.uvoptx | 777 -- test/qxk/test_sched/uvision_efm32.uvprojx | 607 -- zephyr/qf_port.cpp | 148 +- zephyr/qp_port.hpp | 36 +- zephyr/qutest_port.cpp | 2 +- 224 files changed, 5994 insertions(+), 43120 deletions(-) create mode 100644 include/README.md delete mode 100644 include/qs.hpp delete mode 100644 include/qs_pkg.hpp delete mode 100644 include/qxk.hpp create mode 100644 ports/README.md delete mode 100644 ports/arm-cm/qutest/qp_port.hpp delete mode 100644 ports/arm-cm/qutest/qs_port.hpp delete mode 100644 ports/arm-cm/qxk/armclang/qp_port.hpp delete mode 100644 ports/arm-cm/qxk/armclang/qs_port.hpp delete mode 100644 ports/arm-cm/qxk/armclang/qxk_port.cpp delete mode 100644 ports/arm-cm/qxk/config/qp_config.hpp delete mode 100644 ports/arm-cm/qxk/gnu/qp_port.hpp delete mode 100644 ports/arm-cm/qxk/gnu/qs_port.hpp delete mode 100644 ports/arm-cm/qxk/gnu/qxk_port.cpp delete mode 100644 ports/arm-cm/qxk/iar/qp_port.hpp delete mode 100644 ports/arm-cm/qxk/iar/qs_port.hpp delete mode 100644 ports/arm-cm/qxk/iar/qxk_port.cpp delete mode 100644 ports/arm-cm/qxk/llvm/README.txt delete mode 100644 ports/lint-plus/16bit/cpu.lnt delete mode 100644 ports/lint-plus/16bit/cstdint delete mode 100644 ports/lint-plus/16bit/qs_port.hpp delete mode 100644 ports/lint-plus/32bit/cpu.lnt delete mode 100644 ports/lint-plus/32bit/cstdint delete mode 100644 ports/lint-plus/32bit/qs_port.hpp delete mode 100644 ports/lint-plus/au-autosar.lnt delete mode 100644 ports/lint-plus/au-autosar19.lnt delete mode 100644 ports/lint-plus/au-ds.lnt delete mode 100644 ports/lint-plus/au-ql-cpp11.lnt delete mode 100644 ports/lint-plus/cstddef delete mode 100644 ports/lint-plus/make.bat delete mode 100644 ports/lint-plus/options.lnt delete mode 100644 ports/lint-plus/qk/qp_port.hpp delete mode 100644 ports/lint-plus/qpcpp.lnt delete mode 100644 ports/lint-plus/qv/qp_port.hpp delete mode 100644 ports/lint-plus/qxk/qp_port.hpp delete mode 100644 ports/lint-plus/std.lnt delete mode 100644 ports/lint-plus2/16bit/cpu.lnt delete mode 100644 ports/lint-plus2/16bit/cstdint delete mode 100644 ports/lint-plus2/16bit/qs_port.hpp delete mode 100644 ports/lint-plus2/32bit/cpu.lnt delete mode 100644 ports/lint-plus2/32bit/cstdint delete mode 100644 ports/lint-plus2/32bit/qs_port.hpp delete mode 100644 ports/lint-plus2/au-ds.lnt delete mode 100644 ports/lint-plus2/cstddef delete mode 100644 ports/lint-plus2/make.bat delete mode 100644 ports/lint-plus2/options.lnt delete mode 100644 ports/lint-plus2/qk/qp_port.hpp delete mode 100644 ports/lint-plus2/qpcpp.lnt delete mode 100644 ports/lint-plus2/qv/qp_port.hpp delete mode 100644 ports/lint-plus2/qxk/qp_port.hpp delete mode 100644 ports/lint-plus2/std.lnt delete mode 100644 ports/posix-qutest/CMakeLists.txt delete mode 100644 ports/posix-qutest/README.md delete mode 100644 ports/posix-qutest/qp_port.hpp delete mode 100644 ports/posix-qutest/qs_port.hpp delete mode 100644 ports/posix-qutest/qutest_port.cpp delete mode 100644 ports/posix-qutest/safe_std.h delete mode 100644 ports/win32-qutest/CMakeLists.txt delete mode 100644 ports/win32-qutest/qp_port.hpp delete mode 100644 ports/win32-qutest/qs_port.hpp delete mode 100644 ports/win32-qutest/qutest_port.cpp delete mode 100644 ports/win32-qutest/safe_std.h create mode 100644 src/README.md delete mode 100644 src/qs/qs.cpp delete mode 100644 src/qs/qs_64bit.cpp delete mode 100644 src/qs/qs_fp.cpp delete mode 100644 src/qs/qs_rx.cpp delete mode 100644 src/qs/qutest.cpp delete mode 100644 src/qxk/CMakeLists.txt delete mode 100644 src/qxk/qxk.cpp delete mode 100644 src/qxk/qxk_mutex.cpp delete mode 100644 src/qxk/qxk_sema.cpp delete mode 100644 src/qxk/qxk_xthr.cpp delete mode 100644 test/et/et.c delete mode 100644 test/et/et.h delete mode 100644 test/et/et_host.c delete mode 100644 test/qk/README.txt delete mode 100644 test/qk/test_sched/bsp.hpp delete mode 100644 test/qk/test_sched/bsp_efm32pg1b.cpp delete mode 100644 test/qk/test_sched/bsp_nucleo-c031c6.cpp delete mode 100644 test/qk/test_sched/bsp_nucleo-h743zi.cpp delete mode 100644 test/qk/test_sched/bsp_nucleo-l053r8.cpp delete mode 100644 test/qk/test_sched/bsp_nucleo-u545re.cpp delete mode 100644 test/qk/test_sched/efm32pg1b.mak delete mode 100644 test/qk/test_sched/nucleo-c031c6.mak delete mode 100644 test/qk/test_sched/nucleo-h743zi.mak delete mode 100644 test/qk/test_sched/nucleo-l053r8.mak delete mode 100644 test/qk/test_sched/nucleo-u545re.mak delete mode 100644 test/qk/test_sched/test_mpu.py delete mode 100644 test/qk/test_sched/test_sched.cpp delete mode 100644 test/qk/test_sched/test_sched.py delete mode 100644 test/qk/test_sched/uvision_efm32.uvoptx delete mode 100644 test/qk/test_sched/uvision_efm32.uvprojx delete mode 100644 test/qs/qs_rx/Makefile delete mode 100644 test/qs/qs_rx/qp_port.hpp delete mode 100644 test/qs/qs_rx/qs_port.hpp delete mode 100644 test/qs/qs_rx/test.cpp delete mode 100644 test/qs/qs_rx/test.sln delete mode 100644 test/qs/qs_rx/test.vcxproj delete mode 100644 test/qs/qs_rx/test.vcxproj.filters delete mode 100644 test/qxk/README.txt delete mode 100644 test/qxk/test_sched/bsp.hpp delete mode 100644 test/qxk/test_sched/bsp_efm32pg1b.cpp delete mode 100644 test/qxk/test_sched/bsp_nucleo-c031c6.cpp delete mode 100644 test/qxk/test_sched/bsp_nucleo-h743zi.cpp delete mode 100644 test/qxk/test_sched/bsp_nucleo-l053r8.cpp delete mode 100644 test/qxk/test_sched/efm32pg1b.mak delete mode 100644 test/qxk/test_sched/nucleo-c031c6.mak delete mode 100644 test/qxk/test_sched/nucleo-h743zi.mak delete mode 100644 test/qxk/test_sched/nucleo-l053r8.mak delete mode 100644 test/qxk/test_sched/test_mpu.py delete mode 100644 test/qxk/test_sched/test_sched.cpp delete mode 100644 test/qxk/test_sched/test_sched.py delete mode 100644 test/qxk/test_sched/uvision_efm32.uvoptx delete mode 100644 test/qxk/test_sched/uvision_efm32.uvprojx diff --git a/.gitignore b/.gitignore index 37875d82f..70d7322d7 100644 --- a/.gitignore +++ b/.gitignore @@ -37,17 +37,29 @@ version-* JLink*.* -cert/ +include/qs.hpp +include/qs_pkg.hpp +include/qxk.hpp +src/qs/qs.cpp +src/qs/qs_64bit.cpp +src/qs/qs_fp.cpp +src/qs/qs_rx.cpp +src/qs/qutest.cpp +src/qxk/qxk.cpp +src/qxk/qxk_mutex.cpp +src/qxk/qxk_sema.cpp +src/qxk/qxk_xthr.cpp + +ports/posix-qutest/ +ports/win32-qutest/ + +priv/ html/ latex/ -doxygen/gen/ -test_priv/ dbg/ rel/ spy/ -build/ -build_rel/ -build_spy/ +build*/ settings/ .settings/ targetConfigs/ diff --git a/3rd_party b/3rd_party index aca09a2e3..43a99789e 160000 --- a/3rd_party +++ b/3rd_party @@ -1 +1 @@ -Subproject commit aca09a2e3571adf97e5ce6cb5b1d645ba2418c1d +Subproject commit 43a99789efed81bd200558e742623745822c779a diff --git a/LICENSES/License.txt b/LICENSES/License.txt index e20f603a6..5c32ce95c 100644 --- a/LICENSES/License.txt +++ b/LICENSES/License.txt @@ -3,8 +3,8 @@ Quantum Leaps Dual-Licensing: The QP/C Real-Time Embedded Framework is dually-licensed under the following two alternatives: -1. Open source GNU General Public License (GPL) -version 3, or alternatively, +1. Open source GNU General Public License (GPL) version 3, + or alternatively, 2. One of the closed source Quantum Leaps commercial licenses. diff --git a/LICENSES/LicenseRef-QL-dual.qlc b/LICENSES/LicenseRef-QL-dual.qlc index 0a88f5088..721f329af 100644 --- a/LICENSES/LicenseRef-QL-dual.qlc +++ b/LICENSES/LicenseRef-QL-dual.qlc @@ -1,8 +1,7 @@ -Any user of the QP/C++ real-time embedded framework +public qpcpp 2025-12-31 - -Copyright (C) 2005 Quantum Leaps, LLC . +Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. Q u a n t u m L e a P s ------------------------ @@ -10,21 +9,20 @@ Copyright (C) 2005 Quantum Leaps, LLC . 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: +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. -Contact information: +NOTE: +The GPL does NOT permit the incorporation of this code into proprietary +programs. Please contact Quantum Leaps for commercial licensing options, +which expressly supersede the GPL and are designed explicitly for +closed-source distribution. + +Quantum Leaps contact information: -#CEF384A62BD9270573AA82386A5BE6F6E36AD848 \ No newline at end of file +#48B37CF39D4FD9DE279250B31FD388AFD0BE9B40 \ No newline at end of file diff --git a/README.md b/README.md index 9d9c1fbd2..9858e1948 100644 --- a/README.md +++ b/README.md @@ -34,15 +34,15 @@ provides instructions on how to download, install, and get started with QP. - [AppNote: "Getting Started with QP Real-Time Embedded Frameworks"][AN] contains also a tutorial, in which you build a simple "Blinky" application. -## Licensing -The QP frameworks (QP/C and QP/C++) are licensed under the +# Licensing +The QP/C++ real-time embedded framework is licensed under the [dual licensing model](https://www.state-machine.com/licensing), with the following licensing options: 1. [Open-source licensing](https://www.state-machine.com/licensing#Open) under the [GNU General Public License (GPLv3)](https://www.gnu.org/licenses/gpl-3.0.en.html). -> NOTE: GPL requires that all modifications to the original code +> NOTE: The GPL requires that all modifications to the original code as well as your application code (Derivative Works as defined in the Copyright Law) must also be released under the terms of the GPL open source license. @@ -56,13 +56,26 @@ proprietary status of their code. all QP frameworks can be licensed commercially, in which case you don't use any open source license and you do not violate your policy. +## Files Removed from the QP/C++ Open Source GPL Distribution +Due to the widespread non-compliance with the GPL, as well as infringement on the +[dual-licensing model of QP frameworks][Lic], the following QP/C++ components +have been **removed from the open-source GPL distribution**: +- QS target-resident software tracing component +- QXK dual-mode kernel + +> NOTE: These components are available to the [commercial licensees][Cust] with +the active Support Term. Please contact [Quantum Leaps technical support][Sup] +to get the complete QP/C++ framework distribution. + +> NOTE: To request **evaluation** of the complete QP/C++ framework, please contact +Quantum Leaps at: https://www.state-machine.com/contact # About QP/C++ QP/C++ (Quantum Platform in C++) is a lightweight, open source [Real-Time Embedded Framework (RTEF)][RTEF] for building modern embedded software as systems of asynchronous, event-driven [Active Objects][Active] (actors). The [QP/C++] framework is a member of a [QP] family consisting of -[QP/C] and [QP/C++] frameworks, which are strictly quality controlled, +[QP/C++] and [QP/C] frameworks, which are strictly quality controlled, thoroughly documented, and [commercially licensable][Lic]. ## Safer Model of Concurrency @@ -103,7 +116,7 @@ without any traditional RTOS. The framework contains a selection of the [preemptive non-blocking QK kernel][QK], and the preemptive, [dual-mode QXK kernel][QXK] that provides all the features you might expect from a traditional RTOS. Native QP ports and ready-to-use examples are provided -for major CPUs, such as ARM Cortex-M (M0/M0+/M3/M4/M7/M23/M33/M85). +for major CPUs, such as ARM Cortex-M (M0/M0+/M3/M4/M7/M23/M33/...). ## Traditional RTOS/OS QP/C++ can also work with a traditional RTOS, such as ThreadX, embOS, FreeRTOS, @@ -138,12 +151,18 @@ in your web browser. # How to Help this Project? If you like this project, please give it a star (in the upper-right corner of your browser window): -![GitHub star](https://www.state-machine.com/img/github-star.jpg) +

+
+

[RTEF]: [QP]: [QP/C]: [QP/C++]: + [QS/C++]: + [QV]: + [QK]: + [QXK]: [QM]: [QTools]: [QP-Rel]: @@ -153,6 +172,7 @@ If you like this project, please give it a star (in the upper-right corner of yo [HSM]: [Lic]: [Cust]: + [Sup]: [AN]: [Tutorial]: [Video]: diff --git a/cmakeSupport.md b/cmakeSupport.md index 2137b5de1..27745df56 100644 --- a/cmakeSupport.md +++ b/cmakeSupport.md @@ -38,6 +38,10 @@ set(QPCPP_PROJECT qpcPrj) set(QPCPP_CFG_KERNEL QV) set(QPCPP_CFG_GUI TRUE) set(QPCPP_CFG_PORT win32) +# QP/CPP 8.0.0: to include a local 'qp_config.hpp' add the related include path +# to the qpcpp build settings. Replace "${CMAKE_CURRENT_LIST_DIR}/include" by +# your project specific path! +set(QPCPP_CFG_QPCONFIG_H_INCLUDE_PATH ${CMAKE_CURRENT_LIST_DIR}/include) qpcpp_sdk_init() target_link_libraries(qpcppApp PRIVATE qpcpp) @@ -78,6 +82,9 @@ This file is situated in the root directory of qpcpp. It performs a pre-initiali * `QPCPP-CFG-GUI` - BOOL: set this Boolean variable to ON/TRUE, if GUI support (win32) shall be compiled in. Default: OFF * `QPCPP_CFG_UNIT_TEST` - BOOL: set this to ON/TRUE to support qutest, if build configuration `Spy` is active. Default: OFF * `QPCPP_CFG_VERBOSE` - BOOL: set this to enable more verbosity in message output. Default: OFF +* `QPCPP_CFG_QPCONFIG_H_INCLUDE_PATH`: - STRING (PATH): (`QP/CPP 8.0.0`) set this to have the build of QP/CPP use your project specific `qp_config.hpp`. + Default: `${QPCPP_SDK_PATH}/ports/config` + ### General usage hints 1. Set `QPCPP_SDK_PATH` or `QPCPP_FETCH_FROM_GIT` either in your `CMakeLists.txt` file or as an environment variable. @@ -87,7 +94,7 @@ This file is situated in the root directory of qpcpp. It performs a pre-initiali 5. Define the cmake target (executable or library) 6. Include `qpcpp_sdk_init.cmake` 7. configure the qpc SDK -8. call `qpcpp_sdk_init` +8. call `qpcpp_sdk_init()` 9. Add the qpcpp library to your cmake target: `target_link_libraries(> PRIVATE qpcpp)` @@ -102,7 +109,7 @@ Generate and build your cmake project Refer to the [CMakePresets.json manual](https://cmake.org/cmake/help/latest/manual/cmake-presets.7.html) for further details. Then you generate with `cmake --preset= .` from your project directory. The build then can be started with `cmake --build --preset=`. -### QPC configurations support +### QPCPP configurations support Many `qpcpp` examples provide 3 build configurations: * `Debug` - build with debug support and debug symbols. Most optimizations are turned off * `Release` - build without debug support. Activate optimizations instead @@ -110,45 +117,15 @@ Many `qpcpp` examples provide 3 build configurations: These configurations are also supported by qpcpp with cmake. Different possibilities exist to activate those. -### `qp_config.h` support -Some build configurations require the inclusion of `qp_config.h`. To achieve this, the QPC macro `QP_CONFIG` should be set, when compiling the -`qpcpp` source files. The include search paths also needs to be set accordingly in order for the preprocessor to be able to find the correct include -file. +### `qp_config.hpp` support +With the release of QP/C++ V8.0.0 the inclusion of `qp_config.hpp` is mandatory. +The `cmake` build system of qpc addresses this by providing the configuration variable `QPCPP_CFG_QPCONFIG_H_INCLUDE_PATH`. Set this to the path of your local project's `qp_config.hpp` and this will automatically be found by the build system. Do this in your main `CMakeLists.txt` file __before__ calling `qpcpp_sdk_init()`. -As `qp_config.hpp` is a project related file, which - in most cases - resides outside the `qpcpp` source code tree, the decision is to handle the -above mentioned topic within the root project's `CMakeLists.txt` file instead of integrating this topic into a rather complicated configuration -of `qpcpp` itself. +You do not need to set this variable, should the qpcpp default settings be sufficient for your project. In this case the build system uses the `qp_config.hpp` file, as it can be found in the directory `${QPCPP_SDK_PATH}/src/ports/config`. An example can be found in the [cmake dpp example](https://github.com/QuantumLeaps/qpcpp-examples/tree/main/posix-win32-cmake/dpp). Have a look into the example's [CMakeLists.txt](https://github.com/QuantumLeaps/qpcpp-examples/blob/main/posix-win32-cmake/dpp/CMakeLists.txt). -You will find the reference to the `qpc` library, followed by the project's specific setup for `qp_config.h` like this: -``` -# set up qpcpp library -target_link_libraries(dpp - PRIVATE - qpcpp -) -# should a 'qp_config.h' configuration file be used and is it available -# edit the HINTS in the 'find_file()' call according to your project settings -if(USE_QP_CONFIG) - find_file(QP_CONFIG qp_config.h HINTS ${CMAKE_CURRENT_SOURCE_DIR}) # try to identify 'qp_config.h' - if(QP_CONFIG) # found 'qp_config.h' - cmake_path(GET QP_CONFIG PARENT_PATH QP_CONFIG_DIR) # extract the path from the FQFN - target_compile_definitions(qpcpp # add -DQP_CONFIG to the qpcpp build - PUBLIC - QP_CONFIG - ) - target_include_directories(qpcpp # add the path to 'qp_config.h' to the list of include paths for qpcpp - PUBLIC - ${QP_CONFIG_DIR} - ) - else() # 'qp_config.h' requested but not find - try to configure and build anyways - message(WARNING "File 'qp_config.h' not found!") - endif() -endif() -``` - ### Multi configuration generators The most easy way to make use of the different configurations is to use a multi config generator like `Ninja Multi-Config` or `MS Visual Studio`. Using one of such generators enables to generate the build system using `cmake` and afterwards simply selecting the desired build configuration like diff --git a/examples b/examples index 3ba405ac6..c3b9ebe04 160000 --- a/examples +++ b/examples @@ -1 +1 @@ -Subproject commit 3ba405ac6fdc2d31b451ebf3b9dd329ca025311c +Subproject commit c3b9ebe040f79020b8e8c69724075b81f972adfd diff --git a/include/README.md b/include/README.md new file mode 100644 index 000000000..4993634c8 --- /dev/null +++ b/include/README.md @@ -0,0 +1,45 @@ +# Files Missing from the QP/C++ GPL Distribution +Due to the widespread non-compliance with the GPL, as well as infringement +on the [dual-licensing model of QP frameworks][Lic], the following files +have been **removed from the open-source GPL distribution**: + +``` +qpcpp +| ++---include +| qs.hpp +| qs_pkg.hpp +| qxk.hpp +| +\---src + | + +---qs + | qs.cpp + | qs_64bit.cpp + | qs_fp.cpp + | qs_rx.cpp + | qutest.cpp + | + \---qxk + qxk.cpp + qxk_mutex.cpp + qxk_sema.cpp + qxk_xthr.cpp +``` + +> NOTE: These files are available to the [commercial licensees][Cust] with +the active Support Term. Please contact [Quantum Leaps technical support][Sup] +to get the complete QP/C++ framework distribution. + +# QP/C++ Framework Evaluation +To request **evaluation** of the complete QP/C++ framework, please contact +Quantum Leaps at: +- https://www.state-machine.com/contact + +# Quantum Leaps Licensing: +To learn more about the open source and commercial licensing options: +- https://www.state-machine.com/licensing + + [Lic]: + [Cust]: + [Sup]: diff --git a/include/qequeue.hpp b/include/qequeue.hpp index 6fb240b10..143dc415b 100644 --- a/include/qequeue.hpp +++ b/include/qequeue.hpp @@ -3,17 +3,10 @@ // Model: qpcpp.qm // File: ${include::qequeue.hpp} // -// This code has been generated by QM 6.2.0 . +// This code has been generated by QM 7.0.0 . // DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. // -// This code is covered by the following QP license: -// License # : LicenseRef-QL-dual -// Issued to : Any user of the QP/C++ real-time embedded framework -// Framework(s) : qpcpp -// Support ends : 2025-12-31 -// License scope: -// -// Copyright (C) 2005 Quantum Leaps, LLC . +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // Q u a n t u m L e a P s // ------------------------ @@ -21,21 +14,20 @@ // // 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: +// 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. // -// Contact information: +// NOTE: +// The GPL does NOT permit the incorporation of this code into proprietary +// programs. Please contact Quantum Leaps for commercial licensing options, +// which expressly supersede the GPL and are designed explicitly for +// closed-source distribution. +// +// Quantum Leaps contact information: // // // @@ -53,10 +45,8 @@ namespace QP { using QEQueueCtr = std::uint8_t; #elif (QF_EQUEUE_CTR_SIZE == 2U) using QEQueueCtr = std::uint16_t; -#elif (QF_EQUEUE_CTR_SIZE == 4U) - using QEQueueCtr = std::uint32_t; #else - #error "QF_EQUEUE_CTR_SIZE defined incorrectly, expected 1U, 2U, or 4U" + #error "QF_EQUEUE_CTR_SIZE defined incorrectly, expected 1U or 2U" #endif class QEvt; // forward declaration @@ -70,11 +60,27 @@ namespace QP { class QEQueue { private: QEvt const * volatile m_frontEvt; - QEvt const ** m_ring; + QEvt const * * m_ring; QEQueueCtr m_end; QEQueueCtr volatile m_head; QEQueueCtr volatile m_tail; QEQueueCtr volatile m_nFree; + +#ifndef Q_UNSAFE + std::uintptr_t m_frontEvt_dis; +#endif // ndef Q_UNSAFE + +#ifndef Q_UNSAFE + QEQueueCtr m_head_dis; +#endif // ndef Q_UNSAFE + +#ifndef Q_UNSAFE + QEQueueCtr m_tail_dis; +#endif // ndef Q_UNSAFE + +#ifndef Q_UNSAFE + QEQueueCtr m_nFree_dis; +#endif // ndef Q_UNSAFE QEQueueCtr m_nMin; // friends... @@ -91,6 +97,12 @@ class QEQueue { m_head(0U), m_tail(0U), m_nFree(0U), + #ifndef Q_UNSAFE + m_frontEvt_dis(static_cast(~0U)), + m_head_dis(static_cast(~0U)), + m_tail_dis(static_cast(~0U)), + m_nFree_dis(static_cast(~0U)), + #endif m_nMin(0U) {} void init( @@ -108,7 +120,11 @@ class QEQueue { return m_nFree; } QEQueueCtr getNMin() const noexcept { + #ifndef Q_UNSAFE return m_nMin; + #else + return 0U; + #endif } bool isEmpty() const noexcept { return m_frontEvt == nullptr; diff --git a/include/qk.hpp b/include/qk.hpp index 741185ac2..10068a196 100644 --- a/include/qk.hpp +++ b/include/qk.hpp @@ -3,17 +3,10 @@ // Model: qpcpp.qm // File: ${include::qk.hpp} // -// This code has been generated by QM 6.2.0 . +// This code has been generated by QM 7.0.0 . // DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. // -// This code is covered by the following QP license: -// License # : LicenseRef-QL-dual -// Issued to : Any user of the QP/C++ real-time embedded framework -// Framework(s) : qpcpp -// Support ends : 2025-12-31 -// License scope: -// -// Copyright (C) 2005 Quantum Leaps, LLC . +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // Q u a n t u m L e a P s // ------------------------ @@ -21,21 +14,20 @@ // // 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: +// 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. // -// Contact information: +// NOTE: +// The GPL does NOT permit the incorporation of this code into proprietary +// programs. Please contact Quantum Leaps for commercial licensing options, +// which expressly supersede the GPL and are designed explicitly for +// closed-source distribution. +// +// Quantum Leaps contact information: // // // @@ -140,8 +132,7 @@ void QK_activate_() noexcept; } while (false) //${QK-impl::QACTIVE_EQUEUE_WAIT_} ........................................... -#define QACTIVE_EQUEUE_WAIT_(me_) \ - Q_ASSERT_INCRIT(320, (me_)->m_eQueue.m_frontEvt != nullptr) +#define QACTIVE_EQUEUE_WAIT_(me_) (static_cast(0)) //${QK-impl::QACTIVE_EQUEUE_SIGNAL_} ......................................... #ifndef Q_UNSAFE diff --git a/include/qmpool.hpp b/include/qmpool.hpp index 6c6306e73..d7a3749d3 100644 --- a/include/qmpool.hpp +++ b/include/qmpool.hpp @@ -3,17 +3,10 @@ // Model: qpcpp.qm // File: ${include::qmpool.hpp} // -// This code has been generated by QM 6.2.0 . +// This code has been generated by QM 7.0.0 . // DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. // -// This code is covered by the following QP license: -// License # : LicenseRef-QL-dual -// Issued to : Any user of the QP/C++ real-time embedded framework -// Framework(s) : qpcpp -// Support ends : 2025-12-31 -// License scope: -// -// Copyright (C) 2005 Quantum Leaps, LLC . +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // Q u a n t u m L e a P s // ------------------------ @@ -21,21 +14,20 @@ // // 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: +// 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. // -// Contact information: +// NOTE: +// The GPL does NOT permit the incorporation of this code into proprietary +// programs. Please contact Quantum Leaps for commercial licensing options, +// which expressly supersede the GPL and are designed explicitly for +// closed-source distribution. +// +// Quantum Leaps contact information: // // // @@ -75,8 +67,9 @@ namespace QP { } // namespace QP #define QF_MPOOL_EL(evType_) struct { \ - QP::QFreeBlock sto_[((sizeof(evType_) - 1U) \ - / sizeof(QP::QFreeBlock)) + 1U]; } + QP::QFreeBlock sto_[((sizeof(evType_) - 1U) / (2U * sizeof(void *))) + 1U]; \ +} + //$declare${QF::QFreeBlock} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv namespace QP { @@ -106,7 +99,18 @@ class QMPool { QMPoolSize m_blockSize; QMPoolCtr m_nTot; QMPoolCtr volatile m_nFree; + +#ifndef Q_UNSAFE QMPoolCtr m_nMin; +#endif // ndef Q_UNSAFE + +#ifndef Q_UNSAFE + std::uintptr_t m_free_head_dis; +#endif // ndef Q_UNSAFE + +#ifndef Q_UNSAFE + QMPoolCtr m_nFree_dis; +#endif // ndef Q_UNSAFE public: QMPool() @@ -115,8 +119,12 @@ class QMPool { m_free_head(nullptr), m_blockSize(0U), m_nTot(0U), - m_nFree(0U), - m_nMin(0U) + m_nFree(0U) + #ifndef Q_UNSAFE + ,m_nMin(0U), + m_free_head_dis(static_cast(~0U)), + m_nFree_dis(static_cast(~0U)) + #endif {} void init( void * const poolSto, @@ -130,7 +138,11 @@ class QMPool { std::uint_fast8_t const qsId) noexcept; QMPoolSize getBlockSize() const noexcept; QMPoolCtr getNMin() const noexcept { + #ifndef Q_UNSAFE return m_nMin; + #else + return 0U; + #endif } QMPoolCtr getNFree() const noexcept { return m_nFree; diff --git a/include/qp.hpp b/include/qp.hpp index b57e95403..e141c4ba9 100644 --- a/include/qp.hpp +++ b/include/qp.hpp @@ -3,17 +3,10 @@ // Model: qpcpp.qm // File: ${include::qp.hpp} // -// This code has been generated by QM 6.2.0 . +// This code has been generated by QM 7.0.0 . // DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. // -// This code is covered by the following QP license: -// License # : LicenseRef-QL-dual -// Issued to : Any user of the QP/C++ real-time embedded framework -// Framework(s) : qpcpp -// Support ends : 2025-12-31 -// License scope: -// -// Copyright (C) 2005 Quantum Leaps, LLC . +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // Q u a n t u m L e a P s // ------------------------ @@ -21,21 +14,20 @@ // // 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: +// 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. // -// Contact information: +// NOTE: +// The GPL does NOT permit the incorporation of this code into proprietary +// programs. Please contact Quantum Leaps for commercial licensing options, +// which expressly supersede the GPL and are designed explicitly for +// closed-source distribution. +// +// Quantum Leaps contact information: // // // @@ -44,16 +36,16 @@ #define QP_HPP_ //============================================================================ -#define QP_VERSION_STR "7.4.0-rc.3" -#define QP_VERSION 740U -#define QP_RELEASE 0x7092C3BBU +#define QP_VERSION_STR "8.0.0" +#define QP_VERSION 800U +#define QP_RELEASE 0x7055936FU //============================================================================ //! @cond INTERNAL #ifndef Q_SIGNAL_SIZE #define Q_SIGNAL_SIZE 2U -#endif // ndef Q_SIGNAL_SIZE +#endif #ifndef QF_MAX_ACTIVE #define QF_MAX_ACTIVE 32U @@ -97,6 +89,7 @@ //! @endcond //============================================================================ + //$declare${glob-types} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv //${glob-types::int_t} ....................................................... @@ -116,6 +109,7 @@ using float64_t = double; namespace QP { //${QEP::versionStr[]} ....................................................... +//! the current QP version number string in ROM, based on #QP_VERSION_STR constexpr char const versionStr[] {QP_VERSION_STR}; //${QEP::QSignal} ............................................................ @@ -137,18 +131,17 @@ using QSignal = std::uint32_t; class QEvt { public: QSignal sig; - std::uint8_t volatile refCtr_; std::uint8_t evtTag_; + std::uint8_t volatile refCtr_; public: - static constexpr std::uint8_t MARKER {0xE0U}; enum DynEvt: std::uint8_t { DYNAMIC }; public: explicit constexpr QEvt(QSignal const s) noexcept : sig(s), - refCtr_(0U), - evtTag_(MARKER) + evtTag_(0x01U), + refCtr_(0x0EU) {} QEvt() = delete; void init() noexcept { @@ -158,12 +151,13 @@ class QEvt { static_cast(dummy); // no event parameters to initialize } - static bool verify_(QEvt const * const e) noexcept { - return (e != nullptr) - && ((e->evtTag_ & 0xF0U) == MARKER); + bool verify_() const noexcept { + std::uint8_t rc = refCtr_; + return (rc <= 2U*QF_MAX_ACTIVE) + && (((evtTag_ ^ rc) & 0x0FU) == 0x0FU); } std::uint_fast8_t getPoolNum_() const noexcept { - return static_cast(evtTag_) & 0x0FU; + return static_cast(evtTag_ >> 4U); } }; // class QEvt @@ -185,7 +179,7 @@ using QXThreadHandler = void (*)(QXThread * const me); //${QEP::QMState} ............................................................ struct QMState { - QMState const * superstate; + QMState const *superstate; QStateHandler const stateHandler; QActionHandler const entryAction; QActionHandler const exitAction; @@ -194,7 +188,7 @@ struct QMState { //${QEP::QMTranActTable} ..................................................... struct QMTranActTable { - QMState const * target; + QMState const *target; QActionHandler const act[1]; }; @@ -228,7 +222,6 @@ class QAsm { enum QStateRet : QState { // unhandled and need to "bubble up" Q_RET_SUPER, //!< event passed to superstate to handle - Q_RET_SUPER_SUB, //!< event passed to submachine superstate Q_RET_UNHANDLED, //!< event unhandled due to a guard // handled and do not need to "bubble up" @@ -244,12 +237,10 @@ class QAsm { // transitions need to execute transition-action table in QP::QMsm Q_RET_TRAN, //!< regular transition - Q_RET_TRAN_INIT, //!< initial transition in a state or submachine - Q_RET_TRAN_EP, //!< entry-point transition into a submachine + Q_RET_TRAN_INIT, //!< initial transition in a state // transitions that additionally clobber QHsm.m_state Q_RET_TRAN_HIST, //!< transition to history of a given state - Q_RET_TRAN_XP //!< exit-point transition out of a submachine }; //! Reserved signals by the QP-framework. @@ -336,18 +327,6 @@ class QAsm { m_temp.tatbl = static_cast(tatbl); return Q_RET_TRAN_HIST; } - QState qm_tran_ep(void const * const tatbl) noexcept { - m_temp.tatbl = static_cast(tatbl); - return Q_RET_TRAN_EP; - } - QState qm_tran_xp( - QActionHandler const xp, - void const * const tatbl) noexcept - { - m_state.act = xp; - m_temp.tatbl = static_cast(tatbl); - return Q_RET_TRAN_XP; - } #ifdef Q_SPY QState qm_entry(QMState const * const s) noexcept { @@ -376,14 +355,6 @@ class QAsm { return Q_RET_EXIT; } #endif // ndef Q_SPY - QState qm_sm_exit(QMState const * const s) noexcept { - m_temp.obj = s; - return Q_RET_EXIT; - } - QState qm_super_sub(QMState const * const s) noexcept { - m_temp.obj = s; - return Q_RET_SUPER_SUB; - } }; // class QAsm //${QEP::QHsm} ............................................................... @@ -491,12 +462,6 @@ class QMsm : public QP::QAsm { static QP::QState state_(void * const me, QP::QEvt const * const e); \ static QP::QMState const state_ ## _s -//${QEP-macros::QM_SM_STATE_DECL} ............................................ -#define QM_SM_STATE_DECL(subm_, state_) \ - QP::QState state_ ## _h(QP::QEvt const * const e);\ - static QP::QState state_(void * const me, QP::QEvt const * const e); \ - static SM_ ## subm_ const state_ ## _s - //${QEP-macros::QM_ACTION_DECL} .............................................. #define QM_ACTION_DECL(action_) \ QP::QState action_ ## _h(); \ @@ -565,6 +530,9 @@ namespace QP { //${QF::types::QPrioSpec} .................................................... using QPrioSpec = std::uint16_t; +//${QF::types::QEvtPtr} ...................................................... +using QEvtPtr = QEvt const *; + //${QF::types::QTimeEvtCtr} .................................................. #if (QF_TIMEEVT_CTR_SIZE == 1U) using QTimeEvtCtr = std::uint8_t; @@ -703,6 +671,21 @@ class QSubscrList { friend class QActive; }; // class QSubscrList +//${QF::types::QPtrDis} ...................................................... +class QPtrDis { +private: + std::uintptr_t m_ptr_dis; + + // friends... + friend class QTimeEvt; + + // friends... + friend class QXThread; + +public: + QPtrDis(void const * const ptr = nullptr) noexcept; +}; // class QPtrDis + //${QF::types::QEQueue} ...................................................... class QEQueue; @@ -796,14 +779,14 @@ class QActive : public QP::QAsm { void const * attr2 = nullptr); void start( QPrioSpec const prioSpec, - QEvt const * * const qSto, + QEvtPtr * const qSto, std::uint_fast16_t const qLen, void * const stkSto, std::uint_fast16_t const stkSize, void const * const par); void start( QPrioSpec const prioSpec, - QEvt const * * const qSto, + QEvtPtr * const qSto, std::uint_fast16_t const qLen, void * const stkSto, std::uint_fast16_t const stkSize) @@ -944,13 +927,27 @@ namespace QP { class QTimeEvt : public QP::QEvt { private: QTimeEvt * volatile m_next; + +#ifndef Q_UNSAFE + std::uintptr_t m_next_dis; +#endif // ndef Q_UNSAFE void * m_act; QTimeEvtCtr volatile m_ctr; + +#ifndef Q_UNSAFE + QTimeEvtCtr m_ctr_dis; +#endif // ndef Q_UNSAFE QTimeEvtCtr m_interval; + std::uint8_t m_tickRate; + std::uint8_t m_flags; public: static QTimeEvt timeEvtHead_[QF_MAX_TICK_RATE]; +#ifndef Q_UNSAFE + static QPtrDis timeEvtHead_dis_[QF_MAX_TICK_RATE]; +#endif // ndef Q_UNSAFE + private: friend class QXThread; @@ -960,10 +957,10 @@ class QTimeEvt : public QP::QEvt { QSignal const sig, std::uint_fast8_t const tickRate = 0U) noexcept; void armX( - QTimeEvtCtr const nTicks, - QTimeEvtCtr const interval = 0U) noexcept; + std::uint32_t const nTicks, + std::uint32_t const interval = 0U) noexcept; bool disarm() noexcept; - bool rearm(QTimeEvtCtr const nTicks) noexcept; + bool rearm(std::uint32_t const nTicks) noexcept; bool wasDisarmed() noexcept; void const * getAct() const noexcept { return m_act; @@ -974,6 +971,9 @@ class QTimeEvt : public QP::QEvt { QTimeEvtCtr getInterval() const noexcept { return m_interval; } + std::uint8_t getTickRate() const noexcept { + return m_tickRate; + } static void tick( std::uint_fast8_t const tickRate, void const * const sender) noexcept; diff --git a/include/qp_pkg.hpp b/include/qp_pkg.hpp index 4bfc0da96..dc69110d3 100644 --- a/include/qp_pkg.hpp +++ b/include/qp_pkg.hpp @@ -3,17 +3,10 @@ // Model: qpcpp.qm // File: ${include::qp_pkg.hpp} // -// This code has been generated by QM 6.2.0 . +// This code has been generated by QM 7.0.0 . // DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. // -// This code is covered by the following QP license: -// License # : LicenseRef-QL-dual -// Issued to : Any user of the QP/C++ real-time embedded framework -// Framework(s) : qpcpp -// Support ends : 2025-12-31 -// License scope: -// -// Copyright (C) 2005 Quantum Leaps, LLC . +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // Q u a n t u m L e a P s // ------------------------ @@ -21,21 +14,20 @@ // // 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: +// 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. // -// Contact information: +// NOTE: +// The GPL does NOT permit the incorporation of this code into proprietary +// programs. Please contact Quantum Leaps for commercial licensing options, +// which expressly supersede the GPL and are designed explicitly for +// closed-source distribution. +// +// Quantum Leaps contact information: // // // @@ -76,25 +68,30 @@ void bzero_( } // namespace QP //$enddecl${QF::QF-pkg} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -#define QF_CONST_CAST_(type_, ptr_) const_cast(ptr_) +#define QF_CONST_CAST_(type_, ptr_) const_cast(ptr_) +#define Q_PTR2UINT_CAST_(ptr_) (reinterpret_cast(ptr_)) #define QF_PTR_RANGE_(x_, min_, max_) (((min_) <= (x_)) && ((x_) <= (max_))) -#define Q_UINTPTR_CAST_(ptr_) (reinterpret_cast(ptr_)) -#define Q_ACTION_CAST(act_) (reinterpret_cast(act_)) namespace QP { -// Bitmasks are for the QTimeEvt::refCtr_ attribute (inherited from QEvt). -// In QTimeEvt this attribute is NOT used for reference counting. -constexpr std::uint8_t TE_IS_LINKED = 1U << 7U; // flag -constexpr std::uint8_t TE_WAS_DISARMED = 1U << 6U; // flag -constexpr std::uint8_t TE_TICK_RATE = 0x0FU; // bitmask +// Bitmasks are for the QTimeEvt::flags attribute +constexpr std::uint8_t QTE_FLAG_IS_LINKED {1U << 7U}; +constexpr std::uint8_t QTE_FLAG_WAS_DISARMED {1U << 6U}; inline void QEvt_refCtr_inc_(QEvt const * const e) noexcept { - (QF_CONST_CAST_(QEvt*, e))->refCtr_ = e->refCtr_ + 1U; + std::uint8_t rc = e->refCtr_ + 1U; + (QF_CONST_CAST_(QEvt*, e))->refCtr_ = rc; // cast away 'const' +#ifndef Q_UNSAFE + (QF_CONST_CAST_(QEvt*, e))->evtTag_ = (e->evtTag_ & 0xF0U) | ((~rc) & 0x0FU); +#endif } inline void QEvt_refCtr_dec_(QEvt const * const e) noexcept { - (QF_CONST_CAST_(QEvt*, e))->refCtr_ = e->refCtr_ - 1U; + std::uint8_t rc = e->refCtr_ - 1U; + (QF_CONST_CAST_(QEvt*, e))->refCtr_ = rc; // cast away 'const' +#ifndef Q_UNSAFE + (QF_CONST_CAST_(QEvt*, e))->evtTag_ = (e->evtTag_ & 0xF0U) | ((~rc) & 0x0FU); +#endif } } // namespace QP diff --git a/include/qpcpp.hpp b/include/qpcpp.hpp index 89918efe3..2f3c62169 100644 --- a/include/qpcpp.hpp +++ b/include/qpcpp.hpp @@ -3,17 +3,10 @@ // Model: qpcpp.qm // File: ${include::qpcpp.hpp} // -// This code has been generated by QM 6.2.0 . +// This code has been generated by QM 7.0.0 . // DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. // -// This code is covered by the following QP license: -// License # : LicenseRef-QL-dual -// Issued to : Any user of the QP/C++ real-time embedded framework -// Framework(s) : qpcpp -// Support ends : 2025-12-31 -// License scope: -// -// Copyright (C) 2005 Quantum Leaps, LLC . +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // Q u a n t u m L e a P s // ------------------------ @@ -21,21 +14,20 @@ // // 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: +// 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. // -// Contact information: +// NOTE: +// The GPL does NOT permit the incorporation of this code into proprietary +// programs. Please contact Quantum Leaps for commercial licensing options, +// which expressly supersede the GPL and are designed explicitly for +// closed-source distribution. +// +// Quantum Leaps contact information: // // // @@ -54,15 +46,18 @@ //============================================================================ #ifndef QP_API_VERSION - -#define QP_API_VERSION 0 - + #define QP_API_VERSION 0 #endif // QP_API_VERSION +// QP API compatibility layer... //============================================================================ -// QP/C++ API compatibility layer... +#if (QP_API_VERSION < 750) -#if (QP_API_VERSION < 740) +#define QM_SM_STATE_DECL(subm_, state_) error "submachines no longer supported" +#define qm_super_sub(sm_state_) error "submachines no longer supported" +#define qm_tran_ep(tatbl_) error "submachines no longer supported" +#define qm_tran_xp(xp_, tatbl_) error "submachines no longer supported" +#define qm_sm_exit(sm_state_) error "submachines no longer supported" #ifdef QEVT_DYN_CTOR //! @deprecated #QEVT_DYN_CTOR, please use #QEVT_PAR_INIT @@ -84,7 +79,13 @@ using char_t = char; //! @deprecated general purpose assertion with user-specified ID //! number that **always** evaluates the `expr_` expression. - #define Q_ALLEGE_ID(id_, expr_) ((void)(expr_)) + #define Q_ALLEGE_ID(id_, expr_) (static_cast(expr_)) + +#elif defined Q_UNSAFE + + //! @deprecated general purpose assertion with user-specified ID + //! number that **always** evaluates the `expr_` expression. + #define Q_ALLEGE_ID(id_, expr_) (static_cast(expr_)) #else // QP FuSa Subsystem enabled @@ -158,7 +159,7 @@ using char_t = char; QS_CRIT_STAT \ QS_CRIT_ENTRY(); \ QP::QS::beginRec_(static_cast(rec_)); \ - QS_TIME_PRE_(); + QS_TIME_PRE(); //! @deprecated output hex-formatted std::uint32_t to the QS record #define QS_U32_HEX(width_, data_) \ @@ -206,12 +207,6 @@ using char_t = char; //! the QM-generated code calls qm_exit(Q_STATE_CAST(state_)). #define QM_EXIT(state_) (me->qm_exit((state_))) -//! @deprecated -//! Macro to call in a QM submachine exit-handler. Applicable only to QMSMs. -//! Instead use the new impl-strategy without the "me->" pointer, where -//! the QM-generated code calls qm_sm_exit(Q_STATE_CAST(state_)). -#define QM_SM_EXIT(state_) (me->qm_sm_exit((state_))) - //! @deprecated //! Macro to call in a QM state-handler when it executes a tran. //! Instead use the new impl-strategy without the "me->" pointer, where @@ -231,26 +226,8 @@ using char_t = char; #define QM_TRAN_HIST(history_, tatbl_) \ (me->qm_tran_hist((history_), (tatbl_))) -//! @deprecated -//! Macro to call in a QM state-handler when it executes an initial tran. -//! Instead use the new impl-strategy without the "me->" pointer, where -//! the QM-generated code calls qm_tran_ep((tatbl_)). -#define QM_TRAN_EP(tatbl_) (me->qm_tran_ep((tatbl_))) - -//! @deprecated -//! Macro to call in a QM state-handler when it executes a tran-to-exit-point. -//! Instead use the new impl-strategy without the "me->" pointer, where -//! the QM-generated code calls qm_tran_xp((xp_), (tatbl_)). -#define QM_TRAN_XP(xp_, tatbl_) (me->qm_tran_xp((xp_), (tatbl_))) - -//! @deprecated -//! Designates the superstate of a given state in a subclass of QP::QMsm. -//! Instead use the new impl-strategy without the "me->" pointer, where -//! the QM-generated code calls qm_super_sub((state_)). -#define QM_SUPER_SUB(state_) (me->qm_super_sub((state_))) - #endif // QP_API_VERSION < 680 #endif // QP_API_VERSION < 691 -#endif // QP_API_VERSION < 700 +#endif // QP_API_VERSION < 750 #endif // QPCPP_HPP_ diff --git a/include/qs.hpp b/include/qs.hpp deleted file mode 100644 index 85cf8d443..000000000 --- a/include/qs.hpp +++ /dev/null @@ -1,1058 +0,0 @@ -//$file${include::qs.hpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// -// Model: qpcpp.qm -// File: ${include::qs.hpp} -// -// This code has been generated by QM 6.2.0 . -// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. -// -// This code is covered by the following QP license: -// License # : LicenseRef-QL-dual -// Issued to : Any user of the QP/C++ real-time embedded framework -// Framework(s) : qpcpp -// Support ends : 2025-12-31 -// License scope: -// -// Copyright (C) 2005 Quantum Leaps, LLC . -// -// 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 -// -// 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: -// -// -// -//$endhead${include::qs.hpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -#ifndef QS_HPP_ -#define QS_HPP_ - -#ifndef Q_SPY -#error "Q_SPY must be defined to include qs.hpp" -#endif - -//============================================================================ -//! @cond INTERNAL - -#ifndef QS_CTR_SIZE -#define QS_CTR_SIZE 2U -#endif - -#ifndef QS_TIME_SIZE -#define QS_TIME_SIZE 4U -#endif - -//! @endcond -//============================================================================ - -//$declare${QS::types} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { - -//${QS::types::QSpyPre} ...................................................... -//! pre-defined QS record IDs -enum QSpyPre : std::int8_t { - // [0] QS session (not maskable) - QS_EMPTY, //!< QS record for cleanly starting a session - - // [1] SM records - QS_QEP_STATE_ENTRY, //!< a state was entered - QS_QEP_STATE_EXIT, //!< a state was exited - QS_QEP_STATE_INIT, //!< an initial transition was taken in a state - QS_QEP_INIT_TRAN, //!< the top-most initial transition was taken - QS_QEP_INTERN_TRAN, //!< an internal transition was taken - QS_QEP_TRAN, //!< a regular transition was taken - QS_QEP_IGNORED, //!< an event was ignored (silently discarded) - QS_QEP_DISPATCH, //!< an event was dispatched (begin of RTC step) - QS_QEP_UNHANDLED, //!< an event was un-handled due to a guard - - // [10] Active Object (AO) records - QS_QF_ACTIVE_DEFER, //!< AO deferred an event - QS_QF_ACTIVE_RECALL, //!< AO recalled an event - QS_QF_ACTIVE_SUBSCRIBE, //!< an AO subscribed to an event - QS_QF_ACTIVE_UNSUBSCRIBE, //!< an AO unsubscribed to an event - QS_QF_ACTIVE_POST, //!< an event was posted (FIFO) directly to AO - QS_QF_ACTIVE_POST_LIFO, //!< an event was posted (LIFO) directly to AO - QS_QF_ACTIVE_GET, //!< AO got an event and its queue is not empty - QS_QF_ACTIVE_GET_LAST,//!< AO got an event and its queue is empty - QS_QF_ACTIVE_RECALL_ATTEMPT, //!< AO attempted to recall an event - - // [19] Event Queue (EQ) records - QS_QF_EQUEUE_POST, //!< an event was posted (FIFO) to a raw queue - QS_QF_EQUEUE_POST_LIFO, //!< an event was posted (LIFO) to a raw queue - QS_QF_EQUEUE_GET, //!< get an event and queue still not empty - QS_QF_EQUEUE_GET_LAST,//!< get the last event from the queue - - // [23] Framework (QF) records - QS_QF_NEW_ATTEMPT, //!< an attempt to allocate an event failed - - // [24] Memory Pool (MP) records - QS_QF_MPOOL_GET, //!< a memory block was removed from memory pool - QS_QF_MPOOL_PUT, //!< a memory block was returned to memory pool - - // [26] Additional Framework (QF) records - QS_QF_PUBLISH, //!< an event was published to active objects - QS_QF_NEW_REF, //!< new event reference was created - QS_QF_NEW, //!< new event was created - QS_QF_GC_ATTEMPT, //!< garbage collection attempt - QS_QF_GC, //!< garbage collection - QS_QF_TICK, //!< QTimeEvt tick was called - - // [32] Time Event (TE) records - QS_QF_TIMEEVT_ARM, //!< a time event was armed - QS_QF_TIMEEVT_AUTO_DISARM, //!< a time event expired and was disarmed - QS_QF_TIMEEVT_DISARM_ATTEMPT,//!< attempt to disarm a disarmed QTimeEvt - QS_QF_TIMEEVT_DISARM, //!< true disarming of an armed time event - QS_QF_TIMEEVT_REARM, //!< rearming of a time event - QS_QF_TIMEEVT_POST, //!< a time event posted itself directly to an AO - - // [38] Additional Framework (QF) records - QS_QF_DELETE_REF, //!< an event reference is about to be deleted - QS_QF_CRIT_ENTRY, //!< critical section was entered - QS_QF_CRIT_EXIT, //!< critical section was exited - QS_QF_ISR_ENTRY, //!< an ISR was entered - QS_QF_ISR_EXIT, //!< an ISR was exited - QS_QF_INT_DISABLE, //!< interrupts were disabled - QS_QF_INT_ENABLE, //!< interrupts were enabled - - // [45] Additional Active Object (AO) records - QS_QF_ACTIVE_POST_ATTEMPT,//!< attempt to post an evt to AO failed - - // [46] Additional Event Queue (EQ) records - QS_QF_EQUEUE_POST_ATTEMPT,//!< attempt to post evt to QEQueue failed - - // [47] Additional Memory Pool (MP) records - QS_QF_MPOOL_GET_ATTEMPT, //!< attempt to get a memory block failed - - // [48] Scheduler (SC) records - QS_SCHED_PREEMPT, //!< scheduler asynchronously preempted a task - QS_SCHED_RESTORE, //!< scheduler restored preempted task - QS_SCHED_LOCK, //!< scheduler was locked - QS_SCHED_UNLOCK, //!< scheduler was unlocked - QS_SCHED_NEXT, //!< scheduler started next task - QS_SCHED_IDLE, //!< scheduler restored the idle task - - // [54] Miscellaneous QS records (not maskable) - QS_ENUM_DICT, //!< enumeration dictionary entry - - // [55] Additional QEP records - QS_QEP_TRAN_HIST, //!< a tran. to history was taken - QS_QEP_TRAN_EP, //!< a tran. to entry point into a submachine - QS_QEP_TRAN_XP, //!< a tran. to exit point out of a submachine - - // [58] Miscellaneous QS records (not maskable) - QS_TEST_PAUSED, //!< test has been paused - QS_TEST_PROBE_GET, //!< reports that Test-Probe has been used - QS_SIG_DICT, //!< signal dictionary entry - QS_OBJ_DICT, //!< object dictionary entry - QS_FUN_DICT, //!< function dictionary entry - QS_USR_DICT, //!< user QS record dictionary entry - QS_TARGET_INFO, //!< reports the Target information - QS_TARGET_DONE, //!< reports completion of a user callback - QS_RX_STATUS, //!< reports QS data receive status - QS_QUERY_DATA, //!< reports the data from "current object" query - QS_PEEK_DATA, //!< reports the data from the PEEK query - QS_ASSERT_FAIL, //!< assertion failed in the code - QS_QF_RUN, //!< QF_run() was entered - - // [71] Semaphore (SEM) records - QS_SEM_TAKE, //!< a semaphore was taken by a thread - QS_SEM_BLOCK, //!< a semaphore blocked a thread - QS_SEM_SIGNAL, //!< a semaphore was signaled - QS_SEM_BLOCK_ATTEMPT, //!< a semaphore blocked was attempted - - // [75] Mutex (MTX) records - QS_MTX_LOCK, //!< a mutex was locked - QS_MTX_BLOCK, //!< a mutex blocked a thread - QS_MTX_UNLOCK, //!< a mutex was unlocked - QS_MTX_LOCK_ATTEMPT, //!< a mutex lock was attempted - QS_MTX_BLOCK_ATTEMPT, //!< a mutex blocking was attempted - QS_MTX_UNLOCK_ATTEMPT,//!< a mutex unlock was attempted - - // [81] - QS_PRE_MAX //!< the # predefined signals -}; - -//${QS::types::QSpyGroups} ................................................... -//! QS-TX record groups for QS_GLB_FILTER() -enum QSpyGroups : std::int16_t { - QS_ALL_RECORDS = 0xF0,//!< all maskable QS records - QS_SM_RECORDS, //!< State Machine QS records - QS_AO_RECORDS, //!< Active Object QS records - QS_EQ_RECORDS, //!< Event Queues QS records - QS_MP_RECORDS, //!< Memory Pools QS records - QS_TE_RECORDS, //!< Time Events QS records - QS_QF_RECORDS, //!< QF QS records - QS_SC_RECORDS, //!< Scheduler QS records - QS_SEM_RECORDS, //!< Semaphore QS records - QS_MTX_RECORDS, //!< Mutex QS records - QS_U0_RECORDS, //!< User Group 100-104 records - QS_U1_RECORDS, //!< User Group 105-109 records - QS_U2_RECORDS, //!< User Group 110-114 records - QS_U3_RECORDS, //!< User Group 115-119 records - QS_U4_RECORDS, //!< User Group 120-124 records - QS_UA_RECORDS //!< All User records -}; - -//${QS::types::QSpyUserOffsets} .............................................. -//! QS user record group offsets for QS_GLB_FILTER() -enum QSpyUserOffsets : std::int16_t { - QS_USER = 100, //!< the first record available to QS users - QS_USER0 = QS_USER, //!< offset for User Group 0 - QS_USER1 = QS_USER0 + 5, //!< offset for User Group 1 - QS_USER2 = QS_USER1 + 5, //!< offset for User Group 2 - QS_USER3 = QS_USER2 + 5, //!< offset for User Group 3 - QS_USER4 = QS_USER3 + 5 //!< offset for User Group 4 -}; - -//${QS::types::QSpyIdOffsets} ................................................ -//! QS ID offsets for QS_LOC_FILTER() -enum QSpyIdOffsets : std::int16_t { - QS_AO_ID = 0, //!< offset for AO priorities - QS_EP_ID = 64, //!< offset for event-pool IDs - QS_EQ_ID = 80, //!< offset for event-queue IDs - QS_AP_ID = 96 //!< offset for Application-specific IDs -}; - -//${QS::types::QSpyIdGroups} ................................................. -//! QS ID groups for QS_LOC_FILTER() -enum QSpyIdGroups : std::int16_t { - QS_ALL_IDS = 0xF0, //!< all QS IDs - QS_AO_IDS = 0x80 + QS_AO_ID, //!< AO IDs (priorities) - QS_EP_IDS = 0x80 + QS_EP_ID, //!< event-pool IDs - QS_EQ_IDS = 0x80 + QS_EQ_ID, //!< event-queue IDs - QS_AP_IDS = 0x80 + QS_AP_ID //!< Application-specific IDs -}; - -//${QS::types::QSpyId} ....................................................... -struct QSpyId { - std::uint8_t m_prio; //!< prio. (qsId) for the QS "local filter" - - // get the prio. (qsId) from the QSpyId object - std::uint_fast8_t getPrio() const noexcept { - return static_cast(m_prio); - } -}; - -//${QS::types::QSObj} ........................................................ -#if (QS_OBJ_PTR_SIZE == 2U) -using QSObj = std::uint16_t; -#endif // (QS_OBJ_PTR_SIZE == 2U) - -//${QS::types::QSObj} ........................................................ -#if (QS_OBJ_PTR_SIZE == 4U) -using QSObj = std::uint32_t; -#endif // (QS_OBJ_PTR_SIZE == 4U) - -//${QS::types::QSObj} ........................................................ -#if (QS_OBJ_PTR_SIZE == 8U) -using QSObj = std::uint64_t; -#endif // (QS_OBJ_PTR_SIZE == 8U) - -//${QS::types::QSFun} ........................................................ -#if (QS_FUN_PTR_SIZE == 2U) -using QSFun = std::uint16_t; -#endif // (QS_FUN_PTR_SIZE == 2U) - -//${QS::types::QSFun} ........................................................ -#if (QS_FUN_PTR_SIZE == 4U) -using QSFun = std::uint32_t; -#endif // (QS_FUN_PTR_SIZE == 4U) - -//${QS::types::QSFun} ........................................................ -#if (QS_FUN_PTR_SIZE == 8U) -using QSFun = std::uint64_t; -#endif // (QS_FUN_PTR_SIZE == 8U) - -//${QS::types::QSpyFunPtr} ................................................... -using QSpyFunPtr = void (*)(); - -//${QS::types::QSCtr} ........................................................ -#if (QS_CTR_SIZE == 2U) -using QSCtr = std::uint16_t; -#endif // (QS_CTR_SIZE == 2U) - -//${QS::types::QSCtr} ........................................................ -#if (QS_CTR_SIZE == 4U) -using QSCtr = std::uint32_t; -#endif // (QS_CTR_SIZE == 4U) - -//${QS::types::QSTimeCtr} .................................................... -#if (QS_TIME_SIZE == 2U) -using QSTimeCtr = std::uint16_t; -#endif // (QS_TIME_SIZE == 2U) - -//${QS::types::QSTimeCtr} .................................................... -#if (QS_TIME_SIZE == 4U) -using QSTimeCtr = std::uint32_t; -#endif // (QS_TIME_SIZE == 4U) - -} // namespace QP -//$enddecl${QS::types} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//$declare${QS::filters} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { -namespace QS { - -//${QS::filters::Filter} ..................................................... -class Filter { -public: - std::uint8_t glb[16]; - std::uint8_t loc[16]; -}; // class Filter - -//${QS::filters::filt_} ...................................................... -extern Filter filt_; - -} // namespace QS -} // namespace QP -//$enddecl${QS::filters} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//$declare${QS-macros} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv - -//${QS-macros::QS_INIT} ...................................................... -#define QS_INIT(arg_) (QP::QS::onStartup(arg_)) - -//${QS-macros::QS_EXIT} ...................................................... -#define QS_EXIT() (QP::QS::onCleanup()) - -//${QS-macros::QS_OUTPUT} .................................................... -#define QS_OUTPUT() (QP::QS::doOutput()) - -//${QS-macros::QS_RX_INPUT} .................................................. -#define QS_RX_INPUT() (QP::QS::doInput()) - -//${QS-macros::QS_GLB_FILTER} ................................................ -#define QS_GLB_FILTER(rec_) \ - (QP::QS::glbFilter_(static_cast(rec_))) - -//${QS-macros::QS_LOC_FILTER} ................................................ -#define QS_LOC_FILTER(qsId_) \ - (QP::QS::locFilter_(static_cast(qsId_))) - -//${QS-macros::QS_BEGIN_ID} .................................................. -#define QS_BEGIN_ID(rec_, qsId_) \ -if (QS_GLB_CHECK_(rec_) && QS_LOC_CHECK_(qsId_)) { \ - QS_CRIT_STAT \ - QS_CRIT_ENTRY(); \ - QS_MEM_SYS(); \ - QP::QS::beginRec_(static_cast(rec_)); \ - QS_TIME_PRE_(); { - -//${QS-macros::QS_END} ....................................................... -#define QS_END() } \ - QP::QS::endRec_(); \ - QS_MEM_APP(); \ - QS_CRIT_EXIT(); \ -} - -//${QS-macros::QS_FLUSH} ..................................................... -#define QS_FLUSH() (QP::QS::onFlush()) - -//${QS-macros::QS_BEGIN_INCRIT} .............................................. -#define QS_BEGIN_INCRIT(rec_, qsId_) \ -if (QS_GLB_CHECK_(rec_) && QS_LOC_CHECK_(qsId_)) { \ - QP::QS::beginRec_(rec_); \ - QS_TIME_PRE_(); { - -//${QS-macros::QS_END_INCRIT} ................................................ -#define QS_END_INCRIT() } \ - QP::QS::endRec_(); \ -} - -//${QS-macros::QS_GLB_CHECK_} ................................................ -#define QS_GLB_CHECK_(rec_) \ -((static_cast(QP::QS::filt_.glb[ \ - static_cast(rec_) >> 3U]) \ - & (static_cast(1U) \ - << (static_cast(rec_) & 7U))) != 0U) - -//${QS-macros::QS_LOC_CHECK_} ................................................ -#define QS_LOC_CHECK_(qsId_) \ -((static_cast(QP::QS::filt_.loc \ - [static_cast(qsId_) >> 3U]) \ - & (static_cast(1U) \ - << (static_cast(qsId_) & 7U))) != 0U) - -//${QS-macros::QS_REC_DONE} .................................................. -#ifndef QS_REC_DONE -#define QS_REC_DONE() (static_cast(0)) -#endif // ndef QS_REC_DONE - -//${QS-macros::QS_I8} ........................................................ -#define QS_I8(width_, data_) \ -(QP::QS::u8_fmt_(static_cast( \ - (static_cast(((width_) << 4U) & 0x7U)) \ - | static_cast(QP::QS::I8_ENUM_T)), (data_))) - -//${QS-macros::QS_U8} ........................................................ -#define QS_U8(width_, data_) \ -(QP::QS::u8_fmt_(static_cast( \ - (static_cast((width_) << 4U)) \ - | static_cast(QP::QS::U8_T)), (data_))) - -//${QS-macros::QS_I16} ....................................................... -#define QS_I16(width_, data_) \ -(QP::QS::u16_fmt_(static_cast( \ - (static_cast((width_) << 4U)) \ - | static_cast(QP::QS::I16_T)), (data_))) - -//${QS-macros::QS_U16} ....................................................... -#define QS_U16(width_, data_) \ -(QP::QS::u16_fmt_(static_cast((((width_) << 4U)) \ - | static_cast(QP::QS::U16_T)), (data_))) - -//${QS-macros::QS_I32} ....................................................... -#define QS_I32(width_, data_) \ -(QP::QS::u32_fmt_( \ - static_cast((static_cast((width_) << 4U)) \ - | static_cast(QP::QS::I32_T)), (data_))) - -//${QS-macros::QS_U32} ....................................................... -#define QS_U32(width_, data_) \ -(QP::QS::u32_fmt_(static_cast( \ - (static_cast((width_) << 4U)) \ - | static_cast(QP::QS::U32_T)), (data_))) - -//${QS-macros::QS_I64} ....................................................... -#define QS_I64(width_, data_) \ -(QP::QS::u64_fmt_(static_cast( \ - (static_cast((width_) << 4U)) \ - | static_cast(QP::QS::I64_T)), (data_))) - -//${QS-macros::QS_U64} ....................................................... -#define QS_U64(width_, data_) \ -(QP::QS::u64_fmt_(static_cast( \ - (static_cast((width_) << 4U)) \ - | static_cast(QP::QS::U64_T)), (data_))) - -//${QS-macros::QS_F32} ....................................................... -#define QS_F32(width_, data_) \ -(QP::QS::f32_fmt_(static_cast( \ - (static_cast((width_) << 4U)) \ - | static_cast(QP::QS::F32_T)), (data_))) - -//${QS-macros::QS_F64} ....................................................... -#define QS_F64(width_, data_) \ -(QP::QS::f64_fmt_(static_cast( \ - (static_cast((width_) << 4U)) \ - | static_cast(QP::QS::F64_T)), (data_))) - -//${QS-macros::QS_STR} ....................................................... -#define QS_STR(str_) (QP::QS::str_fmt_(str_)) - -//${QS-macros::QS_MEM} ....................................................... -#define QS_MEM(mem_, size_) (QP::QS::mem_fmt_((mem_), (size_))) - -//${QS-macros::QS_ENUM} ...................................................... -#define QS_ENUM(group_, value_) \ - (QP::QS::u8_fmt_(static_cast(0x80U | ((group_) << 4U)) \ - | static_cast(QP::QS::I8_ENUM_T),\ - static_cast(value_))) - -//${QS-macros::QS_TIME_PRE_} ................................................. -#if (QS_TIME_SIZE == 2U) -#define QS_TIME_PRE_() (QP::QS::u16_raw_(QP::QS::onGetTime())) -#endif // (QS_TIME_SIZE == 2U) - -//${QS-macros::QS_TIME_PRE_} ................................................. -#if (QS_TIME_SIZE == 4U) -#define QS_TIME_PRE_() (QP::QS::u32_raw_(QP::QS::onGetTime())) -#endif // (QS_TIME_SIZE == 4U) - -//${QS-macros::QS_OBJ} ....................................................... -#if (QS_OBJ_PTR_SIZE == 2U) -#define QS_OBJ(obj_) (QP::QS::u16_fmt_(QP::QS::OBJ_T, \ - reinterpret_cast(obj_))) -#endif // (QS_OBJ_PTR_SIZE == 2U) - -//${QS-macros::QS_OBJ} ....................................................... -#if (QS_OBJ_PTR_SIZE == 4U) -#define QS_OBJ(obj_) (QP::QS::u32_fmt_(QP::QS::OBJ_T, \ - reinterpret_cast(obj_))) -#endif // (QS_OBJ_PTR_SIZE == 4U) - -//${QS-macros::QS_OBJ} ....................................................... -#if (QS_OBJ_PTR_SIZE == 8U) -#define QS_OBJ(obj_) (QP::QS::u64_fmt_(QP::QS::OBJ_T, \ - reinterpret_cast(obj_))) -#endif // (QS_OBJ_PTR_SIZE == 8U) - -//${QS-macros::QS_FUN} ....................................................... -#if (QS_FUN_PTR_SIZE == 2U) -#define QS_FUN(fun_) (QP::QS::u16_fmt_(QP::QS::FUN_T, \ - reinterpret_cast(fun_))) -#endif // (QS_FUN_PTR_SIZE == 2U) - -//${QS-macros::QS_FUN} ....................................................... -#if (QS_FUN_PTR_SIZE == 4U) -#define QS_FUN(fun_) (QP::QS::u32_fmt_(QP::QS::FUN_T, \ - reinterpret_cast(fun_))) -#endif // (QS_FUN_PTR_SIZE == 4U) - -//${QS-macros::QS_FUN} ....................................................... -#if (QS_FUN_PTR_SIZE == 8U) -#define QS_FUN(fun_) (QP::QS::u64_fmt_(QP::QS::FUN_T, \ - reinterpret_cast(fun_))) -#endif // (QS_FUN_PTR_SIZE == 8U) - -//${QS-macros::QS_SIG} ....................................................... -#if (Q_SIGNAL_SIZE == 1U) -#define QS_SIG(sig_, obj_) \ - QP::QS::u8_fmt_(QP::QS::SIG_T, static_cast(sig_)); \ - QP::QS::obj_raw_(obj_) -#endif // (Q_SIGNAL_SIZE == 1U) - -//${QS-macros::QS_SIG} ....................................................... -#if (Q_SIGNAL_SIZE == 2U) -#define QS_SIG(sig_, obj_) \ - QP::QS::u16_fmt_(QP::QS::SIG_T, static_cast(sig_)); \ - QP::QS::obj_raw_(obj_) -#endif // (Q_SIGNAL_SIZE == 2U) - -//${QS-macros::QS_SIG} ....................................................... -#if (Q_SIGNAL_SIZE == 4U) -#define QS_SIG(sig_, obj_) \ - QP::QS::u32_fmt_(QP::QS::SIG_T, static_cast(sig_)); \ - QP::QS::obj_raw_(obj_) -#endif // (Q_SIGNAL_SIZE == 4U) - -//${QS-macros::QS_SIG_DICTIONARY} ............................................ -#define QS_SIG_DICTIONARY(sig_, obj_) \ - (QP::QS::sig_dict_pre_((sig_), (obj_), #sig_)) - -//${QS-macros::QS_OBJ_DICTIONARY} ............................................ -#define QS_OBJ_DICTIONARY(obj_) \ - (QP::QS::obj_dict_pre_((obj_), #obj_)) - -//${QS-macros::QS_OBJ_ARR_DICTIONARY} ........................................ -#define QS_OBJ_ARR_DICTIONARY(obj_, idx_) \ - (QP::QS::obj_arr_dict_pre_((obj_), (idx_), #obj_)) - -//${QS-macros::QS_FUN_DICTIONARY} ............................................ -#define QS_FUN_DICTIONARY(fun_) \ - (QP::QS::fun_dict_pre_( \ - QP::QS::force_cast(fun_), #fun_)) - -//${QS-macros::QS_USR_DICTIONARY} ............................................ -#define QS_USR_DICTIONARY(rec_) \ - (QP::QS::usr_dict_pre_((rec_), #rec_)) - -//${QS-macros::QS_ENUM_DICTIONARY} ........................................... -#define QS_ENUM_DICTIONARY(value_, group_) \ - (QP::QS::enum_dict_pre_((value_), (group_), #value_)) - -//${QS-macros::QS_QF_CRIT_ENTRY} ............................................. -#define QS_QF_CRIT_ENTRY() (QP::QS::crit_entry_pre_()) - -//${QS-macros::QS_QF_CRIT_EXIT} .............................................. -#define QS_QF_CRIT_EXIT() (QP::QS::crit_exit_pre_()) - -//${QS-macros::QS_QF_ISR_ENTRY} .............................................. -#define QS_QF_ISR_ENTRY(isrnest_, prio_) \ - (QP::QS::isr_entry_pre_((isrnest_), (prio_))) - -//${QS-macros::QS_QF_ISR_EXIT} ............................................... -#define QS_QF_ISR_EXIT(isrnest_, prio_) \ - (QP::QS::isr_exit_pre_((isrnest_), (prio_))) - -//${QS-macros::QS_ONLY} ...................................................... -#define QS_ONLY(code_) (code_) - -//${QS-macros::QS_ASSERTION} ................................................. -#define QS_ASSERTION(module_, id_, delay_) \ - (QP::QS::assertion_pre_((module_), (id_), (delay_))) - -//${QS-macros::QS_EOD} ....................................................... -#define QS_EOD (static_cast(0xFFFFU)) - -//${QS-macros::QS_CMD} ....................................................... -#define QS_CMD (static_cast(7U)) - -//${QS-macros::QS_HEX_FMT} ................................................... -#define QS_HEX_FMT (static_cast(0x0FU)) - -//${QS-macros::QS_CRIT_STAT} ................................................. -#ifndef QS_CRIT_STAT -#define QS_CRIT_STAT QF_CRIT_STAT -#endif // ndef QS_CRIT_STAT - -//${QS-macros::QS_CRIT_ENTRY} ................................................ -#ifndef QS_CRIT_ENTRY -#define QS_CRIT_ENTRY() QF_CRIT_ENTRY() -#endif // ndef QS_CRIT_ENTRY - -//${QS-macros::QS_CRIT_EXIT} ................................................. -#ifndef QS_CRIT_EXIT -#define QS_CRIT_EXIT() QF_CRIT_EXIT() -#endif // ndef QS_CRIT_EXIT - -//${QS-macros::QS_MEM_SYS} ................................................... -#ifndef QS_MEM_SYS -#define QS_MEM_SYS() QF_MEM_SYS() -#endif // ndef QS_MEM_SYS - -//${QS-macros::QS_MEM_APP} ................................................... -#ifndef QS_MEM_APP -#define QS_MEM_APP() QF_MEM_APP() -#endif // ndef QS_MEM_APP -//$enddecl${QS-macros} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -//============================================================================ -//! @cond INTERNAL - -namespace QP { -namespace QS { - -struct Attr { - void const * locFilter_AP; //!< @deprecated - std::uint8_t * buf; - QSCtr end; - QSCtr volatile head; - QSCtr volatile tail; - QSCtr volatile used; - std::uint8_t volatile seq; - std::uint8_t volatile chksum; - std::uint8_t volatile critNest; - std::uint8_t flags; -}; - -extern Attr priv_; - -void glbFilter_(std::int_fast16_t const filter) noexcept; -void locFilter_(std::int_fast16_t const filter) noexcept; - -void beginRec_(std::uint_fast8_t const rec) noexcept; -void endRec_() noexcept; - -void u8_raw_(std::uint8_t const d) noexcept; -void u8u8_raw_(std::uint8_t const d1, std::uint8_t const d2) noexcept; -void u16_raw_(std::uint16_t d) noexcept; -void u32_raw_(std::uint32_t d) noexcept; -void u64_raw_(std::uint64_t d) noexcept; -void obj_raw_(void const * const obj) noexcept; -void str_raw_(char const * s) noexcept; - -void u8_fmt_(std::uint8_t const format, std::uint8_t const d) noexcept; -void u16_fmt_(std::uint8_t format, std::uint16_t d) noexcept; -void u32_fmt_(std::uint8_t format, - std::uint32_t d) noexcept; -void u64_fmt_(std::uint8_t format, std::uint64_t d) noexcept; -void f32_fmt_(std::uint8_t format, float32_t f) noexcept; -void f64_fmt_(std::uint8_t format, float64_t d) noexcept; -void str_fmt_(char const * s) noexcept; -void mem_fmt_(std::uint8_t const * blk, std::uint8_t size) noexcept; - -void sig_dict_pre_(QSignal const sig, void const * const obj, - char const * const name) noexcept; -void obj_dict_pre_(void const * const obj, - char const * const name) noexcept; -void obj_arr_dict_pre_(void const * const obj, - std::uint_fast16_t const idx, - char const * const name) noexcept; -void fun_dict_pre_(QSpyFunPtr fun, - char const * const name) noexcept; -void usr_dict_pre_(enum_t const rec, char const * const name) noexcept; -void enum_dict_pre_(enum_t const value, std::uint8_t const group, - char const * const name) noexcept; - -void assertion_pre_(char const * const module, int_t const id, - std::uint32_t const delay) noexcept; -void crit_entry_pre_() noexcept; -void crit_exit_pre_() noexcept; -void isr_entry_pre_(std::uint8_t const isrnest, - std::uint8_t const prio) noexcept; -void isr_exit_pre_(std::uint8_t const isrnest, - std::uint8_t const prio) noexcept; - -void target_info_pre_(std::uint8_t const isReset); - -} // namespace QS -} // namespace QP - -//! @endcond -//============================================================================ - -//$declare${QS::QS-TX} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { -namespace QS { - -//${QS::QS-TX::preType} ...................................................... -//! Enumerates data elements for app-specific trace records -enum preType : std::uint8_t { - I8_ENUM_T, //!< signed 8-bit integer or enum format - U8_T, //!< unsigned 8-bit integer format - I16_T, //!< signed 16-bit integer format - U16_T, //!< unsigned 16-bit integer format - I32_T, //!< signed 32-bit integer format - U32_T, //!< unsigned 32-bit integer format - F32_T, //!< 32-bit floating point format - F64_T, //!< 64-bit floating point format - STR_T, //!< zero-terminated ASCII string format - MEM_T, //!< up to 255-bytes memory block format - SIG_T, //!< event signal format - OBJ_T, //!< object pointer format - FUN_T, //!< function pointer format - I64_T, //!< signed 64-bit integer format - U64_T //!< unsigned 64-bit integer format -}; - -//${QS::QS-TX::force_cast} ................................................... -template -inline T_OUT force_cast(T_IN in) { - union TCast { - T_IN in; - T_OUT out; - } u = { in }; - return u.out; -} - -//${QS::QS-TX::initBuf} ...................................................... -void initBuf( - std::uint8_t * const sto, - std::uint_fast32_t const stoSize) noexcept; - -//${QS::QS-TX::getByte} ...................................................... -std::uint16_t getByte() noexcept; - -//${QS::QS-TX::getBlock} ..................................................... -std::uint8_t const * getBlock(std::uint16_t * const pNbytes) noexcept; - -//${QS::QS-TX::doOutput} ..................................................... -void doOutput(); - -//${QS::QS-TX::onStartup} .................................................... -bool onStartup(void const * arg); - -//${QS::QS-TX::onCleanup} .................................................... -void onCleanup(); - -//${QS::QS-TX::onFlush} ...................................................... -void onFlush(); - -//${QS::QS-TX::onGetTime} .................................................... -QSTimeCtr onGetTime(); - -} // namespace QS -} // namespace QP -//$enddecl${QS::QS-TX} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -//============================================================================ -#ifdef Q_UTEST - -//$declare${QS::QUTest} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { -namespace QS { - -//${QS::QUTest::TProbe} ...................................................... -struct TProbe { - QSFun addr; - std::uint32_t data; - std::uint8_t idx; -}; - -//${QS::QUTest::onTestSetup} ................................................. -void onTestSetup(); - -//${QS::QUTest::onTestTeardown} .............................................. -void onTestTeardown(); - -//${QS::QUTest::onTestEvt} ................................................... -void onTestEvt(QEvt * e); - -//${QS::QUTest::onTestPost} .................................................. -void onTestPost( - void const * sender, - QActive * recipient, - QEvt const * e, - bool status); - -//${QS::QUTest::onTestLoop} .................................................. -void onTestLoop(); - -} // namespace QS -} // namespace QP -//$enddecl${QS::QUTest} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -#define QUTEST_ON_POST 124 - -//============================================================================ -//! @cond INTERNAL - -namespace QP { -namespace QS { - -struct TestAttr { - TProbe tpBuf[16]; - std::uint8_t tpNum; - QSTimeCtr testTime; - QPSet readySet; - QPSet readySet_dis; - std::uint_fast8_t intLock; -}; - -extern TestAttr tstPriv_; - -void test_pause_(); -std::uint32_t getTestProbe_(QSpyFunPtr const api) noexcept; - -} // namespace QS -} // namespace QP - -//! @endcond -//============================================================================ - -// QP-stub for QUTest -// NOTE: The QP-stub is needed for unit testing QP applications, -// but might NOT be needed for testing QP itself. -#if (Q_UTEST != 0) - -//$declare${QS::QUTest-stub::QHsmDummy} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { - -//${QS::QUTest-stub::QHsmDummy} .............................................. -class QHsmDummy : public QP::QAsm { -public: - QHsmDummy(); - void init( - void const * const e, - std::uint_fast8_t const qsId) override; - void dispatch( - QEvt const * const e, - std::uint_fast8_t const qsId) override; -}; // class QHsmDummy - -} // namespace QP -//$enddecl${QS::QUTest-stub::QHsmDummy} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//$declare${QS::QUTest-stub::QActiveDummy} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { - -//${QS::QUTest-stub::QActiveDummy} ........................................... -class QActiveDummy : public QP::QActive { -private: - friend class QActive; - -public: - QActiveDummy(); - void init( - void const * const e, - std::uint_fast8_t const qsId) override; - void dispatch( - QEvt const * const e, - std::uint_fast8_t const qsId) override; - -private: - bool fakePost( - QEvt const * const e, - std::uint_fast16_t const margin, - void const * const sender) noexcept; - void fakePostLIFO(QEvt const * const e) noexcept; -}; // class QActiveDummy - -} // namespace QP -//$enddecl${QS::QUTest-stub::QActiveDummy} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -#endif // Q_UTEST != 0 - -#define QS_TEST_PROBE_DEF(fun_) \ - std::uint32_t const qs_tp_ = \ - QP::QS::getTestProbe_(QP::QS::force_cast(fun_)); - -#define QS_TEST_PROBE(code_) \ - if (qs_tp_ != 0U) { code_ } - -#define QS_TEST_PROBE_ID(id_, code_) \ - if (qs_tp_ == static_cast(id_)) { code_ } - -#define QS_TEST_PAUSE() (QP::QS::test_pause_()) - -#else // Q_UTEST not defined - -// dummy definitions when not building for QUTEST -#define QS_TEST_PROBE_DEF(fun_) -#define QS_TEST_PROBE(code_) -#define QS_TEST_PROBE_ID(id_, code_) -#define QS_TEST_PAUSE() (static_cast(0)) - -#endif // Q_UTEST - -//============================================================================ -//! @cond INTERNAL - -namespace QP { -namespace QS { - -//............................................................................ -struct CmdVar { - std::uint32_t param1; - std::uint32_t param2; - std::uint32_t param3; - std::uint8_t idx; - std::uint8_t cmdId; -}; - -struct TickVar { - std::uint_fast8_t rate; -}; - -struct PeekVar { - std::uint16_t offs; - std::uint8_t size; - std::uint8_t num; - std::uint8_t idx; -}; - -struct PokeVar { - std::uint32_t data; - std::uint16_t offs; - std::uint8_t size; - std::uint8_t num; - std::uint8_t idx; - std::uint8_t fill; -}; - -struct FltVar { - std::uint8_t data[16]; - std::uint8_t idx; - std::uint8_t recId; // global/local -}; - -struct ObjVar { - QSObj addr; - std::uint8_t idx; - std::uint8_t kind; // see qs.hpp, enum QSpyObjKind - std::uint8_t recId; -}; - -struct EvtVar { - QP::QEvt *e; - std::uint8_t *p; - QP::QSignal sig; - std::uint16_t len; - std::uint8_t prio; - std::uint8_t idx; -}; - -struct RxAttr { - void * currObj[8]; - std::uint8_t * buf; - QSCtr end; - QSCtr volatile head; - QSCtr volatile tail; - std::uint8_t state; - std::uint8_t esc; - std::uint8_t seq; - std::uint8_t chksum; -#ifdef Q_UTEST - bool inTestLoop; -#endif - union Variant { - CmdVar cmd; - TickVar tick; - PeekVar peek; - PokeVar poke; - FltVar flt; - ObjVar obj; - EvtVar evt; -#ifdef Q_UTEST - QP::QS::TProbe tp; -#endif // Q_UTEST - } var; -} ; - -extern RxAttr rxPriv_; - -} // namespace QS -} // namespace QP - -//! @endcond -//============================================================================ - -//$declare${QS::QS-RX} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { -namespace QS { - -//${QS::QS-RX::QSpyObjKind} .................................................. -//! Kinds of objects used QS-RX -enum QSpyObjKind : std::uint8_t { - SM_OBJ, //!< state machine object - AO_OBJ, //!< active object - MP_OBJ, //!< event pool object - EQ_OBJ, //!< raw queue object - TE_OBJ, //!< time event object - AP_OBJ, //!< generic Application-specific object - MAX_OBJ -}; - -//${QS::QS-RX::OSpyObjCombnation} ............................................ -//! Object combinations for QS-RX -enum OSpyObjCombnation : std::uint8_t { - SM_AO_OBJ = MAX_OBJ //!< combination of SM and AO -}; - -//${QS::QS-RX::rxInitBuf} .................................................... -void rxInitBuf( - std::uint8_t * const sto, - std::uint16_t const stoSize) noexcept; - -//${QS::QS-RX::rxPut} ........................................................ -inline bool rxPut(std::uint8_t const b) noexcept { - // NOTE: does not need critical section - // But requires system-level memory access (QF_MEM_SYS()). - - QSCtr head = rxPriv_.head + 1U; - if (head == rxPriv_.end) { - head = 0U; - } - if (head != rxPriv_.tail) { // buffer NOT full? - rxPriv_.buf[rxPriv_.head] = b; - rxPriv_.head = head; - return true; // byte placed in the buffer - } - else { - return false; // byte NOT placed in the buffer - } -} - -//${QS::QS-RX::rxParse} ...................................................... -void rxParse(); - -//${QS::QS-RX::setCurrObj} ................................................... -void setCurrObj( - std::uint8_t const obj_kind, - void * const obj_ptr); - -//${QS::QS-RX::rxGetNfree} ................................................... -std::uint16_t rxGetNfree() noexcept; - -//${QS::QS-RX::doInput} ...................................................... -void doInput(); - -//${QS::QS-RX::onReset} ...................................................... -void onReset(); - -//${QS::QS-RX::onCommand} .................................................... -void onCommand( - std::uint8_t cmdId, - std::uint32_t param1, - std::uint32_t param2, - std::uint32_t param3); - -} // namespace QS -} // namespace QP -//$enddecl${QS::QS-RX} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -#endif // QS_HPP_ diff --git a/include/qs_dummy.hpp b/include/qs_dummy.hpp index 9d112bdbd..8c4da7e67 100644 --- a/include/qs_dummy.hpp +++ b/include/qs_dummy.hpp @@ -1,64 +1,52 @@ -//$file${include::qs_dummy.hpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// -// Model: qpcpp.qm -// File: ${include::qs_dummy.hpp} -// -// This code has been generated by QM 6.2.0 . -// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. -// -// This code is covered by the following QP license: -// License # : LicenseRef-QL-dual -// Issued to : Any user of the QP/C++ real-time embedded framework -// Framework(s) : qpcpp -// Support ends : 2025-12-31 -// License scope: +//============================================================================ +// QP/C++ Spy software tracing target-resident component // -// Copyright (C) 2005 Quantum Leaps, LLC . +// 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 -// -// 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: +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The terms of the closed source Quantum Leaps commercial licenses -// can be found at: +// 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. // -// Contact information: +// NOTE: +// The GPL does NOT permit the incorporation of this code into proprietary +// programs. Please contact Quantum Leaps for commercial licensing options, +// which expressly supersede the GPL and are designed explicitly for +// closed-source distribution. +// +// Quantum Leaps contact information: // // -// -//$endhead${include::qs_dummy.hpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//============================================================================ #ifndef QS_DUMMY_HPP_ #define QS_DUMMY_HPP_ #ifdef Q_SPY -#error "Q_SPY must NOT be defined to include qs_dummy.hpp" + #error "Q_SPY must NOT be defined to include qs_dummy.hpp" +#endif + +#ifdef Q_UTEST + #error "Q_UTEST must NOT be defined to include qs_dummy.hpp" #endif #define QS_INIT(arg_) (true) #define QS_EXIT() static_cast(0) #define QS_DUMP() static_cast(0) #define QS_GLB_FILTER(rec_) static_cast(0) -#define QS_LOC_FILTER(qsId_) static_cast(0) - -#define QS_GET_BYTE(pByte_) (0xFFFFU) -#define QS_GET_BLOCK(pSize_) (nullptr) +#define QS_LOC_FILTER(qsId_) static_cast(0) -#define QS_BEGIN_ID(rec_, qsId_) if (false) { +#define QS_BEGIN_ID(rec_, qsId_) if (false) { #define QS_END() } -#define QS_BEGIN_INCRIT(rec_, qsId_) if (false) { +#define QS_BEGIN_INCRIT(rec_, qsId_) if (false) { #define QS_END_INCRIT() } #define QS_I8(width_, data_) static_cast(0) @@ -96,27 +84,83 @@ #define QS_RX_INPUT() static_cast(0) #define QS_ONLY(code_) static_cast(0) +//============================================================================ +namespace QP { +namespace QS { + +// QS API used inside applications +#ifndef QS_TIME_SIZE + using QSTimeCtr = std::uint32_t; +#elif (QS_TIME_SIZE == 2U) + using QSTimeCtr = std::uint16_t; +#else + using QSTimeCtr = std::uint32_t; +#endif + +void initBuf(std::uint8_t * const sto, + std::uint_fast32_t const stoSize) noexcept; +std::uint16_t getByte() noexcept; +std::uint8_t const *getBlock(std::uint16_t * const pNbytes) noexcept; +void doOutput(); +bool onStartup(void const * arg); +void onCleanup(); +void onFlush(); +QSTimeCtr onGetTime(); + +void rxInitBuf(std::uint8_t * const sto, + std::uint16_t const stoSize) noexcept; +bool rxPut(std::uint8_t const b) noexcept; +void rxParse(); + +} // namespace QP +} // namespace QS + +//============================================================================ +// QS API used inside test fixtures +#ifdef Q_UTEST + +#if (QS_FUN_PTR_SIZE == 2U) + typedef uint16_t QSFun; +#elif (QS_FUN_PTR_SIZE == 4U) + typedef uint32_t QSFun; +#elif (QS_FUN_PTR_SIZE == 8U) + typedef uint64_t QSFun; +#endif + +struct QS_TProbe { + QSFun addr; + uint32_t data; + uint8_t idx; +}; + +void QS_onTestSetup(void); +void QS_onTestTeardown(void); +void QS_onTestEvt(QEvt *e); +void QS_onTestPost(void const *sender, QActive *recipient, + QEvt const *e, bool status); +void QS_onTestLoop(void); + +#endif // def Q_UTEST + //============================================================================ // interface used only for internal implementation, but not in applications #ifdef QP_IMPL // predefined QS trace records - #define QS_BEGIN_PRE_(rec_, qsId_) if (false) { - #define QS_END_PRE_() } - #define QS_BEGIN_PRE_(rec_, qsId_) if (false) { - #define QS_END_PRE_() } - #define QS_U8_PRE_(data_) static_cast(0) - #define QS_2U8_PRE_(data1_, data2_) static_cast(0) - #define QS_U16_PRE_(data_) static_cast(0) - #define QS_U32_PRE_(data_) static_cast(0) - #define QS_TIME_PRE_() static_cast(0) - #define QS_SIG_PRE_(sig_) static_cast(0) - #define QS_EVS_PRE_(size_) static_cast(0) - #define QS_OBJ_PRE_(obj_) static_cast(0) - #define QS_FUN_PRE_(fun_) static_cast(0) - #define QS_EQC_PRE_(ctr_) static_cast(0) - #define QS_MPC_PRE_(ctr_) static_cast(0) - #define QS_MPS_PRE_(size_) static_cast(0) - #define QS_TEC_PRE_(ctr_) static_cast(0) + #define QS_BEGIN_PRE(rec_, qsId_) if (false) { + #define QS_END_PRE() } + #define QS_U8_PRE(data_) static_cast(0) + #define QS_2U8_PRE(data1_, data2_) static_cast(0) + #define QS_U16_PRE(data_) static_cast(0) + #define QS_U32_PRE(data_) static_cast(0) + #define QS_TIME_PRE() static_cast(0) + #define QS_SIG_PRE(sig_) static_cast(0) + #define QS_EVS_PRE(size_) static_cast(0) + #define QS_OBJ_PRE(obj_) static_cast(0) + #define QS_FUN_PRE(fun_) static_cast(0) + #define QS_EQC_PRE(ctr_) static_cast(0) + #define QS_MPC_PRE(ctr_) static_cast(0) + #define QS_MPS_PRE(size_) static_cast(0) + #define QS_TEC_PRE(ctr_) static_cast(0) #define QS_CRIT_STAT #define QS_CRIT_ENTRY() static_cast(0) @@ -128,7 +172,7 @@ #define QS_TR_CRIT_ENTRY() static_cast(0) #define QS_TR_CRIT_EXIT() static_cast(0) #define QS_TR_ISR_ENTRY(isrnest_, prio_) static_cast(0) - #define QS_Tr_ISR_EXIT(isrnest_, prio_) static_cast(0) + #define QS_TR_ISR_EXIT(isrnest_, prio_) static_cast(0) #endif // QP_IMPL #endif // QS_DUMMY_HPP_ diff --git a/include/qs_pkg.hpp b/include/qs_pkg.hpp deleted file mode 100644 index 889df7809..000000000 --- a/include/qs_pkg.hpp +++ /dev/null @@ -1,215 +0,0 @@ -//$file${include::qs_pkg.hpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// -// Model: qpcpp.qm -// File: ${include::qs_pkg.hpp} -// -// This code has been generated by QM 6.2.0 . -// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. -// -// This code is covered by the following QP license: -// License # : LicenseRef-QL-dual -// Issued to : Any user of the QP/C++ real-time embedded framework -// Framework(s) : qpcpp -// Support ends : 2025-12-31 -// License scope: -// -// Copyright (C) 2005 Quantum Leaps, LLC . -// -// 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 -// -// 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: -// -// -// -//$endhead${include::qs_pkg.hpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -#ifndef QS_PKG_HPP_ -#define QS_PKG_HPP_ - -//============================================================================ -//! @cond INTERNAL - -namespace QP { - -//! QS received record types (RX channel) -enum QSpyRxRecords : std::uint8_t { - QS_RX_INFO, //!< query Target info (ver, config, tstamp) - QS_RX_COMMAND, //!< execute a user-defined command in the Target - QS_RX_RESET, //!< reset the Target - QS_RX_TICK, //!< call system clock tick in the Target - QS_RX_PEEK, //!< peek Target memory - QS_RX_POKE, //!< poke Target memory - QS_RX_FILL, //!< fill Target memory - QS_RX_TEST_SETUP, //!< test setup - QS_RX_TEST_TEARDOWN, //!< test teardown - QS_RX_TEST_PROBE, //!< set a Test-Probe in the Target - QS_RX_GLB_FILTER, //!< set global filters in the Target - QS_RX_LOC_FILTER, //!< set local filters in the Target - QS_RX_AO_FILTER, //!< set local AO filter in the Target - QS_RX_CURR_OBJ, //!< set the "current-object" in the Target - QS_RX_TEST_CONTINUE, //!< continue a test after QS_TEST_PAUSE() - QS_RX_QUERY_CURR, //!< query the "current object" in the Target - QS_RX_EVENT //!< inject an event to the Target -}; - -constexpr std::uint8_t QS_FRAME {0x7EU}; -constexpr std::uint8_t QS_ESC {0x7DU}; -constexpr std::uint8_t QS_ESC_XOR {0x20U}; -constexpr std::uint8_t QS_GOOD_CHKSUM {0xFFU}; - -} // namespace QP - -//---------------------------------------------------------------------------- -#define QS_BEGIN_PRE_(rec_, qsId_) \ - if (QS_GLB_CHECK_(rec_) && QS_LOC_CHECK_(qsId_)) { \ - QP::QS::beginRec_(static_cast(rec_)); -#define QS_END_PRE_() QP::QS::endRec_(); } - -#define QS_U8_PRE_(data_) \ - (QP::QS::u8_raw_(static_cast(data_))) -#define QS_2U8_PRE_(data1_, data2_) \ - (QP::QS::u8u8_raw_(static_cast(data1_), \ - static_cast(data2_))) -#define QS_U16_PRE_(data_) \ - (QP::QS::u16_raw_(static_cast(data_))) -#define QS_U32_PRE_(data_) \ - (QP::QS::u32_raw_(static_cast(data_))) -#define QS_STR_PRE_(msg_) (QP::QS::str_raw_(msg_)) -#define QS_OBJ_PRE_(obj_) (QP::QS::obj_raw_(obj_)) - -#if (!defined Q_SIGNAL_SIZE || (Q_SIGNAL_SIZE == 1U)) - #define QS_SIG_PRE_(sig_) \ - (QP::QS::u8_raw_(static_cast(sig_))) -#elif (Q_SIGNAL_SIZE == 2U) - #define QS_SIG_PRE_(sig_) \ - (QP::QS::u16_raw_(static_cast(sig_))) -#elif (Q_SIGNAL_SIZE == 4U) - #define QS_SIG_PRE_(sig_) \ - (QP::QS::u32_raw_(static_cast(sig_))) -#endif - -#if (!defined QS_FUN_PTR_SIZE || (QS_FUN_PTR_SIZE == 2U)) - #define QS_FUN_PRE_(fun_) \ - (QP::QS::u16_raw_(reinterpret_cast(fun_))) -#elif (QS_FUN_PTR_SIZE == 4U) - #define QS_FUN_PRE_(fun_) \ - (QP::QS::u32_raw_(reinterpret_cast(fun_))) -#elif (QS_FUN_PTR_SIZE == 8U) - #define QS_FUN_PRE_(fun_) \ - (QP::QS::u64_raw_(reinterpret_cast(fun_))) -#else - #define QS_FUN_PRE_(fun_) \ - (QP::QS::u32_raw_(reinterpret_cast(fun_))) -#endif - -//---------------------------------------------------------------------------- -#if (!defined QF_EQUEUE_CTR_SIZE || (QF_EQUEUE_CTR_SIZE == 1U)) - #define QS_EQC_PRE_(ctr_) \ - QP::QS::u8_raw_(static_cast(ctr_)) -#elif (QF_EQUEUE_CTR_SIZE == 2U) - #define QS_EQC_PRE_(ctr_) \ - QP::QS::u16_raw_(static_cast(ctr_)) -#elif (QF_EQUEUE_CTR_SIZE == 4U) - #define QS_EQC_PRE_(ctr_) \ - QP::QS::u32_raw_(static_cast(ctr_)) -#else - #error "QF_EQUEUE_CTR_SIZE not defined" -#endif - -#if (!defined QF_EVENT_SIZ_SIZE || (QF_EVENT_SIZ_SIZE == 1U)) - #define QS_EVS_PRE_(size_) \ - QP::QS::u8_raw_(static_cast(size_)) -#elif (QF_EVENT_SIZ_SIZE == 2U) - #define QS_EVS_PRE_(size_) \ - QP::QS::u16_raw_(static_cast(size_)) -#elif (QF_EVENT_SIZ_SIZE == 4U) - #define QS_EVS_PRE_(size_) \ - QP::QS::u32_raw_(static_cast(size_)) -#endif - -#if (!defined QF_MPOOL_SIZ_SIZE || (QF_MPOOL_SIZ_SIZE == 1U)) - #define QS_MPS_PRE_(size_) \ - QP::QS::u8_raw_(static_cast(size_)) -#elif (QF_MPOOL_SIZ_SIZE == 2U) - #define QS_MPS_PRE_(size_) \ - QP::QS::u16_raw_(static_cast(size_)) -#elif (QF_MPOOL_SIZ_SIZE == 4U) - #define QS_MPS_PRE_(size_) \ - QP::QS::u32_raw_(static_cast(size_)) -#endif - -#if (!defined QF_MPOOL_CTR_SIZE || (QF_MPOOL_CTR_SIZE == 1U)) - #define QS_MPC_PRE_(ctr_) \ - QP::QS::u8_raw_(static_cast(ctr_)) -#elif (QF_MPOOL_CTR_SIZE == 2U) - #define QS_MPC_PRE_(ctr_) \ - QP::QS::u16_raw_(static_cast(ctr_)) -#elif (QF_MPOOL_CTR_SIZE == 4U) - #define QS_MPC_PRE_(ctr_) \ - QP::QS::u32_raw_(static_cast(ctr_)) -#endif - -#if (!defined QF_TIMEEVT_CTR_SIZE || (QF_TIMEEVT_CTR_SIZE == 1U)) - #define QS_TEC_PRE_(ctr_) \ - QP::QS::u8_raw_(static_cast(ctr_)) -#elif (QF_TIMEEVT_CTR_SIZE == 2U) - #define QS_TEC_PRE_(ctr_) \ - QP::QS::u16_raw_(static_cast(ctr_)) -#elif (QF_TIMEEVT_CTR_SIZE == 4U) - #define QS_TEC_PRE_(ctr_) \ - QP::QS::u32_raw_(static_cast(ctr_)) -#endif - -#define QS_REC_NUM_(enum_) (static_cast(enum_)) - -//---------------------------------------------------------------------------- -#define QS_INSERT_BYTE_(b_) \ - buf[head] = (b_); \ - ++head; \ - if (head == end) { \ - head = 0U; \ - } - -#define QS_INSERT_ESC_BYTE_(b_) \ - chksum = static_cast(chksum + (b_)); \ - if (((b_) != QS_FRAME) && ((b_) != QS_ESC)) { \ - QS_INSERT_BYTE_(b_) \ - } \ - else { \ - QS_INSERT_BYTE_(QS_ESC) \ - QS_INSERT_BYTE_(static_cast((b_) ^ QS_ESC_XOR)) \ - priv_.used = priv_.used + 1U; \ - } - -//---------------------------------------------------------------------------- -#if (defined Q_UTEST) && (Q_UTEST != 0) -namespace QP { -namespace QS { - -void processTestEvts_(); - -} // namespace QS -} // namespace QP -#endif // Q_UTEST != 0 - -//! @endcond -//============================================================================ - -#endif // QS_PKG_HPP_ diff --git a/include/qstamp.hpp b/include/qstamp.hpp index d78bcb23d..dbf1f5655 100644 --- a/include/qstamp.hpp +++ b/include/qstamp.hpp @@ -3,17 +3,10 @@ // Model: qpcpp.qm // File: ${include::qstamp.hpp} // -// This code has been generated by QM 6.2.0 . +// This code has been generated by QM 7.0.0 . // DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. // -// This code is covered by the following QP license: -// License # : LicenseRef-QL-dual -// Issued to : Any user of the QP/C++ real-time embedded framework -// Framework(s) : qpcpp -// Support ends : 2025-12-31 -// License scope: -// -// Copyright (C) 2005 Quantum Leaps, LLC . +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // Q u a n t u m L e a P s // ------------------------ @@ -21,21 +14,20 @@ // // 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: +// 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. // -// Contact information: +// NOTE: +// The GPL does NOT permit the incorporation of this code into proprietary +// programs. Please contact Quantum Leaps for commercial licensing options, +// which expressly supersede the GPL and are designed explicitly for +// closed-source distribution. +// +// Quantum Leaps contact information: // // // diff --git a/include/qv.hpp b/include/qv.hpp index 3f83fe50e..ca4f21c20 100644 --- a/include/qv.hpp +++ b/include/qv.hpp @@ -3,17 +3,10 @@ // Model: qpcpp.qm // File: ${include::qv.hpp} // -// This code has been generated by QM 6.2.0 . +// This code has been generated by QM 7.0.0 . // DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. // -// This code is covered by the following QP license: -// License # : LicenseRef-QL-dual -// Issued to : Any user of the QP/C++ real-time embedded framework -// Framework(s) : qpcpp -// Support ends : 2025-12-31 -// License scope: -// -// Copyright (C) 2005 Quantum Leaps, LLC . +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // Q u a n t u m L e a P s // ------------------------ @@ -21,21 +14,20 @@ // // 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: +// 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. // -// Contact information: +// NOTE: +// The GPL does NOT permit the incorporation of this code into proprietary +// programs. Please contact Quantum Leaps for commercial licensing options, +// which expressly supersede the GPL and are designed explicitly for +// closed-source distribution. +// +// Quantum Leaps contact information: // // // @@ -94,8 +86,7 @@ void onIdle(); #define QF_SCHED_UNLOCK_() (static_cast(0)) //${QV-impl::QACTIVE_EQUEUE_WAIT_} ........................................... -#define QACTIVE_EQUEUE_WAIT_(me_) \ - Q_ASSERT_INCRIT(310, (me_)->m_eQueue.m_frontEvt != nullptr) +#define QACTIVE_EQUEUE_WAIT_(me_) (static_cast(0)) //${QV-impl::QACTIVE_EQUEUE_SIGNAL_} ......................................... #ifndef Q_UNSAFE diff --git a/include/qxk.hpp b/include/qxk.hpp deleted file mode 100644 index dc4b1e9a7..000000000 --- a/include/qxk.hpp +++ /dev/null @@ -1,342 +0,0 @@ -//$file${include::qxk.hpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// -// Model: qpcpp.qm -// File: ${include::qxk.hpp} -// -// This code has been generated by QM 6.2.0 . -// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. -// -// This code is covered by the following QP license: -// License # : LicenseRef-QL-dual -// Issued to : Any user of the QP/C++ real-time embedded framework -// Framework(s) : qpcpp -// Support ends : 2025-12-31 -// License scope: -// -// Copyright (C) 2005 Quantum Leaps, LLC . -// -// 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 -// -// 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: -// -// -// -//$endhead${include::qxk.hpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -#ifndef QXK_HPP_ -#define QXK_HPP_ - -//$declare${QXK::QSchedStatus} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { - -//${QXK::QSchedStatus} ....................................................... -using QSchedStatus = std::uint_fast16_t; - -} // namespace QP -//$enddecl${QXK::QSchedStatus} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -//$declare${QXK::QXTHREAD_NO_TIMEOUT} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { - -//${QXK::QXTHREAD_NO_TIMEOUT} ................................................ -constexpr QTimeEvtCtr QXTHREAD_NO_TIMEOUT {0U}; - -} // namespace QP -//$enddecl${QXK::QXTHREAD_NO_TIMEOUT} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -//$declare${QXK::QXK-base} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { -namespace QXK { - -//${QXK::QXK-base::onIdle} ................................................... -void onIdle(); - -//${QXK::QXK-base::schedLock} ................................................ -QSchedStatus schedLock(std::uint_fast8_t const ceiling) noexcept; - -//${QXK::QXK-base::schedUnlock} .............................................. -void schedUnlock(QSchedStatus const stat) noexcept; - -//${QXK::QXK-base::current} .................................................. -QP::QActive * current() noexcept; - -} // namespace QXK -} // namespace QP -//$enddecl${QXK::QXK-base} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -//$declare${QXK::QXThread} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { - -//${QXK::QXThread} ........................................................... -class QXThread : public QP::QActive { -private: - QTimeEvt m_timeEvt; - -public: - friend class QActive; - friend class QTimeEvt; - friend class QXSemaphore; - friend class QXMutex; - -public: - static constexpr QTimeEvtCtr QXTHREAD_NO_TIMEOUT{0U}; - -public: - QXThread( - QXThreadHandler const handler, - std::uint_fast8_t const tickRate = 0U) noexcept; - void init( - void const * const e, - std::uint_fast8_t const qsId) override; - void init(std::uint_fast8_t const qsId) override { - this->init(nullptr, qsId); - } - void dispatch( - QEvt const * const e, - std::uint_fast8_t const qsId) override; - QTimeEvt const * getTimeEvt() const noexcept { - return &m_timeEvt; - } - static bool delay(QTimeEvtCtr const nTicks) noexcept; - bool delayCancel() noexcept; - static QEvt const * queueGet(QTimeEvtCtr const nTicks = QXTHREAD_NO_TIMEOUT) noexcept; - -private: - void block_() const noexcept; - void unblock_() const noexcept; - static void timeout_(QActive * const act); - void teArm_( - enum_t const sig, - QTimeEvtCtr const nTicks) noexcept; - bool teDisarm_() noexcept; - void stackInit_( - QP::QXThreadHandler const handler, - void * const stkSto, - std::uint_fast16_t const stkSize) noexcept; -}; // class QXThread - -} // namespace QP -//$enddecl${QXK::QXThread} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -//$declare${QXK::QXSemaphore} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { - -//${QXK::QXSemaphore} ........................................................ -class QXSemaphore { -private: - QPSet m_waitSet; - std::uint8_t m_count; - std::uint8_t m_max_count; - -public: - void init( - std::uint_fast8_t const count, - std::uint_fast8_t const max_count = 0xFFU) noexcept; - bool wait(QTimeEvtCtr const nTicks = QXTHREAD_NO_TIMEOUT) noexcept; - bool tryWait() noexcept; - bool signal() noexcept; -}; // class QXSemaphore - -} // namespace QP -//$enddecl${QXK::QXSemaphore} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -//$declare${QXK::QXMutex} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { - -//${QXK::QXMutex} ............................................................ -class QXMutex { -private: - QActive m_ao; - QPSet m_waitSet; - -public: - QXMutex(); - void init(QPrioSpec const prioSpec) noexcept; - bool lock(QTimeEvtCtr const nTicks = QXTHREAD_NO_TIMEOUT) noexcept; - bool tryLock() noexcept; - void unlock() noexcept; -}; // class QXMutex - -} // namespace QP -//$enddecl${QXK::QXMutex} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -extern "C" { -//$declare${QXK-extern-C} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv - -//${QXK-extern-C::QXK_Attr} .................................................. -class QXK_Attr { -public: - QP::QActive * volatile curr; - QP::QActive * volatile next; - QP::QActive * volatile prev; - std::uint_fast8_t volatile actPrio; - std::uint_fast8_t volatile lockCeil; - std::uint_fast8_t volatile lockHolder; - QP::QPSet readySet; - -#ifndef Q_UNSAFE - QP::QPSet readySet_dis; -#endif // ndef Q_UNSAFE -}; // class QXK_Attr - -//${QXK-extern-C::QXK_priv_} ................................................. -extern QXK_Attr QXK_priv_; - -//${QXK-extern-C::QXK_sched_} ................................................ -std::uint_fast8_t QXK_sched_() noexcept; - -//${QXK-extern-C::QXK_activate_} ............................................. -void QXK_activate_() noexcept; - -//${QXK-extern-C::QXK_contextSw_} ............................................ -void QXK_contextSw_(QP::QActive * const next); - -//${QXK-extern-C::QXK_threadExit_} ........................................... -void QXK_threadExit_(); -//$enddecl${QXK-extern-C} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -} // extern "C" - -//============================================================================ -// interface used only for internal implementation, but not in applications -#ifdef QP_IMPL - -//$declare${QXK-impl} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv - -//${QXK-impl::QF_SCHED_STAT_} ................................................ -#define QF_SCHED_STAT_ QSchedStatus lockStat_; - -//${QXK-impl::QF_SCHED_LOCK_} ................................................ -#define QF_SCHED_LOCK_(ceil_) do { \ - if (QXK_ISR_CONTEXT_()) { \ - lockStat_ = 0xFFU; \ - } else { \ - lockStat_ = QXK::schedLock((ceil_)); \ - } \ -} while (false) - -//${QXK-impl::QF_SCHED_UNLOCK_} .............................................. -#define QF_SCHED_UNLOCK_() do { \ - if (lockStat_ != 0xFFU) { \ - QXK::schedUnlock(lockStat_); \ - } \ -} while (false) - -//${QXK-impl::QACTIVE_EQUEUE_WAIT_} .......................................... -// QXK native event queue waiting -#define QACTIVE_EQUEUE_WAIT_(me_) \ - Q_ASSERT_INCRIT(310, (me_)->m_eQueue.m_frontEvt != nullptr) - -//${QXK-impl::QACTIVE_EQUEUE_SIGNAL_} ........................................ -#ifndef Q_UNSAFE -// QXK native event queue signalling -#define QACTIVE_EQUEUE_SIGNAL_(me_) do { \ - QXK_priv_.readySet.insert( \ - static_cast((me_)->m_prio)); \ - QXK_priv_.readySet.update_(&QXK_priv_.readySet_dis); \ - if (!QXK_ISR_CONTEXT_()) { \ - if (QXK_sched_() != 0U) { \ - QXK_activate_(); \ - } \ - } \ -} while (false) -#endif // ndef Q_UNSAFE - -//${QXK-impl::QACTIVE_EQUEUE_SIGNAL_} ........................................ -#ifdef Q_UNSAFE -// QXK native event queue signalling -#define QACTIVE_EQUEUE_SIGNAL_(me_) do { \ - QXK_priv_.readySet.insert( \ - static_cast((me_)->m_prio)); \ - if (!QXK_ISR_CONTEXT_()) { \ - if (QXK_sched_() != 0U) { \ - QXK_activate_(); \ - } \ - } \ -} while (false) -#endif // def Q_UNSAFE - -//${QXK-impl::QXTHREAD_EQUEUE_SIGNAL_} ....................................... -#ifndef Q_UNSAFE -#define QXTHREAD_EQUEUE_SIGNAL_(me_) do { \ - if ((me_)->m_temp.obj == QXK_PTR_CAST_(QMState*, &(me_)->m_eQueue)) { \ - static_cast(QXTHREAD_CAST_(me_)->teDisarm_()); \ - QXK_priv_.readySet.insert( \ - static_cast((me_)->m_prio)); \ - QXK_priv_.readySet.update_(&QXK_priv_.readySet_dis); \ - if (!QXK_ISR_CONTEXT_()) { \ - static_cast(QXK_sched_()); \ - } \ - } \ -} while (false) -#endif // ndef Q_UNSAFE - -//${QXK-impl::QXTHREAD_EQUEUE_SIGNAL_} ....................................... -#ifdef Q_UNSAFE -#define QXTHREAD_EQUEUE_SIGNAL_(me_) do { \ - if ((me_)->m_temp.obj == QXK_PTR_CAST_(QMState*, &(me_)->m_eQueue)) { \ - static_cast(QXTHREAD_CAST_(me_)->teDisarm_()); \ - QXK_priv_.readySet.insert( \ - static_cast((me_)->m_prio)); \ - if (!QXK_ISR_CONTEXT_()) { \ - static_cast(QXK_sched_()); \ - } \ - } \ -} while (false) -#endif // def Q_UNSAFE - -//${QXK-impl::QXTHREAD_CAST_} ................................................ -#define QXTHREAD_CAST_(ptr_) (static_cast(ptr_)) - -//${QXK-impl::QXK_PTR_CAST_} ................................................. -#define QXK_PTR_CAST_(type_, ptr_) (reinterpret_cast(ptr_)) -//$enddecl${QXK-impl} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -//$declare${QF_EPOOL-impl} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv - -//${QF_EPOOL-impl::QF_EPOOL_TYPE_} ........................................... -#define QF_EPOOL_TYPE_ QMPool - -//${QF_EPOOL-impl::QF_EPOOL_INIT_} ........................................... -#define QF_EPOOL_INIT_(p_, poolSto_, poolSize_, evtSize_) \ - (p_).init((poolSto_), (poolSize_), (evtSize_)) - -//${QF_EPOOL-impl::QF_EPOOL_EVENT_SIZE_} ..................................... -#define QF_EPOOL_EVENT_SIZE_(p_) ((p_).getBlockSize()) - -//${QF_EPOOL-impl::QF_EPOOL_GET_} ............................................ -#define QF_EPOOL_GET_(p_, e_, m_, qsId_) \ - ((e_) = static_cast((p_).get((m_), (qsId_)))) - -//${QF_EPOOL-impl::QF_EPOOL_PUT_} ............................................ -#define QF_EPOOL_PUT_(p_, e_, qsId_) ((p_).put((e_), (qsId_))) -//$enddecl${QF_EPOOL-impl} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -namespace QP { -namespace QXK { -enum TimeoutSigs : QSignal { - DELAY_SIG = 1U, - TIMEOUT_SIG -}; -} // namespace QXK -} // namespace QP - -#endif // QP_IMPL - -#endif // QXK_HPP_ diff --git a/ports/CMakeLists.txt b/ports/CMakeLists.txt index 66ff6be7a..eb2ab3c9f 100644 --- a/ports/CMakeLists.txt +++ b/ports/CMakeLists.txt @@ -14,3 +14,7 @@ else() endif() add_subdirectory(${PORT_DIR}) +if(NOT QPCPP_CFG_QPCONFIG_H_INCLUDE_PATH) + set(QPCPP_CFG_QPCONFIG_H_INCLUDE_PATH config) +endif() +target_include_directories(qpcpp PUBLIC ${QPCPP_CFG_QPCONFIG_H_INCLUDE_PATH}) diff --git a/ports/README.md b/ports/README.md new file mode 100644 index 000000000..171c40e75 --- /dev/null +++ b/ports/README.md @@ -0,0 +1,63 @@ +# Files Missing from the QP/C GPL Distribution +Due to the growing non-compliance with the GPL as well as infringement +on the dual-licensing model of QP frameworks, the following files have +been **removed from the open-source GPL distribution**: + +``` +qpcpp +| +\---ports + +---arm-cm + | +---qxk + | | +---armclang + | | | qxk_port.cpp + | | | qp_port.hpp + | | | qs_port.hpp + | | | + | | +---config + | | | qp_config.hpp + | | | + | | +---gnu + | | | qxk_port.cpp + | | | qp_port.hpp + | | | qs_port.hpp + | | | + | | \---iar + | | qxk_port.cpp + | | qp_port.hpp + | | qs_port.hpp + | | + | \---qutest + | qp_port.hpp + | qs_port.hpp + | + +---posix-qutest + | qp_port.hpp + | qs_port.hpp + | qutest_port.cpp + | safe_std.hpp + | + \---win32-qutest + qp_port.hpp + qs_port.hpp + qutest_port.cpp + safe_std.hpp +``` + +> NOTE: These files are available to the [commercial licensees][com] with +current Support Term. Please contact [Quantum Leaps technical support][sup] +to get the complete QP/C++ framework distribution. + +# QP/C++ Framework Evaluation +To request **evaluation** of the complete QP/C++ framework, please contact +Quantum Leaps at: + +- https://www.state-machine.com/contact +- mailto:info@state-machine.com + +# Quantum Leaps Licensing: +To learn more about the open source and commercial licensing options: +- https://www.state-machine.com/licensing + + [com]: + [sup]: diff --git a/ports/arm-cm/qk/armclang/qk_port.cpp b/ports/arm-cm/qk/armclang/qk_port.cpp index f96c92cfb..23aad6d68 100644 --- a/ports/arm-cm/qk/armclang/qk_port.cpp +++ b/ports/arm-cm/qk/armclang/qk_port.cpp @@ -1,34 +1,33 @@ //============================================================================ // 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 // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC . -// // 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: +// 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. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2023-12-03 -//! @version Last updated for: @ref qpcpp_7_3_1 +//! @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 @@ -78,14 +77,17 @@ 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. // Additionally, the function also asserts that the interrupts are -// NOT disabled upon the entry to the function. -__attribute__ ((naked, weak)) void QF_int_disable_(void) { +// NOT disabled upon the entry to the function, which means that +// this interrupt management policy CANNOT nest. +__attribute__ ((naked, weak)) +void QF_int_disable_(void) { __asm volatile ( #if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK @@ -107,13 +109,16 @@ __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. // Additionally, the function also asserts that the interrupts ARE -// disabled upon the entry to the function. -__attribute__ ((naked, weak)) void QF_int_enable_(void) { +// 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 @@ -138,6 +143,7 @@ __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 @@ -145,11 +151,10 @@ __asm volatile ( // On ARMv7-M and higher, critical section is entered by disabling // interrupts *selectively* with the BASEPRI register. // Additionally, the function also asserts that the interrupts are -// NOT disabled upon the entry to the function. -// -// NOTE: -// The assertion means that this critical section CANNOT nest. -__attribute__ ((naked, weak)) void QF_crit_entry_(void) { +// NOT disabled upon the entry to the function, which means that +// this critical section CANNOT nest. +__attribute__ ((naked, weak)) +void QF_crit_entry_(void) { __asm volatile ( #if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK @@ -171,6 +176,7 @@ __asm volatile ( } //............................................................................ // Exit QF critical section. +// NOTE: this function must NOT use the stack. // // description: // On ARMv6-M, critical section is exited by enabling interrupts @@ -178,11 +184,10 @@ __asm volatile ( // On ARMv7-M and higher, critical section is exited by enabling // interrupts with the BASEPRI register. // Additionally, the function also asserts that the interrupts ARE -// disabled upon the entry to the function. -// -// NOTE: -// The assertion means that this critical section CANNOT nest. -__attribute__ ((naked, weak)) void QF_crit_exit_(void) { +// 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 @@ -219,8 +224,8 @@ __asm volatile ( // application programmer forgets to explicitly set priorities of all // "kernel aware" interrupts. // -// The interrupt priorities established in QK_init() can be later -// changed by the application-level code. +// NOTE: The IRQ priorities established in QK_init() can be later changed +// by the application-level code. void QK_init(void) { #if (__ARM_ARCH != 6) //--------- if ARMv7-M and higher... @@ -242,7 +247,11 @@ void QK_init(void) { #ifdef QK_USE_IRQ_NUM //--------- QK IRQ specified? // The QK port is configured to use a given ARM Cortex-M IRQ # // to return to thread mode (default is to use the NMI exception) - NVIC_IP[QK_USE_IRQ_NUM] = 0U; // priority 0 (highest) + + // clear the IRQ priority to 0 (highest) + NVIC_IP[QK_USE_IRQ_NUM >> 2U] &= ~(0xFFU << (8U*(QK_USE_IRQ_NUM & 3U))); + + // enable the IRQ NVIC_EN[QK_USE_IRQ_NUM >> 5U] = (1U << (QK_USE_IRQ_NUM & 0x1FU)); #endif //--------- QK IRQ specified @@ -255,17 +264,14 @@ void QK_init(void) { #endif //--------- VFP available } -//............................................................................ -// The PendSV_Handler exception is used for handling the asynchronous -// preemption in QK. The use of the PendSV exception is the recommended and -// the most efficient method for performing context switches with ARM Cortex-M. +//============================================================================ +// The PendSV exception is used for handling asynchronous preemption in QK. +// The use of the PendSV exception is the recommended and most efficient +// method for performing context switches in ARM Cortex-M. // // The PendSV exception should have the lowest priority in the whole system // (0xFF, see QK_init). All other exceptions and interrupts should have higher -// priority. For example, for NVIC with 2 priority bits all interrupts and -// exceptions must have numerical value of priority lower than 0xC0. In this -// case the interrupt priority levels available to your applications are (in -// the order from the lowest urgency to the highest urgency): 0x80, 0x40, 0x00. +// priority. // // Also, *all* "kernel aware" ISRs in the QK application must call the // QK_ISR_EXIT() macro, which triggers PendSV when it detects a need for @@ -326,84 +332,132 @@ __asm volatile ( //============================================================================ // QK_thread_ret is a helper function executed when the QXK activator returns. // -// NOTE: QK_thread_ret does not execute in the PendSV context! +// After the QK activator returns, we need to resume the preempted +// thread. However, this must be accomplished by a return-from-exception, +// while we are still in the *thread* context. The switching to the +// exception context is accomplished by triggering the NMI exception or +// the selected IRQ (if macro #QK_USE_IRQ_NUM is defined). +// // NOTE: QK_thread_ret is entered with interrupts DISABLED. +// NOTE: any function calls made from this code corrupt lr, but it is +// NOT used to return from QK_thread_ret(). Instead QK_thread_ret() +// "returns" by entering an exception (either NMI or IRQ). +// __attribute__ ((naked, used)) void QK_thread_ret(void) { -__asm volatile ( + __asm volatile ( +#ifdef QF_MEM_ISOLATE + " LDR r0,=QF_onMemApp \n" + " BLX r0 \n" // call QF_onMemApp() +#endif + +#if (__ARM_ARCH == 6) //--------- if ARMv6-M... + +#ifdef QK_USE_IRQ_NUM //--------- IRQ defined, use the specified IRQ + " LDR r0,=" STRINGIFY(NVIC_PEND + ((QK_USE_IRQ_NUM >> 5) << 2)) "\n" + " MOVS r1,#1 \n" + " LSLS r1,r1,#" STRINGIFY(QK_USE_IRQ_NUM & 0x1F) "\n" // r1 := IRQ bit + " STR r1,[r0] \n" // pend the IRQ - // After the QK activator returns, we need to resume the preempted - // thread. However, this must be accomplished by a return-from-exception, - // while we are still in the thread context. The switch to the exception - // context is accomplished by triggering the NMI exception or the selected - // IRQ (if macro #QK_USE_IRQ_NUM is defined). + " LDR r0,=QF_int_enable_ \n" + " BLX r0 \n" // enable interrupts with PRIMASK + // This code stops here and continues in the IRQ handler + +#else //--------- use the NMI (default) + " LDR r0,=" STRINGIFY(SCB_ICSR) "\n" // Interrupt Control and State + " MOVS r1,#1 \n" + " LSLS r1,r1,#31 \n" // r1 := (1 << 31) (NMI bit) + " STR r1,[r0] \n" // ICSR[31] := 1 (pend NMI) + // This code stops here and continues in the NMI handler + // NOTE: interrupts remain *disabled*. + +#endif //--------- use the NMI + +#else //--------- ARMv7-M and higher... + " CPSID i \n" // disable interrupts with PRIMASK + " LDR r0,=QF_int_enable_ \n" + " BLX r0 \n" // enable interrupts with BASEPRI + // NOTE: interrupts remain disabled with PRIMASK - // before triggering the NMI/IRQ, make sure that the VFP stack frame - // will NOT be used... #ifdef __ARM_FP //--------- if VFP available... - // make sure that the VFP stack frame will NOT be used + // make sure that the following IRQ/NMI will NOT use the VFP stack frame " MRS r0,CONTROL \n" // r0 := CONTROL " BICS r0,r0,#4 \n" // r0 := r0 & ~4 (FPCA bit) " MSR CONTROL,r0 \n" // CONTROL := r0 (clear CONTROL[2] FPCA bit) " ISB \n" // ISB after MSR CONTROL (ARM AN321,Sect.4.16) #endif //--------- VFP available -#ifdef QF_MEM_ISOLATE - " LDR r0,=QF_onMemApp \n" - " BLX r0 \n" // call QF_onMemApp() -#endif +#ifdef QK_USE_IRQ_NUM //--------- IRQ defined, use the specified IRQ + " LDR r0,=" STRINGIFY(NVIC_PEND + ((QK_USE_IRQ_NUM >> 5) << 2)) "\n" + " MOVS r1,#1 \n" + " LSLS r1,r1,#" STRINGIFY(QK_USE_IRQ_NUM & 0x1F) "\n" // r1 := IRQ bit + " STR r1,[r0] \n" // pend the IRQ + " CPSIE i \n" // enable interrupts with PRIMASK + // This code stops here and continues in the IRQ handler -#ifndef QK_USE_IRQ_NUM //--------- IRQ NOT defined, use NMI by default +#else //--------- use the NMI (default) " LDR r0,=" STRINGIFY(SCB_ICSR) "\n" // Interrupt Control and State " MOVS r1,#1 \n" " LSLS r1,r1,#31 \n" // r1 := (1 << 31) (NMI bit) " STR r1,[r0] \n" // ICSR[31] := 1 (pend NMI) + // NOTE: this code stops here and continues in the NMI handler + // NOTE: PRIMASK remains *disabled*. -#else //--------- use the selected IRQ - " LDR r0,=" STRINGIFY(NVIC_PEND + ((QK_USE_IRQ_NUM >> 5) << 2)) "\n" - " MOVS r1,#1 \n" - " LSLS r1,r1,#" STRINGIFY(QK_USE_IRQ_NUM & 0x1F) "\n" // r1 := IRQ bit - " STR r1,[r0] \n" // pend the IRQ +#endif //--------- use the NMI - // now enable interrupts so that pended IRQ can be entered - " LDR r0,=QF_int_enable_ \n" - " BLX r0 \n" // call QF_int_enable_() -#endif //--------- use IRQ +#endif //--------- ARMv7-M and higher - // NOTE! interrupts are still disabled when NMI is used - " B . \n" // wait for preemption by NMI/IRQ + // execution should *never* reach here, so the following code + // enters the Q_onError() error handler + " LDR r0,=QF_int_disable_ \n" + " BLX r0 \n" // call QF_int_disable_() + " LDR r0,=QF_port_module_ \n" + " MOVS r1,#121 \n" + " LDR r2,=Q_onError \n" + " BX r2 \n" ); } //============================================================================ -// This exception handler is used for returning back to the preempted thread. -// The exception handler simply removes its own interrupt stack frame from -// the stack (MSP) and returns to the preempted task using the interrupt -// stack frame that must be at the top of the stack. -__attribute__ ((naked)) -#ifndef QK_USE_IRQ_NUM //--------- IRQ NOT defined, use NMI by default +// The following exception handlers are used for returning back to the +// preempted *thread* context. -// NOTE: The NMI_Handler() is entered with interrupts still DISABLED! -void NMI_Handler(void) { -__asm volatile ( - // enable interrupts - " LDR r0,=QF_int_enable_ \n" - " BLX r0 \n" // call QF_int_enable_() -); - -#else //--------- use the selected IRQ +#ifdef QK_USE_IRQ_NUM //--------- IRQ defined, use the specified IRQ // NOTE: The IRQ Handler is entered with interrupts already ENABLED +__attribute__ ((naked)) void QK_USE_IRQ_HANDLER(void) { -#endif //--------- use IRQ +__asm volatile ( + " ADD sp,sp,#(8*4) \n" // remove one 8-register exception frame + " POP {r0,pc} \n" // pop stack aligner and EXC_RETURN to pc + // NOTE: this causes exception-return to the preempted *thread* context + ); +} - // ...continue here from either NMI_Handler() or IRQ_Handler() +#else //--------- IRQ NOT defined, use the NMI (default) + +// NOTE: The NMI_Handler() is entered with interrupts still DISABLED! +__attribute__ ((naked)) +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... + " 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 " POP {r0,pc} \n" // pop stack aligner and EXC_RETURN to pc ); + // NOTE: this causes exception-return to the preempted *thread* context } +#endif //--------- use the NMI + //============================================================================ #if (__ARM_ARCH == 6) // if ARMv6-M... diff --git a/ports/arm-cm/qk/armclang/qp_port.hpp b/ports/arm-cm/qk/armclang/qp_port.hpp index da11f8d2c..ecea1f76c 100644 --- a/ports/arm-cm/qk/armclang/qp_port.hpp +++ b/ports/arm-cm/qk/armclang/qp_port.hpp @@ -1,34 +1,34 @@ //============================================================================ // 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 // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC . -// // 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: +// 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. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2023-12-02 -//! @version Last updated for: @ref qpcpp_7_3_1 +//! @date Last updated on: 2024-09-30 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QP/C++ port to ARM Cortex-M, preemptive QK kernel, ARM-CLANG @@ -36,11 +36,8 @@ #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ -#include // Exact-width types. C++11 Standard - -#ifdef QP_CONFIG -#include "qp_config.hpp" // external QP configuration -#endif +#include // Exact-width types. C++11 Standard +#include "qp_config.hpp" // QP configuration from the application // no-return function specifier (C++11 Standard) #define Q_NORETURN [[ noreturn ]] void diff --git a/ports/arm-cm/qk/armclang/qs_port.hpp b/ports/arm-cm/qk/armclang/qs_port.hpp index 4ddb938b5..7da8a41ae 100644 --- a/ports/arm-cm/qk/armclang/qs_port.hpp +++ b/ports/arm-cm/qk/armclang/qs_port.hpp @@ -28,7 +28,7 @@ // //============================================================================ //! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_7_4_0 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler diff --git a/ports/arm-cm/qk/config/qp_config.hpp b/ports/arm-cm/qk/config/qp_config.hpp index 5d92c5bc8..ca1f1825f 100644 --- a/ports/arm-cm/qk/config/qp_config.hpp +++ b/ports/arm-cm/qk/config/qp_config.hpp @@ -1,32 +1,30 @@ //============================================================================ // QP configuration file (QK on ARM Cortex-M) -// Last updated for version: 7.4.0 -// Last updated on: 2024-06-06 +// +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // 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: +// 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. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ #ifndef QP_CONFIG_HPP_ @@ -34,17 +32,10 @@ //-------- <<< Use Configuration Wizard in Context Menu >>> ----------------- -// NOTE: Requires command-line macro: QP_CONFIG -// This qp_config.h header file is activated only when the macro -// QP_CONFIG is defined on the command-line to the compiler -// ------------------------------------------- - // QP API compatibility version (QP_API_VERSION) // <0=> 0 (Maximum compatibility) -// <580=>580 (QP 5.8.0 or newer) -// <660=>660 (QP 6.6.0 or newer) // <691=>691 (QP 6.9.1 or newer) -// <700=>700 (QP 7.0.0 or newer) +// <734=>7.3.4 (QP 7.3.4 or newer) // <9999=>9999 (Latest only) // QP API backwards compatibility with the QP/C API version. // Lower QP_API_VERSION values enable backwards compatibility @@ -132,6 +123,7 @@ // Event parameter initialization (QEVT_PAR_INIT) // Resource Acquisition Is Initialization (RAII) for dynamic events //#define QEVT_PAR_INIT +// // Provide destructors for QP classes // Destructors for classes @@ -162,7 +154,6 @@ // Event queue counter size (QF_EQUEUE_CTR_SIZE) // <1U=>1 (default) // <2U=>2 -// <4U=>4 // Size of event queue counter [bytes] // Default: 1 (255 events maximum in a queue) #define QF_EQUEUE_CTR_SIZE 1U @@ -215,7 +206,7 @@ //.......................................................................... // QK Preemptive Non-Blocking Kernel -// Preemptive non-blocking RTOS kernel. +// Preemptive non-blocking/blocking RTOS kernel. // Context switch callback (QF_ON_CONTEXT_SW) @@ -248,8 +239,8 @@ // If enabled, provide the otherwise unused IRQ number (QK_USE_IRQ_NUM) // and the corresponding IRQ handler name (QK_USE_IRQ_HANDLER) // in the "Text Editor" mode. -//#define QK_USE_IRQ_NUM 31 -//#define QK_USE_IRQ_HANDLER Reserved31_IRQHandler +//#define QK_USE_IRQ_NUM +//#define QK_USE_IRQ_HANDLER // // diff --git a/ports/arm-cm/qk/gnu/qk_port.cpp b/ports/arm-cm/qk/gnu/qk_port.cpp index ac5d907da..92e7d461d 100644 --- a/ports/arm-cm/qk/gnu/qk_port.cpp +++ b/ports/arm-cm/qk/gnu/qk_port.cpp @@ -1,34 +1,33 @@ //============================================================================ // 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 // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC . -// // 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: +// 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. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2024-01-30 -//! @version Last updated for: @ref qpcpp_7_3_3 +//! @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 @@ -71,20 +70,24 @@ void NMI_Handler(void); // For best performance, these functions are implemented in assembly, // but they can be implemented in C as well. + //std::int32_t volatile QF_int_lock_nest_; // not used extern char const QF_port_module_[]; char const QF_port_module_[] = "qk_port"; //............................................................................ // 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. // Additionally, the function also asserts that the interrupts are -// NOT disabled upon the entry to the function. -__attribute__ ((naked, weak)) void QF_int_disable_(void) { +// NOT disabled upon the entry to the function, which means that +// this interrupt management policy CANNOT nest. +__attribute__ ((naked, weak)) +void QF_int_disable_(void) { __asm volatile ( #if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK @@ -106,13 +109,16 @@ __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. // Additionally, the function also asserts that the interrupts ARE -// disabled upon the entry to the function. -__attribute__ ((naked, weak)) void QF_int_enable_(void) { +// 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 @@ -137,6 +143,7 @@ __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 @@ -144,11 +151,10 @@ __asm volatile ( // On ARMv7-M and higher, critical section is entered by disabling // interrupts *selectively* with the BASEPRI register. // Additionally, the function also asserts that the interrupts are -// NOT disabled upon the entry to the function. -// -// NOTE: -// The assertion means that this critical section CANNOT nest. -__attribute__ ((naked, weak)) void QF_crit_entry_(void) { +// NOT disabled upon the entry to the function, which means that +// this critical section CANNOT nest. +__attribute__ ((naked, weak)) +void QF_crit_entry_(void) { __asm volatile ( #if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK @@ -170,6 +176,7 @@ __asm volatile ( } //............................................................................ // Exit QF critical section. +// NOTE: this function must NOT use the stack. // // description: // On ARMv6-M, critical section is exited by enabling interrupts @@ -177,11 +184,10 @@ __asm volatile ( // On ARMv7-M and higher, critical section is exited by enabling // interrupts with the BASEPRI register. // Additionally, the function also asserts that the interrupts ARE -// disabled upon the entry to the function. -// -// NOTE: -// The assertion means that this critical section CANNOT nest. -__attribute__ ((naked, weak)) void QF_crit_exit_(void) { +// 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 @@ -218,8 +224,8 @@ __asm volatile ( // application programmer forgets to explicitly set priorities of all // "kernel aware" interrupts. // -// The interrupt priorities established in QK_init() can be later -// changed by the application-level code. +// NOTE: The IRQ priorities established in QK_init() can be later changed +// by the application-level code. void QK_init(void) { #if (__ARM_ARCH != 6) //--------- if ARMv7-M and higher... @@ -241,7 +247,11 @@ void QK_init(void) { #ifdef QK_USE_IRQ_NUM //--------- QK IRQ specified? // The QK port is configured to use a given ARM Cortex-M IRQ # // to return to thread mode (default is to use the NMI exception) - NVIC_IP[QK_USE_IRQ_NUM] = 0U; // priority 0 (highest) + + // clear the IRQ priority to 0 (highest) + NVIC_IP[QK_USE_IRQ_NUM >> 2U] &= ~(0xFFU << (8U*(QK_USE_IRQ_NUM & 3U))); + + // enable the IRQ NVIC_EN[QK_USE_IRQ_NUM >> 5U] = (1U << (QK_USE_IRQ_NUM & 0x1FU)); #endif //--------- QK IRQ specified @@ -254,17 +264,14 @@ void QK_init(void) { #endif //--------- VFP available } -//............................................................................ -// The PendSV_Handler exception is used for handling the asynchronous -// preemption in QK. The use of the PendSV exception is the recommended and -// the most efficient method for performing context switches with ARM Cortex-M. +//============================================================================ +// The PendSV exception is used for handling asynchronous preemption in QK. +// The use of the PendSV exception is the recommended and most efficient +// method for performing context switches in ARM Cortex-M. // // The PendSV exception should have the lowest priority in the whole system // (0xFF, see QK_init). All other exceptions and interrupts should have higher -// priority. For example, for NVIC with 2 priority bits all interrupts and -// exceptions must have numerical value of priority lower than 0xC0. In this -// case the interrupt priority levels available to your applications are (in -// the order from the lowest urgency to the highest urgency): 0x80, 0x40, 0x00. +// priority. // // Also, *all* "kernel aware" ISRs in the QK application must call the // QK_ISR_EXIT() macro, which triggers PendSV when it detects a need for @@ -282,7 +289,7 @@ void QK_init(void) { __attribute__ ((naked, optimize("-fno-stack-protector"))) void PendSV_Handler(void) { __asm volatile ( - " PUSH {r0,lr} \n" // save EXC_RETURN + stack-aligner + " PUSH {r0,lr} \n" // save stack-aligner + EXC_RETURN //<<<<<<<<<<<<<<<<<<<<<<< CRITICAL SECTION BEGIN <<<<<<<<<<<<<<<<<<<<<<<< " LDR r0,=QF_int_disable_ \n" @@ -330,84 +337,136 @@ __asm volatile ( //============================================================================ // QK_thread_ret is a helper function executed when the QXK activator returns. // -// NOTE: QK_thread_ret does not execute in the PendSV context! +// After the QK activator returns, we need to resume the preempted +// thread. However, this must be accomplished by a return-from-exception, +// while we are still in the *thread* context. The switching to the +// exception context is accomplished by triggering the NMI exception or +// the selected IRQ (if macro #QK_USE_IRQ_NUM is defined). +// // NOTE: QK_thread_ret is entered with interrupts DISABLED. -__attribute__ ((naked, used, optimize("-fno-stack-protector"))) +// NOTE: any function calls made from this code corrupt lr, but it is +// NOT used to return from QK_thread_ret(). Instead QK_thread_ret() +// "returns" by entering an exception (either NMI or IRQ). +// +// NOTE: +// The inline GNU assembler does not accept mnemonics MOVS, LSRS and ADDS, +// but for ARMv6-M the mnemonics MOV, LSR and ADD always set the condition +// flags in the PSR. +__attribute__ ((naked, used)) void QK_thread_ret(void) { -__asm volatile ( + __asm volatile ( +#ifdef QF_MEM_ISOLATE + " LDR r0,=QF_onMemApp \n" + " BLX r0 \n" // call QF_onMemApp() +#endif + +#if (__ARM_ARCH == 6) //--------- if ARMv6-M... + +#ifdef QK_USE_IRQ_NUM //--------- IRQ defined, use the specified IRQ + " LDR r0,=" STRINGIFY(NVIC_PEND + ((QK_USE_IRQ_NUM >> 5) << 2)) "\n" + " MOV r1,#1 \n" + " LSL r1,r1,#" STRINGIFY(QK_USE_IRQ_NUM & 0x1F) "\n" // r1 := IRQ bit + " STR r1,[r0] \n" // pend the IRQ + + " LDR r0,=QF_int_enable_ \n" + " BLX r0 \n" // enable interrupts with PRIMASK + // This code stops here and continues in the IRQ handler + +#else //--------- use the NMI (default) + " LDR r0,=" STRINGIFY(SCB_ICSR) "\n" // Interrupt Control and State + " MOV r1,#1 \n" + " LSL r1,r1,#31 \n" // r1 := (1 << 31) (NMI bit) + " STR r1,[r0] \n" // ICSR[31] := 1 (pend NMI) + // This code stops here and continues in the NMI handler + // NOTE: interrupts remain *disabled*. + +#endif //--------- use the NMI - // After the QK activator returns, we need to resume the preempted - // thread. However, this must be accomplished by a return-from-exception, - // while we are still in the thread context. The switch to the exception - // context is accomplished by triggering the NMI exception or the selected - // IRQ (if macro #QK_USE_IRQ_NUM is defined). +#else //--------- ARMv7-M and higher... + " CPSID i \n" // disable interrupts with PRIMASK + " LDR r0,=QF_int_enable_ \n" + " BLX r0 \n" // enable interrupts with BASEPRI + // NOTE: interrupts remain disabled with PRIMASK - // before triggering the NMI/IRQ, make sure that the VFP stack frame - // will NOT be used... #ifdef __ARM_FP //--------- if VFP available... - // make sure that the VFP stack frame will NOT be used + // make sure that the following IRQ/NMI will NOT use the VFP stack frame " MRS r0,CONTROL \n" // r0 := CONTROL " BIC r0,r0,#4 \n" // r0 := r0 & ~4 (FPCA bit) " MSR CONTROL,r0 \n" // CONTROL := r0 (clear CONTROL[2] FPCA bit) " ISB \n" // ISB after MSR CONTROL (ARM AN321,Sect.4.16) #endif //--------- VFP available -#ifdef QF_MEM_ISOLATE - " LDR r0,=QF_onMemApp \n" - " BLX r0 \n" // call QF_onMemApp() -#endif +#ifdef QK_USE_IRQ_NUM //--------- IRQ defined, use the specified IRQ + " LDR r0,=" STRINGIFY(NVIC_PEND + ((QK_USE_IRQ_NUM >> 5) << 2)) "\n" + " MOV r1,#1 \n" + " LSL r1,r1,#" STRINGIFY(QK_USE_IRQ_NUM & 0x1F) "\n" // r1 := IRQ bit + " STR r1,[r0] \n" // pend the IRQ + " CPSIE i \n" // enable interrupts with PRIMASK + // This code stops here and continues in the IRQ handler -#ifndef QK_USE_IRQ_NUM //--------- IRQ NOT defined, use NMI by default +#else //--------- use the NMI (default) " LDR r0,=" STRINGIFY(SCB_ICSR) "\n" // Interrupt Control and State " MOV r1,#1 \n" " LSL r1,r1,#31 \n" // r1 := (1 << 31) (NMI bit) " STR r1,[r0] \n" // ICSR[31] := 1 (pend NMI) + // NOTE: this code stops here and continues in the NMI handler + // NOTE: PRIMASK remains *disabled*. -#else //--------- use the selected IRQ - " LDR r0,=" STRINGIFY(NVIC_PEND + ((QK_USE_IRQ_NUM >> 5) << 2)) "\n" - " MOV r1,#1 \n" - " LSL r1,r1,#" STRINGIFY(QK_USE_IRQ_NUM & 0x1F) "\n" // r1 := IRQ bit - " STR r1,[r0] \n" // pend the IRQ +#endif //--------- use the NMI - // now enable interrupts so that pended IRQ can be entered - " LDR r0,=QF_int_enable_ \n" - " BLX r0 \n" // call QF_int_enable_() -#endif //--------- use IRQ +#endif //--------- ARMv7-M and higher - // NOTE! interrupts are still disabled when NMI is used - " B . \n" // wait for preemption by NMI/IRQ + // execution should *never* reach here, so the following code + // enters the Q_onError() error handler + " LDR r0,=QF_int_disable_ \n" + " BLX r0 \n" // call QF_int_disable_() + " LDR r0,=QF_port_module_ \n" + " MOV r1,#121 \n" + " LDR r2,=Q_onError \n" + " BX r2 \n" ); } //============================================================================ -// This exception handler is used for returning back to the preempted thread. -// The exception handler simply removes its own interrupt stack frame from -// the stack (MSP) and returns to the preempted task using the interrupt -// stack frame that must be at the top of the stack. -__attribute__ ((naked, optimize("-fno-stack-protector"))) -#ifndef QK_USE_IRQ_NUM //--------- IRQ NOT defined, use NMI by default - -// NOTE: The NMI_Handler() is entered with interrupts still DISABLED! -void NMI_Handler(void) { -__asm volatile ( - // enable interrupts - " LDR r0,=QF_int_enable_ \n" - " BLX r0 \n" // call QF_int_enable_() -); +// The following exception handlers are used for returning back to the +// preempted *thread* context. -#else //--------- use the selected IRQ +#ifdef QK_USE_IRQ_NUM //--------- IRQ defined, use the specified IRQ // NOTE: The IRQ Handler is entered with interrupts already ENABLED +__attribute__ ((naked)) void QK_USE_IRQ_HANDLER(void) { -#endif //--------- use IRQ +__asm volatile ( + " ADD sp,sp,#(8*4) \n" // remove one 8-register exception frame + " POP {r0,pc} \n" // pop stack aligner and EXC_RETURN to pc + // NOTE: this causes exception-return to the preempted *thread* context + ); +} + +#else //--------- IRQ NOT defined, use the NMI (default) - // ...continue here from either NMI_Handler() or IRQ_Handler() +// NOTE: The NMI_Handler() is entered with interrupts still DISABLED! +__attribute__ ((naked)) +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... + " 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 " POP {r0,pc} \n" // pop stack aligner and EXC_RETURN to pc ); + // NOTE: this causes exception-return to the preempted *thread* context } +#endif //--------- use the NMI + //============================================================================ #if (__ARM_ARCH == 6) // if ARMv6-M... diff --git a/ports/arm-cm/qk/gnu/qp_port.hpp b/ports/arm-cm/qk/gnu/qp_port.hpp index 911caaf13..a10a94ce8 100644 --- a/ports/arm-cm/qk/gnu/qp_port.hpp +++ b/ports/arm-cm/qk/gnu/qp_port.hpp @@ -1,34 +1,34 @@ //============================================================================ // 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 // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC . -// // 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: +// 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. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2023-12-03 -//! @version Last updated for: @ref qpcpp_7_3_1 +//! @date Last updated on: 2024-09-30 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QP/C++ port to ARM Cortex-M, preemptive QK kernel, GNU-ARM @@ -36,11 +36,8 @@ #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ -#include // Exact-width types. C++11 Standard - -#ifdef QP_CONFIG -#include "qp_config.hpp" // external QP configuration -#endif +#include // Exact-width types. C++11 Standard +#include "qp_config.hpp" // QP configuration from the application // no-return function specifier (C++11 Standard) #define Q_NORETURN [[ noreturn ]] void diff --git a/ports/arm-cm/qk/gnu/qs_port.hpp b/ports/arm-cm/qk/gnu/qs_port.hpp index 4ddb938b5..7da8a41ae 100644 --- a/ports/arm-cm/qk/gnu/qs_port.hpp +++ b/ports/arm-cm/qk/gnu/qs_port.hpp @@ -28,7 +28,7 @@ // //============================================================================ //! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_7_4_0 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler diff --git a/ports/arm-cm/qk/iar/qk_port.cpp b/ports/arm-cm/qk/iar/qk_port.cpp index a64f74f2f..d26ab4485 100644 --- a/ports/arm-cm/qk/iar/qk_port.cpp +++ b/ports/arm-cm/qk/iar/qk_port.cpp @@ -1,34 +1,33 @@ //============================================================================ // 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 // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC . -// // 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: +// 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. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2023-12-03 -//! @version Last updated for: @ref qpcpp_7_3_1 +//! @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 @@ -82,13 +81,16 @@ 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. // Additionally, the function also asserts that the interrupts are -// NOT disabled upon the entry to the function. +// 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? @@ -111,12 +113,15 @@ __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. // Additionally, the function also asserts that the interrupts ARE -// disabled upon the entry to the function. +// 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? @@ -142,6 +147,7 @@ __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 @@ -149,10 +155,9 @@ __asm volatile ( // On ARMv7-M and higher, critical section is entered by disabling // interrupts *selectively* with the BASEPRI register. // Additionally, the function also asserts that the interrupts are -// NOT disabled upon the entry to the function. -// -// NOTE: -// The assertion means that this critical section CANNOT nest. +// 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? @@ -175,6 +180,7 @@ __asm volatile ( } //............................................................................ // Exit QF critical section. +// NOTE: this function must NOT use the stack. // // description: // On ARMv6-M, critical section is exited by enabling interrupts @@ -182,10 +188,9 @@ __asm volatile ( // On ARMv7-M and higher, critical section is exited by enabling // interrupts with the BASEPRI register. // Additionally, the function also asserts that the interrupts ARE -// disabled upon the entry to the function. -// -// NOTE: -// The assertion means that this critical section CANNOT nest. +// 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? @@ -223,8 +228,8 @@ __asm volatile ( // application programmer forgets to explicitly set priorities of all // "kernel aware" interrupts. // -// The interrupt priorities established in QK_init() can be later -// changed by the application-level code. +// NOTE: The IRQ priorities established in QK_init() can be later changed +// by the application-level code. void QK_init(void) { #if (__ARM_ARCH != 6) //--------- if ARMv7-M and higher... @@ -246,7 +251,11 @@ void QK_init(void) { #ifdef QK_USE_IRQ_NUM //--------- QK IRQ specified? // The QK port is configured to use a given ARM Cortex-M IRQ # // to return to thread mode (default is to use the NMI exception) - NVIC_IP[QK_USE_IRQ_NUM] = 0U; // priority 0 (highest) + + // clear the IRQ priority to 0 (highest) + NVIC_IP[QK_USE_IRQ_NUM >> 2U] &= ~(0xFFU << (8U*(QK_USE_IRQ_NUM & 3U))); + + // enable the IRQ NVIC_EN[QK_USE_IRQ_NUM >> 5U] = (1U << (QK_USE_IRQ_NUM & 0x1FU)); #endif //--------- QK IRQ specified @@ -259,17 +268,14 @@ void QK_init(void) { #endif //--------- VFP available } -//............................................................................ -// The PendSV_Handler exception is used for handling the asynchronous -// preemption in QK. The use of the PendSV exception is the recommended and -// the most efficient method for performing context switches with ARM Cortex-M. +//============================================================================ +// The PendSV exception is used for handling asynchronous preemption in QK. +// The use of the PendSV exception is the recommended and most efficient +// method for performing context switches in ARM Cortex-M. // // The PendSV exception should have the lowest priority in the whole system // (0xFF, see QK_init). All other exceptions and interrupts should have higher -// priority. For example, for NVIC with 2 priority bits all interrupts and -// exceptions must have numerical value of priority lower than 0xC0. In this -// case the interrupt priority levels available to your applications are (in -// the order from the lowest urgency to the highest urgency): 0x80, 0x40, 0x00. +// priority. // // Also, *all* "kernel aware" ISRs in the QK application must call the // QK_ISR_EXIT() macro, which triggers PendSV when it detects a need for @@ -330,88 +336,137 @@ __asm volatile ( //============================================================================ // QK_thread_ret is a helper function executed when the QXK activator returns. // -// NOTE: QK_thread_ret does not execute in the PendSV context! +// After the QK activator returns, we need to resume the preempted +// thread. However, this must be accomplished by a return-from-exception, +// while we are still in the *thread* context. The switching to the +// exception context is accomplished by triggering the NMI exception or +// the selected IRQ (if macro #QK_USE_IRQ_NUM is defined). +// // NOTE: QK_thread_ret is entered with interrupts DISABLED. +// NOTE: any function calls made from this code corrupt lr, but it is +// NOT used to return from QK_thread_ret(). Instead QK_thread_ret() +// "returns" by entering an exception (either NMI or IRQ). +// __stackless void QK_thread_ret(void) { -__asm volatile ( + __asm volatile ( +#ifdef QF_MEM_ISOLATE + " LDR r0,=QF_onMemApp \n" + " BLX r0 \n" // call QF_onMemApp() +#endif + +#if (__ARM_ARCH == 6) //--------- if ARMv6-M... + +#ifdef QK_USE_IRQ_NUM //--------- IRQ defined, use the specified IRQ + " LDR r0,=" STRINGIFY(NVIC_PEND + ((QK_USE_IRQ_NUM >> 5) << 2)) "\n" + " MOVS r1,#1 \n" + " LSLS r1,r1,#" STRINGIFY(QK_USE_IRQ_NUM & 0x1F) "\n" // r1 := IRQ bit + " STR r1,[r0] \n" // pend the IRQ + + " LDR r0,=QF_int_enable_ \n" + " BLX r0 \n" // enable interrupts with PRIMASK + // This code stops here and continues in the IRQ handler + +#else //--------- use the NMI (default) + " LDR r0,=" STRINGIFY(SCB_ICSR) "\n" // Interrupt Control and State + " MOVS r1,#1 \n" + " LSLS r1,r1,#31 \n" // r1 := (1 << 31) (NMI bit) + " STR r1,[r0] \n" // ICSR[31] := 1 (pend NMI) + // This code stops here and continues in the NMI handler + // NOTE: interrupts remain *disabled*. + +#endif //--------- use the NMI - // After the QK activator returns, we need to resume the preempted - // thread. However, this must be accomplished by a return-from-exception, - // while we are still in the thread context. The switch to the exception - // context is accomplished by triggering the NMI exception or the selected - // IRQ (if macro #QK_USE_IRQ_NUM is defined). +#else //--------- ARMv7-M and higher... + " CPSID i \n" // disable interrupts with PRIMASK + " LDR r0,=QF_int_enable_ \n" + " BLX r0 \n" // enable interrupts with BASEPRI + // NOTE: interrupts remain disabled with PRIMASK - // before triggering the NMI/IRQ, make sure that the VFP stack frame - // will NOT be used... #ifdef __ARM_FP //--------- if VFP available... - // make sure that the VFP stack frame will NOT be used + // make sure that the following IRQ/NMI will NOT use the VFP stack frame " MRS r0,CONTROL \n" // r0 := CONTROL " BICS r0,r0,#4 \n" // r0 := r0 & ~4 (FPCA bit) " MSR CONTROL,r0 \n" // CONTROL := r0 (clear CONTROL[2] FPCA bit) " ISB \n" // ISB after MSR CONTROL (ARM AN321,Sect.4.16) #endif //--------- VFP available -#ifdef QF_MEM_ISOLATE - " LDR r0,=QF_onMemApp \n" - " BLX r0 \n" // call QF_onMemApp() -#endif +#ifdef QK_USE_IRQ_NUM //--------- IRQ defined, use the specified IRQ + " LDR r0,=" STRINGIFY(NVIC_PEND + ((QK_USE_IRQ_NUM >> 5) << 2)) "\n" + " MOVS r1,#1 \n" + " LSLS r1,r1,#" STRINGIFY(QK_USE_IRQ_NUM & 0x1F) "\n" // r1 := IRQ bit + " STR r1,[r0] \n" // pend the IRQ + " CPSIE i \n" // enable interrupts with PRIMASK + // This code stops here and continues in the IRQ handler -#ifndef QK_USE_IRQ_NUM //--------- IRQ NOT defined, use NMI by default +#else //--------- use the NMI (default) " LDR r0,=" STRINGIFY(SCB_ICSR) "\n" // Interrupt Control and State " MOVS r1,#1 \n" " LSLS r1,r1,#31 \n" // r1 := (1 << 31) (NMI bit) " STR r1,[r0] \n" // ICSR[31] := 1 (pend NMI) + // NOTE: this code stops here and continues in the NMI handler + // NOTE: PRIMASK remains *disabled*. -#else //--------- use the selected IRQ - " LDR r0,=" STRINGIFY(NVIC_PEND + ((QK_USE_IRQ_NUM >> 5) << 2)) "\n" - " MOVS r1,#1 \n" - " LSLS r1,r1,#" STRINGIFY(QK_USE_IRQ_NUM & 0x1F) "\n" // r1 := IRQ bit - " STR r1,[r0] \n" // pend the IRQ +#endif //--------- use the NMI - // now enable interrupts so that pended IRQ can be entered - " LDR r0,=QF_int_enable_ \n" - " BLX r0 \n" // call QF_int_enable_() -#endif //--------- use IRQ +#endif //--------- ARMv7-M and higher - // NOTE! interrupts are still disabled when NMI is used - " B . \n" // wait for preemption by NMI/IRQ + // execution should *never* reach here, so the following code + // enters the Q_onError() error handler + " LDR r0,=QF_int_disable_ \n" + " BLX r0 \n" // call QF_int_disable_() + " LDR r0,=QF_port_module_ \n" + " MOVS r1,#121 \n" + " LDR r2,=Q_onError \n" + " BX r2 \n" ); } //============================================================================ -// This exception handler is used for returning back to the preempted thread. -// The exception handler simply removes its own interrupt stack frame from -// the stack (MSP) and returns to the preempted task using the interrupt -// stack frame that must be at the top of the stack. -__stackless -#ifndef QK_USE_IRQ_NUM //--------- IRQ NOT defined, use NMI by default - -// NOTE: The NMI_Handler() is entered with interrupts still DISABLED! -void NMI_Handler(void) { -__asm volatile ( - // enable interrupts - " LDR r0,=QF_int_enable_ \n" - " BLX r0 \n" // call QF_int_enable_() -); +// The following exception handlers are used for returning back to the +// preempted *thread* context. -#else //--------- use the selected IRQ +#ifdef QK_USE_IRQ_NUM //--------- IRQ defined, use the specified IRQ // NOTE: The IRQ Handler is entered with interrupts already ENABLED +__stackless void QK_USE_IRQ_HANDLER(void) { -#endif //--------- use IRQ +__asm volatile ( + " ADD sp,sp,#(8*4) \n" // remove one 8-register exception frame + " POP {r0,pc} \n" // pop stack aligner and EXC_RETURN to pc + // NOTE: this causes exception-return to the preempted *thread* context + ); +} - // ...continue here from either NMI_Handler() or IRQ_Handler() +#else //--------- IRQ NOT defined, use the NMI (default) + +// NOTE: The NMI_Handler() is entered with interrupts still DISABLED! +__stackless +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... + " 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 " POP {r0,pc} \n" // pop stack aligner and EXC_RETURN to pc ); + // NOTE: this causes exception-return to the preempted *thread* context } +#endif //--------- use the NMI + //============================================================================ #if (__ARM_ARCH == 6) // if ARMv6-M... // hand-optimized quick LOG2 in assembly (no CLZ instruction in ARMv6-M) +__stackless uint_fast8_t QF_qlog2(uint32_t x) { static uint8_t const log2LUT[16] = { 0U, 1U, 2U, 2U, 3U, 3U, 3U, 3U, diff --git a/ports/arm-cm/qk/iar/qp_port.hpp b/ports/arm-cm/qk/iar/qp_port.hpp index c34f3a139..d9e902156 100644 --- a/ports/arm-cm/qk/iar/qp_port.hpp +++ b/ports/arm-cm/qk/iar/qp_port.hpp @@ -1,34 +1,34 @@ //============================================================================ // 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 // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC . -// // 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: +// 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. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2023-12-03 -//! @version Last updated for: @ref qpcpp_7_3_1 +//! @date Last updated on: 2024-09-30 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QP/C++ port to ARM Cortex-M, preemptive QK kernel, IAR-ARM @@ -36,12 +36,9 @@ #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ -#include // Exact-width types. C++11 Standard -#include // IAR intrinsic functions - -#ifdef QP_CONFIG -#include "qp_config.hpp" // external QP configuration -#endif +#include // Exact-width types. C++11 Standard +#include // IAR intrinsic functions +#include "qp_config.hpp" // QP configuration from the application // no-return function specifier (C++11 Standard) #define Q_NORETURN [[ noreturn ]] void diff --git a/ports/arm-cm/qk/iar/qs_port.hpp b/ports/arm-cm/qk/iar/qs_port.hpp index 4ddb938b5..7da8a41ae 100644 --- a/ports/arm-cm/qk/iar/qs_port.hpp +++ b/ports/arm-cm/qk/iar/qs_port.hpp @@ -28,7 +28,7 @@ // //============================================================================ //! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_7_4_0 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler diff --git a/ports/arm-cm/qutest/qp_port.hpp b/ports/arm-cm/qutest/qp_port.hpp deleted file mode 100644 index 865c8a29f..000000000 --- a/ports/arm-cm/qutest/qp_port.hpp +++ /dev/null @@ -1,100 +0,0 @@ -//============================================================================ -// QP/C++ Real-Time Embedded Framework (RTEF) -// Copyright (C) 2005 Quantum Leaps, LLC . -// -// 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 qpcpp_7_3_0 -//! -//! @file -//! @brief QP/C "port" for QUTEST unit test harness, generic C99 - -#ifndef QP_PORT_HPP_ -#define QP_PORT_HPP_ - -#include // Exact-width types. C++11 Standard - -#ifdef QP_CONFIG -#include "qp_config.hpp" // external QP configuration -#endif - -// no-return function specifier (C++11 Standard) -#define Q_NORETURN [[ noreturn ]] void - -// QUTest event queue and thread types -#define QACTIVE_EQUEUE_TYPE QEQueue -// QACTIVE_OS_OBJ_TYPE not used in this port -// QACTIVE_THREAD_TYPE not used in this port - -// QF interrupt disable/enable -#define QF_INT_DISABLE() (++QP::QS::tstPriv_.intLock) -#define QF_INT_ENABLE() (--QP::QS::tstPriv_.intLock) - -// QF critical section -#define QF_CRIT_STAT -#define QF_CRIT_ENTRY() QF_INT_DISABLE() -#define QF_CRIT_EXIT() QF_INT_ENABLE() - -// QF_LOG2 not defined -- use the internal LOG2() implementation - -// include files ------------------------------------------------------------- -#include "qequeue.hpp" // QUTest port uses QEQueue event-queue -#include "qmpool.hpp" // QUTest port uses QMPool memory-pool -#include "qp.hpp" // QP platform-independent public interface - -//============================================================================ -// interface used only inside QF implementation, but not in applications -#ifdef QP_IMPL - - // QUTest scheduler locking (not used) - #define QF_SCHED_STAT_ - - #define QF_SCHED_LOCK_(dummy) (static_cast(0)) - #define QF_SCHED_UNLOCK_() (static_cast(0)) - - // native event queue operations - #define QACTIVE_EQUEUE_WAIT_(me_) \ - Q_ASSERT_INCRIT(310, (me_)->m_eQueue.m_frontEvt != nullptr) - -#ifndef Q_UNSAFE - #define QACTIVE_EQUEUE_SIGNAL_(me_) \ - QS::tstPriv_.readySet.insert((me_)->m_prio); \ - QS::tstPriv_.readySet.update_(&QS::tstPriv_.readySet_dis) -#else - #define QACTIVE_EQUEUE_SIGNAL_(me_) \ - (QS::tstPriv_.readySet.insert((me_)->m_prio)) -#endif - - // native QF event pool operations - #define QF_EPOOL_TYPE_ QMPool - #define QF_EPOOL_INIT_(p_, poolSto_, poolSize_, evtSize_) \ - (p_).init((poolSto_), (poolSize_), (evtSize_)) - - #define QF_EPOOL_EVENT_SIZE_(p_) ((p_).getBlockSize()) - #define QF_EPOOL_GET_(p_, e_, m_, qsId_) \ - ((e_) = static_cast((p_).get((m_), (qsId_)))) - #define QF_EPOOL_PUT_(p_, e_, qsId_) ((p_).put((e_), (qsId_))) - -#endif // QP_IMPL - -#endif // QP_PORT_HPP_ - diff --git a/ports/arm-cm/qutest/qs_port.hpp b/ports/arm-cm/qutest/qs_port.hpp deleted file mode 100644 index 4ddb938b5..000000000 --- a/ports/arm-cm/qutest/qs_port.hpp +++ /dev/null @@ -1,57 +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: 2024-06-06 -//! @version Last updated for: @ref qpcpp_7_4_0 -//! -//! @file -//! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler - -#ifndef QS_PORT_HPP_ -#define QS_PORT_HPP_ - -// 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.hpp" -// *before* "qs.hpp". -#ifndef QP_PORT_HPP_ -#include "qp_port.hpp" // use QS with QP -#endif - -#include "qs.hpp" // QS platform-independent public interface - -#endif // QS_PORT_HPP_ diff --git a/ports/arm-cm/qv/armclang/qp_port.hpp b/ports/arm-cm/qv/armclang/qp_port.hpp index 557e314f1..ace56dd2f 100644 --- a/ports/arm-cm/qv/armclang/qp_port.hpp +++ b/ports/arm-cm/qv/armclang/qp_port.hpp @@ -1,34 +1,34 @@ //============================================================================ // 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 // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC . -// // 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: +// 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. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2023-12-03 -//! @version Last updated for: @ref qpcpp_7_3_1 +//! @date Last updated on: 2024-09-30 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QF/C++ port to ARM Cortex-M, cooperative QV kernel, ARM-CLANG @@ -36,11 +36,8 @@ #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ -#include // Exact-width types. C++11 Standard - -#ifdef QP_CONFIG -#include "qp_config.hpp" // external QP configuration -#endif +#include // Exact-width types. C++11 Standard +#include "qp_config.hpp" // QP configuration from the application // no-return function specifier (C++11 Standard) #define Q_NORETURN [[ noreturn ]] void @@ -114,10 +111,9 @@ #if (__ARM_ARCH == 6) // ARMv6-M? // macro to put the CPU to sleep inside QV_onIdle() - #define QV_CPU_SLEEP() do { \ + #define QV_CPU_SLEEP() do { \ __asm volatile ("wfi"::: "memory"); \ - QF_MEM_APP(); \ - QF_INT_ENABLE(); \ + QF_INT_ENABLE(); \ } while (false) #define QV_ARM_ERRATUM_838869() ((void)0) @@ -125,11 +121,10 @@ #else // ARMv7-M or higher // macro to put the CPU to sleep inside QV_onIdle() - #define QV_CPU_SLEEP() do { \ + #define QV_CPU_SLEEP() do { \ __asm volatile ("cpsid i" ::: "memory"); \ - QF_MEM_APP(); \ - QF_INT_ENABLE(); \ - __asm volatile ("wfi" ::: "memory"); \ + QF_INT_ENABLE(); \ + __asm volatile ("wfi" ::: "memory"); \ __asm volatile ("cpsie i" ::: "memory"); \ } while (false) diff --git a/ports/arm-cm/qv/armclang/qs_port.hpp b/ports/arm-cm/qv/armclang/qs_port.hpp index 4ddb938b5..7da8a41ae 100644 --- a/ports/arm-cm/qv/armclang/qs_port.hpp +++ b/ports/arm-cm/qv/armclang/qs_port.hpp @@ -28,7 +28,7 @@ // //============================================================================ //! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_7_4_0 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler diff --git a/ports/arm-cm/qv/armclang/qv_port.cpp b/ports/arm-cm/qv/armclang/qv_port.cpp index 3d0bdf86d..de2635878 100644 --- a/ports/arm-cm/qv/armclang/qv_port.cpp +++ b/ports/arm-cm/qv/armclang/qv_port.cpp @@ -1,34 +1,33 @@ //============================================================================ // 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 // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC . -// // 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: +// 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. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2023-12-03 -//! @version Last updated for: @ref qpcpp_7_3_1 +//! @date Last updated on: 2024-09-30 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QV/C++ port to ARM Cortex-M, ARM-CLANG @@ -66,14 +65,17 @@ 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. // Additionally, the function also asserts that the interrupts are -// NOT disabled upon the entry to the function. -__attribute__ ((naked, weak)) void QF_int_disable_(void) { +// NOT disabled upon the entry to the function, which means that +// this interrupt management policy CANNOT nest. +__attribute__ ((naked, weak)) +void QF_int_disable_(void) { __asm volatile ( #if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK @@ -95,13 +97,16 @@ __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. // Additionally, the function also asserts that the interrupts ARE -// disabled upon the entry to the function. -__attribute__ ((naked, weak)) void QF_int_enable_(void) { +// 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 @@ -126,6 +131,7 @@ __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 @@ -133,11 +139,10 @@ __asm volatile ( // On ARMv7-M and higher, critical section is entered by disabling // interrupts *selectively* with the BASEPRI register. // Additionally, the function also asserts that the interrupts are -// NOT disabled upon the entry to the function. -// -// NOTE: -// The assertion means that this critical section CANNOT nest. -__attribute__ ((naked, weak)) void QF_crit_entry_(void) { +// NOT disabled upon the entry to the function, which means that +// this critical section CANNOT nest. +__attribute__ ((naked, weak)) +void QF_crit_entry_(void) { __asm volatile ( #if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK @@ -159,6 +164,7 @@ __asm volatile ( } //............................................................................ // Exit QF critical section. +// NOTE: this function must NOT use the stack. // // description: // On ARMv6-M, critical section is exited by enabling interrupts @@ -166,11 +172,10 @@ __asm volatile ( // On ARMv7-M and higher, critical section is exited by enabling // interrupts with the BASEPRI register. // Additionally, the function also asserts that the interrupts ARE -// disabled upon the entry to the function. -// -// NOTE: -// The assertion means that this critical section CANNOT nest. -__attribute__ ((naked, weak)) void QF_crit_exit_(void) { +// 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 @@ -207,8 +212,8 @@ __asm volatile ( // application programmer forgets to explicitly set priorities of all // "kernel aware" interrupts. // -// The interrupt priorities established in QV_init() can be later -// changed by the application-level code. +// NOTE: The IRQ priorities established in QV_init() can be later changed +// by the application-level code. void QV_init(void) { #if (__ARM_ARCH != 6) //--------- if ARMv7-M and higher... diff --git a/ports/arm-cm/qv/config/qp_config.hpp b/ports/arm-cm/qv/config/qp_config.hpp index b47fcfd26..5c7131892 100644 --- a/ports/arm-cm/qv/config/qp_config.hpp +++ b/ports/arm-cm/qv/config/qp_config.hpp @@ -1,32 +1,30 @@ //============================================================================ // QP configuration file (QV on ARM Cortex-M) -// Last updated for version: 7.4.0 -// Last updated on: 2024-06-06 +// +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // 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: +// 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. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ #ifndef QP_CONFIG_HPP_ @@ -34,17 +32,10 @@ //-------- <<< Use Configuration Wizard in Context Menu >>> ----------------- -// NOTE: Requires command-line macro: QP_CONFIG -// This qp_config.h header file is activated only when the macro -// QP_CONFIG is defined on the command-line to the compiler -// ------------------------------------------- - // QP API compatibility version (QP_API_VERSION) // <0=> 0 (Maximum compatibility) -// <580=>580 (QP 5.8.0 or newer) -// <660=>660 (QP 6.6.0 or newer) // <691=>691 (QP 6.9.1 or newer) -// <700=>700 (QP 7.0.0 or newer) +// <734=>7.3.4 (QP 7.3.4 or newer) // <9999=>9999 (Latest only) // QP API backwards compatibility with the QP/C API version. // Lower QP_API_VERSION values enable backwards compatibility @@ -132,6 +123,7 @@ // Event parameter initialization (QEVT_PAR_INIT) // Resource Acquisition Is Initialization (RAII) for dynamic events //#define QEVT_PAR_INIT +// // Provide destructors for QP classes // Destructors for classes @@ -162,7 +154,6 @@ // Event queue counter size (QF_EQUEUE_CTR_SIZE) // <1U=>1 (default) // <2U=>2 -// <4U=>4 // Size of event queue counter [bytes] // Default: 1 (255 events maximum in a queue) #define QF_EQUEUE_CTR_SIZE 1U diff --git a/ports/arm-cm/qv/gnu/qp_port.hpp b/ports/arm-cm/qv/gnu/qp_port.hpp index e30b21d42..f10499b9a 100644 --- a/ports/arm-cm/qv/gnu/qp_port.hpp +++ b/ports/arm-cm/qv/gnu/qp_port.hpp @@ -1,34 +1,34 @@ //============================================================================ // 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 // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC . -// // 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: +// 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. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2023-12-02 -//! @version Last updated for: @ref qpcpp_7_3_1 +//! @date Last updated on: 2024-09-30 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief Qp/C++ port to ARM Cortex-M, cooperative QV kernel, GNU-ARM @@ -36,11 +36,8 @@ #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ -#include // Exact-width types. C++11 Standard - -#ifdef QP_CONFIG -#include "qp_config.hpp" // external QP configuration -#endif +#include // Exact-width types. C++11 Standard +#include "qp_config.hpp" // QP configuration from the application // no-return function specifier (C++11 Standard) #define Q_NORETURN [[ noreturn ]] void @@ -114,10 +111,9 @@ #if (__ARM_ARCH == 6) // ARMv6-M? // macro to put the CPU to sleep inside QV_onIdle() - #define QV_CPU_SLEEP() do { \ + #define QV_CPU_SLEEP() do { \ __asm volatile ("wfi"::: "memory"); \ - QF_MEM_APP(); \ - QF_INT_ENABLE(); \ + QF_INT_ENABLE(); \ } while (false) #define QV_ARM_ERRATUM_838869() ((void)0) @@ -125,11 +121,10 @@ #else // ARMv7-M or higher // macro to put the CPU to sleep inside QV_onIdle() - #define QV_CPU_SLEEP() do { \ + #define QV_CPU_SLEEP() do { \ __asm volatile ("cpsid i" ::: "memory"); \ - QF_MEM_APP(); \ - QF_INT_ENABLE(); \ - __asm volatile ("wfi" ::: "memory"); \ + QF_INT_ENABLE(); \ + __asm volatile ("wfi" ::: "memory"); \ __asm volatile ("cpsie i" ::: "memory"); \ } while (false) diff --git a/ports/arm-cm/qv/gnu/qs_port.hpp b/ports/arm-cm/qv/gnu/qs_port.hpp index 4ddb938b5..7da8a41ae 100644 --- a/ports/arm-cm/qv/gnu/qs_port.hpp +++ b/ports/arm-cm/qv/gnu/qs_port.hpp @@ -28,7 +28,7 @@ // //============================================================================ //! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_7_4_0 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler diff --git a/ports/arm-cm/qv/gnu/qv_port.cpp b/ports/arm-cm/qv/gnu/qv_port.cpp index 9c02be08f..04e8a132a 100644 --- a/ports/arm-cm/qv/gnu/qv_port.cpp +++ b/ports/arm-cm/qv/gnu/qv_port.cpp @@ -1,34 +1,33 @@ //============================================================================ // 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 // ------------------------ // 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: +// 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. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2023-12-03 -//! @version Last updated for: @ref qpcpp_7_3_1 +//! @date Last updated on: 2024-09-30 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QV/C++ port to ARM Cortex-M, GNU-ARM @@ -66,14 +65,17 @@ 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. // Additionally, the function also asserts that the interrupts are -// NOT disabled upon the entry to the function. -__attribute__ ((naked, weak)) void QF_int_disable_(void) { +// NOT disabled upon the entry to the function, which means that +// this interrupt management policy CANNOT nest. +__attribute__ ((naked, weak)) +void QF_int_disable_(void) { __asm volatile ( #if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK @@ -95,13 +97,16 @@ __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. // Additionally, the function also asserts that the interrupts ARE -// disabled upon the entry to the function. -__attribute__ ((naked, weak)) void QF_int_enable_(void) { +// 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 @@ -126,6 +131,7 @@ __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 @@ -133,11 +139,10 @@ __asm volatile ( // On ARMv7-M and higher, critical section is entered by disabling // interrupts *selectively* with the BASEPRI register. // Additionally, the function also asserts that the interrupts are -// NOT disabled upon the entry to the function. -// -// NOTE: -// The assertion means that this critical section CANNOT nest. -__attribute__ ((naked, weak)) void QF_crit_entry_(void) { +// NOT disabled upon the entry to the function, which means that +// this critical section CANNOT nest. +__attribute__ ((naked, weak)) +void QF_crit_entry_(void) { __asm volatile ( #if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK @@ -159,6 +164,7 @@ __asm volatile ( } //............................................................................ // Exit QF critical section. +// NOTE: this function must NOT use the stack. // // description: // On ARMv6-M, critical section is exited by enabling interrupts @@ -166,11 +172,10 @@ __asm volatile ( // On ARMv7-M and higher, critical section is exited by enabling // interrupts with the BASEPRI register. // Additionally, the function also asserts that the interrupts ARE -// disabled upon the entry to the function. -// -// NOTE: -// The assertion means that this critical section CANNOT nest. -__attribute__ ((naked, weak)) void QF_crit_exit_(void) { +// 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 @@ -207,8 +212,8 @@ __asm volatile ( // application programmer forgets to explicitly set priorities of all // "kernel aware" interrupts. // -// The interrupt priorities established in QV_init() can be later -// changed by the application-level code. +// NOTE: The IRQ priorities established in QV_init() can be later changed +// by the application-level code. void QV_init(void) { #if (__ARM_ARCH != 6) //--------- if ARMv7-M and higher... diff --git a/ports/arm-cm/qv/iar/qp_port.hpp b/ports/arm-cm/qv/iar/qp_port.hpp index 2b7922a20..11aa635c0 100644 --- a/ports/arm-cm/qv/iar/qp_port.hpp +++ b/ports/arm-cm/qv/iar/qp_port.hpp @@ -1,34 +1,34 @@ //============================================================================ // 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 // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC . -// // 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: +// 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. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2023-12-02 -//! @version Last updated for: @ref qpcpp_7_3_1 +//! @date Last updated on: 2024-09-30 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QP/C++ port to ARM Cortex-M, cooperative QV kernel, IAR-ARM @@ -36,12 +36,9 @@ #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ -#include // Exact-width types. C++11 Standard -#include // IAR intrinsic functions - -#ifdef QP_CONFIG -#include "qp_config.hpp" // external QP configuration -#endif +#include // Exact-width types. C++11 Standard +#include // IAR intrinsic functions +#include "qp_config.hpp" // QP configuration from the application // no-return function specifier (C++11 Standard) #define Q_NORETURN [[ noreturn ]] void @@ -116,9 +113,8 @@ // macro to put the CPU to sleep inside QV_onIdle() #define QV_CPU_SLEEP() do { \ - __WFI(); \ - QF_MEM_APP(); \ - QF_INT_ENABLE(); \ + __WFI(); \ + QF_INT_ENABLE(); \ } while (false) #define QV_ARM_ERRATUM_838869() ((void)0) @@ -128,7 +124,6 @@ // macro to put the CPU to sleep inside QV_onIdle() #define QV_CPU_SLEEP() do { \ __disable_interrupt(); \ - QF_MEM_APP(); \ QF_INT_ENABLE(); \ __WFI(); \ __enable_interrupt(); \ diff --git a/ports/arm-cm/qv/iar/qs_port.hpp b/ports/arm-cm/qv/iar/qs_port.hpp index 4ddb938b5..7da8a41ae 100644 --- a/ports/arm-cm/qv/iar/qs_port.hpp +++ b/ports/arm-cm/qv/iar/qs_port.hpp @@ -28,7 +28,7 @@ // //============================================================================ //! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_7_4_0 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler diff --git a/ports/arm-cm/qv/iar/qv_port.cpp b/ports/arm-cm/qv/iar/qv_port.cpp index 166850820..d6e6b7c9b 100644 --- a/ports/arm-cm/qv/iar/qv_port.cpp +++ b/ports/arm-cm/qv/iar/qv_port.cpp @@ -1,34 +1,33 @@ //============================================================================ // 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 // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC . -// // 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: +// 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. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2023-12-03 -//! @version Last updated for: @ref qpcpp_7_3_1 +//! @date Last updated on: 2024-09-30 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QV/C++ port to ARM Cortex-M, IAR-ARM toolset @@ -71,13 +70,16 @@ 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. // Additionally, the function also asserts that the interrupts are -// NOT disabled upon the entry to the function. +// 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? @@ -100,12 +102,15 @@ __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. // Additionally, the function also asserts that the interrupts ARE -// disabled upon the entry to the function. +// 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? @@ -131,6 +136,7 @@ __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 @@ -138,10 +144,9 @@ __asm volatile ( // On ARMv7-M and higher, critical section is entered by disabling // interrupts *selectively* with the BASEPRI register. // Additionally, the function also asserts that the interrupts are -// NOT disabled upon the entry to the function. -// -// NOTE: -// The assertion means that this critical section CANNOT nest. +// 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? @@ -164,6 +169,7 @@ __asm volatile ( } //............................................................................ // Exit QF critical section. +// NOTE: this function must NOT use the stack. // // description: // On ARMv6-M, critical section is exited by enabling interrupts @@ -171,10 +177,9 @@ __asm volatile ( // On ARMv7-M and higher, critical section is exited by enabling // interrupts with the BASEPRI register. // Additionally, the function also asserts that the interrupts ARE -// disabled upon the entry to the function. -// -// NOTE: -// The assertion means that this critical section CANNOT nest. +// 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? @@ -212,8 +217,8 @@ __asm volatile ( // application programmer forgets to explicitly set priorities of all // "kernel aware" interrupts. // -// The interrupt priorities established in QV_init() can be later -// changed by the application-level code. +// NOTE: The IRQ priorities established in QV_init() can be later changed +// by the application-level code. void QV_init(void) { #if (__ARM_ARCH != 6) //--------- if ARMv7-M and higher... @@ -242,6 +247,7 @@ void QV_init(void) { #if (__ARM_ARCH == 6) // if ARMv6-M... // hand-optimized quick LOG2 in assembly (no CLZ instruction in ARMv6-M) +__stackless uint_fast8_t QF_qlog2(uint32_t x) { static uint8_t const log2LUT[16] = { 0U, 1U, 2U, 2U, 3U, 3U, 3U, 3U, @@ -250,7 +256,7 @@ uint_fast8_t QF_qlog2(uint32_t x) { uint_fast8_t n; __asm volatile ( - " MOVS %[n],#0 \n" + " MOVS %[n],#0 \n" #if (QF_MAX_ACTIVE > 16U) " LSRS r2,r0,#16 \n" " BEQ QF_qlog2_1 \n" @@ -270,7 +276,7 @@ __asm volatile ( " ADDS %[n],%[n],#4 \n" " MOVS r0,r2 \n" "QF_qlog2_3:" : [n]"=r"(n) -); + ); return n + log2LUT[x]; } diff --git a/ports/arm-cm/qxk/armclang/qp_port.hpp b/ports/arm-cm/qxk/armclang/qp_port.hpp deleted file mode 100644 index 8f28a4f13..000000000 --- a/ports/arm-cm/qxk/armclang/qp_port.hpp +++ /dev/null @@ -1,237 +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 . -// -// 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-12-02 -//! @version Last updated for: @ref qpc_7_3_1 -//! -//! @file -//! @brief QP/C++ port to ARM Cortex-M, dual-mode QXK kernel, ARM-CLANG - -#ifndef QP_PORT_HPP_ -#define QP_PORT_HPP_ - -#include // Exact-width types. C++11 Standard - -#ifdef QP_CONFIG -#include "qp_config.hpp" // external QP configuration -#endif - -// no-return function specifier (C++11 Standard) -#define Q_NORETURN [[ noreturn ]] void - -// QF configuration for QXK -- data members of the QActive class... - -// QXK event-queue type used for AOs and eXtended threads. -#define QACTIVE_EQUEUE_TYPE QEQueue - -// QXK OS-Object type used for the private stack pointer for eXtended threads. -// (The private stack pointer is NULL for basic-threads). -#define QACTIVE_OS_OBJ_TYPE void* - -// QF "thread" type used to store the MPU settings in the AO -#define QACTIVE_THREAD_TYPE void const * - -// QF interrupt disable/enable and log2()... -#if (__ARM_ARCH == 6) // ARMv6-M? - - // CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4 - #define QF_AWARE_ISR_CMSIS_PRI 0 - - // hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M) - #define QF_LOG2(n_) QF_qlog2(static_cast(n_)) - -#else // ARMv7-M or higher - - // BASEPRI threshold for "QF-aware" interrupts, see NOTE3 - #define QF_BASEPRI 0x3F - - // CMSIS threshold for "QF-aware" interrupts, see NOTE4 - #define QF_AWARE_ISR_CMSIS_PRI (QF_BASEPRI >> (8 - __NVIC_PRIO_BITS)) - - // ARMv7-M or higher provide the CLZ instruction for fast LOG2 - #define QF_LOG2(n_) \ - (static_cast(32 - __builtin_clz((n_)))) - -#endif - -// interrupt disabling policy, see NOTE2 and NOTE3 -#define QF_INT_DISABLE() (QF_int_disable_()) -#define QF_INT_ENABLE() (QF_int_enable_()) - -// QF critical section, see NOTE1, NOTE2, and NOTE3 -#define QF_CRIT_STAT -#define QF_CRIT_ENTRY() (QF_crit_entry_()) -#define QF_CRIT_EXIT() (QF_crit_exit_()) - -#define QF_CRIT_EXIT_NOP() __asm volatile ("isb" ::: "memory") - -#if (__ARM_ARCH == 6) // ARMv6-M? - // hand-optimized quick LOG2 in assembly - extern "C" std::uint_fast8_t QF_qlog2(std::uint32_t x); -#endif // ARMv7-M or higher - -// Memory isolation ---------------------------------------------------------- -#ifdef QF_MEM_ISOLATE - - // Memory isolation requires the context-switch - #define QF_ON_CONTEXT_SW 1U - - // Memory System setting - #define QF_MEM_SYS() QF_onMemSys() - - // Memory Application setting - #define QF_MEM_APP() QF_onMemApp() - - // callback functions for memory settings (provided by applications) - extern "C" void QF_onMemSys(void); - extern "C" void QF_onMemApp(void); - -#endif // def QF_MEM_ISOLATE - -// determination if the code executes in the ISR context -#define QXK_ISR_CONTEXT_() (QXK_get_IPSR() != 0U) - -__attribute__((always_inline)) -static inline uint32_t QXK_get_IPSR(void) { - uint32_t regIPSR; - __asm volatile ("mrs %0,ipsr" : "=r" (regIPSR)); - return regIPSR; -} - -// trigger the PendSV exception to perform the context switch -#define QXK_CONTEXT_SWITCH_() \ - *Q_UINT2PTR_CAST(uint32_t, 0xE000ED04U) = (1U << 28U) - -// QXK ISR entry and exit -#define QXK_ISR_ENTRY() ((void)0) - -#ifdef QF_MEM_ISOLATE - #define QXK_ISR_EXIT() do { \ - QF_INT_DISABLE(); \ - QF_MEM_SYS(); \ - if (QXK_sched_() != 0U) { \ - *Q_UINT2PTR_CAST(uint32_t, 0xE000ED04U) = (1U << 28U);\ - } \ - QF_MEM_APP(); \ - QF_INT_ENABLE(); \ - QXK_ARM_ERRATUM_838869(); \ - } while (false) -#else - #define QXK_ISR_EXIT() do { \ - QF_INT_DISABLE(); \ - if (QXK_sched_() != 0U) { \ - *Q_UINT2PTR_CAST(uint32_t, 0xE000ED04U) = (1U << 28U);\ - } \ - QF_INT_ENABLE(); \ - QXK_ARM_ERRATUM_838869(); \ - } while (false) -#endif - -#if (__ARM_ARCH == 6) // ARMv6-M? - #define QXK_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. - #define QXK_ARM_ERRATUM_838869() \ - __asm volatile ("dsb" ::: "memory") - -#endif // ARMv6-M - -// initialization of the QXK kernel -#define QXK_INIT() QXK_init() -extern "C" void QXK_init(void); -extern "C" void QXK_thread_ret(void); - -#ifdef __ARM_FP //--------- if VFP available... -// When the FPU is configured, clear the FPCA bit in the CONTROL register -// to prevent wasting the stack space for the FPU context. -#define QXK_START() __asm volatile ("msr CONTROL,%0" :: "r" (0) : ) -#endif - -// include files ------------------------------------------------------------- -#include "qequeue.hpp" // QXK kernel uses the native QP event queue -#include "qmpool.hpp" // QXK kernel uses the native QP memory pool -#include "qp.hpp" // QP framework -#include "qxk.hpp" // QXK kernel - -// prototypes -extern "C" { - void QF_int_disable_(void); - void QF_int_enable_(void); - void QF_crit_entry_(void); - void QF_crit_exit_(void); - - extern std::int32_t volatile QF_int_lock_nest_; -} // extern "C" - -//============================================================================ -// NOTE1: -// The critical section policy does not use the "saving and restoring" -// interrupt status policy (macro QF_CRIT_STAT is defined to nothing). -// However, this the QF critical sections might still be able to nest, -// depending on the implementation of the QF_crit_entry_()/QF_crit_exit_() -// 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. -// -// NOTE2: -// On Cortex-M0/M0+/M1 (architecture ARMv6-M, ARMv6S-M), the interrupt -// disabling policy uses the PRIMASK register to disable interrupts globally. -// The QF_AWARE_ISR_CMSIS_PRI level is zero, meaning that all interrupts -// 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. -// 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 -// ("kernel-aware" interrupts ), can call QF services. -// -// NOTE4: -// The QF_AWARE_ISR_CMSIS_PRI macro is useful as an offset for enumerating -// the "QF-aware" interrupt priorities in the applications, whereas the -// numerical values of the "QF-aware" interrupts must be greater or equal to -// QF_AWARE_ISR_CMSIS_PRI. The values based on QF_AWARE_ISR_CMSIS_PRI can be -// passed directly to the CMSIS function NVIC_SetPriority(), which shifts -// them by (8 - __NVIC_PRIO_BITS) into the correct bit position, while -// __NVIC_PRIO_BITS is the CMSIS macro defining the number of implemented -// priority bits in the NVIC. Please note that the macro QF_AWARE_ISR_CMSIS_PRI -// is intended only for applications and is not used inside the QF port, which -// remains generic and not dependent on the number of implemented priority bits -// implemented in the NVIC. - -#endif // QP_PORT_HPP_ - diff --git a/ports/arm-cm/qxk/armclang/qs_port.hpp b/ports/arm-cm/qxk/armclang/qs_port.hpp deleted file mode 100644 index 4ddb938b5..000000000 --- a/ports/arm-cm/qxk/armclang/qs_port.hpp +++ /dev/null @@ -1,57 +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: 2024-06-06 -//! @version Last updated for: @ref qpcpp_7_4_0 -//! -//! @file -//! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler - -#ifndef QS_PORT_HPP_ -#define QS_PORT_HPP_ - -// 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.hpp" -// *before* "qs.hpp". -#ifndef QP_PORT_HPP_ -#include "qp_port.hpp" // use QS with QP -#endif - -#include "qs.hpp" // QS platform-independent public interface - -#endif // QS_PORT_HPP_ diff --git a/ports/arm-cm/qxk/armclang/qxk_port.cpp b/ports/arm-cm/qxk/armclang/qxk_port.cpp deleted file mode 100644 index ad2fe15d9..000000000 --- a/ports/arm-cm/qxk/armclang/qxk_port.cpp +++ /dev/null @@ -1,809 +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 . -// -// 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: 2024-05-28 -//! @version Last updated for: @ref qpcpp_7_3_5 -//! -//! @file -//! @brief QXK/C++ port to ARM Cortex-M, ARM-CLANG - -#define QP_IMPL 1U -#include "qp_port.hpp" -#include "qp_pkg.hpp" -#include "qsafe.h" // QP Functional Safety (FuSa) System - -#include // for offsetof() - -//============================================================================ -// NOTE: keep in synch with struct QXK_Attr in "qxk.hpp" !!! -#define QXK_CURR 0 -#define QXK_NEXT 4 -#define QXK_ACT_PRIO 12 - -// make sure that the offsets match the QXK declaration in "qxk.hpp" -static_assert(QXK_CURR == offsetof(QXK_Attr, curr), - "QXK_Attr.curr at unexpected offset"); -static_assert(QXK_NEXT == offsetof(QXK_Attr, next), - "QXK_Attr.next at unexpected offset"); -static_assert(QXK_ACT_PRIO == offsetof(QXK_Attr, actPrio), - "QXK_Attr.actPrio at unexpected offset"); - -// offsets within struct QActive; NOTE: keep in synch with "qp.hpp" !!! -#define QACTIVE_PRIO 12 -#define QACTIVE_OSOBJ 20 - - -//============================================================================ -namespace QP { - -// Initialize the private stack of an extended QXK thread. -// -// NOTE -// The function aligns the stack to the 8-byte boundary for compatibility -// with the AAPCS. Additionally, the function pre-fills the stack with the -// known bit pattern (0xDEADBEEF). -// -// NOTE: QXK_stackInit_() must be called before the QXK kernel is made aware -// of this thread. In that case the kernel cannot use the thread yet, so no -// critical section is needed. -void QXThread::stackInit_(QP::QXThreadHandler const handler, - void * const stkSto, std::uint_fast16_t const stkSize) noexcept -{ - // make sure that the offsets match the QActive declaration in "qf.hpp" - static_assert(QACTIVE_OSOBJ == offsetof(QP::QActive, m_osObject), - "QActive.m_osObject at unexpected offset"); - static_assert(QACTIVE_PRIO == offsetof(QP::QActive, m_prio), - "QActive.m_prio at unexpected offset"); - - // round down the stack top to the 8-byte boundary - // NOTE: ARM Cortex-M stack grows down from hi -> low memory - std::uint32_t *sp = (std::uint32_t *)( - (((std::uint32_t)stkSto + stkSize) >> 3U) << 3U); - std::uint32_t *sp_limit; - - // synthesize the ARM Cortex-M exception stack frame... - *(--sp) = (1U << 24); // xPSR (just the THUMB bit) - *(--sp) = (std::uint32_t)handler; // PC (the thread handler) - *(--sp) = (std::uint32_t)&QXK_threadExit_; // LR (exit from thread) - *(--sp) = 0x0000000CU; // R12 - *(--sp) = 0x00000003U; // R3 - *(--sp) = 0x00000002U; // R2 - *(--sp) = 0x00000001U; // R1 - *(--sp) = (std::uint32_t)this; // R0 parameter to handler (thread object) - *(--sp) = 0x0000000BU; // R11 - *(--sp) = 0x0000000AU; // R10 - *(--sp) = 0x00000009U; // R9 - *(--sp) = 0x00000008U; // R8 - *(--sp) = 0x00000007U; // R7 - *(--sp) = 0x00000006U; // R6 - *(--sp) = 0x00000005U; // R5 - *(--sp) = 0x00000004U; // R4 - -#ifdef __ARM_FP //--------- if VFP available... - *(--sp) = 0xFFFFFFFDU; // exception return with VFP state - *(--sp) = 0xAAAAAAAAU; // stack "aligner" -#endif // VFP available - - // save the top of the stack in the thread's attribute - m_osObject = sp; - - // pre-fill the unused part of the stack with 0xDEADBEEF - sp_limit = (std::uint32_t *)( - ((((std::uint32_t)stkSto - 1U) >> 3U) + 1U) << 3U); - for (; sp >= sp_limit; --sp) { - *sp = 0xDEADBEEFU; - } -} - -} // namespace QP - -//============================================================================ -extern "C" { - -// prototypes ---------------------------------------------------------------- -void PendSV_Handler(void); -#ifdef QXK_USE_IRQ_HANDLER // if use IRQ... -void QXK_USE_IRQ_HANDLER(void); -#else // use default (NMI) -void NMI_Handler(void); -#endif - -#define SCB_SYSPRI ((uint32_t volatile *)0xE000ED18U) -#define NVIC_EN ((uint32_t volatile *)0xE000E100U) -#define NVIC_IP ((uint32_t volatile *)0xE000E400U) -#define SCB_CPACR *((uint32_t volatile *)0xE000ED88U) -#define FPU_FPCCR *((uint32_t volatile *)0xE000EF34U) -#define NVIC_PEND 0xE000E200 -#define SCB_ICSR 0xE000ED04 - -// helper macros to "stringify" values -#define VAL(x) #x -#define STRINGIFY(x) VAL(x) - -//============================================================================ -// interrupts and critical section... -// -// NOTE: -// The following interrupt disabling/enabling as well as critical section -// entry/exit functions are defined as "weak" so that they can be -// re-implemented differently at the application level. -// -// NOTE: -// For best performance, these functions are implemented in assembly, -// but they can be implemented in C as well. - - -//std::int32_t volatile QF_int_lock_nest_; // not used -extern char const QF_port_module_[]; -char const QF_port_module_[] = "qxk_port"; - -//............................................................................ -// Unconditionally disable interrupts. -// -// description: -// On ARMv6-M, interrupts are disabled with the PRIMASK register. -// On ARMv7-M and higher, interrupts are disabled *selectively* with the -// BASEPRI register. -// Additionally, the function also asserts that the interrupts are -// NOT disabled upon the entry to the function. -__attribute__ ((naked, weak)) void QF_int_disable_(void) { -__asm volatile ( -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK - " CPSID i \n" // set PRIMASK -#else //--------- ARMv7-M or higher - " 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 - " CMP r0,#0 \n" // assert(PRIMASK/BASEPRI == 0) - " BNE QF_int_disable_error\n" - " BX lr \n" - "QF_int_disable_error: \n" - " LDR r0,=QF_port_module_ \n" - " MOVS r1,#100 \n" - " LDR r2,=Q_onError \n" - " BX r2 \n" - ); -} -//............................................................................ -// Unconditionally enable interrupts. -// -// description: -// On ARMv6-M, interrupts are enabled with the PRIMASK register. -// On ARMv7-M and higher, interrupts are enabled with the BASEPRI register. -// Additionally, the function also asserts that the interrupts ARE -// disabled upon the entry to the function. -// -// NOTE: -// QF_int_enable_() is NOT allowed to push anything on the stack -// (see NOTE-1 at the end of QXK_thread_ret(). -__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 - " MRS r0,BASEPRI \n" // r0 <- previous BASEPRI -#endif //--------- ARMv7-M or higher - " 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 - " MOVS r1,#0 \n" - " MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK -#endif //--------- ARMv7-M or higher - " BX lr \n" - "QF_int_enable_error: \n" - " LDR r0,=QF_port_module_ \n" - " MOVS r1,#101 \n" - " LDR r2,=Q_onError \n" - " BX r2 \n" - ); -} -//............................................................................ -// Enter QF critical section. -// -// 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. -// Additionally, the function also asserts that the interrupts are -// NOT disabled upon the entry to the function. -// -// NOTE: -// The assertion means that this critical section CANNOT nest. -__attribute__ ((naked, weak)) void QF_crit_entry_(void) { -__asm volatile ( -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK - " CPSID i \n" // set PRIMASK -#else //--------- ARMv7-M or higher - " 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 - " CMP r0,#0 \n" // assert(PRIMASK/BASEPRI == 0) - " BNE QF_crit_entry_error\n" - " BX lr \n" - "QF_crit_entry_error: \n" - " LDR r0,=QF_port_module_ \n" - " MOVS r1,#110 \n" - " LDR r2,=Q_onError \n" - " BX r2 \n" - ); -} -//............................................................................ -// Exit QF critical section. -// -// 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. -// Additionally, the function also asserts that the interrupts ARE -// disabled upon the entry to the function. -// -// NOTE: -// The assertion 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 - " MRS r0,BASEPRI \n" // r0 <- previous BASEPRI -#endif //--------- ARMv7-M or higher - " 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 - " MOVS r1,#0 \n" - " MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK -#endif //--------- ARMv7-M or higher - " BX lr \n" - "QF_crit_exit_error: \n" - " LDR r0,=QF_port_module_ \n" - " MOVS r1,#111 \n" - " LDR r2,=Q_onError \n" - " BX r2 \n" - ); -} - -//============================================================================ -// Initialize the exception priorities and IRQ priorities to safe values. -// -// description: -// On ARMv7-M or higher, this QF port disables interrupts by means of the -// 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. -// This avoids breaching of the QF critical sections in case the -// application programmer forgets to explicitly set priorities of all -// "kernel aware" interrupts. -// -// The interrupt priorities established in QXK_init() can be later -// changed by the application-level code. -void QXK_init(void) { - -#if (__ARM_ARCH != 6) //--------- if ARMv7-M and higher... - - // SCB_SYSPRI[2]: SysTick - SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_BASEPRI << 24U)); - - // set all 240 possible IRQ priories to QF_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; - } - -#endif //--------- ARMv7-M or higher - - // SCB_SYSPRI[2]: PendSV set to priority 0xFF (lowest) - SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (0xFFU << 16U)); - -#ifdef QXK_USE_IRQ_NUM //--------- QXK IRQ specified? - // The QXK port is configured to use a given ARM Cortex-M IRQ # - // to return to thread mode (default is to use the NMI exception) - NVIC_IP[QXK_USE_IRQ_NUM] = 0U; // priority 0 (highest) - NVIC_EN[QXK_USE_IRQ_NUM >> 5U] = (1U << (QXK_USE_IRQ_NUM & 0x1FU)); -#endif //--------- QXK IRQ specified - -#ifdef __ARM_FP //--------- if VFP available... - // make sure that the FPU is enabled by setting CP10 & CP11 Full Access - SCB_CPACR = (SCB_CPACR | ((3UL << 20U) | (3UL << 22U))); - - // FPU automatic state preservation (ASPEN) lazy stacking (LSPEN) - FPU_FPCCR = (FPU_FPCCR | (1U << 30U) | (1U << 31U)); -#endif //--------- VFP available -} - -//============================================================================ -// The PendSV exception is used for performing asynchronous preemption in QXK. -// The use of the PendSV exception is the recommended and most efficient -// method for performing context switches in ARM Cortex-M. -// -// The PendSV exception should have the lowest interrupt priority in the system -// (0xFF, see QXK_init()). All other exceptions and interrupts should have -// higher interrupt priority. -// -// Also, *all* "kernel aware" ISRs in the QXK application must call the -// QXK_ISR_EXIT() macro, which triggers PendSV when it detects a need for -// asynchronous preemption. -// -// Due to tail-chaining and its lowest priority, the PendSV exception will be -// entered immediately after the exit from the *last* nested interrupt (or -// exception). In QXK, this is exactly the time when the QXK activator needs to -// handle the asynchronous preemption. -__attribute__ ((naked)) -void PendSV_Handler(void) { -__asm volatile ( - - //<<<<<<<<<<<<<<<<<<<<<<< CRITICAL SECTION BEGIN <<<<<<<<<<<<<<<<<<<<<<<< - " PUSH {r0,lr} \n" // save stack-aligner + EXC_RETURN - " LDR r0,=QF_int_disable_ \n" - " BLX r0 \n" // call QF_int_disable_() - -#ifdef QF_MEM_ISOLATE - " LDR r0,=QF_onMemSys \n" - " BLX r0 \n" // call QF_onMemSys() -#endif - " POP {r0,r1} \n" // restore the aligner + EXC_RETURN in r1 - " MOV lr,r1 \n" // restore EXC_RETURN into lr - - // The PendSV exception handler can be preempted by an interrupt, - // which might pend PendSV exception again. The following write to - // ICSR[27] un-pends any such spurious instance of PendSV. - " MOVS r1,#1 \n" - " LSLS r1,r1,#27 \n" // r1 := (1 << 27) (UNPENDSVSET bit) - " LDR r2,=" STRINGIFY(SCB_ICSR) "\n" // Interrupt Control and State - " STR r1,[r2] \n" // ICSR[27] := 1 (un-pend PendSV) - - // Check QXK_priv_.next, which contains the pointer to the next thread - // to run, which is set in QXK_ISR_EXIT(). Return if QXK_priv_.next == 0 - " LDR r3,=QXK_priv_ \n" - " LDR r0,[r3,#" STRINGIFY(QXK_NEXT) "]\n" // r1 := QXK_priv_.next - " CMP r0,#0 \n" // is (QXK_priv_.next == 0)? - " BEQ PendSV_return \n" // branch if (QXK_priv_.next == 0) - - // Load pointers into registers... - " MOV r12,r0 \n" // save QXK_priv_.next in r12 - " LDR r2,[r0,#" STRINGIFY(QACTIVE_OSOBJ) "]\n" // r2 := QXK_priv_.next->osObject - " LDR r1,[r3,#" STRINGIFY(QXK_CURR) "]\n" // r1 := QXK_priv_.curr - - " CMP r1,#0 \n" // (QXK_priv_.curr != 0)? - " BNE PendSV_save_ex \n" // branch if (current thread is extended) - - " CMP r2,#0 \n" // (QXK_priv_.next->osObject != 0)? - " BNE PendSV_save_ao \n" // branch if (next thread is extended) - - "PendSV_activate: \n" -#ifdef __ARM_FP //--------- if VFP available... - " TST lr,#(1 << 4) \n" // is it return with the VFP exception frame? - " IT EQ \n" // if lr[4] is zero... - " VSTMDBEQ sp!,{s16-s31} \n" // ... save VFP registers s16..s31 - " PUSH {r0,lr} \n" // save the "aligner" and the EXC_RETURN value -#endif // VFP available - // The QXK activator must be called in a Thread mode, while this code - // executes in the Handler mode of the PendSV exception. The switch - // to the Thread mode is accomplished by returning from PendSV using - // a fabricated exception stack frame, where the return address is - // QXK_activate_(). - // - // NOTE: the QXK activator is called with interrupts DISABLED and also - // returns with interrupts DISABLED. - " MOVS r3,#1 \n" - " LSLS r3,r3,#24 \n" // r3 := (1 << 24), set T bit (new xpsr) - " LDR r2,=QXK_activate_\n" // address of QXK_activate_ - " SUBS r2,r2,#1 \n" // align Thumb-address at halfword (new pc) - " LDR r1,=QXK_thread_ret\n" // return address after the call (new lr) - - " SUB sp,sp,#(8*4) \n" // reserve space for exception stack frame - " ADD r0,sp,#(5*4) \n" // r0 := 5 registers below the SP - " STM r0!,{r1-r3} \n" // save xpsr,pc,lr - - " MOVS r0,#6 \n" - " MVNS r0,r0 \n" // r0 := ~6 == 0xFFFFFFF9 -#if (__ARM_ARCH != 6) // ARMv7-M or higher - " DSB \n" // ARM Erratum 838869 -#endif // ARMv7-M or higher - " BX r0 \n" // exception-return to the QXK activator - - //======================================================================== - // Saving AO-thread before crossing to eXtended-thread - // expected register contents: - // r0 -> QXK_priv_.next / basic-thread - // r1 -> QXK_priv_.curr / basic-thread - // r2 -> QXK_priv_.next->osObject (SP) - // r3 -> &QXK_priv_ - // r12 -> QXK_priv_.next / basic-thread - "PendSV_save_ao: \n" -#if (__ARM_ARCH == 6) // if ARMv6-M... - " SUB sp,sp,#(8*4) \n" // make room for 8 registers r4-r11 - " MOV r0,sp \n" // r0 := temporary stack pointer - " STMIA r0!,{r4-r7} \n" // save the low registers - " MOV r4,r8 \n" // move the high registers to low registers... - " MOV r5,r9 \n" - " MOV r6,r10 \n" - " MOV r7,r11 \n" - " STMIA r0!,{r4-r7} \n" // save the high registers - " MOV r0,r12 \n" // restore QXK_priv_.next in r0 -#else // ARMv7-M or higher - " PUSH {r4-r11} \n" // save r4-r11 on top of the exception frame -#ifdef __ARM_FP //--------- if VFP available... - " TST lr,#(1 << 4) \n" // is it return with the VFP exception frame? - " IT EQ \n" // if lr[4] is zero... - " VSTMDBEQ sp!,{s16-s31} \n" // ... save VFP registers s16..s31 - " PUSH {r0,lr} \n" // save the "aligner" and the EXC_RETURN value -#endif // VFP available -#endif // ARMv7-M or higher - - " CMP r2,#0 \n" - " BNE PendSV_restore_ex\n" // branch if (QXK_priv_.next->osObject != 0) - // otherwise continue to restoring next AO-thread... - - //------------------------------------------------------------------------ - // Restoring AO-thread after crossing from eXtended-thread - // expected register contents: - // r1 -> QXK_priv_.curr / basic-thread - // r2 -> QXK_priv_.next->osObject (SP) - // r3 -> &QXK_priv_ - // r12 -> QXK_priv_.next / basic-thread - "PendSV_restore_ao: \n" - // don NOT clear QXK_priv_.curr or QXK_priv_.next, - // as they might be needed for AO activation - -#if (__ARM_ARCH == 6) // if ARMv6-M... - " MOV r0,sp \n" // r0 := top of stack - " MOV r2,r0 \n" - " ADDS r2,r2,#(4*4) \n" // point r2 to the 4 high registers r7-r11 - " LDMIA r2!,{r4-r7} \n" // pop the 4 high registers into low registers - " MOV r8,r4 \n" // move low registers into high registers - " MOV r9,r5 \n" - " MOV r10,r6 \n" - " MOV r11,r7 \n" - " LDMIA r0!,{r4-r7} \n" // pop the low registers - " ADD sp,sp,#(8*4) \n" // remove 8 registers from the stack - - " MOVS r2,#6 \n" - " MVNS r2,r2 \n" // r2 := ~6 == 0xFFFFFFF9 - " MOV lr,r2 \n" // make sure MSP is used -#else // ARMv7-M or higher -#ifdef __ARM_FP //--------- if VFP available... - " POP {r0,lr} \n" // restore aligner and EXC_RETURN into lr - " DSB \n" // ARM Erratum 838869 - " TST lr,#(1 << 4) \n" // is it return to the VFP exception frame? - " IT EQ \n" // if EXC_RETURN[4] is zero... - " VLDMIAEQ sp!,{s16-s31} \n" // ... restore VFP registers s16..s31 -#else - " BIC lr,lr,#(1 << 2) \n" // make sure MSP is used -#endif // VFP available - " POP {r4-r11} \n" // restore r4-r11 from the next thread's stack -#endif // ARMv7-M or higher - - " MOV r0,r12 \n" // r0 := QXK_priv_.next - " MOVS r2,#" STRINGIFY(QACTIVE_PRIO) "\n" // r2 := offset of .prio - " LDRB r0,[r0,r2] \n" // r0 := QXK_priv_.next->prio - " LDR r2,[r3,#" STRINGIFY(QXK_ACT_PRIO) "]\n" // r2 := QXK_priv_.actPrio - " CMP r2,r0 \n" - " BCC PendSV_activate \n" // if (next->prio > actPrio) activate the next AO - - // otherwise no activation needed... - " MOVS r2,#0 \n" - " STR r2,[r3,#" STRINGIFY(QXK_CURR) "]\n" // QXK_priv_.curr := 0 - " STR r2,[r3,#" STRINGIFY(QXK_NEXT) "]\n" // QXK_priv_.next := 0 - - " PUSH {r0,lr} \n" // save the aligner + EXC_RETURN -#if defined(Q_SPY) || defined(QF_ON_CONTEXT_SW) - " CMP r0,#0 \n" // r0 == QXK_priv_.next->prio - " BEQ PendSV_idle \n" // if (QXK_priv_.next->prio != 0) - " MOV r0,r12 \n" // r0 := parameter 'next' for QXK_contextSw_() - "PendSV_idle: \n" - " LDR r3,=QXK_contextSw_ \n" - " BLX r3 \n" // call QXK_contextSw_() -#endif // defined(Q_SPY) || defined(QF_ON_CONTEXT_SW) - " B PendSV_return1 \n" // skip over saving aligner + EXC_RETURN - - // re-enable interrupts and return from PendSV - "PendSV_return: \n" - " PUSH {r0,lr} \n" // save the aligner + EXC_RETURN - - "PendSV_return1: \n" -#ifdef QF_MEM_ISOLATE - " LDR r3,=QF_onMemApp \n" - " BLX r3 \n" // call QF_onMemApp() -#endif - " LDR r0,=QF_int_enable_ \n" - " BLX r0 \n" // call QF_int_enable_() - //>>>>>>>>>>>>>>>>>>>>>>>> CRITICAL SECTION END >>>>>>>>>>>>>>>>>>>>>>>>> - - " POP {r0,pc} \n" // return to the preempted AO-thread - - //------------------------------------------------------------------------ - // Saving extended-thread - // expected register contents: - // r0 -> QXK_priv_.next / basic-thread - // r1 -> QXK_priv_.curr / basic-thread - // r2 -> QXK_priv_.next->osObject (SP) - // r3 -> &QXK_priv_ - // r12 -> QXK_priv_.next / basic-thread - "PendSV_save_ex: \n" - " MRS r0,PSP \n" // r0 := Process Stack Pointer -#if (__ARM_ARCH == 6) // if ARMv6-M... - " SUBS r0,r0,#(8*4) \n" // make room for 8 registers r4-r11 - " MOVS r1,r0 \n" // r1 := temporary PSP (do not clobber r0!) - " STMIA r1!,{r4-r7} \n" // save the low registers - " MOV r4,r8 \n" // move the high registers to low registers... - " MOV r5,r9 \n" - " MOV r6,r10 \n" - " MOV r7,r11 \n" - " STMIA r1!,{r4-r7} \n" // save the high registers - // NOTE: at this point r0 holds the top of stack - - " LDR r1,[r3,#" STRINGIFY(QXK_CURR) "]\n" // r1 := QXK_priv_.curr (restore value) -#else // ARMv7-M or higher - " ISB \n" // reset pipeline after fetching PSP - " STMDB r0!,{r4-r11} \n" // save r4-r11 on top of the exception frame -#ifdef __ARM_FP //--------- if VFP available... - " TST lr,#(1 << 4) \n" // is it return with the VFP exception frame? - " IT EQ \n" // if lr[4] is zero... - " VSTMDBEQ r0!,{s16-s31} \n" // ... save VFP registers s16..s31 - " STMDB r0!,{r1,lr} \n" // save the "aligner" and the EXC_RETURN value -#endif // VFP available -#endif // ARMv7-M or higher - - // store the SP of the current extended-thread - " STR r0,[r1,#" STRINGIFY(QACTIVE_OSOBJ) "]\n" // QXK_priv_.curr->osObject := r0 - " MOV r0,r12 \n" // QXK_priv_.next (restore value) - - " CMP r2,#0 \n" - " BEQ PendSV_restore_ao\n" // branch if (QXK_priv_.next->osObject == 0) - // otherwise continue to restoring next extended-thread... - - //------------------------------------------------------------------------ - // Restoring extended-thread - // expected register contents: - // r0 -> QXK_priv_.next / basic-thread - // r1 -> QXK_priv_.curr / basic-thread - // r2 -> QXK_priv_.next->osObject (SP) - // r3 -> &QXK_priv_ - // r12 -> QXK_priv_.next / basic-thread - "PendSV_restore_ex: \n" - " STR r0,[r3,#" STRINGIFY(QXK_CURR) "]\n" // QXK_priv_.curr := r0 (QXK_priv_.next) - " MOVS r0,#0 \n" - " STR r0,[r3,#" STRINGIFY(QXK_NEXT) "]\n" // QXK_priv_.next := 0 - - " PUSH {r0-r2,lr} \n" // save next, osObject, EXC_RETURN -#if defined(Q_SPY) || defined(QF_ON_CONTEXT_SW) - " MOV r0,r12 \n" // r0 := parameter 'next' for QXK_contextSw_() - " LDR r3,=QXK_contextSw_ \n" - " BLX r3 \n" // call QXK_contextSw_() -#ifdef QF_MEM_ISOLATE - " LDR r3,=QF_onMemApp \n" - " BLX r3 \n" // call QF_onMemApp() -#endif -#endif // defined(Q_SPY) || defined(QF_ON_CONTEXT_SW) - - - // exit the critical section - " LDR r3,=QF_int_enable_ \n" - " BLX r3 \n" // call QF_int_enable_() - " POP {r0-r3} \n" // restore next, osObject, EXC_RETURN - " MOV lr,r3 \n" // restore the EXC_RETURN into lr - -#if (__ARM_ARCH == 6) // if ARMv6-M... - " MOVS r0,r2 \n" // r2 := top of stack - " ADDS r0,r0,#(4*4) \n" // point r0 to the 4 high registers r7-r11 - " LDMIA r0!,{r4-r7} \n" // pop the 4 high registers into low registers - " MOV r8,r4 \n" // move low registers into high registers - " MOV r9,r5 \n" - " MOV r10,r6 \n" - " MOV r11,r7 \n" - " LDMIA r2!,{r4-r7} \n" // pop the low registers - " MOVS r2,r0 \n" // r2 := holds the new top of stack - - " MOVS r1,#2 \n" - " MVNS r1,r1 \n" // r1 := ~2 == 0xFFFFFFFD - " MOV lr,r1 \n" // make sure PSP is used -#else // ARMv7-M or higher -#ifdef __ARM_FP //--------- if VFP available... - " LDMIA r2!,{r1,lr} \n" // restore aligner and EXC_RETURN into lr - " TST lr,#(1 << 4) \n" // is it return to the VFP exception frame? - " IT EQ \n" // if lr[4] is zero... - " VLDMIAEQ r2!,{s16-s31} \n" // ... restore VFP registers s16..s31 -#else - " ORR lr,lr,#(1 << 2) \n" // make sure PSP is used -#endif // VFP available - " LDMIA r2!,{r4-r11} \n" // restore r4-r11 from the next thread's stack -#endif // ARMv7-M or higher - - // set the PSP to the next thread's SP - " MSR PSP,r2 \n" // Process Stack Pointer := r2 - -#if (__ARM_ARCH != 6) // if ARMv7-M or higher... - " DSB \n" // ARM Erratum 838869 -#endif // ARMv7-M or higher - " BX lr \n" // return to the next extended-thread - ); -} - -//============================================================================ -// QXK_thread_ret is a helper function executed when the QXK activator returns. -// -// NOTE: QXK_thread_ret() does not execute in the PendSV context! -// NOTE: QXK_thread_ret() is entered with interrupts DISABLED. -__attribute__ ((naked, used)) -void QXK_thread_ret(void) { -__asm volatile ( - - // After the QXK activator returns, we need to resume the preempted - // thread. However, this must be accomplished by a return-from-exception, - // while we are still in the thread context. The switch to the exception - // context is accomplished by triggering the NMI exception or the selected - // IRQ (if macro #QXK_USE_IRQ_NUM is defined). - - // before triggering the NMI/IRQ, make sure that the VFP stack frame - // will NOT be used... -#ifdef __ARM_FP //--------- if VFP available... - // make sure that the VFP stack frame will NOT be used - " MRS r0,CONTROL \n" // r0 := CONTROL - " BICS r0,r0,#4 \n" // r0 := r0 & ~4 (FPCA bit) - " MSR CONTROL,r0 \n" // CONTROL := r0 (clear CONTROL[2] FPCA bit) - " ISB \n" // ISB after MSR CONTROL (ARM AN321,Sect.4.16) -#endif //--------- VFP available - - // NOTE: the following function calls corrupt lr, but it is NOT - // used to return from QXK_thread_ret(). Instead QXK_thread_ret() - // "returns" by entering an exception (either NMI or IRQ). -#ifdef QF_MEM_ISOLATE - " LDR r0,=QF_onMemApp \n" - " BLX r0 \n" // call QF_onMemApp() -#endif - -#ifndef QXK_USE_IRQ_NUM //--------- IRQ NOT defined, use NMI by default - " LDR r0,=" STRINGIFY(SCB_ICSR) "\n" // Interrupt Control and State - " MOVS r1,#1 \n" - " LSLS r1,r1,#31 \n" // r1 := (1 << 31) (NMI bit) - " STR r1,[r0] \n" // ICSR[31] := 1 (pend NMI) - // NOTE! interrupts are still disabled when NMI is entered - -#else //--------- use the selected IRQ - " LDR r0,=" STRINGIFY(NVIC_PEND + ((QXK_USE_IRQ_NUM >> 5) << 2)) "\n" - " MOVS r1,#1 \n" - " LSLS r1,r1,#" STRINGIFY(QXK_USE_IRQ_NUM & 0x1F) "\n" // r1 := IRQ bit - " STR r1,[r0] \n" // pend the IRQ - - // now enable interrupts so that pended IRQ can be entered - // - // NOTE-1: - // The IRQ preempts immediately after interrupts are enabled, - // without cleanly returning from QF_int_enable_(). Therefore - // QF_int_enable_() is NOT allowed to push anything on the stack - // because the stack is NOT restored when the IRQ preempts. - " LDR r0,=QF_int_enable_ \n" - " BLX r0 \n" // call QF_int_enable_() -#endif //--------- use IRQ - - " B . \n" // wait for preemption by NMI/IRQ - ); -} - -//============================================================================ -// This exception handler is used for returning back to the preempted thread. -// The exception handler simply removes its own interrupt stack frame from -// the stack (MSP) and returns to the preempted task using the interrupt -// stack frame that must be at the top of the stack. -__attribute__ ((naked)) -#ifndef QXK_USE_IRQ_NUM //--------- IRQ NOT defined, use NMI by default - -// NOTE: The NMI_Handler() is entered with interrupts still DISABLED! -void NMI_Handler(void) { -__asm volatile ( - // call QF_int_enable_(), NOTE: corrupts lr (EXC_RETURN) - // but see code after "BLX r0" - " LDR r0,=QF_int_enable_ \n" - " BLX r0 \n" // call QF_int_enable_() -#ifdef __ARM_FP //--------- if VFP available... - // When VFP is available, lr (EXC_RETURN) is restored from the stack - // before returning from exception, so the value in lr doesn't matter -#else //--------- VFP NOT available - // lr (EXC_RETURN) can be synthesized because it is known (0xFFFFFFF9): - // - return to Thread mode; - // - exception return uses non-floating-point state from MSP; - // - execution uses MSP after return. - " MOVS r0,#6 \n" - " MVNS r0,r0 \n" // r0 := ~6 == 0xFFFFFFF9 - " MOV lr,r0 \n" // lr := 0xFFFFFFF9 (EXC_RETURN) -#endif //--------- VFP NOT available -); - -#else //--------- IRQ defined, use the selected IRQ - -// NOTE: The IRQ Handler is entered with interrupts already ENABLED -void QXK_USE_IRQ_HANDLER(void) { -#endif //--------- IRQ defined - - // ...continue here from either NMI or IRQ -__asm volatile ( - " ADD sp,sp,#(8*4) \n" // remove one 8-register exception frame - -#ifdef __ARM_FP //--------- if VFP available... - " POP {r0,lr} \n" // restore aligher and EXC_RETURN into lr - " DSB \n" // ARM Erratum 838869 - " TST lr,#(1 << 4) \n" // is it return to the VFP exception frame? - " IT EQ \n" // if EXC_RETURN[4] is zero... - " VLDMIAEQ sp!,{s16-s31} \n" // ... restore VFP registers s16..s31 -#endif //--------- VFP available - " BX lr \n" // return to the preempted task - ); -} - -//============================================================================ -#if (__ARM_ARCH == 6) // if ARMv6-M... - -// hand-optimized quick LOG2 in assembly (no CLZ instruction in ARMv6-M) -__attribute__ ((naked)) -std::uint_fast8_t QF_qlog2(std::uint32_t x) { -__asm volatile ( - " MOVS r1,#0 \n" -#if (QF_MAX_ACTIVE > 16U) - " LSRS r2,r0,#16 \n" - " BEQ QF_qlog2_1 \n" - " MOVS r1,#16 \n" - " MOVS r0,r2 \n" - "QF_qlog2_1: \n" -#endif -#if (QF_MAX_ACTIVE > 8U) - " LSRS r2,r0,#8 \n" - " BEQ QF_qlog2_2 \n" - " ADDS r1, r1,#8 \n" - " MOVS r0, r2 \n" - "QF_qlog2_2: \n" -#endif - " LSRS r2,r0,#4 \n" - " BEQ QF_qlog2_3 \n" - " ADDS r1,r1,#4 \n" - " MOV r0,r2 \n" - "QF_qlog2_3: \n" - " LDR r2,=QF_qlog2_LUT \n" - " LDRB r0,[r2,r0] \n" - " ADDS r0,r1,r0 \n" - " BX lr \n" - " .align \n" - "QF_qlog2_LUT: \n" - " .byte 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4" - ); -} - -#endif // ARMv6-M - -} // extern "C" - diff --git a/ports/arm-cm/qxk/config/qp_config.hpp b/ports/arm-cm/qxk/config/qp_config.hpp deleted file mode 100644 index fa8f24126..000000000 --- a/ports/arm-cm/qxk/config/qp_config.hpp +++ /dev/null @@ -1,259 +0,0 @@ -//============================================================================ -// QP configuration file (QXK on ARM Cortex-M) -// Last updated for version: 7.4.0 -// Last updated on: 2024-06-06 -// -// 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: -// -// -//============================================================================ -#ifndef QP_CONFIG_HPP_ -#define QP_CONFIG_HPP_ - -//-------- <<< Use Configuration Wizard in Context Menu >>> ----------------- - -// NOTE: Requires command-line macro: QP_CONFIG -// This qp_config.h header file is activated only when the macro -// QP_CONFIG is defined on the command-line to the compiler -// ------------------------------------------- - -// QP API compatibility version (QP_API_VERSION) -// <0=> 0 (Maximum compatibility) -// <580=>580 (QP 5.8.0 or newer) -// <660=>660 (QP 6.6.0 or newer) -// <691=>691 (QP 6.9.1 or newer) -// <700=>700 (QP 7.0.0 or newer) -// <9999=>9999 (Latest only) -// QP API backwards compatibility with the QP/C API version. -// Lower QP_API_VERSION values enable backwards compatibility -// with lower (older) QP API versions. -// For example, QP_API_VERSION==691 will enable the compatibility -// layer with QP version 6.9.1 and newer, but not older than 6.9.1. -// QP_API_VERSION==0 enables the maximum currently supported -// backwards compatibility. Conversely, QP_API_VERSION==9999 means -// that no backwards compatibility layer should be enabled. -// Default: 0 (All supported) -#define QP_API_VERSION 0 - -//.......................................................................... -// QP Functional Safety (FuSa) Subsystem (Q_UNSAFE) -// The QP FuSa Subsystem consists of the following facilities: -// - Software assertions as a recommended technique -// (called Failure Assertion Programming (FAP) in IEC 61508) -// - Software Self-Monitoring (SSM), which encompasses such techniques: -// * Duplicate Inverse Storage for critical variables -// * Memory Markers for critical objects (e.g., events) -// * Hard-limits for all loops -// * Memory Isolation by means of Memory Protection Unit (MPU) - -// Disable QP FuSa in development -// Disable assertions and other self monitoring features -// in development build configurations (NDEBUG undefined). -// VIOLATES functional safety standards. NOT recommended !!! -//#ifndef NDEBUG -//#define Q_UNSAFE -//#endif -// - -// Disable QP FuSa in production release -// Disable assertions and other self monitoring features -// in the release build configurations (NDEBUG defined). -// VIOLATES functional safety standards. NOT recommended !!! -//#ifdef NDEBUG -//#define Q_UNSAFE -//#endif -// - -// - -//.......................................................................... -// QEP Event Processor -// Events and state machines. - -// Event signal size (Q_SIGNAL_SIZE) -// <1U=>1 -// <2U=>2 (default) -// <4U=>4 -// Size of the QEvt signal for QEP/QF [bytes] -// Default: 2 -#define Q_SIGNAL_SIZE 2U - -// - -//.......................................................................... -// QF Framework -// Active Object framework - -// Maximum # Active Objects (QF_MAX_ACTIVE) <1-64> -// Maximum # Active Objects in the system <1..64> -// Default: 32 -#define QF_MAX_ACTIVE 32U - -// Maximum # event pools (QF_MAX_EPOOL) -// <0=>0 no event pools -// <1=>1 <2=>2 <3=>3 (default) <4=>4 <5=>5 -// <6=>6 <7=>7 <8=>8 <9=>9 <10=>10 <11=>11 -// <12=>12 <13=>13 <14=>14 <15=>15 -// Maximum # Event Pools <1..15> -// Default: 3 -#define QF_MAX_EPOOL 3U - -// Maximum # clock tick rates (QF_MAX_TICK_RATE) -// <0=>0 no time events -// <1=>1 (default) <2=>2 <3=>3 <4=>4 <5=>5 -// <6=>6 <7=>7 <8=>8 <9=>9 <10=>10 <11=>11 -// <12=>12 <13=>13 <14=>14 <15=>15 -// Maximum # clock tick rates for time events <1..15> -// Default: 1 -#define QF_MAX_TICK_RATE 1U - -// Event parameter initialization (QEVT_PAR_INIT) -// Resource Acquisition Is Initialization (RAII) for dynamic events -//#define QEVT_PAR_INIT - -// Provide destructors for QP classes -// Destructors for classes -//#define Q_XTOR -// - -// Active Object stop API (QACTIVE_CAN_STOP) -// Enable Active Object stop API (Not recommended) -//#define QACTIVE_CAN_STOP -// - -// Event size (QF_EVENT_SIZ_SIZE) -// <1U=>1 -// <2U=>2 (default) -// <4U=>4 -// Size of the dynamic events for QF [bytes] -// Default: 2 (64K bytes maximum event size) -#define QF_EVENT_SIZ_SIZE 2U - -// Time event counter size (QF_TIMEEVT_CTR_SIZE) -// <1U=>1 -// <2U=>2 -// <4U=>4 (default) -// Size of the QTimeEvt counter [bytes] -// Default: 4 (2^32 dynamic range) -#define QF_TIMEEVT_CTR_SIZE 4U - -// Event queue counter size (QF_EQUEUE_CTR_SIZE) -// <1U=>1 (default) -// <2U=>2 -// <4U=>4 -// Size of event queue counter [bytes] -// Default: 1 (255 events maximum in a queue) -#define QF_EQUEUE_CTR_SIZE 1U - -// Memory pool counter size (QF_MPOOL_CTR_SIZE) -// <1U=>1 -// <2U=>2 (default) -// <4U=>4 -// Size of memory pool counter [bytes] -// Default: 2 (64K blocks maximum in a pool) -#define QF_MPOOL_CTR_SIZE 2U - -// Memory block size (QF_MPOOL_SIZ_SIZE) -// <1U=>1 -// <2U=>2 (default) -// <4U=>4 -// Size of memory pool block [bytes] -// Default: 2 (64K bytes maximum block size) -#define QF_MPOOL_SIZ_SIZE 2U - -// - -//.......................................................................... -// QS Software Tracing -// Target-resident component of QP/Spy software tracing system -// (tracing instrumentation and command-input). - -// NOTE: Requires command-line macro: Q_SPY -// The QS software tracing instrumentation is activated only when -// the macro Q_SPY is defined on the command-line to the compiler. -// Typically, Q_SPY is defined only in the "spy" build configuration. - -// QS timestamp size (QS_TIME_SIZE) -// <1U=>1 -// <2U=>2 -// <4U=>4 (default) -// Size of the timestamp in QS [bytes] -// Default: 4 (2^32 dynamic range) -#define QS_TIME_SIZE 4U - -// QS buffer counter size (QS_CTR_SIZE) -// <1U=>1 -// <2U=>2 (default) -// <4U=>4 -// Size of the counter in the internal QS buffer [bytes] -// Default: 2 (64K bytes in QS buffer) -#define QS_CTR_SIZE 2U - -// - -//.......................................................................... -// QXK Preemptive Dual-Mode Kernel -// Preemptive non-blocking/blocking RTOS kernel. - -// Context switch callback (QF_ON_CONTEXT_SW) - -// Context switch callback WITHOUT QS -// Enable context switch callback QF_onContextSw() -// When Q_SPY is undefined. -//#ifndef Q_SPY -//#define QF_ON_CONTEXT_SW -//#endif -// - -// Context switch callback WITH QS -// Enable context switch callback QF_onContextSw() -// When Q_SPY is defined. -//#ifdef Q_SPY -//#define QF_ON_CONTEXT_SW -//#endif -// - -// - -// MPU memory isolation (QF_MEM_ISOLATE) -// Enable memory isolation (requires MPU) -// NOTE: implies QF_ON_CONTEXT_SW. -//#define QF_MEM_ISOLATE -// - -// Use IRQ handler for QXK return-from-preemption -// Enable this option only if the NMI handler is used in the project. -// If enabled, provide the otherwise unused IRQ number (QXK_USE_IRQ_NUM) -// and the corresponding IRQ handler name (QXK_USE_IRQ_HANDLER) -// in the "Text Editor" mode. -//#define QXK_USE_IRQ_NUM 31 -//#define QXK_USE_IRQ_HANDLER Reserved31_IRQHandler -// - -// - -//------------- <<< end of configuration section >>> ----------------------- - -#endif // QP_CONFIG_HPP_ diff --git a/ports/arm-cm/qxk/gnu/qp_port.hpp b/ports/arm-cm/qxk/gnu/qp_port.hpp deleted file mode 100644 index 11317672f..000000000 --- a/ports/arm-cm/qxk/gnu/qp_port.hpp +++ /dev/null @@ -1,237 +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 . -// -// 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-12-03 -//! @version Last updated for: @ref qpcpp_7_3_1 -//! -//! @file -//! @brief QP/C++ port to ARM Cortex-M, dual-mode QXK kernel, GNU-ARM - -#ifndef QP_PORT_HPP_ -#define QP_PORT_HPP_ - -#include // Exact-width types. C++11 Standard - -#ifdef QP_CONFIG -#include "qp_config.hpp" // external QP configuration -#endif - -// no-return function specifier (C++11 Standard) -#define Q_NORETURN [[ noreturn ]] void - -// QF configuration for QXK -- data members of the QActive class... - -// QActive event-queue type used for AOs and eXtended threads. -#define QACTIVE_EQUEUE_TYPE QEQueue - -// QActive OS-Object type used for the private stack pointer for eXtended threads. -// (The private stack pointer is NULL for basic-threads). -#define QACTIVE_OS_OBJ_TYPE void* - -// QActive "thread" type used to store the MPU settings in the AO -#define QACTIVE_THREAD_TYPE void const * - -// QF interrupt disable/enable and log2()... -#if (__ARM_ARCH == 6) // ARMv6-M? - - // CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4 - #define QF_AWARE_ISR_CMSIS_PRI 0 - - // hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M) - #define QF_LOG2(n_) QF_qlog2(static_cast(n_)) - -#else // ARMv7-M or higher - - // BASEPRI threshold for "QF-aware" interrupts, see NOTE3 - #define QF_BASEPRI 0x3F - - // CMSIS threshold for "QF-aware" interrupts, see NOTE5 - #define QF_AWARE_ISR_CMSIS_PRI (QF_BASEPRI >> (8 - __NVIC_PRIO_BITS)) - - // ARMv7-M or higher provide the CLZ instruction for fast LOG2 - #define QF_LOG2(n_) \ - (static_cast(32 - __builtin_clz((n_)))) - -#endif - -// interrupt disabling policy, see NOTE2 and NOTE3 -#define QF_INT_DISABLE() (QF_int_disable_()) -#define QF_INT_ENABLE() (QF_int_enable_()) - -// QF critical section, see NOTE1, NOTE2, and NOTE3 -#define QF_CRIT_STAT -#define QF_CRIT_ENTRY() (QF_crit_entry_()) -#define QF_CRIT_EXIT() (QF_crit_exit_()) - -#define QF_CRIT_EXIT_NOP() __asm volatile ("isb" ::: "memory") - -#if (__ARM_ARCH == 6) // ARMv6-M? - // hand-optimized quick LOG2 in assembly - extern "C" std::uint_fast8_t QF_qlog2(std::uint32_t x); -#endif // ARMv7-M or higher - -// Memory isolation ---------------------------------------------------------- -#ifdef QF_MEM_ISOLATE - - // Memory isolation requires the context-switch - #define QF_ON_CONTEXT_SW 1U - - // Memory System setting - #define QF_MEM_SYS() QF_onMemSys() - - // Memory Application setting - #define QF_MEM_APP() QF_onMemApp() - - // callback functions for memory settings (provided by applications) - extern "C" void QF_onMemSys(void); - extern "C" void QF_onMemApp(void); - -#endif // def QF_MEM_ISOLATE - -// determination if the code executes in the ISR context -#define QXK_ISR_CONTEXT_() (QXK_get_IPSR() != 0U) - -__attribute__((always_inline)) -static inline uint32_t QXK_get_IPSR(void) { - uint32_t regIPSR; - __asm volatile ("mrs %0,ipsr" : "=r" (regIPSR)); - return regIPSR; -} - -// trigger the PendSV exception to perform the context switch -#define QXK_CONTEXT_SWITCH_() \ - *Q_UINT2PTR_CAST(uint32_t, 0xE000ED04U) = (1U << 28U) - -// QXK ISR entry and exit -#define QXK_ISR_ENTRY() ((void)0) - -#ifdef QF_MEM_ISOLATE - #define QXK_ISR_EXIT() do { \ - QF_INT_DISABLE(); \ - QF_MEM_SYS(); \ - if (QXK_sched_() != 0U) { \ - *Q_UINT2PTR_CAST(uint32_t, 0xE000ED04U) = (1U << 28U);\ - } \ - QF_MEM_APP(); \ - QF_INT_ENABLE(); \ - QXK_ARM_ERRATUM_838869(); \ - } while (false) -#else - #define QXK_ISR_EXIT() do { \ - QF_INT_DISABLE(); \ - if (QXK_sched_() != 0U) { \ - *Q_UINT2PTR_CAST(uint32_t, 0xE000ED04U) = (1U << 28U);\ - } \ - QF_INT_ENABLE(); \ - QXK_ARM_ERRATUM_838869(); \ - } while (false) -#endif - -#if (__ARM_ARCH == 6) // ARMv6-M? - #define QXK_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. - #define QXK_ARM_ERRATUM_838869() \ - __asm volatile ("dsb" ::: "memory") - -#endif // ARMv6-M - -// initialization of the QXK kernel -#define QXK_INIT() QXK_init() -extern "C" void QXK_init(void); -extern "C" void QXK_thread_ret(void); - -#ifdef __ARM_FP //--------- if VFP available... -// When the FPU is configured, clear the FPCA bit in the CONTROL register -// to prevent wasting the stack space for the FPU context. -#define QXK_START() __asm volatile ("msr CONTROL,%0" :: "r" (0) : ) -#endif - -// include files ------------------------------------------------------------- -#include "qequeue.hpp" // QXK kernel uses the native QP event queue -#include "qmpool.hpp" // QXK kernel uses the native QP memory pool -#include "qp.hpp" // QP framework -#include "qxk.hpp" // QXK kernel - -// prototypes -extern "C" { - void QF_int_disable_(void); - void QF_int_enable_(void); - void QF_crit_entry_(void); - void QF_crit_exit_(void); - - extern std::int32_t volatile QF_int_lock_nest_; -} // extern "C" - -//============================================================================ -// NOTE1: -// The critical section policy does not use the "saving and restoring" -// interrupt status policy (macro QF_CRIT_STAT is defined to nothing). -// However, this the QF critical sections might still be able to nest, -// depending on the implementation of the QF_crit_entry_()/QF_crit_exit_() -// 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. -// -// NOTE2: -// On Cortex-M0/M0+/M1 (architecture ARMv6-M, ARMv6S-M), the interrupt -// disabling policy uses the PRIMASK register to disable interrupts globally. -// The QF_AWARE_ISR_CMSIS_PRI level is zero, meaning that all interrupts -// 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. -// 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 -// ("kernel-aware" interrupts ), can call QF services. -// -// NOTE4: -// The QF_AWARE_ISR_CMSIS_PRI macro is useful as an offset for enumerating -// the "QF-aware" interrupt priorities in the applications, whereas the -// numerical values of the "QF-aware" interrupts must be greater or equal to -// QF_AWARE_ISR_CMSIS_PRI. The values based on QF_AWARE_ISR_CMSIS_PRI can be -// passed directly to the CMSIS function NVIC_SetPriority(), which shifts -// them by (8 - __NVIC_PRIO_BITS) into the correct bit position, while -// __NVIC_PRIO_BITS is the CMSIS macro defining the number of implemented -// priority bits in the NVIC. Please note that the macro QF_AWARE_ISR_CMSIS_PRI -// is intended only for applications and is not used inside the QF port, which -// remains generic and not dependent on the number of implemented priority bits -// implemented in the NVIC. - -#endif // QP_PORT_HPP_ - diff --git a/ports/arm-cm/qxk/gnu/qs_port.hpp b/ports/arm-cm/qxk/gnu/qs_port.hpp deleted file mode 100644 index 4ddb938b5..000000000 --- a/ports/arm-cm/qxk/gnu/qs_port.hpp +++ /dev/null @@ -1,57 +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: 2024-06-06 -//! @version Last updated for: @ref qpcpp_7_4_0 -//! -//! @file -//! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler - -#ifndef QS_PORT_HPP_ -#define QS_PORT_HPP_ - -// 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.hpp" -// *before* "qs.hpp". -#ifndef QP_PORT_HPP_ -#include "qp_port.hpp" // use QS with QP -#endif - -#include "qs.hpp" // QS platform-independent public interface - -#endif // QS_PORT_HPP_ diff --git a/ports/arm-cm/qxk/gnu/qxk_port.cpp b/ports/arm-cm/qxk/gnu/qxk_port.cpp deleted file mode 100644 index 3aee0726b..000000000 --- a/ports/arm-cm/qxk/gnu/qxk_port.cpp +++ /dev/null @@ -1,819 +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 . -// -// 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: 2024-05-28 -//! @version Last updated for: @ref qpcpp_7_3_5 -//! -//! @file -//! @brief QXK/C++ port to ARM Cortex-M, GNU-ARM - -#define QP_IMPL 1U -#include "qp_port.hpp" -#include "qp_pkg.hpp" -#include "qsafe.h" // QP Functional Safety (FuSa) System - -#include // for offsetof() - -//============================================================================ -// NOTE: keep in synch with struct QXK_Attr in "qxk.hpp" !!! -#define QXK_CURR 0 -#define QXK_NEXT 4 -#define QXK_ACT_PRIO 12 - -// make sure that the offsets match the QXK declaration in "qxk.hpp" -static_assert(QXK_CURR == offsetof(QXK_Attr, curr), - "QXK_Attr.curr at unexpected offset"); -static_assert(QXK_NEXT == offsetof(QXK_Attr, next), - "QXK_Attr.next at unexpected offset"); -static_assert(QXK_ACT_PRIO == offsetof(QXK_Attr, actPrio), - "QXK_Attr.actPrio at unexpected offset"); - -// offsets within struct QActive; NOTE: keep in synch with "qp.hpp" !!! -#define QACTIVE_PRIO 12 -#define QACTIVE_OSOBJ 20 - - -//============================================================================ -namespace QP { - -// Initialize the private stack of an extended QXK thread. -// -// NOTE -// The function aligns the stack to the 8-byte boundary for compatibility -// with the AAPCS. Additionally, the function pre-fills the stack with the -// known bit pattern (0xDEADBEEF). -// -// NOTE: QXK_stackInit_() must be called before the QXK kernel is made aware -// of this thread. In that case the kernel cannot use the thread yet, so no -// critical section is needed. -void QXThread::stackInit_(QP::QXThreadHandler const handler, - void * const stkSto, std::uint_fast16_t const stkSize) noexcept -{ - // make sure that the offsets match the QActive declaration in "qf.hpp" - //static_assert(QACTIVE_OSOBJ == offsetof(QP::QActive, m_osObject), - // "QActive.m_osObject at unexpected offset"); - //static_assert(QACTIVE_PRIO == offsetof(QP::QActive, m_prio), - // "QActive.m_prio at unexpected offset"); - - // round down the stack top to the 8-byte boundary - // NOTE: ARM Cortex-M stack grows down from hi -> low memory - std::uint32_t *sp = (std::uint32_t *)( - (((std::uint32_t)stkSto + stkSize) >> 3U) << 3U); - std::uint32_t *sp_limit; - - // synthesize the ARM Cortex-M exception stack frame... - *(--sp) = (1U << 24); // xPSR (just the THUMB bit) - *(--sp) = (std::uint32_t)handler; // PC (the thread handler) - *(--sp) = (std::uint32_t)&QXK_threadExit_; // LR (exit from thread) - *(--sp) = 0x0000000CU; // R12 - *(--sp) = 0x00000003U; // R3 - *(--sp) = 0x00000002U; // R2 - *(--sp) = 0x00000001U; // R1 - *(--sp) = (std::uint32_t)this; // R0 parameter to handler (thread object) - *(--sp) = 0x0000000BU; // R11 - *(--sp) = 0x0000000AU; // R10 - *(--sp) = 0x00000009U; // R9 - *(--sp) = 0x00000008U; // R8 - *(--sp) = 0x00000007U; // R7 - *(--sp) = 0x00000006U; // R6 - *(--sp) = 0x00000005U; // R5 - *(--sp) = 0x00000004U; // R4 - -#ifdef __ARM_FP //--------- if VFP available... - *(--sp) = 0xFFFFFFFDU; // exception return with VFP state - *(--sp) = 0xAAAAAAAAU; // stack "aligner" -#endif // VFP available - - // save the top of the stack in the thread's attribute - m_osObject = sp; - - // pre-fill the unused part of the stack with 0xDEADBEEF - sp_limit = (std::uint32_t *)( - ((((std::uint32_t)stkSto - 1U) >> 3U) + 1U) << 3U); - for (; sp >= sp_limit; --sp) { - *sp = 0xDEADBEEFU; - } -} - -} // namespace QP - -//============================================================================ -extern "C" { - -// prototypes ---------------------------------------------------------------- -void PendSV_Handler(void); -#ifdef QXK_USE_IRQ_HANDLER // if use IRQ... -void QXK_USE_IRQ_HANDLER(void); -#else // use default (NMI) -void NMI_Handler(void); -#endif - -#define SCB_SYSPRI ((uint32_t volatile *)0xE000ED18U) -#define NVIC_EN ((uint32_t volatile *)0xE000E100U) -#define NVIC_IP ((uint32_t volatile *)0xE000E400U) -#define SCB_CPACR *((uint32_t volatile *)0xE000ED88U) -#define FPU_FPCCR *((uint32_t volatile *)0xE000EF34U) -#define NVIC_PEND 0xE000E200 -#define SCB_ICSR 0xE000ED04 - -// helper macros to "stringify" values -#define VAL(x) #x -#define STRINGIFY(x) VAL(x) - -//============================================================================ -// interrupts and critical section... -// -// NOTE: -// The following interrupt disabling/enabling as well as critical section -// entry/exit functions are defined as "weak" so that they can be -// re-implemented differently at the application level. -// -// NOTE: -// For best performance, these functions are implemented in assembly, -// but they can be implemented in C as well. - - -//std::int32_t volatile QF_int_lock_nest_; // not used -extern char const QF_port_module_[]; -char const QF_port_module_[] = "qxk_port"; - -//............................................................................ -// Unconditionally disable interrupts. -// -// description: -// On ARMv6-M, interrupts are disabled with the PRIMASK register. -// On ARMv7-M and higher, interrupts are disabled *selectively* with the -// BASEPRI register. -// Additionally, the function also asserts that the interrupts are -// NOT disabled upon the entry to the function. -__attribute__ ((naked, weak)) void QF_int_disable_(void) { -__asm volatile ( -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK - " CPSID i \n" // set PRIMASK -#else //--------- ARMv7-M or higher - " 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 - " CMP r0,#0 \n" // assert(PRIMASK/BASEPRI == 0) - " BNE QF_int_disable_error\n" - " BX lr \n" - "QF_int_disable_error: \n" - " LDR r0,=QF_port_module_ \n" - " MOVS r1,#100 \n" - " LDR r2,=Q_onError \n" - " BX r2 \n" - ); -} -//............................................................................ -// Unconditionally enable interrupts. -// -// description: -// On ARMv6-M, interrupts are enabled with the PRIMASK register. -// On ARMv7-M and higher, interrupts are enabled with the BASEPRI register. -// Additionally, the function also asserts that the interrupts ARE -// disabled upon the entry to the function. -// -// NOTE: -// QF_int_enable_() is NOT allowed to push anything on the stack -// (see NOTE-1 at the end of QXK_thread_ret(). -__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 - " MRS r0,BASEPRI \n" // r0 <- previous BASEPRI -#endif //--------- ARMv7-M or higher - " 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 - " MOVS r1,#0 \n" - " MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK -#endif //--------- ARMv7-M or higher - " BX lr \n" - "QF_int_enable_error: \n" - " LDR r0,=QF_port_module_ \n" - " MOVS r1,#101 \n" - " LDR r2,=Q_onError \n" - " BX r2 \n" - ); -} -//............................................................................ -// Enter QF critical section. -// -// 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. -// Additionally, the function also asserts that the interrupts are -// NOT disabled upon the entry to the function. -// -// NOTE: -// The assertion means that this critical section CANNOT nest. -__attribute__ ((naked, weak)) void QF_crit_entry_(void) { -__asm volatile ( -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK - " CPSID i \n" // set PRIMASK -#else //--------- ARMv7-M or higher - " 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 - " CMP r0,#0 \n" // assert(PRIMASK/BASEPRI == 0) - " BNE QF_crit_entry_error\n" - " BX lr \n" - "QF_crit_entry_error: \n" - " LDR r0,=QF_port_module_ \n" - " MOVS r1,#110 \n" - " LDR r2,=Q_onError \n" - " BX r2 \n" - ); -} -//............................................................................ -// Exit QF critical section. -// -// 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. -// Additionally, the function also asserts that the interrupts ARE -// disabled upon the entry to the function. -// -// NOTE: -// The assertion 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 - " MRS r0,BASEPRI \n" // r0 <- previous BASEPRI -#endif //--------- ARMv7-M or higher - " 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 - " MOVS r1,#0 \n" - " MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK -#endif //--------- ARMv7-M or higher - " BX lr \n" - "QF_crit_exit_error: \n" - " LDR r0,=QF_port_module_ \n" - " MOVS r1,#111 \n" - " LDR r2,=Q_onError \n" - " BX r2 \n" - ); -} - -//============================================================================ -// Initialize the exception priorities and IRQ priorities to safe values. -// -// description: -// On ARMv7-M or higher, this QF port disables interrupts by means of the -// 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. -// This avoids breaching of the QF critical sections in case the -// application programmer forgets to explicitly set priorities of all -// "kernel aware" interrupts. -// -// The interrupt priorities established in QXK_init() can be later -// changed by the application-level code. -void QXK_init(void) { - -#if (__ARM_ARCH != 6) //--------- if ARMv7-M and higher... - - // SCB_SYSPRI[2]: SysTick - SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_BASEPRI << 24U)); - - // set all 240 possible IRQ priories to QF_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; - } - -#endif //--------- ARMv7-M or higher - - // SCB_SYSPRI[2]: PendSV set to priority 0xFF (lowest) - SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (0xFFU << 16U)); - -#ifdef QXK_USE_IRQ_NUM //--------- QXK IRQ specified? - // The QXK port is configured to use a given ARM Cortex-M IRQ # - // to return to thread mode (default is to use the NMI exception) - NVIC_IP[QXK_USE_IRQ_NUM] = 0U; // priority 0 (highest) - NVIC_EN[QXK_USE_IRQ_NUM >> 5U] = (1U << (QXK_USE_IRQ_NUM & 0x1FU)); -#endif //--------- QXK IRQ specified - -#ifdef __ARM_FP //--------- if VFP available... - // make sure that the FPU is enabled by setting CP10 & CP11 Full Access - SCB_CPACR = (SCB_CPACR | ((3UL << 20U) | (3UL << 22U))); - - // FPU automatic state preservation (ASPEN) lazy stacking (LSPEN) - FPU_FPCCR = (FPU_FPCCR | (1U << 30U) | (1U << 31U)); -#endif //--------- VFP available -} - -//============================================================================ -// The PendSV exception is used for performing asynchronous preemption in QXK. -// The use of the PendSV exception is the recommended and most efficient -// method for performing context switches in ARM Cortex-M. -// -// The PendSV exception should have the lowest interrupt priority in the system -// (0xFF, see QXK_init()). All other exceptions and interrupts should have -// higher interrupt priority. -// -// Also, *all* "kernel aware" ISRs in the QXK application must call the -// QXK_ISR_EXIT() macro, which triggers PendSV when it detects a need for -// asynchronous preemption. -// -// Due to tail-chaining and its lowest priority, the PendSV exception will be -// entered immediately after the exit from the *last* nested interrupt (or -// exception). In QXK, this is exactly the time when the QXK activator needs to -// handle the asynchronous preemption. -// -// NOTE: -// The inline GNU assembler does not accept mnemonics MOVS, LSRS and ADDS, -// but for Cortex-M0/M0+/M1 the mnemonics MOV, LSR and ADD always set the -// condition flags in the PSR. -__attribute__ ((naked, optimize("-fno-stack-protector"))) -void PendSV_Handler(void) { -__asm volatile ( - - //<<<<<<<<<<<<<<<<<<<<<<< CRITICAL SECTION BEGIN <<<<<<<<<<<<<<<<<<<<<<<< - " PUSH {r0,lr} \n" // save stack-aligner + EXC_RETURN - " LDR r0,=QF_int_disable_ \n" - " BLX r0 \n" // call QF_int_disable_() - -#ifdef QF_MEM_ISOLATE - " LDR r0,=QF_onMemSys \n" - " BLX r0 \n" // call QF_onMemSys() -#endif - " POP {r0,r1} \n" // restore the aligner + EXC_RETURN in r1 - " MOV lr,r1 \n" // restore EXC_RETURN into lr - - // The PendSV exception handler can be preempted by an interrupt, - // which might pend PendSV exception again. The following write to - // ICSR[27] un-pends any such spurious instance of PendSV. - " MOV r1,#1 \n" - " LSL r1,r1,#27 \n" // r1 := (1 << 27) (UNPENDSVSET bit) - " LDR r2,=" STRINGIFY(SCB_ICSR) "\n" // Interrupt Control and State - " STR r1,[r2] \n" // ICSR[27] := 1 (un-pend PendSV) - - // Check QXK_priv_.next, which contains the pointer to the next thread - // to run, which is set in QXK_ISR_EXIT(). Return if QXK_priv_.next == 0 - " LDR r3,=QXK_priv_ \n" - " LDR r0,[r3,#" STRINGIFY(QXK_NEXT) "]\n" // r1 := QXK_priv_.next - " CMP r0,#0 \n" // is (QXK_priv_.next == 0)? - " BEQ PendSV_return \n" // branch if (QXK_priv_.next == 0) - - // Load pointers into registers... - " MOV r12,r0 \n" // save QXK_priv_.next in r12 - " LDR r2,[r0,#" STRINGIFY(QACTIVE_OSOBJ) "]\n" // r2 := QXK_priv_.next->osObject - " LDR r1,[r3,#" STRINGIFY(QXK_CURR) "]\n" // r1 := QXK_priv_.curr - - " CMP r1,#0 \n" // (QXK_priv_.curr != 0)? - " BNE PendSV_save_ex \n" // branch if (current thread is extended) - - " CMP r2,#0 \n" // (QXK_priv_.next->osObject != 0)? - " BNE PendSV_save_ao \n" // branch if (next thread is extended) - - "PendSV_activate: \n" -#ifdef __ARM_FP //--------- if VFP available... - " TST lr,#(1 << 4) \n" // is it return with the VFP exception frame? - " IT EQ \n" // if lr[4] is zero... - " VSTMDBEQ sp!,{s16-s31} \n" // ... save VFP registers s16..s31 - " PUSH {r0,lr} \n" // save the "aligner" and the EXC_RETURN value -#endif // VFP available - // The QXK activator must be called in a Thread mode, while this code - // executes in the Handler mode of the PendSV exception. The switch - // to the Thread mode is accomplished by returning from PendSV using - // a fabricated exception stack frame, where the return address is - // QXK_activate_(). - // - // NOTE: the QXK activator is called with interrupts DISABLED and also - // returns with interrupts DISABLED. - " MOV r3,#1 \n" - " LSL r3,r3,#24 \n" // r3 := (1 << 24), set T bit (new xpsr) - " LDR r2,=QXK_activate_\n" // address of QXK_activate_ - " SUB r2,r2,#1 \n" // align Thumb-address at halfword (new pc) - " LDR r1,=QXK_thread_ret\n" // return address after the call (new lr) - - " SUB sp,sp,#(8*4) \n" // reserve space for exception stack frame - " ADD r0,sp,#(5*4) \n" // r0 := 5 registers below the SP - " STM r0!,{r1-r3} \n" // save xpsr,pc,lr - - " MOV r0,#6 \n" - " MVN r0,r0 \n" // r0 := ~6 == 0xFFFFFFF9 -#if (__ARM_ARCH != 6) // ARMv7-M or higher - " DSB \n" // ARM Erratum 838869 -#endif // ARMv7-M or higher - " BX r0 \n" // exception-return to the QXK activator - - //======================================================================== - // Saving AO-thread before crossing to eXtended-thread - // expected register contents: - // r0 -> QXK_priv_.next / basic-thread - // r1 -> QXK_priv_.curr / basic-thread - // r2 -> QXK_priv_.next->osObject (SP) - // r3 -> &QXK_priv_ - // r12 -> QXK_priv_.next / basic-thread - "PendSV_save_ao: \n" -#if (__ARM_ARCH == 6) // if ARMv6-M... - " SUB sp,sp,#(8*4) \n" // make room for 8 registers r4-r11 - " MOV r0,sp \n" // r0 := temporary stack pointer - " STMIA r0!,{r4-r7} \n" // save the low registers - " MOV r4,r8 \n" // move the high registers to low registers... - " MOV r5,r9 \n" - " MOV r6,r10 \n" - " MOV r7,r11 \n" - " STMIA r0!,{r4-r7} \n" // save the high registers - " MOV r0,r12 \n" // restore QXK_priv_.next in r0 -#else // ARMv7-M or higher - " PUSH {r4-r11} \n" // save r4-r11 on top of the exception frame -#ifdef __ARM_FP //--------- if VFP available... - " TST lr,#(1 << 4) \n" // is it return with the VFP exception frame? - " IT EQ \n" // if lr[4] is zero... - " VSTMDBEQ sp!,{s16-s31} \n" // ... save VFP registers s16..s31 - " PUSH {r0,lr} \n" // save the "aligner" and the EXC_RETURN value -#endif // VFP available -#endif // ARMv7-M or higher - - " CMP r2,#0 \n" - " BNE PendSV_restore_ex\n" // branch if (QXK_priv_.next->osObject != 0) - // otherwise continue to restoring next AO-thread... - - //------------------------------------------------------------------------ - // Restoring AO-thread after crossing from eXtended-thread - // expected register contents: - // r1 -> QXK_priv_.curr / basic-thread - // r2 -> QXK_priv_.next->osObject (SP) - // r3 -> &QXK_priv_ - // r12 -> QXK_priv_.next / basic-thread - "PendSV_restore_ao: \n" - // don NOT clear QXK_priv_.curr or QXK_priv_.next, - // as they might be needed for AO activation - -#if (__ARM_ARCH == 6) // if ARMv6-M... - " MOV r0,sp \n" // r0 := top of stack - " MOV r2,r0 \n" - " ADD r2,r2,#(4*4) \n" // point r2 to the 4 high registers r7-r11 - " LDMIA r2!,{r4-r7} \n" // pop the 4 high registers into low registers - " MOV r8,r4 \n" // move low registers into high registers - " MOV r9,r5 \n" - " MOV r10,r6 \n" - " MOV r11,r7 \n" - " LDMIA r0!,{r4-r7} \n" // pop the low registers - " ADD sp,sp,#(8*4) \n" // remove 8 registers from the stack - - " MOV r2,#6 \n" - " MVN r2,r2 \n" // r2 := ~6 == 0xFFFFFFF9 - " MOV lr,r2 \n" // make sure MSP is used -#else // ARMv7-M or higher -#ifdef __ARM_FP //--------- if VFP available... - " POP {r0,lr} \n" // restore aligner and EXC_RETURN into lr - " DSB \n" // ARM Erratum 838869 - " TST lr,#(1 << 4) \n" // is it return to the VFP exception frame? - " IT EQ \n" // if EXC_RETURN[4] is zero... - " VLDMIAEQ sp!,{s16-s31} \n" // ... restore VFP registers s16..s31 -#else - " BIC lr,lr,#(1 << 2) \n" // make sure MSP is used -#endif // VFP available - " POP {r4-r11} \n" // restore r4-r11 from the next thread's stack -#endif // ARMv7-M or higher - - " MOV r0,r12 \n" // r0 := QXK_priv_.next - " MOV r2,#" STRINGIFY(QACTIVE_PRIO) "\n" // r2 := offset of .prio - " LDRB r0,[r0,r2] \n" // r0 := QXK_priv_.next->prio - " LDR r2,[r3,#" STRINGIFY(QXK_ACT_PRIO) "]\n" // r2 := QXK_priv_.actPrio - " CMP r2,r0 \n" - " BCC PendSV_activate \n" // if (next->prio > actPrio) activate the next AO - - // otherwise no activation needed... - " MOV r2,#0 \n" - " STR r2,[r3,#" STRINGIFY(QXK_CURR) "]\n" // QXK_priv_.curr := 0 - " STR r2,[r3,#" STRINGIFY(QXK_NEXT) "]\n" // QXK_priv_.next := 0 - - " PUSH {r0,lr} \n" // save the aligner + EXC_RETURN -#if defined(Q_SPY) || defined(QF_ON_CONTEXT_SW) - " CMP r0,#0 \n" // r0 == QXK_priv_.next->prio - " BEQ PendSV_idle \n" // if (QXK_priv_.next->prio != 0) - " MOV r0,r12 \n" // r0 := parameter 'next' for QXK_contextSw_() - "PendSV_idle: \n" - " LDR r3,=QXK_contextSw_ \n" - " BLX r3 \n" // call QXK_contextSw_() -#endif // defined(Q_SPY) || defined(QF_ON_CONTEXT_SW) - " B PendSV_return1 \n" // skip over saving aligner + EXC_RETURN - - // re-enable interrupts and return from PendSV - "PendSV_return: \n" - " PUSH {r0,lr} \n" // save the aligner + EXC_RETURN - - "PendSV_return1: \n" -#ifdef QF_MEM_ISOLATE - " LDR r3,=QF_onMemApp \n" - " BLX r3 \n" // call QF_onMemApp() -#endif - " LDR r0,=QF_int_enable_ \n" - " BLX r0 \n" // call QF_int_enable_() - //>>>>>>>>>>>>>>>>>>>>>>>> CRITICAL SECTION END >>>>>>>>>>>>>>>>>>>>>>>>> - - " POP {r0,pc} \n" // return to the preempted AO-thread - - //------------------------------------------------------------------------ - // Saving extended-thread - // expected register contents: - // r0 -> QXK_priv_.next / basic-thread - // r1 -> QXK_priv_.curr / basic-thread - // r2 -> QXK_priv_.next->osObject (SP) - // r3 -> &QXK_priv_ - // r12 -> QXK_priv_.next / basic-thread - "PendSV_save_ex: \n" - " MRS r0,PSP \n" // r0 := Process Stack Pointer -#if (__ARM_ARCH == 6) // if ARMv6-M... - " SUB r0,r0,#(8*4) \n" // make room for 8 registers r4-r11 - " MOV r1,r0 \n" // r1 := temporary PSP (do not clobber r0!) - " STMIA r1!,{r4-r7} \n" // save the low registers - " MOV r4,r8 \n" // move the high registers to low registers... - " MOV r5,r9 \n" - " MOV r6,r10 \n" - " MOV r7,r11 \n" - " STMIA r1!,{r4-r7} \n" // save the high registers - // NOTE: at this point r0 holds the top of stack - - " LDR r1,[r3,#" STRINGIFY(QXK_CURR) "]\n" // r1 := QXK_priv_.curr (restore value) -#else // ARMv7-M or higher - " ISB \n" // reset pipeline after fetching PSP - " STMDB r0!,{r4-r11} \n" // save r4-r11 on top of the exception frame -#ifdef __ARM_FP //--------- if VFP available... - " TST lr,#(1 << 4) \n" // is it return with the VFP exception frame? - " IT EQ \n" // if lr[4] is zero... - " VSTMDBEQ r0!,{s16-s31} \n" // ... save VFP registers s16..s31 - " STMDB r0!,{r1,lr} \n" // save the "aligner" and the EXC_RETURN value -#endif // VFP available -#endif // ARMv7-M or higher - - // store the SP of the current extended-thread - " STR r0,[r1,#" STRINGIFY(QACTIVE_OSOBJ) "]\n" // QXK_priv_.curr->osObject := r0 - " MOV r0,r12 \n" // QXK_priv_.next (restore value) - - " CMP r2,#0 \n" - " BEQ PendSV_restore_ao\n" // branch if (QXK_priv_.next->osObject == 0) - // otherwise continue to restoring next extended-thread... - - //------------------------------------------------------------------------ - // Restoring extended-thread - // expected register contents: - // r0 -> QXK_priv_.next / basic-thread - // r1 -> QXK_priv_.curr / basic-thread - // r2 -> QXK_priv_.next->osObject (SP) - // r3 -> &QXK_priv_ - // r12 -> QXK_priv_.next / basic-thread - "PendSV_restore_ex: \n" - " STR r0,[r3,#" STRINGIFY(QXK_CURR) "]\n" // QXK_priv_.curr := r0 (QXK_priv_.next) - " MOV r0,#0 \n" - " STR r0,[r3,#" STRINGIFY(QXK_NEXT) "]\n" // QXK_priv_.next := 0 - - " PUSH {r0-r2,lr} \n" // save next, osObject, EXC_RETURN -#if defined(Q_SPY) || defined(QF_ON_CONTEXT_SW) - " MOV r0,r12 \n" // r0 := parameter 'next' for QXK_contextSw_() - " LDR r3,=QXK_contextSw_ \n" - " BLX r3 \n" // call QXK_contextSw_() -#ifdef QF_MEM_ISOLATE - " LDR r3,=QF_onMemApp \n" - " BLX r3 \n" // call QF_onMemApp() -#endif -#endif // defined(Q_SPY) || defined(QF_ON_CONTEXT_SW) - - - // exit the critical section - " LDR r3,=QF_int_enable_ \n" - " BLX r3 \n" // call QF_int_enable_() - " POP {r0-r3} \n" // restore next, osObject, EXC_RETURN - " MOV lr,r3 \n" // restore the EXC_RETURN into lr - -#if (__ARM_ARCH == 6) // if ARMv6-M... - " MOV r0,r2 \n" // r2 := top of stack - " ADD r0,r0,#(4*4) \n" // point r0 to the 4 high registers r7-r11 - " LDMIA r0!,{r4-r7} \n" // pop the 4 high registers into low registers - " MOV r8,r4 \n" // move low registers into high registers - " MOV r9,r5 \n" - " MOV r10,r6 \n" - " MOV r11,r7 \n" - " LDMIA r2!,{r4-r7} \n" // pop the low registers - " MOV r2,r0 \n" // r2 := holds the new top of stack - - " MOV r1,#2 \n" - " MVN r1,r1 \n" // r1 := ~2 == 0xFFFFFFFD - " MOV lr,r1 \n" // make sure PSP is used -#else // ARMv7-M or higher -#ifdef __ARM_FP //--------- if VFP available... - " LDMIA r2!,{r1,lr} \n" // restore aligner and EXC_RETURN into lr - " TST lr,#(1 << 4) \n" // is it return to the VFP exception frame? - " IT EQ \n" // if lr[4] is zero... - " VLDMIAEQ r2!,{s16-s31} \n" // ... restore VFP registers s16..s31 -#else - " ORR lr,lr,#(1 << 2) \n" // make sure PSP is used -#endif // VFP available - " LDMIA r2!,{r4-r11} \n" // restore r4-r11 from the next thread's stack -#endif // ARMv7-M or higher - - // set the PSP to the next thread's SP - " MSR PSP,r2 \n" // Process Stack Pointer := r2 - -#if (__ARM_ARCH != 6) // if ARMv7-M or higher... - " DSB \n" // ARM Erratum 838869 -#endif // ARMv7-M or higher - " BX lr \n" // return to the next extended-thread - ); -} - -//============================================================================ -// QXK_thread_ret is a helper function executed when the QXK activator returns. -// -// NOTE: QXK_thread_ret() does not execute in the PendSV context! -// NOTE: QXK_thread_ret() is entered with interrupts DISABLED. -__attribute__ ((naked, used)) -void QXK_thread_ret(void) { -__asm volatile ( - - // After the QXK activator returns, we need to resume the preempted - // thread. However, this must be accomplished by a return-from-exception, - // while we are still in the thread context. The switch to the exception - // context is accomplished by triggering the NMI exception or the selected - // IRQ (if macro #QXK_USE_IRQ_NUM is defined). - - // before triggering the NMI/IRQ, make sure that the VFP stack frame - // will NOT be used... -#ifdef __ARM_FP //--------- if VFP available... - // make sure that the VFP stack frame will NOT be used - " MRS r0,CONTROL \n" // r0 := CONTROL - " BIC r0,r0,#4 \n" // r0 := r0 & ~4 (FPCA bit) - " MSR CONTROL,r0 \n" // CONTROL := r0 (clear CONTROL[2] FPCA bit) - " ISB \n" // ISB after MSR CONTROL (ARM AN321,Sect.4.16) -#endif //--------- VFP available - - // NOTE: the following function calls corrupt lr, but it is NOT - // used to return from QXK_thread_ret(). Instead QXK_thread_ret() - // "returns" by entering an exception (either NMI or IRQ). -#ifdef QF_MEM_ISOLATE - " LDR r0,=QF_onMemApp \n" - " BLX r0 \n" // call QF_onMemApp() -#endif - -#ifndef QXK_USE_IRQ_NUM //--------- IRQ NOT defined, use NMI by default - " LDR r0,=" STRINGIFY(SCB_ICSR) "\n" // Interrupt Control and State - " MOV r1,#1 \n" - " LSL r1,r1,#31 \n" // r1 := (1 << 31) (NMI bit) - " STR r1,[r0] \n" // ICSR[31] := 1 (pend NMI) - // NOTE! interrupts are still disabled when NMI is entered - -#else //--------- use the selected IRQ - " LDR r0,=" STRINGIFY(NVIC_PEND + ((QXK_USE_IRQ_NUM >> 5) << 2)) "\n" - " MOV r1,#1 \n" - " LSL r1,r1,#" STRINGIFY(QXK_USE_IRQ_NUM & 0x1F) "\n" // r1 := IRQ bit - " STR r1,[r0] \n" // pend the IRQ - - // now enable interrupts so that pended IRQ can be entered - // - // NOTE-1: - // The IRQ preempts immediately after interrupts are enabled, - // without cleanly returning from QF_int_enable_(). Therefore - // QF_int_enable_() is NOT allowed to push anything on the stack - // because the stack is NOT restored when the IRQ preempts. - " LDR r0,=QF_int_enable_ \n" - " BLX r0 \n" // call QF_int_enable_() -#endif //--------- use IRQ - - " B . \n" // wait for preemption by NMI/IRQ - ); -} - -//============================================================================ -// This exception handler is used for returning back to the preempted thread. -// The exception handler simply removes its own interrupt stack frame from -// the stack (MSP) and returns to the preempted task using the interrupt -// stack frame that must be at the top of the stack. -__attribute__ ((naked, optimize("-fno-stack-protector"))) -#ifndef QXK_USE_IRQ_NUM //--------- IRQ NOT defined, use NMI by default - -// NOTE: The NMI_Handler() is entered with interrupts still DISABLED! -void NMI_Handler(void) { -__asm volatile ( - // call QF_int_enable_(), NOTE: corrupts lr (EXC_RETURN) - // but see code after "BLX r0" - " LDR r0,=QF_int_enable_ \n" - " BLX r0 \n" // call QF_int_enable_() -#ifdef __ARM_FP //--------- if VFP available... - // When VFP is available, lr (EXC_RETURN) is restored from the stack - // before returning from exception, so the value in lr doesn't matter -#else //--------- VFP NOT available - // lr (EXC_RETURN) can be synthesized because it is known (0xFFFFFFF9): - // - return to Thread mode; - // - exception return uses non-floating-point state from MSP; - // - execution uses MSP after return. - " MOV r0,#6 \n" - " MVN r0,r0 \n" // r0 := ~6 == 0xFFFFFFF9 - " MOV lr,r0 \n" // lr := 0xFFFFFFF9 (EXC_RETURN) -#endif //--------- VFP NOT available -); - -#else //--------- IRQ defined, use the selected IRQ - -// NOTE: The IRQ Handler is entered with interrupts already ENABLED -void QXK_USE_IRQ_HANDLER(void) { -#endif //--------- IRQ defined - - // ...continue here from either NMI or IRQ -__asm volatile ( - " ADD sp,sp,#(8*4) \n" // remove one 8-register exception frame - -#ifdef __ARM_FP //--------- if VFP available... - " POP {r0,lr} \n" // restore aligher and EXC_RETURN into lr - " DSB \n" // ARM Erratum 838869 - " TST lr,#(1 << 4) \n" // is it return to the VFP exception frame? - " IT EQ \n" // if EXC_RETURN[4] is zero... - " VLDMIAEQ sp!,{s16-s31} \n" // ... restore VFP registers s16..s31 -#endif //--------- VFP available - " BX lr \n" // return to the preempted task - ); -} - -//============================================================================ -#if (__ARM_ARCH == 6) // if ARMv6-M... - -// hand-optimized quick LOG2 in assembly (no CLZ instruction in ARMv6-M) -// NOTE: -// The inline GNU assembler does not accept mnemonics MOVS, LSRS and ADDS, -// but for ARMv6-M the mnemonics MOV, LSR and ADD always set the condition -// flags in the PSR. -__attribute__ ((naked, optimize("-fno-stack-protector"))) -uint_fast8_t QF_qlog2(uint32_t x) { - Q_UNUSED_PAR(x); -__asm volatile ( - " MOV r1,#0 \n" -#if (QF_MAX_ACTIVE > 16U) - " LSR r2,r0,#16 \n" - " BEQ QF_qlog2_1 \n" - " MOV r1,#16 \n" - " MOV r0,r2 \n" - "QF_qlog2_1: \n" -#endif -#if (QF_MAX_ACTIVE > 8U) - " LSR r2,r0,#8 \n" - " BEQ QF_qlog2_2 \n" - " ADD r1, r1,#8 \n" - " MOV r0, r2 \n" - "QF_qlog2_2: \n" -#endif - " LSR r2,r0,#4 \n" - " BEQ QF_qlog2_3 \n" - " ADD r1,r1,#4 \n" - " MOV r0,r2 \n" - "QF_qlog2_3: \n" - " LDR r2,=QF_qlog2_LUT \n" - " LDRB r0,[r2,r0] \n" - " ADD r0,r1,r0 \n" - " BX lr \n" - " .align \n" - "QF_qlog2_LUT: \n" - " .byte 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4" - ); -} - -#endif // ARMv6-M - -} // extern "C" - diff --git a/ports/arm-cm/qxk/iar/qp_port.hpp b/ports/arm-cm/qxk/iar/qp_port.hpp deleted file mode 100644 index 1dd4a7c1c..000000000 --- a/ports/arm-cm/qxk/iar/qp_port.hpp +++ /dev/null @@ -1,230 +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 . -// -// 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-12-03 -//! @version Last updated for: @ref qpcpp_7_3_1 -//! -//! @file -//! @brief QP/C++ port to ARM Cortex-M, dual-mode QXK kernel, IAR-ARM - -#ifndef QP_PORT_HPP_ -#define QP_PORT_HPP_ - -#include // Exact-width types. C++11 Standard -#include // IAR intrinsic functions - -#ifdef QP_CONFIG -#include "qp_config.hpp" // external QP configuration -#endif - -// no-return function specifier (C++11 Standard) -#define Q_NORETURN [[ noreturn ]] void - -// QF configuration for QXK -- data members of the QActive class... - -// QActive event-queue type used for AOs and eXtended threads. -#define QACTIVE_EQUEUE_TYPE QEQueue - -// QActive OS-Object type used for the private stack pointer for eXtended threads. -// (The private stack pointer is NULL for basic-threads). -#define QACTIVE_OS_OBJ_TYPE void* - -// QActive "thread" type used to store the MPU settings in the AO -#define QACTIVE_THREAD_TYPE void const * - -// QF interrupt disable/enable and log2()... -#if (__ARM_ARCH == 6) // ARMv6-M? - - // CMSIS threshold for "QF-aware" interrupts, see NOTE2 and NOTE4 - #define QF_AWARE_ISR_CMSIS_PRI 0 - - // hand-optimized LOG2 in assembly for Cortex-M0/M0+/M1(v6-M, v6S-M) - #define QF_LOG2(n_) QF_qlog2(static_cast(n_)) - -#else // ARMv7-M or higher - - // BASEPRI threshold for "QF-aware" interrupts, see NOTE3 - #define QF_BASEPRI 0x3F - - // CMSIS threshold for "QF-aware" interrupts, see NOTE4 - #define QF_AWARE_ISR_CMSIS_PRI (QF_BASEPRI >> (8 - __NVIC_PRIO_BITS)) - - // ARMv7-M or higher provide the CLZ instruction for fast LOG2 - #define QF_LOG2(n_) \ - (static_cast(32U - __CLZ((n_)))) - -#endif - -// interrupt disabling policy, see NOTE2 and NOTE3 -#define QF_INT_DISABLE() (QF_int_disable_()) -#define QF_INT_ENABLE() (QF_int_enable_()) - -// QF critical section, see NOTE1, NOTE2, and NOTE3 -#define QF_CRIT_STAT -#define QF_CRIT_ENTRY() (QF_crit_entry_()) -#define QF_CRIT_EXIT() (QF_crit_exit_()) - -#define QF_CRIT_EXIT_NOP() __ISB() - -#if (__ARM_ARCH == 6) // ARMv6-M? - // hand-optimized quick LOG2 in assembly - extern "C" std::uint_fast8_t QF_qlog2(std::uint32_t x); -#endif // ARMv7-M or higher - -// Memory isolation ---------------------------------------------------------- -#ifdef QF_MEM_ISOLATE - - // Memory isolation requires the context-switch - #define QF_ON_CONTEXT_SW 1U - - // Memory System setting - #define QF_MEM_SYS() QF_onMemSys() - - // Memory Application setting - #define QF_MEM_APP() QF_onMemApp() - - // callback functions for memory settings (provided by applications) - extern "C" void QF_onMemSys(void); - extern "C" void QF_onMemApp(void); - -#endif // def QF_MEM_ISOLATE - -// determination if the code executes in the ISR context -#define QXK_ISR_CONTEXT_() (__get_IPSR() != 0U) - -// trigger the PendSV exception to perform the context switch -#define QXK_CONTEXT_SWITCH_() \ - *Q_UINT2PTR_CAST(uint32_t, 0xE000ED04U) = (1U << 28U) - -// QXK ISR entry and exit -#define QXK_ISR_ENTRY() ((void)0) - -#ifdef QF_MEM_ISOLATE - #define QXK_ISR_EXIT() do { \ - QF_INT_DISABLE(); \ - QF_MEM_SYS(); \ - if (QXK_sched_() != 0U) { \ - *Q_UINT2PTR_CAST(uint32_t, 0xE000ED04U) = (1U << 28U);\ - } \ - QF_MEM_APP(); \ - QF_INT_ENABLE(); \ - QXK_ARM_ERRATUM_838869(); \ - } while (false) -#else - #define QXK_ISR_EXIT() do { \ - QF_INT_DISABLE(); \ - if (QXK_sched_() != 0U) { \ - *Q_UINT2PTR_CAST(uint32_t, 0xE000ED04U) = (1U << 28U);\ - } \ - QF_INT_ENABLE(); \ - QXK_ARM_ERRATUM_838869(); \ - } while (false) -#endif - -#if (__ARM_ARCH == 6) // ARMv6-M? - #define QXK_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. - #define QXK_ARM_ERRATUM_838869() __DSB() - -#endif // ARMv6-M - -// initialization of the QXK kernel -#define QXK_INIT() QXK_init() -extern "C" void QXK_init(void); -extern "C" void QXK_thread_ret(void); - -#ifdef __ARM_FP //--------- if VFP available... -// When the FPU is configured, clear the FPCA bit in the CONTROL register -// to prevent wasting the stack space for the FPU context. -#define QXK_START() __set_CONTROL(0U) -#endif - -// include files ------------------------------------------------------------- -#include "qequeue.hpp" // QXK kernel uses the native QP event queue -#include "qmpool.hpp" // QXK kernel uses the native QP memory pool -#include "qp.hpp" // QP framework -#include "qxk.hpp" // QXK kernel - -// prototypes -extern "C" { - void QF_int_disable_(void); - void QF_int_enable_(void); - void QF_crit_entry_(void); - void QF_crit_exit_(void); - - extern std::int32_t volatile QF_int_lock_nest_; -} // extern "C" - -//============================================================================ -// NOTE1: -// The critical section policy does not use the "saving and restoring" -// interrupt status policy (macro QF_CRIT_STAT is defined to nothing). -// However, this the QF critical sections might still be able to nest, -// depending on the implementation of the QF_crit_entry_()/QF_crit_exit_() -// 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. -// -// NOTE2: -// On Cortex-M0/M0+/M1 (architecture ARMv6-M, ARMv6S-M), the interrupt -// disabling policy uses the PRIMASK register to disable interrupts globally. -// The QF_AWARE_ISR_CMSIS_PRI level is zero, meaning that all interrupts -// 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. -// 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 -// ("kernel-aware" interrupts ), can call QF services. -// -// NOTE4: -// The QF_AWARE_ISR_CMSIS_PRI macro is useful as an offset for enumerating -// the "QF-aware" interrupt priorities in the applications, whereas the -// numerical values of the "QF-aware" interrupts must be greater or equal to -// QF_AWARE_ISR_CMSIS_PRI. The values based on QF_AWARE_ISR_CMSIS_PRI can be -// passed directly to the CMSIS function NVIC_SetPriority(), which shifts -// them by (8 - __NVIC_PRIO_BITS) into the correct bit position, while -// __NVIC_PRIO_BITS is the CMSIS macro defining the number of implemented -// priority bits in the NVIC. Please note that the macro QF_AWARE_ISR_CMSIS_PRI -// is intended only for applications and is not used inside the QF port, which -// remains generic and not dependent on the number of implemented priority bits -// implemented in the NVIC. - -#endif // QP_PORT_HPP_ - diff --git a/ports/arm-cm/qxk/iar/qs_port.hpp b/ports/arm-cm/qxk/iar/qs_port.hpp deleted file mode 100644 index 4ddb938b5..000000000 --- a/ports/arm-cm/qxk/iar/qs_port.hpp +++ /dev/null @@ -1,57 +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: 2024-06-06 -//! @version Last updated for: @ref qpcpp_7_4_0 -//! -//! @file -//! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler - -#ifndef QS_PORT_HPP_ -#define QS_PORT_HPP_ - -// 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.hpp" -// *before* "qs.hpp". -#ifndef QP_PORT_HPP_ -#include "qp_port.hpp" // use QS with QP -#endif - -#include "qs.hpp" // QS platform-independent public interface - -#endif // QS_PORT_HPP_ diff --git a/ports/arm-cm/qxk/iar/qxk_port.cpp b/ports/arm-cm/qxk/iar/qxk_port.cpp deleted file mode 100644 index 9bf581d8d..000000000 --- a/ports/arm-cm/qxk/iar/qxk_port.cpp +++ /dev/null @@ -1,812 +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 . -// -// 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: 2024-05-28 -//! @version Last updated for: @ref qpcpp_7_3_5 -//! -//! @file -//! @brief QXK/C++ port to ARM Cortex-M, IAR-ARM - -#define QP_IMPL 1U -#include "qp_port.hpp" -#include "qp_pkg.hpp" -#include "qsafe.h" // QP Functional Safety (FuSa) System - -#include // for offsetof() - -//============================================================================ -// NOTE: keep in synch with struct QXK_Attr in "qxk.hpp" !!! -#define QXK_CURR 0 -#define QXK_NEXT 4 -#define QXK_ACT_PRIO 12 - -// make sure that the offsets match the QXK declaration in "qxk.hpp" -static_assert(QXK_CURR == offsetof(QXK_Attr, curr), - "QXK_Attr.curr at unexpected offset"); -static_assert(QXK_NEXT == offsetof(QXK_Attr, next), - "QXK_Attr.next at unexpected offset"); -static_assert(QXK_ACT_PRIO == offsetof(QXK_Attr, actPrio), - "QXK_Attr.actPrio at unexpected offset"); - -// offsets within struct QActive; NOTE: keep in synch with "qp.hpp" !!! -#define QACTIVE_PRIO 12 -#define QACTIVE_OSOBJ 20 - - -//============================================================================ -namespace QP { - -// Initialize the private stack of an extended QXK thread. -// -// NOTE -// The function aligns the stack to the 8-byte boundary for compatibility -// with the AAPCS. Additionally, the function pre-fills the stack with the -// known bit pattern (0xDEADBEEF). -// -// NOTE: QXK_stackInit_() must be called before the QXK kernel is made aware -// of this thread. In that case the kernel cannot use the thread yet, so no -// critical section is needed. -void QXThread::stackInit_(QP::QXThreadHandler const handler, - void * const stkSto, std::uint_fast16_t const stkSize) noexcept -{ - // make sure that the offsets match the QActive declaration in "qf.hpp" - static_assert(QACTIVE_OSOBJ == offsetof(QP::QActive, m_osObject), - "QActive.m_osObject at unexpected offset"); - static_assert(QACTIVE_PRIO == offsetof(QP::QActive, m_prio), - "QActive.m_prio at unexpected offset"); - - // round down the stack top to the 8-byte boundary - // NOTE: ARM Cortex-M stack grows down from hi -> low memory - std::uint32_t *sp = (std::uint32_t *)( - (((std::uint32_t)stkSto + stkSize) >> 3U) << 3U); - std::uint32_t *sp_limit; - - // synthesize the ARM Cortex-M exception stack frame... - *(--sp) = (1U << 24); // xPSR (just the THUMB bit) - *(--sp) = (std::uint32_t)handler; // PC (the thread handler) - *(--sp) = (std::uint32_t)&QXK_threadExit_; // LR (exit from thread) - *(--sp) = 0x0000000CU; // R12 - *(--sp) = 0x00000003U; // R3 - *(--sp) = 0x00000002U; // R2 - *(--sp) = 0x00000001U; // R1 - *(--sp) = (std::uint32_t)this; // R0 parameter to handler (thread object) - *(--sp) = 0x0000000BU; // R11 - *(--sp) = 0x0000000AU; // R10 - *(--sp) = 0x00000009U; // R9 - *(--sp) = 0x00000008U; // R8 - *(--sp) = 0x00000007U; // R7 - *(--sp) = 0x00000006U; // R6 - *(--sp) = 0x00000005U; // R5 - *(--sp) = 0x00000004U; // R4 - -#ifdef __ARM_FP //--------- if VFP available... - *(--sp) = 0xFFFFFFFDU; // exception return with VFP state - *(--sp) = 0xAAAAAAAAU; // stack "aligner" -#endif // VFP available - - // save the top of the stack in the thread's attribute - m_osObject = sp; - - // pre-fill the unused part of the stack with 0xDEADBEEF - sp_limit = (std::uint32_t *)( - ((((std::uint32_t)stkSto - 1U) >> 3U) + 1U) << 3U); - for (; sp >= sp_limit; --sp) { - *sp = 0xDEADBEEFU; - } -} - -} // namespace QP - -//============================================================================ -extern "C" { - -// prototypes ---------------------------------------------------------------- -void PendSV_Handler(void); -#ifdef QXK_USE_IRQ_HANDLER // if use IRQ... -void QXK_USE_IRQ_HANDLER(void); -#else // use default (NMI) -void NMI_Handler(void); -#endif - -#define SCB_SYSPRI ((uint32_t volatile *)0xE000ED18U) -#define NVIC_EN ((uint32_t volatile *)0xE000E100U) -#define NVIC_IP ((uint32_t volatile *)0xE000E400U) -#define SCB_CPACR *((uint32_t volatile *)0xE000ED88U) -#define FPU_FPCCR *((uint32_t volatile *)0xE000EF34U) -#define NVIC_PEND 0xE000E200 -#define SCB_ICSR 0xE000ED04 - -// helper macros to "stringify" values -#define VAL(x) #x -#define STRINGIFY(x) VAL(x) - -//============================================================================ -// interrupts and critical section... -// -// NOTE: -// The following interrupt disabling/enabling as well as critical section -// entry/exit functions are defined as "weak" so that they can be -// re-implemented differently at the application level. -// -// NOTE: -// For best performance, these functions are implemented in assembly, -// but they can be implemented in C as well. - -#pragma weak QF_int_disable_ -#pragma weak QF_int_enable_ -#pragma weak QF_crit_entry_ -#pragma weak QF_crit_exit_ - -//std::int32_t volatile QF_int_lock_nest_; // not used -extern char const QF_port_module_[]; -char const QF_port_module_[] = "qxk_port"; - -//............................................................................ -// Unconditionally disable interrupts. -// -// description: -// On ARMv6-M, interrupts are disabled with the PRIMASK register. -// On ARMv7-M and higher, interrupts are disabled *selectively* with the -// BASEPRI register. -// Additionally, the function also asserts that the interrupts are -// NOT disabled upon the entry to the function. -void QF_int_disable_(void) { -__asm volatile ( -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK - " CPSID i \n" // set PRIMASK -#else //--------- ARMv7-M or higher - " 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 - " CMP r0,#0 \n" // assert(PRIMASK/BASEPRI == 0) - " BNE QF_int_disable_error\n" - " BX lr \n" - "QF_int_disable_error: \n" - " LDR r0,=QF_port_module_ \n" - " MOVS r1,#100 \n" - " LDR r2,=Q_onError \n" - " BX r2 \n" - ); -} -//............................................................................ -// Unconditionally enable interrupts. -// -// description: -// On ARMv6-M, interrupts are enabled with the PRIMASK register. -// On ARMv7-M and higher, interrupts are enabled with the BASEPRI register. -// Additionally, the function also asserts that the interrupts ARE -// disabled upon the entry to the function. -// -// NOTE: -// QF_int_enable_() is NOT allowed to push anything on the stack -// (see NOTE-1 at the end of QXK_thread_ret(). -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 - " MRS r0,BASEPRI \n" // r0 <- previous BASEPRI -#endif //--------- ARMv7-M or higher - " 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 - " MOVS r1,#0 \n" - " MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK -#endif //--------- ARMv7-M or higher - " BX lr \n" - "QF_int_enable_error: \n" - " LDR r0,=QF_port_module_ \n" - " MOVS r1,#101 \n" - " LDR r2,=Q_onError \n" - " BX r2 \n" - ); -} -//............................................................................ -// Enter QF critical section. -// -// 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. -// Additionally, the function also asserts that the interrupts are -// NOT disabled upon the entry to the function. -// -// NOTE: -// The assertion means that this critical section CANNOT nest. -void QF_crit_entry_(void) { -__asm volatile ( -#if (__ARM_ARCH == 6) //--------- ARMv6-M architecture? - " MRS r0,PRIMASK \n" // r0 <- previous PRIMASK - " CPSID i \n" // set PRIMASK -#else //--------- ARMv7-M or higher - " 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 - " CMP r0,#0 \n" // assert(PRIMASK/BASEPRI == 0) - " BNE QF_crit_entry_error\n" - " BX lr \n" - "QF_crit_entry_error: \n" - " LDR r0,=QF_port_module_ \n" - " MOVS r1,#110 \n" - " LDR r2,=Q_onError \n" - " BX r2 \n" - ); -} -//............................................................................ -// Exit QF critical section. -// -// 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. -// Additionally, the function also asserts that the interrupts ARE -// disabled upon the entry to the function. -// -// NOTE: -// The assertion means that this critical section CANNOT nest. -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 - " MRS r0,BASEPRI \n" // r0 <- previous BASEPRI -#endif //--------- ARMv7-M or higher - " 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 - " MOVS r1,#0 \n" - " MSR BASEPRI,r1 \n" // NOTE: Cortes-M7 erratum 837070 is OK -#endif //--------- ARMv7-M or higher - " BX lr \n" - "QF_crit_exit_error: \n" - " LDR r0,=QF_port_module_ \n" - " MOVS r1,#111 \n" - " LDR r2,=Q_onError \n" - " BX r2 \n" - ); -} - -//============================================================================ -// Initialize the exception priorities and IRQ priorities to safe values. -// -// description: -// On ARMv7-M or higher, this QF port disables interrupts by means of the -// 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. -// This avoids breaching of the QF critical sections in case the -// application programmer forgets to explicitly set priorities of all -// "kernel aware" interrupts. -// -// The interrupt priorities established in QXK_init() can be later -// changed by the application-level code. -void QXK_init(void) { - -#if (__ARM_ARCH != 6) //--------- if ARMv7-M and higher... - - // SCB_SYSPRI[2]: SysTick - SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (QF_BASEPRI << 24U)); - - // set all 240 possible IRQ priories to QF_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; - } - -#endif //--------- ARMv7-M or higher - - // SCB_SYSPRI[2]: PendSV set to priority 0xFF (lowest) - SCB_SYSPRI[2] = (SCB_SYSPRI[2] | (0xFFU << 16U)); - -#ifdef QXK_USE_IRQ_NUM //--------- QXK IRQ specified? - // The QXK port is configured to use a given ARM Cortex-M IRQ # - // to return to thread mode (default is to use the NMI exception) - NVIC_IP[QXK_USE_IRQ_NUM] = 0U; // priority 0 (highest) - NVIC_EN[QXK_USE_IRQ_NUM >> 5U] = (1U << (QXK_USE_IRQ_NUM & 0x1FU)); -#endif //--------- QXK IRQ specified - -#ifdef __ARM_FP //--------- if VFP available... - // make sure that the FPU is enabled by setting CP10 & CP11 Full Access - SCB_CPACR = (SCB_CPACR | ((3UL << 20U) | (3UL << 22U))); - - // FPU automatic state preservation (ASPEN) lazy stacking (LSPEN) - FPU_FPCCR = (FPU_FPCCR | (1U << 30U) | (1U << 31U)); -#endif //--------- VFP available -} - -//============================================================================ -// The PendSV exception is used for performing asynchronous preemption in QXK. -// The use of the PendSV exception is the recommended and most efficient -// method for performing context switches in ARM Cortex-M. -// -// The PendSV exception should have the lowest interrupt priority in the system -// (0xFF, see QXK_init()). All other exceptions and interrupts should have -// higher interrupt priority. -// -// Also, *all* "kernel aware" ISRs in the QXK application must call the -// QXK_ISR_EXIT() macro, which triggers PendSV when it detects a need for -// asynchronous preemption. -// -// Due to tail-chaining and its lowest priority, the PendSV exception will be -// entered immediately after the exit from the *last* nested interrupt (or -// exception). In QXK, this is exactly the time when the QXK activator needs to -// handle the asynchronous preemption. -__stackless -void PendSV_Handler(void) { -__asm volatile ( - - //<<<<<<<<<<<<<<<<<<<<<<< CRITICAL SECTION BEGIN <<<<<<<<<<<<<<<<<<<<<<<< - " PUSH {r0,lr} \n" // save stack-aligner + EXC_RETURN - " LDR r0,=QF_int_disable_ \n" - " BLX r0 \n" // call QF_int_disable_() - -#ifdef QF_MEM_ISOLATE - " LDR r0,=QF_onMemSys \n" - " BLX r0 \n" // call QF_onMemSys() -#endif - " POP {r0,r1} \n" // restore the aligner + EXC_RETURN in r1 - " MOV lr,r1 \n" // restore EXC_RETURN into lr - - // The PendSV exception handler can be preempted by an interrupt, - // which might pend PendSV exception again. The following write to - // ICSR[27] un-pends any such spurious instance of PendSV. - " MOVS r1,#1 \n" - " LSLS r1,r1,#27 \n" // r1 := (1 << 27) (UNPENDSVSET bit) - " LDR r2,=" STRINGIFY(SCB_ICSR) "\n" // Interrupt Control and State - " STR r1,[r2] \n" // ICSR[27] := 1 (un-pend PendSV) - - // Check QXK_priv_.next, which contains the pointer to the next thread - // to run, which is set in QXK_ISR_EXIT(). Return if QXK_priv_.next == 0 - " LDR r3,=QXK_priv_ \n" - " LDR r0,[r3,#" STRINGIFY(QXK_NEXT) "]\n" // r1 := QXK_priv_.next - " CMP r0,#0 \n" // is (QXK_priv_.next == 0)? - " BEQ PendSV_return \n" // branch if (QXK_priv_.next == 0) - - // Load pointers into registers... - " MOV r12,r0 \n" // save QXK_priv_.next in r12 - " LDR r2,[r0,#" STRINGIFY(QACTIVE_OSOBJ) "]\n" // r2 := QXK_priv_.next->osObject - " LDR r1,[r3,#" STRINGIFY(QXK_CURR) "]\n" // r1 := QXK_priv_.curr - - " CMP r1,#0 \n" // (QXK_priv_.curr != 0)? - " BNE PendSV_save_ex \n" // branch if (current thread is extended) - - " CMP r2,#0 \n" // (QXK_priv_.next->osObject != 0)? - " BNE PendSV_save_ao \n" // branch if (next thread is extended) - - "PendSV_activate: \n" -#ifdef __ARM_FP //--------- if VFP available... - " TST lr,#(1 << 4) \n" // is it return with the VFP exception frame? - " IT EQ \n" // if lr[4] is zero... - " VSTMDBEQ sp!,{s16-s31} \n" // ... save VFP registers s16..s31 - " PUSH {r0,lr} \n" // save the "aligner" and the EXC_RETURN value -#endif // VFP available - // The QXK activator must be called in a Thread mode, while this code - // executes in the Handler mode of the PendSV exception. The switch - // to the Thread mode is accomplished by returning from PendSV using - // a fabricated exception stack frame, where the return address is - // QXK_activate_(). - // - // NOTE: the QXK activator is called with interrupts DISABLED and also - // returns with interrupts DISABLED. - " MOVS r3,#1 \n" - " LSLS r3,r3,#24 \n" // r3 := (1 << 24), set T bit (new xpsr) - " LDR r2,=QXK_activate_\n" // address of QXK_activate_ - " SUBS r2,r2,#1 \n" // align Thumb-address at halfword (new pc) - " LDR r1,=QXK_thread_ret\n" // return address after the call (new lr) - - " SUB sp,sp,#(8*4) \n" // reserve space for exception stack frame - " ADD r0,sp,#(5*4) \n" // r0 := 5 registers below the SP - " STM r0!,{r1-r3} \n" // save xpsr,pc,lr - - " MOVS r0,#6 \n" - " MVNS r0,r0 \n" // r0 := ~6 == 0xFFFFFFF9 -#if (__ARM_ARCH != 6) // ARMv7-M or higher - " DSB \n" // ARM Erratum 838869 -#endif // ARMv7-M or higher - " BX r0 \n" // exception-return to the QXK activator - - //======================================================================== - // Saving AO-thread before crossing to eXtended-thread - // expected register contents: - // r0 -> QXK_priv_.next / basic-thread - // r1 -> QXK_priv_.curr / basic-thread - // r2 -> QXK_priv_.next->osObject (SP) - // r3 -> &QXK_priv_ - // r12 -> QXK_priv_.next / basic-thread - "PendSV_save_ao: \n" -#if (__ARM_ARCH == 6) // if ARMv6-M... - " SUB sp,sp,#(8*4) \n" // make room for 8 registers r4-r11 - " MOV r0,sp \n" // r0 := temporary stack pointer - " STMIA r0!,{r4-r7} \n" // save the low registers - " MOV r4,r8 \n" // move the high registers to low registers... - " MOV r5,r9 \n" - " MOV r6,r10 \n" - " MOV r7,r11 \n" - " STMIA r0!,{r4-r7} \n" // save the high registers - " MOV r0,r12 \n" // restore QXK_priv_.next in r0 -#else // ARMv7-M or higher - " PUSH {r4-r11} \n" // save r4-r11 on top of the exception frame -#ifdef __ARM_FP //--------- if VFP available... - " TST lr,#(1 << 4) \n" // is it return with the VFP exception frame? - " IT EQ \n" // if lr[4] is zero... - " VSTMDBEQ sp!,{s16-s31} \n" // ... save VFP registers s16..s31 - " PUSH {r0,lr} \n" // save the "aligner" and the EXC_RETURN value -#endif // VFP available -#endif // ARMv7-M or higher - - " CMP r2,#0 \n" - " BNE PendSV_restore_ex\n" // branch if (QXK_priv_.next->osObject != 0) - // otherwise continue to restoring next AO-thread... - - //------------------------------------------------------------------------ - // Restoring AO-thread after crossing from eXtended-thread - // expected register contents: - // r1 -> QXK_priv_.curr / basic-thread - // r2 -> QXK_priv_.next->osObject (SP) - // r3 -> &QXK_priv_ - // r12 -> QXK_priv_.next / basic-thread - "PendSV_restore_ao: \n" - // don NOT clear QXK_priv_.curr or QXK_priv_.next, - // as they might be needed for AO activation - -#if (__ARM_ARCH == 6) // if ARMv6-M... - " MOV r0,sp \n" // r0 := top of stack - " MOV r2,r0 \n" - " ADDS r2,r2,#(4*4) \n" // point r2 to the 4 high registers r7-r11 - " LDMIA r2!,{r4-r7} \n" // pop the 4 high registers into low registers - " MOV r8,r4 \n" // move low registers into high registers - " MOV r9,r5 \n" - " MOV r10,r6 \n" - " MOV r11,r7 \n" - " LDMIA r0!,{r4-r7} \n" // pop the low registers - " ADD sp,sp,#(8*4) \n" // remove 8 registers from the stack - - " MOVS r2,#6 \n" - " MVNS r2,r2 \n" // r2 := ~6 == 0xFFFFFFF9 - " MOV lr,r2 \n" // make sure MSP is used -#else // ARMv7-M or higher -#ifdef __ARM_FP //--------- if VFP available... - " POP {r0,lr} \n" // restore aligner and EXC_RETURN into lr - " DSB \n" // ARM Erratum 838869 - " TST lr,#(1 << 4) \n" // is it return to the VFP exception frame? - " IT EQ \n" // if EXC_RETURN[4] is zero... - " VLDMIAEQ sp!,{s16-s31} \n" // ... restore VFP registers s16..s31 -#else - " BIC lr,lr,#(1 << 2) \n" // make sure MSP is used -#endif // VFP available - " POP {r4-r11} \n" // restore r4-r11 from the next thread's stack -#endif // ARMv7-M or higher - - " MOV r0,r12 \n" // r0 := QXK_priv_.next - " MOVS r2,#" STRINGIFY(QACTIVE_PRIO) "\n" // r2 := offset of .prio - " LDRB r0,[r0,r2] \n" // r0 := QXK_priv_.next->prio - " LDR r2,[r3,#" STRINGIFY(QXK_ACT_PRIO) "]\n" // r2 := QXK_priv_.actPrio - " CMP r2,r0 \n" - " BCC PendSV_activate \n" // if (next->prio > actPrio) activate the next AO - - // otherwise no activation needed... - " MOVS r2,#0 \n" - " STR r2,[r3,#" STRINGIFY(QXK_CURR) "]\n" // QXK_priv_.curr := 0 - " STR r2,[r3,#" STRINGIFY(QXK_NEXT) "]\n" // QXK_priv_.next := 0 - - " PUSH {r0,lr} \n" // save the aligner + EXC_RETURN -#if defined(Q_SPY) || defined(QF_ON_CONTEXT_SW) - " CMP r0,#0 \n" // r0 == QXK_priv_.next->prio - " BEQ PendSV_idle \n" // if (QXK_priv_.next->prio != 0) - " MOV r0,r12 \n" // r0 := parameter 'next' for QXK_contextSw_() - "PendSV_idle: \n" - " LDR r3,=QXK_contextSw_ \n" - " BLX r3 \n" // call QXK_contextSw_() -#endif // defined(Q_SPY) || defined(QF_ON_CONTEXT_SW) - " B PendSV_return1 \n" // skip over saving aligner + EXC_RETURN - - // re-enable interrupts and return from PendSV - "PendSV_return: \n" - " PUSH {r0,lr} \n" // save the aligner + EXC_RETURN - - "PendSV_return1: \n" -#ifdef QF_MEM_ISOLATE - " LDR r3,=QF_onMemApp \n" - " BLX r3 \n" // call QF_onMemApp() -#endif - " LDR r0,=QF_int_enable_ \n" - " BLX r0 \n" // call QF_int_enable_() - //>>>>>>>>>>>>>>>>>>>>>>>> CRITICAL SECTION END >>>>>>>>>>>>>>>>>>>>>>>>> - - " POP {r0,pc} \n" // return to the preempted AO-thread - - //------------------------------------------------------------------------ - // Saving extended-thread - // expected register contents: - // r0 -> QXK_priv_.next / basic-thread - // r1 -> QXK_priv_.curr / basic-thread - // r2 -> QXK_priv_.next->osObject (SP) - // r3 -> &QXK_priv_ - // r12 -> QXK_priv_.next / basic-thread - "PendSV_save_ex: \n" - " MRS r0,PSP \n" // r0 := Process Stack Pointer -#if (__ARM_ARCH == 6) // if ARMv6-M... - " SUBS r0,r0,#(8*4) \n" // make room for 8 registers r4-r11 - " MOVS r1,r0 \n" // r1 := temporary PSP (do not clobber r0!) - " STMIA r1!,{r4-r7} \n" // save the low registers - " MOV r4,r8 \n" // move the high registers to low registers... - " MOV r5,r9 \n" - " MOV r6,r10 \n" - " MOV r7,r11 \n" - " STMIA r1!,{r4-r7} \n" // save the high registers - // NOTE: at this point r0 holds the top of stack - - " LDR r1,[r3,#" STRINGIFY(QXK_CURR) "]\n" // r1 := QXK_priv_.curr (restore value) -#else // ARMv7-M or higher - " ISB \n" // reset pipeline after fetching PSP - " STMDB r0!,{r4-r11} \n" // save r4-r11 on top of the exception frame -#ifdef __ARM_FP //--------- if VFP available... - " TST lr,#(1 << 4) \n" // is it return with the VFP exception frame? - " IT EQ \n" // if lr[4] is zero... - " VSTMDBEQ r0!,{s16-s31} \n" // ... save VFP registers s16..s31 - " STMDB r0!,{r1,lr} \n" // save the "aligner" and the EXC_RETURN value -#endif // VFP available -#endif // ARMv7-M or higher - - // store the SP of the current extended-thread - " STR r0,[r1,#" STRINGIFY(QACTIVE_OSOBJ) "]\n" // QXK_priv_.curr->osObject := r0 - " MOV r0,r12 \n" // QXK_priv_.next (restore value) - - " CMP r2,#0 \n" - " BEQ PendSV_restore_ao\n" // branch if (QXK_priv_.next->osObject == 0) - // otherwise continue to restoring next extended-thread... - - //------------------------------------------------------------------------ - // Restoring extended-thread - // expected register contents: - // r0 -> QXK_priv_.next / basic-thread - // r1 -> QXK_priv_.curr / basic-thread - // r2 -> QXK_priv_.next->osObject (SP) - // r3 -> &QXK_priv_ - // r12 -> QXK_priv_.next / basic-thread - "PendSV_restore_ex: \n" - " STR r0,[r3,#" STRINGIFY(QXK_CURR) "]\n" // QXK_priv_.curr := r0 (QXK_priv_.next) - " MOVS r0,#0 \n" - " STR r0,[r3,#" STRINGIFY(QXK_NEXT) "]\n" // QXK_priv_.next := 0 - - " PUSH {r0-r2,lr} \n" // save next, osObject, EXC_RETURN -#if defined(Q_SPY) || defined(QF_ON_CONTEXT_SW) - " MOV r0,r12 \n" // r0 := parameter 'next' for QXK_contextSw_() - " LDR r3,=QXK_contextSw_ \n" - " BLX r3 \n" // call QXK_contextSw_() -#ifdef QF_MEM_ISOLATE - " LDR r3,=QF_onMemApp \n" - " BLX r3 \n" // call QF_onMemApp() -#endif -#endif // defined(Q_SPY) || defined(QF_ON_CONTEXT_SW) - - - // exit the critical section - " LDR r3,=QF_int_enable_ \n" - " BLX r3 \n" // call QF_int_enable_() - " POP {r0-r3} \n" // restore next, osObject, EXC_RETURN - " MOV lr,r3 \n" // restore the EXC_RETURN into lr - -#if (__ARM_ARCH == 6) // if ARMv6-M... - " MOVS r0,r2 \n" // r2 := top of stack - " ADDS r0,r0,#(4*4) \n" // point r0 to the 4 high registers r7-r11 - " LDMIA r0!,{r4-r7} \n" // pop the 4 high registers into low registers - " MOV r8,r4 \n" // move low registers into high registers - " MOV r9,r5 \n" - " MOV r10,r6 \n" - " MOV r11,r7 \n" - " LDMIA r2!,{r4-r7} \n" // pop the low registers - " MOVS r2,r0 \n" // r2 := holds the new top of stack - - " MOVS r1,#2 \n" - " MVNS r1,r1 \n" // r1 := ~2 == 0xFFFFFFFD - " MOV lr,r1 \n" // make sure PSP is used -#else // ARMv7-M or higher -#ifdef __ARM_FP //--------- if VFP available... - " LDMIA r2!,{r1,lr} \n" // restore aligner and EXC_RETURN into lr - " TST lr,#(1 << 4) \n" // is it return to the VFP exception frame? - " IT EQ \n" // if lr[4] is zero... - " VLDMIAEQ r2!,{s16-s31} \n" // ... restore VFP registers s16..s31 -#else - " ORR lr,lr,#(1 << 2) \n" // make sure PSP is used -#endif // VFP available - " LDMIA r2!,{r4-r11} \n" // restore r4-r11 from the next thread's stack -#endif // ARMv7-M or higher - - // set the PSP to the next thread's SP - " MSR PSP,r2 \n" // Process Stack Pointer := r2 - -#if (__ARM_ARCH != 6) // if ARMv7-M or higher... - " DSB \n" // ARM Erratum 838869 -#endif // ARMv7-M or higher - " BX lr \n" // return to the next extended-thread - ); -} - -//============================================================================ -// QXK_thread_ret is a helper function executed when the QXK activator returns. -// -// NOTE: QXK_thread_ret() does not execute in the PendSV context! -// NOTE: QXK_thread_ret() is entered with interrupts DISABLED. -__stackless -void QXK_thread_ret(void) { -__asm volatile ( - - // After the QXK activator returns, we need to resume the preempted - // thread. However, this must be accomplished by a return-from-exception, - // while we are still in the thread context. The switch to the exception - // context is accomplished by triggering the NMI exception or the selected - // IRQ (if macro #QXK_USE_IRQ_NUM is defined). - - // before triggering the NMI/IRQ, make sure that the VFP stack frame - // will NOT be used... -#ifdef __ARM_FP //--------- if VFP available... - // make sure that the VFP stack frame will NOT be used - " MRS r0,CONTROL \n" // r0 := CONTROL - " BICS r0,r0,#4 \n" // r0 := r0 & ~4 (FPCA bit) - " MSR CONTROL,r0 \n" // CONTROL := r0 (clear CONTROL[2] FPCA bit) - " ISB \n" // ISB after MSR CONTROL (ARM AN321,Sect.4.16) -#endif //--------- VFP available - - // NOTE: the following function calls corrupt lr, but it is NOT - // used to return from QXK_thread_ret(). Instead QXK_thread_ret() - // "returns" by entering an exception (either NMI or IRQ). -#ifdef QF_MEM_ISOLATE - " LDR r0,=QF_onMemApp \n" - " BLX r0 \n" // call QF_onMemApp() -#endif - -#ifndef QXK_USE_IRQ_NUM //--------- IRQ NOT defined, use NMI by default - " LDR r0,=" STRINGIFY(SCB_ICSR) "\n" // Interrupt Control and State - " MOVS r1,#1 \n" - " LSLS r1,r1,#31 \n" // r1 := (1 << 31) (NMI bit) - " STR r1,[r0] \n" // ICSR[31] := 1 (pend NMI) - // NOTE! interrupts are still disabled when NMI is entered - -#else //--------- use the selected IRQ - " LDR r0,=" STRINGIFY(NVIC_PEND + ((QXK_USE_IRQ_NUM >> 5) << 2)) "\n" - " MOVS r1,#1 \n" - " LSLS r1,r1,#" STRINGIFY(QXK_USE_IRQ_NUM & 0x1F) "\n" // r1 := IRQ bit - " STR r1,[r0] \n" // pend the IRQ - - // now enable interrupts so that pended IRQ can be entered - // - // NOTE-1: - // The IRQ preempts immediately after interrupts are enabled, - // without cleanly returning from QF_int_enable_(). Therefore - // QF_int_enable_() is NOT allowed to push anything on the stack - // because the stack is NOT restored when the IRQ preempts. - " LDR r0,=QF_int_enable_ \n" - " BLX r0 \n" // call QF_int_enable_() -#endif //--------- use IRQ - - " B . \n" // wait for preemption by NMI/IRQ - ); -} - -//============================================================================ -// This exception handler is used for returning back to the preempted thread. -// The exception handler simply removes its own interrupt stack frame from -// the stack (MSP) and returns to the preempted task using the interrupt -// stack frame that must be at the top of the stack. -__stackless -#ifndef QXK_USE_IRQ_NUM //--------- IRQ NOT defined, use NMI by default - -// NOTE: The NMI_Handler() is entered with interrupts still DISABLED! -void NMI_Handler(void) { -__asm volatile ( - // call QF_int_enable_(), NOTE: corrupts lr (EXC_RETURN) - // but see code after "BLX r0" - " LDR r0,=QF_int_enable_ \n" - " BLX r0 \n" // call QF_int_enable_() -#ifdef __ARM_FP //--------- if VFP available... - // When VFP is available, lr (EXC_RETURN) is restored from the stack - // before returning from exception, so the value in lr doesn't matter -#else //--------- VFP NOT available - // lr (EXC_RETURN) can be synthesized because it is known (0xFFFFFFF9): - // - return to Thread mode; - // - exception return uses non-floating-point state from MSP; - // - execution uses MSP after return. - " MOVS r0,#6 \n" - " MVNS r0,r0 \n" // r0 := ~6 == 0xFFFFFFF9 - " MOV lr,r0 \n" // lr := 0xFFFFFFF9 (EXC_RETURN) -#endif //--------- VFP NOT available -); - -#else //--------- IRQ defined, use the selected IRQ - -// NOTE: The IRQ Handler is entered with interrupts already ENABLED -void QXK_USE_IRQ_HANDLER(void) { -#endif //--------- IRQ defined - - // ...continue here from either NMI or IRQ -__asm volatile ( - " ADD sp,sp,#(8*4) \n" // remove one 8-register exception frame - -#ifdef __ARM_FP //--------- if VFP available... - " POP {r0,lr} \n" // restore aligher and EXC_RETURN into lr - " DSB \n" // ARM Erratum 838869 - " TST lr,#(1 << 4) \n" // is it return to the VFP exception frame? - " IT EQ \n" // if EXC_RETURN[4] is zero... - " VLDMIAEQ sp!,{s16-s31} \n" // ... restore VFP registers s16..s31 -#endif //--------- VFP available - " BX lr \n" // return to the preempted task - ); -} - -//============================================================================ -#if (__ARM_ARCH == 6) // if ARMv6-M... - -// hand-optimized quick LOG2 in assembly (no CLZ instruction in ARMv6-M) -std::uint_fast8_t QF_qlog2(std::uint32_t x) { - static uint8_t const log2LUT[16] = { - 0U, 1U, 2U, 2U, 3U, 3U, 3U, 3U, - 4U, 4U, 4U, 4U, 4U, 4U, 4U, 4U - }; - uint_fast8_t n; - -__asm volatile ( - " MOVS %[n],#0 \n" -#if (QF_MAX_ACTIVE > 16U) - " LSRS r2,r0,#16 \n" - " BEQ QF_qlog2_1 \n" - " MOVS %[n],#16 \n" - " MOVS r0,r2 \n" - "QF_qlog2_1: \n" -#endif -#if (QF_MAX_ACTIVE > 8U) - " LSRS r2,r0,#8 \n" - " BEQ QF_qlog2_2 \n" - " ADDS %[n],%[n],#8 \n" - " MOVS r0,r2 \n" - "QF_qlog2_2: \n" -#endif - " LSRS r2,r0,#4 \n" - " BEQ.N QF_qlog2_3 \n" - " ADDS %[n],%[n],#4 \n" - " MOVS r0,r2 \n" - "QF_qlog2_3:" : [n]"=r"(n) -); - return n + log2LUT[x]; -} - -#endif // ARMv6-M - -} // extern "C" - diff --git a/ports/arm-cm/qxk/llvm/README.txt b/ports/arm-cm/qxk/llvm/README.txt deleted file mode 100644 index 9cd332f7f..000000000 --- a/ports/arm-cm/qxk/llvm/README.txt +++ /dev/null @@ -1,2 +0,0 @@ -The port to ARM-LLVM toolchain is identical to ARM-CLANG -and is located in ports/arm-cm/armclang/ sub-directory \ No newline at end of file diff --git a/ports/arm-cr/qk/config/qp_config.hpp b/ports/arm-cr/qk/config/qp_config.hpp index e147cea22..b2621dfc4 100644 --- a/ports/arm-cr/qk/config/qp_config.hpp +++ b/ports/arm-cr/qk/config/qp_config.hpp @@ -1,32 +1,30 @@ //============================================================================ // QP configuration file (QK on ARM Cortex-R) -// Last updated for version: 7.4.0 -// Last updated on: 2024-06-06 +// +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // 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: +// 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. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ #ifndef QP_CONFIG_HPP_ @@ -34,17 +32,10 @@ //-------- <<< Use Configuration Wizard in Context Menu >>> ----------------- -// NOTE: Requires command-line macro: QP_CONFIG -// This qp_config.h header file is activated only when the macro -// QP_CONFIG is defined on the command-line to the compiler -// ------------------------------------------- - // QP API compatibility version (QP_API_VERSION) // <0=> 0 (Maximum compatibility) -// <580=>580 (QP 5.8.0 or newer) -// <660=>660 (QP 6.6.0 or newer) // <691=>691 (QP 6.9.1 or newer) -// <700=>700 (QP 7.0.0 or newer) +// <734=>7.3.4 (QP 7.3.4 or newer) // <9999=>9999 (Latest only) // QP API backwards compatibility with the QP/C API version. // Lower QP_API_VERSION values enable backwards compatibility @@ -132,6 +123,7 @@ // Event parameter initialization (QEVT_PAR_INIT) // Resource Acquisition Is Initialization (RAII) for dynamic events //#define QEVT_PAR_INIT +// // Provide destructors for QP classes // Destructors for classes @@ -162,7 +154,6 @@ // Event queue counter size (QF_EQUEUE_CTR_SIZE) // <1U=>1 (default) // <2U=>2 -// <4U=>4 // Size of event queue counter [bytes] // Default: 1 (255 events maximum in a queue) #define QF_EQUEUE_CTR_SIZE 1U diff --git a/ports/arm-cr/qk/gnu/qp_port.hpp b/ports/arm-cr/qk/gnu/qp_port.hpp index eb87163a4..8a9f82fac 100644 --- a/ports/arm-cr/qk/gnu/qp_port.hpp +++ b/ports/arm-cr/qk/gnu/qp_port.hpp @@ -1,34 +1,34 @@ //============================================================================ // 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 // ------------------------ // 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: +// 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. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2023-09-07 -//! @version Last updated for: @ref qpcpp_7_3_0 +//! @date Last updated on: 2024-09-30 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QP/C++ port to ARM Cortex-R, preemptive QK kernel, GNU-ARM @@ -36,11 +36,8 @@ #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ -#include // Exact-width types. C++11 Standard - -#ifdef QP_CONFIG -#include "qp_config.hpp" // external QP configuration -#endif +#include // Exact-width types. C++11 Standard +#include "qp_config.hpp" // QP configuration from the application // no-return function specifier (C++11 Standard) #define Q_NORETURN [[ noreturn ]] void diff --git a/ports/arm-cr/qk/gnu/qs_port.hpp b/ports/arm-cr/qk/gnu/qs_port.hpp index 4ddb938b5..7da8a41ae 100644 --- a/ports/arm-cr/qk/gnu/qs_port.hpp +++ b/ports/arm-cr/qk/gnu/qs_port.hpp @@ -28,7 +28,7 @@ // //============================================================================ //! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_7_4_0 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler diff --git a/ports/arm-cr/qk/iar/qp_port.hpp b/ports/arm-cr/qk/iar/qp_port.hpp index 8ba84ac78..61e739b49 100644 --- a/ports/arm-cr/qk/iar/qp_port.hpp +++ b/ports/arm-cr/qk/iar/qp_port.hpp @@ -1,34 +1,34 @@ //============================================================================ // 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 // ------------------------ // 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: +// 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. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2023-09-07 -//! @version Last updated for: @ref qpcpp_7_3_0 +//! @date Last updated on: 2024-09-30 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QP/C++ port to ARM Cortex-R, preemptive QK kernel, IAR-ARM @@ -36,12 +36,9 @@ #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ -#include // Exact-width types. C++11 Standard -#include // IAR intrinsic functions - -#ifdef QP_CONFIG -#include "qp_config.hpp" // external QP configuration -#endif +#include // Exact-width types. C++11 Standard +#include // IAR intrinsic functions +#include "qp_config.hpp" // QP configuration from the application // no-return function specifier (C++11 Standard) #define Q_NORETURN [[ noreturn ]] void diff --git a/ports/arm-cr/qk/iar/qs_port.hpp b/ports/arm-cr/qk/iar/qs_port.hpp index 4ddb938b5..7da8a41ae 100644 --- a/ports/arm-cr/qk/iar/qs_port.hpp +++ b/ports/arm-cr/qk/iar/qs_port.hpp @@ -28,7 +28,7 @@ // //============================================================================ //! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_7_4_0 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler diff --git a/ports/arm-cr/qk/ti/qp_port.hpp b/ports/arm-cr/qk/ti/qp_port.hpp index bb85b0da4..349cff322 100644 --- a/ports/arm-cr/qk/ti/qp_port.hpp +++ b/ports/arm-cr/qk/ti/qp_port.hpp @@ -1,34 +1,34 @@ //============================================================================ // 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 // ------------------------ // 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: +// 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. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2023-09-07 -//! @version Last updated for: @ref qpcpp_7_3_0 +//! @date Last updated on: 2024-09-30 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QP/C++ port to ARM Cortex-R, preemptive QK kernel, TI-ARM @@ -36,11 +36,8 @@ #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ -#include // Exact-width types. C++11 Standard - -#ifdef QP_CONFIG -#include "qp_config.hpp" // external QP configuration -#endif +#include // Exact-width types. C++11 Standard +#include "qp_config.hpp" // QP configuration from the application // no-return function specifier (C++11 Standard) #define Q_NORETURN [[ noreturn ]] void diff --git a/ports/arm-cr/qk/ti/qs_port.hpp b/ports/arm-cr/qk/ti/qs_port.hpp index 4ddb938b5..7da8a41ae 100644 --- a/ports/arm-cr/qk/ti/qs_port.hpp +++ b/ports/arm-cr/qk/ti/qs_port.hpp @@ -28,7 +28,7 @@ // //============================================================================ //! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_7_4_0 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler diff --git a/ports/arm-cr/qv/config/qp_config.hpp b/ports/arm-cr/qv/config/qp_config.hpp index 8744164bb..8e5152c5a 100644 --- a/ports/arm-cr/qv/config/qp_config.hpp +++ b/ports/arm-cr/qv/config/qp_config.hpp @@ -1,32 +1,30 @@ //============================================================================ -// QP configuration file (generic) -// Last updated for version: 7.4.0 -// Last updated on: 2024-06-06 +// 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 // -// 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: +// 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. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ #ifndef QP_CONFIG_HPP_ @@ -34,17 +32,10 @@ //-------- <<< Use Configuration Wizard in Context Menu >>> ----------------- -// NOTE: Requires command-line macro: QP_CONFIG -// This qp_config.h header file is activated only when the macro -// QP_CONFIG is defined on the command-line to the compiler -// ------------------------------------------- - // QP API compatibility version (QP_API_VERSION) // <0=> 0 (Maximum compatibility) -// <580=>580 (QP 5.8.0 or newer) -// <660=>660 (QP 6.6.0 or newer) // <691=>691 (QP 6.9.1 or newer) -// <700=>700 (QP 7.0.0 or newer) +// <734=>7.3.4 (QP 7.3.4 or newer) // <9999=>9999 (Latest only) // QP API backwards compatibility with the QP/C API version. // Lower QP_API_VERSION values enable backwards compatibility @@ -132,6 +123,7 @@ // Event parameter initialization (QEVT_PAR_INIT) // Resource Acquisition Is Initialization (RAII) for dynamic events //#define QEVT_PAR_INIT +// // Provide destructors for QP classes // Destructors for classes @@ -162,7 +154,6 @@ // Event queue counter size (QF_EQUEUE_CTR_SIZE) // <1U=>1 (default) // <2U=>2 -// <4U=>4 // Size of event queue counter [bytes] // Default: 1 (255 events maximum in a queue) #define QF_EQUEUE_CTR_SIZE 1U diff --git a/ports/arm-cr/qv/gnu/qp_port.hpp b/ports/arm-cr/qv/gnu/qp_port.hpp index 2a6382efc..b243c54ff 100644 --- a/ports/arm-cr/qv/gnu/qp_port.hpp +++ b/ports/arm-cr/qv/gnu/qp_port.hpp @@ -1,34 +1,34 @@ //============================================================================ // 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 // ------------------------ // 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: +// 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. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2023-09-07 -//! @version Last updated for: @ref qpcpp_7_3_0 +//! @date Last updated on: 2024-09-30 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QP/C port to ARM Cortex-R, cooperative QV kernel, GNU-ARM @@ -36,11 +36,8 @@ #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ -#include // Exact-width types. C++11 Standard - -#ifdef QP_CONFIG -#include "qp_config.hpp" // external QP configuration -#endif +#include // Exact-width types. C++11 Standard +#include "qp_config.hpp" // QP configuration from the application // no-return function specifier (C++11 Standard) #define Q_NORETURN [[ noreturn ]] void diff --git a/ports/arm-cr/qv/gnu/qs_port.hpp b/ports/arm-cr/qv/gnu/qs_port.hpp index 4ddb938b5..7da8a41ae 100644 --- a/ports/arm-cr/qv/gnu/qs_port.hpp +++ b/ports/arm-cr/qv/gnu/qs_port.hpp @@ -28,7 +28,7 @@ // //============================================================================ //! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_7_4_0 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler diff --git a/ports/arm-cr/qv/iar/qp_port.hpp b/ports/arm-cr/qv/iar/qp_port.hpp index 474efd5a5..09205bcf1 100644 --- a/ports/arm-cr/qv/iar/qp_port.hpp +++ b/ports/arm-cr/qv/iar/qp_port.hpp @@ -1,34 +1,34 @@ //============================================================================ // 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 // ------------------------ // 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: +// 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. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2023-09-07 -//! @version Last updated for: @ref qpcpp_7_3_0 +//! @date Last updated on: 2024-09-30 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QP/C++ port to Cortex-R, cooperative QV kernel, IAR-ARM @@ -36,12 +36,9 @@ #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ -#include // Exact-width types. C++11 Standard -#include // IAR intrinsic functions - -#ifdef QP_CONFIG -#include "qp_config.hpp" // external QP configuration -#endif +#include // Exact-width types. C++11 Standard +#include // IAR intrinsic functions +#include "qp_config.hpp" // QP configuration from the application // no-return function specifier (C++11 Standard) #define Q_NORETURN [[ noreturn ]] void diff --git a/ports/arm-cr/qv/iar/qs_port.hpp b/ports/arm-cr/qv/iar/qs_port.hpp index 4ddb938b5..7da8a41ae 100644 --- a/ports/arm-cr/qv/iar/qs_port.hpp +++ b/ports/arm-cr/qv/iar/qs_port.hpp @@ -28,7 +28,7 @@ // //============================================================================ //! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_7_4_0 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler diff --git a/ports/arm-cr/qv/ti/qp_port.hpp b/ports/arm-cr/qv/ti/qp_port.hpp index 00e5f1b03..b238f144b 100644 --- a/ports/arm-cr/qv/ti/qp_port.hpp +++ b/ports/arm-cr/qv/ti/qp_port.hpp @@ -1,34 +1,34 @@ //============================================================================ // 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 // ------------------------ // 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: +// 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. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2023-09-07 -//! @version Last updated for: @ref qpcpp_7_3_0 +//! @date Last updated on: 2024-09-30 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QP/C++ port to ARM Cortex-R, cooperative QV kernel, TI-ARM @@ -36,11 +36,8 @@ #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ -#include // Exact-width types. C++11 Standard - -#ifdef QP_CONFIG -#include "qp_config.hpp" // external QP configuration -#endif +#include // Exact-width types. C++11 Standard +#include "qp_config.hpp" // QP configuration from the application // no-return function specifier (C++11 Standard) #define Q_NORETURN [[ noreturn ]] void diff --git a/ports/arm-cr/qv/ti/qs_port.hpp b/ports/arm-cr/qv/ti/qs_port.hpp index 4ddb938b5..7da8a41ae 100644 --- a/ports/arm-cr/qv/ti/qs_port.hpp +++ b/ports/arm-cr/qv/ti/qs_port.hpp @@ -28,7 +28,7 @@ // //============================================================================ //! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_7_4_0 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler diff --git a/ports/config/qp_config.hpp b/ports/config/qp_config.hpp index cca1e00fc..e7c67eeeb 100644 --- a/ports/config/qp_config.hpp +++ b/ports/config/qp_config.hpp @@ -1,32 +1,30 @@ //============================================================================ // QP configuration file (generic) -// Last updated for version: 7.4.0 -// Last updated on: 2024-06-06 +// +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // 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: +// 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. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ #ifndef QP_CONFIG_HPP_ @@ -34,17 +32,10 @@ //-------- <<< Use Configuration Wizard in Context Menu >>> ----------------- -// NOTE: Requires command-line macro: QP_CONFIG -// This qp_config.h header file is activated only when the macro -// QP_CONFIG is defined on the command-line to the compiler -// ------------------------------------------- - // QP API compatibility version (QP_API_VERSION) // <0=> 0 (Maximum compatibility) -// <580=>580 (QP 5.8.0 or newer) -// <660=>660 (QP 6.6.0 or newer) // <691=>691 (QP 6.9.1 or newer) -// <700=>700 (QP 7.0.0 or newer) +// <734=>7.3.4 (QP 7.3.4 or newer) // <9999=>9999 (Latest only) // QP API backwards compatibility with the QP/C API version. // Lower QP_API_VERSION values enable backwards compatibility @@ -132,6 +123,7 @@ // Event parameter initialization (QEVT_PAR_INIT) // Resource Acquisition Is Initialization (RAII) for dynamic events //#define QEVT_PAR_INIT +// // Provide destructors for QP classes // Destructors for classes @@ -162,7 +154,6 @@ // Event queue counter size (QF_EQUEUE_CTR_SIZE) // <1U=>1 (default) // <2U=>2 -// <4U=>4 // Size of event queue counter [bytes] // Default: 1 (255 events maximum in a queue) #define QF_EQUEUE_CTR_SIZE 1U diff --git a/ports/embos/qf_port.cpp b/ports/embos/qf_port.cpp index 0a599ba66..7149d48bf 100644 --- a/ports/embos/qf_port.cpp +++ b/ports/embos/qf_port.cpp @@ -1,29 +1,32 @@ //============================================================================ -// 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. +// Q u a n t u m L e a P s +// ------------------------ +// Modern Embedded Software // -// The terms of the open source GNU General Public License version 3 -// can be found at: +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The terms of the closed source Quantum Leaps commercial licenses -// can be found at: +// 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. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2024-06-11 -//! @version Last updated for: @ref qpcpp_7_4_0 +//! @date Last updated on: 2024-09-26 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QF/C++ port to embOS RTOS kernel, generic C++11 compiler @@ -80,18 +83,21 @@ namespace QP { //............................................................................ void QF::init() { + bzero_(&QF::priv_, sizeof(QF::priv_)); + bzero_(&QActive::registry_[0], sizeof(QActive::registry_)); + OS_InitKern(); // initialize embOS OS_InitHW(); // initialize the hardware used by embOS } //............................................................................ int QF::run() { - onStartup(); // QF callback to configure and start interrupts + onStartup(); // QF callback to configure and start interrupts // produce the QS_QF_RUN trace record QS_CRIT_STAT QS_CRIT_ENTRY(); - QS_BEGIN_PRE_(QS_QF_RUN, 0U) - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_RUN, 0U) + QS_END_PRE() QS_CRIT_EXIT(); OS_Start(); // start embOS multitasking @@ -100,7 +106,7 @@ int QF::run() { } //............................................................................ void QF::stop() { - onCleanup(); // cleanup callback + onCleanup(); // cleanup callback } // thread for active objects ------------------------------------------------- @@ -116,13 +122,13 @@ void QActive::evtLoop_(QActive *act) { //............................................................................ void QActive::start(QPrioSpec const prioSpec, - QEvt const * * const qSto, std::uint_fast16_t const qLen, + QEvtPtr * const qSto, std::uint_fast16_t const qLen, void * const stkSto, std::uint_fast16_t const stkSize, void const * const par) { // create the embOS message box for the AO OS_MAILBOX_Create(&m_eQueue, - static_cast(sizeof(QEvt *)), + static_cast(sizeof(QEvtPtr)), static_cast(qLen), static_cast(&qSto[0])); @@ -160,11 +166,11 @@ void QActive::start(QPrioSpec const prioSpec, // create an embOS task for the AO OS_TASK_CreateEx(&m_thread, #if (OS_TRACKNAME != 0) - m_thread.Name, // the configured task name + m_thread.Name, // the configured task name #elif - "AO", // a generic AO task name + "AO", // a generic AO task name #endif - embos_prio, // embOS priority + embos_prio, // embOS priority &thread_function, static_cast(stkSto), static_cast(stkSize), @@ -198,6 +204,12 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin, { QF_CRIT_STAT QF_CRIT_ENTRY(); + + Q_REQUIRE_INCRIT(200, e != nullptr); +#ifndef Q_UNSAFE + Q_INVARIANT_INCRIT(201, e->verify_()); +#endif // ndef Q_UNSAFE + std::uint_fast16_t nFree = static_cast(m_eQueue.maxMsg - m_eQueue.nofMsg); @@ -208,7 +220,7 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin, } else { status = false; // cannot post - Q_ERROR_INCRIT(510); // must be able to post the event + Q_ERROR_INCRIT(210); // must be able to post the event } } else if (nFree > static_cast(margin)) { @@ -220,15 +232,15 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin, if (status) { // can post the event? - QS_BEGIN_PRE_(QS_QF_ACTIVE_POST, m_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_(this); // this active object (recipient) - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_EQC_PRE_(nFree); // # free entries - QS_EQC_PRE_(0U); // min # free entries (unknown) - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_ACTIVE_POST, m_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(this); // this active object (recipient) + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_EQC_PRE(nFree); // # free entries + QS_EQC_PRE(0U); // min # free entries (unknown) + QS_END_PRE() if (e->getPoolNum_() != 0U) { // is it a pool event? QEvt_refCtr_inc_(e); // increment the reference counter @@ -239,20 +251,19 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin, static_cast(&e)); QF_CRIT_ENTRY(); // posting to the embOS mailbox must succeed, see NOTE3 - Q_ASSERT_INCRIT(520, err == '\0'); + Q_ASSERT_INCRIT(220, err == '\0'); } else { - QS_BEGIN_PRE_(QS_QF_ACTIVE_POST_ATTEMPT, m_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_(this); // this active object (recipient) - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_EQC_PRE_(nFree); // # free entries - QS_EQC_PRE_(margin); // margin requested - QS_END_PRE_() - + QS_BEGIN_PRE(QS_QF_ACTIVE_POST_ATTEMPT, m_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(this); // this active object (recipient) + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr + QS_EQC_PRE(nFree); // # free entries + QS_EQC_PRE(margin); // margin requested + QS_END_PRE() } QF_CRIT_EXIT(); @@ -263,14 +274,19 @@ void QActive::postLIFO(QEvt const * const e) noexcept { QF_CRIT_STAT QF_CRIT_ENTRY(); - QS_BEGIN_PRE_(QS_QF_ACTIVE_POST_LIFO, m_prio) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of this event - QS_OBJ_PRE_(this); // this active object - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_EQC_PRE_(m_eQueue.maxMsg - m_eQueue.nofMsg); // # free entries - QS_EQC_PRE_(0U); // min # free entries (unknown) - QS_END_PRE_() + Q_REQUIRE_INCRIT(300, e != nullptr); +#ifndef Q_UNSAFE + Q_INVARIANT_INCRIT(301, e->verify_()); +#endif // ndef Q_UNSAFE + + QS_BEGIN_PRE(QS_QF_ACTIVE_POST_LIFO, m_prio) + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(e->sig); // the signal of this event + QS_OBJ_PRE(this); // this active object + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_EQC_PRE(m_eQueue.maxMsg - m_eQueue.nofMsg); // # free entries + QS_EQC_PRE(0U); // min # free entries (unknown) + QS_END_PRE() if (e->getPoolNum_() != 0U) { // is it a pool event? QEvt_refCtr_inc_(e); // increment the reference counter @@ -281,23 +297,23 @@ void QActive::postLIFO(QEvt const * const e) noexcept { static_cast(&e)); QF_CRIT_ENTRY(); // posting to the embOS mailbox must succeed, see NOTE3 - Q_ASSERT_INCRIT(610, err == '\0'); + Q_ASSERT_INCRIT(320, err == '\0'); QF_CRIT_EXIT(); } //............................................................................ -QEvt const *QActive::get_(void) noexcept { +QEvt const *QActive::get_() noexcept { QEvt const *e; OS_MAILBOX_GetBlocked(&m_eQueue, static_cast(&e)); QS_CRIT_STAT QS_CRIT_ENTRY(); - QS_BEGIN_PRE_(QS_QF_ACTIVE_GET, m_prio) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of this event - QS_OBJ_PRE_(this); // this active object - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_EQC_PRE_(m_eQueue.maxMsg - m_eQueue.nofMsg); // # free - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_ACTIVE_GET, m_prio) + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(e->sig); // the signal of this event + QS_OBJ_PRE(this); // this active object + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr + QS_EQC_PRE(m_eQueue.maxMsg - m_eQueue.nofMsg); // # free + QS_END_PRE() QS_CRIT_EXIT(); return e; @@ -313,8 +329,8 @@ QEvt const *QActive::get_(void) noexcept { // FPU. In this QP-embOS port, an active object task that uses the FPU is // designated by the QF_TASK_USES_FPU attribute, which can be set with the // QF_setEmbOsTaskAttr() function. The task attributes must be set *before* -// calling QActive::start(). The task attributes are saved in QActive.osObject -// member. +// calling QActive::start(). The task attributes are saved in the +// QActive.osObject member. // // NOTE3: // The event posting to embOS mailbox occurs OUTSIDE critical section, diff --git a/ports/embos/qp_port.hpp b/ports/embos/qp_port.hpp index 9c407e16f..e23d478f4 100644 --- a/ports/embos/qp_port.hpp +++ b/ports/embos/qp_port.hpp @@ -1,34 +1,34 @@ //============================================================================ // 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 // ------------------------ // 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: +// 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. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2023-09-07 -//! @version Last updated for: @ref qpcpp_7_3_0 +//! @date Last updated on: 2024-09-30 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QP/C++ port to embOS RTOS (v5), generic C++11 compiler @@ -36,11 +36,8 @@ #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ -#include // Exact-width types. C++11 Standard - -#ifdef QP_CONFIG -#include "qp_config.hpp" // external QP configuration -#endif +#include // Exact-width types. C++11 Standard +#include "qp_config.hpp" // QP configuration from the application // no-return function specifier (C++11 Standard) #define Q_NORETURN [[ noreturn ]] void diff --git a/ports/embos/qs_port.hpp b/ports/embos/qs_port.hpp index 4ddb938b5..7da8a41ae 100644 --- a/ports/embos/qs_port.hpp +++ b/ports/embos/qs_port.hpp @@ -28,7 +28,7 @@ // //============================================================================ //! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_7_4_0 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler diff --git a/ports/freertos/qf_port.cpp b/ports/freertos/qf_port.cpp index e6393b04f..5d5eafcb7 100644 --- a/ports/freertos/qf_port.cpp +++ b/ports/freertos/qf_port.cpp @@ -1,29 +1,32 @@ //============================================================================ -// 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. +// Q u a n t u m L e a P s +// ------------------------ +// Modern Embedded Software // -// The terms of the open source GNU General Public License version 3 -// can be found at: +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The terms of the closed source Quantum Leaps commercial licenses -// can be found at: +// 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. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2024-06-11 -//! @version Last updated for: @ref qpcpp_7_4_0 +//! @date Last updated on: 2024-10-29 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QF/C++ port to FreeRTOS 10.x, generic C++11 compiler @@ -84,7 +87,9 @@ namespace QP { //............................................................................ void QF::init() { - // empty for FreeRTOS + bzero_(&QF::priv_, sizeof(QF::priv_)); + bzero_(&QActive::registry_[0], sizeof(QActive::registry_)); + // nothing to do for FreeRTOS } //............................................................................ int_t QF::run() { @@ -94,8 +99,8 @@ int_t QF::run() { #ifdef Q_SPY QF_CRIT_STAT QF_CRIT_ENTRY(); - QS_BEGIN_PRE_(QS_QF_RUN, 0U) - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_RUN, 0U) + QS_END_PRE() QF_CRIT_EXIT(); #endif @@ -133,7 +138,7 @@ void QActive::evtLoop_(QActive *act) { //............................................................................ void QActive::start( QPrioSpec const prioSpec, - QEvt const * * const qSto, + QEvtPtr * const qSto, std::uint_fast16_t const qLen, void * const stkSto, std::uint_fast16_t const stkSize, @@ -146,7 +151,7 @@ void QActive::start( // - queue size must be provided // - stack storage must be provided // - stack size must be provided - Q_REQUIRE_INCRIT(200, + Q_REQUIRE_INCRIT(100, (qSto != nullptr) && (qLen > 0U) && (stkSto != nullptr) && (stkSize > 0U)); QF_CRIT_EXIT(); @@ -158,7 +163,7 @@ void QActive::start( reinterpret_cast(qSto), // queue buffer &m_osObject); // static queue buffer QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(210, m_eQueue != static_cast(0)); + Q_ASSERT_INCRIT(110, m_eQueue != static_cast(0)); QF_CRIT_EXIT(); m_prio = static_cast(prioSpec & 0xFFU); // QF-priority @@ -209,8 +214,12 @@ void QActive::start( &m_thread); // task buffer QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(220, task != static_cast(0)); + Q_ASSERT_INCRIT(120, task != static_cast(0)); QF_CRIT_EXIT(); + +#ifdef Q_UNSAFE + Q_UNUSED_PAR(task); +#endif } //............................................................................ #ifdef QACTIVE_CAN_STOP @@ -225,13 +234,15 @@ void QActive::setAttr(std::uint32_t attr1, void const *attr2) { QF_CRIT_ENTRY(); // this function must be called before QACTIVE_START(), // which implies that m_thread.pxDummy1 must not be used yet; - Q_REQUIRE_INCRIT(300, m_thread.pxDummy1 == nullptr); + Q_REQUIRE_INCRIT(150, m_thread.pxDummy1 == nullptr); switch (attr1) { case TASK_NAME_ATTR: // temporarily store the name, cast 'const' away m_thread.pxDummy1 = const_cast(attr2); break; // ... + default: + break; } QF_CRIT_EXIT(); } @@ -245,7 +256,12 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin, QF_CRIT_STAT QF_CRIT_ENTRY(); - // find the number of free slots available in the queue + Q_REQUIRE_INCRIT(200, e != nullptr); +#ifndef Q_UNSAFE + Q_INVARIANT_INCRIT(201, e->verify_()); +#endif // ndef Q_UNSAFE + + // the number of free slots available in the queue std::uint_fast16_t nFree = static_cast(FREERTOS_QUEUE_GET_FREE()); @@ -256,7 +272,7 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin, } else { status = false; // cannot post - Q_ERROR_INCRIT(510); // must be able to post the event + Q_ERROR_INCRIT(210); // must be able to post the event } } else if (nFree > margin) { @@ -268,15 +284,15 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin, if (status) { // can post the event? - QS_BEGIN_PRE_(QS_QF_ACTIVE_POST, m_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_(this); // this active object (recipient) - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // pool Id&ref Count - QS_EQC_PRE_(static_cast(nFree)); // # free entries - QS_EQC_PRE_(0U); // min # free entries (unknown) - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_ACTIVE_POST, m_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(this); // this active object (recipient) + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_EQC_PRE(static_cast(nFree)); // # free entries + QS_EQC_PRE(0U); // min # free entries (unknown) + QS_END_PRE() if (e->getPoolNum_() != 0U) { // is it a pool event? QEvt_refCtr_inc_(e); // increment the reference counter @@ -286,21 +302,25 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin, BaseType_t err = xQueueSendToBack( m_eQueue, static_cast(&e), 0U); - // posting to the FreeRTOS message queue must succeed, see NOTE3 QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(520, err == pdPASS); - } - else { + // posting to the FreeRTOS message queue must succeed, see NOTE3 + Q_ASSERT_INCRIT(220, err == pdPASS); - QS_BEGIN_PRE_(QS_QF_ACTIVE_POST_ATTEMPT, m_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_(this); // this active object (recipient) - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // pool Id&ref Count - QS_EQC_PRE_(static_cast(nFree)); // # free entries - QS_EQC_PRE_(margin); // margin requested - QS_END_PRE_() +#ifdef Q_UNSAFE + Q_UNUSED_PAR(err); +#endif + } + else { // cannot post the event + + QS_BEGIN_PRE(QS_QF_ACTIVE_POST_ATTEMPT, m_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(this); // this active object (recipient) + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_EQC_PRE(static_cast(nFree)); // # free entries + QS_EQC_PRE(margin); // margin requested + QS_END_PRE() } QF_CRIT_EXIT(); @@ -311,14 +331,19 @@ void QActive::postLIFO(QEvt const * const e) noexcept { QF_CRIT_STAT QF_CRIT_ENTRY(); - QS_BEGIN_PRE_(QS_QF_ACTIVE_POST_LIFO, m_prio) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of this event - QS_OBJ_PRE_(this); // this active object - QS_2U8_PRE_(e->evtTag_, e->refCtr_); // pool Id & refCtr of the evt - QS_EQC_PRE_(static_cast(FREERTOS_QUEUE_GET_FREE())); - QS_EQC_PRE_(0U); // min # free entries (unknown) - QS_END_PRE_() + Q_REQUIRE_INCRIT(300, e != nullptr); +#ifndef Q_UNSAFE + Q_INVARIANT_INCRIT(301, e->verify_()); +#endif // ndef Q_UNSAFE + + QS_BEGIN_PRE(QS_QF_ACTIVE_POST_LIFO, m_prio) + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(e->sig); // the signal of this event + QS_OBJ_PRE(this); // this active object + QS_2U8_PRE(e->evtTag_, e->refCtr_); // pool Id & refCtr of the evt + QS_EQC_PRE(static_cast(FREERTOS_QUEUE_GET_FREE())); + QS_EQC_PRE(0U); // min # free entries (unknown) + QS_END_PRE() if (e->getPoolNum_() != 0U) { // is it a pool event? QEvt_refCtr_inc_(e); // increment the reference counter @@ -328,10 +353,14 @@ void QActive::postLIFO(QEvt const * const e) noexcept { BaseType_t err = xQueueSendToFront( m_eQueue, static_cast(&e), 0U); - // LIFO posting to the FreeRTOS queue must succeed, see NOTE3 QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(610, err == pdPASS); + // LIFO posting to the FreeRTOS queue must succeed, see NOTE3 + Q_ASSERT_INCRIT(320, err == pdPASS); QF_CRIT_EXIT(); + +#ifdef Q_UNSAFE + Q_UNUSED_PAR(err); +#endif } //............................................................................ QEvt const *QActive::get_(void) noexcept { @@ -340,13 +369,13 @@ QEvt const *QActive::get_(void) noexcept { QS_CRIT_STAT QS_CRIT_ENTRY(); - QS_BEGIN_PRE_(QS_QF_ACTIVE_GET, m_prio) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of this event - QS_OBJ_PRE_(this); // this active object - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // pool Id&ref Count - QS_EQC_PRE_(static_cast(FREERTOS_QUEUE_GET_FREE())); - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_ACTIVE_GET, m_prio) + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(e->sig); // the signal of this event + QS_OBJ_PRE(this); // this active object + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); // pool Id&ref Count + QS_EQC_PRE(static_cast(FREERTOS_QUEUE_GET_FREE())); + QS_END_PRE() QS_CRIT_EXIT(); return e; @@ -361,6 +390,11 @@ bool QActive::postFromISR(QEvt const * const e, { UBaseType_t uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + Q_REQUIRE_INCRIT(500, e != nullptr); +#ifndef Q_UNSAFE + Q_INVARIANT_INCRIT(501, e->verify_()); +#endif // ndef Q_UNSAFE + // find the number of free slots available in the queue std::uint_fast16_t const nFree = static_cast(FREERTOS_QUEUE_GET_FREE()); @@ -372,7 +406,7 @@ bool QActive::postFromISR(QEvt const * const e, } else { status = false; // cannot post - Q_ERROR_INCRIT(810); // must be able to post the event + Q_ERROR_INCRIT(510); // must be able to post the event } } else if (nFree > margin) { @@ -384,15 +418,15 @@ bool QActive::postFromISR(QEvt const * const e, if (status) { // can post the event? - QS_BEGIN_PRE_(QS_QF_ACTIVE_POST, m_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_(this); // this active object (recipient) - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // pool Id&ref Count - QS_EQC_PRE_(nFree); // # free entries available - QS_EQC_PRE_(0U); // min # free entries (unknown) - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_ACTIVE_POST, m_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(this); // this active object (recipient) + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_EQC_PRE(nFree); // # free entries available + QS_EQC_PRE(0U); // min # free entries (unknown) + QS_END_PRE() if (e->getPoolNum_() != 0U) { // is it a pool event? QEvt_refCtr_inc_(e); // increment the reference counter @@ -405,20 +439,24 @@ bool QActive::postFromISR(QEvt const * const e, // posting to the FreeRTOS message queue must succeed uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); - Q_ASSERT_INCRIT(820, err == pdPASS); + Q_ASSERT_INCRIT(520, err == pdPASS); portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus); + +#ifdef Q_UNSAFE + Q_UNUSED_PAR(err); +#endif } else { - QS_BEGIN_PRE_(QS_QF_ACTIVE_POST_ATTEMPT, m_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_(this); // this active object (recipient) - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // pool Id&ref Count - QS_EQC_PRE_(nFree); // # free entries available - QS_EQC_PRE_(margin); // margin requested - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_ACTIVE_POST_ATTEMPT, m_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(this); // this active object (recipient) + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_EQC_PRE(nFree); // # free entries available + QS_EQC_PRE(margin); // margin requested + QS_END_PRE() portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus); QF::gcFromISR(e); // recycle the event to avoid a leak @@ -431,21 +469,26 @@ void QActive::publishFromISR(QEvt const *e, void *par, void const * const sender) noexcept { + Q_REQUIRE_INCRIT(600, e != nullptr); +#ifndef Q_UNSAFE + Q_INVARIANT_INCRIT(601, e->verify_()); +#endif // ndef Q_UNSAFE + QSignal const sig = e->sig; UBaseType_t uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); - //! @pre the published signal must be within the configured range - Q_REQUIRE_INCRIT(500, sig < QActive::maxPubSignal_); - Q_REQUIRE_INCRIT(502, + // the published signal must be within the configured range + Q_REQUIRE_INCRIT(610, sig < QActive::maxPubSignal_); + Q_REQUIRE_INCRIT(611, subscrList_[sig].m_set.verify_(&subscrList_[sig].m_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_(e->getPoolNum_(), e->refCtr_);// pool-Id & ref-Count - QS_END_PRE_() + 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(e->getPoolNum_(), e->refCtr_); + QS_END_PRE() // is it a dynamic event? if (e->getPoolNum_() != 0U) { @@ -470,7 +513,7 @@ void QActive::publishFromISR(QEvt const *e, do { // loop over all subscribers // the prio of the AO must be registered with the framework uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); - Q_ASSERT_INCRIT(510, registry_[p] != nullptr); + Q_ASSERT_INCRIT(620, registry_[p] != nullptr); portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus); // POST_FROM_ISR() asserts if the queue overflows @@ -494,98 +537,152 @@ void QActive::publishFromISR(QEvt const *e, } //............................................................................ void QTimeEvt::tickFromISR(std::uint_fast8_t const tickRate, - void *par, + void *pxHigherPriorityTaskWoken, void const * const sender) noexcept { + #ifndef Q_SPY + Q_UNUSED_PAR(sender); + #endif + UBaseType_t uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + Q_REQUIRE_INCRIT(700, tickRate < Q_DIM(timeEvtHead_)); + QTimeEvt *prev = &timeEvtHead_[tickRate]; - QS_BEGIN_PRE_(QS_QF_TICK, 0U) - ++prev->m_ctr; - QS_TEC_PRE_(prev->m_ctr); // tick ctr - QS_U8_PRE_(tickRate); // tick rate - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_TICK, 0U) + prev->m_ctr = (prev->m_ctr + 1U); + QS_TEC_PRE(prev->m_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->m_next; // advance down the time evt. list + std::uint_fast8_t lbound = 2U*QF_MAX_ACTIVE; // fixed upper loop bound + for (; lbound > 0U; --lbound) { + Q_ASSERT_INCRIT(710, prev != nullptr); // sanity check - // end of the list? - if (t == nullptr) { + QTimeEvt *te = prev->m_next; // advance down the time evt. list +#ifndef Q_UNSAFE + Q_INVARIANT_INCRIT(711, + Q_PTR2UINT_CAST_(te) == + static_cast(~prev->m_next_dis)); +#endif // ndef Q_UNSAFE - // any new time events armed since the last run? - if (timeEvtHead_[tickRate].m_act != nullptr) { + if (te == nullptr) { // end of the list? - // sanity check - Q_ASSERT_INCRIT(610, prev != nullptr); - prev->m_next = QTimeEvt::timeEvtHead_[tickRate].toTimeEvt(); + // any new time events armed since the last QTimeEvt_tick_()? + if (timeEvtHead_[tickRate].m_act != nullptr) { +#ifndef Q_UNSAFE + Q_INVARIANT_INCRIT(712, + Q_PTR2UINT_CAST_(timeEvtHead_[tickRate].m_act) == + static_cast( + ~timeEvtHead_dis_[tickRate].m_ptr_dis)); +#endif // ndef Q_UNSAFE + prev->m_next = timeEvtHead_[tickRate].toTimeEvt(); timeEvtHead_[tickRate].m_act = nullptr; - t = prev->m_next; // switch to the new list +#ifndef Q_UNSAFE + prev->m_next_dis = + static_cast( + ~Q_PTR2UINT_CAST_(prev->m_next)); + timeEvtHead_dis_[tickRate].m_ptr_dis = + static_cast(~Q_PTR2UINT_CAST_(nullptr)); +#endif // ndef Q_UNSAFE + + te = prev->m_next; // switch to the new list } - else { - break; // all currently armed time evts. processed + else { // all currently armed time events are processed + break; // terminate the for-loop } } - // time event scheduled for removal? - if (t->m_ctr == 0U) { - prev->m_next = t->m_next; - // mark time event 't' as NOT linked - t->refCtr_ &= static_cast(~TE_IS_LINKED); + // the time event 'te' must be valid + Q_ASSERT_INCRIT(720, te != nullptr); + Q_INVARIANT_INCRIT(721, te->verify_()); + + QTimeEvtCtr ctr = te->m_ctr; +#ifndef Q_UNSAFE + Q_INVARIANT_INCRIT(722, ctr == + static_cast(~te->m_ctr_dis)); +#endif // ndef Q_UNSAFE + + if (ctr == 0U) { // time event scheduled for removal? + prev->m_next = te->m_next; +#ifndef Q_UNSAFE + prev->m_next_dis = + static_cast(~Q_PTR2UINT_CAST_(te->m_next)); +#endif // ndef Q_UNSAFE + + // mark time event 'te' as NOT linked + te->m_flags &= static_cast(~QTE_FLAG_IS_LINKED); + // do NOT advance the prev pointer + // exit crit. section to reduce latency portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus); } - else { - --t->m_ctr; - - // is time evt about to expire? - if (t->m_ctr == 0U) { - QActive *act = t->toActive(); // temp. for volatile - - // periodic time evt? - if (t->m_interval != 0U) { - t->m_ctr = t->m_interval; // rearm the time event - prev = t; // advance to this time event - } - // one-shot time event: automatically disarm - else { - prev->m_next = t->m_next; - // mark time event 't' as NOT linked - t->refCtr_ &= static_cast(~TE_IS_LINKED); - // do NOT advance the prev pointer - - QS_BEGIN_PRE_(QS_QF_TIMEEVT_AUTO_DISARM, act->m_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->m_prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(t); // the time event object - QS_SIG_PRE_(t->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 - portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus); - - // asserts if the queue overflows - act->POST_FROM_ISR(t, par, sender); + else if (ctr == 1U) { // is time event about to expire? + QActive * const act = te->toActive(); + if (te->m_interval != 0U) { // periodic time evt? + te->m_ctr = te->m_interval; // rearm the time event +#ifndef Q_UNSAFE + te->m_ctr_dis = static_cast(~te->m_interval); +#endif // ndef Q_UNSAFE + prev = te; // advance to this time event } - else { - prev = t; // advance to this time event - // exit crit. section to reduce latency - portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus); + else { // one-shot time event: automatically disarm + te->m_ctr = 0U; + prev->m_next = te->m_next; +#ifndef Q_UNSAFE + te->m_ctr_dis = + static_cast(~static_cast(0U)); + prev->m_next_dis = + static_cast(~Q_PTR2UINT_CAST_(te->m_next)); +#endif // ndef Q_UNSAFE + + // mark time event 'te' as NOT linked + te->m_flags &= + static_cast(~QTE_FLAG_IS_LINKED); + // do NOT advance the prev pointer + + QS_BEGIN_PRE(QS_QF_TIMEEVT_AUTO_DISARM, act->m_prio) + QS_OBJ_PRE(te); // 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->m_prio) + QS_TIME_PRE(); // timestamp + QS_OBJ_PRE(te); // the time event object + QS_SIG_PRE(te->sig); // signal of this time event + QS_OBJ_PRE(act); // the target AO + QS_U8_PRE(tickRate); // tick rate + QS_END_PRE() + + portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus); + + // POST_FROM_ISR() asserts if the queue overflows + act->POST_FROM_ISR(te, + pxHigherPriorityTaskWoken, + sender); + } + else { // time event keeps timing out + --ctr; // decrement the tick counter + te->m_ctr = ctr; // update the original +#ifndef Q_UNSAFE + te->m_ctr_dis = static_cast(~ctr); +#endif // ndef Q_UNSAFE + + prev = te; // advance to this time event + + portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus); } - // re-enter crit. section to continue + // re-enter crit. section to continue the loop uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); } + + Q_ENSURE_INCRIT(890, lbound > 0U); + portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus); } //............................................................................ @@ -593,216 +690,263 @@ QEvt *QF::newXfromISR_(std::uint_fast16_t const evtSize, std::uint_fast16_t const margin, enum_t const sig) noexcept { - // find the pool index that fits the requested event size ... - std::uint_fast8_t idx; - for (idx = 0U; idx < priv_.maxPool_; ++idx) { - if (evtSize <= QF_EPOOL_EVENT_SIZE_(priv_.ePool_[idx])) { + // find the pool index that fits the requested event size... + std::uint_fast8_t poolNum = 0U; // zero-based poolNum initially + for (; poolNum < priv_.maxPool_; ++poolNum) { + if (evtSize <= QF_EPOOL_EVENT_SIZE_(priv_.ePool_[poolNum])) { break; } } - // cannot run out of registered pools + UBaseType_t uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); - Q_REQUIRE_INCRIT(700, idx < priv_.maxPool_); + + // precondition: + // - cannot run out of registered pools + Q_REQUIRE_INCRIT(800, poolNum < priv_.maxPool_); + + ++poolNum; // convert to 1-based poolNum + portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus); - // get e -- platform-dependent + // get event e (port-dependent)... #ifdef Q_SPY QEvt *e = static_cast( - priv_.ePool_[idx].getFromISR(((margin != QF::NO_MARGIN) - ? margin : 0U), - static_cast(QS_EP_ID) + idx + 1U)); + priv_.ePool_[poolNum - 1U].getFromISR(((margin != QF::NO_MARGIN) + ? margin : 0U), + static_cast(QS_EP_ID) + poolNum)); #else QEvt *e = static_cast( - priv_.ePool_[idx].getFromISR(((margin != QF::NO_MARGIN) - ? margin : 0U), 0U)); + priv_.ePool_[poolNum - 1U].getFromISR(((margin != QF::NO_MARGIN) + ? margin : 0U), 0U)); #endif - // was e allocated correctly? - if (e != nullptr) { + if (e != nullptr) { // was e allocated correctly? e->sig = static_cast(sig); // set the signal e->refCtr_ = 0U; - e->evtTag_ = static_cast(QEvt::MARKER | (idx + 1U)); + e->evtTag_ = static_cast((poolNum << 4U) | 0x0FU); #ifdef Q_SPY uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); - QS_BEGIN_PRE_(QS_QF_NEW, - static_cast(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_() + QS_BEGIN_PRE(QS_QF_NEW, + static_cast(QS_EP_ID) + poolNum) + 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() portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus); -#endif // Q_SPY +#endif // def Q_SPY } - else { // event cannot be allocated - // must tolerate bad alloc. + else { // event was not allocated uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); - Q_ASSERT_INCRIT(720, margin != QF::NO_MARGIN); - portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus); -#ifdef Q_SPY - uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); - QS_BEGIN_PRE_(QS_QF_NEW_ATTEMPT, - static_cast(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_() + // This assertion means that the event allocation failed, + // and this failure cannot be tolerated. The most frequent + // reason is an event leak in the application. + Q_ASSERT_INCRIT(820, margin != QF::NO_MARGIN); + + QS_BEGIN_PRE(QS_QF_NEW_ATTEMPT, + static_cast(QS_EP_ID) + poolNum) + 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() + portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus); -#endif // Q_SPY } - return e; // can't be NULL if we can't tolerate bad allocation + + // the returned event e is guaranteed to be valid (not NULL) + // if we can't tolerate failed allocation + return e; } //............................................................................ void QF::gcFromISR(QEvt const * const e) noexcept { - // is it a dynamic event? - if (e->getPoolNum_() != 0U) { - UBaseType_t uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + UBaseType_t uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); - // isn't this the last ref? - if (e->refCtr_ > 1U) { - QEvt_refCtr_dec_(e); // decrement the ref counter + Q_REQUIRE_INCRIT(700, e != nullptr); +#ifndef Q_UNSAFE + Q_INVARIANT_INCRIT(701, e->verify_()); +#endif - QS_BEGIN_PRE_(QS_QF_GC_ATTEMPT, - static_cast(e->getPoolNum_())) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of the event - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_);//poolNum & refCtr - QS_END_PRE_() + std::uint_fast8_t const poolNum = e->getPoolNum_(); + + if (poolNum != 0U) { // is it a pool event (mutable)? + + if (e->refCtr_ > 1U) { // isn't this the last ref? + + QS_BEGIN_PRE(QS_QF_GC_ATTEMPT, + static_cast(QS_EP_ID) + poolNum) + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(e->sig); // the signal of the event + QS_2U8_PRE(poolNum, e->refCtr_); + QS_END_PRE() + + QEvt_refCtr_dec_(e); // decrement the ref counter portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus); } - // this is the last reference to this event, recycle it - else { - std::uint_fast8_t idx = - static_cast(e->getPoolNum_()) - 1U; + else { // this is the last reference to this event, recycle it - QS_BEGIN_PRE_(QS_QF_GC, - static_cast(e->getPoolNum_())) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of the event - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_);//poolNum & refCtr - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_GC, + static_cast(QS_EP_ID) + poolNum) + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(e->sig); // the signal of the event + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_);//poolNum & refCtr + QS_END_PRE() - // pool ID must be in range - Q_ASSERT_INCRIT(810, idx < priv_.maxPool_); + // pool number must be in range + Q_ASSERT_INCRIT(710, (poolNum <= priv_.maxPool_) + && (poolNum <= QF_MAX_EPOOL)); portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus); #ifdef Q_SPY - // cast 'const' away, which is OK because it's a pool event - priv_.ePool_[idx].putFromISR(QF_CONST_CAST_(QEvt*, e), + // cast 'const' away in (QEvt *)e is OK because it's a pool event + priv_.ePool_[poolNum - 1U].putFromISR(QF_CONST_CAST_(QEvt*, e), static_cast(QS_EP_ID) + e->getPoolNum_()); #else - priv_.ePool_[idx].putFromISR(QF_CONST_CAST_(QEvt*, e), 0U); + priv_.ePool_[poolNum - 1U].putFromISR(QF_CONST_CAST_(QEvt*, e), 0U); #endif } } + else { + portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus); + } } //............................................................................ -void QMPool::putFromISR(void *block, - std::uint_fast8_t const qs_id) noexcept +void *QMPool::getFromISR(std::uint_fast16_t const margin, + std::uint_fast8_t const qsId) noexcept { -#ifndef Q_SPY - Q_UNUSED_PAR(qs_id); -#endif - - QFreeBlock * const fb = static_cast(block); + #ifndef Q_SPY + Q_UNUSED_PAR(qsId); + #endif UBaseType_t uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); - // precondition: - // - # free blocks cannot exceed the total # blocks and - // - the block pointer must be from this pool. - Q_REQUIRE_INCRIT(900, (m_nFree < m_nTot) - && QF_PTR_RANGE_(fb, m_start, m_end)); + // get volatile into temporaries + QFreeBlock *fb = m_free_head; + QMPoolCtr nFree = m_nFree; - fb->m_next = static_cast(m_free_head); // link into list -#ifndef Q_UNSAFE - fb->m_next_dis = static_cast(~Q_UINTPTR_CAST_(fb->m_next)); -#endif - - m_free_head = fb; // set as new head of the free list - ++m_nFree; // one more free block in this pool - - QS_BEGIN_PRE_(QS_QF_MPOOL_PUT, qs_id) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this memory pool - QS_MPC_PRE_(m_nFree); // the number of free blocks in the pool - QS_END_PRE_() - - portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus); -} -//............................................................................ -void *QMPool::getFromISR(std::uint_fast16_t const margin, - std::uint_fast8_t const qs_id) noexcept -{ -#ifndef Q_SPY - Q_UNUSED_PAR(qs_id); -#endif - - UBaseType_t uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + #ifndef Q_UNSAFE + Q_INVARIANT_INCRIT(801, Q_PTR2UINT_CAST_(fb) + == static_cast(~m_free_head_dis)); + Q_INVARIANT_INCRIT(802, nFree == static_cast(~m_nFree_dis)); + #endif // ndef Q_UNSAFE // have more free blocks than the requested margin? - QFreeBlock *fb; - if (m_nFree > static_cast(margin)) { - fb = static_cast(m_free_head); // get a free block - - // the pool has some free blocks, so a free block must be available - Q_ASSERT_INCRIT(900, fb != nullptr); + if (nFree > static_cast(margin)) { + Q_ASSERT_INCRIT(810, fb != nullptr); - QFreeBlock * const fb_next = fb->m_next; // fast temporary to avoid UB + QFreeBlock * const fb_next = fb->m_next; + #ifndef Q_UNSAFE // the free block must have integrity (duplicate inverse storage) - Q_ASSERT_INCRIT(902, Q_UINTPTR_CAST_(fb_next) - == static_cast(~fb->m_next_dis)); + Q_INVARIANT_INCRIT(811, Q_PTR2UINT_CAST_(fb_next) + == static_cast(~fb->m_next_dis)); + #endif // ndef Q_UNSAFE - // is the pool becoming empty? - --m_nFree; // one less free block - if (m_nFree == 0U) { + --nFree; // one less free block + if (nFree == 0U) { // is the pool becoming empty? // pool is becoming empty, so the next free block must be NULL - Q_ASSERT_INCRIT(920, fb_next == nullptr); + Q_ASSERT_INCRIT(820, fb_next == nullptr); + m_nFree = 0U; + #ifndef Q_UNSAFE + m_nFree_dis = static_cast(~m_nFree); m_nMin = 0U; // remember that the pool got empty + #endif // ndef Q_UNSAFE } 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, QF_PTR_RANGE_(fb_next, m_start, m_end)); - - // is the number of free blocks the new minimum so far? - if (m_nMin > m_nFree) { - m_nMin = m_nFree; // remember the new minimum + m_nFree = nFree; // update the original + #ifndef Q_UNSAFE + m_nFree_dis = static_cast(~nFree); + + // The pool is not empty, so the next free-block pointer + // must be in range. + Q_INVARIANT_INCRIT(830, + QF_PTR_RANGE_(fb_next, m_start, m_end)); + + // is the # free blocks the new minimum so far? + if (m_nMin > nFree) { + m_nMin = nFree; // remember the minimum so far } + #endif // ndef Q_UNSAFE } m_free_head = fb_next; // set the head to the next free block - - QS_BEGIN_PRE_(QS_QF_MPOOL_GET, qs_id) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this memory pool - QS_MPC_PRE_(m_nFree); // # free blocks in the pool - QS_MPC_PRE_(m_nMin); // min # free blocks ever in the pool - QS_END_PRE_() + #ifndef Q_UNSAFE + m_free_head_dis = + static_cast(~Q_PTR2UINT_CAST_(fb_next)); + #endif // ndef Q_UNSAFE + + QS_BEGIN_PRE(QS_QF_MPOOL_GET, qsId) + QS_TIME_PRE(); // timestamp + QS_OBJ_PRE(this); // this memory pool + QS_MPC_PRE(nFree); // # of free blocks in the pool + #ifndef Q_UNSAFE + QS_MPC_PRE(m_nMin); // min # free blocks ever in the pool + #else + QS_MPC_PRE(0U); // min # free blocks (not available) + #endif // ndef Q_UNSAFE + QS_END_PRE() } else { // don't have enough free blocks at this point fb = nullptr; - QS_BEGIN_PRE_(QS_QF_MPOOL_GET_ATTEMPT, qs_id) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this memory pool - QS_MPC_PRE_(m_nFree); // # free blocks in the pool - QS_MPC_PRE_(margin); // the requested margin - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_MPOOL_GET_ATTEMPT, qsId) + QS_TIME_PRE(); // timestamp + QS_OBJ_PRE(this); // this memory pool + QS_MPC_PRE(nFree); // # free blocks in the pool + QS_MPC_PRE(margin); // the requested margin + QS_END_PRE() } + portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus); - return fb; // return the block or NULL pointer to the caller + return fb; // return the block or nullptr to the caller +} +//............................................................................ +void QMPool::putFromISR(void *block, + std::uint_fast8_t const qsId) noexcept +{ + #ifndef Q_SPY + Q_UNUSED_PAR(qsId); + #endif + + QFreeBlock * const fb = static_cast(block); + + UBaseType_t uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + + // get volatile into temporaries + QFreeBlock * const free_head = m_free_head; + QMPoolCtr nFree = m_nFree; + + #ifndef Q_UNSAFE + Q_INVARIANT_INCRIT(901, Q_PTR2UINT_CAST_(free_head) + == static_cast(~m_free_head_dis)); + Q_INVARIANT_INCRIT(902, nFree == static_cast(~m_nFree_dis)); + #endif // ndef Q_UNSAFE + + Q_REQUIRE_INCRIT(910, nFree < m_nTot); + Q_REQUIRE_INCRIT(911, QF_PTR_RANGE_(fb, m_start, m_end)); + + ++nFree; // one more free block in this pool + + m_free_head = fb; // set as new head of the free list + m_nFree = nFree; + fb->m_next = free_head; // link into the list + #ifndef Q_UNSAFE + m_free_head_dis = static_cast(~Q_PTR2UINT_CAST_(fb)); + m_nFree_dis = static_cast(~nFree); + fb->m_next_dis = static_cast(~Q_PTR2UINT_CAST_(free_head)); + #endif + + QS_BEGIN_PRE(QS_QF_MPOOL_PUT, qsId) + QS_TIME_PRE(); // timestamp + QS_OBJ_PRE(this); // this memory pool + QS_MPC_PRE(nFree); // the # free blocks in the pool + QS_END_PRE() + + portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus); } } // namespace QP diff --git a/ports/freertos/qp_port.hpp b/ports/freertos/qp_port.hpp index 6ec03cf94..6aa0f6c37 100644 --- a/ports/freertos/qp_port.hpp +++ b/ports/freertos/qp_port.hpp @@ -1,34 +1,34 @@ //============================================================================ // 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 // ------------------------ // 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: +// 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. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2023-09-07 -//! @version Last updated for: @ref qpcpp_7_3_0 +//! @date Last updated on: 2024-09-30 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QP/C++ port to FreeRTOS 10.x generic C++11 compiler @@ -36,11 +36,8 @@ #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ -#include // Exact-width types. C++11 Standard - -#ifdef QP_CONFIG -#include "qp_config.hpp" // external QP configuration -#endif +#include // Exact-width types. C++11 Standard +#include "qp_config.hpp" // QP configuration from the application // no-return function specifier (C++11 Standard) #define Q_NORETURN [[ noreturn ]] void @@ -176,7 +173,7 @@ extern "C" { ((e_) = static_cast((p_).get((m_), (qsId_)))) #define QF_EPOOL_PUT_(p_, e_, qsId_) ((p_).put((e_), (qsId_))) -#endif // ifdef QP_IMPL +#endif // def QP_IMPL //============================================================================ // NOTE2: diff --git a/ports/freertos/qs_port.hpp b/ports/freertos/qs_port.hpp index 4ddb938b5..7da8a41ae 100644 --- a/ports/freertos/qs_port.hpp +++ b/ports/freertos/qs_port.hpp @@ -28,7 +28,7 @@ // //============================================================================ //! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_7_4_0 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler diff --git a/ports/lint-plus/16bit/cpu.lnt b/ports/lint-plus/16bit/cpu.lnt deleted file mode 100644 index d5cc76b10..000000000 --- a/ports/lint-plus/16bit/cpu.lnt +++ /dev/null @@ -1,6 +0,0 @@ -// Size Options for 16bit CPU (e.g., MSP430) --si2 -sl4 -sll8 -ss2 -sw2 -sp2 -sf4 -sd8 -sld8 - -// Alignment options for 16bit CPU --ai2 -al2 -all2 -as2 -af4 -ad8 -ald8 - diff --git a/ports/lint-plus/16bit/cstdint b/ports/lint-plus/16bit/cstdint deleted file mode 100644 index 0566fa50d..000000000 --- a/ports/lint-plus/16bit/cstdint +++ /dev/null @@ -1,39 +0,0 @@ -/// @file cstdint -/// This is an emulation of a Standard C++ Library header for 16bit CPUs, -/// like MSP430. - -#ifndef _GLIBCXX_CSTDINT -#define _GLIBCXX_CSTDINT - -//lint -save -//lint -e9093 AUTOSAR:M17-0-2 the name ... is reserved to the compiler -//lint -e9145 AUTOSAR:M7-3-6 9145: using declaration in header - -namespace std { - - using int8_t = signed char; //!< exact-width 8-bit signed int - using int16_t = signed int; //!< exact-width 16-bit signed int - using int32_t = signed long int; //!< exact-width 32-bit signed int - using int64_t = signed long long; //!< exact-width 64-bit signed int - - using uint8_t = unsigned char; //!< exact-width 8-bit unsigned int - using uint16_t = unsigned int; //!< exact-width 16-bit unsigned int - using uint32_t = unsigned long int; //!< exact-width 32-bit unsigned int - using uint64_t = unsigned long long; //!< exact-width 64-bit unsigned int - - // Fastest minimum-width types. WG14/N843 C99 Standard, Section 7.18.1.3 - using int_fast8_t = signed int; //!< fast at-least 8-bit signed int - using uint_fast8_t = unsigned int; //!< fast at-least 8-bit unsigned int - using int_fast16_t = signed int; //!< fast at-least 16-bit signed int - using uint_fast16_t = unsigned int; //!< fast at-least 16-bit unsigned int - using int_fast32_t = signed long; //!< fast at-least 32-bit signed int - using uint_fast32_t = unsigned long; //!< fast at-least 32-bit unsigned int - - // unsigned integer type capable of holding a pointer to void. - using uintptr_t = unsigned; //!< unsigned int capable of holding void* - -} // namespace std - -//lint -restore - -#endif // _GLIBCXX_CSTDINT diff --git a/ports/lint-plus/16bit/qs_port.hpp b/ports/lint-plus/16bit/qs_port.hpp deleted file mode 100644 index 1bae19a70..000000000 --- a/ports/lint-plus/16bit/qs_port.hpp +++ /dev/null @@ -1,57 +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: 2024-06-06 -//! @version Last updated for: @ref qpcpp_7_4_0 -//! -//! @file -//! @brief QS/C++ port to a 16-bit CPU, generic C++11 compiler - -#ifndef QS_PORT_HPP_ -#define QS_PORT_HPP_ - -// object pointer size in bytes -#define QS_OBJ_PTR_SIZE 2U - -// function pointer size in bytes -#define QS_FUN_PTR_SIZE 2U - -//============================================================================ -// 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.hpp" -// *before* "qs.hpp". -#ifndef QP_PORT_HPP_ -#include "qp_port.hpp" // use QS with QP -#endif - -#include "qs.hpp" // QS platform-independent public interface - -#endif // QS_PORT_HPP_ diff --git a/ports/lint-plus/32bit/cpu.lnt b/ports/lint-plus/32bit/cpu.lnt deleted file mode 100644 index 9281e892b..000000000 --- a/ports/lint-plus/32bit/cpu.lnt +++ /dev/null @@ -1,3 +0,0 @@ -// Size Options for 32bit CPU (e.g., ARM Cortex-M) --si4 -sl4 -sll8 -ss2 -sw4 -sp4 -sf4 -sd8 -sld8 - diff --git a/ports/lint-plus/32bit/cstdint b/ports/lint-plus/32bit/cstdint deleted file mode 100644 index b372ca328..000000000 --- a/ports/lint-plus/32bit/cstdint +++ /dev/null @@ -1,39 +0,0 @@ -/// @file cstdint -/// This is an emulation of a Standard C++ Library header for 32bit CPUs, -/// like ARM Cortex-M. - -#ifndef _GLIBCXX_CSTDINT -#define _GLIBCXX_CSTDINT - -//lint -save -//lint -e9093 AUTOSAR:M17-0-2 the name ... is reserved to the compiler -//lint -e9145 AUTOSAR:M7-3-6 9145: using declaration in header - -namespace std { - - using int8_t = signed char; //!< exact-width 8-bit signed int - using int16_t = signed short; //!< exact-width 16-bit signed int - using int32_t = signed long; //!< exact-width 32-bit signed int - using int64_t = signed long long; //!< exact-width 64-bit signed int - - using uint8_t = unsigned char; //!< exact-width 8-bit unsigned int - using uint16_t = unsigned short; //!< exact-width 16-bit unsigned int - using uint32_t = unsigned long; //!< exact-width 32-bit unsigned int - using uint64_t = unsigned long long; //!< exact-width 64-bit unsigned int - - // Fastest minimum-width types. WG14/N843 C99 Standard, Section 7.18.1.3 - using int_fast8_t = signed int; //!< fast at-least 8-bit signed int - using uint_fast8_t = unsigned int; //!< fast at-least 8-bit unsigned int - using int_fast16_t = signed int; //!< fast at-least 16-bit signed int - using uint_fast16_t = unsigned int; //!< fast at-least 16-bit unsigned int - using int_fast32_t = signed long; //!< fast at-least 32-bit signed int - using uint_fast32_t = unsigned long; //!< fast at-least 32-bit unsigned int - - // unsigned integer type capable of holding a pointer to void. - using uintptr_t = unsigned; //!< unsigned int capable of holding void* - -} // namespace std - -//lint -restore - -#endif // _GLIBCXX_CSTDINT diff --git a/ports/lint-plus/32bit/qs_port.hpp b/ports/lint-plus/32bit/qs_port.hpp deleted file mode 100644 index 4ddb938b5..000000000 --- a/ports/lint-plus/32bit/qs_port.hpp +++ /dev/null @@ -1,57 +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: 2024-06-06 -//! @version Last updated for: @ref qpcpp_7_4_0 -//! -//! @file -//! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler - -#ifndef QS_PORT_HPP_ -#define QS_PORT_HPP_ - -// 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.hpp" -// *before* "qs.hpp". -#ifndef QP_PORT_HPP_ -#include "qp_port.hpp" // use QS with QP -#endif - -#include "qs.hpp" // QS platform-independent public interface - -#endif // QS_PORT_HPP_ diff --git a/ports/lint-plus/au-autosar.lnt b/ports/lint-plus/au-autosar.lnt deleted file mode 100644 index f1e27ba2c..000000000 --- a/ports/lint-plus/au-autosar.lnt +++ /dev/null @@ -1,2773 +0,0 @@ -// --------------------------------------------------------------------------- -// Copyright Vector Informatik GmbH 2020. All rights reserved. -// -// This file is provided by Vector Informatik GmbH (https://www.vector.com) for -// use with PC-lint Plus. Redistribution is permitted but any redistribution -// must preserve this notice and, if the redistributed file has been modified, -// provide notice that the file has been modified from the original. -// --------------------------------------------------------------------------- - - -// au-autosar.lnt -- Author options - AUTOSAR C++ - -/* - This options file can be used to explicitly activate those - checks advocated AUTOSAR for C++ code. - - Vector Informatik GmbH relies on the document, "Guidelines for the use of - the C++14 language in critical and safety-related systems" copyright - 2017 by AUTOSAR, as the primary source for this file. Vector Informatik GmbH - makes no warranty as to the completeness or applicability of this - options file and reserves the right to amend or alter the official - contents of such at any time. - - "AUTOSAR" is a registered trademark of AUTOSAR GbR. - - */ - -/* version check */ -cond('%PCLP_NO_LNT_VERSION_CHECK%' != '1' && (%LINT_MAJOR_VERSION% != 2 || %LINT_MINOR_VERSION% != 0), - +fatal_error(This configuration file is intended for PC-lint Plus 2.0. - You are attempting to use it with PC-lint Plus %LINT_MAJOR_VERSION%.%LINT_MINOR_VERSION%. - It is recommended that you use configuration files intended - for PC-lint Plus %LINT_MAJOR_VERSION%.%LINT_MINOR_VERSION%.) -) - -/* ISO/IEC 14882:2014 */ --std=c++14 - -/* Rule M0-1-1 (required, implementation, automated) */ - - /* 527 - statement is unreachable due to unconditional transfer of control */ - +e527 - +elib(527) - -append(527,[AUTOSAR Rule M0-1-1]) - - /* 681 - loop is likely not entered */ - +e681 - +elib(681) - -append(681,[AUTOSAR Rule M0-1-1]) - - /* 827 - loop can only be reached via goto due to unconditional transfer of - control */ - +e827 - +elib(827) - -append(827,[AUTOSAR Rule M0-1-1]) - - /* 685 - relational operator always evaluates to true/false */ - +e685 - +elib(685) - -append(685,[AUTOSAR Rule M0-1-1]) - - /* 774 - boolean condition always evaluates to true/false */ - +e774 - +elib(774) - -append(774,[AUTOSAR Rule M0-1-1]) - - /* 944 - left/right operand always evaluates to true/false */ - +e944 - +elib(944) - -append(944,[AUTOSAR Rule M0-1-1]) - -/* Rule M0-1-2 (required, implementation, automated) */ - - /* 685 - relational operator always evaluates to true/false */ - +e685 - +elib(685) - -append(685,[AUTOSAR Rule M0-1-2]) - - /* 774 - boolean condition always evaluates to true/false */ - +e774 - +elib(774) - -append(774,[AUTOSAR Rule M0-1-2]) - - /* 827 - loop can only be reached via goto due to unconditional transfer of - control */ - +e827 - +elib(827) - -append(827,[AUTOSAR Rule M0-1-2]) - - /* 944 - left/right operand always evaluates to true/false */ - +e944 - +elib(944) - -append(944,[AUTOSAR Rule M0-1-2]) - -/* Rule M0-1-3 (required, implementation, automated) */ - - /* 528 - static symbol not referenced */ - +e528 - +elib(528) - -append(528,[AUTOSAR Rule M0-1-3]) - - /* 529 - local variable not subsequently referenced */ - +e529 - +elib(529) - -append(529,[AUTOSAR Rule M0-1-3]) - - /* 714 - external symbol was defined but not referenced */ - +e714 - +elib(714) - -append(714,[AUTOSAR Rule M0-1-3]) - - /* 752 - local declarator not referenced */ - +e752 - +elib(752) - -append(752,[AUTOSAR Rule M0-1-3]) - - /* 757 - global declarator not referenced */ - +e757 - +elib(757) - -append(757,[AUTOSAR Rule M0-1-3]) - - /* 1715 - static member symbol not referenced */ - +e1715 - +elib(1715) - -append(1715,[AUTOSAR Rule M0-1-3]) - -/* Rule M0-1-4 (required, implementation, automated) */ - - /* 528 - static symbol not referenced */ - +e528 - +elib(528) - -append(528,[AUTOSAR Rule M0-1-4]) - - /* 529 - local variable not subsequently referenced */ - +e529 - +elib(529) - -append(529,[AUTOSAR Rule M0-1-4]) - - /* 550 - local variable not subsequently accessed */ - +e550 - +elib(550) - -append(550,[AUTOSAR Rule M0-1-4]) - - /* 551 - static variable not accessed */ - +e551 - +elib(551) - -append(551,[AUTOSAR Rule M0-1-4]) - - /* 552 - external variable not accessed */ - +e552 - +elib(552) - -append(552,[AUTOSAR Rule M0-1-4]) - -/* Rule M0-1-5 (required, implementation, automated) */ - - /* 751 - local typedef not referenced */ - +e751 - +elib(751) - -append(751,[AUTOSAR Rule M0-1-5]) - - /* 753 - local tag not referenced */ - +e753 - +elib(753) - -append(753,[AUTOSAR Rule M0-1-5]) - - /* 756 - global typedef not referenced */ - +e756 - +elib(756) - -append(756,[AUTOSAR Rule M0-1-5]) - - /* 758 - global tag not referenced */ - +e758 - +elib(758) - -append(758,[AUTOSAR Rule M0-1-5]) - -/* Rule A0-1-1 (required, implementation, automated) */ - - /* 438 - last value assigned to symbol not used */ - +e438 - +elib(438) - -append(438,[AUTOSAR Rule A0-1-1]) - - /* 838 - previous value assigned to symbol not used */ - +e838 - +elib(838) - -append(838,[AUTOSAR Rule A0-1-1]) - -/* Rule A0-1-2 (required, implementation, automated) */ - - /* 534 - ignoring return value of function */ - +e534 - +elib(534) - -append(534,[AUTOSAR Rule A0-1-2]) - -/* Rule M0-1-8 (required, implementation, automated) */ - - /* 9175 - function has void return type and no external side-effects */ - +e9175 - +elib(9175) - -append(9175,[AUTOSAR Rule M0-1-8]) - -/* Rule M0-1-9 (required, implementation, automated) */ - - /* 438 - last value assigned to symbol not used */ - +e438 - +elib(438) - -append(438,[AUTOSAR Rule M0-1-9]) - - /* 587 - predicate can be pre-determined and always evaluates to true/false */ - +e587 - +elib(587) - -append(587,[AUTOSAR Rule M0-1-9]) - - /* 685 - relational operator always evaluates to true/false */ - +e685 - +elib(685) - -append(685,[AUTOSAR Rule M0-1-9]) - - /* 774 - boolean condition always evaluates to true/false */ - +e774 - +elib(774) - -append(774,[AUTOSAR Rule M0-1-9]) - - /* 838 - previous value assigned to symbol not used */ - +e838 - +elib(838) - -append(838,[AUTOSAR Rule M0-1-9]) - - /* 944 - left/right operand always evaluates to true/false */ - +e944 - +elib(944) - -append(944,[AUTOSAR Rule M0-1-9]) - - /* 948 - operator always evaluates to true/false */ - +e948 - +elib(948) - -append(948,[AUTOSAR Rule M0-1-9]) - -/* Rule M0-1-10 (advisory, implementation, automated) */ - - /* 528 - static symbol not referenced */ - +e528 - +elib(528) - -append(528,[AUTOSAR Rule M0-1-10]) - - /* 714 - external symbol was defined but not referenced */ - +e714 - +elib(714) - -append(714,[AUTOSAR Rule M0-1-10]) - - /*1714 - member function not referenced */ - +e1714 - +elib(1714) - -append(1714,[AUTOSAR Rule M0-1-10]) - - /* default constructor not referenced */ - +e1914 - +elib(1914) - -append(1914,[AUTOSAR Rule M0-1-10]) - -/* Rule A0-1-3 (required, implementation, automated) */ - - /* 528 - static symbol not referenced */ - +e528 - +elib(528) - -append(528,[AUTOSAR Rule A0-1-3]) - -/* Rule M0-1-11 (required, implementation, automated) */ - - /* 715 - named parameter not subsequently referenced */ - +estring(715,non-virtual) - +elib(715) - -append(715(non-virtual),[AUTOSAR Rule M0-1-11]) - - /* 9215 - unnamed function parameter */ - +estring(9215,non-virtual) - +elib(9215) - -append(9215(non-virtual),[AUTOSAR Rule M0-1-11]) - -/* Rule M0-1-12 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M0-2-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M0-3-1 (required, implementation/verification, non-automated) */ - - /* Static Analysis is provided by using PC-lint Plus */ - -/* Rule M0-3-2 (required, implementation, non-automated) */ - - /* not currently supported */ - -/* Rule M0-4-1 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule M0-4-2 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule A0-4-1 (required, infrastructure/toolchain, non-automated) */ - - /* not statically checkable */ - -/* Rule A0-4-2 (required, implementation, automated) */ - - /* 586 - type is deprecated */ - +e586 - +elib(586) - -deprecate(basetype, long double) - -append(586(long double),[AUTOSAR Rule A0-4-2]) - -/* Rule A0-4-3 (required, toolchain, automated) */ - - /* not statically checkable */ - -/* Rule A1-1-1 (required, implementation, automated) */ - - /* 1407 - incrementing expression of type bool */ - +e1407 - +elib(1407) - -append(1407,[AUTOSAR Rule A1-1-1]) - - /* 586 - keyword is deprecated */ - +e586 - +elib(586) - -deprecate(keyword, register) - -append(586(register),[AUTOSAR Rule A1-1-1]) - - /* 1906 - exception specification for function */ - +e1906 - +elib(1906) - -append(1906,[AUTOSAR Rule A1-1-1]) - - /* 586 - function random_shuffle is deprecated */ - +e586 - +elib(586) - -deprecate(function,std::random_shuffle) - -append(586(std::random_shuffle),[AUTOSAR Rule A1-1-1]) - - /* 586 - function adaptors are deprecated */ - +e586 - +elib(586) - -deprecate(function,std::ptr_fun,[AUTOSAR Rule A1-1-1]) - -deprecate(function,std::mem_fun,[AUTOSAR Rule A1-1-1]) - -deprecate(function,std::mem_fun_ref,[AUTOSAR Rule A1-1-1]) - -append(586(std::ptr_fun),[AUTOSAR Rule A1-1-1]) - -append(586(std::mem_fun),[AUTOSAR Rule A1-1-1]) - -append(586(std::mem_fun_ref),[AUTOSAR Rule A1-1-1]) - - /* 586 - functions bind1st and bind2nd are deprecated */ - +e586 - +elib(586) - -deprecate(function,std::bind1st,[AUTOSAR Rule A1-1-1]) - -append(586(std::bind1st),[AUTOSAR Rule A1-1-1]) - -deprecate(function,std::bind2nd,[AUTOSAR Rule A1-1-1]) - -append(586(std::bind2nd),[AUTOSAR Rule A1-1-1]) - -/* Rule M1-0-2 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule A1-1-2 (required, toolchain, non-automated) */ - - /* not statically checkable */ - -/* Rule A1-1-3 (required, implementation, automated) */ - - /* not statically checkable */ - -/* Rule A1-2-1 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule A1-4-1 (required, implementation, non-automated) */ - - /* not currently supported */ - -/* Rule A1-4-2 (required, implementation, non-automated) */ - - /* not currently supported */ - -/* Rule A2-2-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A2-5-1 (required, implementation, automated) */ - - -ftg /* disable trigraph expansion */ - - /* 584 - trigraph sequence detected */ - +e584 - +elib(584) - -append(584,[AUTOSAR Rule A2-5-1]) - - /* 739 - trigraph sequence in string literal */ - +e739 - +elib(739) - -append(739,[AUTOSAR Rule A2-5-1]) - -/* Rule A2-6-1 (required, implementation, automated) */ - - /* 9102 - possible digraph sequence */ - +e9102 - +elib(9102) - -append(9102,[AUTOSAR Rule A2-6-1]) - -/* Rule A2-8-1 (required, implementation, automated) */ - - /* 427 - / / comment continued via back-slash */ - +e427 - +elib(427) - -append(427,[AUTOSAR Rule A2-8-1]) - -/* Rule A2-8-2 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule A2-8-3 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A2-8-4 (required, implementation, automated) */ - - /* 1904 - old-style c comment */ - +e1904 - +elib(1904) - -append(1904,[AUTOSAR Rule A2-8-4]) - -/* Rule A2-9-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M2-10-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A2-11-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M2-10-3 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A2-11-2 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A2-11-3 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A2-11-4 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A2-11-5 (advisory, implementation, automated) */ - - /* not currently supported */ - -/* Rule M2-10-6 (required, implementation, automated) */ - - /* 18 - redefinition of symbol as different kind of symbol */ - +e18 - +elib(18) - -append(18,[AUTOSAR Rule M2-10-6]) - -/* Rule A2-14-1 (required, implementation, automated) */ - - /* 606 - non-ANSI escape sequence */ - +e606 - +elib(606) - -append(606,[AUTOSAR Rule A2-14-1]) - -/* Rule M2-13-2 (required, implementation, automated) */ - - /* 9001 - octal constant used */ - +e9001 - +elib(9001) - -append(9001,[AUTOSAR Rule M2-13-2]) - - /* 9104 - octal escape sequence used */ - +e9104 - +elib(9104) - -append(9104,[AUTOSAR Rule M2-13-2]) - -/* Rule M2-13-3 (required, implementation, automated) */ - - /* 9105 - unsigned octal and hexadecimal literals require a 'U' suffix */ - +e9105 - +elib(9105) - -append(9105,[AUTOSAR Rule M2-13-3]) - -/* Rule M2-13-4 (required, implementation, automated) */ - - /* 9106 - lower case literal suffix */ - +e9106 - +elib(9106) - -append(9106,[AUTOSAR Rule M2-13-4]) - -/* Rule A2-14-2 (required, implementation, automated) */ - - /* 1107 - invalid concatenation of wide string literals of different kinds */ - +e1107 - +elib(1107) - -append(1107,[AUTOSAR Rule A2-14-2]) - -/* Rule A2-14-3 (required, implementation, automated) */ - - /* 586 - type is deprecated */ - +e586 - +elib(586) - -deprecate(type, wchar_t) - -append(586(wchar_t),[AUTOSAR Rule A2-14-3]) - -/* Rule A3-1-1 (required, implementation, automated) */ - - /* 9107 - header cannot be included in more than one translation unit because - of the definition of symbol */ - +e9107 - +elib(9107) - -append(9107,[AUTOSAR Rule A3-1-1]) - -/* Rule A3-1-2 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A3-1-3 (advisory, implementation, automated) */ - - /* not currently supported */ - -/* Rule M3-1-2 (required, implementation, automated) */ - - /* 9108 - function declared at block scope */ - +e9108 - +elib(9108) - -append(9108,[AUTOSAR Rule M3-1-2]) - - /* 1798 - block scope declaration of function is taken to mean a member of an enclosing namespace but does not introduce a name */ - +e1798 - +elib(1798) - -append(1798,[AUTOSAR Rule M3-1-2]) - -/* Rule A3-1-4 (required, implementation, automated) */ - - /* 9067 - extern array declared without size or initializer */ - +e9067 - +elib(9067) - -append(9067,[AUTOSAR Rule A3-1-4]) - -/* Rule M3-2-1 (required, implementation, automated) */ - - /* 18 - redefinition of symbol as different kind of symbol */ - +e18 - +elib(18) - -append(18,[AUTOSAR Rule M3-2-1]) - - /* 31 - redefinition of symbol */ - +e31 - +elib(31) - -append(31,[AUTOSAR Rule M3-2-1]) - -/* Rule M3-2-2 (required, implementation, automated) */ - - /* 15 - symbol redeclared with different type */ - +e15 - +elib(15) - -append(15,[AUTOSAR Rule M3-2-2]) - - /* 31 - redefinition of symbol */ - +e31 - +elib(31) - -append(31,[AUTOSAR Rule M3-2-2]) - -/* Rule M3-2-3 (required, implementation, automated) */ - - /* 9004 - object/function previously declared */ - +e9004 - +elib(9004) - -append(9004,[AUTOSAR Rule M3-2-3]) - -/* Rule M3-2-4 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A3-3-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A3-3-2 (required, implementation, automated) */ - - /* 1756 - variable has static/thread storage duration and non-POD type */ - +e1756 - +elib(1756) - -append(1756,[AUTOSAR Rule A3-3-2]) - -/* Rule M3-3-2 (required, implementation, automated) */ - - /* 401 - not previously declared static */ - +e401 - +elib(401) - -append(401,[AUTOSAR Rule M3-3-2]) - - /* 839 - storage class of symbol assumed static */ - +e839 - +elib(839) - -append(839,[AUTOSAR Rule M3-3-2]) - -/* Rule M3-4-1 (required, implementation, automated) */ - - /* 9003 - could define global variable 'Symbol' within function */ - +e9003 - +elib(9003) - -append(9003,[AUTOSAR Rule M3-4-1]) - -/* Rule M3-9-1 (required, implementation, automated) */ - - /* 9073 - parameter 'Integer' of function 'Symbol' has type alias name - difference with previous declaration ('Type' vs 'Type') */ - +e9073 - +elib(9073) - -append(9073,[AUTOSAR Rule M3-9-1]) - - /* 9094 - return type of function 'Symbol' has type alias name difference - with previous declaration ('Type' vs 'Type') */ - +e9094 - +elib(9094) - -append(9094,[AUTOSAR Rule M3-9-1]) - - /* 9168 - variable has type alias name difference with previous - declaration */ - +e9168 - +elib(9168) - -append(9168,[AUTOSAR Rule M3-9-1]) - -/* Rule A3-9-1 (required, implementation, automated) */ - - /* 586 - type is deprecated */ - +e586 - +elib(586) - - -deprecate(type, signed char) - -append(586(signed char),[AUTOSAR Rule A3-9-1]) - - -deprecate(type, unsigned char) - -append(586(unsigned char),[AUTOSAR Rule A3-9-1]) - - -deprecate(type, int) - -append(586(int),[AUTOSAR Rule A3-9-1]) - - -deprecate(type, unsigned int) - -append(586(unsigned int),[AUTOSAR Rule A3-9-1]) - - -deprecate(type, short) - -append(586(short),[AUTOSAR Rule A3-9-1]) - - -deprecate(type, unsigned short) - -append(586(unsigned short),[AUTOSAR Rule A3-9-1]) - - -deprecate(type, long) - -append(586(long),[AUTOSAR Rule A3-9-1]) - - -deprecate(type, unsigned long) - -append(586(unsigned long),[AUTOSAR Rule A3-9-1]) - - -deprecate(type, long long) - -append(586(long long),[AUTOSAR Rule A3-9-1]) - - -deprecate(type, unsigned long long) - -append(586(unsigned long long),[AUTOSAR Rule A3-9-1]) - -/* Rule M3-9-3 (required, implementation, automated) */ - - /* 9110 - bit representation of a floating point type used */ - +e9110 - +elib(9110) - -append(9110,[AUTOSAR Rule M3-9-3]) - - /* 2499 - memcmp of floating data */ - +e2499 - +elib(2499) - -append(2499,[AUTOSAR Rule M3-9-3]) - - /* 2498 - memcmp of floating data within structure/union */ - +e2498 - +elib(2498) - -append(2498,[AUTOSAR Rule M3-9-3]) - -/* Rule M4-5-1 (required, implementation, automated) */ - - /* 9111 - boolean expression used with non-permitted operator */ - +e9111 - +elib(9111) - -append(9111,[AUTOSAR Rule M4-5-1]) - -/* Rule A4-5-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M4-5-3 (required, implementation, automated) */ - - /* 9112 - plain character expression used with non-permitted operator */ - +e9112 - +elib(9112) - -append(9112,[AUTOSAR Rule M4-5-3]) - -/* Rule A4-7-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M4-10-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A4-10-1 (required, implementation, automated) */ - - /* 910 - implicit conversion of null pointer constant to pointer */ - +e910 - +elib(910) - -append(910,[AUTOSAR Rule A4-10-1]) - -/* Rule M4-10-2 (required, implementation, automated) */ - - /* 910 - implicit conversion of null pointer constant to pointer */ - +e910 - +elib(910) - -append(910,[AUTOSAR Rule M4-10-2]) - -/* Rule A5-0-1 (required, implementation, automated) */ - - /* 564 - variable depends on order of evaluation */ - +e564 - +elib(564) - -append(564,[AUTOSAR Rule A5-0-1]) - -/* Rule M5-0-2 (advisory, implementation, partially automated) */ - - /* 9113 - dependence placed on C++ operator precedence */ - +e9113 - +elib(9113) - -append(9113,[AUTOSAR Rule M5-0-2]) - -/* Rule M5-0-3 (required, implementation, automated) */ - - /* 9114 - implicit conversion of integer cvalue expression */ - +e9114 - +elib(9114) - -append(9114,[AUTOSAR Rule M5-0-3]) - - /* 9116 - implicit conversion of floating point cvalue expression */ - +e9116 - +elib(9116) - -append(9116,[AUTOSAR Rule M5-0-3]) - -/* Rule M5-0-4 (required, implementation, automated) */ - - /* 9117 - implicit conversion changes signedness */ - +e9117 - +elib(9117) - -append(9117,[AUTOSAR Rule M5-0-4]) - -/* Rule M5-0-5 (required, implementation, automated) */ - - /* 9115 - implicit conversion from integer to floating point type */ - +e9115 - +elib(9115) - -append(9115,[AUTOSAR Rule M5-0-5]) - - /* 9118 - implicit conversion from floating point to integer type */ - +e9118 - +elib(9118) - -append(9118,[AUTOSAR Rule M5-0-5]) - -/* Rule M5-0-6 (required, implementation, automated) */ - - /* 9119 - implicit conversion of integer to smaller type */ - +e9119 - +elib(9119) - -append(9119,[AUTOSAR Rule M5-0-6]) - - /* 9120 - implicit conversion of floating point to smaller type */ - +e9120 - +elib(9120) - -append(9120,[AUTOSAR Rule M5-0-6]) - -/* Rule M5-0-7 (required, implementation, automated) */ - - /* 9121 - cast of cvalue expression from integer to floating point type */ - +e9121 - +elib(9121) - -append(9121,[AUTOSAR Rule M5-0-7]) - - /* 9122 - cast of cvalue expression from floating point to integer type */ - +e9122 - +elib(9122) - -append(9122,[AUTOSAR Rule M5-0-7]) - -/* Rule M5-0-8 (required, implementation, automated) */ - - /* 9123 - cast of integer cvalue expression to larger type */ - +e9123 - +elib(9123) - -append(9123,[AUTOSAR Rule M5-0-8]) - - /* 9124 - cast of floating point cvalue expression to larger type */ - +e9124 - +elib(9124) - -append(9124,[AUTOSAR Rule M5-0-8]) - -/* Rule M5-0-9 (required, implementation, automated) */ - - /* 9125 - cast of integer cvalue expression changes signedness */ - +e9125 - +elib(9125) - -append(9125,[AUTOSAR Rule M5-0-9]) - -/* Rule M5-0-10 (required, implementation, automated) */ - - /* 9126 - result of operator applied to underlying type must be cast */ - +e9126 - +elib(9126) - -append(9126,[AUTOSAR Rule M5-0-10]) - -/* Rule M5-0-11 (required, implementation, automated) */ - - /* 9128 - plain char type mixed with type other than plain char */ - +e9128 - +elib(9128) - -append(9128,[AUTOSAR Rule M5-0-11]) - -/* Rule M5-0-12 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A5-0-2 (required, implementation, automated) */ - - /* 9177 - condition of if/for/while/do statement has non-Boolean type */ - +e9177 - +elib(9177) - -append(9177,[AUTOSAR Rule A5-0-2]) - -/* Rule M5-0-14 (required, implementation, automated) */ - - /* 9178 - predicate of conditional operator has non-Boolean type */ - +e9178 - +elib(9178) - -append(9178,[AUTOSAR Rule M5-0-14]) - -/* Rule M5-0-15 (required, implementation, automated) */ - - /* 947 - pointer subtraction */ - +e947 - +elib(947) - -append(947,[AUTOSAR Rule M5-0-15]) - - /* 9016 - performing pointer arithmetic via addition/subtraction */ - +e9016 - +elib(9016) - -append(9016,[AUTOSAR Rule M5-0-15]) - -/* Rule M5-0-16 (required, implementation, automated) */ - - /* 415 - likely out of bounds pointer access */ - +e415 - +elib(415) - -append(415,[AUTOSAR Rule M5-0-16]) - - /* 416 - likely creating out-of-bounds pointer */ - +e416 - +elib(416) - -append(416,[AUTOSAR Rule M5-0-16]) - - /* 661 - potential out of bounds pointer access */ - +e661 - +elib(661) - -append(661,[AUTOSAR Rule M5-0-16]) - - /* 662 - possibly creating out-of-bounds pointer */ - +e662 - +elib(662) - -append(662,[AUTOSAR Rule M5-0-16]) - -/* Rule M5-0-17 (required, implementation, automated) */ - - /* 947 - pointer subtraction */ - +e947 - +elib(947) - -append(947,[AUTOSAR Rule M5-0-17]) - -/* Rule M5-0-18 (required, implementation, automated) */ - - /* 946 - relational operator applied to pointers */ - +e946 - +elib(946) - -append(946,[AUTOSAR Rule M5-0-18]) - -/* Rule A5-0-3 (required, implementation, automated) */ - - /* 9025 - more than two levels of pointer indirection */ - +e9025 - +elib(9025) - -append(9025,[AUTOSAR Rule A5-0-3]) - -/* Rule M5-0-20 (required, implementation, automated) */ - - /* 9172 - bitwise operator 'Operator' used with non-const operands of - differing underlying types */ - +e9172 - +elib(9172) - -append(9172,[AUTOSAR Rule M5-0-20]) - -/* Rule M5-0-21 (required, implementation, automated) */ - - /* 9130 - bitwise operator applied to signed underlying type */ - +e9130 - +elib(9130) - -append(9130,[AUTOSAR Rule M5-0-21]) - -/* Rule A5-1-1 (required, implementation, partially automated) */ - - /* not currently supported */ - -/* Rule A5-1-2 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A5-1-3 (required, implementation, automated) */ - - /* 9424 - parameter list omitted from lambda expression */ - +e9424 - +elib(9424) - -append(9424,[AUTOSAR Rule A5-1-3]) - -/* Rule A5-1-4 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A5-1-5 (advisory, implementation, non-automated) */ - - /* not currently supported */ - -/* Rule A5-1-6 (advisory, implementation, automated) */ - - /* 3903 - lambda return type not explicitly specified */ - +e3903 - +elib(3903) - -append(3903,[AUTOSAR Rule A5-1-6]) - -/* Rule A5-1-7 (required, implementation, automated) */ - - /* 9426 - lambda used as operand to decltype or typeid */ - +e9426 - +elib(9426) - -append(9426,[AUTOSAR Rule A5-1-7]) - -/* Rule A5-1-8 (advisory, implementation, automated) */ - - /* 9442 - nested lambda expression */ - +e9442 - +elib(9442) - -append(9442,[AUTOSAR Rule A5-1-8]) - -/* Rule M5-2-1 (required, implementation, automated) */ - - /* 9131 - left/right side of logical operator is not a postfix expression */ - +e9131 - +elib(9131) - -append(9131,[AUTOSAR Rule M5-2-1]) - -/* Rule M5-2-2 (required, implementation, automated) */ - - /* 1774 - only dynamic_cast can indicate a failure by returning null */ - +e1774 - +elib(1774) - -append(1774,[AUTOSAR Rule M5-2-2]) - - /* 1939 - casting from base class to derived class */ - +e1939 - +elib(1939) - -append(1939,[AUTOSAR Rule M5-2-2]) - -/* Rule M5-2-3 (advisory, implementation, automated) */ - - /* 9171 - downcast of polymorphic type 'Type' to type 'Type' */ - +e9171 - +elib(9171) - -append(9171,[AUTOSAR Rule M5-2-3]) - -/* Rule A5-2-1 (advisory, implementation, automated) */ - - /* 586 - keyword is deprecated */ - +e586 - +elib(586) - - -deprecate(keyword, dynamic_cast) - -append(586(dynamic_cast),[AUTOSAR Rule A5-2-1]) - -/* Rule A5-2-2 (required, implementation, automated) */ - - /* 1924 - use of c-style cast (except to void) */ - +e1924 - +elib(1924) - -append(1924,[AUTOSAR Rule A5-2-2]) - - /* 1954 - use of c-style cast (to void) */ - +e1954 - +elib(1954) - -append(1954,[AUTOSAR Rule A5-2-2]) - -/* Rule A5-2-3 (required, implementation, automated) */ - - /* 9005 - cast drops qualifier */ - +e9005 - +elib(9005) - -append(9005,[AUTOSAR Rule A5-2-3]) - -/* Rule M5-2-6 (required, implementation, automated) */ - - /* 611 - cast between pointer to function type and pointer to object type */ - +e611 - +elib(611) - -append(611,[AUTOSAR Rule M5-2-6]) - -/* Rule A5-2-4 (required, implementation, automated) */ - - /* 586 - keyword is deprecated */ - +e586 - +elib(586) - - -deprecate(keyword, reinterpret_cast) - -append(586(reinterpret_cast),[AUTOSAR Rule A5-2-4]) - -/* Rule M5-2-8 (required, implementation, automated) */ - - /* 9010 - conversion from integer to pointer */ - +e9010 - +elib(9010) - -append(9010,[AUTOSAR Rule M5-2-8]) - - /* 9079 - conversion from pointer to void to pointer */ - +e9079 - +elib(9079) - -append(9079,[AUTOSAR Rule M5-2-8]) - -/* Rule M5-2-9 (required, implementation, automated) */ - - /* 9091 - cast from pointer to integer type */ - +e9091 - +elib(9091) - -append(9091,[AUTOSAR Rule M5-2-9]) - -/* Rule M5-2-10 (required, implementation, automated) */ - - /* 9049 - increment/decrement operation combined with other operation with - side-effects */ - +e9049 - +elib(9049) - -append(9049,[AUTOSAR Rule M5-2-10]) - -/* Rule M5-2-11 (required, implementation, automated) */ - - /* 1753 - overloading operator 'Operator' precludes short-circuit evaluation */ - +e1753 - +elib(1753) - -append(1753,[AUTOSAR Rule M5-2-11]) - -/* Rule A5-2-5 (required, implementation, automated) */ - - /* 415 - likely out of bounds pointer access */ - +e415 - +elib(415) - -append(415,[AUTOSAR Rule A5-2-5]) - - /* 416 - likely creating out-of-bounds pointer */ - +e416 - +elib(416) - -append(416,[AUTOSAR Rule A5-2-5]) - - /* 661 - potential out of bounds pointer access */ - +e661 - +elib(661) - -append(661,[AUTOSAR Rule A5-2-5]) - - /* 662 - possibly creating out-of-bounds pointer */ - +e662 - +elib(662) - -append(662,[AUTOSAR Rule A5-2-5]) - -/* Rule M5-2-12 (required, implementation, automated) */ - - /* 9132 - array type passed to function expecting a pointer */ - +e9132 - +elib(9132) - -append(9132,[AUTOSAR Rule M5-2-12]) - -/* Rule M5-3-1 (required, implementation, automated) */ - - /* 9133 - boolean expression required for operator 'Operator' */ - +e9133 - +elib(9133) - -append(9133,[AUTOSAR Rule M5-3-1]) - -/* Rule M5-3-2 (required, implementation, automated) */ - - /* 9134 - unary minus applied to operand with unsigned underlying type */ - +e9134 - +elib(9134) - -append(9134,[AUTOSAR Rule M5-3-2]) - -/* Rule M5-3-3 (required, implementation, automated) */ - - /* 9135 - unary operator & overloaded */ - +e9135 - +elib(9135) - -append(9135,[AUTOSAR Rule M5-3-3]) - -/* Rule M5-3-4 (required, implementation, automated) */ - - /* 9006 - 'sizeof' used on expression with side effect */ - +e9006 - +elib(9006) - -append(9006,[AUTOSAR Rule M5-3-4]) - -/* Rule A5-3-1 (required, implementation, non-automated) */ - - /* 9414 - typeid' used on expression with side effect */ - +e9414 - +elib(9414) - -append(9414,[AUTOSAR Rule A5-3-1]) - -/* Rule A5-5-1 (required, implementation, automated) */ - - /* 414 - possible division by zero */ - +e414 - +elib(414) - -append(414,[AUTOSAR Rule A5-5-1]) - -/* Rule M5-8-1 (required, implementation, partially automated) */ - - /* 9136 - the shift value is at least the precision of the AUTOSAR - underlying type of the left hand side */ - +e9136 - +elib(9136) - -append(9136,[AUTOSAR Rule M5-8-1]) - -/* Rule A5-10-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M5-14-1 (required, implementation, automated) */ - - /* side effects on right hand of logical operator */ - +e9007 - +elib(9007) - -append(9007,[AUTOSAR Rule M5-14-1]) - -/* Rule A5-16-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M5-17-1 (required, implementation, non-automated) */ - - /* not currently supported */ - -/* Rule M5-18-1 (required, implementation, automated) */ - - /* 9008 - comma operator used */ - +e9008 - +elib(9008) - -append(9008,[AUTOSAR Rule M5-18-1]) - -/* Rule M5-19-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M6-2-1 (required, implementation, automated) */ - - /* 720 - boolean test of assignment */ - +e720 - +elib(720) - -append(720,[AUTOSAR Rule M6-2-1]) - - /* 820 - boolean test of parenthesized assignment */ - +e820 - +elib(820) - -append(820,[AUTOSAR Rule M6-2-1]) - - /* 9084 - result of assignment operator used */ - +e9084 - +elib(9084) - -append(9084,[AUTOSAR Rule M6-2-1]) - -/* Rule M6-2-2 (required, implementation, partially automated) */ - - /* 777 - testing floating point values for equality */ - +e777 - +elib(777) - -append(777,[AUTOSAR Rule M6-2-2]) - - /* 9252 - testing floating point for equality using exact value */ - +e9252 - +elib(9252) - -append(9252,[AUTOSAR Rule M6-2-2]) - -/* Rule M6-2-3 (required, implementation, automated) */ - - /* 9138 - null statement not on line by itself */ - +e9138 - +elib(9138) - -append(9138,[AUTOSAR Rule M6-2-3]) - -/* Rule M6-3-1 (required, implementation, automated) */ - - /* 9012 - body should be a compound statement */ - +e9012 - +elib(9012) - -append(9012,[AUTOSAR Rule M6-3-1]) - -/* Rule M6-4-1 (required, implementation, automated) */ - - /* 9012 - body should be a compound statement */ - +e9012 - +elib(9012) - -append(9012,[AUTOSAR Rule M6-4-1]) - -/* Rule M6-4-2 (required, implementation, automated) */ - - /* 9013 - no 'else' at end of 'if ... else if' chain */ - +e9013 - +elib(9013) - -append(9013,[AUTOSAR Rule M6-4-2]) - -/* Rule M6-4-3 (required, implementation, automated) */ - - /* 9042 - departure from MISRA switch syntax */ - +e9042 - +elib(9042) - -append(9042,[AUTOSAR Rule M6-4-3]) - -/* Rule M6-4-4 (required, implementation, automated) */ - - /* 9055 - most closely enclosing compound statement of this case/default - label is not a switch statement */ - +e9055 - +elib(9055) - -append(9055,[AUTOSAR Rule M6-4-4]) - -/* Rule M6-4-5 (required, implementation, automated) */ - - /* 9090 - switch case lacks unconditional break or throw */ - +e9090 - +elib(9090) - -append(9090,[AUTOSAR Rule M6-4-5]) - -/* Rule M6-4-6 (required, implementation, automated) */ - - /* 744 - switch statement has no default */ - +e744 - +elib(744) - -append(744,[AUTOSAR Rule M6-4-6]) - - /* 787 - enum constant not used within switch */ - +e787 - +elib(787) - -append(787,[AUTOSAR Rule M6-4-6]) - - /* 9139 - case label follows default in switch statement */ - +e9139 - +elib(9139) - -append(9139,[AUTOSAR Rule M6-4-6]) - -/* Rule M6-4-7 (required, implementation, automated) */ - - /* 483 - switching on a boolean value */ - +e483 - +elib(483) - -append(483,[AUTOSAR Rule M6-4-7]) - -/* Rule A6-4-1 (required, implementation, automated) */ - - /* 9181 - switch contains fewer than two non-default switch cases */ - +e9181 - +elib(9181) - -append(9181,[AUTOSAR Rule A6-4-1]) - -/* Rule A6-5-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A6-5-2 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M6-5-2 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M6-5-3 (required, implementation, automated) */ - - /* 850 - for statement index variable modified in body */ - +e850 - +elib(850) - -append(850,[AUTOSAR Rule M6-5-3]) - -/* Rule M6-5-4 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M6-5-5 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M6-5-6 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A6-6-1 (required, implementation, automated) */ - - /* 801 - goto statement used */ - +e801 - +elib(801) - -append(801,[AUTOSAR Rule A6-6-1]) - -/* Rule M6-6-1 (required, implementation, automated) */ - - /* 9041 - goto appears in block 'String' which is not nested in - block 'String' which contains label 'Symbol' */ - +e9041 - +elib(9041) - -append(9041,[AUTOSAR Rule M6-6-1]) - -/* Rule M6-6-2 (required, implementation, automated) */ - - /* 107 - label not defined */ - +e107 - +elib(107) - -append(107,[AUTOSAR Rule M6-6-2]) - - /* 9064 - goto references earlier label */ - +e9064 - +elib(9064) - -append(9064,[AUTOSAR Rule M6-6-2]) - -/* Rule M6-6-3 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A7-1-1 (required, implementation, automated) */ - - /* 843 - static storage duration variable could be const */ - +e843 - +elib(843) - -append(843,[AUTOSAR Rule A7-1-1]) - - /* 952 - parameter of function could be const */ - +e952 - +elib(952) - -append(952,[AUTOSAR Rule A7-1-1]) - - /* 953 - local variable could be const */ - +e953 - +elib(953) - -append(953,[AUTOSAR Rule A7-1-1]) - -/* Rule A7-1-2 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M7-1-2 (required, implementation, automated) */ - - /* 818 - parameter of function could be pointer to const */ - +e818 - +elib(818) - -append(818,[AUTOSAR Rule M7-1-2]) - - /* 1764 - reference parameter could be reference to const */ - +e1764 - +elib(1764) - -append(1764,[AUTOSAR Rule M7-1-2]) - - -fcv /* report parameters even if exclusively cast to void */ - -/* Rule A7-1-3 (required, implementation, automated) */ - - /* 9183 - qualifier precedes typedef type */ - +e9183 - +elib(9183) - -append(9183,[AUTOSAR Rule A7-1-3]) - -/* Rule A7-1-4 (required, implementation, automated) */ - - /* 586 - keyword is deprecated */ - +e586 - +elib(586) - - -deprecate(keyword, register) - -append(586(register),[AUTOSAR Rule A7-1-4]) - -/* Rule A7-1-5 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A7-1-6 (required, implementation, automated) */ - - /* 9416 - typedef used to define name */ - +e9416 - +elib(9416) - -append(9416,[AUTOSAR Rule A7-1-6]) - -/* Rule A7-1-7 (required, implementation, automated) */ - - /* 9146 - multiple declarators in a declaration */ - +e9146 - +elib(9146) - -append(9146,[AUTOSAR Rule A7-1-7]) - -/* Rule A7-1-8 (required, implementation, automated) */ - - /* 618 - storage class specified after a type */ - +e618 - +elib(618) - -append(618,[AUTOSAR Rule A7-1-8]) - - /* 2618 - non-type specifier appears after a type */ - +e2618 - +elib(2618) - -append(2618,[AUTOSAR Rule A7-1-8]) - -/* Rule A7-2-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A7-2-2 (required, implementation, automated) */ - - /* 9418 - enum does not have an explicitly specified underlying type */ - +e9418 - +elib(9418) - -append(9418,[AUTOSAR Rule A7-2-2]) - -/* Rule A7-2-3 (required, implementation, automated) */ - - /* 9419 - enum is not a scoped enumeration */ - +e9419 - +elib(9419) - -append(9419,[AUTOSAR Rule A7-2-3]) - -/* Rule A7-2-4 (required, implementation, automated) */ - - /* 9148 - '=' should initialize either all enum members or only the first */ - +e9148 - +elib(9148) - -append(9148,[AUTOSAR Rule A7-2-4]) - -/* Rule M7-3-1 (required, implementation, automated) */ - - /* 9141 - global declaration of symbol */ - +e9141 - +elib(9141) - -append(9141,[AUTOSAR Rule M7-3-1]) - - /* 9162 - use of static_assert/using declaration at global scope */ - +e9162 - +elib(9162) - -append(9162,[AUTOSAR Rule M7-3-1]) - -/* Rule M7-3-2 (required, implementation, automated) */ - - /* 9142 - function main declared outside the global namespace */ - +e9142 - +elib(9142) - -append(9142,[AUTOSAR Rule M7-3-2]) - -/* Rule M7-3-3 (required, implementation, automated) */ - - /* 1751 - anonymous namespace declared in a header file */ - +e1751 - +elib(1751) - -append(1751,[AUTOSAR Rule M7-3-3]) - -/* Rule M7-3-4 (required, implementation, automated) */ - - /* 9144 - using directive used */ - +e9144 - +elib(9144) - -append(9144,[AUTOSAR Rule M7-3-4]) - -/* Rule M7-3-5 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M7-3-6 (required, implementation, automated) */ - - /* 9145 - using declaration/directive in header */ - +e9145 - +elib(9145) - -append(9145,[AUTOSAR Rule M7-3-6]) - -/* Rule A7-4-1 (required, implementation, automated) */ - - /* 586 - keyword is deprecated */ - +e586 - +elib(586) - - -deprecate(keyword, asm) - -append(586(asm),[AUTOSAR Rule A7-4-1]) - -/* Rule M7-4-1 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule M7-4-2 (required, implementation, automated) */ - - -rw(_asm) - -rw(__asm) - -pragma(asm) - -pragma(endasm) - -ppw(asm) - -ppw(endasm) - -/* Rule M7-4-3 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M7-5-1 (required, implementation, non-automated) */ - - /* 604 - returning address of auto variable */ - +e604 - +elib(604) - -append(604,[AUTOSAR Rule M7-5-1]) - -/* Rule M7-5-2 (required, implementation, non-automated) */ - - /* 789 - assigning address of auto variable to static */ - +e789 - +elib(789) - -append(789,[AUTOSAR Rule M7-5-2]) - -/* Rule A7-5-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A7-5-2 (required, implementation, automated) */ - - /* 9070 - function is recursive */ - +e9070 - +elib(9070) - -append(9070,[AUTOSAR Rule A7-5-2]) - -/* Rule M8-0-1 (required, implementation, automated) */ - - /* 9146 - multiple declarators in a declaration */ - +e9146 - +elib(9146) - -append(9146,[AUTOSAR Rule M8-0-1]) - -/* Rule A8-2-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M8-3-1 (required, implementation, automated) */ - - /* 1735 - parameter of virtual function has default argument */ - +e1735 - +elib(1735) - -append(1735,[AUTOSAR Rule M8-3-1]) - -/* Rule A8-4-1 (required, implementation, automated) */ - - /* 9165 - function defined with a variable number of arguments */ - +e9165 - +elib(9165) - -append(9165,[AUTOSAR Rule A8-4-1]) - -/* Rule M8-4-2 (required, implementation, automated) */ - - /* 9072 - parameter of function has different name than previous - declaration */ - +e9072 - +elib(9072) - -append(9072,[AUTOSAR Rule M8-4-2]) - - /* 9272 - parameter of function has different name than overridden - function */ - +e9272 - +elib(9272) - -append(9272,[AUTOSAR Rule M8-4-2]) - -/* Rule A8-4-2 (required, implementation, automated) */ - - /* 533 - function should return a value */ - +e533 - +elib(533) - -append(533,[AUTOSAR Rule A8-4-2]) - -/* Rule M8-4-4 (required, implementation, automated) */ - - /* 9147 - implicit function-to-pointer decay */ - +e9147 - +elib(9147) - -append(9147,[AUTOSAR Rule M8-4-4]) - -/* Rule M8-5-1 (required, implementation, automated) */ - - /* 530 - likely using an uninitialized value */ - +e530 - +elib(530) - -append(530,[AUTOSAR Rule M8-5-1]) - -/* Rule A8-5-1 (required, implementation, automated) */ - - /* 1729 - initializer inversion */ - +e1729 - +elib(1729) - -append(1729,[AUTOSAR Rule A8-5-1]) - -/* Rule M8-5-2 (required, implementation, automated) */ - - /* 940 - omitted braces within initializer */ - +e940 - +elib(940) - -append(940,[AUTOSAR Rule M8-5-2]) - -/* Rule A8-5-2 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A8-5-3 (required, implementation, automated) */ - - /* 9415 - 'auto' variable initialized using list initialization */ - +e9415 - +elib(9415) - -append(9415,[AUTOSAR Rule A8-5-3]) - -/* Rule A8-5-4 (advisory, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule M9-3-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A9-3-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M9-3-3 (required, implementation, automated) */ - - /* 1762 - member function could be made const */ - +e1762 - +elib(1762) - -append(1762,[AUTOSAR Rule M9-3-3]) - -/* Rule M9-5-1 (required, implementation, automated) */ - - /* 9018 - union declared */ - +e9018 - +elib(9018) - -append(9018,[AUTOSAR Rule M9-5-1]) - -/* Rule M9-6-1 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule A9-6-1 (required, implementation, automated) */ - - /* 9420 - bitfield does not have unsigned integer or explicitly unsigned enumeration type */ - +e9420 - +elib(9420) - -append(9420,[AUTOSAR Rule A9-6-1]) - -/* Rule A10-1-1 (required, implementation, automated) */ - - /* 9432 - class has multiple non-interface bases */ - +e9432 - +elib(9432) - -append(9432,[AUTOSAR Rule A10-1-1]) - -/* Rule M10-1-1 (advisory, implementation, automated) */ - - /* 9174 - 'Type' is a virtual base class of 'Symbol' */ - +e9174 - +elib(9174) - -append(9174,[AUTOSAR Rule M10-1-1]) - -/* Rule M10-1-2 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M10-1-3 (required, implementation, automated) */ - - /* 1748 - non-virtual base class symbol included twice in class symbol */ - +e1748 - +elib(1748) - -append(1748,[AUTOSAR Rule M10-1-3]) - -/* Rule M10-2-1 (advisory, implementation, automated) */ - - /* not currently supported */ - -/* Rule A10-2-1 (required, implementation, automated) */ - - /* 1511 - member hides non-virtual member */ - +e1511 - +elib(1511) - -append(1511,[AUTOSAR Rule A10-2-1]) - -/* Rule A10-3-1 (required, implementation, automated) */ - - /* 9422 - virtual function should specify exactly one of 'virtual', 'override', or 'final' */ - +e9422 - +elib(9422) - -append(9422,[AUTOSAR Rule A10-3-1]) - -/* Rule A10-3-2 (required, implementation, automated) */ - - /* 9421 - virtual function overrides and is not marked with 'override' or 'final' */ - +e9421 - +elib(9421) - -append(9421,[AUTOSAR Rule A10-3-2]) - -/* Rule A10-3-3 (required, implementation, automated) */ - - /* 1779 - virtual function introduced in class which is marked as 'final' */ - +e1779 - +elib(1779) - -append(1779,[AUTOSAR Rule A10-3-3]) - -/* Rule A10-3-5 (required, implementation, automated) */ - - /* 9407 - copy assignment operator should not be virtual */ - +e9407 - +elib(9407) - -append(9407,[AUTOSAR Rule A10-3-5]) - - /* 9410 - move assignment operator should not be virtual */ - +e9410 - +elib(9410) - -append(9410,[AUTOSAR Rule A10-3-5]) - - /* 9438 - assignment operator should not be virtual */ - +e9438 - +elib(9438) - -append(9438,[AUTOSAR Rule A10-3-5]) - -/* Rule M10-3-3 (required, implementation, automated) */ - - /* 9170 - pure function 'Symbol' overrides non-pure function 'Symbol' */ - +e9170 - +elib(9170) - -append(9170,[AUTOSAR Rule M10-3-3]) - -/* Rule M11-0-1 (required, implementation, automated) */ - - /* 9150 - non-private data member within a non-POD structure */ - +e9150 - +elib(9150) - -append(9150,[AUTOSAR Rule M11-0-1]) - -/* Rule A11-0-1 (advisory, implementation, automated) */ - - /* 9437 - non-POD struct should be defined as a class */ - +e9437 - +elib(9437) - -append(9437,[AUTOSAR Rule A11-0-1]) - -/* Rule A11-0-2 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A11-3-1 (required, implementation, automated) */ - - /* 9435 - declared as friend in class */ - +e9435 - +elib(9435) - -append(9435,[AUTOSAR Rule A11-3-1]) - -/* Rule A12-0-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A12-1-1 (required, implementation, automated) */ - - /* 1401 - non-static data member not initialized by constructor */ - +e1401 - +elib(1401) - -append(1401,[AUTOSAR Rule A12-1-1]) - - /* 1928 - base class absent from initializer list for constructor */ - +e1928 - +elib(1928) - -append(1928,[AUTOSAR Rule A12-1-1]) - -/* Rule M12-1-1 (required, implementation, automated) */ - - /* 1506 - call to virtual function within a constructor/destructor */ - +e1506 - +elib(1506) - -append(1506,[AUTOSAR Rule M12-1-1]) - -/* Rule A12-1-2 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A12-1-3 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A12-1-4 (required, implementation, automated) */ - - /* 9169 - constructor can be used for implicit conversions to fundamental type */ - +e9169 - +elib(9169) - -append(9169,[AUTOSAR Rule A12-1-4]) - -/* Rule A12-4-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A12-4-2 (advisory, implementation, automated) */ - - /* 9441 - non-final class symbol has a public non-virtual destructor */ - +e9441 - +elib(9441) - -append(9441,[AUTOSAR Rule A12-4-2]) - -/* Rule A12-6-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A12-7-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A12-8-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A12-8-2 (advisory, implementation, automated) */ - - /* not currently supported */ - -/* Rule A12-8-3 (required, implementation, partially automated) */ - - /* not currently supported */ - -/* Rule A12-8-4 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A12-8-5 (required, implementation, automated) */ - - /* 1529 - assignment operator should check for self-assignment */ - +e1529 - +elib(1529) - -append(1529,[AUTOSAR Rule A12-8-5]) - -/* Rule A12-8-6 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A12-8-7 (advisory, implementation, automated) */ - - /* 9185 - assignment operator declared without lvalue ref-qualifier */ - +e9185 - +elib(9185) - -append(9185,[AUTOSAR Rule A12-8-7]) - -/* Rule A13-1-1 (required, implementation, automated) */ - - /* 9433 - literal operator function declared */ - +e9433 - +elib(9433) - -append(9433,[AUTOSAR Rule A13-1-1]) - - /* 9434 - user-defined literal with suffix used */ - +e9434 - +elib(9434) - -append(9434,[AUTOSAR Rule A13-1-1]) - -/* Rule A13-1-2 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A13-1-3 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A13-2-1 (required, implementation, automated) */ - - /* 9447 - assignment operator should return type */ - +e9447 - +elib(9447) - -append(9447,[AUTOSAR Rule A13-2-1]) - - /* 9448 - assignment operator should return value */ - +e9448 - +elib(9448) - -append(9448,[AUTOSAR Rule A13-2-1]) - -/* Rule A13-2-2 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A13-2-3 (required, implementation, automated) */ - - /* 9186 - non-Boolean return type for comparison function */ - +e9186 - +elib(9186) - -append(9186,[AUTOSAR Rule A13-2-3]) - -/* Rule A13-3-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A13-5-1 (required, implementation, automated) */ - - /* 9187 - non-const overloaded subscript operator declared without a corresponding const version */ - +e9187 - +elib(9187) - -append(9187,[AUTOSAR Rule A13-5-1]) - -/* Rule A13-6-1 (required, implementation, automated) */ - - /* 9440 - Digit sequence separators in STRING TYPE literal 'STRING' should be every INTEGER digits */ - +e9440 - +elib(9440) - -append(9440,[AUTOSAR Rule A13-6-1]) - -/* Rule A14-1-1 (advisory, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule M14-5-2 (required, implementation, automated) */ - - /* 1789 - constructor template cannot be a copy constructor */ - +e1789 - +elib(1789) - -append(1789,[AUTOSAR Rule M14-5-2]) - -/* Rule M14-5-3 (required, implementation, automated) */ - - /* 1721 - operator=() for is not a copy nor move assignment operator */ - +e1721 - +elib(1721) - -append(1721,[AUTOSAR Rule M14-5-3]) - -/* Rule M14-6-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A14-7-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M14-7-3 (required, implementation, automated) */ - - /* 1576 - explicit specialization is not in the same file as specialized - function template */ - +e1576 - +elib(1576) - -append(1576,[AUTOSAR Rule M14-7-3]) - -/* Rule M14-8-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A14-8-1 (advisory, implementation, automated) */ - - /* 9153 - viable set contains both function and template */ - +e9153 - +elib(9153) - -append(9153,[AUTOSAR Rule A14-8-1]) - -/* Rule A15-0-1 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule A15-0-2 (required, implementation, partially automated) */ - - /* not currently supported */ - -/* Rule A15-0-3 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule A15-0-4 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule A15-0-5 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule A15-0-6 (required, verification, non-automated) */ - - /* not statically checkable */ - -/* Rule A15-0-7 (required, implementation, partially automated) */ - - /* not currently supported */ - -/* Rule A15-0-8 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule A15-1-1 (required, implementation, automated) */ - - /* 3902 - thrown object of type is not a class derived from std::exception */ - +e3902 - +elib(3902) - -append(3902,[AUTOSAR Rule A15-1-1]) - -/* Rule A15-1-2 (required, implementation, automated) */ - - /* 9154 - throwing a pointer */ - +e9154 - +elib(9154) - -append(9154,[AUTOSAR Rule A15-1-2]) - -/* Rule M15-0-3 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M15-1-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M15-1-2 (required, implementation, automated) */ - - /* 1419 - throwing the NULL macro will invoke an implementation-defined handler */ - +e1419 - +elib(1419) - -append(1419,[AUTOSAR Rule M15-1-2]) - -/* Rule M15-1-3 (required, implementation, automated) */ - - /* 9156 - rethrow outside of catch block will call std::terminate if no - exception is being handled */ - +e9156 - +elib(9156) - -append(9156,[AUTOSAR Rule M15-1-3]) - -/* Rule A15-1-3 (advisory, implementation, automated) */ - - /* not currently supported */ - -/* Rule A15-1-4 (required, implementation, partially automated) */ - - /* not currently supported */ - -/* Rule A15-1-5 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule A15-2-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A15-2-2 (required, implementation, partially automated) */ - - /* not currently supported */ - -/* Rule M15-3-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A15-3-1 (advisory, implementation, automated) */ - - /* not currently supported */ - -/* Rule A15-3-2 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule A15-3-3 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A15-3-4 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule M15-3-3 (required, implementation, automated) */ - - /* not statically checkable */ - -/* Rule M15-3-4 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A15-3-5 (required, implementation, automated) */ - - /* 1752 - catch parameter is not a reference */ - +e1752 - +elib(1752) - -append(1752,[AUTOSAR Rule A15-3-5]) - -/* Rule M15-3-6 (required, implementation, automated) */ - - /* 1775 - catch block does not catch any declared exceptions */ - +e1775 - +elib(1775) - -append(1775,[AUTOSAR Rule M15-3-6]) - -/* Rule M15-3-7 (required, implementation, automated) */ - - /* 1127 - catch handler after catch(...) */ - +e1127 - +elib(1127) - -append(1127,[AUTOSAR Rule M15-3-7]) - -/* Rule A15-4-1 (required, implementation, automated) */ - - /* 1906 - exception specification for function */ - +e1906 - +elib(1906) - -append(1906,[AUTOSAR Rule A15-4-1]) - -/* Rule A15-4-2 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A15-4-3 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A15-4-4 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A15-4-5 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A15-4-6 (advisory, implementation, automated) */ - - /* not currently supported */ - -/* Rule A15-5-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A15-5-2 (required, implementation, partially automated) */ - - /* 9156 - rethrow outside of catch block will call std::terminate if no - exception is being handled */ - +e9156 - +elib(9156) - -append(9156,[AUTOSAR Rule A15-5-2]) - - /* 586 - type is deprecated */ - +e586 - +elib(586) - - -deprecate(function,abort,[AUTOSAR Rule A15-5-2]) - -deprecate(function,quick_exit,[AUTOSAR Rule A15-5-2]) - -deprecate(function,_Exit,[AUTOSAR Rule A15-5-2]) - -deprecate(function,terminate,[AUTOSAR Rule A15-5-2]) - - -deprecate(function,std::abort,[AUTOSAR Rule A15-5-2]) - -deprecate(function,std::quick_exit,[AUTOSAR Rule A15-5-2]) - -deprecate(function,std::_Exit,[AUTOSAR Rule A15-5-2]) - -deprecate(function,std::terminate,[AUTOSAR Rule A15-5-2]) - -/* Rule A15-5-3 (required, implementation, automated) */ - - /* 9156 - rethrow outside of catch block will call std::terminate if no exception is being handled */ - +e9156 - +elib(9156) - -append(9156,[AUTOSAR Rule A15-5-3]) - -/* Rule A16-0-1 (required, implementation, automated) */ - - /* 9021 - use of '#undef' is discouraged */ - +e9021 - +elib(9021) - -append(9021,[AUTOSAR Rule A16-0-1]) - - /* 9026 - function-like macro defined */ - +e9026 - +elib(9026) - -append(9026,[AUTOSAR Rule A16-0-1]) - - /* 586 - preprocessor directive is deprecated */ - +e586 - +elib(586) - - /* 886 - preprocessor directive encountered in conditionally excluded region is deprecated. */ - +e886 - +elib(886) - - -deprecate(ppw,pragma,[AUTOSAR Rule A16-0-1]) - -deprecate(ppw,error,[AUTOSAR Rule A16-0-1]) - -deprecate(ppw,line,[AUTOSAR Rule A16-0-1]) - /* Deprecate the null directive */ - -deprecate(ppw,"",[AUTOSAR Rule A16-0-1]) - -/* Rule M16-0-1 (required, implementation, automated) */ - - /* 9019 - declaration of 'Symbol' before #include */ - +e9019 - +elib(9019) - -append(9019,[AUTOSAR Rule M16-0-1]) - -/* Rule M16-0-2 (required, implementation, automated) */ - - /* 9158 - #define used within block scope */ - +e9158 - +elib(9158) - -append(9158,[AUTOSAR Rule M16-0-2]) - - /* 9159 - #undef used within block scope */ - +e9159 - +elib(9159) - -append(9159,[AUTOSAR Rule M16-0-2]) - -/* Rule M16-0-5 (required, implementation, automated) */ - - /* 436 - preprocessor directive in invocation of macro */ - +e436 - +elib(436) - -append(436,[AUTOSAR Rule M16-0-5]) - -/* Rule M16-0-6 (required, implementation, automated) */ - - /* 9022 - unparenthesized macro parameter in definition of macro */ - +e9022 - +elib(9022) - -append(9022,[AUTOSAR Rule M16-0-6]) - -/* Rule M16-0-7 (required, implementation, automated) */ - - /* 553 - undefined preprocessor variable assumed to be 0 */ - +e553 - +elib(553) - -append(553,[AUTOSAR Rule M16-0-7]) - -/* Rule M16-0-8 (required, implementation, automated) */ - - /* 16 - unknown preprocessor directive */ - +e16 - +elib(16) - -append(16,[AUTOSAR Rule M16-0-8]) - - /* 544 - preprocessor directive not followed by EOL */ - +e544 - +elib(544) - -append(544,[AUTOSAR Rule M16-0-8]) - - /* 9160 - unknown preprocessor directive in conditionally excluded region */ - +e9160 - +elib(9160) - -append(9160,[AUTOSAR Rule M16-0-8]) - -/* Rule M16-1-1 (required, implementation, automated) */ - - /* 491 - non-standard use of 'defined' preprocessor operator */ - +e491 - +elib(491) - -append(491,[AUTOSAR Rule M16-1-1]) - -/* Rule M16-1-2 (required, implementation, automated) */ - - /* 8 - unclosed #if */ - +e8 - +elib(8) - -append(8,[AUTOSAR Rule M16-1-2]) - -/* Rule M16-2-3 (required, implementation, automated) */ - - /* 967 - header file does not have a standard include guard */ - +e967 - +elib(967) - -append(967,[AUTOSAR Rule M16-2-3]) - -/* Rule A16-2-1 (required, implementation, automated) */ - - /* 9020 - header file name with non-standard character */ - +e9020 - -append(9020,[AUTOSAR Rule A16-2-1]) - -/* Rule A16-2-2 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A16-2-3 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule M16-3-1 (required, implementation, automated) */ - - /* 9023 - multiple use of stringize/pasting operators in definition of macro */ - +e9023 - +elib(9023) - -append(9023,[AUTOSAR Rule M16-3-1]) - -/* Rule M16-3-2 (advisory, implementation, automated) */ - - /* 9024 - pasting/stringize operator used in definition of macro */ - +e9024 - +elib(9024) - -append(9024,[AUTOSAR Rule M16-3-2]) - -/* Rule A16-6-1 (required, implementation, automated) */ - - /* 586 - preprocessor directive is deprecated */ - +e586 - +elib(586) - - /* 886 - preprocessor directive encountered in conditionally excluded region is deprecated. */ - +e886 - +elib(886) - - -deprecate(ppw,error,[AUTOSAR Rule A16-6-1]) - -/* Rule A16-7-1 (required, implementation, automated) */ - - /* 586 - preprocessor directive is deprecated */ - +e586 - +elib(586) - - /* 886 - preprocessor directive encountered in conditionally excluded region is deprecated. */ - +e886 - +elib(886) - - -deprecate(ppw,pragma,[AUTOSAR Rule A16-7-1]) - -/* Rule A17-0-1 (required, implementation, automated) */ - - /* 9093 - the name is reserved to the compiler */ - +e9093 - +elib(9093) - -append(9093,[AUTOSAR Rule A17-0-1]) - -/* Rule M17-0-2 (required, implementation, automated) */ - - /* 9093 - the name is reserved to the compiler */ - +e9093 - +elib(9093) - -append(9093,[AUTOSAR Rule M17-0-2]) - -/* Rule M17-0-3 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M17-0-5 (required, implementation, automated) */ - - /* 586 - symbol is deprecated */ - +e586 - +elib(586) - - -deprecate(function,longjmp,[AUTOSAR Rule M17-0-5] ) - -deprecate(function,std::longjmp,[AUTOSAR Rule M17-0-5] ) - -deprecate(macro,setjmp,[AUTOSAR Rule M17-0-5] ) - -/* Rule A17-1-1 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule A18-0-1 (required, implementation, automated) */ - - /* 829 - a +headerwarn option was previously issued for header */ - +e829 - +elib(829) - - +headerwarn(time.h) - +headerwarn(limits.h) - +headerwarn(float.h) - +headerwarn(stddef.h) - +headerwarn(errno.h) - +headerwarn(locale.h) - +headerwarn(stdio.h) - +headerwarn(ctype.h) - +headerwarn(string.h) - +headerwarn(math.h) - +headerwarn(stdlib.h) - +headerwarn(assert.h) - +headerwarn(stdarg.h) - +headerwarn(setjmp.h) - +headerwarn(signal.h) - - -append(829(time.h),[AUTOSAR Rule A18-0-1]) - -append(829(limits.h),[AUTOSAR Rule A18-0-1]) - -append(829(float.h),[AUTOSAR Rule A18-0-1]) - -append(829(stddef.h),[AUTOSAR Rule A18-0-1]) - -append(829(errno.h),[AUTOSAR Rule A18-0-1]) - -append(829(locale.h),[AUTOSAR Rule A18-0-1]) - -append(829(stdio.h),[AUTOSAR Rule A18-0-1]) - -append(829(ctype.h),[AUTOSAR Rule A18-0-1]) - -append(829(string.h),[AUTOSAR Rule A18-0-1]) - -append(829(math.h),[AUTOSAR Rule A18-0-1]) - -append(829(stdlib.h),[AUTOSAR Rule A18-0-1]) - -append(829(assert.h),[AUTOSAR Rule A18-0-1]) - -append(829(stdarg.h),[AUTOSAR Rule A18-0-1]) - -append(829(setjmp.h),[AUTOSAR Rule A18-0-1]) - -append(829(signal.h),[AUTOSAR Rule A18-0-1]) - -/* Rule A18-0-2 (required, implementation, automated) */ - - /* 586 - function is deprecated */ - +e586 - +elib(586) - - -deprecate(function,atof,[AUTOSAR Rule A18-0-2]) - -deprecate(function,atoi,[AUTOSAR Rule A18-0-2]) - -deprecate(function,atol,[AUTOSAR Rule A18-0-2]) - - -deprecate(function,std::atof,[AUTOSAR Rule A18-0-2]) - -deprecate(function,std::atoi,[AUTOSAR Rule A18-0-2]) - -deprecate(function,std::atol,[AUTOSAR Rule A18-0-2]) - -/* Rule M18-0-3 (required, implementation, automated) */ - - /* 586 - function is deprecated */ - +e586 - +elib(586) - - -deprecate(function,abort,[AUTOSAR Rule M18-0-3]) - -deprecate(function,exit,[AUTOSAR Rule M18-0-3]) - -deprecate(function,getenv,[AUTOSAR Rule M18-0-3]) - -deprecate(function,system,[AUTOSAR Rule M18-0-3]) - - -deprecate(function,std::abort,[AUTOSAR Rule M18-0-3]) - -deprecate(function,std::exit,[AUTOSAR Rule M18-0-3]) - -deprecate(function,std::getenv,[AUTOSAR Rule M18-0-3]) - -deprecate(function,std::system,[AUTOSAR Rule M18-0-3]) - -/* Rule M18-0-4 (required, implementation, automated) */ - - /* 586 - function is deprecated */ - +e586 - +elib(586) - - -deprecate(function,wcsftime,[AUTOSAR Rule M18-0-4]) - -deprecate(function,clock,[AUTOSAR Rule M18-0-4]) - -deprecate(function,difftime,[AUTOSAR Rule M18-0-4]) - -deprecate(function,mktime,[AUTOSAR Rule M18-0-4]) - -deprecate(function,time,[AUTOSAR Rule M18-0-4]) - -deprecate(function,asctime,[AUTOSAR Rule M18-0-4]) - -deprecate(function,ctime,[AUTOSAR Rule M18-0-4]) - -deprecate(function,gmtime,[AUTOSAR Rule M18-0-4]) - -deprecate(function,localtime,[AUTOSAR Rule M18-0-4]) - -deprecate(function,strftime,[AUTOSAR Rule M18-0-4]) - - -deprecate(function,std::wcsftime,[AUTOSAR Rule M18-0-4]) - -deprecate(function,std::clock,[AUTOSAR Rule M18-0-4]) - -deprecate(function,std::difftime,[AUTOSAR Rule M18-0-4]) - -deprecate(function,std::mktime,[AUTOSAR Rule M18-0-4]) - -deprecate(function,std::time,[AUTOSAR Rule M18-0-4]) - -deprecate(function,std::asctime,[AUTOSAR Rule M18-0-4]) - -deprecate(function,std::ctime,[AUTOSAR Rule M18-0-4]) - -deprecate(function,std::gmtime,[AUTOSAR Rule M18-0-4]) - -deprecate(function,std::localtime,[AUTOSAR Rule M18-0-4]) - -deprecate(function,std::strftime,[AUTOSAR Rule M18-0-4]) - -/* Rule M18-0-5 (required, implementation, automated) */ - - /* 586 - function is deprecated */ - +e586 - +elib(586) - - -deprecate(function,strcpy,[AUTOSAR Rule M18-0-5]) - -deprecate(function,strcmp,[AUTOSAR Rule M18-0-5]) - -deprecate(function,strcat,[AUTOSAR Rule M18-0-5]) - -deprecate(function,strchr,[AUTOSAR Rule M18-0-5]) - -deprecate(function,strspn,[AUTOSAR Rule M18-0-5]) - -deprecate(function,strcspn,[AUTOSAR Rule M18-0-5]) - -deprecate(function,strpbrk,[AUTOSAR Rule M18-0-5]) - -deprecate(function,strrchr,[AUTOSAR Rule M18-0-5]) - -deprecate(function,strstr,[AUTOSAR Rule M18-0-5]) - -deprecate(function,strtok,[AUTOSAR Rule M18-0-5]) - -deprecate(function,strlen,[AUTOSAR Rule M18-0-5]) - - -deprecate(function,std::strcpy,[AUTOSAR Rule M18-0-5]) - -deprecate(function,std::strcmp,[AUTOSAR Rule M18-0-5]) - -deprecate(function,std::strcat,[AUTOSAR Rule M18-0-5]) - -deprecate(function,std::strchr,[AUTOSAR Rule M18-0-5]) - -deprecate(function,std::strspn,[AUTOSAR Rule M18-0-5]) - -deprecate(function,std::strcspn,[AUTOSAR Rule M18-0-5]) - -deprecate(function,std::strpbrk,[AUTOSAR Rule M18-0-5]) - -deprecate(function,std::strrchr,[AUTOSAR Rule M18-0-5]) - -deprecate(function,std::strstr,[AUTOSAR Rule M18-0-5]) - -deprecate(function,std::strtok,[AUTOSAR Rule M18-0-5]) - -deprecate(function,std::strlen,[AUTOSAR Rule M18-0-5]) - -/* Rule A18-0-3 (required, implementation, automated) */ - - /* 829 - a +headerwarn option was previously issued for header */ - +e829 - +elib(829) - - +headerwarn(locale.h) - +headerwarn(clocale) - - -append(829(locale.h),[AUTOSAR Rule A18-0-3]) - -append(829(clocale),[AUTOSAR Rule A18-0-3]) - - /* 586 - function is deprecated */ - +e586 - +elib(586) - - -deprecate(function,setlocale,[AUTOSAR Rule A18-0-3]) - -deprecate(function,std::setlocale,[AUTOSAR Rule A18-0-3]) - -/* Rule A18-1-1 (advisory, implementation, automated) */ - - /* 9436 - symbol has array type */ - +e9436 - +elib(9436) - -append(9436,[AUTOSAR Rule A18-1-1]) - -/* Rule A18-1-2 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A18-1-3 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A18-1-4 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A18-1-5 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M18-2-1 (required, implementation, automated) */ - - /* 586 - macro is deprecated */ - +e586 - +elib(586) - - -deprecate(macro,offsetof,[AUTOSAR Rule M18-2-1]) - -/* Rule A18-5-1 (required, implementation, automated) */ - - /* 586 - function is deprecated */ - +e586 - +elib(586) - - -deprecate(function,calloc,[AUTOSAR Rule A18-5-1]) - -deprecate(function,malloc,[AUTOSAR Rule A18-5-1]) - -deprecate(function,realloc,[AUTOSAR Rule A18-5-1]) - -deprecate(function,free,[AUTOSAR Rule A18-5-1]) - - -deprecate(function,std::calloc,[AUTOSAR Rule A18-5-1]) - -deprecate(function,std::malloc,[AUTOSAR Rule A18-5-1]) - -deprecate(function,std::realloc,[AUTOSAR Rule A18-5-1]) - -deprecate(function,std::free,[AUTOSAR Rule A18-5-1]) - -/* Rule A18-5-2 (required, implementation, partially automated) */ - - /* not currently supported */ - -/* Rule A18-5-3 (required, implementation, automated) */ - - /* 424 - delete/delete[]/free is not appropriate for deallocating */ - +e424 - +elib(424) - -append(424,[AUTOSAR Rule A18-5-3]) - -/* Rule A18-5-4 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A18-5-5 (required, implementation, partially automated) */ - - /* not statically checkable */ - -/* Rule A18-5-6 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule A18-5-7 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule M18-7-1 (required, implementation, automated) */ - - /* 586 - function is deprecated */ - +e586 - +elib(586) - - -deprecate(function,signal,[AUTOSAR Rule A18-7-1]) - -deprecate(function,raise,[AUTOSAR Rule A18-7-1]) - - -deprecate(function,std::signal,[AUTOSAR Rule A18-7-1]) - -deprecate(function,std::raise,[AUTOSAR Rule A18-7-1]) - -/* Rule A18-9-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A18-9-2 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A18-9-3 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A18-9-4 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M19-3-1 (required, implementation, automated) */ - - /* 586 - variable is deprecated */ - +e586 - +elib(586) - - -deprecate(variable,errno,[AUTOSAR Rule M19-3-1] ) - -/* Rule A23-0-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M27-0-1 (required, implementation, automated) */ - - /* 586 - variable is deprecated */ - +e586 - +elib(586) - - -deprecate(function,clearerr,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fclose,[AUTOSAR Rule M27-0-1]) - -deprecate(function,feof,[AUTOSAR Rule M27-0-1]) - -deprecate(function,ferror,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fflush,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fgetc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fgetpos,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fgets,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fgetwc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fgetws,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fopen,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fputc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fputs,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fputwc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fputws,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fread,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fseek,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fsetpos,[AUTOSAR Rule M27-0-1]) - -deprecate(function,freopen,[AUTOSAR Rule M27-0-1]) - -deprecate(function,ftell,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fwide,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fwprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fwrite,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fwscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,getc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,getchar,[AUTOSAR Rule M27-0-1]) - -deprecate(function,gets,[AUTOSAR Rule M27-0-1]) - -deprecate(function,getwc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,getwchar,[AUTOSAR Rule M27-0-1]) - -deprecate(function,perror,[AUTOSAR Rule M27-0-1]) - -deprecate(function,printf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,putc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,putchar,[AUTOSAR Rule M27-0-1]) - -deprecate(function,puts,[AUTOSAR Rule M27-0-1]) - -deprecate(function,putwc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,putwchar,[AUTOSAR Rule M27-0-1]) - -deprecate(function,remove,[AUTOSAR Rule M27-0-1]) - -deprecate(function,rename,[AUTOSAR Rule M27-0-1]) - -deprecate(function,rewind,[AUTOSAR Rule M27-0-1]) - -deprecate(function,scanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,setbuf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,setvbuf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,snprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,sprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,sscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,swprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,swscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,tmpfile,[AUTOSAR Rule M27-0-1]) - -deprecate(function,tmpnam,[AUTOSAR Rule M27-0-1]) - -deprecate(function,ungetc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,ungetwc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,vfprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,vfscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,vfwprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,vfwscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,vprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,vscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,vsnprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,vsprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,vsscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,vswprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,vswscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,vwprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,vwscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,wprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,wscanf,[AUTOSAR Rule M27-0-1]) - - -deprecate(function,std::clearerr,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fclose,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::feof,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::ferror,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fflush,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fgetc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fgetpos,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fgets,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fgetwc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fgetws,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fopen,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fputc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fputs,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fputwc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fputws,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fread,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fseek,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fsetpos,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::freopen,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::ftell,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fwide,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fwprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fwrite,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fwscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::getc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::getchar,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::gets,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::getwc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::getwchar,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::perror,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::printf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::putc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::putchar,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::puts,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::putwc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::putwchar,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::remove,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::rename,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::rewind,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::scanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::setbuf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::setvbuf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::snprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::sprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::sscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::swprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::swscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::tmpfile,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::tmpnam,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::ungetc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::ungetwc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::vfprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::vfscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::vfwprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::vfwscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::vprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::vscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::vsnprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::vsprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::vsscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::vswprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::vswscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::vwprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::vwscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::wprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::wscanf,[AUTOSAR Rule M27-0-1]) - -/* Rule A27-0-1 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule A27-0-2 (required, implementation, automated) */ - - /* not currently supported */ - diff --git a/ports/lint-plus/au-autosar19.lnt b/ports/lint-plus/au-autosar19.lnt deleted file mode 100644 index e2bcb8b4e..000000000 --- a/ports/lint-plus/au-autosar19.lnt +++ /dev/null @@ -1,3074 +0,0 @@ -// --------------------------------------------------------------------------- -// Copyright Vector Informatik GmbH 2020. All rights reserved. -// -// This file is provided by Vector Informatik GmbH (https://www.vector.com) for -// use with PC-lint Plus. Redistribution is permitted but any redistribution -// must preserve this notice and, if the redistributed file has been modified, -// provide notice that the file has been modified from the original. -// --------------------------------------------------------------------------- - - -// au-autosar19.lnt -- Author options - AUTOSAR C++ 19-03 - -/* - This options file can be used to explicitly activate those - checks advocated AUTOSAR for C++ code. - - Vector Informatik GmbH relies on the document, "Guidelines for the use of - the C++14 language in critical and safety-related systems" copyright - 2019 by AUTOSAR, as the primary source for this file. Vector Informatik GmbH - makes no warranty as to the completeness or applicability of this - options file and reserves the right to amend or alter the official - contents of such at any time. - - "AUTOSAR" is a registered trademark of AUTOSAR GbR. - - */ - -/* version check */ -cond('%PCLP_NO_LNT_VERSION_CHECK%' != '1' && (%LINT_MAJOR_VERSION% != 2 || %LINT_MINOR_VERSION% != 0), - +fatal_error(This configuration file is intended for PC-lint Plus 2.0. - You are attempting to use it with PC-lint Plus %LINT_MAJOR_VERSION%.%LINT_MINOR_VERSION%. - It is recommended that you use configuration files intended - for PC-lint Plus %LINT_MAJOR_VERSION%.%LINT_MINOR_VERSION%.) -) - -/* ISO/IEC 14882:2014 */ --std=c++14 - -/* Rule M0-1-1 (required, implementation, automated) */ - - /* 527 - statement is unreachable due to unconditional transfer of control */ - +e527 - +elib(527) - -append(527,[AUTOSAR Rule M0-1-1]) - - /* 681 - loop is likely not entered */ - +e681 - +elib(681) - -append(681,[AUTOSAR Rule M0-1-1]) - - /* 827 - loop can only be reached via goto due to unconditional transfer of - control */ - +e827 - +elib(827) - -append(827,[AUTOSAR Rule M0-1-1]) - - /* 685 - relational operator always evaluates to true/false */ - +e685 - +elib(685) - -append(685,[AUTOSAR Rule M0-1-1]) - - /* 774 - boolean condition always evaluates to true/false */ - +e774 - +elib(774) - -append(774,[AUTOSAR Rule M0-1-1]) - - /* 944 - left/right operand always evaluates to true/false */ - +e944 - +elib(944) - -append(944,[AUTOSAR Rule M0-1-1]) - -/* Rule M0-1-2 (required, implementation, automated) */ - - /* 685 - relational operator always evaluates to true/false */ - +e685 - +elib(685) - -append(685,[AUTOSAR Rule M0-1-2]) - - /* 774 - boolean condition always evaluates to true/false */ - +e774 - +elib(774) - -append(774,[AUTOSAR Rule M0-1-2]) - - /* 827 - loop can only be reached via goto due to unconditional transfer of - control */ - +e827 - +elib(827) - -append(827,[AUTOSAR Rule M0-1-2]) - - /* 944 - left/right operand always evaluates to true/false */ - +e944 - +elib(944) - -append(944,[AUTOSAR Rule M0-1-2]) - -/* Rule M0-1-3 (required, implementation, automated) */ - - /* 528 - static symbol not referenced */ - +e528 - +elib(528) - -append(528,[AUTOSAR Rule M0-1-3]) - - /* 529 - local variable not subsequently referenced */ - +e529 - +elib(529) - -append(529,[AUTOSAR Rule M0-1-3]) - - /* 714 - external symbol was defined but not referenced */ - +e714 - +elib(714) - -append(714,[AUTOSAR Rule M0-1-3]) - - /* 752 - local declarator not referenced */ - +e752 - +elib(752) - -append(752,[AUTOSAR Rule M0-1-3]) - - /* 757 - global declarator not referenced */ - +e757 - +elib(757) - -append(757,[AUTOSAR Rule M0-1-3]) - - /* 1715 - static member symbol not referenced */ - +e1715 - +elib(1715) - -append(1715,[AUTOSAR Rule M0-1-3]) - -/* Rule M0-1-4 (required, implementation, automated) */ - - /* 528 - static symbol not referenced */ - +e528 - +elib(528) - -append(528,[AUTOSAR Rule M0-1-4]) - - /* 529 - local variable not subsequently referenced */ - +e529 - +elib(529) - -append(529,[AUTOSAR Rule M0-1-4]) - - /* 550 - local variable not subsequently accessed */ - +e550 - +elib(550) - -append(550,[AUTOSAR Rule M0-1-4]) - - /* 551 - static variable not accessed */ - +e551 - +elib(551) - -append(551,[AUTOSAR Rule M0-1-4]) - - /* 552 - external variable not accessed */ - +e552 - +elib(552) - -append(552,[AUTOSAR Rule M0-1-4]) - -/* Rule A0-1-1 (required, implementation, automated) */ - - /* 438 - last value assigned to symbol not used */ - +e438 - +elib(438) - -append(438,[AUTOSAR Rule A0-1-1]) - - /* 838 - previous value assigned to symbol not used */ - +e838 - +elib(838) - -append(838,[AUTOSAR Rule A0-1-1]) - -/* Rule A0-1-2 (required, implementation, automated) */ - - /* 534 - ignoring return value of function */ - +e534 - +elib(534) - -append(534,[AUTOSAR Rule A0-1-2]) - -/* Rule M0-1-8 (required, implementation, automated) */ - - /* 9175 - function has void return type and no external side-effects */ - +e9175 - +elib(9175) - -append(9175,[AUTOSAR Rule M0-1-8]) - -/* Rule M0-1-9 (required, implementation, automated) */ - - /* 438 - last value assigned to symbol not used */ - +e438 - +elib(438) - -append(438,[AUTOSAR Rule M0-1-9]) - - /* 587 - predicate can be pre-determined and always evaluates to true/false */ - +e587 - +elib(587) - -append(587,[AUTOSAR Rule M0-1-9]) - - /* 685 - relational operator always evaluates to true/false */ - +e685 - +elib(685) - -append(685,[AUTOSAR Rule M0-1-9]) - - /* 774 - boolean condition always evaluates to true/false */ - +e774 - +elib(774) - -append(774,[AUTOSAR Rule M0-1-9]) - - /* 838 - previous value assigned to symbol not used */ - +e838 - +elib(838) - -append(838,[AUTOSAR Rule M0-1-9]) - - /* 944 - left/right operand always evaluates to true/false */ - +e944 - +elib(944) - -append(944,[AUTOSAR Rule M0-1-9]) - - /* 948 - operator always evaluates to true/false */ - +e948 - +elib(948) - -append(948,[AUTOSAR Rule M0-1-9]) - -/* Rule M0-1-10 (advisory, implementation, automated) */ - - /* 528 - static symbol not referenced */ - +e528 - +elib(528) - -append(528,[AUTOSAR Rule M0-1-10]) - - /* 714 - external symbol was defined but not referenced */ - +e714 - +elib(714) - -append(714,[AUTOSAR Rule M0-1-10]) - - /*1714 - member function not referenced */ - +e1714 - +elib(1714) - -append(1714,[AUTOSAR Rule M0-1-10]) - - /* default constructor not referenced */ - +e1914 - +elib(1914) - -append(1914,[AUTOSAR Rule M0-1-10]) - -/* Rule A0-1-3 (required, implementation, automated) */ - - /* 528 - static symbol not referenced */ - +e528 - +elib(528) - -append(528,[AUTOSAR Rule A0-1-3]) - -/* Rule A0-1-4 (required, implementation, automated) */ - - /* 715 - named parameter not subsequently referenced */ - +estring(715,non-virtual) - +elib(715) - -append(715(non-virtual),[AUTOSAR Rule A0-1-4]) - -/* Rule A0-1-5 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A0-1-6 (advisory, implementation, automated) */ - - /* 751 - local typedef not referenced */ - +e751 - +elib(751) - -append(751,[AUTOSAR Rule A0-1-6]) - - /* 753 - local tag not referenced */ - +e753 - +elib(753) - -append(753,[AUTOSAR Rule A0-1-6]) - - /* 756 - global typedef not referenced */ - +e756 - +elib(756) - -append(756,[AUTOSAR Rule A0-1-6]) - - /* 758 - global tag not referenced */ - +e758 - +elib(758) - -append(758,[AUTOSAR Rule A0-1-6]) - -/* Rule M0-2-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M0-3-1 (required, implementation/verification, non-automated) */ - - /* Static Analysis is provided by using PC-lint Plus */ - -/* Rule M0-3-2 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule M0-4-1 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule M0-4-2 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule A0-4-1 (required, infrastructure/toolchain, non-automated) */ - - /* not statically checkable */ - -/* Rule A0-4-2 (required, implementation, automated) */ - - /* 586 - type is deprecated */ - +e586 - +elib(586) - -deprecate(basetype, long double) - -append(586(long double),[AUTOSAR Rule A0-4-2]) - -/* Rule A0-4-3 (required, toolchain, automated) */ - - /* not statically checkable */ - -/* Rule A0-4-4 (required, implementation, partially automated) */ - - /* 2423 - apparent domain error for function */ - +e2423 - +elib(2423) - -append(2423,[AUTOSAR Rule A0-4-4]) - -/* Rule A1-1-1 (required, implementation, automated) */ - - /* 1407 - incrementing expression of type bool */ - +e1407 - +elib(1407) - -append(1407,[AUTOSAR Rule A1-1-1]) - - /* 586 - keyword is deprecated */ - +e586 - +elib(586) - -deprecate(keyword, register) - -append(586(register),[AUTOSAR Rule A1-1-1]) - - /* 1906 - exception specification for function */ - +e1906 - +elib(1906) - -append(1906,[AUTOSAR Rule A1-1-1]) - - /* 586 - function random_shuffle is deprecated */ - +e586 - +elib(586) - -deprecate(function,std::random_shuffle) - -append(586(std::random_shuffle),[AUTOSAR Rule A1-1-1]) - - /* 586 - function adaptors are deprecated */ - +e586 - +elib(586) - -deprecate(function,std::ptr_fun,[AUTOSAR Rule A1-1-1]) - -deprecate(function,std::mem_fun,[AUTOSAR Rule A1-1-1]) - -deprecate(function,std::mem_fun_ref,[AUTOSAR Rule A1-1-1]) - -append(586(std::ptr_fun),[AUTOSAR Rule A1-1-1]) - -append(586(std::mem_fun),[AUTOSAR Rule A1-1-1]) - -append(586(std::mem_fun_ref),[AUTOSAR Rule A1-1-1]) - - /* 586 - functions bind1st and bind2nd are deprecated */ - +e586 - +elib(586) - -deprecate(function,std::bind1st,[AUTOSAR Rule A1-1-1]) - -append(586(std::bind1st),[AUTOSAR Rule A1-1-1]) - -deprecate(function,std::bind2nd,[AUTOSAR Rule A1-1-1]) - -append(586(std::bind2nd),[AUTOSAR Rule A1-1-1]) - -/* Rule M1-0-2 (required, toolchain, non-automated) */ - - /* not statically checkable */ - -/* Rule A1-1-2 (required, implementation/toolchain, non-automated) */ - - /* not statically checkable */ - -/* Rule A1-1-3 (required, toolchain, non-automated) */ - - /* not statically checkable */ - -/* Rule A1-2-1 (required, toolchain, non-automated) */ - - /* not statically checkable */ - -/* Rule A1-4-1 (required, implementation/verification, non-automated) */ - - /* not statically checkable */ - -/* Rule A1-4-3 (advisory, implementation, automated) */ - - /* not statically checkable */ - -/* Rule A2-3-1 (required, architecture/design/implementation, automated) */ - - /* not currently supported */ - -/* Rule A2-5-1 (required, implementation, automated) */ - - -ftg /* disable trigraph expansion */ - - /* 584 - trigraph sequence detected */ - +e584 - +elib(584) - -append(584,[AUTOSAR Rule A2-5-1]) - - /* 739 - trigraph sequence in string literal */ - +e739 - +elib(739) - -append(739,[AUTOSAR Rule A2-5-1]) - -/* Rule A2-5-2 (required, implementation, automated) */ - - /* 9102 - possible digraph sequence */ - +e9102 - +elib(9102) - -append(9102,[AUTOSAR Rule A2-5-2]) - -/* Rule M2-7-1 (required, implementation, automated) */ - - -fnc /* disable nested comments */ - - /* 602 - slash star within block comment */ - +e602 - +elib(602) - -append(602,[AUTOSAR Rule M2-7-1]) - -/* Rule A2-7-1 (required, implementation, automated) */ - - /* 427 - / / comment continued via back-slash */ - +e427 - +elib(427) - -append(427,[AUTOSAR Rule A2-7-1]) - -/* Rule A2-7-2 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule A2-7-3 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A2-7-5 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule A2-8-1 (required, architecture/design/implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule A2-8-2 (advisory, architecture/design/implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule M2-10-1 (required, architecture/design/implementation, automated) */ - - /* not currently supported */ - -/* Rule A2-10-1 (required, architecture/design/implementation, automated) */ - - /* not currently supported */ - -/* Rule A2-10-6 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A2-10-4 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A2-10-5 (advisory, design/implementation, automated) */ - - /* not currently supported */ - -/* Rule A2-11-1 (required, design/implementation, automated) */ - - /* 586 - keyword is deprecated */ - +e586 - +elib(586) - - -deprecate(keyword, volatile) - -append(586(volatile),[AUTOSAR Rule A2-11-1]) - -/* Rule A2-13-1 (required, architecture/design/implementation, automated) */ - - /* 606 - non-ANSI escape sequence */ - +e606 - +elib(606) - -append(606,[AUTOSAR Rule A2-13-1]) - -/* Rule A2-13-6 (required, architecture/design/implementation, automated) */ - - /* 9443 - universal-character-name used in identifier */ - +e9443 - +elib(9443) - -append(9443,[AUTOSAR Rule A2-13-6]) - -/* Rule A2-13-5 (advisory, implementation, automated) */ - - /* 9439 - hexadecimal __integral|floating__ literal '__string__' should be upper case */ - +e9439 - +elib(9439) - -append(9439,[AUTOSAR Rule A2-13-5]) - -/* Rule M2-13-2 (required, architecture/design/implementation, automated) */ - - /* 9001 - octal constant used */ - +e9001 - +elib(9001) - -append(9001,[AUTOSAR Rule M2-13-2]) - - /* 9104 - octal escape sequence used */ - +e9104 - +elib(9104) - -append(9104,[AUTOSAR Rule M2-13-2]) - -/* Rule M2-13-3 (required, architecture/design/implementation, automated) */ - - /* 9105 - unsigned octal and hexadecimal literals require a 'U' suffix */ - +e9105 - +elib(9105) - -append(9105,[AUTOSAR Rule M2-13-3]) - -/* Rule M2-13-4 (required, architecture/design/implementation, automated) */ - - /* 9106 - lower case literal suffix */ - +e9106 - +elib(9106) - -append(9106,[AUTOSAR Rule M2-13-4]) - -/* Rule A2-13-2 (required, implementation, automated) */ - - /* 1107 - invalid concatenation of wide string literals of different kinds */ - +e1107 - +elib(1107) - -append(1107,[AUTOSAR Rule A2-13-2]) - -/* Rule A2-13-3 (required, architecture/design/implementation, automated) */ - - /* 586 - type is deprecated */ - +e586 - +elib(586) - -deprecate(type, wchar_t) - -append(586(wchar_t),[AUTOSAR Rule A2-13-3]) - -/* Rule A2-13-4 (required, architecture/design/implementation, automated) */ - - /* 1776 - converting string literal to type is not const safe */ - +e1776 - +elib(1776) - -append(1776,[AUTOSAR Rule A2-13-4]) - -/* Rule A3-1-1 (required, architecture/design/implementation, automated) */ - - /* 9107 - header cannot be included in more than one translation unit because - of the definition of symbol */ - +e9107 - +elib(9107) - -append(9107,[AUTOSAR Rule A3-1-1]) - -/* Rule A3-1-2 (required, architecture/design/implementation, automated) */ - - /* not currently supported */ - -/* Rule A3-1-3 (advisory, architecture/design/implementation, automated) */ - - /* not currently supported */ - -/* Rule M3-1-2 (required, implementation, automated) */ - - /* 9108 - function declared at block scope */ - +e9108 - +elib(9108) - -append(9108,[AUTOSAR Rule M3-1-2]) - - /* 1798 - block scope declaration of function is taken to mean a member of an enclosing namespace but does not introduce a name */ - +e1798 - +elib(1798) - -append(1798,[AUTOSAR Rule M3-1-2]) - -/* Rule A3-1-4 (required, design/implementation, automated) */ - - /* 9067 - extern array declared without size or initializer */ - +e9067 - +elib(9067) - -append(9067,[AUTOSAR Rule A3-1-4]) - -/* Rule A3-1-5 (required, design, partially-automated) */ - - /* 9449 - inlined member function is not marked as inline */ - +e9449 - +elib(9449) - -append(9449,[AUTOSAR Rule A3-1-5]) - -/* Rule A3-1-6 (advisory, design, automated) */ - - /* not currently supported */ - -/* Rule M3-2-1 (required, implementation, automated) */ - - /* 18 - redefinition of symbol as different kind of symbol */ - +e18 - +elib(18) - -append(18,[AUTOSAR Rule M3-2-1]) - - /* 31 - redefinition of symbol */ - +e31 - +elib(31) - -append(31,[AUTOSAR Rule M3-2-1]) - -/* Rule M3-2-2 (required, implementation, automated) */ - - /* 15 - symbol redeclared with different type */ - +e15 - +elib(15) - -append(15,[AUTOSAR Rule M3-2-2]) - - /* 31 - redefinition of symbol */ - +e31 - +elib(31) - -append(31,[AUTOSAR Rule M3-2-2]) - -/* Rule M3-2-3 (required, implementation, automated) */ - - /* 9004 - object/function previously declared */ - +e9004 - +elib(9004) - -append(9004,[AUTOSAR Rule M3-2-3]) - -/* Rule M3-2-4 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A3-3-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A3-3-2 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M3-3-2 (required, implementation, automated) */ - - /* 401 - not previously declared static */ - +e401 - +elib(401) - -append(401,[AUTOSAR Rule M3-3-2]) - - /* 839 - storage class of symbol assumed static */ - +e839 - +elib(839) - -append(839,[AUTOSAR Rule M3-3-2]) - -/* Rule M3-4-1 (required, implementation, automated) */ - - /* 9003 - could define global variable 'Symbol' within function */ - +e9003 - +elib(9003) - -append(9003,[AUTOSAR Rule M3-4-1]) - -/* Rule A3-8-1 (required, implementation, not automated) */ - - /* not statically checkable */ - -/* Rule M3-9-1 (required, implementation, automated) */ - - /* 9073 - parameter 'Integer' of function 'Symbol' has type alias name - difference with previous declaration ('Type' vs 'Type') */ - +e9073 - +elib(9073) - -append(9073,[AUTOSAR Rule M3-9-1]) - - /* 9094 - return type of function 'Symbol' has type alias name difference - with previous declaration ('Type' vs 'Type') */ - +e9094 - +elib(9094) - -append(9094,[AUTOSAR Rule M3-9-1]) - - /* 9168 - variable has type alias name difference with previous - declaration */ - +e9168 - +elib(9168) - -append(9168,[AUTOSAR Rule M3-9-1]) - -/* Rule A3-9-1 (required, implementation, automated) */ - - /* 586 - type is deprecated */ - +e586 - +elib(586) - - -deprecate(type, signed char) - -append(586(signed char),[AUTOSAR Rule A3-9-1]) - - -deprecate(type, unsigned char) - -append(586(unsigned char),[AUTOSAR Rule A3-9-1]) - - -deprecate(type, int) - -append(586(int),[AUTOSAR Rule A3-9-1]) - - -deprecate(type, unsigned int) - -append(586(unsigned int),[AUTOSAR Rule A3-9-1]) - - -deprecate(type, short) - -append(586(short),[AUTOSAR Rule A3-9-1]) - - -deprecate(type, unsigned short) - -append(586(unsigned short),[AUTOSAR Rule A3-9-1]) - - -deprecate(type, long) - -append(586(long),[AUTOSAR Rule A3-9-1]) - - -deprecate(type, unsigned long) - -append(586(unsigned long),[AUTOSAR Rule A3-9-1]) - - -deprecate(type, long long) - -append(586(long long),[AUTOSAR Rule A3-9-1]) - - -deprecate(type, unsigned long long) - -append(586(unsigned long long),[AUTOSAR Rule A3-9-1]) - -/* Rule M3-9-3 (required, implementation, automated) */ - - /* 9110 - bit representation of a floating point type used */ - +e9110 - +elib(9110) - -append(9110,[AUTOSAR Rule M3-9-3]) - - /* 2499 - memcmp of floating data */ - +e2499 - +elib(2499) - -append(2499,[AUTOSAR Rule M3-9-3]) - - /* 2498 - memcmp of floating data within structure/union */ - +e2498 - +elib(2498) - -append(2498,[AUTOSAR Rule M3-9-3]) - -/* Rule M4-5-1 (required, implementation, automated) */ - - /* 9111 - boolean expression used with non-permitted operator */ - +e9111 - +elib(9111) - -append(9111,[AUTOSAR Rule M4-5-1]) - -/* Rule A4-5-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M4-5-3 (required, implementation, automated) */ - - /* 9112 - plain character expression used with non-permitted operator */ - +e9112 - +elib(9112) - -append(9112,[AUTOSAR Rule M4-5-3]) - -/* Rule A4-7-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M4-10-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A4-10-1 (required, architecture/design/implementation, automated) */ - - /* 910 - implicit conversion of null pointer constant to pointer */ - +e910 - +elib(910) - -append(910,[AUTOSAR Rule A4-10-1]) - -/* Rule M4-10-2 (required, implementation, automated) */ - - /* 910 - implicit conversion of null pointer constant to pointer */ - +e910 - +elib(910) - -append(910,[AUTOSAR Rule M4-10-2]) - -/* Rule A5-0-1 (required, implementation, automated) */ - - /* 564 - variable depends on order of evaluation */ - +e564 - +elib(564) - -append(564,[AUTOSAR Rule A5-0-1]) - -/* Rule M5-0-2 (advisory, implementation, partially automated) */ - - /* 9113 - dependence placed on C++ operator precedence */ - +e9113 - +elib(9113) - -append(9113,[AUTOSAR Rule M5-0-2]) - -/* Rule M5-0-3 (required, implementation, automated) */ - - /* 9114 - implicit conversion of integer cvalue expression */ - +e9114 - +elib(9114) - -append(9114,[AUTOSAR Rule M5-0-3]) - - /* 9116 - implicit conversion of floating point cvalue expression */ - +e9116 - +elib(9116) - -append(9116,[AUTOSAR Rule M5-0-3]) - -/* Rule M5-0-4 (required, implementation, automated) */ - - /* 9117 - implicit conversion changes signedness */ - +e9117 - +elib(9117) - -append(9117,[AUTOSAR Rule M5-0-4]) - -/* Rule M5-0-5 (required, implementation, automated) */ - - /* 9115 - implicit conversion from integer to floating point type */ - +e9115 - +elib(9115) - -append(9115,[AUTOSAR Rule M5-0-5]) - - /* 9118 - implicit conversion from floating point to integer type */ - +e9118 - +elib(9118) - -append(9118,[AUTOSAR Rule M5-0-5]) - -/* Rule M5-0-6 (required, implementation, automated) */ - - /* 9119 - implicit conversion of integer to smaller type */ - +e9119 - +elib(9119) - -append(9119,[AUTOSAR Rule M5-0-6]) - - /* 9120 - implicit conversion of floating point to smaller type */ - +e9120 - +elib(9120) - -append(9120,[AUTOSAR Rule M5-0-6]) - -/* Rule M5-0-7 (required, implementation, automated) */ - - /* 9121 - cast of cvalue expression from integer to floating point type */ - +e9121 - +elib(9121) - -append(9121,[AUTOSAR Rule M5-0-7]) - - /* 9122 - cast of cvalue expression from floating point to integer type */ - +e9122 - +elib(9122) - -append(9122,[AUTOSAR Rule M5-0-7]) - -/* Rule M5-0-8 (required, implementation, automated) */ - - /* 9123 - cast of integer cvalue expression to larger type */ - +e9123 - +elib(9123) - -append(9123,[AUTOSAR Rule M5-0-8]) - - /* 9124 - cast of floating point cvalue expression to larger type */ - +e9124 - +elib(9124) - -append(9124,[AUTOSAR Rule M5-0-8]) - -/* Rule M5-0-9 (required, implementation, automated) */ - - /* 9125 - cast of integer cvalue expression changes signedness */ - +e9125 - +elib(9125) - -append(9125,[AUTOSAR Rule M5-0-9]) - -/* Rule M5-0-10 (required, implementation, automated) */ - - /* 9126 - result of operator applied to underlying type must be cast */ - +e9126 - +elib(9126) - -append(9126,[AUTOSAR Rule M5-0-10]) - -/* Rule M5-0-11 (required, implementation, automated) */ - - /* 9128 - plain char type mixed with type other than plain char */ - +e9128 - +elib(9128) - -append(9128,[AUTOSAR Rule M5-0-11]) - -/* Rule M5-0-12 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A5-0-2 (required, implementation, automated) */ - - /* 9177 - condition of if/for/while/do statement has non-Boolean type */ - +e9177 - +elib(9177) - -append(9177,[AUTOSAR Rule A5-0-2]) - -/* Rule M5-0-14 (required, implementation, automated) */ - - /* 9178 - predicate of conditional operator has non-Boolean type */ - +e9178 - +elib(9178) - -append(9178,[AUTOSAR Rule M5-0-14]) - -/* Rule M5-0-15 (required, implementation, automated) */ - - /* 947 - pointer subtraction */ - +e947 - +elib(947) - -append(947,[AUTOSAR Rule M5-0-15]) - - /* 9016 - performing pointer arithmetic via addition/subtraction */ - +e9016 - +elib(9016) - -append(9016,[AUTOSAR Rule M5-0-15]) - -/* Rule M5-0-16 (required, implementation, automated) */ - - /* 415 - likely out of bounds pointer access */ - +e415 - +elib(415) - -append(415,[AUTOSAR Rule M5-0-16]) - - /* 416 - likely creating out-of-bounds pointer */ - +e416 - +elib(416) - -append(416,[AUTOSAR Rule M5-0-16]) - - /* 661 - potential out of bounds pointer access */ - +e661 - +elib(661) - -append(661,[AUTOSAR Rule M5-0-16]) - - /* 662 - possibly creating out-of-bounds pointer */ - +e662 - +elib(662) - -append(662,[AUTOSAR Rule M5-0-16]) - -/* Rule M5-0-17 (required, implementation, automated) */ - - /* 947 - pointer subtraction */ - +e947 - +elib(947) - -append(947,[AUTOSAR Rule M5-0-17]) - -/* Rule A5-0-4 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M5-0-18 (required, implementation, automated) */ - - /* 946 - relational operator applied to pointers */ - +e946 - +elib(946) - -append(946,[AUTOSAR Rule M5-0-18]) - -/* Rule A5-0-3 (required, implementation, automated) */ - - /* 9025 - more than two levels of pointer indirection */ - +e9025 - +elib(9025) - -append(9025,[AUTOSAR Rule A5-0-3]) - -/* Rule M5-0-20 (required, implementation, automated) */ - - /* 9172 - bitwise operator 'Operator' used with non-const operands of - differing underlying types */ - +e9172 - +elib(9172) - -append(9172,[AUTOSAR Rule M5-0-20]) - -/* Rule M5-0-21 (required, implementation, automated) */ - - /* 9130 - bitwise operator applied to signed underlying type */ - +e9130 - +elib(9130) - -append(9130,[AUTOSAR Rule M5-0-21]) - -/* Rule A5-1-1 (required, implementation, partially automated) */ - - /* not currently supported */ - -/* Rule A5-1-2 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A5-1-3 (required, implementation, automated) */ - - /* 9424 - parameter list omitted from lambda expression */ - +e9424 - +elib(9424) - -append(9424,[AUTOSAR Rule A5-1-3]) - -/* Rule A5-1-4 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A5-1-6 (advisory, implementation, automated) */ - - /* 3903 - lambda return type not explicitly specified */ - +e3903 - +elib(3903) - -append(3903,[AUTOSAR Rule A5-1-6]) - -/* Rule A5-1-7 (required, implementation, automated) */ - - /* 9426 - lambda used as operand to decltype or typeid */ - +e9426 - +elib(9426) - -append(9426,[AUTOSAR Rule A5-1-7]) - -/* Rule A5-1-8 (advisory, implementation, automated) */ - - /* 9442 - nested lambda expression */ - +e9442 - +elib(9442) - -append(9442,[AUTOSAR Rule A5-1-8]) - -/* Rule A5-1-9 (advisory, implementation, automated) */ - - /* not currently supported */ - -/* Rule M5-2-2 (required, implementation, automated) */ - - /* 1774 - only dynamic_cast can indicate a failure by returning null */ - +e1774 - +elib(1774) - -append(1774,[AUTOSAR Rule M5-2-2]) - - /* 1939 - casting from base class to derived class */ - +e1939 - +elib(1939) - -append(1939,[AUTOSAR Rule M5-2-2]) - -/* Rule M5-2-3 (advisory, implementation, automated) */ - - /* 9171 - downcast of polymorphic type 'Type' to type 'Type' */ - +e9171 - +elib(9171) - -append(9171,[AUTOSAR Rule M5-2-3]) - -/* Rule A5-2-1 (advisory, implementation, automated) */ - - /* 586 - keyword is deprecated */ - +e586 - +elib(586) - - -deprecate(keyword, dynamic_cast) - -append(586(dynamic_cast),[AUTOSAR Rule A5-2-1]) - -/* Rule A5-2-2 (required, implementation, automated) */ - - /* 1924 - use of c-style cast (except to void) */ - +e1924 - +elib(1924) - -append(1924,[AUTOSAR Rule A5-2-2]) - - /* 1954 - use of c-style cast (to void) */ - +e1954 - +elib(1954) - -append(1954,[AUTOSAR Rule A5-2-2]) - -/* Rule A5-2-3 (required, implementation, automated) */ - - /* 9005 - cast drops qualifier */ - +e9005 - +elib(9005) - -append(9005,[AUTOSAR Rule A5-2-3]) - -/* Rule M5-2-6 (required, implementation, automated) */ - - /* 611 - cast between pointer to function type and pointer to object type */ - +e611 - +elib(611) - -append(611,[AUTOSAR Rule M5-2-6]) - -/* Rule A5-2-4 (required, implementation, automated) */ - - /* 586 - keyword is deprecated */ - +e586 - +elib(586) - - -deprecate(keyword, reinterpret_cast) - -append(586(reinterpret_cast),[AUTOSAR Rule A5-2-4]) - -/* Rule A5-2-6 (required, implementation, automated) */ - - /* 9131 - left/right side of logical operator is not a postfix expression */ - +e9131 - +elib(9131) - -append(9131,[AUTOSAR Rule A5-2-6]) - -/* Rule M5-2-8 (required, implementation, automated) */ - - /* 9010 - conversion from integer to pointer */ - +e9010 - +elib(9010) - -append(9010,[AUTOSAR Rule M5-2-8]) - - /* 9079 - conversion from pointer to void to pointer */ - +e9079 - +elib(9079) - -append(9079,[AUTOSAR Rule M5-2-8]) - -/* Rule M5-2-9 (required, implementation, automated) */ - - /* 9091 - cast from pointer to integer type */ - +e9091 - +elib(9091) - -append(9091,[AUTOSAR Rule M5-2-9]) - -/* Rule M5-2-10 (required, implementation, automated) */ - - /* 9049 - increment/decrement operation combined with other operation with - side-effects */ - +e9049 - +elib(9049) - -append(9049,[AUTOSAR Rule M5-2-10]) - -/* Rule M5-2-11 (required, implementation, automated) */ - - /* 1753 - overloading operator 'Operator' precludes short-circuit evaluation */ - +e1753 - +elib(1753) - -append(1753,[AUTOSAR Rule M5-2-11]) - -/* Rule A5-2-5 (required, implementation, automated) */ - - /* 415 - likely out of bounds pointer access */ - +e415 - +elib(415) - -append(415,[AUTOSAR Rule A5-2-5]) - - /* 416 - likely creating out-of-bounds pointer */ - +e416 - +elib(416) - -append(416,[AUTOSAR Rule A5-2-5]) - - /* 661 - potential out of bounds pointer access */ - +e661 - +elib(661) - -append(661,[AUTOSAR Rule A5-2-5]) - - /* 662 - possibly creating out-of-bounds pointer */ - +e662 - +elib(662) - -append(662,[AUTOSAR Rule A5-2-5]) - -/* Rule M5-2-12 (required, implementation, automated) */ - - /* 9132 - array type passed to function expecting a pointer */ - +e9132 - +elib(9132) - -append(9132,[AUTOSAR Rule M5-2-12]) - -/* Rule M5-3-1 (required, implementation, automated) */ - - /* 9133 - boolean expression required for operator 'Operator' */ - +e9133 - +elib(9133) - -append(9133,[AUTOSAR Rule M5-3-1]) - -/* Rule M5-3-2 (required, implementation, automated) */ - - /* 9134 - unary minus applied to operand with unsigned underlying type */ - +e9134 - +elib(9134) - -append(9134,[AUTOSAR Rule M5-3-2]) - -/* Rule M5-3-3 (required, implementation, automated) */ - - /* 9135 - unary operator & overloaded */ - +e9135 - +elib(9135) - -append(9135,[AUTOSAR Rule M5-3-3]) - -/* Rule M5-3-4 (required, implementation, automated) */ - - /* 9006 - 'sizeof' used on expression with side effect */ - +e9006 - +elib(9006) - -append(9006,[AUTOSAR Rule M5-3-4]) - -/* Rule A5-3-1 (required, implementation, non-automated) */ - - /* 9414 - typeid' used on expression with side effect */ - +e9414 - +elib(9414) - -append(9414,[AUTOSAR Rule A5-3-1]) - -/* Rule A5-3-2 (required, implementation, partially automated) */ - - +fnr /* Assume functions can return null pointers by default */ - +fpn /* Assume pointer arguments may be null */ - - /* 413 - likely use of null pointer */ - +e413 - +elib(413) - -append(413,[AUTOSAR Rule A5-3-2]) - - /* 613 - potential use of null pointer */ - +e613 - +elib(613) - -append(613,[AUTOSAR Rule A5-3-2]) - -/* Rule A5-3-3 (required, implementation, automated) */ - - /* 1404 - deleting an object of type before that type is defined */ - +e1404 - +elib(1404) - -append(1404,[AUTOSAR Rule A5-3-3]) - -/* Rule A5-5-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A5-6-1 (required, implementation, automated) */ - - /* 414 - possible division by zero */ - +e414 - +elib(414) - -append(414,[AUTOSAR Rule A5-6-1]) - -/* Rule M5-8-1 (required, implementation, partially automated) */ - - /* 9136 - the shift value is at least the precision of the AUTOSAR - underlying type of the left hand side */ - +e9136 - +elib(9136) - -append(9136,[AUTOSAR Rule M5-8-1]) - -/* Rule A5-10-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M5-14-1 (required, implementation, automated) */ - - /* side effects on right hand of logical operator */ - +e9007 - +elib(9007) - -append(9007,[AUTOSAR Rule M5-14-1]) - -/* Rule A5-16-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M5-17-1 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule M5-18-1 (required, implementation, automated) */ - - /* 9008 - comma operator used */ - +e9008 - +elib(9008) - -append(9008,[AUTOSAR Rule M5-18-1]) - -/* Rule M5-19-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M6-2-1 (required, implementation, automated) */ - - /* 720 - boolean test of assignment */ - +e720 - +elib(720) - -append(720,[AUTOSAR Rule M6-2-1]) - - /* 820 - boolean test of parenthesized assignment */ - +e820 - +elib(820) - -append(820,[AUTOSAR Rule M6-2-1]) - - /* 9084 - result of assignment operator used */ - +e9084 - +elib(9084) - -append(9084,[AUTOSAR Rule M6-2-1]) - -/* Rule A6-2-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A6-2-2 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M6-2-2 (required, implementation, partially automated) */ - - /* 777 - testing floating point values for equality */ - +e777 - +elib(777) - -append(777,[AUTOSAR Rule M6-2-2]) - - /* 9252 - testing floating point for equality using exact value */ - +e9252 - +elib(9252) - -append(9252,[AUTOSAR Rule M6-2-2]) - -/* Rule M6-2-3 (required, implementation, automated) */ - - /* 9138 - null statement not on line by itself */ - +e9138 - +elib(9138) - -append(9138,[AUTOSAR Rule M6-2-3]) - -/* Rule M6-3-1 (required, implementation, automated) */ - - /* 9012 - body should be a compound statement */ - +e9012 - +elib(9012) - -append(9012,[AUTOSAR Rule M6-3-1]) - -/* Rule M6-4-1 (required, implementation, automated) */ - - /* 9012 - body should be a compound statement */ - +e9012 - +elib(9012) - -append(9012,[AUTOSAR Rule M6-4-1]) - -/* Rule M6-4-2 (required, implementation, automated) */ - - /* 9013 - no 'else' at end of 'if ... else if' chain */ - +e9013 - +elib(9013) - -append(9013,[AUTOSAR Rule M6-4-2]) - -/* Rule M6-4-3 (required, implementation, automated) */ - - /* 9042 - departure from MISRA switch syntax */ - +e9042 - +elib(9042) - -append(9042,[AUTOSAR Rule M6-4-3]) - -/* Rule M6-4-4 (required, implementation, automated) */ - - /* 9055 - most closely enclosing compound statement of this case/default - label is not a switch statement */ - +e9055 - +elib(9055) - -append(9055,[AUTOSAR Rule M6-4-4]) - -/* Rule M6-4-5 (required, implementation, automated) */ - - /* 9090 - switch case lacks unconditional break or throw */ - +e9090 - +elib(9090) - -append(9090,[AUTOSAR Rule M6-4-5]) - -/* Rule M6-4-6 (required, implementation, automated) */ - - /* 744 - switch statement has no default */ - +e744 - +elib(744) - -append(744,[AUTOSAR Rule M6-4-6]) - - /* 787 - enum constant not used within switch */ - +e787 - +elib(787) - -append(787,[AUTOSAR Rule M6-4-6]) - - /* 9139 - case label follows default in switch statement */ - +e9139 - +elib(9139) - -append(9139,[AUTOSAR Rule M6-4-6]) - -/* Rule M6-4-7 (required, implementation, automated) */ - - /* 483 - switching on a boolean value */ - +e483 - +elib(483) - -append(483,[AUTOSAR Rule M6-4-7]) - -/* Rule A6-4-1 (required, implementation, automated) */ - - /* 9181 - switch contains fewer than two non-default switch cases */ - +e9181 - +elib(9181) - -append(9181,[AUTOSAR Rule A6-4-1]) - -/* Rule A6-5-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A6-5-2 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M6-5-2 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M6-5-3 (required, implementation, automated) */ - - /* 850 - for statement index variable modified in body */ - +e850 - +elib(850) - -append(850,[AUTOSAR Rule M6-5-3]) - -/* Rule M6-5-4 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M6-5-5 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M6-5-6 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A6-5-3 (advisory, implementation, automated) */ - - /* 9456 - do statement used outside statement-like macro */ - +e9456 - +elib(9456) - -append(9456,[AUTOSAR Rule A6-5-3]) - -/* Rule A6-5-4 (advisory, implementation, automated) */ - - /* not currently supported */ - -/* Rule A6-6-1 (required, implementation, automated) */ - - /* 801 - goto statement used */ - +e801 - +elib(801) - -append(801,[AUTOSAR Rule A6-6-1]) - -/* Rule M6-6-1 (required, implementation, automated) */ - - /* 9041 - goto appears in block 'String' which is not nested in - block 'String' which contains label 'Symbol' */ - +e9041 - +elib(9041) - -append(9041,[AUTOSAR Rule M6-6-1]) - -/* Rule M6-6-2 (required, implementation, automated) */ - - /* 107 - label not defined */ - +e107 - +elib(107) - -append(107,[AUTOSAR Rule M6-6-2]) - - /* 9064 - goto references earlier label */ - +e9064 - +elib(9064) - -append(9064,[AUTOSAR Rule M6-6-2]) - -/* Rule M6-6-3 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A7-1-1 (required, implementation, automated) */ - - /* 843 - static storage duration variable could be const */ - +e843 - +elib(843) - -append(843,[AUTOSAR Rule A7-1-1]) - - /* 952 - parameter of function could be const */ - +e952 - +elib(952) - -append(952,[AUTOSAR Rule A7-1-1]) - - /* 953 - local variable could be const */ - +e953 - +elib(953) - -append(953,[AUTOSAR Rule A7-1-1]) - -/* Rule A7-1-2 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M7-1-2 (required, implementation, automated) */ - - /* 818 - parameter of function could be pointer to const */ - +e818 - +elib(818) - -append(818,[AUTOSAR Rule M7-1-2]) - - /* 1764 - reference parameter could be reference to const */ - +e1764 - +elib(1764) - -append(1764,[AUTOSAR Rule M7-1-2]) - - -fcv /* report parameters even if exclusively cast to void */ - -/* Rule A7-1-3 (required, implementation, automated) */ - - /* 9183 - qualifier precedes typedef type */ - +e9183 - +elib(9183) - -append(9183,[AUTOSAR Rule A7-1-3]) - -/* Rule A7-1-4 (required, implementation, automated) */ - - /* 586 - keyword is deprecated */ - +e586 - +elib(586) - - -deprecate(keyword, register) - -append(586(register),[AUTOSAR Rule A7-1-4]) - -/* Rule A7-1-5 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A7-1-6 (required, implementation, automated) */ - - /* 9416 - typedef used to define name */ - +e9416 - +elib(9416) - -append(9416,[AUTOSAR Rule A7-1-6]) - -/* Rule A7-1-7 (required, implementation, automated) */ - - /* 9146 - multiple declarators in a declaration */ - +e9146 - +elib(9146) - -append(9146,[AUTOSAR Rule A7-1-7]) - -/* Rule A7-1-8 (required, implementation, automated) */ - - /* 618 - storage class specified after a type */ - +e618 - +elib(618) - -append(618,[AUTOSAR Rule A7-1-8]) - - /* 2618 - non-type specifier appears after a type */ - +e2618 - +elib(2618) - -append(2618,[AUTOSAR Rule A7-1-8]) - -/* Rule A7-1-9 (required, implementation, automated) */ - - /* 9428 - class, structure, union, or enumeration object declared with the definition of type */ - +e9428 - +elib(9428) - -append(9428,[AUTOSAR Rule A7-1-9]) - -/* Rule A7-2-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A7-2-2 (required, implementation, automated) */ - - /* 9418 - enum does not have an explicitly specified underlying type */ - +e9418 - +elib(9418) - -append(9418,[AUTOSAR Rule A7-2-2]) - -/* Rule A7-2-3 (required, implementation, automated) */ - - /* 9419 - enum is not a scoped enumeration */ - +e9419 - +elib(9419) - -append(9419,[AUTOSAR Rule A7-2-3]) - -/* Rule A7-2-4 (required, implementation, automated) */ - - /* 9148 - '=' should initialize either all enum members or only the first */ - +e9148 - +elib(9148) - -append(9148,[AUTOSAR Rule A7-2-4]) - -/* Rule A7-2-5 (advisory, design, non-automated) */ - - /* not statically checkable */ - -/* Rule M7-3-1 (required, implementation, automated) */ - - /* 9141 - global declaration of symbol */ - +e9141 - +elib(9141) - -append(9141,[AUTOSAR Rule M7-3-1]) - - /* 9162 - use of static_assert/using declaration at global scope */ - +e9162 - +elib(9162) - -append(9162,[AUTOSAR Rule M7-3-1]) - -/* Rule M7-3-2 (required, implementation, automated) */ - - /* 9142 - function main declared outside the global namespace */ - +e9142 - +elib(9142) - -append(9142,[AUTOSAR Rule M7-3-2]) - -/* Rule M7-3-3 (required, implementation, automated) */ - - /* 1751 - anonymous namespace declared in a header file */ - +e1751 - +elib(1751) - -append(1751,[AUTOSAR Rule M7-3-3]) - -/* Rule M7-3-4 (required, implementation, automated) */ - - /* 9144 - using directive used */ - +e9144 - +elib(9144) - -append(9144,[AUTOSAR Rule M7-3-4]) - -/* Rule A7-3-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M7-3-6 (required, implementation, automated) */ - - /* 9145 - using declaration/directive in header */ - +e9145 - +elib(9145) - -append(9145,[AUTOSAR Rule M7-3-6]) - -/* Rule A7-4-1 (required, implementation, automated) */ - - /* 586 - keyword is deprecated */ - +e586 - +elib(586) - - -deprecate(keyword, asm) - -append(586(asm),[AUTOSAR Rule A7-4-1]) - -/* Rule M7-4-1 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule M7-4-2 (required, implementation, automated) */ - - -rw(_asm) - -rw(__asm) - -pragma(asm) - -pragma(endasm) - -ppw(asm) - -ppw(endasm) - -/* Rule M7-4-3 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M7-5-1 (required, implementation, non-automated) */ - - /* 604 - returning address of auto variable */ - +e604 - +elib(604) - -append(604,[AUTOSAR Rule M7-5-1]) - -/* Rule M7-5-2 (required, implementation, non-automated) */ - - /* 789 - assigning address of auto variable to static */ - +e789 - +elib(789) - -append(789,[AUTOSAR Rule M7-5-2]) - -/* Rule A7-5-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A7-5-2 (required, implementation, automated) */ - - /* 9070 - function is recursive */ - +e9070 - +elib(9070) - -append(9070,[AUTOSAR Rule A7-5-2]) - -/* Rule A7-6-1 (required, implementation, automated) */ - - /* 2436 - function declared 'noreturn' should not return */ - +e2436 - +elib(2436) - -append(2436,[AUTOSAR Rule A7-6-1]) - -/* Rule M8-0-1 (required, implementation, automated) */ - - /* 9146 - multiple declarators in a declaration */ - +e9146 - +elib(9146) - -append(9146,[AUTOSAR Rule M8-0-1]) - -/* Rule A8-2-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M8-3-1 (required, implementation, automated) */ - - /* 1735 - parameter of virtual function has default argument */ - +e1735 - +elib(1735) - -append(1735,[AUTOSAR Rule M8-3-1]) - -/* Rule A8-4-1 (required, implementation, automated) */ - - /* 9165 - function defined with a variable number of arguments */ - +e9165 - +elib(9165) - -append(9165,[AUTOSAR Rule A8-4-1]) - -/* Rule M8-4-2 (required, implementation, automated) */ - - /* 9072 - parameter of function has different name than previous - declaration */ - +e9072 - +elib(9072) - -append(9072,[AUTOSAR Rule M8-4-2]) - - /* 9272 - parameter of function has different name than overridden - function */ - +e9272 - +elib(9272) - -append(9272,[AUTOSAR Rule M8-4-2]) - -/* Rule A8-4-2 (required, implementation, automated) */ - - /* 533 - function should return a value */ - +e533 - +elib(533) - -append(533,[AUTOSAR Rule A8-4-2]) - -/* Rule M8-4-4 (required, implementation, automated) */ - - /* 9147 - implicit function-to-pointer decay */ - +e9147 - +elib(9147) - -append(9147,[AUTOSAR Rule M8-4-4]) - -/* Rule A8-4-3 (advisory, design, non-automated) */ - - /* not statically checkable */ - -/* Rule A8-4-4 (advisory, design, automated) */ - - /* not currently supported */ - -/* Rule A8-4-5 (required, design, automated) */ - - /* not currently supported */ - -/* Rule A8-4-6 (required, design, automated) */ - - /* not currently supported */ - -/* Rule A8-4-7 (required, design, automated) */ - - /* not currently supported */ - -/* Rule A8-4-8 (required, design, automated) */ - - /* not currently supported */ - -/* Rule A8-4-9 (required, design, automated) */ - - /* not currently supported */ - -/* Rule A8-4-10 (required, design, automated) */ - - /* not currently supported */ - -/* Rule A8-4-11 (required, design, automated) */ - - /* not currently supported */ - -/* Rule A8-4-12 (required, design, automated) */ - - /* not currently supported */ - -/* Rule A8-4-13 (required, design, automated) */ - - /* not currently supported */ - -/* Rule A8-4-14 (required, design, non-automated) */ - - /* not statically checkable */ - -/* Rule A8-5-0 (required, implementation, automated) */ - - /* 530 - likely using an uninitialized value */ - +e530 - +elib(530) - -append(530,[AUTOSAR Rule A8-5-0]) - -/* Rule A8-5-1 (required, implementation, automated) */ - - /* 1729 - initializer inversion */ - +e1729 - +elib(1729) - -append(1729,[AUTOSAR Rule A8-5-1]) - -/* Rule M8-5-2 (required, implementation, automated) */ - - /* 940 - omitted braces within initializer */ - +e940 - +elib(940) - -append(940,[AUTOSAR Rule M8-5-2]) - -/* Rule A8-5-2 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A8-5-3 (required, implementation, automated) */ - - /* 9415 - 'auto' variable initialized using list initialization */ - +e9415 - +elib(9415) - -append(9415,[AUTOSAR Rule A8-5-3]) - -/* Rule A8-5-4 (advisory, implementation, automated) */ - - /* not currently supported */ - -/* Rule M9-3-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A9-3-1 (required, implementation, partially automated) */ - - /* not currently supported */ - -/* Rule M9-3-3 (required, implementation, automated) */ - - /* 1762 - member function could be made const */ - +e1762 - +elib(1762) - -append(1762,[AUTOSAR Rule M9-3-3]) - -/* Rule A9-5-1 (required, implementation, automated) */ - - /* 9018 - union declared */ - +e9018 - +elib(9018) - -append(9018,[AUTOSAR Rule A9-5-1]) - -/* Rule M9-6-1 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule A9-6-1 (required, design, partially automated) */ - - /* not currently supported */ - -/* Rule A9-6-2 (required, design, non-automated) */ - - /* not statically checkable */ - -/* Rule M9-6-4 (required, implementation, automated) */ - - /* 9088 - named signed single-bit bitfield */ - +e9088 - +elib(9088) - -append(9088,[AUTOSAR Rule M9-6-4]) - -/* Rule A10-0-1 (required, design, non-automated) */ - - /* not statically checkable */ - -/* Rule A10-0-2 (required, design, non-automated) */ - - /* not statically checkable */ - -/* Rule A10-1-1 (required, implementation, automated) */ - - /* 9432 - class has multiple non-interface bases */ - +e9432 - +elib(9432) - -append(9432,[AUTOSAR Rule A10-1-1]) - -/* Rule M10-1-1 (advisory, implementation, automated) */ - - /* 9174 - 'Type' is a virtual base class of 'Symbol' */ - +e9174 - +elib(9174) - -append(9174,[AUTOSAR Rule M10-1-1]) - -/* Rule M10-1-2 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M10-1-3 (required, implementation, automated) */ - - /* 1748 - non-virtual base class symbol included twice in class symbol */ - +e1748 - +elib(1748) - -append(1748,[AUTOSAR Rule M10-1-3]) - -/* Rule M10-2-1 (advisory, implementation, automated) */ - - /* not currently supported */ - -/* Rule A10-2-1 (required, implementation, automated) */ - - /* 1511 - member hides non-virtual member */ - +estring(1511,public,protected) - +elib(1511) - -append(1511(public),[AUTOSAR Rule A10-2-1]) - -append(1511(protected),[AUTOSAR Rule A10-2-1]) - -/* Rule A10-3-1 (required, implementation, automated) */ - - /* 9422 - virtual function should specify exactly one of 'virtual', 'override', or 'final' */ - +e9422 - +elib(9422) - -append(9422,[AUTOSAR Rule A10-3-1]) - -/* Rule A10-3-2 (required, implementation, automated) */ - - /* 9421 - virtual function overrides and is not marked with 'override' or 'final' */ - +e9421 - +elib(9421) - -append(9421,[AUTOSAR Rule A10-3-2]) - -/* Rule A10-3-3 (required, implementation, automated) */ - - /* 1779 - virtual function introduced in class which is marked as 'final' */ - +e1779 - +elib(1779) - -append(1779,[AUTOSAR Rule A10-3-3]) - -/* Rule A10-3-5 (required, implementation, automated) */ - - /* 9407 - copy assignment operator should not be virtual */ - +e9407 - +elib(9407) - -append(9407,[AUTOSAR Rule A10-3-5]) - - /* 9410 - move assignment operator should not be virtual */ - +e9410 - +elib(9410) - -append(9410,[AUTOSAR Rule A10-3-5]) - - /* 9438 - assignment operator should not be virtual */ - +e9438 - +elib(9438) - -append(9438,[AUTOSAR Rule A10-3-5]) - -/* Rule M10-3-3 (required, implementation, automated) */ - - /* 9170 - pure function 'Symbol' overrides non-pure function 'Symbol' */ - +e9170 - +elib(9170) - -append(9170,[AUTOSAR Rule M10-3-3]) - -/* Rule A10-4-1 (advisory, design, non-automated) */ - - /* not statically checkable */ - -/* Rule M11-0-1 (required, implementation, automated) */ - - /* 9150 - non-private data member within a non-POD structure */ - +e9150 - +elib(9150) - -append(9150,[AUTOSAR Rule M11-0-1]) - -/* Rule A11-0-1 (advisory, implementation, automated) */ - - /* 9437 - non-POD struct should be defined as a class */ - +e9437 - +elib(9437) - -append(9437,[AUTOSAR Rule A11-0-1]) - -/* Rule A11-0-2 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A11-3-1 (required, implementation, automated) */ - - /* 9435 - declared as friend in class */ - +e9435 - +elib(9435) - -append(9435,[AUTOSAR Rule A11-3-1]) - - /* Comparison operators are exempt from this Rule */ - -esym(9435,"[*::]operator==") - -esym(9435,"[*::]operator!=") - -esym(9435,"[*::]operator>=") - -esym(9435,"[*::]operator<=") - -esym(9435,"[*::]operator>") - -esym(9435,"[*::]operator<") - -/* Rule A12-0-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A12-0-2 (required, implementation, partially automated) */ - - /* 1415 - pointer to non-POD type passed to function */ - +e1415 - +elib(1415) - -append(1415,[AUTOSAR Rule A12-0-2]) - -/* Rule A12-1-1 (required, implementation, automated) */ - - /* 1401 - non-static data member not initialized by constructor */ - +e1401 - +elib(1401) - -append(1401,[AUTOSAR Rule A12-1-1]) - - /* 1928 - base class absent from initializer list for constructor */ - +e1928 - +elib(1928) - -append(1928,[AUTOSAR Rule A12-1-1]) - -/* Rule M12-1-1 (required, implementation, automated) */ - - /* 1506 - call to virtual function within a constructor/destructor */ - +e1506 - +elib(1506) - -append(1506,[AUTOSAR Rule M12-1-1]) - -/* Rule A12-1-2 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A12-1-3 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A12-1-4 (required, implementation, automated) */ - - /* 9169 - constructor can be used for implicit conversions to fundamental type */ - +e9169 - +elib(9169) - -append(9169,[AUTOSAR Rule A12-1-4]) - -/* Rule A12-1-5 (required, implementation, partially automated) */ - - /* not currently supported */ - -/* Rule A12-1-6 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A12-4-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A12-4-2 (advisory, implementation, automated) */ - - /* 9441 - non-final class symbol has a public non-virtual destructor */ - +e9441 - +elib(9441) - -append(9441,[AUTOSAR Rule A12-4-2]) - -/* Rule A12-6-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A12-7-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A12-8-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A12-8-2 (advisory, implementation, automated) */ - - /* not currently supported */ - -/* Rule A12-8-3 (required, implementation, partially automated) */ - - /* not currently supported */ - -/* Rule A12-8-4 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A12-8-5 (required, implementation, automated) */ - - /* 1529 - assignment operator should check for self-assignment */ - +e1529 - +elib(1529) - -append(1529,[AUTOSAR Rule A12-8-5]) - -/* Rule A12-8-6 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A12-8-7 (advisory, implementation, automated) */ - - /* 9185 - assignment operator declared without lvalue ref-qualifier */ - +e9185 - +elib(9185) - -append(9185,[AUTOSAR Rule A12-8-7]) - -/* Rule A13-1-2 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A13-1-3 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A13-2-1 (required, implementation, automated) */ - - /* 9447 - assignment operator should return type */ - +e9447 - +elib(9447) - -append(9447,[AUTOSAR Rule A13-2-1]) - - /* 9448 - assignment operator should return value */ - +e9448 - +elib(9448) - -append(9448,[AUTOSAR Rule A13-2-1]) - -/* Rule A13-2-2 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A13-2-3 (required, implementation, automated) */ - - /* 9186 - non-Boolean return type for comparison function */ - +e9186 - +elib(9186) - -append(9186,[AUTOSAR Rule A13-2-3]) - -/* Rule A13-3-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A13-5-1 (required, implementation, automated) */ - - /* 9187 - non-const overloaded subscript operator declared without a corresponding const version */ - +e9187 - +elib(9187) - -append(9187,[AUTOSAR Rule A13-5-1]) - -/* Rule A13-5-2 (required, implementation, automated) */ - - /* 1930 - (non-explicit) conversion operator found */ - +e1930 - +elib(1930) - -append(1930,[AUTOSAR Rule A13-5-2]) - -/* Rule A13-5-3 (advisory, implementation, automated) */ - - /* 1912 - implicit call of conversion function */ - +e1912 - +elib(1912) - -append(1912,[AUTOSAR Rule A13-5-3]) - -/* Rule A13-5-4 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A13-5-5 (required, implementation, automated) */ - - /* 9444 - user declared comparison operator is a member function */ - +e9444 - +elib(9444) - -append(9444,[AUTOSAR Rule A13-5-5]) - - /* 9445 - user declared comparison operator is not noexcept */ - +e9445 - +elib(9445) - -append(9445,[AUTOSAR Rule A13-5-5]) - - /* 9446 - user declared comparison operator does not have identical parameter types */ - +e9446 - +elib(9446) - -append(9446,[AUTOSAR Rule A13-5-5]) - -/* Rule A13-6-1 (required, implementation, automated) */ - - /* 9440 - Digit sequence separators in STRING TYPE literal 'STRING' should be every INTEGER digits */ - +e9440 - +elib(9440) - -append(9440,[AUTOSAR Rule A13-6-1]) - -/* Rule A14-1-1 (advisory, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule A14-5-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A14-5-2 (advisory, design, partially-automated) */ - - /* not currently supported */ - -/* Rule A14-5-3 (advisory, design, automated) */ - - /* not currently supported */ - -/* Rule M14-5-3 (required, implementation, automated) */ - - /* 1721 - operator=() for is not a copy nor move assignment operator */ - +e1721 - +elib(1721) - -append(1721,[AUTOSAR Rule M14-5-3]) - -/* Rule M14-6-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A14-7-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A14-7-2 (required, implementation, automated) */ - - /* 1576 - explicit specialization is not in the same file as specialized function template */ - +e1576 - +elib(1576) - -append(1576,[AUTOSAR Rule A14-7-2]) - -/* Rule A14-8-2 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A15-0-1 (required, architecture/design/implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule A15-0-2 (required, architecture/design/implementation, partially automated) */ - - /* not currently supported */ - -/* Rule A15-0-3 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule A15-0-4 (required, architecture/design/implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule A15-0-5 (required, architecture/design/implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule A15-0-6 (required, verification/toolchain, non-automated) */ - - /* not statically checkable */ - -/* Rule A15-0-7 (required, verification/toolchain, partially automated) */ - - /* not currently supported */ - -/* Rule A15-0-8 (required, verification/toolchain, non-automated) */ - - /* not statically checkable */ - -/* Rule A15-1-1 (advisory, implementation, automated) */ - - /* 3902 - thrown object of type is not a class derived from std::exception */ - +e3902 - +elib(3902) - -append(3902,[AUTOSAR Rule A15-1-1]) - -/* Rule A15-1-2 (required, implementation, automated) */ - - /* 9154 - throwing a pointer */ - +e9154 - +elib(9154) - -append(9154,[AUTOSAR Rule A15-1-2]) - -/* Rule M15-0-3 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M15-1-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M15-1-2 (required, implementation, automated) */ - - /* 1419 - throwing the NULL macro will invoke an implementation-defined handler */ - +e1419 - +elib(1419) - -append(1419,[AUTOSAR Rule M15-1-2]) - -/* Rule M15-1-3 (required, implementation, automated) */ - - /* 9156 - rethrow outside of catch block will call std::terminate if no - exception is being handled */ - +e9156 - +elib(9156) - -append(9156,[AUTOSAR Rule M15-1-3]) - -/* Rule A15-1-3 (advisory, implementation, automated) */ - - /* not currently supported */ - -/* Rule A15-1-4 (required, implementation, partially automated) */ - - /* not currently supported */ - -/* Rule A15-1-5 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule A15-2-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A15-2-2 (required, implementation, partially automated) */ - - /* not currently supported */ - -/* Rule M15-3-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A15-3-2 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule A15-3-3 (required, implementation, partially automated) */ - - /* not currently supported */ - -/* Rule A15-3-4 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule M15-3-3 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M15-3-4 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A15-3-5 (required, implementation, automated) */ - - /* 1752 - catch parameter is not a reference */ - +e1752 - +elib(1752) - -append(1752,[AUTOSAR Rule A15-3-5]) - -/* Rule M15-3-6 (required, implementation, automated) */ - - /* 1775 - catch block does not catch any declared exceptions */ - +e1775 - +elib(1775) - -append(1775,[AUTOSAR Rule M15-3-6]) - -/* Rule M15-3-7 (required, implementation, automated) */ - - /* 1127 - catch handler after catch(...) */ - +e1127 - +elib(1127) - -append(1127,[AUTOSAR Rule M15-3-7]) - -/* Rule A15-4-1 (required, implementation, automated) */ - - /* 1906 - exception specification for function */ - +e1906 - +elib(1906) - -append(1906,[AUTOSAR Rule A15-4-1]) - -/* Rule A15-4-2 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A15-4-3 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A15-4-4 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A15-4-5 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A15-5-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A15-5-2 (required, implementation, partially automated) */ - - /* 9156 - rethrow outside of catch block will call std::terminate if no - exception is being handled */ - +e9156 - +elib(9156) - -append(9156,[AUTOSAR Rule A15-5-2]) - - /* 586 - type is deprecated */ - +e586 - +elib(586) - - -deprecate(function,abort,[AUTOSAR Rule A15-5-2]) - -deprecate(function,quick_exit,[AUTOSAR Rule A15-5-2]) - -deprecate(function,_Exit,[AUTOSAR Rule A15-5-2]) - -deprecate(function,terminate,[AUTOSAR Rule A15-5-2]) - - -deprecate(function,std::abort,[AUTOSAR Rule A15-5-2]) - -deprecate(function,std::quick_exit,[AUTOSAR Rule A15-5-2]) - -deprecate(function,std::_Exit,[AUTOSAR Rule A15-5-2]) - -deprecate(function,std::terminate,[AUTOSAR Rule A15-5-2]) - -/* Rule A15-5-3 (required, implementation, automated) */ - - /* 9156 - rethrow outside of catch block will call std::terminate if no exception is being handled */ - +e9156 - +elib(9156) - -append(9156,[AUTOSAR Rule A15-5-3]) - -/* Rule A16-0-1 (required, implementation, automated) */ - - /* 9021 - use of '#undef' is discouraged */ - +e9021 - +elib(9021) - -append(9021,[AUTOSAR Rule A16-0-1]) - - /* 9026 - function-like macro defined */ - +e9026 - +elib(9026) - -append(9026,[AUTOSAR Rule A16-0-1]) - - /* 586 - preprocessor directive is deprecated */ - +e586 - +elib(586) - - /* 886 - preprocessor directive encountered in conditionally excluded region is deprecated. */ - +e886 - +elib(886) - - -deprecate(ppw,pragma,[AUTOSAR Rule A16-0-1]) - -deprecate(ppw,error,[AUTOSAR Rule A16-0-1]) - -deprecate(ppw,line,[AUTOSAR Rule A16-0-1]) - /* Deprecate the null directive */ - -deprecate(ppw,"",[AUTOSAR Rule A16-0-1]) - -/* Rule M16-0-1 (required, implementation, automated) */ - - /* 9019 - declaration of 'Symbol' before #include */ - +e9019 - +elib(9019) - -append(9019,[AUTOSAR Rule M16-0-1]) - -/* Rule M16-0-2 (required, implementation, automated) */ - - /* 9158 - #define used within block scope */ - +e9158 - +elib(9158) - -append(9158,[AUTOSAR Rule M16-0-2]) - - /* 9159 - #undef used within block scope */ - +e9159 - +elib(9159) - -append(9159,[AUTOSAR Rule M16-0-2]) - -/* Rule M16-0-5 (required, implementation, automated) */ - - /* 436 - preprocessor directive in invocation of macro */ - +e436 - +elib(436) - -append(436,[AUTOSAR Rule M16-0-5]) - -/* Rule M16-0-6 (required, implementation, automated) */ - - /* 9022 - unparenthesized macro parameter in definition of macro */ - +e9022 - +elib(9022) - -append(9022,[AUTOSAR Rule M16-0-6]) - -/* Rule M16-0-7 (required, implementation, automated) */ - - /* 553 - undefined preprocessor variable assumed to be 0 */ - +e553 - +elib(553) - -append(553,[AUTOSAR Rule M16-0-7]) - -/* Rule M16-0-8 (required, implementation, automated) */ - - /* 16 - unknown preprocessor directive */ - +e16 - +elib(16) - -append(16,[AUTOSAR Rule M16-0-8]) - - /* 544 - preprocessor directive not followed by EOL */ - +e544 - +elib(544) - -append(544,[AUTOSAR Rule M16-0-8]) - - /* 9160 - unknown preprocessor directive in conditionally excluded region */ - +e9160 - +elib(9160) - -append(9160,[AUTOSAR Rule M16-0-8]) - -/* Rule M16-1-1 (required, implementation, automated) */ - - /* 491 - non-standard use of 'defined' preprocessor operator */ - +e491 - +elib(491) - -append(491,[AUTOSAR Rule M16-1-1]) - -/* Rule M16-1-2 (required, implementation, automated) */ - - /* 8 - unclosed #if */ - +e8 - +elib(8) - -append(8,[AUTOSAR Rule M16-1-2]) - -/* Rule M16-2-3 (required, implementation, automated) */ - - /* 967 - header file does not have a standard include guard */ - +e967 - +elib(967) - -append(967,[AUTOSAR Rule M16-2-3]) - -/* Rule A16-2-1 (required, implementation, automated) */ - - /* 9020 - header file name with non-standard character */ - +e9020 - -append(9020,[AUTOSAR Rule A16-2-1]) - -/* Rule A16-2-2 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A16-2-3 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule M16-3-1 (required, implementation, automated) */ - - /* 9023 - multiple use of stringize/pasting operators in definition of macro */ - +e9023 - +elib(9023) - -append(9023,[AUTOSAR Rule M16-3-1]) - -/* Rule M16-3-2 (advisory, implementation, automated) */ - - /* 9024 - pasting/stringize operator used in definition of macro */ - +e9024 - +elib(9024) - -append(9024,[AUTOSAR Rule M16-3-2]) - -/* Rule A16-6-1 (required, implementation, automated) */ - - /* 586 - preprocessor directive is deprecated */ - +e586 - +elib(586) - - /* 886 - preprocessor directive encountered in conditionally excluded region is deprecated. */ - +e886 - +elib(886) - - -deprecate(ppw,error,[AUTOSAR Rule A16-6-1]) - -/* Rule A16-7-1 (required, implementation, automated) */ - - /* 586 - preprocessor directive is deprecated */ - +e586 - +elib(586) - - /* 886 - preprocessor directive encountered in conditionally excluded region is deprecated. */ - +e886 - +elib(886) - - -deprecate(ppw,pragma,[AUTOSAR Rule A16-7-1]) - -/* Rule A17-0-1 (required, implementation, automated) */ - - /* 9093 - the name is reserved to the compiler */ - +e9093 - +elib(9093) - -append(9093,[AUTOSAR Rule A17-0-1]) - -/* Rule M17-0-2 (required, implementation, automated) */ - - /* 9093 - the name is reserved to the compiler */ - +e9093 - +elib(9093) - -append(9093,[AUTOSAR Rule M17-0-2]) - -/* Rule M17-0-3 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A17-0-2 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule M17-0-5 (required, implementation, automated) */ - - /* 586 - symbol is deprecated */ - +e586 - +elib(586) - - -deprecate(function,longjmp,[AUTOSAR Rule M17-0-5] ) - -deprecate(function,std::longjmp,[AUTOSAR Rule M17-0-5] ) - -deprecate(macro,setjmp,[AUTOSAR Rule M17-0-5] ) - -/* Rule A17-1-1 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule A17-6-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A18-0-1 (required, implementation, automated) */ - - /* 829 - a +headerwarn option was previously issued for header */ - +e829 - +elib(829) - - +headerwarn(time.h) - +headerwarn(limits.h) - +headerwarn(float.h) - +headerwarn(stddef.h) - +headerwarn(errno.h) - +headerwarn(locale.h) - +headerwarn(stdio.h) - +headerwarn(ctype.h) - +headerwarn(string.h) - +headerwarn(math.h) - +headerwarn(stdlib.h) - +headerwarn(assert.h) - +headerwarn(stdarg.h) - +headerwarn(setjmp.h) - +headerwarn(signal.h) - - -append(829(time.h),[AUTOSAR Rule A18-0-1]) - -append(829(limits.h),[AUTOSAR Rule A18-0-1]) - -append(829(float.h),[AUTOSAR Rule A18-0-1]) - -append(829(stddef.h),[AUTOSAR Rule A18-0-1]) - -append(829(errno.h),[AUTOSAR Rule A18-0-1]) - -append(829(locale.h),[AUTOSAR Rule A18-0-1]) - -append(829(stdio.h),[AUTOSAR Rule A18-0-1]) - -append(829(ctype.h),[AUTOSAR Rule A18-0-1]) - -append(829(string.h),[AUTOSAR Rule A18-0-1]) - -append(829(math.h),[AUTOSAR Rule A18-0-1]) - -append(829(stdlib.h),[AUTOSAR Rule A18-0-1]) - -append(829(assert.h),[AUTOSAR Rule A18-0-1]) - -append(829(stdarg.h),[AUTOSAR Rule A18-0-1]) - -append(829(setjmp.h),[AUTOSAR Rule A18-0-1]) - -append(829(signal.h),[AUTOSAR Rule A18-0-1]) - -/* Rule A18-0-2 (required, implementation, automated) */ - - /* 586 - function is deprecated */ - +e586 - +elib(586) - - -deprecate(function,atof,[AUTOSAR Rule A18-0-2]) - -deprecate(function,atoi,[AUTOSAR Rule A18-0-2]) - -deprecate(function,atol,[AUTOSAR Rule A18-0-2]) - - -deprecate(function,std::atof,[AUTOSAR Rule A18-0-2]) - -deprecate(function,std::atoi,[AUTOSAR Rule A18-0-2]) - -deprecate(function,std::atol,[AUTOSAR Rule A18-0-2]) - -/* Rule M18-0-3 (required, implementation, automated) */ - - /* 586 - function is deprecated */ - +e586 - +elib(586) - - -deprecate(function,abort,[AUTOSAR Rule M18-0-3]) - -deprecate(function,exit,[AUTOSAR Rule M18-0-3]) - -deprecate(function,getenv,[AUTOSAR Rule M18-0-3]) - -deprecate(function,system,[AUTOSAR Rule M18-0-3]) - - -deprecate(function,std::abort,[AUTOSAR Rule M18-0-3]) - -deprecate(function,std::exit,[AUTOSAR Rule M18-0-3]) - -deprecate(function,std::getenv,[AUTOSAR Rule M18-0-3]) - -deprecate(function,std::system,[AUTOSAR Rule M18-0-3]) - -/* Rule M18-0-4 (required, implementation, automated) */ - - /* 586 - function is deprecated */ - +e586 - +elib(586) - - -deprecate(function,wcsftime,[AUTOSAR Rule M18-0-4]) - -deprecate(function,clock,[AUTOSAR Rule M18-0-4]) - -deprecate(function,difftime,[AUTOSAR Rule M18-0-4]) - -deprecate(function,mktime,[AUTOSAR Rule M18-0-4]) - -deprecate(function,time,[AUTOSAR Rule M18-0-4]) - -deprecate(function,asctime,[AUTOSAR Rule M18-0-4]) - -deprecate(function,ctime,[AUTOSAR Rule M18-0-4]) - -deprecate(function,gmtime,[AUTOSAR Rule M18-0-4]) - -deprecate(function,localtime,[AUTOSAR Rule M18-0-4]) - -deprecate(function,strftime,[AUTOSAR Rule M18-0-4]) - - -deprecate(function,std::wcsftime,[AUTOSAR Rule M18-0-4]) - -deprecate(function,std::clock,[AUTOSAR Rule M18-0-4]) - -deprecate(function,std::difftime,[AUTOSAR Rule M18-0-4]) - -deprecate(function,std::mktime,[AUTOSAR Rule M18-0-4]) - -deprecate(function,std::time,[AUTOSAR Rule M18-0-4]) - -deprecate(function,std::asctime,[AUTOSAR Rule M18-0-4]) - -deprecate(function,std::ctime,[AUTOSAR Rule M18-0-4]) - -deprecate(function,std::gmtime,[AUTOSAR Rule M18-0-4]) - -deprecate(function,std::localtime,[AUTOSAR Rule M18-0-4]) - -deprecate(function,std::strftime,[AUTOSAR Rule M18-0-4]) - -/* Rule M18-0-5 (required, implementation, automated) */ - - /* 586 - function is deprecated */ - +e586 - +elib(586) - - -deprecate(function,strcpy,[AUTOSAR Rule M18-0-5]) - -deprecate(function,strcmp,[AUTOSAR Rule M18-0-5]) - -deprecate(function,strcat,[AUTOSAR Rule M18-0-5]) - -deprecate(function,strchr,[AUTOSAR Rule M18-0-5]) - -deprecate(function,strspn,[AUTOSAR Rule M18-0-5]) - -deprecate(function,strcspn,[AUTOSAR Rule M18-0-5]) - -deprecate(function,strpbrk,[AUTOSAR Rule M18-0-5]) - -deprecate(function,strrchr,[AUTOSAR Rule M18-0-5]) - -deprecate(function,strstr,[AUTOSAR Rule M18-0-5]) - -deprecate(function,strtok,[AUTOSAR Rule M18-0-5]) - -deprecate(function,strlen,[AUTOSAR Rule M18-0-5]) - - -deprecate(function,std::strcpy,[AUTOSAR Rule M18-0-5]) - -deprecate(function,std::strcmp,[AUTOSAR Rule M18-0-5]) - -deprecate(function,std::strcat,[AUTOSAR Rule M18-0-5]) - -deprecate(function,std::strchr,[AUTOSAR Rule M18-0-5]) - -deprecate(function,std::strspn,[AUTOSAR Rule M18-0-5]) - -deprecate(function,std::strcspn,[AUTOSAR Rule M18-0-5]) - -deprecate(function,std::strpbrk,[AUTOSAR Rule M18-0-5]) - -deprecate(function,std::strrchr,[AUTOSAR Rule M18-0-5]) - -deprecate(function,std::strstr,[AUTOSAR Rule M18-0-5]) - -deprecate(function,std::strtok,[AUTOSAR Rule M18-0-5]) - -deprecate(function,std::strlen,[AUTOSAR Rule M18-0-5]) - -/* Rule A18-0-3 (required, implementation, automated) */ - - /* 829 - a +headerwarn option was previously issued for header */ - +e829 - +elib(829) - - +headerwarn(locale.h) - +headerwarn(clocale) - - -append(829(locale.h),[AUTOSAR Rule A18-0-3]) - -append(829(clocale),[AUTOSAR Rule A18-0-3]) - - /* 586 - function is deprecated */ - +e586 - +elib(586) - - -deprecate(function,setlocale,[AUTOSAR Rule A18-0-3]) - -deprecate(function,std::setlocale,[AUTOSAR Rule A18-0-3]) - -/* Rule A18-1-1 (required, implementation, automated) */ - - /* 9436 - symbol has array type */ - +e9436 - +elib(9436) - -append(9436,[AUTOSAR Rule A18-1-1]) - -/* Rule A18-1-2 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A18-1-3 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A18-1-4 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A18-1-6 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M18-2-1 (required, implementation, automated) */ - - /* 586 - macro is deprecated */ - +e586 - +elib(586) - - -deprecate(macro,offsetof,[AUTOSAR Rule M18-2-1]) - -/* Rule A18-5-1 (required, implementation, automated) */ - - /* 586 - function is deprecated */ - +e586 - +elib(586) - - -deprecate(function,calloc,[AUTOSAR Rule A18-5-1]) - -deprecate(function,malloc,[AUTOSAR Rule A18-5-1]) - -deprecate(function,realloc,[AUTOSAR Rule A18-5-1]) - -deprecate(function,free,[AUTOSAR Rule A18-5-1]) - - -deprecate(function,std::calloc,[AUTOSAR Rule A18-5-1]) - -deprecate(function,std::malloc,[AUTOSAR Rule A18-5-1]) - -deprecate(function,std::realloc,[AUTOSAR Rule A18-5-1]) - -deprecate(function,std::free,[AUTOSAR Rule A18-5-1]) - -/* Rule A18-5-2 (required, implementation, partially automated) */ - - /* not currently supported */ - -/* Rule A18-5-3 (required, implementation, automated) */ - - /* 424 - delete/delete[]/free is not appropriate for deallocating */ - +e424 - +elib(424) - -append(424,[AUTOSAR Rule A18-5-3]) - -/* Rule A18-5-4 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A18-5-5 (required, toolchain, partially automated) */ - - /* not currently supported */ - -/* Rule A18-5-6 (required, verification/toolchain, non-automated) */ - - /* not statically checkable */ - -/* Rule A18-5-7 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule A18-5-8 (required, implementation, partially automated) */ - - /* not currently supported */ - -/* Rule A18-5-9 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A18-5-10 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A18-5-11 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M18-7-1 (required, implementation, automated) */ - - /* 586 - function is deprecated */ - +e586 - +elib(586) - - -deprecate(function,signal,[AUTOSAR Rule A18-7-1]) - -deprecate(function,raise,[AUTOSAR Rule A18-7-1]) - - -deprecate(function,std::signal,[AUTOSAR Rule A18-7-1]) - -deprecate(function,std::raise,[AUTOSAR Rule A18-7-1]) - -/* Rule A18-9-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A18-9-2 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A18-9-3 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A18-9-4 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M19-3-1 (required, implementation, automated) */ - - /* 586 - variable is deprecated */ - +e586 - +elib(586) - - -deprecate(variable,errno,[AUTOSAR Rule M19-3-1] ) - -/* Rule A20-8-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A20-8-2 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A20-8-3 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A20-8-4 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A20-8-5 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A20-8-6 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A20-8-7 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule A21-8-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A23-0-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A23-0-2 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A25-1-1 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A25-4-1 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule A26-5-1 (required, implementation, automated) */ - - /* 586 - function is deprecated */ - +e586 - +elib(586) - - -deprecate(function,rand,[AUTOSAR Rule A26-5-1]) - -deprecate(function,std::rand,[AUTOSAR Rule A26-5-1]) - -deprecate(function,std::random_shuffle,[AUTOSAR Rule A26-5-1]) - -/* Rule A26-5-2 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule M27-0-1 (required, implementation, automated) */ - - /* 586 - variable is deprecated */ - +e586 - +elib(586) - - -deprecate(function,clearerr,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fclose,[AUTOSAR Rule M27-0-1]) - -deprecate(function,feof,[AUTOSAR Rule M27-0-1]) - -deprecate(function,ferror,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fflush,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fgetc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fgetpos,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fgets,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fgetwc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fgetws,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fopen,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fputc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fputs,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fputwc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fputws,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fread,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fseek,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fsetpos,[AUTOSAR Rule M27-0-1]) - -deprecate(function,freopen,[AUTOSAR Rule M27-0-1]) - -deprecate(function,ftell,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fwide,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fwprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fwrite,[AUTOSAR Rule M27-0-1]) - -deprecate(function,fwscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,getc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,getchar,[AUTOSAR Rule M27-0-1]) - -deprecate(function,gets,[AUTOSAR Rule M27-0-1]) - -deprecate(function,getwc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,getwchar,[AUTOSAR Rule M27-0-1]) - -deprecate(function,perror,[AUTOSAR Rule M27-0-1]) - -deprecate(function,printf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,putc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,putchar,[AUTOSAR Rule M27-0-1]) - -deprecate(function,puts,[AUTOSAR Rule M27-0-1]) - -deprecate(function,putwc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,putwchar,[AUTOSAR Rule M27-0-1]) - -deprecate(function,remove,[AUTOSAR Rule M27-0-1]) - -deprecate(function,rename,[AUTOSAR Rule M27-0-1]) - -deprecate(function,rewind,[AUTOSAR Rule M27-0-1]) - -deprecate(function,scanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,setbuf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,setvbuf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,snprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,sprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,sscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,swprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,swscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,tmpfile,[AUTOSAR Rule M27-0-1]) - -deprecate(function,tmpnam,[AUTOSAR Rule M27-0-1]) - -deprecate(function,ungetc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,ungetwc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,vfprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,vfscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,vfwprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,vfwscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,vprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,vscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,vsnprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,vsprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,vsscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,vswprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,vswscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,vwprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,vwscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,wprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,wscanf,[AUTOSAR Rule M27-0-1]) - - -deprecate(function,std::clearerr,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fclose,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::feof,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::ferror,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fflush,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fgetc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fgetpos,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fgets,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fgetwc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fgetws,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fopen,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fputc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fputs,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fputwc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fputws,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fread,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fseek,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fsetpos,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::freopen,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::ftell,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fwide,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fwprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fwrite,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::fwscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::getc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::getchar,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::gets,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::getwc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::getwchar,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::perror,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::printf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::putc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::putchar,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::puts,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::putwc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::putwchar,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::remove,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::rename,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::rewind,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::scanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::setbuf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::setvbuf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::snprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::sprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::sscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::swprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::swscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::tmpfile,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::tmpnam,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::ungetc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::ungetwc,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::vfprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::vfscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::vfwprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::vfwscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::vprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::vscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::vsnprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::vsprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::vsscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::vswprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::vswscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::vwprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::vwscanf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::wprintf,[AUTOSAR Rule M27-0-1]) - -deprecate(function,std::wscanf,[AUTOSAR Rule M27-0-1]) - -/* Rule A27-0-1 (required, implementation, non-automated) */ - - /* not statically checkable */ - -/* Rule A27-0-4 (required, implementation, automated) */ - - /* not currently supported */ - -/* Rule A27-0-2 (advisory, implementation, automated) */ - - /* not currently supported */ - -/* Rule A27-0-3 (required, implementation, automated) */ - - /* not currently supported */ - - diff --git a/ports/lint-plus/au-ds.lnt b/ports/lint-plus/au-ds.lnt deleted file mode 100644 index 38fcd6736..000000000 --- a/ports/lint-plus/au-ds.lnt +++ /dev/null @@ -1,21 +0,0 @@ -// au-ds.lnt -- Author options - Dan Saks - -/* - This options file can be used to explicitly activate those - checks advocated by Dan Saks in his series of presentations on - "C++ Gotchas". - - You can use this file directly when linting your programs as in: - - lin au-ds files - - */ - -+fsc // consider string constants as const char * -+e1933 // turn on "virtual call from member detection" - -// The rationale for the following two options are fully described -// in Dan Saks' article "const T vs. T const". Visit his web site -// at www.dansaks.com and click "Published Articles". -// --fqb +e963 // require T const rather than const T diff --git a/ports/lint-plus/au-ql-cpp11.lnt b/ports/lint-plus/au-ql-cpp11.lnt deleted file mode 100644 index dc71dcf46..000000000 --- a/ports/lint-plus/au-ql-cpp11.lnt +++ /dev/null @@ -1,635 +0,0 @@ -// --------------------------------------------------------------------------- -// Copyright Gimpel Software LLC 2019. All rights reserved. -// -// This file is provided by Gimpel Software LLC (https://www.gimpel.com) for -// use with PC-lint Plus. Redistribution is permitted but any redistribution -// must preserve this notice and, if the redistributed file has been modified, -// provide notice that the file has been modified from the original. -// --------------------------------------------------------------------------- - -// au-ql-cpp11.lnt -- Author options - QL-C++11:2022 -// -// This options file contains options to help enforce the checks advocated -// by the Quantum Leaps Embedded C/C++ Coding Style (QL-C/C++:2022): -// https://github.com/QuantumLeaps/embedded-coding-style - -// ========== GENERAL RULES ========== - -// 1.1 Which C++? - - /* Enable C++11 mode */ - -std=c++11 - - /* 975 - unknown pragma will be ignored */ - +e975 - -append(975,[BARR-C:2018 Rule 1.1c]) - - /* 9051 - macro defined with the same name as a C keyword */ - +e9051 - -append(9051,[BARR-C:2018 Rule 1.1d]) - -// 1.2 Line Widths - - /* not currently supported */ - -// 1.3 Braces - - /* 9012 - body should be a compound statement */ - +e9012 - -append(9012,[BARR-C:2018 Rule 1.3a]) - -// 1.4 Parentheses - - /* 9050 - dependence placed on precedence */ - +e9050 - -append(9050,[BARR-C:2018 Rule 1.4a]) - - /* 9097 - unparenthesized argument to sizeof */ - +e9097 - -append(9097,[BARR-C:2018 Rule 1.4a]) - - /* 821 - right hand side of assignment not parenthesized */ - +e821 - -append(821,[BARR-C:2018 Rule 1.4a]) - - /* 834 - operator op1 followed by operator op2 could be confusing */ - +e834 - -append(834,[BARR-C:2018 Rule 1.4a]) - - /* 9240 - left/right side of logical operator is not a primary expression */ - +e9240 - -append(9240,[BARR-C:2018 Rule 1.4b]) - -// 1.5 Common Abbreviations - - /* not currently supported */ - -// 1.6 Casts - - /* not currently supported */ - -// 1.7 Keywords to Avoid - - /* 586 - keyword is deprecated */ - -deprecate(keyword, auto,[BARR-C:2018 Rule 1.7a]) - -deprecate(keyword, register,[BARR-C:2018 Rule 1.7b]) - -deprecate(keyword, continue,[BARR-C:2018 Rule 1.7d]) - - /* 801 - goto statement used */ - +e801 - -append(801,[BARR-C:2018 Rule 1.7c]) - - /* 9041 - goto appears in block which is not nested in block containing label */ - +e9041 - -append(9041,[BARR-C:2018 Rule 1.7c]) - - /* 9064 - goto references earlier label */ - +e9064 - -append(9064,[BARR-C:2018 Rule 1.7c]) - -// 1.8 Keywords to Frequent - - /* 765 - external symbol could be made static */ - +e765 - -append(765,[BARR-C:2018 Rule 1.8a]) - - /* 818 - parameter of function could be pointer to const */ -//QL +e818 -//QL -append(818,[BARR-C:2018 Rule 1.8b]) - - /* 843 - static storage duration variable could be made const */ - +e843 - -append(843,[BARR-C:2018 Rule 1.8b]) - - /* 844 - static storage duration variable could be made pointer to const */ - +e844 - -append(844,[BARR-C:2018 Rule 1.8b]) - - /* 952 - parameter of function could be const */ -//QL +e952 -//QL -append(952,[BARR-C:2018 Rule 1.8b]) - - /* 953 - local variable could be const */ - +e953 - -append(953,[BARR-C:2018 Rule 1.8b]) - - /* 954 - local variable could be pointer to const */ - +e954 - -append(954,[BARR-C:2018 Rule 1.8b]) - - /* 2765 - reference to variable which is neither atomic nor volatile sig_atomic_t within signal handler */ - +e2765 - -append(2765,[BARR-C:2018 Rule 1.8c]) - -// ========== COMMENTS ========== - -// 2.1 Acceptable Formats - - /* 427 - C++ comment continued via back-slash */ - +e427 - -append(427,[BARR-C:2018 Rule 2.1b]) - - /* 602 - nested block comment */ - +e602 - -append(602,[BARR-C:2018 Rule 2.1b]) - - /* 9059 - C comment contains C++ comment */ - +e9059 - -append(9059,[BARR-C:2018 Rule 2.1b]) - - // 9259 - C comment contains '://' sequence - +e9259 - -append(9259,[BARR-C:2018 Rule 2.1b]) - - /* 9066 - C++ comment contains C comment */ - +e9066 - -append(9066,[BARR-C:2018 Rule 2.1b]) - -// 2.2 Locations and Comments - - /* not statically checkable */ - -// ========== WHITE SPACE RULES ========== - -// 3.1 Spaces - - /* not currently supported */ - -// 3.2 Alignment - - /* not currently supported */ - -// 3.3 Black Lines - - /* 783 - line does not end with a newline */ - +e783 - -append(783,[BARR-C:2018 Rule 3.3c]) - -// 3.4 Indentation - - /* 525 - unexpected negative indentation */ - +e525 - -append(525,[BARR-C:2018 Rule 3.4a]) - - /* 539 - unexpected positive indentation */ - +e539 - -append(539,[BARR-C:2018 Rule 3.4a]) - - /* 725 - unexpected lack of indentation */ - +e725 - -append(725,[BARR-C:2018 Rule 3.4a]) - -// 3.5 Tabs - - /* not currently supported */ - -// 3.6 Non-Printing Characters - - /* not currently supported */ - -// ========== MODULE RULES ========== - -// 4.1 Naming Conventions - - /* 8516 - module name should contain only lowercase letters, numbers, and underscores */ - -hook(module_open, -cond(!('%[file_name]' ~ '^[[:lower:][:digit:]_./\\\\]+$'), - +message(8516, "module '%[file_name]' should contain only lowercase letters, numbers, and underscores"))) - +e8516 - -append(8516,[BARR-C:2018 Rule 4.1a]) - - /* 8517 - module does not end with '.cpp' */ - -hook(module_open, -cond(!('%[file_name]' ~ '[.]cpp$'), - +message(8517, "module '%[file_name]' should have '.cpp' extension"))) - +e8517 - -append(8517,[BARR-C:2018 Rule 4.1b]) - - /* 8518 - header does not end with '.hpp' */ - -hook(header_open, -cond(!('%[file_name]' ~ '[.]hpp$'), - +message(8517, "header '%[file_name]' should have '.hpp' extension"))) - +e8518 - -append(8518,[BARR-C:2018 Rule 4.1b]) - - /* 8519 - 'main' function defined in file that does not contain the word 'main' */ - -hook(func_decl, -cond('%[qual_name]' == 'main' && %[is_definition] && !('%[file]' ~ 'main'), - +message(8519, "main function defined in file '%[file]' which does not have the word 'main' in its name"))) - +e8519 - -append(8519,[BARR-C:2018 Rule 4.1d]) - -// 4.2 Header Files - - /* 451 - header file repeatedly included but has no header guard */ - +e451 - -append(451,[BARR-C:2018 Rule 4.2b]) - - /* 967 - header file does not have a standard include guard */ - +e967 - -append(967,[BARR-C:2018 Rule 4.2b]) - - /* 9107 - header cannot be included in more than one translation unit because of the definition of symbol */ - +e9107 - -append(9107,[BARR-C:2018 Rule 4.2c]) - - /* 755 - global macro not referenced */ - +e755 - -append(755,[BARR-C:2018 Rule 4.2c]) - - /* 756 - global typedef not referenced */ - +e756 - -append(756,[BARR-C:2018 Rule 4.2c]) - - /* 757 - global declarator not referenced */ - +e757 - -append(757,[BARR-C:2018 Rule 4.2c]) - - /* 758 - global tag not referenced */ - +e758 - -append(758,[BARR-C:2018 Rule 4.2c]) - - /* 759 - header declaration for symbol could be moved from header to module */ - +e759 - -append(759,[BARR-C:2018 Rule 4.2c]) - - /* 768 - global field not referenced */ - +e768 - -append(768,[BARR-C:2018 Rule 4.2c]) - - /* 769 - global enumeration constant not referenced */ - +e769 - -append(769,[BARR-C:2018 Rule 4.2c]) - -// 4.3 Source Files - - /* 9019 - declaration of symbol before #include */ - -append(9019,[BARR-C:2018 Rule 4.3b]) - - /* 8520 - #include used with absolute path */ - -hook(header_open, -cond('%[file_name]' ~ '^([[:alpha:]]:)?[/\\\\]', - +message(8520, "#include directive uses absolute path to include file '%[file_name]'"))) - +e8520 - -append(8520,[BARR-C:2018 Rule 4.3d]) - - /* 8521 - #include used to include module file */ - -hook(header_open, -cond('%[file_name]' ~ '[.]c$', - +message(8521, "#include directive used to include module file '%[file_name]'"))) - +e8521 - -append(8521,[BARR-C:2018 Rule 4.3f]) - -// 4.4 File Templates - - /* not statically checkable */ - -// ========== DATA TYPE RULES ========== - -// 5.1 Naming Conventions - - /* 8526 - typedef name should consist of lowercase letters and underscores */ -//QL -hook(typename_decl, -cond(!('%[name]' ~ '^[[:lower:]_]*$'), -//QL +message(8526, "typedef name '%[name]' should consist of lowercase letters and underscores"))) -//QL +e8526 -//QL -append(8526,[BARR-C:2018 Rule 5.1a]) - - /* 8527 - typedef name should end with '_t' suffix */ -//QL -hook(typename_decl, -cond(!('%[name]' ~ '_t$'), -//QL +message(8527, "typedef name '%[name]' should end with '_t' suffix"))) -//QL +e8527 -//QL -append(8527,[BARR-C:2018 Rule 5.1a]) - - /* 8528 - non-anonymous struct/union/enum declared outside of typedef */ -//QL -hook(record_decl, -cond(%[is_freestanding] && !%[is_anonymous], -//QL +message(8528, "non-anonymous struct/union declared outside of a typedef"))) -//QL -hook(enum_decl, -cond(%[is_freestanding] && '%[name]' != '', -//QL +message(8528, "non-anonymous enum declared outside of a typedef"))) -//QL +e8528 -//QL -append(8528,[BARR-C:2018 Rule 5.1b]) - -// 5.2 Fixed-Width Integers - - /* 586 - keyword/type is deprecated */ - +e586 - - -deprecate(type,signed char,[BARR-C:2018 Rule 5.2a]) - -deprecate(type,unsigned char,[BARR-C:2018 Rule 5.2a]) - -deprecate(type,signed short,[BARR-C:2018 Rule 5.2a]) - -deprecate(type,unsigned short,[BARR-C:2018 Rule 5.2a]) - -deprecate(type,signed int,[BARR-C:2018 Rule 5.2a]) - -deprecate(type,unsigned int,[BARR-C:2018 Rule 5.2a]) - -deprecate(type,signed long,[BARR-C:2018 Rule 5.2a]) - -deprecate(type,unsigned long,[BARR-C:2018 Rule 5.2a]) - -deprecate(type,signed long long,[BARR-C:2018 Rule 5.2a]) - -deprecate(type,unsigned long long,[BARR-C:2018 Rule 5.2a]) - - -deprecate(keyword, short,[BARR-C:2018 Rule 5.2b]) - -deprecate(keyword, long,[BARR-C:2018 Rule 5.2b]) - - /* 9209 - plain character data used with prohibited operator */ -//QL +e9209 -//QL -append(9209,[BARR-C:2018 Rule 5.2c]) - -// 5.3 Signed and Unsigned Integers - - /* 9420 - bitfield does not have unsigned type */ - +e9420 - -append(9420,[BARR-C:2018 Rule 5.3a]) - - /* 9130 - bitwise operator applied to signed underlying type */ - +e9130 - -append(9130,[BARR-C:2018 Rule 5.3b]) - - /* 570 - negative value loses sign during implicit conversion */ - +e570 - -append(570,[BARR-C:2018 Rule 5.3c]) - - /* 713 - implicit conversion from unsigned to signed may lose precision */ - +e713 - -append(713,[BARR-C:2018 Rule 5.3c]) - - /* 8524 - combining signed and unsigned types with operator op1 */ - -hook(binary_expr, -cond(%[walk_lhs_expr{false}.walk_type.is_integer] && - %[walk_rhs_expr{false}.walk_type.is_integer] && - !%[walk_lhs_expr.walk_past_paren_imp.walk_type.is_enumeral] && - !%[walk_rhs_expr.walk_past_paren_imp.walk_type.is_enumeral] && - !%[walk_lhs_expr.walk_past_paren_imp.walk_type.is_boolean] && - !%[walk_rhs_expr.walk_past_paren_imp.walk_type.is_boolean] && - '%[walk_lhs_expr.walk_past_paren_imp.walk_type.is_unsigned_int_enum]' != - '%[walk_rhs_expr.walk_past_paren_imp.walk_type.is_unsigned_int_enum]', - +message(8524, "combining signed and unsigned types with operator '%[opcode]'"))) - +e8524 - -append(8524,[BARR-C:2018 Rule 5.3c]) - -// 5.4 Floating Point - - /* 586 - type is deprecated */ - -deprecate(type,float,[BARR-C:2018 Rule 5.4b]) - -deprecate(type,double,[BARR-C:2018 Rule 5.4b]) - -deprecate(type,long double,[BARR-C:2018 Rule 5.4b]) - - /* 777 - testing floating point values for equality */ - +e777 - -append(777,[BARR-C:2018 Rule 5.4b]) - - /* 9252 - testing floating point for equality using exact value */ - +e9252 - -append(9252,[BARR-C:2018 Rule 5.4b]) - -// 5.5 Structures and Unions - - /* not currently supported */ - -// 5.6 Booleans - - /* 8523 - cast to boolean */ - -hook(cast_expr, -cond(%[is_cstyle_cast] && %[walk_type.is_boolean], - +message(8523, "cast to boolean"))) - +e8523 - -append(8523,[BARR-C:2018 Rule 5.6b]) - -// ========== PROCEDURE RULES ========== - -// 6.1 Naming Conventions - - /* 8501 - function has name that matches a keyword in C or C++ */ - -hook(func_decl, -cond('%[name]' ~ '^(?Palignas|alignof|and|and_eq|asm|auto|bitand|bitor|bool|break|case|catch|char|char8_t|char16_t|char32_t|class|compl|concept|const|consteval|constexpr|const_cast|continue|co_await|co_return|co_yield|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|false|float|for|friend|goto|if|inline|int|long|mutable|namespace|new|noexcept|not|not_eq|nullptr|operator|or|or_eq|private|protected|public|register|reinterpret_cast|requires|restrict|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|true|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while|xor|xor_eq|_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local)$', +message(8501, "function '%[name]' matches the name of a C/C++ keyword"))) - +e8501 - -append(8501,[BARR-C:2018 Rule 6.1a]) - - /* 8502 - function has same name as standard library function */ -/*QL - -hook(func_decl, -cond('%[name]' ~ '^(?:abort|abs|acos|acosf|acosh|acoshf|acoshl|acosl|asctime|asin|asinf|asinh|asinhf|asinhl|asinl|assert|atan|atan2|atan2f|atan2l|atanf|atanh|atanhf|atanhl|atanl|atexit|atof|atoi|atol|atoll|bsearch|btowc|cabs|cabsf|cabsl|cacos|cacosf|cacosh|cacoshf|cacoshl|cacosl|calloc|carg|cargf|cargl|casin|casinf|casinh|casinhf|casinhl|casinl|catan|catanf|catanh|catanhf|catanhl|catanl|cbrt|cbrtf|cbrtl|ccos|ccosf|ccosh|ccoshf|ccoshl|ccosl|ceil|ceilf|ceill|cexp|cexpf|cexpl|cimag|cimagf|cimagl|clearerr|clock|clog|clogf|clogl|conj|conjf|conjl|copysign|copysignf|copysignl|cos|cosf|cosh|coshf|coshl|cosl|cpow|cpowf|cpowl|cproj|cprojf|cprojl|creal|crealf|creall|csin|csinf|csinh|csinhf|csinhl|csinl|csqrt|csqrtf|csqrtl|ctan|ctanf|ctanh|ctanhf|ctanhl|ctanl|ctime|difftime|div|erf|erfc|erfcf|erfcl|erff|erfl|exit|_Exit|exp|exp2|exp2f|exp2l|expf|expl|expm1|expm1f|expm1l|fabs|fabsf|fabsl|fclose|fdim|fdimf|fdiml|feclearexcept|fegetenv|fegetexceptflag|fegetround|feholdexcept|feof|feraiseexcept|ferror|fesetenv|fesetexceptflag|fesetround|fetestexcept|feupdateenv|fflush|fgetc|fgetpos|fgets|fgetwc|fgetws|floor|floorf|floorl|fma|fmaf|fmal|fmax|fmaxf|fmaxl|fmin|fminf|fminl|fmod|fmodf|fmodl|fopen|fpclassify|fprintf|fputc|fputs|fputwc|fputws|fread|free|freopen|frexp|frexpf|frexpl|fscanf|fseek|fsetpos|ftell|fwide|fwprintf|fwrite|fwscanf|getc|getchar|getenv|gets|getwc|getwchar|gmtime|hypot|hypotf|hypotl|ilogb|ilogbf|ilogbl|imaxabs|imaxdiv|isalnum|isalpha|isblank|iscntrl|isdigit|isfinite|isgraph|isgreater|isgreaterequal|isinf|isless|islessequal|islessgreater|islower|isnan|isnormal|isprint|ispunct|isspace|isunordered|isupper|iswalnum|iswalpha|iswblank|iswcntrl|iswctype|iswdigit|iswgraph|iswlower|iswprint|iswpunct|iswspace|iswupper|iswxdigit|isxdigit|labs|ldexp|ldexpf|ldexpl|ldiv|lgamma|lgammaf|lgammal|llabs|lldiv|llrint|llrintf|llrintl|llround|llroundf|llroundl|localeconv|localtime|log|log10|log10f|log10l|log1p|log1pf|log1pl|log2|log2f|log2l|logb|logbf|logbl|logf|logl|longjmp|lrint|lrintf|lrintl|lround|lroundf|lroundl|malloc|mblen|mbrlen|mbrtowc|mbsinit|mbsrtowcs|mbstowcs|mbtowc|memchr|memcmp|memcpy|memmove|memset|mktime|modf|modff|modfl|nan|nanf|nanl|nearbyint|nearbyintf|nearbyintl|nextafter|nextafterf|nextafterl|nexttoward|nexttowardf|nexttowardl|perror|pow|powf|powl|printf|putc|putchar|puts|putwc|putwchar|qsort|raise|rand|realloc|remainder|remainderf|remainderl|remove|remquo|remquof|remquol|rename|rewind|rint|rintf|rintl|round|roundf|roundl|scalbln|scalblnf|scalblnl|scalbn|scalbnf|scalbnl|scanf|setbuf|setjmp|setlocale|setvbuf|signal|signbit|sin|sinf|sinh|sinhf|sinhl|sinl|snprintf|sprintf|sqrt|sqrtf|sqrtl|srand|sscanf|strcat|strchr|strcmp|strcoll|strcpy|strcspn|strerror|strftime|strlen|strncat|strncmp|strncpy|strpbrk|strrchr|strspn|strstr|strtod|strtof|strtoimax|strtok|strtol|strtold|strtoll|strtoul|strtoull|strtoumax|strxfrm|swprintf|swscanf|system|tan|tanf|tanh|tanhf|tanhl|tanl|tgamma|tgammaf|tgammal|time|tmpfile|tmpnam|tolower|toupper|towctrans|towlower|towupper|trunc|truncf|truncl|ungetc|ungetwc|va_arg|va_copy|va_end|va_start|vfprintf|vfscanf|vfwprintf|vfwscanf|vprintf|vscanf|vsnprintf|vsprintf|vsscanf|vswprintf|vswscanf|vwprintf|vwscanf|wcrtomb|wcscat|wcschr|wcscmp|wcscoll|wcscpy|wcscspn|wcsftime|wcslen|wcsncat|wcsncmp|wcsncpy|wcspbrk|wcsrchr|wcsrtombs|wcsspn|wcsstr|wcstod|wcstof|wcstoimax|wcstok|wcstol|wcstold|wcstoll|wcstombs|wcstoul|wcstoull|wcstoumax|wcsxfrm|wctob|wctomb|wctrans|wctype|wmemchr|wmemcmp|wmemcpy|wmemmove|wmemset|wprintf|wscanf)$', +message(8502, "function '%[name]' matches the name of a standard library function"))) - +e8502 - -append(8502,[BARR-C:2018 Rule 6.1b]) -*/ - - /* 8503 - function has name that begins with an underscore */ - -hook(func_decl, -cond('%[name]' ~ '^_', +message(8503, "function '%[name]' begins with an underscore"))) - +e8503 - -append(8503,[BARR-C:2018 Rule 6.1c]) - - /* 8504 - function name is longer than 31 characters */ - -hook(func_decl, -cond('%[name]' ~ '.{32,}', +message(8504, "function '%[name]' is longer than 31 characters"))) - +e8504 - -append(8504,[BARR-C:2018 Rule 6.1d]) - - /* 8505 - function name contains upper case letter(s) */ -//QL -hook(func_decl, -cond('%[name]' ~ '[[:upper:]]', +message(8505, "function '%[name]' contains uppercase letters"))) -//QL +e8505 -//QL -append(8505,[BARR-C:2018 Rule 6.1e]) - - /* 8506 - macro name contains lowercase letter(s) */ - -hook(macro_define, -cond(!%[is_builtin] && '%[name]' ~ '[[:lower:]]', +message(8506, "macro '%[name]' contains lowercase letters"))) - +e8506 - -append(8506,[BARR-C:2018 Rule 6.1f]) - -// 6.2 Functions - - /* 904 - return statement before end of function */ - +e904 - -append(904,[BARR-C:2018 Rule 6.2c]) - - /* 937 - old-style function declaration for function */ - +e937 - -append(937,[BARR-C:2018 Rule 6.2f]) - - /* 957 - function defined without a prototype in scope */ - +e957 - -append(957,[BARR-C:2018 Rule 6.2f]) - - /* 832 - parameter not explicitly declared, int assumed */ - +e832 - -append(832,[BARR-C:2018 Rule 6.2f]) - -// 6.3 Function-Like Macros - - /* 9026 - function-like macro defined */ - +e9026 - -append(9026,[BARR-C:2018 Rule 6.3a]) - - /* 665 - unparenthesized parameter in macro is passed an expression */ - +e665 - -append(665,[BARR-C:2018 Rule 6.3b]) - - /* 666 - expression with side effects passed to repeated parameter */ - +e666 - -append(666,[BARR-C:2018 Rule 6.3b]) - - /* 773 - expression-like macro not parenthesized */ - +e773 - -append(773,[BARR-C:2018 Rule 6.3b]) - - /* 9022 - unparenthesized macro parameter in definition of macro */ - +e9022 - -append(9022,[BARR-C:2018 Rule 6.3b]) - -// 6.4 Threads of Execution - - /* not currently supported */ - -// 6.5 Interrupt Service Routines - - /* not currently supported */ - -// ========== VARIABLES ========== - -// 7.1 Naming Conventions - - /* 8507 - variable has name that matches a keyword in C or C++ */ - -hook(var_decl, -cond('%[name]' ~ '^(?Palignas|alignof|and|and_eq|asm|auto|bitand|bitor|bool|break|case|catch|char|char8_t|char16_t|char32_t|class|compl|concept|const|consteval|constexpr|const_cast|continue|co_await|co_return|co_yield|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|false|float|for|fortran|friend|goto|if|inline|int|interrupt|long|mutable|namespace|new|noexcept|not|not_eq|nullptr|operator|or|or_eq|private|protected|public|register|reinterpret_cast|requires|restrict|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|true|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while|xor|xor_eq|_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local)$', +message(8507, "variable '%[name]' matches the name of a C/C++ keyword"))) - +e8507 - -append(8507,[BARR-C:2018 Rule 7.1a]) - - /* 8525 - variable has same name as standard library variable */ - -hook(var_decl, -cond('%[name]' ~ '^(?:errno|stderr|stdin|stdout)$', - +message(8525, "variale '%[name]' matches the same name of a standard library variable"))) - +e8525 - -append(8525,[BARR-C:2018 Rule 7.1b]) - - /* 8508 - variable has name that begins with an underscore */ - -hook(var_decl, -cond('%[name]' ~ '^_', +message(8508, "variable '%[name]' begins with an underscore"))) - +e8508 - -append(8508,[BARR-C:2018 Rule 7.1c]) - - /* 8509 - variable name is longer than 31 characters */ - -hook(var_decl, -cond('%[name]' ~ '.{32,}', +message(8509, "variable '%[name]' is longer than 31 characters"))) - +e8509 - -append(8509,[BARR-C:2018 Rule 6.1d]) - - /* 8510 - variable name contains less than 3 characters */ -//QL -hook(var_decl, -cond('%[name]' ~ '^.{1,2}$', +message(8510, "variable '%[name]' contains less than 3 characters"))) -//QL +e8510 -//QL -append(8510,[BARR-C:2018 Rule 7.1e]) - - /* 8511 - variable name contains upper case letter(s) */ -//QL -hook(var_decl, -cond('%[name]' ~ '[[:upper:]]', +message(8511, "variable '%[name]' contains uppercase letters"))) -//QL +e8511 -//QL -append(8511,[BARR-C:2018 Rule 7.1f]) - - /* 8512 - global variable must start with 'g' */ -//QL -hook(var_decl, -cond('%[linkage]' == 'external' && !('%[name]' ~ '^g'), +message(8512, "global variable '%[name]' should have 'g' prefix"))) -//QL +e8512 -//QL -append(8512,[BARR-C:2018 Rule 7.1j]) - - /* 8513 - variable of pointer type should have 'p' prefix */ - /* 8514 - variable of pointer type should have 'pp' prefix */ -//QL -hook(var_decl, -cond('%[walk_type.is_pointer]' == 'true', -//QL -cond('%[walk_type.walk_pointee.is_pointer]' == 'true', -//QL -cond(!('%[name]' ~ '^g?pp'), +message(8513, "variable '%[name]' of type '%[walk_type.as_string]' should have 'pp' prefix")), -//QL -cond(!('%[name]' ~ '^g?p'), +message(8514, "variable '%[name]' of type '%[walk_type.as_string]' should have 'p' prefix")) -//QL ))) -//QL +e8513 -//QL +e8514 -//QL -append(8513,[BARR-C:2018 Rule 7.1k]) -//QL -append(8514,[BARR-C:2018 Rule 7.1l]) - - /* 8515 - boolean variable should have 'b' prefix */ -//QL -hook(var_decl, -cond('%[walk_type.is_boolean]' == 'true' && !('%[name]' ~ '^g?b'), +message(8515, "boolean variable '%[name]' should have 'b' prefix"))) -//QL +e8515 -//QL -append(8515,[BARR-C:2018 Rule 7.1m]) - -// 7.2 Initialization - - /* 530 - likely using an uninitialized value */ - +e530 - -append(530,[BARR-C:2018 Rule 7.2a]) - - /* 603 - argument to parameter of type pointer to const may be a pointer to uninitialized memory */ - +e603 - -append(603,[BARR-C:2018 Rule 7.2a]) - - /* 644 - potentially using an uninitialized value */ - +e644 - -append(644,[BARR-C:2018 Rule 7.2a]) - - /* 708 - union initialization */ - +e708 - -append(708,[BARR-C:2018 Rule 7.2a]) - - /* 727 - static local symbol not explicitly initialized */ - +e727 - -append(727,[BARR-C:2018 Rule 7.2a]) - - /* 728 - file scope static variable not explicitly initialized */ - +e728 - -append(728,[BARR-C:2018 Rule 7.2a]) - - /* 729 - external variable not explicitly initialized */ - +e729 - -append(729,[BARR-C:2018 Rule 7.2a]) - - /* 738 - address of static local symbol not explicitly initialized before passed to a function */ - +e738 - -append(738,[BARR-C:2018 Rule 7.2a]) - - /* 784 - nul character truncated from string */ - +e784 - -append(784,[BARR-C:2018 Rule 7.2a]) - - /* 785 - too few initializers for aggregate */ - +e785 - -append(785,[BARR-C:2018 Rule 7.2a]) - -// ========== STATEMENT RULES ========== - -// 8.1 Variable Declarations - - /* 9146 - multiple declarators in a declaration */ - +e9146 - -append(9146,[BARR-C:2018 Rule 8.1a]) - -// 8.2 Conditional Statements - - /* 720 - boolean test of assignment */ - +e720 - -append(720,[BARR-C:2018 Rule 8.2c]) - - /* 820 - boolean test of parenthesized assignment */ - +e820 - -append(820,[BARR-C:2018 Rule 8.2c]) - - /* 9013 - no 'else' at end of 'if ... else if' chain */ - +e9013 - -append(9013,[BARR-C:2018 Rule 8.2d]) - -// 8.3 Switch Statements - - /* 9014 - switch without default */ - +e9014 - -append(9014,[BARR-C:2018 Rule 8.3b]) - - /* 616 - control flow falls through to next case without an intervening comment */ - +e616 - -append(616,[BARR-C:2018 Rule 8.3c]) - -// 8.4 Loops - - /* 850 - for statement index variable modified in body */ - +e850 - -append(850,[BARR-C:2018 Rule 8.4b]) - - /* 716 - infinite loop via while */ - +e716 - -append(716,[BARR-C:2018 Rule 8.4c]) - -// 8.5 Jumps - - /* 9041 - goto appears in block which is not nested in block containing label */ - +e9041 - -append(9041,[BARR-C:2018 Rule 8.5a]) - - /* 9064 - goto references earlier label */ - +e9064 - -append(9064,[BARR-C:2018 Rule 8.5a]) - - /* 586 - function/macro is deprecated */ - -deprecate(function,abort,[BARR-C:2018 Rule 8.5b]) - -deprecate(function,exit,[BARR-C:2018 Rule 8.5b]) - -deprecate(function,longjmp,[BARR-C:2018 Rule 8.5b]) - -deprecate(macro,setjmp,[BARR-C:2018 Rule 8.5b]) - -// 8.6 Equivalence Test - - /* 8522 - variable should appear on RHS of '==' operator */ -//QL -hook(binary_expr, -cond('%[opcode]' == '==' && -//QL '%[walk_lhs_expr.walk_past_paren_cast.set_msg_loc.is_decl_ref_expr]' == 'true' && -//QL '%[walk_rhs_expr.is_constant_expr]' == 'true', -//QL +message(8522, "variable '%[walk_lhs_expr.walk_past_paren_cast.walk_decl.qual_name]' should appear on RHS of '==' operator"))) -//QL +e8522 -//QL -append(8522,[BARR-C:2018 Rule 8.6a]) diff --git a/ports/lint-plus/cstddef b/ports/lint-plus/cstddef deleted file mode 100644 index f2d44f23b..000000000 --- a/ports/lint-plus/cstddef +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef _CSTDDEF_ -#define _CSTDDEF_ - -//lint -save -//lint -e9093 the name is reserved to the compiler -//lint -e9141 global declaration of symbol 'operator new' -//lint -e9215 unnamed parameter for 'non-virtual' function 'operator new' - -namespace std { - using ptrdiff_t = unsigned int; - using size_t = unsigned int; - using max_align_t = unsigned int; - using nullptr_t = decltype(nullptr); - - enum class byte : unsigned char {}; - - // byte type operations - template - constexpr byte& operator<<=(byte& b, IntType shift) noexcept; - template - constexpr byte operator<<(byte b, IntType shift) noexcept; - template - constexpr byte& operator>>=(byte& b, IntType shift) noexcept; - template - constexpr byte operator>>(byte b, IntType shift) noexcept; - constexpr byte& operator|=(byte& l, byte r) noexcept; - constexpr byte operator|(byte l, byte r) noexcept; - constexpr byte& operator&=(byte& l, byte r) noexcept; - constexpr byte operator&(byte l, byte r) noexcept; - constexpr byte& operator^=(byte& l, byte r) noexcept; - constexpr byte operator^(byte l, byte r) noexcept; - constexpr byte operator~(byte b) noexcept; - template - constexpr IntType to_integer(byte b) noexcept; -} - -#define NULL nullptr -//#define offsetof(type, member) ... - -//lint -restore - -#endif // _CSTDDEF_ \ No newline at end of file diff --git a/ports/lint-plus/make.bat b/ports/lint-plus/make.bat deleted file mode 100644 index 4405b1ff0..000000000 --- a/ports/lint-plus/make.bat +++ /dev/null @@ -1,69 +0,0 @@ -@echo off -:: =========================================================================== -:: Batch script for linting QP/C with PC-Lint-Plus2 -:: 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: -:: -:: -:: =========================================================================== -@setlocal - -:: usage of make.bat -@echo Usage: make [16bit] [-d...] -@echo examples: -@echo make -uQ_SPY -uQ_UTEST : use 32bit CPU (default) and undefine Q_SPY/Q_UTEST -@echo make 16bit -uQ_SPY : use 16bit CPU includes and undefine Q_SPY -@echo. - -:: NOTE: adjust to for your installation directory of PC-Lint-Plus -@set PCLP=C:\tools\lint-plus2\windows\pclp64.exe - -if NOT exist "%PCLP%" ( - @echo The PC-Lint-Plus toolset not found. Please adjust make.bat - @goto end -) - -:: set the QP/C++ directory -set QPCPP=..\.. - -if "%1"=="16bit" ( - set LINTFLAGS=-i16bit options.lnt %2 %3 %4 - @echo 16bit CPU -) else ( - set LINTFLAGS=-i32bit options.lnt %1 %2 %3 %4 - @echo 32bit CPU default -) - -:: cleanup -@del *.log - -:: linting ------------------------------------------------------------------- -%PCLP% -os(lint_qf.log) std.lnt %LINTFLAGS% -iqv ..\..\src\qf\*.cpp - -%PCLP% -os(lint_qv.log) std.lnt %LINTFLAGS% -iqv ..\..\src\qv\*.cpp - -%PCLP% -os(lint_qk.log) std.lnt %LINTFLAGS% -iqk ..\..\src\qk\*.cpp - -%PCLP% -os(lint_qxk.log) std.lnt %LINTFLAGS% -iqxk ..\..\src\qxk\*.cpp - -%PCLP% -os(lint_qs.log) std.lnt %LINTFLAGS% -iqv ..\..\src\qs\*.cpp - -:end -@endlocal diff --git a/ports/lint-plus/options.lnt b/ports/lint-plus/options.lnt deleted file mode 100644 index 1aac76749..000000000 --- a/ports/lint-plus/options.lnt +++ /dev/null @@ -1,405 +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: 2024-05-01 -//! @version Last updated for version: 7.3.4 -//! -//! @file -//! @brief PC-Lint-Plus option file for linting QP/C++ source code - -//============================================================================ -// general options --unit_check // perform only subset check (suppresses Global Wrapup) --max_threads=1 // suppress message "no '-max_threads=N' option" -++efreeze(686) // never suppress (see PC-Lint-Plus in Safety-Critical) -//-vf // print names of all source files (for debugging linting) - -// include directories --i. // QP/C++ port includes (see also qk/ and qv/) --i%QPCPP%/include // QP/C++ public includes - -// standards -au-autosar.lnt // AUTOSAR:C++14 -au-ds.lnt // Dan Saks recommendations -cpu.lnt // size/alignment options for the chosen CPU - -// defined macros (might be undefined on command-line with -u) --dQ_SPY --dQ_UTEST - -//============================================================================ -// QP/C++ options for clients -qpcpp.lnt // QP/C++ options - -//============================================================================ -// additional suppression rules for building QP/C source code... - -// general suppression for now... - -// preprocessor directive ... is deprecated. [AUTOSAR Rule A16-0-1] --e586 - -// preprocessor directive encountered in conditionally excluded region -// [AUTOSAR Rule A16-0-1], [AUTOSAR Rule A16-6-1] --e886 - -// friend ... in class --e9435 - -// symbol ... has array type --e9436 - -// enum ... is not a scoped enumeration [AUTOSAR Rule A7-2-3] --e9419 - -// QEP ----------------------------------------------------------------------- - -//! MC++R16-0-4 function-like macro ??? --esym(9026, - Q_ASSERT_INCRIT, - Q_REQUIRE_INCRIT, - Q_ENSURE_INCRIT, - Q_INVARIANT_INCRIT, - Q_ERROR_INCRIT) - -//! M4-D4.9(A) function-like macro -//! @tr{DVP-QP-MC4-D04_09B} --esym(9026, - QHSM_RESERVED_EVT_, - QS_STATE_ENTRY_, - QS_STATE_EXIT_) - -// implicit conversion of enum 'QP::QAsm::QStateRet' to integral type --esym(641, - QP::QAsm::QStateRet) - -// MC++R7-1-2 parameter of function could be pointer to const --esym(818, - QP::QHsm::top) - -// QF ------------------------------------------------------------------------ - -// MC++R16-0-4 function-like macro --esym(9026, - QF_CRIT_ENTRY, - QF_CRIT_EXIT, - QF_MEM_SYS, - QF_MEM_APP, - QF_CONST_CAST_, - QF_SCHED_LOCK_, - QF_SCHED_UNLOCK_, - QF_PTR_RANGE_, - QF_MPOOL_EL, - Q_ACTION_CAST, - QTICKER_CAST_) - -// MC++R16-0-4 function-like macro --esym(9026, - QACTIVE_EQUEUE_WAIT_, - QACTIVE_EQUEUE_SIGNAL_, - QF_EPOOL_INIT_, - QF_EPOOL_EVENT_SIZE_, - QF_EPOOL_GET_, - QF_EPOOL_PUT_) - -// MC++R10-0-6 unparenthesized macro parameter in definition of macro --esym(9022, - QF_CONST_CAST_) - -// [AUTOSAR Rule A5-2-3] cast drops const qualifier --emacro(9005, - QF_CONST_CAST_) - -// M3-R11.3(r) cast from pointer to object type --emacro(9087, - QTICKER_CAST_) - -// suspicious pointer-to-pointer conversion (area too small) --emacro(826, - QTICKER_CAST_) - -// AC++M5-2-9 casting from pointer type to integer type --emacro(9091, - Q_UINTPTR_CAST_) - -// [AC++M12-1-1] non-static data member not initialized by ctor --esym(1401, - QP::QEvt::*, - QP::QActive::*) - -// definition of macro ends in semi-colon --esym(823, - QF_SCHED_STAT_) - -// MC++5-2-8 conversion from integer type (0) to pointer type --emacro(9010, - Q_ACTION_CAST) - - -// M3-R11.8(r) cast drops const qualifier --emacro(9005, - QF_EPOOL_PUT_) - -// M3-D11.5(a) conversion from pointer to void to other pointer type --efunc(9079, - QF_bzero) - -// M3-R17.8(a) function parameter modified --efunc(9044, - QF_LOG2, - QMPool_init) - -// M3-R18.1(r) potential out of bounds pointer access --emacro(661, - QF_EPOOL_EVENT_SIZE_) - -// AR-M5-2-8 conversion from pointer to void to other pointer type --emacro(9079, - QF_EPOOL_GET_) - -// M3-R18.3(r) relational operator <= applied to pointers --emacro(946, - QF_PTR_RANGE_) - -// M3-R8.13(a) parameter of function could be pointer to const --efunc(818, - QP::QActive::start, - QP::QTicker::postLIFO) - -// MC++R0-1-1 statement is unreachable due to unconditional transfer -// of control (assertion) -//-efunc(527, -// QP::QMActive::isIn, -// QP::QMActive::state, -// QP::QMActive::childState) - -// MC++R7-1-1 parameter of function could be declared const --esym(952, - QP::QEQueue::init) - -// AC++M5-2-3: downcast of polymorphic type --efunc(9171, - QP::QActive::post_, - QP::QActive::postLIFO) - -// BARR-C:2018 R 6.2c return statement before end of function --efunc(904, - QP::QActive::post_, - QP::QActive::postLIFO) - -// [AC++M5-2-2]: casting from base class to derived class (QP::QActiveDummy) --efunc(1939, - QP::QActive::post_, - QP::QActive::postLIFO) - -// PCLP-1731: public virtual function (in a class without virtual destructor) --esym(1731, - QP::QTicker::*) - - // PCLP-1933: call to unqualified virtual function from non-static member function --efunc(1933, - QP::QActive::start) - -// PCLP-9079: --efunc(9079, - QP::QF::bzero_, - QP::QTimeEvt::armX, - QP::QTimeEvt::disarm, - QP::QTimeEvt::rearm, - QP::QMPool::init, - QP::QMPool::get, - QP::QMPool::put) - - -// QV ------------------------------------------------------------------------ -// MC++R16-0-4 function-like macro --esym(9026, - QV_CPU_SLEEP) - - -// QK ------------------------------------------------------------------------ - -// MC++R16-0-4 function-like macro --esym(9026, - QK_ISR_CONTEXT_, - QK_ISR_ENTRY, - QK_ISR_EXIT) - - -// QXK ----------------------------------------------------------------------- -// MC++R16-0-4 function-like macro --esym(9026, - QXK_ISR_CONTEXT_, - QXK_CONTEXT_SWITCH_, - QXK_PTR_CAST_, - QXTHREAD_CAST_, - QXTHREAD_EQUEUE_SIGNAL_) - -// MC++R10-0-6 unparenthesized macro parameter in definition of macro --esym(9022, - QXK_PTR_CAST_) - -// MC++R5-2-7 pointer type converted to unrelated pointer --emacro(9176, - Q_STATE_CAST) - -// M3-R11.3(r) cast to pointer to different object type -//-emacro(9087, -// QXK_PTR_CAST_, -// QXTHREAD_CAST_) - -// MC++R5-2-7 pointer type converted to unrelated pointer type --emacro(9176, - QXK_PTR_CAST_) - -// MC++R5-2-3 downcast of polymorphic type ... to type ... --emacro(9171, - QXK_PTR_CAST_) - -// casting from base class 'QP::QActive' to derived class --emacro(1939, - QXK_PTR_CAST_) - -// suspicious pointer-to-pointer conversion (area too small) --emacro(826, - QXK_PTR_CAST_, - QXTHREAD_CAST_) - - -// QS ------------------------------------------------------------------------ -// the following options are needed only when Q_SPY is defined - -// MC++R16-0-4 function-like macro --esym(9026, - QS_CRIT_ENTRY, - QS_CRIT_EXIT, - QS_MEM_SYS, - QS_MEM_APP, - QS_PTR_AT_, - QS_PTR_INC_, - QS_INSERT_BYTE_, - QS_INSERT_ESC_BYTE_, - QS_REC_NUM_) - -// M3-R14.3(r) boolean condition for 'if' always evaluates to 'false' --emacro(774,, - QS_INSERT_BYTE_, - QS_INSERT_ESC_BYTE_, - QS_BEGIN_PRE_, - QS_BEGIN_PRE_) - -// the right operand to << always evaluates to 0 --emacro(845, - QS_BEGIN_PRE_, - QS_BEGIN_PRE_) - -// excessive shift value (precision 3 shifted right by 3) --emacro(572, - QS_BEGIN_PRE_, - QS_BEGIN_PRE_) - -// constant expression evaluates to 0 in 'binary' operation '>>' --emacro(778, - QS_BEGIN_PRE_, - QS_BEGIN_PRE_) - -// constant value used in Boolean context --emacro(506, - QS_BEGIN_PRE_, - QS_BEGIN_PRE_) - -// bitwise operator '>>' applied to signed underlying type [AS-M5-0-21] --emacro(9130, - QS_BEGIN_PRE_, - QS_BEGIN_PRE_) - -// use of c-style cast to void [AS-A5-2-2] --emacro(1954, - QS_END_PRE_) - -// MC++R0-1-9 operator == always evaluates to true --emacro(948, - QS_BEGIN_PRE_) - -// MC++R0-1-1, MC++R0-1-2, MC++R0-1-9 -// left operand to '||' always evaluates to 'true' --emacro(944, - QS_BEGIN_PRE_) - -// MC++R5-2-9 casting from pointer type to integer type --emacro(9091, - QS_OBJ_PRE_, - QS_FUN_PRE_) - -// M3-R11.6(r) explicit cast from 'void *volatile' to 'uint32_t' -//-emacro(923, -// QS_OBJ_PRE_, -// QS_FUN_PRE_) - -// M3-R11.1(4) conversion between pointer to function and differing type -//-emacro(9074, -// QS_FUN_PRE_) - -// definition of macro ends in semi-colon --esym(823, - QS_CRIT_STAT, - QS_BEGIN_PRE_) - -// union initialization --efunc(708, - QS_f64_fmt_) - -// M3-R19.2(a) union declared --efunc(9018, - QS_f32_fmt_, - QS_f64_fmt_) - -// MC++R10-0-6 unparenthesized macro parameter in definition of macro --esym(9022, - QS_TEST_PROBE, - QS_TEST_PROBE_ID) - -// AR M5-0-10 the result of the ~ operator applied to an object with an -// underlying type of 'unsigned char' must be cast to 'unsigned char' -// in this context --efunc(9126, - QP::QS::glbFilter_, - QP::QS::locFilter_) - -// don't report problems within QS_target_info_() function --efunc(9130, - QP::QS_target_info_) --efunc(9114, - QP::QS_target_info_) --efunc(9117, - QP::QS_target_info_) --efunc(9125, - QP::QS_target_info_) --efunc(9112, - QP::QS_target_info_) --efunc(9128, - QP::QS_target_info_) --efunc(737, - QP::QS_target_info_) - diff --git a/ports/lint-plus/qk/qp_port.hpp b/ports/lint-plus/qk/qp_port.hpp deleted file mode 100644 index 89d9a211f..000000000 --- a/ports/lint-plus/qk/qp_port.hpp +++ /dev/null @@ -1,101 +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 qpcpp_7_3_0 -//! -//! @file -//! @brief QP/C++ port for QK kernel, Generic C++11 - -#ifndef QP_PORT_HPP_ -#define QP_PORT_HPP_ - -#include // Exact-width types. C++11 Standard - -#ifdef QP_CONFIG -#include "qp_config.hpp" // external QP configuration -#endif - -// no-return function specifier (C++11 Standard) -#define Q_NORETURN [[ noreturn ]] void - -// QF configuration for QK -- data members of the QActive class... - -// QK event-queue used for AOs -#define QACTIVE_EQUEUE_TYPE QEQueue - -// QF "thread" type used to store the MPU settings in the AO -#define QACTIVE_THREAD_TYPE void const * - -// interrupt disabling mechanism -#define QF_INT_DISABLE() intDisable() -#define QF_INT_ENABLE() intEnable() - -// QF critical section mechanism -#define QF_CRIT_STAT std::uint32_t crit_stat_; -#define QF_CRIT_ENTRY() (crit_stat_ = critEntry()) -#define QF_CRIT_EXIT() critExit(crit_stat_) - -// Check if the code executes in the ISR context -#define QK_ISR_CONTEXT_() (QK_get_IPSR() != 0U) - -// Define the ISR entry sequence -#define QK_ISR_ENTRY() (static_cast(0)) - -// Define the ISR exit sequence -#define QK_ISR_EXIT() \ -do { \ - QF_INT_DISABLE(); \ - --QK_priv_.intNest; \ - if (QK_priv_.intNest == 0U) { \ - if (QK_sched_() != 0U) { \ - QK_activate_(); \ - } \ - } \ - QF_INT_ENABLE(); \ -} while (false) - -extern "C" { - -void intDisable(void); -void intEnable(void); -std::uint32_t critEntry(void); -void critExit(std::uint32_t stat); -std::uint32_t QK_get_IPSR(void); - -} // extern "C" - -// include files ------------------------------------------------------------- -#include "qequeue.hpp" // QK kernel uses the native QP event queue -#include "qmpool.hpp" // QK kernel uses the native QP memory pool -#include "qp.hpp" // QP framework -#include "qk.hpp" // QK kernel - -#endif // QP_PORT_HPP_ - diff --git a/ports/lint-plus/qpcpp.lnt b/ports/lint-plus/qpcpp.lnt deleted file mode 100644 index b9aa5005d..000000000 --- a/ports/lint-plus/qpcpp.lnt +++ /dev/null @@ -1,458 +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: 2024-02-18 -//! @version Last updated for version: 7.3.3 -//! -//! @file -//! @brief PC-Lint-Plus option file for linting QP/C++ __Applications__ - -//---------------------------------------------------------------------------- -// globally suppress the following warnings: --e546 // explicitly taking address of function --e717 // monocarpic do-while used to group statements --e1756 // variable has 'static' storage duration and non-POD type --e3412 // class has virtual functions but non-virtual destructor - -// Assertions ---------------------------------------------------------------- - -// give Q_onError() the semantics of "exit" --function(exit, - Q_onError) - -// C-style array type [AUTOSAR Rule A18-1-1] --esym(9436, - QP::versionStr) - -// AC++M16-3-2 function-like macro --esym(9026, - Q_DEFINE_THIS_MODULE, - Q_ASSERT_STATIC, - Q_ASSERT, - Q_ASSERT_ID, - Q_ERROR, - Q_ERROR_ID, - Q_REQUIRE, - Q_REQUIRE_ID, - Q_ENSURE, - Q_ENSURE_ID, - Q_INVARIANT, - Q_INVARIANT_ID, - Q_DIM) - -// use of c-style cast to void [AS-A5-2-2] --emacro(1954, - Q_ASSERT, - Q_ASSERT_ID, - Q_ERROR, - Q_ERROR_ID, - Q_REQUIRE, - Q_REQUIRE_ID, - Q_ENSURE, - Q_ENSURE_ID, - Q_INVARIANT, - Q_INVARIANT_ID, - Q_ASSERT_INCRIT) - -// MC++R10-0-6 unparenthesized macro parameter in definition of macro --esym(9022, - Q_DEFINE_THIS_MODULE) - -// definition of macro ends in semi-colon --esym(823, - Q_DEFINE_THIS_FILE, - Q_DEFINE_THIS_MODULE) - -// AC++M16-3-2 function-like macro --esym(9026, - Q_UNUSED_PAR, - Q_DIM, - Q_UINT2PTR_CAST, - Q_UINTPTR_CAST_) - -// MC++R5-2-4 use of c-style cast --emacro(1924, - Q_ASSERT, - Q_ASSERT_ID, - Q_ERROR, - Q_ERROR_ID) - - -// QEP ----------------------------------------------------------------------- - -// MC++R7-3-1 global declaration of symbol --esym(9141, - char_t, - int_t, - enum_t, - float32_t, - float64_t) - -// AUTOSAR Rule A3-3-2 non-private data member within a non-POD structure -// NOTE: public access needed for extern "C" functions --esym(9150, - QP::QAsmAttr::*, - QP::QAsm::*) - -// AC++M16-3-2 function-like macro --esym(9026, - INIT, - DISPATCH, - Q_STATE_DECL, - Q_STATE_DEF, - QM_STATE_DECL, - QM_STATE_DEF, - QM_SM_STATE_DECL, - QM_ACTION_DECL, - QM_ACTION_DEF, - QHSM_INIT, - QHSM_DISPATCH, - Q_TRAN, - Q_TRAN_HIST, - Q_SUPER, - Q_HANDLED, - Q_UNHANDLED, - QM_ENTRY, - QM_EXIT, - QM_SM_EXIT, - QM_TRAN, - QM_TRAN_INIT, - QM_TRAN_HIST, - QM_TRAN_EP, - QM_TRAN_XP, - QM_SUPER, - QM_SUPER_SUB, - QM_HANDLED, - QM_UNHANDLED, - Q_HSM_UPCAST, - Q_EVT_CAST, - Q_STATE_CAST, - Q_UINT2PTR_CAST) - -// MC++R5-2-8 conversion from pointer to other pointer type --emacro(9079, - Q_EVT_CAST) - -// MC++R5-2-2 casting from base class 'QP::QEvt' to derived class --emacro(1939, - Q_EVT_CAST) - -// MC++R10-0-6 unparenthesized macro parameter 'class_' in definition of macro --esym(9022, - Q_EVT_CAST, - Q_UINT2PTR_CAST, - Q_STATE_DECL, - Q_STATE_DEF, - QM_STATE_DECL, - QM_STATE_DEF, - QM_SM_STATE_DECL, - QM_ACTION_DECL, - QM_ACTION_DEF, - QEP_TRIG_, - QEP_ENTER_, - QEP_EXIT_) - -// MC++16-3-1 multiple use of stringize/pasting operators in definition of macro --esym(9023, - Q_STATE_DECL, - Q_STATE_DEF, - QM_STATE_DECL, - QM_STATE_DEF, - QM_SM_STATE_DECL, - QM_ACTION_DEF) - -// AC++M16-3-2 stringize operator used in definition of function-like macro --esym(9024, - Q_STATE_DECL, - Q_STATE_DEF, - QM_STATE_DECL, - QM_STATE_DEF, - QM_SM_STATE_DECL, - QM_ACTION_DECL, - QM_ACTION_DEF) - -// MC++R5-2-8 conversion from pointer to void to other pointer type --emacro(9079, - Q_STATE_DEF, - QM_STATE_DEF, - QM_ACTION_DEF) - - // MC++R9-3-3 member function could be made const --emacro(1762, - Q_STATE_DEF, - QM_STATE_DEF) - -// MC++9-5-1 union declared --esym(9018, - QP::QAsmAttr) - -// MC++5-2-8 conversion from integer type (0) to pointer type --emacro(9010, - Q_STATE_CAST) - -// public virtual function 'QP::QHsm::...' --esym(1731, - QP::QHsm::*, - QP::QMsm::*) - - -// QF ------------------------------------------------------------------------ - -// AUTOSAR Rule A3-3-2 non-private data member within a non-POD structure -// NOTE: public access needed for extern "C" functions --esym(9150, - QP::QF::QF_Attr::*) - -// AC++M16-3-2 function-like macro --esym(9026, - POST, - POST_X, - PUBLISH, - TICK_X, - TICK, - TRIG, - QF_INT_DISABLE, - QF_INT_ENABLE, - QF_CRIT_EXIT_NOP, - QF_LOG2, - Q_PRIO, - Q_NEW, - Q_NEW_X, - Q_NEW_REF, - Q_DELETE_REF, - QF_INT_DISABLE, - QF_INT_ENABLE, - QF_MPOOL_EL) - -// MC++R0-3-2 ignoring return value of function --emacro(534, - POST) - -// [AUTOSAR Rule M17-0-2] the name xxx is reserved to the compiler --esym(9093, - remove) // QPrioSet::remove() - -// MC++R5-2-7 pointer type converted to unrelated pointer type --emacro(9176, - QF_QMACTIVE_TO_QMSM_CAST_, - QF_QMACTIVE_TO_QMSM_CONST_CAST_) - -// MC++R5-2-2 casting from base class 'QP::QEvt' to derived class --emacro(1939, - Q_NEW, - Q_NEW_X) - -// MC++R10-0-6 unparenthesized macro parameter in definition of macro --esym(9022, - Q_NEW, - Q_NEW_X, - Q_NEW_REF) - - -// QK ------------------------------------------------------------------------ - -// AC++M16-3-2 function-like macro --esym(9026, - QK_ISR_ENTRY, - QK_ISR_EXIT) - -// AC++M7-3-1 global declaration of symbol --esym(9141, - QK_Attr) - -// MC++R11-0-1 non-private data member within a non-POD structure -// NOTE: public access needed for extern "C" functions --esym(9150, - QK_Attr::*) - - -// QXK ----------------------------------------------------------------------- -// MC++R16-0-4 function-like macro --esym(9026, - QXK_ISR_ENTRY, - QXK_ISR_EXIT, - QXK_TLS) - -// MC++R7-3-1 global declaration of symbol --esym(9141, - QXK_Attr) - -// MC++R10-0-6 unparenthesized macro parameter in definition of macro --esym(9022, - QXK_TLS) - -// MC++R5-2-8 conversion from pointer to void to other pointer type --emacro(9079, - QXK_PTR_CAST_) - -// MC++R5-2-2 casting from base class to derived class --emacro(1939, - QXTHREAD_CAST_) - -// MC++R5-2-3 downcast of polymorphic type --emacro(9171, - QXTHREAD_CAST_) - -// [AUTOSAR Rule M17-0-2] the name 'signal' is reserved to the compiler --esym(9093, - signal) - -// public virtual function 'QP::QXThread::...' --esym(1731, - QP::QXThread::*) - -// [AUTOSAR Rule M8-4-2] parameter of function has different name than -// overridden function --esym(9272, - QP::QXMutex::init*) - -// function xxx matches the name of a standard library function --esym(8502, - signal) // QXSemaphore::signal() - - -// QS ------------------------------------------------------------------------ - -// AC++M16-3-2 function-like macro --esym(9026, - QS_INIT, - QS_EXIT, - QS_DUMP, - QS_RESET, - QS_GLB_FILTER, - QS_LOC_FILTER, - QS_FILTER_AP_OBJ, - QS_GET_BYTE, - QS_GET_BLOCK, - QS_BEGIN_ID, - QS_END, - QS_BEGIN_INCRIT, - QS_END_INCRIT, - QS_QF_CRIT_ENTRY, - QS_QF_CRIT_EXIT, - QS_QF_ISR_ENTRY, - QS_QF_ISR_EXIT, - QS_ONLY, - QS_I8, - QS_U8, - QS_I16, - QS_U16, - QS_I32, - QS_I64, - QS_U32, - QS_F32, - QS_F64, - QS_U64, - QS_U32_HEX, - QS_STR, - QS_OBJ, - QS_FUN, - QS_SIG_DICTIONARY, - QS_OBJ_DICTIONARY, - QS_OBJ_ARR_DICTIONARY, - QS_FUN_DICTIONARY, - QS_USR_DICTIONARY, - QS_ENUM_DICTIONARY, - QS_ASSERTION, - QS_FLUSH, - QS_MEM, - QS_ENUM, - QS_SIG, - QS_PTR_AT_, - QS_RX_PUT, - QS_OUTPUT, - QS_RX_INPUT, - QS_TEST_PAUSE, - QS_TEST_PROBE_DEF, - QS_TEST_PROBE, - QS_TEST_PROBE_ID) - -// AC++M16-3-2 function-like macro --esym(9026, - QS_GLB_CHECK_, - QS_LOC_CHECK_, - QS_BEGIN_PRE_, - QS_END_PRE_, - QS_BEGIN_PRE_, - QS_END_PRE_, - QS_U8_PRE_, - QS_2U8_PRE_, - QS_U16_PRE_, - QS_U32_PRE_, - QS_STR_PRE_, - QS_TIME_PRE_, - QS_SIG_PRE_, - QS_EVS_PRE_, - QS_OBJ_PRE_, - QS_FUN_PRE_, - QS_EQC_PRE_, - QS_MPC_PRE_, - QS_MPS_PRE_, - QS_TEC_PRE_) - -// AC++M16-3-2 function-like macro --esym(9026, - QS_REC_DONE) - -// definition of macro ends in semi-colon --esym(823, - QS_TEST_PROBE_DEF) - -// M3-R11.1(r) conversion between pointer to function type --emacro(9074, - QS_FUN_DICTIONARY, - QS_TEST_PROBE_DEF) - -// AC++M16-3-2 stringize operator used in definition of function-like macro --esym(9024, - QS_OBJ_DICTIONARY, - QS_OBJ_ARR_DICTIONARY, - QS_FUN_DICTIONARY, - QS_SIG_DICTIONARY, - QS_USR_DICTIONARY, - QS_ENUM_DICTIONARY) - -// M3-R10.3(r) cannot assign enum to different essential type --emacro(9034, - QS_SIG_DICTIONARY) - -// implicit conversion of enum to integral type 'int' --emacro(641, - QS_SIG_DICTIONARY) - -// MC++R11-0-1 non-private data member within a non-POD structure --esym(9150, - QP::QEvt::*, - QP::QActive::*, - QP::QF::Attr::*, - QP::QS::QSrxPriv::*) - -// MC++9-5-1 union declared --esym(9018, - F32Rep, - F64Rep, - U32Rep, - TCast, - QP::QS::RxAttr::Variant) - diff --git a/ports/lint-plus/qv/qp_port.hpp b/ports/lint-plus/qv/qp_port.hpp deleted file mode 100644 index 9c7c7be26..000000000 --- a/ports/lint-plus/qv/qp_port.hpp +++ /dev/null @@ -1,89 +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 qpcpp_7_3_0 -//! -//! @file -//! @brief QP/C++ port for QV kernel, Generic C++ - -#ifndef QP_PORT_HPP_ -#define QP_PORT_HPP_ - -#include // Exact-width types. C++11 Standard - -#ifdef QP_CONFIG -#include "qp_config.hpp" // external QP configuration -#endif - -// no-return function specifier (C++11 Standard) -#define Q_NORETURN [[ noreturn ]] void - -// QF configuration for QV -- data members of the QActive class... - -// QV event-queue used for AOs -#define QACTIVE_EQUEUE_TYPE QEQueue - -// QF "thread" type used to store the MPU settings in the AO -#define QACTIVE_THREAD_TYPE void const * - -// interrupt disabling mechanism -#define QF_INT_DISABLE() intDisable() -#define QF_INT_ENABLE() intEnable() - -// QF critical section mechanism -#define QF_CRIT_STAT std::uint32_t crit_stat_; -#define QF_CRIT_ENTRY() (crit_stat_ = critEntry()) -#define QF_CRIT_EXIT() critExit(crit_stat_) - -#define QV_CPU_SLEEP() \ -do { \ - __disable_interrupt(); \ - QF_INT_ENABLE(); \ - __WFI(); \ - __enable_interrupt(); \ -} while (false) - -extern "C" { - -void intDisable(void); -void intEnable(void); -std::uint32_t critEntry(void); -void critExit(std::uint32_t stat); - -} // extern "C" - -// include files ------------------------------------------------------------- -#include "qequeue.hpp" // QV kernel uses the native QP event queue -#include "qmpool.hpp" // QV kernel uses the native QP memory pool -#include "qp.hpp" // QP framework -#include "qv.hpp" // QV kernel - -#endif // QP_PORT_HPP_ - diff --git a/ports/lint-plus/qxk/qp_port.hpp b/ports/lint-plus/qxk/qp_port.hpp deleted file mode 100644 index 3211158c3..000000000 --- a/ports/lint-plus/qxk/qp_port.hpp +++ /dev/null @@ -1,104 +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 qpcpp_7_3_0 -//! -//! @file -//! @brief QP/C++ port for QXK kernel, Generic C++ - -#ifndef QP_PORT_HPP_ -#define QP_PORT_HPP_ - -#include // Exact-width types. C++11 Standard - -#ifdef QP_CONFIG -#include "qp_config.hpp" // external QP configuration -#endif - -// no-return function specifier (C++11 Standard) -#define Q_NORETURN [[ noreturn ]] void - -// QF configuration for QXK -- data members of the QActive class... - -// QXK event-queue type used for AOs and eXtended threads. -#define QACTIVE_EQUEUE_TYPE QEQueue - -// QXK OS-Object type used for the private stack pointer for eXtended threads. -// (The private stack pointer is NULL for basic-threads). -#define QACTIVE_OS_OBJ_TYPE void* - -// QF "thread" type used to store the MPU settings in the AO -#define QACTIVE_THREAD_TYPE void const * - -// interrupt disabling mechanism -#define QF_INT_DISABLE() intDisable() -#define QF_INT_ENABLE() intEnable() - -// QF critical section mechanism -#define QF_CRIT_STAT std::uint32_t crit_stat_; -#define QF_CRIT_ENTRY() (crit_stat_ = critEntry()) -#define QF_CRIT_EXIT() critExit(crit_stat_) - -// Check if the code executes in the ISR context -#define QXK_ISR_CONTEXT_() (QXK_get_IPSR() != 0U) - -// Define the ISR entry sequence -#define QXK_ISR_ENTRY() (static_cast(0)) - -// Define the ISR exit sequence -#define QXK_ISR_EXIT() do { \ - QF_INT_DISABLE(); \ - if (QXK_sched_() != 0U) { \ - *Q_UINT2PTR_CAST(uint32_t, 0xE000ED04U) = (1U << 28U);\ - } \ - QF_INT_ENABLE(); \ -} while (false) - -#define QXK_CONTEXT_SWITCH_() (QXK_trigPendSV()) - -extern "C" { - -void intDisable(void); -void intEnable(void); -std::uint32_t critEntry(void); -void critExit(std::uint32_t stat); -std::uint32_t QXK_get_IPSR(void); -void QXK_trigPendSV(void); - -} // extern "C" - -// include files ------------------------------------------------------------- -#include "qequeue.hpp" // QK kernel uses the native QP event queue -#include "qmpool.hpp" // QK kernel uses the native QP memory pool -#include "qp.hpp" // QP framework -#include "qxk.hpp" // QXK kernel - -#endif // QP_PORT_HPP_ - diff --git a/ports/lint-plus/std.lnt b/ports/lint-plus/std.lnt deleted file mode 100644 index 0b77cdb5c..000000000 --- a/ports/lint-plus/std.lnt +++ /dev/null @@ -1,45 +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-08 -//! @version Last updated for version: 7.3.0 -//! -//! @file -//! @brief PC-Lint-Plus standard option file - -// message formatting options... --hF1 // output: a single line -+ffn // use full path names -//-"format=%(\q%f\q %l %C%) %t %n: %m" -//-width(0,0) // do not break lines --width(120,4) // break lines after 99 characters with 4 characters indent -+flm // make sure no foreign includes change the format - -+rw(inline, entry) - --zero(99) // don't stop because of warnings --passes(2) // make two passes (for better error messages) --restore_at_end // don't let -e options bleed to other files --summary() // produce a summary of all produced messages - diff --git a/ports/lint-plus2/16bit/cpu.lnt b/ports/lint-plus2/16bit/cpu.lnt deleted file mode 100644 index d5cc76b10..000000000 --- a/ports/lint-plus2/16bit/cpu.lnt +++ /dev/null @@ -1,6 +0,0 @@ -// Size Options for 16bit CPU (e.g., MSP430) --si2 -sl4 -sll8 -ss2 -sw2 -sp2 -sf4 -sd8 -sld8 - -// Alignment options for 16bit CPU --ai2 -al2 -all2 -as2 -af4 -ad8 -ald8 - diff --git a/ports/lint-plus2/16bit/cstdint b/ports/lint-plus2/16bit/cstdint deleted file mode 100644 index 0566fa50d..000000000 --- a/ports/lint-plus2/16bit/cstdint +++ /dev/null @@ -1,39 +0,0 @@ -/// @file cstdint -/// This is an emulation of a Standard C++ Library header for 16bit CPUs, -/// like MSP430. - -#ifndef _GLIBCXX_CSTDINT -#define _GLIBCXX_CSTDINT - -//lint -save -//lint -e9093 AUTOSAR:M17-0-2 the name ... is reserved to the compiler -//lint -e9145 AUTOSAR:M7-3-6 9145: using declaration in header - -namespace std { - - using int8_t = signed char; //!< exact-width 8-bit signed int - using int16_t = signed int; //!< exact-width 16-bit signed int - using int32_t = signed long int; //!< exact-width 32-bit signed int - using int64_t = signed long long; //!< exact-width 64-bit signed int - - using uint8_t = unsigned char; //!< exact-width 8-bit unsigned int - using uint16_t = unsigned int; //!< exact-width 16-bit unsigned int - using uint32_t = unsigned long int; //!< exact-width 32-bit unsigned int - using uint64_t = unsigned long long; //!< exact-width 64-bit unsigned int - - // Fastest minimum-width types. WG14/N843 C99 Standard, Section 7.18.1.3 - using int_fast8_t = signed int; //!< fast at-least 8-bit signed int - using uint_fast8_t = unsigned int; //!< fast at-least 8-bit unsigned int - using int_fast16_t = signed int; //!< fast at-least 16-bit signed int - using uint_fast16_t = unsigned int; //!< fast at-least 16-bit unsigned int - using int_fast32_t = signed long; //!< fast at-least 32-bit signed int - using uint_fast32_t = unsigned long; //!< fast at-least 32-bit unsigned int - - // unsigned integer type capable of holding a pointer to void. - using uintptr_t = unsigned; //!< unsigned int capable of holding void* - -} // namespace std - -//lint -restore - -#endif // _GLIBCXX_CSTDINT diff --git a/ports/lint-plus2/16bit/qs_port.hpp b/ports/lint-plus2/16bit/qs_port.hpp deleted file mode 100644 index 1bae19a70..000000000 --- a/ports/lint-plus2/16bit/qs_port.hpp +++ /dev/null @@ -1,57 +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: 2024-06-06 -//! @version Last updated for: @ref qpcpp_7_4_0 -//! -//! @file -//! @brief QS/C++ port to a 16-bit CPU, generic C++11 compiler - -#ifndef QS_PORT_HPP_ -#define QS_PORT_HPP_ - -// object pointer size in bytes -#define QS_OBJ_PTR_SIZE 2U - -// function pointer size in bytes -#define QS_FUN_PTR_SIZE 2U - -//============================================================================ -// 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.hpp" -// *before* "qs.hpp". -#ifndef QP_PORT_HPP_ -#include "qp_port.hpp" // use QS with QP -#endif - -#include "qs.hpp" // QS platform-independent public interface - -#endif // QS_PORT_HPP_ diff --git a/ports/lint-plus2/32bit/cpu.lnt b/ports/lint-plus2/32bit/cpu.lnt deleted file mode 100644 index 9281e892b..000000000 --- a/ports/lint-plus2/32bit/cpu.lnt +++ /dev/null @@ -1,3 +0,0 @@ -// Size Options for 32bit CPU (e.g., ARM Cortex-M) --si4 -sl4 -sll8 -ss2 -sw4 -sp4 -sf4 -sd8 -sld8 - diff --git a/ports/lint-plus2/32bit/cstdint b/ports/lint-plus2/32bit/cstdint deleted file mode 100644 index b372ca328..000000000 --- a/ports/lint-plus2/32bit/cstdint +++ /dev/null @@ -1,39 +0,0 @@ -/// @file cstdint -/// This is an emulation of a Standard C++ Library header for 32bit CPUs, -/// like ARM Cortex-M. - -#ifndef _GLIBCXX_CSTDINT -#define _GLIBCXX_CSTDINT - -//lint -save -//lint -e9093 AUTOSAR:M17-0-2 the name ... is reserved to the compiler -//lint -e9145 AUTOSAR:M7-3-6 9145: using declaration in header - -namespace std { - - using int8_t = signed char; //!< exact-width 8-bit signed int - using int16_t = signed short; //!< exact-width 16-bit signed int - using int32_t = signed long; //!< exact-width 32-bit signed int - using int64_t = signed long long; //!< exact-width 64-bit signed int - - using uint8_t = unsigned char; //!< exact-width 8-bit unsigned int - using uint16_t = unsigned short; //!< exact-width 16-bit unsigned int - using uint32_t = unsigned long; //!< exact-width 32-bit unsigned int - using uint64_t = unsigned long long; //!< exact-width 64-bit unsigned int - - // Fastest minimum-width types. WG14/N843 C99 Standard, Section 7.18.1.3 - using int_fast8_t = signed int; //!< fast at-least 8-bit signed int - using uint_fast8_t = unsigned int; //!< fast at-least 8-bit unsigned int - using int_fast16_t = signed int; //!< fast at-least 16-bit signed int - using uint_fast16_t = unsigned int; //!< fast at-least 16-bit unsigned int - using int_fast32_t = signed long; //!< fast at-least 32-bit signed int - using uint_fast32_t = unsigned long; //!< fast at-least 32-bit unsigned int - - // unsigned integer type capable of holding a pointer to void. - using uintptr_t = unsigned; //!< unsigned int capable of holding void* - -} // namespace std - -//lint -restore - -#endif // _GLIBCXX_CSTDINT diff --git a/ports/lint-plus2/32bit/qs_port.hpp b/ports/lint-plus2/32bit/qs_port.hpp deleted file mode 100644 index 4ddb938b5..000000000 --- a/ports/lint-plus2/32bit/qs_port.hpp +++ /dev/null @@ -1,57 +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: 2024-06-06 -//! @version Last updated for: @ref qpcpp_7_4_0 -//! -//! @file -//! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler - -#ifndef QS_PORT_HPP_ -#define QS_PORT_HPP_ - -// 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.hpp" -// *before* "qs.hpp". -#ifndef QP_PORT_HPP_ -#include "qp_port.hpp" // use QS with QP -#endif - -#include "qs.hpp" // QS platform-independent public interface - -#endif // QS_PORT_HPP_ diff --git a/ports/lint-plus2/au-ds.lnt b/ports/lint-plus2/au-ds.lnt deleted file mode 100644 index 38fcd6736..000000000 --- a/ports/lint-plus2/au-ds.lnt +++ /dev/null @@ -1,21 +0,0 @@ -// au-ds.lnt -- Author options - Dan Saks - -/* - This options file can be used to explicitly activate those - checks advocated by Dan Saks in his series of presentations on - "C++ Gotchas". - - You can use this file directly when linting your programs as in: - - lin au-ds files - - */ - -+fsc // consider string constants as const char * -+e1933 // turn on "virtual call from member detection" - -// The rationale for the following two options are fully described -// in Dan Saks' article "const T vs. T const". Visit his web site -// at www.dansaks.com and click "Published Articles". -// --fqb +e963 // require T const rather than const T diff --git a/ports/lint-plus2/cstddef b/ports/lint-plus2/cstddef deleted file mode 100644 index f2d44f23b..000000000 --- a/ports/lint-plus2/cstddef +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef _CSTDDEF_ -#define _CSTDDEF_ - -//lint -save -//lint -e9093 the name is reserved to the compiler -//lint -e9141 global declaration of symbol 'operator new' -//lint -e9215 unnamed parameter for 'non-virtual' function 'operator new' - -namespace std { - using ptrdiff_t = unsigned int; - using size_t = unsigned int; - using max_align_t = unsigned int; - using nullptr_t = decltype(nullptr); - - enum class byte : unsigned char {}; - - // byte type operations - template - constexpr byte& operator<<=(byte& b, IntType shift) noexcept; - template - constexpr byte operator<<(byte b, IntType shift) noexcept; - template - constexpr byte& operator>>=(byte& b, IntType shift) noexcept; - template - constexpr byte operator>>(byte b, IntType shift) noexcept; - constexpr byte& operator|=(byte& l, byte r) noexcept; - constexpr byte operator|(byte l, byte r) noexcept; - constexpr byte& operator&=(byte& l, byte r) noexcept; - constexpr byte operator&(byte l, byte r) noexcept; - constexpr byte& operator^=(byte& l, byte r) noexcept; - constexpr byte operator^(byte l, byte r) noexcept; - constexpr byte operator~(byte b) noexcept; - template - constexpr IntType to_integer(byte b) noexcept; -} - -#define NULL nullptr -//#define offsetof(type, member) ... - -//lint -restore - -#endif // _CSTDDEF_ \ No newline at end of file diff --git a/ports/lint-plus2/make.bat b/ports/lint-plus2/make.bat deleted file mode 100644 index fb85591f2..000000000 --- a/ports/lint-plus2/make.bat +++ /dev/null @@ -1,70 +0,0 @@ -@echo off -:: =========================================================================== -:: Batch script for linting QP/C with PC-Lint-Plus2 -:: 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: -:: -:: -:: =========================================================================== -@setlocal - -:: usage of make.bat -@echo Usage: make [16bit] [-u...] files -@echo examples: -@echo make -uQ_SPY -uQ_UTEST : use 32bit CPU (default) and undefine Q_SPY/Q_UTEST -@echo make 16bit -uQ_SPY : use 16bit CPU includes and undefine Q_SPY -@echo. - -:: NOTE: adjust to for your installation directory of PC-Lint-Plus -@set PCLP=C:\tools\lint-plus2.2-beta\windows -@set PCLP_EXE=%PCLP%\pclp64.exe - -if NOT exist "%PCLP%" ( - @echo The PC-Lint-Plus toolset not found. Please adjust make.bat - @goto end -) - -:: set the QP/C++ directory -set QPCPP=..\.. - -if "%1"=="16bit" ( - set LINTFLAGS=-i16bit options.lnt %1 %2 %3 %4 - @echo 16bit CPU -) else ( - set LINTFLAGS=-i32bit options.lnt %1 %2 %3 %4 - @echo 32bit CPU default -) - -:: cleanup -@del *.log - -:: linting ------------------------------------------------------------------- -%PCLP_EXE% -os(lint_qf.log) std.lnt %LINTFLAGS% -iqv ..\..\src\qf\*.cpp - -%PCLP_EXE% -os(lint_qv.log) std.lnt %LINTFLAGS% -iqv ..\..\src\qv\*.cpp - -%PCLP_EXE% -os(lint_qk.log) std.lnt %LINTFLAGS% -iqk ..\..\src\qk\*.cpp - -%PCLP_EXE% -os(lint_qxk.log) std.lnt %LINTFLAGS% -iqxk ..\..\src\qxk\*.cpp - -%PCLP_EXE% -os(lint_qs.log) std.lnt %LINTFLAGS% -iqv ..\..\src\qs\*.cpp - -:end -@endlocal diff --git a/ports/lint-plus2/options.lnt b/ports/lint-plus2/options.lnt deleted file mode 100644 index adfd8c618..000000000 --- a/ports/lint-plus2/options.lnt +++ /dev/null @@ -1,406 +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: 2024-05-01 -//! @version Last updated for version: 7.3.4 -//! -//! @file -//! @brief PC-Lint-Plus option file for linting QP/C++ source code - -//============================================================================ -// general options --unit_check // perform only subset check (suppresses Global Wrapup) --max_threads=1 // suppress message "no '-max_threads=N' option" -++efreeze(686) // never suppress (see PC-Lint-Plus in Safety-Critical) -//-vf // print names of all source files (for debugging linting) - -// include directories --i%PCLP%/lnt // PC-Lint-Plus standard .lnt files --i. // QP/C++ port includes (see also qk/ and qv/) --i%QPCPP%/include // QP/C++ public includes - -// standards -au-autosar.lnt // AUTOSAR:C++14 -au-ds.lnt // Dan Saks recommendations -cpu.lnt // size/alignment options for the chosen CPU - -// defined macros (might be undefined on command-line with -u) --dQ_SPY --dQ_UTEST - -//============================================================================ -// QP/C++ options for clients -qpcpp.lnt // QP/C++ options - -//============================================================================ -// additional suppression rules for building QP/C source code... - -// general suppression for now... - -// preprocessor directive ... is deprecated. [AUTOSAR Rule A16-0-1] --e586 - -// preprocessor directive encountered in conditionally excluded region -// [AUTOSAR Rule A16-0-1], [AUTOSAR Rule A16-6-1] --e886 - -// friend ... in class --e9435 - -// symbol ... has array type --e9436 - -// enum ... is not a scoped enumeration [AUTOSAR Rule A7-2-3] --e9419 - -// QEP ----------------------------------------------------------------------- - -//! MC++R16-0-4 function-like macro ??? --esym(9026, - Q_ASSERT_INCRIT, - Q_REQUIRE_INCRIT, - Q_ENSURE_INCRIT, - Q_INVARIANT_INCRIT, - Q_ERROR_INCRIT) - -//! M4-D4.9(A) function-like macro -//! @tr{DVP-QP-MC4-D04_09B} --esym(9026, - QHSM_RESERVED_EVT_, - QS_STATE_ENTRY_, - QS_STATE_EXIT_) - -// implicit conversion of enum 'QP::QAsm::QStateRet' to integral type --esym(641, - QP::QAsm::QStateRet) - -// MC++R7-1-2 parameter of function could be pointer to const --esym(818, - QP::QHsm::top) - -// QF ------------------------------------------------------------------------ - -// MC++R16-0-4 function-like macro --esym(9026, - QF_CRIT_ENTRY, - QF_CRIT_EXIT, - QF_MEM_SYS, - QF_MEM_APP, - QF_CONST_CAST_, - QF_SCHED_LOCK_, - QF_SCHED_UNLOCK_, - QF_PTR_RANGE_, - QF_MPOOL_EL, - Q_ACTION_CAST, - QTICKER_CAST_) - -// MC++R16-0-4 function-like macro --esym(9026, - QACTIVE_EQUEUE_WAIT_, - QACTIVE_EQUEUE_SIGNAL_, - QF_EPOOL_INIT_, - QF_EPOOL_EVENT_SIZE_, - QF_EPOOL_GET_, - QF_EPOOL_PUT_) - -// MC++R10-0-6 unparenthesized macro parameter in definition of macro --esym(9022, - QF_CONST_CAST_) - -// [AUTOSAR Rule A5-2-3] cast drops const qualifier --emacro(9005, - QF_CONST_CAST_) - -// M3-R11.3(r) cast from pointer to object type --emacro(9087, - QTICKER_CAST_) - -// suspicious pointer-to-pointer conversion (area too small) --emacro(826, - QTICKER_CAST_) - -// AC++M5-2-9 casting from pointer type to integer type --emacro(9091, - Q_UINTPTR_CAST_) - -// [AC++M12-1-1] non-static data member not initialized by ctor --esym(1401, - QP::QEvt::*, - QP::QActive::*) - -// definition of macro ends in semi-colon --esym(823, - QF_SCHED_STAT_) - -// MC++5-2-8 conversion from integer type (0) to pointer type --emacro(9010, - Q_ACTION_CAST) - - -// M3-R11.8(r) cast drops const qualifier --emacro(9005, - QF_EPOOL_PUT_) - -// M3-D11.5(a) conversion from pointer to void to other pointer type --efunc(9079, - QF_bzero) - -// M3-R17.8(a) function parameter modified --efunc(9044, - QF_LOG2, - QMPool_init) - -// M3-R18.1(r) potential out of bounds pointer access --emacro(661, - QF_EPOOL_EVENT_SIZE_) - -// AR-M5-2-8 conversion from pointer to void to other pointer type --emacro(9079, - QF_EPOOL_GET_) - -// M3-R18.3(r) relational operator <= applied to pointers --emacro(946, - QF_PTR_RANGE_) - -// M3-R8.13(a) parameter of function could be pointer to const --efunc(818, - QP::QActive::start, - QP::QTicker::postLIFO) - -// MC++R0-1-1 statement is unreachable due to unconditional transfer -// of control (assertion) -//-efunc(527, -// QP::QMActive::isIn, -// QP::QMActive::state, -// QP::QMActive::childState) - -// MC++R7-1-1 parameter of function could be declared const --esym(952, - QP::QEQueue::init) - -// AC++M5-2-3: downcast of polymorphic type --efunc(9171, - QP::QActive::post_, - QP::QActive::postLIFO) - -// BARR-C:2018 R 6.2c return statement before end of function --efunc(904, - QP::QActive::post_, - QP::QActive::postLIFO) - -// [AC++M5-2-2]: casting from base class to derived class (QP::QActiveDummy) --efunc(1939, - QP::QActive::post_, - QP::QActive::postLIFO) - -// PCLP-1731: public virtual function (in a class without virtual destructor) --esym(1731, - QP::QTicker::*) - - // PCLP-1933: call to unqualified virtual function from non-static member function --efunc(1933, - QP::QActive::start) - -// PCLP-9079: --efunc(9079, - QP::QF::bzero_, - QP::QTimeEvt::armX, - QP::QTimeEvt::disarm, - QP::QTimeEvt::rearm, - QP::QMPool::init, - QP::QMPool::get, - QP::QMPool::put) - - -// QV ------------------------------------------------------------------------ -// MC++R16-0-4 function-like macro --esym(9026, - QV_CPU_SLEEP) - - -// QK ------------------------------------------------------------------------ - -// MC++R16-0-4 function-like macro --esym(9026, - QK_ISR_CONTEXT_, - QK_ISR_ENTRY, - QK_ISR_EXIT) - - -// QXK ----------------------------------------------------------------------- -// MC++R16-0-4 function-like macro --esym(9026, - QXK_ISR_CONTEXT_, - QXK_CONTEXT_SWITCH_, - QXK_PTR_CAST_, - QXTHREAD_CAST_, - QXTHREAD_EQUEUE_SIGNAL_) - -// MC++R10-0-6 unparenthesized macro parameter in definition of macro --esym(9022, - QXK_PTR_CAST_) - -// MC++R5-2-7 pointer type converted to unrelated pointer --emacro(9176, - Q_STATE_CAST) - -// M3-R11.3(r) cast to pointer to different object type -//-emacro(9087, -// QXK_PTR_CAST_, -// QXTHREAD_CAST_) - -// MC++R5-2-7 pointer type converted to unrelated pointer type --emacro(9176, - QXK_PTR_CAST_) - -// MC++R5-2-3 downcast of polymorphic type ... to type ... --emacro(9171, - QXK_PTR_CAST_) - -// casting from base class 'QP::QActive' to derived class --emacro(1939, - QXK_PTR_CAST_) - -// suspicious pointer-to-pointer conversion (area too small) --emacro(826, - QXK_PTR_CAST_, - QXTHREAD_CAST_) - - -// QS ------------------------------------------------------------------------ -// the following options are needed only when Q_SPY is defined - -// MC++R16-0-4 function-like macro --esym(9026, - QS_CRIT_ENTRY, - QS_CRIT_EXIT, - QS_MEM_SYS, - QS_MEM_APP, - QS_PTR_AT_, - QS_PTR_INC_, - QS_INSERT_BYTE_, - QS_INSERT_ESC_BYTE_, - QS_REC_NUM_) - -// M3-R14.3(r) boolean condition for 'if' always evaluates to 'false' --emacro(774,, - QS_INSERT_BYTE_, - QS_INSERT_ESC_BYTE_, - QS_BEGIN_PRE_, - QS_BEGIN_PRE_) - -// the right operand to << always evaluates to 0 --emacro(845, - QS_BEGIN_PRE_, - QS_BEGIN_PRE_) - -// excessive shift value (precision 3 shifted right by 3) --emacro(572, - QS_BEGIN_PRE_, - QS_BEGIN_PRE_) - -// constant expression evaluates to 0 in 'binary' operation '>>' --emacro(778, - QS_BEGIN_PRE_, - QS_BEGIN_PRE_) - -// constant value used in Boolean context --emacro(506, - QS_BEGIN_PRE_, - QS_BEGIN_PRE_) - -// bitwise operator '>>' applied to signed underlying type [AS-M5-0-21] --emacro(9130, - QS_BEGIN_PRE_, - QS_BEGIN_PRE_) - -// use of c-style cast to void [AS-A5-2-2] --emacro(1954, - QS_END_PRE_) - -// MC++R0-1-9 operator == always evaluates to true --emacro(948, - QS_BEGIN_PRE_) - -// MC++R0-1-1, MC++R0-1-2, MC++R0-1-9 -// left operand to '||' always evaluates to 'true' --emacro(944, - QS_BEGIN_PRE_) - -// MC++R5-2-9 casting from pointer type to integer type --emacro(9091, - QS_OBJ_PRE_, - QS_FUN_PRE_) - -// M3-R11.6(r) explicit cast from 'void *volatile' to 'uint32_t' -//-emacro(923, -// QS_OBJ_PRE_, -// QS_FUN_PRE_) - -// M3-R11.1(4) conversion between pointer to function and differing type -//-emacro(9074, -// QS_FUN_PRE_) - -// definition of macro ends in semi-colon --esym(823, - QS_CRIT_STAT, - QS_BEGIN_PRE_) - -// union initialization --efunc(708, - QS_f64_fmt_) - -// M3-R19.2(a) union declared --efunc(9018, - QS_f32_fmt_, - QS_f64_fmt_) - -// MC++R10-0-6 unparenthesized macro parameter in definition of macro --esym(9022, - QS_TEST_PROBE, - QS_TEST_PROBE_ID) - -// AR M5-0-10 the result of the ~ operator applied to an object with an -// underlying type of 'unsigned char' must be cast to 'unsigned char' -// in this context --efunc(9126, - QP::QS::glbFilter_, - QP::QS::locFilter_) - -// don't report problems within QS_target_info_() function --efunc(9130, - QP::QS_target_info_) --efunc(9114, - QP::QS_target_info_) --efunc(9117, - QP::QS_target_info_) --efunc(9125, - QP::QS_target_info_) --efunc(9112, - QP::QS_target_info_) --efunc(9128, - QP::QS_target_info_) --efunc(737, - QP::QS_target_info_) - diff --git a/ports/lint-plus2/qk/qp_port.hpp b/ports/lint-plus2/qk/qp_port.hpp deleted file mode 100644 index 89d9a211f..000000000 --- a/ports/lint-plus2/qk/qp_port.hpp +++ /dev/null @@ -1,101 +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 qpcpp_7_3_0 -//! -//! @file -//! @brief QP/C++ port for QK kernel, Generic C++11 - -#ifndef QP_PORT_HPP_ -#define QP_PORT_HPP_ - -#include // Exact-width types. C++11 Standard - -#ifdef QP_CONFIG -#include "qp_config.hpp" // external QP configuration -#endif - -// no-return function specifier (C++11 Standard) -#define Q_NORETURN [[ noreturn ]] void - -// QF configuration for QK -- data members of the QActive class... - -// QK event-queue used for AOs -#define QACTIVE_EQUEUE_TYPE QEQueue - -// QF "thread" type used to store the MPU settings in the AO -#define QACTIVE_THREAD_TYPE void const * - -// interrupt disabling mechanism -#define QF_INT_DISABLE() intDisable() -#define QF_INT_ENABLE() intEnable() - -// QF critical section mechanism -#define QF_CRIT_STAT std::uint32_t crit_stat_; -#define QF_CRIT_ENTRY() (crit_stat_ = critEntry()) -#define QF_CRIT_EXIT() critExit(crit_stat_) - -// Check if the code executes in the ISR context -#define QK_ISR_CONTEXT_() (QK_get_IPSR() != 0U) - -// Define the ISR entry sequence -#define QK_ISR_ENTRY() (static_cast(0)) - -// Define the ISR exit sequence -#define QK_ISR_EXIT() \ -do { \ - QF_INT_DISABLE(); \ - --QK_priv_.intNest; \ - if (QK_priv_.intNest == 0U) { \ - if (QK_sched_() != 0U) { \ - QK_activate_(); \ - } \ - } \ - QF_INT_ENABLE(); \ -} while (false) - -extern "C" { - -void intDisable(void); -void intEnable(void); -std::uint32_t critEntry(void); -void critExit(std::uint32_t stat); -std::uint32_t QK_get_IPSR(void); - -} // extern "C" - -// include files ------------------------------------------------------------- -#include "qequeue.hpp" // QK kernel uses the native QP event queue -#include "qmpool.hpp" // QK kernel uses the native QP memory pool -#include "qp.hpp" // QP framework -#include "qk.hpp" // QK kernel - -#endif // QP_PORT_HPP_ - diff --git a/ports/lint-plus2/qpcpp.lnt b/ports/lint-plus2/qpcpp.lnt deleted file mode 100644 index dd1d1eb16..000000000 --- a/ports/lint-plus2/qpcpp.lnt +++ /dev/null @@ -1,459 +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: 2024-02-18 -//! @version Last updated for version: 7.3.3 -//! -//! @file -//! @brief PC-Lint-Plus option file for linting QP/C++ __Applications__ - -//---------------------------------------------------------------------------- -// globally suppress the following warnings: --e546 // explicitly taking address of function --e717 // monocarpic do-while used to group statements --e1756 // variable has 'static' storage duration and non-POD type --e3412 // class has virtual functions but non-virtual destructor - -// Assertions ---------------------------------------------------------------- - -// give Q_onError() the semantics of "exit" --function(exit, - Q_onError) - -// C-style array type [AUTOSAR Rule A18-1-1] --esym(9436, - QP::versionStr) - -// AC++M16-3-2 function-like macro --esym(9026, - Q_DEFINE_THIS_MODULE, - Q_ASSERT_STATIC, - Q_ASSERT, - Q_ASSERT_ID, - Q_ERROR, - Q_ERROR_ID, - Q_REQUIRE, - Q_REQUIRE_ID, - Q_ENSURE, - Q_ENSURE_ID, - Q_INVARIANT, - Q_INVARIANT_ID, - Q_DIM) - -// use of c-style cast to void [AS-A5-2-2] --emacro(1954, - Q_ASSERT, - Q_ASSERT_ID, - Q_ERROR, - Q_ERROR_ID, - Q_REQUIRE, - Q_REQUIRE_ID, - Q_ENSURE, - Q_ENSURE_ID, - Q_INVARIANT, - Q_INVARIANT_ID, - Q_ASSERT_INCRIT) - -// MC++R10-0-6 unparenthesized macro parameter in definition of macro --esym(9022, - Q_DEFINE_THIS_FILE, - Q_DEFINE_THIS_MODULE) - -// definition of macro ends in semi-colon --esym(823, - Q_DEFINE_THIS_FILE, - Q_DEFINE_THIS_MODULE) - -// AC++M16-3-2 function-like macro --esym(9026, - Q_UNUSED_PAR, - Q_DIM, - Q_UINT2PTR_CAST, - Q_UINTPTR_CAST_) - -// MC++R5-2-4 use of c-style cast --emacro(1924, - Q_ASSERT, - Q_ASSERT_ID, - Q_ERROR, - Q_ERROR_ID) - - -// QEP ----------------------------------------------------------------------- - -// MC++R7-3-1 global declaration of symbol --esym(9141, - char_t, - int_t, - enum_t, - float32_t, - float64_t) - -// AUTOSAR Rule A3-3-2 non-private data member within a non-POD structure -// NOTE: public access needed for extern "C" functions --esym(9150, - QP::QAsmAttr::*, - QP::QAsm::*) - -// AC++M16-3-2 function-like macro --esym(9026, - INIT, - DISPATCH, - Q_STATE_DECL, - Q_STATE_DEF, - QM_STATE_DECL, - QM_STATE_DEF, - QM_SM_STATE_DECL, - QM_ACTION_DECL, - QM_ACTION_DEF, - QHSM_INIT, - QHSM_DISPATCH, - Q_TRAN, - Q_TRAN_HIST, - Q_SUPER, - Q_HANDLED, - Q_UNHANDLED, - QM_ENTRY, - QM_EXIT, - QM_SM_EXIT, - QM_TRAN, - QM_TRAN_INIT, - QM_TRAN_HIST, - QM_TRAN_EP, - QM_TRAN_XP, - QM_SUPER, - QM_SUPER_SUB, - QM_HANDLED, - QM_UNHANDLED, - Q_HSM_UPCAST, - Q_EVT_CAST, - Q_STATE_CAST, - Q_UINT2PTR_CAST) - -// MC++R5-2-8 conversion from pointer to other pointer type --emacro(9079, - Q_EVT_CAST) - -// MC++R5-2-2 casting from base class 'QP::QEvt' to derived class --emacro(1939, - Q_EVT_CAST) - -// MC++R10-0-6 unparenthesized macro parameter 'class_' in definition of macro --esym(9022, - Q_EVT_CAST, - Q_UINT2PTR_CAST, - Q_STATE_DECL, - Q_STATE_DEF, - QM_STATE_DECL, - QM_STATE_DEF, - QM_SM_STATE_DECL, - QM_ACTION_DECL, - QM_ACTION_DEF, - QEP_TRIG_, - QEP_ENTER_, - QEP_EXIT_) - -// MC++16-3-1 multiple use of stringize/pasting operators in definition of macro --esym(9023, - Q_STATE_DECL, - Q_STATE_DEF, - QM_STATE_DECL, - QM_STATE_DEF, - QM_SM_STATE_DECL, - QM_ACTION_DEF) - -// AC++M16-3-2 stringize operator used in definition of function-like macro --esym(9024, - Q_STATE_DECL, - Q_STATE_DEF, - QM_STATE_DECL, - QM_STATE_DEF, - QM_SM_STATE_DECL, - QM_ACTION_DECL, - QM_ACTION_DEF) - -// MC++R5-2-8 conversion from pointer to void to other pointer type --emacro(9079, - Q_STATE_DEF, - QM_STATE_DEF, - QM_ACTION_DEF) - - // MC++R9-3-3 member function could be made const --emacro(1762, - Q_STATE_DEF, - QM_STATE_DEF) - -// MC++9-5-1 union declared --esym(9018, - QP::QAsmAttr) - -// MC++5-2-8 conversion from integer type (0) to pointer type --emacro(9010, - Q_STATE_CAST) - -// public virtual function 'QP::QHsm::...' --esym(1731, - QP::QHsm::*, - QP::QMsm::*) - - -// QF ------------------------------------------------------------------------ - -// AUTOSAR Rule A3-3-2 non-private data member within a non-POD structure -// NOTE: public access needed for extern "C" functions --esym(9150, - QP::QF::QF_Attr::*) - -// AC++M16-3-2 function-like macro --esym(9026, - POST, - POST_X, - PUBLISH, - TICK_X, - TICK, - TRIG, - QF_INT_DISABLE, - QF_INT_ENABLE, - QF_CRIT_EXIT_NOP, - QF_LOG2, - Q_PRIO, - Q_NEW, - Q_NEW_X, - Q_NEW_REF, - Q_DELETE_REF, - QF_INT_DISABLE, - QF_INT_ENABLE, - QF_MPOOL_EL) - -// MC++R0-3-2 ignoring return value of function --emacro(534, - POST) - -// [AUTOSAR Rule M17-0-2] the name xxx is reserved to the compiler --esym(9093, - remove) // QPrioSet::remove() - -// MC++R5-2-7 pointer type converted to unrelated pointer type --emacro(9176, - QF_QMACTIVE_TO_QMSM_CAST_, - QF_QMACTIVE_TO_QMSM_CONST_CAST_) - -// MC++R5-2-2 casting from base class 'QP::QEvt' to derived class --emacro(1939, - Q_NEW, - Q_NEW_X) - -// MC++R10-0-6 unparenthesized macro parameter in definition of macro --esym(9022, - Q_NEW, - Q_NEW_X, - Q_NEW_REF) - - -// QK ------------------------------------------------------------------------ - -// AC++M16-3-2 function-like macro --esym(9026, - QK_ISR_ENTRY, - QK_ISR_EXIT) - -// AC++M7-3-1 global declaration of symbol --esym(9141, - QK_Attr) - -// MC++R11-0-1 non-private data member within a non-POD structure -// NOTE: public access needed for extern "C" functions --esym(9150, - QK_Attr::*) - - -// QXK ----------------------------------------------------------------------- -// MC++R16-0-4 function-like macro --esym(9026, - QXK_ISR_ENTRY, - QXK_ISR_EXIT, - QXK_TLS) - -// MC++R7-3-1 global declaration of symbol --esym(9141, - QXK_Attr) - -// MC++R10-0-6 unparenthesized macro parameter in definition of macro --esym(9022, - QXK_TLS) - -// MC++R5-2-8 conversion from pointer to void to other pointer type --emacro(9079, - QXK_PTR_CAST_) - -// MC++R5-2-2 casting from base class to derived class --emacro(1939, - QXTHREAD_CAST_) - -// MC++R5-2-3 downcast of polymorphic type --emacro(9171, - QXTHREAD_CAST_) - -// [AUTOSAR Rule M17-0-2] the name 'signal' is reserved to the compiler --esym(9093, - signal) - -// public virtual function 'QP::QXThread::...' --esym(1731, - QP::QXThread::*) - -// [AUTOSAR Rule M8-4-2] parameter of function has different name than -// overridden function --esym(9272, - QP::QXMutex::init*) - -// function xxx matches the name of a standard library function --esym(8502, - signal) // QXSemaphore::signal() - - -// QS ------------------------------------------------------------------------ - -// AC++M16-3-2 function-like macro --esym(9026, - QS_INIT, - QS_EXIT, - QS_DUMP, - QS_RESET, - QS_GLB_FILTER, - QS_LOC_FILTER, - QS_FILTER_AP_OBJ, - QS_GET_BYTE, - QS_GET_BLOCK, - QS_BEGIN_ID, - QS_END, - QS_BEGIN_INCRIT, - QS_END_INCRIT, - QS_QF_CRIT_ENTRY, - QS_QF_CRIT_EXIT, - QS_QF_ISR_ENTRY, - QS_QF_ISR_EXIT, - QS_ONLY, - QS_I8, - QS_U8, - QS_I16, - QS_U16, - QS_I32, - QS_I64, - QS_U32, - QS_F32, - QS_F64, - QS_U64, - QS_U32_HEX, - QS_STR, - QS_OBJ, - QS_FUN, - QS_SIG_DICTIONARY, - QS_OBJ_DICTIONARY, - QS_OBJ_ARR_DICTIONARY, - QS_FUN_DICTIONARY, - QS_USR_DICTIONARY, - QS_ENUM_DICTIONARY, - QS_ASSERTION, - QS_FLUSH, - QS_MEM, - QS_ENUM, - QS_SIG, - QS_PTR_AT_, - QS_RX_PUT, - QS_OUTPUT, - QS_RX_INPUT, - QS_TEST_PAUSE, - QS_TEST_PROBE_DEF, - QS_TEST_PROBE, - QS_TEST_PROBE_ID) - -// AC++M16-3-2 function-like macro --esym(9026, - QS_GLB_CHECK_, - QS_LOC_CHECK_, - QS_BEGIN_PRE_, - QS_END_PRE_, - QS_BEGIN_PRE_, - QS_END_PRE_, - QS_U8_PRE_, - QS_2U8_PRE_, - QS_U16_PRE_, - QS_U32_PRE_, - QS_STR_PRE_, - QS_TIME_PRE_, - QS_SIG_PRE_, - QS_EVS_PRE_, - QS_OBJ_PRE_, - QS_FUN_PRE_, - QS_EQC_PRE_, - QS_MPC_PRE_, - QS_MPS_PRE_, - QS_TEC_PRE_) - -// AC++M16-3-2 function-like macro --esym(9026, - QS_REC_DONE) - -// definition of macro ends in semi-colon --esym(823, - QS_TEST_PROBE_DEF) - -// M3-R11.1(r) conversion between pointer to function type --emacro(9074, - QS_FUN_DICTIONARY, - QS_TEST_PROBE_DEF) - -// AC++M16-3-2 stringize operator used in definition of function-like macro --esym(9024, - QS_OBJ_DICTIONARY, - QS_OBJ_ARR_DICTIONARY, - QS_FUN_DICTIONARY, - QS_SIG_DICTIONARY, - QS_USR_DICTIONARY, - QS_ENUM_DICTIONARY) - -// M3-R10.3(r) cannot assign enum to different essential type --emacro(9034, - QS_SIG_DICTIONARY) - -// implicit conversion of enum to integral type 'int' --emacro(641, - QS_SIG_DICTIONARY) - -// MC++R11-0-1 non-private data member within a non-POD structure --esym(9150, - QP::QEvt::*, - QP::QActive::*, - QP::QF::Attr::*, - QP::QS::QSrxPriv::*) - -// MC++9-5-1 union declared --esym(9018, - F32Rep, - F64Rep, - U32Rep, - TCast, - QP::QS::RxAttr::Variant) - diff --git a/ports/lint-plus2/qv/qp_port.hpp b/ports/lint-plus2/qv/qp_port.hpp deleted file mode 100644 index 9c7c7be26..000000000 --- a/ports/lint-plus2/qv/qp_port.hpp +++ /dev/null @@ -1,89 +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 qpcpp_7_3_0 -//! -//! @file -//! @brief QP/C++ port for QV kernel, Generic C++ - -#ifndef QP_PORT_HPP_ -#define QP_PORT_HPP_ - -#include // Exact-width types. C++11 Standard - -#ifdef QP_CONFIG -#include "qp_config.hpp" // external QP configuration -#endif - -// no-return function specifier (C++11 Standard) -#define Q_NORETURN [[ noreturn ]] void - -// QF configuration for QV -- data members of the QActive class... - -// QV event-queue used for AOs -#define QACTIVE_EQUEUE_TYPE QEQueue - -// QF "thread" type used to store the MPU settings in the AO -#define QACTIVE_THREAD_TYPE void const * - -// interrupt disabling mechanism -#define QF_INT_DISABLE() intDisable() -#define QF_INT_ENABLE() intEnable() - -// QF critical section mechanism -#define QF_CRIT_STAT std::uint32_t crit_stat_; -#define QF_CRIT_ENTRY() (crit_stat_ = critEntry()) -#define QF_CRIT_EXIT() critExit(crit_stat_) - -#define QV_CPU_SLEEP() \ -do { \ - __disable_interrupt(); \ - QF_INT_ENABLE(); \ - __WFI(); \ - __enable_interrupt(); \ -} while (false) - -extern "C" { - -void intDisable(void); -void intEnable(void); -std::uint32_t critEntry(void); -void critExit(std::uint32_t stat); - -} // extern "C" - -// include files ------------------------------------------------------------- -#include "qequeue.hpp" // QV kernel uses the native QP event queue -#include "qmpool.hpp" // QV kernel uses the native QP memory pool -#include "qp.hpp" // QP framework -#include "qv.hpp" // QV kernel - -#endif // QP_PORT_HPP_ - diff --git a/ports/lint-plus2/qxk/qp_port.hpp b/ports/lint-plus2/qxk/qp_port.hpp deleted file mode 100644 index 3211158c3..000000000 --- a/ports/lint-plus2/qxk/qp_port.hpp +++ /dev/null @@ -1,104 +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 qpcpp_7_3_0 -//! -//! @file -//! @brief QP/C++ port for QXK kernel, Generic C++ - -#ifndef QP_PORT_HPP_ -#define QP_PORT_HPP_ - -#include // Exact-width types. C++11 Standard - -#ifdef QP_CONFIG -#include "qp_config.hpp" // external QP configuration -#endif - -// no-return function specifier (C++11 Standard) -#define Q_NORETURN [[ noreturn ]] void - -// QF configuration for QXK -- data members of the QActive class... - -// QXK event-queue type used for AOs and eXtended threads. -#define QACTIVE_EQUEUE_TYPE QEQueue - -// QXK OS-Object type used for the private stack pointer for eXtended threads. -// (The private stack pointer is NULL for basic-threads). -#define QACTIVE_OS_OBJ_TYPE void* - -// QF "thread" type used to store the MPU settings in the AO -#define QACTIVE_THREAD_TYPE void const * - -// interrupt disabling mechanism -#define QF_INT_DISABLE() intDisable() -#define QF_INT_ENABLE() intEnable() - -// QF critical section mechanism -#define QF_CRIT_STAT std::uint32_t crit_stat_; -#define QF_CRIT_ENTRY() (crit_stat_ = critEntry()) -#define QF_CRIT_EXIT() critExit(crit_stat_) - -// Check if the code executes in the ISR context -#define QXK_ISR_CONTEXT_() (QXK_get_IPSR() != 0U) - -// Define the ISR entry sequence -#define QXK_ISR_ENTRY() (static_cast(0)) - -// Define the ISR exit sequence -#define QXK_ISR_EXIT() do { \ - QF_INT_DISABLE(); \ - if (QXK_sched_() != 0U) { \ - *Q_UINT2PTR_CAST(uint32_t, 0xE000ED04U) = (1U << 28U);\ - } \ - QF_INT_ENABLE(); \ -} while (false) - -#define QXK_CONTEXT_SWITCH_() (QXK_trigPendSV()) - -extern "C" { - -void intDisable(void); -void intEnable(void); -std::uint32_t critEntry(void); -void critExit(std::uint32_t stat); -std::uint32_t QXK_get_IPSR(void); -void QXK_trigPendSV(void); - -} // extern "C" - -// include files ------------------------------------------------------------- -#include "qequeue.hpp" // QK kernel uses the native QP event queue -#include "qmpool.hpp" // QK kernel uses the native QP memory pool -#include "qp.hpp" // QP framework -#include "qxk.hpp" // QXK kernel - -#endif // QP_PORT_HPP_ - diff --git a/ports/lint-plus2/std.lnt b/ports/lint-plus2/std.lnt deleted file mode 100644 index 0b77cdb5c..000000000 --- a/ports/lint-plus2/std.lnt +++ /dev/null @@ -1,45 +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-08 -//! @version Last updated for version: 7.3.0 -//! -//! @file -//! @brief PC-Lint-Plus standard option file - -// message formatting options... --hF1 // output: a single line -+ffn // use full path names -//-"format=%(\q%f\q %l %C%) %t %n: %m" -//-width(0,0) // do not break lines --width(120,4) // break lines after 99 characters with 4 characters indent -+flm // make sure no foreign includes change the format - -+rw(inline, entry) - --zero(99) // don't stop because of warnings --passes(2) // make two passes (for better error messages) --restore_at_end // don't let -e options bleed to other files --summary() // produce a summary of all produced messages - diff --git a/ports/msp430/qk/qp_port.hpp b/ports/msp430/qk/qp_port.hpp index 2ed5b93c4..bc058a10d 100644 --- a/ports/msp430/qk/qp_port.hpp +++ b/ports/msp430/qk/qp_port.hpp @@ -1,34 +1,34 @@ //============================================================================ // 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 // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC . -// // 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: +// 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. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2023-09-07 -//! @version Last updated for: @ref qpcpp_7_3_0 +//! @date Last updated on: 2024-09-30 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QP/C++ port to MSP430, preemptive QK kernel @@ -36,9 +36,8 @@ #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ -#include // Exact-width types. C++11 Standard - -#include "qp_config.hpp" // external QP configuration required in this port +#include // Exact-width types. C++11 Standard +#include "qp_config.hpp" // QP configuration from the application // no-return function specifier (C++11 Standard) #define Q_NORETURN [[ noreturn ]] void diff --git a/ports/msp430/qk/qs_port.hpp b/ports/msp430/qk/qs_port.hpp index 1bae19a70..b5fecfe1b 100644 --- a/ports/msp430/qk/qs_port.hpp +++ b/ports/msp430/qk/qs_port.hpp @@ -28,7 +28,7 @@ // //============================================================================ //! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_7_4_0 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QS/C++ port to a 16-bit CPU, generic C++11 compiler diff --git a/ports/msp430/qutest/qp_port.hpp b/ports/msp430/qutest/qp_port.hpp index b6fdf3bff..3807f8e3a 100644 --- a/ports/msp430/qutest/qp_port.hpp +++ b/ports/msp430/qutest/qp_port.hpp @@ -1,34 +1,34 @@ //============================================================================ // 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 // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC . -// // 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: +// 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. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2023-09-07 -//! @version Last updated for: @ref qpcpp_7_3_0 +//! @date Last updated on: 2024-09-30 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QP/C++ to MSP40, QUTEST unit test harness, generic C++11 compiler @@ -36,9 +36,8 @@ #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ -#include // Exact-width types. C++11 Standard - -#include "qp_config.hpp" // external QP configuration required in this port +#include // Exact-width types. C++11 Standard +#include "qp_config.hpp" // QP configuration from the application // no-return function specifier (C++11 Standard) #define Q_NORETURN [[ noreturn ]] void @@ -83,8 +82,8 @@ #define QF_SCHED_UNLOCK_() ((void)0) // native event queue operations - #define QACTIVE_EQUEUE_WAIT_(me_) \ - Q_ASSERT_INCRIT(110, (me_)->m_eQueue.m_frontEvt != nullptr) + #define QACTIVE_EQUEUE_WAIT_(me_) (static_cast(0)) + #ifndef Q_UNSAFE #define QACTIVE_EQUEUE_SIGNAL_(me_) \ QF::readySet_.insert(static_cast((me_)->m_prio)); diff --git a/ports/msp430/qutest/qs_port.hpp b/ports/msp430/qutest/qs_port.hpp index 1bae19a70..b5fecfe1b 100644 --- a/ports/msp430/qutest/qs_port.hpp +++ b/ports/msp430/qutest/qs_port.hpp @@ -28,7 +28,7 @@ // //============================================================================ //! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_7_4_0 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QS/C++ port to a 16-bit CPU, generic C++11 compiler diff --git a/ports/msp430/qv/qp_port.hpp b/ports/msp430/qv/qp_port.hpp index 613658fe5..e6e29258e 100644 --- a/ports/msp430/qv/qp_port.hpp +++ b/ports/msp430/qv/qp_port.hpp @@ -1,34 +1,34 @@ //============================================================================ // 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 // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC . -// // 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: +// 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. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2023-09-07 -//! @version Last updated for: @ref qpcpp_7_3_0 +//! @date Last updated on: 2024-09-30 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QP/C++ port to MSP430, cooperative QV kernel @@ -36,9 +36,8 @@ #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ -#include // Exact-width types. C++11 Standard - -#include "qp_config.hpp" // external QP configuration required in this port +#include // Exact-width types. C++11 Standard +#include "qp_config.hpp" // QP configuration from the application // no-return function specifier (C++11 Standard) #define Q_NORETURN [[ noreturn ]] void diff --git a/ports/msp430/qv/qs_port.hpp b/ports/msp430/qv/qs_port.hpp index 1bae19a70..b5fecfe1b 100644 --- a/ports/msp430/qv/qs_port.hpp +++ b/ports/msp430/qv/qs_port.hpp @@ -28,7 +28,7 @@ // //============================================================================ //! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_7_4_0 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QS/C++ port to a 16-bit CPU, generic C++11 compiler diff --git a/ports/posix-qutest/CMakeLists.txt b/ports/posix-qutest/CMakeLists.txt deleted file mode 100644 index f526975f0..000000000 --- a/ports/posix-qutest/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -# ports/posix-qutest -target_include_directories(qpcpp PUBLIC .) -target_sources(qpcpp PRIVATE - qutest_port.cpp -) \ No newline at end of file diff --git a/ports/posix-qutest/README.md b/ports/posix-qutest/README.md deleted file mode 100644 index 6e988cf3f..000000000 --- a/ports/posix-qutest/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# POSIX port for the QUTest unit testing harness - -Documentation for this port is available in the QP/C Manual at: - -- https://www.state-machine.com/qpcpp/posix-qutest.html diff --git a/ports/posix-qutest/qp_port.hpp b/ports/posix-qutest/qp_port.hpp deleted file mode 100644 index 00d88b914..000000000 --- a/ports/posix-qutest/qp_port.hpp +++ /dev/null @@ -1,109 +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 . -// -// 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: 2024-06-10 -//! @version Last updated for: @ref qpc_7_4_0 -//! -//! @file -//! @brief QP/C++ port for QUTEST Windows, generic C++11 - -#ifndef QP_PORT_HPP_ -#define QP_PORT_HPP_ - -#include // Exact-width types. C++11 Standard - -#ifdef QP_CONFIG -#include "qp_config.hpp" // external QP configuration -#endif - -// no-return function specifier (C++11 Standard) -#define Q_NORETURN [[ noreturn ]] void - -// QActive event queue type -#define QACTIVE_EQUEUE_TYPE QEQueue - -// QF interrupt disable/enable -#define QF_INT_DISABLE() (QP::QS::onIntDisable()) -#define QF_INT_ENABLE() (QP::QS::onIntEnable()) - -// QF critical section -#define QF_CRIT_STAT -#define QF_CRIT_ENTRY() QF_INT_DISABLE() -#define QF_CRIT_EXIT() QF_INT_ENABLE() - -// QF_LOG2 not defined -- use the internal LOG2() implementation - -// include files ------------------------------------------------------------- -#include "qequeue.hpp" // QUTest port uses QEQueue event-queue -#include "qmpool.hpp" // QUTest port uses QMPool memory-pool -#include "qp.hpp" // QP platform-independent public interface - -namespace QP { -namespace QS { -void onIntDisable(); -void onIntEnable(); -} -} -//============================================================================ -// interface used only inside QF implementation, but not in applications - -#ifdef QP_IMPL - - // QUTest scheduler locking (not used) - #define QF_SCHED_STAT_ - #define QF_SCHED_LOCK_(dummy) (static_cast(0)) - #define QF_SCHED_UNLOCK_() (static_cast(0)) - - // native event queue operations - #define QACTIVE_EQUEUE_WAIT_(me_) \ - Q_ASSERT_INCRIT(305, (me_)->m_eQueue.m_frontEvt != nullptr) -#ifndef Q_UNSAFE - #define QACTIVE_EQUEUE_SIGNAL_(me_) \ - (QP::QS::tstPriv_.readySet.insert( \ - static_cast((me_)->m_prio))); \ - QP::QS::tstPriv_.readySet.update_(&QP::QS::tstPriv_.readySet_dis) -#else - #define QACTIVE_EQUEUE_SIGNAL_(me_) \ - (QP::QS::tstPriv_.readySet.insert( \ - static_cast((me_)->m_prio))) -#endif - - // native QF event pool operations - #define QF_EPOOL_TYPE_ QMPool - #define QF_EPOOL_INIT_(p_, poolSto_, poolSize_, evtSize_) \ - (p_).init((poolSto_), (poolSize_), (evtSize_)) - #define QF_EPOOL_EVENT_SIZE_(p_) ((p_).getBlockSize()) - #define QF_EPOOL_GET_(p_, e_, m_, qsId_) \ - ((e_) = static_cast((p_).get((m_), (qsId_)))) - #define QF_EPOOL_PUT_(p_, e_, qsId_) ((p_).put((e_), (qsId_))) - -#endif // QP_IMPL - -#endif // QP_PORT_HPP_ - diff --git a/ports/posix-qutest/qs_port.hpp b/ports/posix-qutest/qs_port.hpp deleted file mode 100644 index 2cf165e8f..000000000 --- a/ports/posix-qutest/qs_port.hpp +++ /dev/null @@ -1,64 +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: 2024-06-06 -//! @version Last updated for: @ref qpcpp_7_4_0 -//! -//! @file -//! @brief QS/C++ port to POSIX/Win32 - -#ifndef QS_PORT_HPP_ -#define QS_PORT_HPP_ - -#if defined(_WIN64) || defined(__LP64__) || defined(_LP64) // 64-bit OS? - #define QS_OBJ_PTR_SIZE 8U - #define QS_FUN_PTR_SIZE 8U -#else // 32-bit OS - #define QS_OBJ_PTR_SIZE 4U - #define QS_FUN_PTR_SIZE 4U -#endif - -namespace QP { -void QS_output(void); // handle the QS output -void QS_rx_input(void); // handle the QS-RX input -} - -//============================================================================ -// 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.hpp" -// *before* "qs.hpp". -#ifndef QP_PORT_HPP_ -#include "qp_port.hpp" // use QS with QP -#endif - -#include "qs.hpp" // QS platform-independent public interface - -#endif // QS_PORT_HPP_ diff --git a/ports/posix-qutest/qutest_port.cpp b/ports/posix-qutest/qutest_port.cpp deleted file mode 100644 index 3fb7f9437..000000000 --- a/ports/posix-qutest/qutest_port.cpp +++ /dev/null @@ -1,310 +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: 2024-06-11 -//! @version Last updated for: @ref qpc_7_4_0 -//! -//! @file -//! @brief QS/C++ "port" to QUTest with POSIX - -// expose features from the 2008 POSIX standard (IEEE Standard 1003.1-2008) -#define _POSIX_C_SOURCE 200809L - -#ifndef Q_SPY - #error "Q_SPY must be defined for QUTest application" -#endif // Q_SPY - -#define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#include "qs_port.hpp" // QS port - -#include "safe_std.h" // portable "safe" / facilities -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define QS_TX_SIZE (8*1024) -#define QS_RX_SIZE (2*1024) -#define QS_TX_CHUNK QS_TX_SIZE -#define QS_TIMEOUT_MS 10L - -#define INVALID_SOCKET -1 -#define SOCKET_ERROR -1 - -namespace { // unnamed local namespace - -Q_DEFINE_THIS_MODULE("qutest_port") - -// local variables ........................................................... -static int l_sock = INVALID_SOCKET; -static struct timespec const c_timeout = { 0, QS_TIMEOUT_MS*1000000L }; - -static void sigIntHandler(int); // prototype -static void sigIntHandler(int) { - QP::QS::onCleanup(); - //PRINTF_S("\n%s\n"," disconnecting from QSPY"); - exit(-1); -} - -} // unnamed local namespace - -//============================================================================ -namespace QP { - -//............................................................................ -bool QS::onStartup(void const *arg) { - - static std::uint8_t qsBuf[QS_TX_SIZE]; // buffer for QS-TX channel - initBuf(qsBuf, sizeof(qsBuf)); - - static std::uint8_t qsRxBuf[QS_RX_SIZE]; // buffer for QS-RX channel - rxInitBuf(qsRxBuf, sizeof(qsRxBuf)); - - char hostName[128]; - char const *serviceName = "6601"; // default QSPY server port - char const *src; - char *dst; - int status; - - struct addrinfo *result = NULL; - struct addrinfo *rp = NULL; - struct addrinfo hints; - int sockopt_bool; - - // extract hostName from 'arg' (hostName:port_remote)... - src = (arg != nullptr) - ? static_cast(arg) - : "localhost"; // default QSPY host - dst = hostName; - while ((*src != '\0') - && (*src != ':') - && (dst < &hostName[sizeof(hostName) - 1])) - { - *dst++ = *src++; - } - *dst = '\0'; // zero-terminate hostName - - // extract serviceName from 'arg' (hostName:serviceName)... - if (*src == ':') { - serviceName = src + 1; - } - //printf(" Connecting to QSPY on Host=%s:%s...\n", - // hostName, serviceName); - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - status = getaddrinfo(hostName, serviceName, &hints, &result); - if (status != 0) { - FPRINTF_S(stderr, - " ERROR cannot resolve host Name=%s:%s,Err=%d\n", - hostName, serviceName, status); - goto error; - } - - for (rp = result; rp != NULL; rp = rp->ai_next) { - l_sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); - if (l_sock != INVALID_SOCKET) { - if (connect(l_sock, rp->ai_addr, rp->ai_addrlen) - == SOCKET_ERROR) - { - close(l_sock); - l_sock = INVALID_SOCKET; - } - break; - } - } - - freeaddrinfo(result); - - // socket could not be opened & connected? - if (l_sock == INVALID_SOCKET) { - FPRINTF_S(stderr, " ERROR cannot connect to QSPY at " - "host=%s:%s\n", - hostName, serviceName); - goto error; - } - - // set the socket to non-blocking mode - status = fcntl(l_sock, F_GETFL, 0); - if (status == -1) { - FPRINTF_S(stderr, - " ERROR Socket configuration failed errno=%d\n", - errno); - QS_EXIT(); - goto error; - } - if (fcntl(l_sock, F_SETFL, status | O_NONBLOCK) != 0) { - FPRINTF_S(stderr, " ERROR Failed to set non-blocking socket " - "errno=%d\n", errno); - QF::stop(); // <== stop and exit the application - goto error; - } - - // configure the socket to reuse the address and not to linger - sockopt_bool = 1; - setsockopt(l_sock, SOL_SOCKET, SO_REUSEADDR, - &sockopt_bool, sizeof(sockopt_bool)); - sockopt_bool = 0; // negative option - setsockopt(l_sock, SOL_SOCKET, SO_LINGER, - &sockopt_bool, sizeof(sockopt_bool)); - onFlush(); - - // install the SIGINT (Ctrl-C) signal handler - struct sigaction sig_act; - memset(&sig_act, 0, sizeof(sig_act)); - sig_act.sa_handler = &sigIntHandler; - sigaction(SIGINT, &sig_act, NULL); - - return true; // success - -error: - return false; // failure -} -//............................................................................ -void QS::onCleanup() { - nanosleep(&c_timeout, NULL); // allow the last QS output to come out - if (l_sock != INVALID_SOCKET) { - close(l_sock); - l_sock = INVALID_SOCKET; - } - //PRINTF_S("%s\n", " Disconnected from QSPY"); -} -//............................................................................ -void QS::onReset() { - onCleanup(); - //PRINTF_S("\n%s\n", "QS_onReset"); - exit(0); -} -//............................................................................ -void QS::onFlush() { - // NOTE: - // No critical section in QS::onFlush() to avoid nesting of critical sections - // in case QS::onFlush() is called from Q_onError(). - if (l_sock == INVALID_SOCKET) { // socket NOT initialized? - FPRINTF_S(stderr, " ERROR %s\n", - "invalid TCP socket"); - QF::stop(); // <== stop and exit the application - return; - } - - std::uint16_t nBytes = QS_TX_CHUNK; - std::uint8_t const *data; - while ((data = getBlock(&nBytes)) != nullptr) { - for (;;) { // for-ever until break or return - int nSent = send(l_sock, (char const *)data, (int)nBytes, 0); - if (nSent == SOCKET_ERROR) { // sending failed? - if ((errno == EWOULDBLOCK) || (errno == EAGAIN)) { - // sleep for the timeout and then loop back - // to send() the SAME data again - nanosleep(&c_timeout, NULL); - } - else { // some other socket error... - FPRINTF_S(stderr, " ERROR sending data over TCP," - "errno=%d\n", errno); - QF::stop(); // <== stop and exit the application - return; - } - } - else if (nSent < (int)nBytes) { // sent fewer than requested? - nanosleep(&c_timeout, NULL); // sleep for the timeout - // adjust the data and loop back to send() the rest - data += nSent; - nBytes -= (uint16_t)nSent; - } - else { - break; // break out of the for-ever loop - } - } - // set nBytes for the next call to QS::getBlock() - nBytes = QS_TX_CHUNK; - } -} - -//............................................................................ -void QS::onTestLoop() { - fd_set readSet; - FD_ZERO(&readSet); - - rxPriv_.inTestLoop = true; - while (rxPriv_.inTestLoop) { - FD_SET(l_sock, &readSet); - - struct timeval timeout = { - (long)0, (long)(QS_TIMEOUT_MS * 1000) - }; - - // selective, timed blocking on the TCP/IP socket... - timeout.tv_usec = (long)(QS_TIMEOUT_MS * 1000); - int status = select(l_sock + 1, &readSet, - (fd_set *)0, (fd_set *)0, &timeout); - if (status < 0) { - FPRINTF_S(stderr, " ERROR socket select,errno=%d\n", - errno); - QF::stop(); // <== stop and exit the application - } - else if ((status > 0) && FD_ISSET(l_sock, &readSet)) { //socket ready? - status = recv(l_sock, - (char *)QS::rxPriv_.buf, (int)QS::rxPriv_.end, 0); - if (status > 0) { // any data received? - QS::rxPriv_.tail = 0U; - QS::rxPriv_.head = status; // # bytes received - QS::rxParse(); // parse all received bytes - } - } - - onFlush(); - } - // set inTestLoop to true in case calls to QS_onTestLoop() nest, - // which can happen through the calls to QS_TEST_PAUSE(). - rxPriv_.inTestLoop = true; -} - -//............................................................................ -void QS::onIntDisable(void) { - if (tstPriv_.intLock != 0U) { - Q_onError(&Q_this_module_[0], 998); - } - ++tstPriv_.intLock; -} -//............................................................................ -void QS::onIntEnable(void) { - --tstPriv_.intLock; - if (tstPriv_.intLock != 0U) { - Q_onError(&Q_this_module_[0], 999); - } -} - -} // namespace QP - diff --git a/ports/posix-qutest/safe_std.h b/ports/posix-qutest/safe_std.h deleted file mode 100644 index 989212c12..000000000 --- a/ports/posix-qutest/safe_std.h +++ /dev/null @@ -1,115 +0,0 @@ -/** -* @file -* @brief "safe" and facilities -* @cond -****************************************************************************** -* Last updated for version 6.9.0 -* Last updated on 2020-08-24 -* -* Q u a n t u m L e a P s -* ------------------------ -* Modern Embedded Software -* -* Copyright (C) 2005-2020 Quantum Leaps, LLC. All rights reserved. -* -* This program is open source software: you can redistribute it and/or -* modify it under the terms of the GNU General Public License as published -* by the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* Alternatively, this program may be distributed and modified under the -* terms of Quantum Leaps commercial licenses, which expressly supersede -* the GNU General Public License and are specifically designed for -* licensees interested in retaining the proprietary status of their code. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -* -* Contact information: -* -* -****************************************************************************** -* @endcond -*/ -#ifndef SAFE_STD_H -#define SAFE_STD_H - -#include -#include - -/* portable "safe" facilities from and ................*/ -#ifdef _WIN32 /* Windows OS? */ - -#define MEMMOVE_S(dest_, num_, src_, count_) \ - memmove_s(dest_, num_, src_, count_) - -#define STRNCPY_S(dest_, destsiz_, src_) \ - strncpy_s(dest_, destsiz_, src_, _TRUNCATE) - -#define STRCAT_S(dest_, destsiz_, src_) \ - strcat_s(dest_, destsiz_, src_) - -#define SNPRINTF_S(buf_, bufsiz_, format_, ...) \ - _snprintf_s(buf_, bufsiz_, _TRUNCATE, format_, ##__VA_ARGS__) - -#define PRINTF_S(format_, ...) \ - printf_s(format_, ##__VA_ARGS__) - -#define FPRINTF_S(fp_, format_, ...) \ - fprintf_s(fp_, format_, ##__VA_ARGS__) - -#ifdef _MSC_VER -#define FREAD_S(buf_, bufsiz_, elsiz_, count_, fp_) \ - fread_s(buf_, bufsiz_, elsiz_, count_, fp_) -#else -#define FREAD_S(buf_, bufsiz_, elsiz_, count_, fp_) \ - fread(buf_, elsiz_, count_, fp_) -#endif /* _MSC_VER */ - -#define FOPEN_S(fp_, fName_, mode_) \ -if (fopen_s(&fp_, fName_, mode_) != 0) { \ - fp_ = (FILE *)0; \ -} else (void)0 - -#define LOCALTIME_S(tm_, time_) \ - localtime_s(tm_, time_) - -#else /* other OS (Linux, MacOS, etc.) .....................................*/ - -#define MEMMOVE_S(dest_, num_, src_, count_) \ - memmove(dest_, src_, count_) - -#define STRNCPY_S(dest_, destsiz_, src_) do { \ - strncpy(dest_, src_, destsiz_); \ - dest_[(destsiz_) - 1] = '\0'; \ -} while (false) - -#define STRCAT_S(dest_, destsiz_, src_) \ - strcat(dest_, src_) - -#define SNPRINTF_S(buf_, bufsiz_, format_, ...) \ - snprintf(buf_, bufsiz_, format_, ##__VA_ARGS__) - -#define PRINTF_S(format_, ...) \ - printf(format_, ##__VA_ARGS__) - -#define FPRINTF_S(fp_, format_, ...) \ - fprintf(fp_, format_, ##__VA_ARGS__) - -#define FREAD_S(buf_, bufsiz_, elsiz_, count_, fp_) \ - fread(buf_, elsiz_, count_, fp_) - -#define FOPEN_S(fp_, fName_, mode_) \ - (fp_ = fopen(fName_, mode_)) - -#define LOCALTIME_S(tm_, time_) \ - memcpy(tm_, localtime(time_), sizeof(struct tm)) - -#endif /* _WIN32 */ - -#endif /* SAFE_STD_H */ diff --git a/ports/posix-qv/qf_port.cpp b/ports/posix-qv/qf_port.cpp index 620f07bda..6c40e563f 100644 --- a/ports/posix-qv/qf_port.cpp +++ b/ports/posix-qv/qf_port.cpp @@ -22,8 +22,8 @@ // // //============================================================================ -//! @date Last updated on: 2024-07-18 -//! @version Last updated for: @ref qpcpp_7_4_0 +//! @date Last updated on: 2024-09-19 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QF/C++ port to POSIX-QV (single-threaded) @@ -258,8 +258,8 @@ int run() { QF_CRIT_ENTRY(); // produce the QS_QF_RUN trace record - QS_BEGIN_PRE_(QS_QF_RUN, 0U) - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_RUN, 0U) + QS_END_PRE() while (l_isRunning) { Q_ASSERT_INCRIT(300, readySet_.verify_(&readySet_dis_)); @@ -374,7 +374,7 @@ int consoleWaitForKey() { // QActive functions ========================================================= void QActive::start(QPrioSpec const prioSpec, - QEvt const * * const qSto, std::uint_fast16_t const qLen, + QEvtPtr * const qSto, std::uint_fast16_t const qLen, void * const stkSto, std::uint_fast16_t const stkSize, void const * const par) { diff --git a/ports/posix-qv/qp_port.hpp b/ports/posix-qv/qp_port.hpp index 3da4e54b8..578521bd5 100644 --- a/ports/posix-qv/qp_port.hpp +++ b/ports/posix-qv/qp_port.hpp @@ -1,34 +1,34 @@ //============================================================================ // 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 // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC . -// // 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: +// 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. // -// Contact information: +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: // // //============================================================================ -//! @date Last updated on: 2024-02-16 -//! @version Last updated for: @ref qpcpp_7_3_3 +//! @date Last updated on: 2024-09-30 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QP/C++ port to POSIX-QV (signgle threaded), generic C++11 @@ -36,11 +36,8 @@ #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ -#include // Exact-width types. C++11 Standard - -#ifdef QP_CONFIG -#include "qp_config.hpp" // external QP configuration -#endif +#include // Exact-width types. C++11 Standard +#include "qp_config.hpp" // QP configuration from the application // no-return function specifier (C++11 Standard) #define Q_NORETURN [[ noreturn ]] void @@ -98,8 +95,7 @@ void onClockTick(); #define QF_SCHED_UNLOCK_() (static_cast(0)) // QF event queue customization for POSIX-QV... - #define QACTIVE_EQUEUE_WAIT_(me_) \ - Q_ASSERT_INCRIT(302, (me_)->m_eQueue.m_frontEvt != nullptr) + #define QACTIVE_EQUEUE_WAIT_(me_) (static_cast(0)) #ifndef Q_UNSAFE #define QACTIVE_EQUEUE_SIGNAL_(me_) \ diff --git a/ports/posix-qv/qs_port.cpp b/ports/posix-qv/qs_port.cpp index d9a88ea60..a0a72ab5b 100644 --- a/ports/posix-qv/qs_port.cpp +++ b/ports/posix-qv/qs_port.cpp @@ -23,7 +23,7 @@ // //============================================================================ //! @date Last updated on: 2024-07-18 -//! @version Last updated for: @ref qpcpp_7_4_0 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QS/C++ port to POSIX diff --git a/ports/posix-qv/qs_port.hpp b/ports/posix-qv/qs_port.hpp index 2cf165e8f..c66fa9711 100644 --- a/ports/posix-qv/qs_port.hpp +++ b/ports/posix-qv/qs_port.hpp @@ -28,7 +28,7 @@ // //============================================================================ //! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_7_4_0 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QS/C++ port to POSIX/Win32 diff --git a/ports/posix/qf_port.cpp b/ports/posix/qf_port.cpp index 7a00bbc15..77751cf51 100644 --- a/ports/posix/qf_port.cpp +++ b/ports/posix/qf_port.cpp @@ -22,8 +22,8 @@ // // //============================================================================ -//! @date Last updated on: 2024-07-18 -//! @version Last updated for: @ref qpcpp_7_4_0 +//! @date Last updated on: 2024-09-19 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QF/C++ port to POSIX (multithreaded with P-threads) @@ -170,8 +170,8 @@ int run() { onStartup(); // application-specific startup callback // produce the QS_QF_RUN trace record - QS_BEGIN_PRE_(QS_QF_RUN, 0U) - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_RUN, 0U) + QS_END_PRE() // try to set the priority of the ticker thread, see NOTE01 struct sched_param sparam; @@ -314,7 +314,7 @@ void QActive::evtLoop_(QActive *act) { //============================================================================ void QActive::start(QPrioSpec const prioSpec, - QEvt const * * const qSto, std::uint_fast16_t const qLen, + QEvtPtr * const qSto, std::uint_fast16_t const qLen, void * const stkSto, std::uint_fast16_t const stkSize, void const * const par) { diff --git a/ports/posix/qp_port.hpp b/ports/posix/qp_port.hpp index 89453c91f..b773b98ad 100644 --- a/ports/posix/qp_port.hpp +++ b/ports/posix/qp_port.hpp @@ -1,34 +1,34 @@ //============================================================================ // 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 // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC . -// // 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: +// 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. // -// Contact information: +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: // // //============================================================================ -//! @date Last updated on: 2024-02-16 -//! @version Last updated for: @ref qpcpp_7_3_3 +//! @date Last updated on: 2024-09-30 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QP/C++ port to POSIX (multithreaded with P-threads), generic C++11 @@ -36,12 +36,9 @@ #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ -#include // Exact-width types. C++11 Standard -#include // POSIX-thread API - -#ifdef QP_CONFIG -#include "qp_config.hpp" // external QP configuration -#endif +#include // Exact-width types. C++11 Standard +#include // POSIX-thread API +#include "qp_config.hpp" // QP configuration from the application // no-return function specifier (C++11 Standard) #define Q_NORETURN [[ noreturn ]] void @@ -100,7 +97,7 @@ void onClockTick(); // QF event queue customization for POSIX... #define QACTIVE_EQUEUE_WAIT_(me_) do { \ while ((me_)->m_eQueue.m_frontEvt == nullptr) { \ - Q_ASSERT_INCRIT(301, QF::critSectNest_ == 1); \ + Q_ASSERT_INCRIT(400, QF::critSectNest_ == 1); \ --QF::critSectNest_; \ pthread_cond_wait(&(me_)->m_osObject, &QF::critSectMutex_); \ Q_ASSERT_INCRIT(302, QF::critSectNest_ == 0); \ diff --git a/ports/posix/qs_port.cpp b/ports/posix/qs_port.cpp index d9a88ea60..a0a72ab5b 100644 --- a/ports/posix/qs_port.cpp +++ b/ports/posix/qs_port.cpp @@ -23,7 +23,7 @@ // //============================================================================ //! @date Last updated on: 2024-07-18 -//! @version Last updated for: @ref qpcpp_7_4_0 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QS/C++ port to POSIX diff --git a/ports/posix/qs_port.hpp b/ports/posix/qs_port.hpp index 2cf165e8f..c66fa9711 100644 --- a/ports/posix/qs_port.hpp +++ b/ports/posix/qs_port.hpp @@ -28,7 +28,7 @@ // //============================================================================ //! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_7_4_0 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QS/C++ port to POSIX/Win32 diff --git a/ports/qep-only/qp_port.hpp b/ports/qep-only/qp_port.hpp index 4da389b20..78ca54379 100644 --- a/ports/qep-only/qp_port.hpp +++ b/ports/qep-only/qp_port.hpp @@ -1,34 +1,34 @@ //============================================================================ // 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 // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC . -// // 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: +// 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. // -// Contact information: +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: // // //============================================================================ -//! @date Last updated on: 2023-09-07 -//! @version Last updated for: @ref qpcpp_7_3_0 +//! @date Last updated on: 2024-09-30 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QP/C dummy port @@ -36,26 +36,12 @@ #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ -#include // Exact-width types. C++11 Standard - -#ifdef QP_CONFIG -#include "qp_config.hpp" // external QP configuration -#endif - // no-return function specifier (C++11 Standard) #define Q_NORETURN [[ noreturn ]] void -#define QF_MAX_EPOOL 0U - -#define QF_CRIT_STAT -#define QF_CRIT_ENTRY() (static_cast(0)) -#define QF_CRIT_EXIT() (static_cast(0)) - -#define QF_MEM_SYS() (static_cast(0)) -#define QF_MEM_APP() (static_cast(0)) - // include files ------------------------------------------------------------- -#include "qp.hpp" // QP platform-independent public interface +#include // Exact-width types. C++11 Standard +#include "qp_config.hpp" // QP configuration from the application +#include "qp.hpp" // QP platform-independent public interface #endif // QP_PORT_HPP_ - diff --git a/ports/threadx/qf_port.cpp b/ports/threadx/qf_port.cpp index 0e3af62f6..bff26435d 100644 --- a/ports/threadx/qf_port.cpp +++ b/ports/threadx/qf_port.cpp @@ -1,29 +1,32 @@ //============================================================================ -// 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. +// Q u a n t u m L e a P s +// ------------------------ +// Modern Embedded Software // -// The terms of the open source GNU General Public License version 3 -// can be found at: +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The terms of the closed source Quantum Leaps commercial licenses -// can be found at: +// 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. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2024-06-11 -//! @version Last updated for: @ref qpcpp_7_4_0 +//! @date Last updated on: 2024-09-26 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QF/C++ port to ThreadX (a.k.a. Azure RTOS), generic C++11 compiler @@ -56,6 +59,9 @@ namespace QP { //............................................................................ void QF::init() { + bzero_(&QF::priv_, sizeof(QF::priv_)); + bzero_(&QActive::registry_[0], sizeof(QActive::registry_)); + // nothing to do for ThreadX } //............................................................................ int QF::run() { @@ -64,15 +70,15 @@ int QF::run() { // produce the QS_QF_RUN trace record QS_CRIT_STAT QS_CRIT_ENTRY(); - QS_BEGIN_PRE_(QS_QF_RUN, 0U) - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_RUN, 0U) + QS_END_PRE() QS_CRIT_EXIT(); return 0; // return success } //............................................................................ void QF::stop() { - onCleanup(); // cleanup callback + onCleanup(); // cleanup callback } // thread for active objects ------------------------------------------------- @@ -83,35 +89,34 @@ void QActive::evtLoop_(QActive *act) { QF::gc(e); // check if the event is garbage, and collect it if so } } - //............................................................................ void QActive::start(QPrioSpec const prioSpec, - QEvt const * * const qSto, std::uint_fast16_t const qLen, + QEvtPtr * const qSto, std::uint_fast16_t const qLen, void * const stkSto, std::uint_fast16_t const stkSize, void const * const par) { + m_prio = static_cast(prioSpec & 0xFFU); // QF-priority + m_pthre = static_cast(prioSpec >> 8U); // QF preemption-thre. + register_(); // make QF aware of this AO + // create the ThreadX message queue for the AO UINT tx_err = tx_queue_create(&m_eQueue, - m_thread.tx_thread_name, - TX_1_ULONG, - static_cast(qSto), - static_cast(qLen * sizeof(ULONG))); + m_thread.tx_thread_name, + TX_1_ULONG, + static_cast(qSto), + static_cast(qLen * sizeof(QEvtPtr))); QF_CRIT_STAT QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(210, tx_err == TX_SUCCESS); + Q_ASSERT_INCRIT(110, tx_err == TX_SUCCESS); QF_CRIT_EXIT(); - m_prio = static_cast(prioSpec & 0xFFU); // QF-priority - m_pthre = static_cast(prioSpec >> 8U); // QF preemption-thre. - register_(); // make QF aware of this AO - // top-most initial tran. (virtual call) init(par, m_prio); QS_FLUSH(); // flush the trace buffer to the host - UINT tx_prio = QF_TX_PRIO_OFFSET + QF_MAX_ACTIVE - m_prio; - UINT tx_pt = QF_TX_PRIO_OFFSET + QF_MAX_ACTIVE - m_pthre; + UINT tx_prio = QF_TO_TX_PRIO_MAP(m_prio); + UINT tx_pt = QF_TO_TX_PRIO_MAP(m_pthre); tx_err = tx_thread_create( &m_thread, // ThreadX thread control block m_thread.tx_thread_name, // unique thread name @@ -125,16 +130,16 @@ void QActive::start(QPrioSpec const prioSpec, TX_AUTO_START); QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(220, tx_err == TX_SUCCESS); + Q_ASSERT_INCRIT(120, tx_err == TX_SUCCESS); QF_CRIT_EXIT(); } //............................................................................ void QActive::setAttr(std::uint32_t const attr1, void const *attr2) { - // this function must be called before QACTIVE_START(), + // this function must be called before QActive::start(), // which implies that m_thread.tx_thread_name must not be used yet; QF_CRIT_STAT QF_CRIT_ENTRY(); - Q_REQUIRE_INCRIT(300, m_thread.tx_thread_name == nullptr); + Q_REQUIRE_INCRIT(150, m_thread.tx_thread_name == nullptr); switch (attr1) { case THREAD_NAME_ATTR: @@ -152,8 +157,18 @@ void QActive::setAttr(std::uint32_t const attr1, void const *attr2) { bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin, void const * const sender) noexcept { +#ifndef Q_SPY + Q_UNUSED_PAR(sender); +#endif + QF_CRIT_STAT QF_CRIT_ENTRY(); + + Q_REQUIRE_INCRIT(200, e != nullptr); +#ifndef Q_UNSAFE + Q_INVARIANT_INCRIT(201, e->verify_()); +#endif // ndef Q_UNSAFE + std::uint_fast16_t nFree = static_cast(m_eQueue.tx_queue_available_storage); @@ -164,7 +179,7 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin, } else { status = false; // cannot post - Q_ERROR_INCRIT(510); // must be able to post the event + Q_ERROR_INCRIT(210); // must be able to post the event } } else if (nFree > static_cast(margin)) { @@ -176,41 +191,42 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin, if (status) { // can post the event? - QS_BEGIN_PRE_(QS_QF_ACTIVE_POST, m_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_(this); // this active object (recipient) - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_EQC_PRE_(nFree); // # free entries - QS_EQC_PRE_(0U); // min # free entries (unknown) - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_ACTIVE_POST, m_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(this); // this active object (recipient) + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_EQC_PRE(nFree); // # free entries available + QS_EQC_PRE(0U); // min # free entries (unknown) + QS_END_PRE() if (e->getPoolNum_() != 0U) { // is it a pool event? QEvt_refCtr_inc_(e); // increment the reference counter } QF_CRIT_EXIT(); - UINT tx_err = tx_queue_send(&m_eQueue, const_cast(&e), + UINT tx_err = tx_queue_send(&m_eQueue, const_cast(&e), TX_NO_WAIT); QF_CRIT_ENTRY(); // posting to the ThreadX message queue must succeed, see NOTE3 - Q_ASSERT_INCRIT(520, tx_err == TX_SUCCESS); + Q_ASSERT_INCRIT(220, tx_err == TX_SUCCESS); + QF_CRIT_EXIT(); } else { - QS_BEGIN_PRE_(QS_QF_ACTIVE_POST_ATTEMPT, m_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_(this); // this active object (recipient) - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_EQC_PRE_(nFree); // # free entries - QS_EQC_PRE_(margin); // margin requested - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_ACTIVE_POST_ATTEMPT, m_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(this); // this active object (recipient) + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_EQC_PRE(nFree); // # free entries + QS_EQC_PRE(0U); // min # free entries (unknown) + QS_END_PRE() + QF_CRIT_EXIT(); } - QF_CRIT_EXIT(); return status; } @@ -219,44 +235,50 @@ void QActive::postLIFO(QEvt const * const e) noexcept { QF_CRIT_STAT QF_CRIT_ENTRY(); - QS_BEGIN_PRE_(QS_QF_ACTIVE_POST_LIFO, m_prio) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of this event - QS_OBJ_PRE_(this); // this active object - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_EQC_PRE_(m_eQueue.tx_queue_available_storage); // # free - QS_EQC_PRE_(0U); // min # free entries (unknown) - QS_END_PRE_() + Q_REQUIRE_INCRIT(300, e != nullptr); +#ifndef Q_UNSAFE + Q_INVARIANT_INCRIT(301, e->verify_()); +#endif // ndef Q_UNSAFE + + + QS_BEGIN_PRE(QS_QF_ACTIVE_POST_LIFO, m_prio) + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(e->sig); // the signal of this event + QS_OBJ_PRE(this); // this active object + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_EQC_PRE(m_eQueue.tx_queue_available_storage); // # free + QS_EQC_PRE(0U); // min # free entries (unknown) + QS_END_PRE() if (e->getPoolNum_() != 0U) { // is it a pool event? QEvt_refCtr_inc_(e); // increment the reference counter } QF_CRIT_EXIT(); - UINT tx_err = tx_queue_front_send(&m_eQueue, const_cast(&e), + UINT tx_err = tx_queue_front_send(&m_eQueue, const_cast(&e), TX_NO_WAIT); - // LIFO posting must succeed, see NOTE3 + QF_CRIT_ENTRY(); - // posting to the embOS mailbox must succeed, see NOTE3 - Q_ASSERT_INCRIT(610, tx_err == TX_SUCCESS); + // LIFO posting must succeed, see NOTE3 + Q_ASSERT_INCRIT(310, tx_err == TX_SUCCESS); QF_CRIT_EXIT(); } //............................................................................ QEvt const *QActive::get_(void) noexcept { - QEvt const *e; + QEvtPtr e; UINT tx_err = tx_queue_receive(&m_eQueue, (VOID *)&e, TX_WAIT_FOREVER); QF_CRIT_STAT QF_CRIT_ENTRY(); Q_ASSERT_INCRIT(710, tx_err == TX_SUCCESS); - QS_BEGIN_PRE_(QS_QF_ACTIVE_GET, m_prio) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of this event - QS_OBJ_PRE_(this); // this active object - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_EQC_PRE_(m_eQueue.tx_queue_available_storage); // # free - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_ACTIVE_GET, m_prio) + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(e->sig); // the signal of this event + QS_OBJ_PRE(this); // this active object + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_EQC_PRE(m_eQueue.tx_queue_available_storage); // # free + QS_END_PRE() QF_CRIT_EXIT(); return e; @@ -275,18 +297,18 @@ void QFSchedLock::lock(std::uint_fast8_t prio) { // change the preemption threshold of the current thread UINT tx_err = tx_thread_preemption_change(m_lockHolder, - (QF_TX_PRIO_OFFSET + QF_MAX_ACTIVE - prio), + QF_TO_TX_PRIO_MAP(prio), &m_prevThre); if (tx_err == TX_SUCCESS) { m_lockPrio = prio; QF_CRIT_ENTRY(); - QS_BEGIN_PRE_(QS_SCHED_LOCK, 0U) - QS_TIME_PRE_(); // timestamp - QS_2U8_PRE_(QF_TX_PRIO_OFFSET + QF_MAX_ACTIVE - m_prevThre, + QS_BEGIN_PRE(QS_SCHED_LOCK, 0U) + QS_TIME_PRE(); // timestamp + QS_2U8_PRE(TX_TO_QF_PRIO_MAP(m_prevThre), prio); // new lock prio - QS_END_PRE_() + QS_END_PRE() QF_CRIT_EXIT(); } else if (tx_err == TX_THRESH_ERROR) { @@ -303,19 +325,21 @@ void QFSchedLock::lock(std::uint_fast8_t prio) { //............................................................................ void QFSchedLock::unlock(void) const { + QF_CRIT_STAT QF_CRIT_ENTRY(); // the lock holder must be valid and the scheduler must be locked Q_REQUIRE_INCRIT(900, (m_lockHolder != nullptr) - && (m_lockPrio != 0U)); + && (m_lockPrio != 0U)); - QS_BEGIN_PRE_(QS_SCHED_UNLOCK, 0U) - QS_TIME_PRE_(); // timestamp - QS_2U8_PRE_(m_lockPrio,/* prev lock prio */ - QF_TX_PRIO_OFFSET + QF_MAX_ACTIVE - m_prevThre); - QS_END_PRE_() + QS_BEGIN_PRE(QS_SCHED_UNLOCK, 0U) + QS_TIME_PRE(); // timestamp + QS_2U8_PRE(m_lockPrio, // prev lock prio + TX_TO_QF_PRIO_MAP(m_prevThre)); // new lock prio + QS_END_PRE() QF_CRIT_EXIT(); + // restore the preemption threshold of the lock holder UINT old_thre; UINT tx_err = tx_thread_preemption_change(m_lockHolder, m_prevThre, &old_thre); @@ -326,3 +350,17 @@ void QFSchedLock::unlock(void) const { } // namespace QP +//============================================================================ +// NOTE1: +// When QF preemption threshold is NOT specified (upper byte of prio is 0), +// QActive::register_() will set m_pthre equal to m_prio, which means +// that tx_pt == tx_prio. In that case the call to ThreadX tx_thread_create() +// will disable the ThreadX preemption-threshold for this thread. +// +// NOTE3: +// The event posting to ThreadX 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/threadx/qp_port.hpp b/ports/threadx/qp_port.hpp index e90a9f57e..fd669ca32 100644 --- a/ports/threadx/qp_port.hpp +++ b/ports/threadx/qp_port.hpp @@ -1,34 +1,34 @@ //============================================================================ // 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 // ------------------------ // 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: +// 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. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2023-09-07 -//! @version Last updated for: @ref qpcpp_7_3_0 +//! @date Last updated on: 2024-09-30 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QP/C++ port to ThreadX (a.k.a, Azure RTOS), generic C++11 compiler @@ -36,27 +36,38 @@ #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ -#include // Exact-width types. C++11 Standard - -#ifdef QP_CONFIG -#include "qp_config.hpp" // external QP configuration -#endif +#include // Exact-width types. C++11 Standard +#include "qp_config.hpp" // QP configuration from the application // no-return function specifier (C++11 Standard) #define Q_NORETURN [[ noreturn ]] void // QActive customization for ThreadX #define QACTIVE_EQUEUE_TYPE TX_QUEUE -#define QACTIVE_OS_OBJ_TYPE bool #define QACTIVE_THREAD_TYPE TX_THREAD +#define QACTIVE_OS_OBJ_TYPE std::uint8_t -// QF priority offset within ThreadX priority numbering scheme, see NOTE1 -#define QF_TX_PRIO_OFFSET 8U +// QF priority offset within ThreadX priority numbering scheme +#define QF_TX_PRIO_OFFSET 2U + +#ifndef QF_MAX_ACTIVE +#define QF_MAX_ACTIVE (TX_MAX_PRIORITIES - QF_TX_PRIO_OFFSET) +#else +#error "QF_MAX_ACTIVE shouild not be externally defined in QP-ThreadX port" +#endif + +// mapping between QF-priority and TX-priority, see NOTE1 +#define QF_TO_TX_PRIO_MAP(qp_prio_) \ + (TX_MAX_PRIORITIES - QF_TX_PRIO_OFFSET - (qp_prio_)) + +// mapping between TX-priority and QF-priority, see NOTE1 +#define TX_TO_QF_PRIO_MAP(tx_prio_) \ + (TX_MAX_PRIORITIES - QF_TX_PRIO_OFFSET - (tx_prio_)) // QF critical section for ThreadX, see NOTE3 -#define QF_CRIT_STAT UINT int_ctrl_; -#define QF_CRIT_ENTRY() (int_ctrl_ = tx_interrupt_control(TX_INT_DISABLE)) -#define QF_CRIT_EXIT() ((void)tx_interrupt_control(int_ctrl_)) +#define QF_CRIT_STAT UINT int_ctrl_; +#define QF_CRIT_ENTRY() (int_ctrl_ = tx_interrupt_control(TX_INT_DISABLE)) +#define QF_CRIT_EXIT() ((void)tx_interrupt_control(int_ctrl_)) // include files ------------------------------------------------------------- #include "tx_api.h" // ThreadX API @@ -65,7 +76,6 @@ #include "qmpool.hpp" // QP memory pool (for event pools) #include "qp.hpp" // QP platform-independent public interface - namespace QP { enum ThreadX_ThreadAttrs { @@ -74,10 +84,8 @@ enum ThreadX_ThreadAttrs { } // namespace QP - //============================================================================ -// interface used only inside QF, but not in applications - +// interface used only inside QF implementation, but not in applications #ifdef QP_IMPL // ThreadX-specific scheduler locking (implemented in qf_port.cpp) @@ -87,7 +95,7 @@ enum ThreadX_ThreadAttrs { lockStat_.m_lockPrio = 0U; \ } else { \ lockStat_.lock((prio_)); \ - } \ + } \ } while (false) #define QF_SCHED_UNLOCK_() do { \ if (lockStat_.m_lockPrio != 0U) { \ @@ -97,9 +105,9 @@ enum ThreadX_ThreadAttrs { namespace QP { struct QFSchedLock { - uint_fast8_t m_lockPrio; //!< lock prio [QF numbering scheme] - UINT m_prevThre; //!< previoius preemption threshold - TX_THREAD *m_lockHolder; //!< the thread holding the lock + uint_fast8_t m_lockPrio; // lock prio [QF numbering scheme] + UINT m_prevThre; // previoius preemption threshold + TX_THREAD *m_lockHolder; // the thread holding the lock void lock(uint_fast8_t prio); void unlock(void) const; @@ -123,15 +131,13 @@ enum ThreadX_ThreadAttrs { //============================================================================ // NOTE1: -// QF_TX_PRIO_OFFSET specifies the number of highest-urgency ThreadX -// priorities not available to QP active objects. These highest-urgency -// priorities might be used by ThreadX threads that run "above" QP active -// objects. -// // Because the ThreadX priority numbering is "upside down" compared // to the QP priority numbering, the ThreadX priority for an active object -// thread is calculated as follows: -// tx_prio = QF_TX_PRIO_OFFSET + QF_MAX_ACTIVE - qp_prio +// thread is calculated as specified in the macro QF_TO_TX_PRIO_MAP(prio_). +// This mapping leaves the QF_TX_PRIO_OFFSET number of lowest-priority +// ThreadX threads NOT available as threads for QP Active Objects. The use +// of such lowest-priority ThredX threads is, for example, to emulate idle +// thread, etc. // // NOTE3: // The ThreadX critical section must be able to nest, which is the case with diff --git a/ports/threadx/qs_port.hpp b/ports/threadx/qs_port.hpp index 4ddb938b5..7da8a41ae 100644 --- a/ports/threadx/qs_port.hpp +++ b/ports/threadx/qs_port.hpp @@ -28,7 +28,7 @@ // //============================================================================ //! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_7_4_0 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler diff --git a/ports/uc-os2/qf_port.cpp b/ports/uc-os2/qf_port.cpp index b5f87bb9f..ecb945e5a 100644 --- a/ports/uc-os2/qf_port.cpp +++ b/ports/uc-os2/qf_port.cpp @@ -1,29 +1,32 @@ //============================================================================ -// 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. +// Q u a n t u m L e a P s +// ------------------------ +// Modern Embedded Software // -// The terms of the open source GNU General Public License version 3 -// can be found at: +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The terms of the closed source Quantum Leaps commercial licenses -// can be found at: +// 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. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2024-06-11 -//! @version Last updated for: @ref qpcpp_7_4_0 +//! @date Last updated on: 2024-09-26 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QF/C++ port to uC-OS2 RTOS, generic C++11 compiler @@ -66,8 +69,8 @@ int QF::run() { // produce the QS_QF_RUN trace record QS_CRIT_STAT QS_CRIT_ENTRY(); - QS_BEGIN_PRE_(QS_QF_RUN, 0U) - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_RUN, 0U) + QS_END_PRE() QS_CRIT_EXIT(); OSStart(); // start uC-OS2 multitasking, should never return @@ -91,9 +94,9 @@ void QActive::evtLoop_(QActive *act) { //............................................................................ void QActive::start(QPrioSpec const prioSpec, - QEvt const * * const qSto, std::uint_fast16_t const qLen, - void * const stkSto, std::uint_fast16_t const stkSize, - void const * const par) + QEvtPtr * const qSto, std::uint_fast16_t const qLen, + void * const stkSto, std::uint_fast16_t const stkSize, + void const * const par) { // task name to be passed to OSTaskCreateExt() void * const task_name = static_cast(m_eQueue); @@ -104,7 +107,7 @@ void QActive::start(QPrioSpec const prioSpec, QF_CRIT_STAT QF_CRIT_ENTRY(); // the uC-OS2 queue must be created correctly - Q_ASSERT_INCRIT(210, m_eQueue != nullptr); + Q_ASSERT_INCRIT(110, m_eQueue != nullptr); QF_CRIT_EXIT(); m_prio = static_cast(prioSpec & 0xFFU); // QF-priority @@ -168,17 +171,22 @@ void QActive::start(QPrioSpec const prioSpec, // uC-OS2 task must be created correctly Q_ASSERT_INCRIT(220, err == OS_ERR_NONE); QF_CRIT_EXIT(); + +#ifdef Q_UNSAFE + Q_UNUSED_PAR(err); +#endif } //............................................................................ -// NOTE: This function must be called BEFORE starting an active object void QActive::setAttr(std::uint32_t attr1, void const *attr2) { + // NOTE: this function must be called *before* QActive_start(), + // which implies that me->thread.tx_thread_name must not be used yet; QF_CRIT_STAT QF_CRIT_ENTRY(); switch (attr1) { case TASK_NAME_ATTR: - // this function must be called before QACTIVE_START(), + // this function must be called before QActive_start(), // which implies that m_eQueue must not be used yet; - Q_ASSERT_INCRIT(300, m_eQueue == nullptr); + Q_ASSERT_INCRIT(150, m_eQueue == nullptr); // temporarily store the name, cast 'const' away m_eQueue = static_cast( const_cast(attr2)); @@ -197,6 +205,12 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin, { QF_CRIT_STAT QF_CRIT_ENTRY(); + + Q_REQUIRE_INCRIT(200, e != nullptr); +#ifndef Q_UNSAFE + Q_INVARIANT_INCRIT(201, e->verify_()); +#endif + std::uint_fast16_t const nFree = static_cast( reinterpret_cast(m_eQueue)->OSQSize - reinterpret_cast(m_eQueue)->OSNMsgs); @@ -204,15 +218,15 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin, bool status; if (margin == QF::NO_MARGIN) { if (nFree > 0U) { - status = true; // can post + status = true; // can post } else { status = false; // cannot post - Q_ERROR_INCRIT(710); // must be able to post the event + Q_ERROR_INCRIT(210); // must be able to post the event } } else if (nFree > static_cast(margin)) { - status = true; // can post + status = true; // can post } else { status = false; // cannot post @@ -220,40 +234,43 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin, if (status) { // can post the event? - QS_BEGIN_PRE_(QS_QF_ACTIVE_POST, m_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_(this); // this active object (recipient) - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_);// pool-Id & ref-Count - QS_EQC_PRE_(nFree); // # free entries - QS_EQC_PRE_(0U); // min # free entries (unknown) - QS_END_PRE_() - - if (e->getPoolNum_() != 0U) { // is it a pool event? + QS_BEGIN_PRE(QS_QF_ACTIVE_POST, m_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(this); // this active object (recipient) + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_EQC_PRE(nFree); // # free entries + QS_EQC_PRE(0U); // min # free entries (unknown) + QS_END_PRE() + + if (e->getPoolNum_() != 0U) { // is it a pool event? QEvt_refCtr_inc_(e); // increment the reference counter } - QF_CRIT_EXIT(); INT8U err = OSQPost(m_eQueue, const_cast(e)); QF_CRIT_ENTRY(); // posting to uC-OS2 message queue must succeed, see NOTE3 - Q_ASSERT_INCRIT(720, err == OS_ERR_NONE); + Q_ASSERT_INCRIT(220, err == OS_ERR_NONE); QF_CRIT_EXIT(); + +#ifdef Q_UNSAFE + Q_UNUSED_PAR(err); +#endif } else { - QS_BEGIN_PRE_(QS_QF_ACTIVE_POST_ATTEMPT, m_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_(this); // this active object (recipient) - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_);// pool-Id & ref-Count - QS_EQC_PRE_(nFree); // # free entries - QS_EQC_PRE_(margin); // margin requested - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_ACTIVE_POST_ATTEMPT, m_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(this); // this active object (recipient) + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_EQC_PRE(nFree); // # free entries available + QS_EQC_PRE(margin); // margin requested + QS_END_PRE() QF_CRIT_EXIT(); } @@ -265,18 +282,23 @@ void QActive::postLIFO(QEvt const * const e) noexcept { QF_CRIT_STAT QF_CRIT_ENTRY(); - QS_BEGIN_PRE_(QS_QF_ACTIVE_POST_LIFO, m_prio) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of this event - QS_OBJ_PRE_(this); // this active object - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // pool-Id & ref-Count - // # free entries - QS_EQC_PRE_(reinterpret_cast(m_eQueue)->OSQSize + Q_REQUIRE_INCRIT(300, e != nullptr); +#ifndef Q_UNSAFE + Q_INVARIANT_INCRIT(301, e->verify_()); +#endif + + QS_BEGIN_PRE(QS_QF_ACTIVE_POST_LIFO, m_prio) + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(e->sig); // the signal of this event + QS_OBJ_PRE(this); // this active object + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + // # free entries + QS_EQC_PRE(reinterpret_cast(m_eQueue)->OSQSize - reinterpret_cast(m_eQueue)->OSQEntries); - QS_EQC_PRE_(0U); // min # free (unknown) - QS_END_PRE_() + QS_EQC_PRE(0U); // min # free entries (unknown) + QS_END_PRE() - if (e->getPoolNum_() != 0U) { // is it a pool event? + if (e->getPoolNum_() != 0U) { // is it a pool event? QEvt_refCtr_inc_(e); // increment the reference counter } QF_CRIT_EXIT(); @@ -285,8 +307,12 @@ void QActive::postLIFO(QEvt const * const e) noexcept { QF_CRIT_ENTRY(); // posting to uC-OS2 message queue must succeed, see NOTE3 - Q_ASSERT_INCRIT(810, err == OS_ERR_NONE); + Q_ASSERT_INCRIT(310, err == OS_ERR_NONE); QF_CRIT_EXIT(); + +#ifdef Q_UNSAFE + Q_UNUSED_PAR(err); +#endif } //............................................................................ QEvt const *QActive::get_(void) noexcept { @@ -296,19 +322,22 @@ QEvt const *QActive::get_(void) noexcept { QF_CRIT_STAT QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(910, err == OS_ERR_NONE); - - QS_BEGIN_PRE_(QS_QF_ACTIVE_GET, m_prio) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of this event - QS_OBJ_PRE_(this); // this active object - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // pool-Id & ref-Count - // # free entries - QS_EQC_PRE_(reinterpret_cast(m_eQueue)->OSQSize + Q_ASSERT_INCRIT(410, err == OS_ERR_NONE); + + QS_BEGIN_PRE(QS_QF_ACTIVE_GET, m_prio) + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(e->sig); // the signal of this event + QS_OBJ_PRE(this); // this active object + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + // # free entries + QS_EQC_PRE(reinterpret_cast(m_eQueue)->OSQSize - reinterpret_cast(m_eQueue)->OSQEntries); - QS_END_PRE_() + QS_END_PRE() QF_CRIT_EXIT(); +#ifdef Q_UNSAFE + Q_UNUSED_PAR(err); +#endif return e; } diff --git a/ports/uc-os2/qp_port.hpp b/ports/uc-os2/qp_port.hpp index a2e8cf4fe..4a14d975e 100644 --- a/ports/uc-os2/qp_port.hpp +++ b/ports/uc-os2/qp_port.hpp @@ -1,34 +1,34 @@ //============================================================================ // 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 // ------------------------ // 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: +// 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. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2023-09-07 -//! @version Last updated for: @ref qpcpp_7_3_0 +//! @date Last updated on: 2024-09-30 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QP/C++ port to uC-OS2 RTOS, generic C++11 compiler @@ -36,11 +36,8 @@ #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ -#include // Exact-width types. C++11 Standard - -#ifdef QP_CONFIG -#include "qp_config.hpp" // external QP configuration -#endif +#include // Exact-width types. C++11 Standard +#include "qp_config.hpp" // QP configuration from the application // no-return function specifier (C++11 Standard) #define Q_NORETURN [[ noreturn ]] void diff --git a/ports/uc-os2/qs_port.hpp b/ports/uc-os2/qs_port.hpp index 4ddb938b5..7da8a41ae 100644 --- a/ports/uc-os2/qs_port.hpp +++ b/ports/uc-os2/qs_port.hpp @@ -28,7 +28,7 @@ // //============================================================================ //! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_7_4_0 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QS/C++ port to a 32-bit CPU, generic C++11 compiler diff --git a/ports/win32-qutest/CMakeLists.txt b/ports/win32-qutest/CMakeLists.txt deleted file mode 100644 index e0b6c6b57..000000000 --- a/ports/win32-qutest/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -# ports/win32-qutest -target_include_directories(qpcpp PUBLIC .) -target_sources(qpcpp PRIVATE - qutest_port.cpp -) \ No newline at end of file diff --git a/ports/win32-qutest/qp_port.hpp b/ports/win32-qutest/qp_port.hpp deleted file mode 100644 index 00d88b914..000000000 --- a/ports/win32-qutest/qp_port.hpp +++ /dev/null @@ -1,109 +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 . -// -// 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: 2024-06-10 -//! @version Last updated for: @ref qpc_7_4_0 -//! -//! @file -//! @brief QP/C++ port for QUTEST Windows, generic C++11 - -#ifndef QP_PORT_HPP_ -#define QP_PORT_HPP_ - -#include // Exact-width types. C++11 Standard - -#ifdef QP_CONFIG -#include "qp_config.hpp" // external QP configuration -#endif - -// no-return function specifier (C++11 Standard) -#define Q_NORETURN [[ noreturn ]] void - -// QActive event queue type -#define QACTIVE_EQUEUE_TYPE QEQueue - -// QF interrupt disable/enable -#define QF_INT_DISABLE() (QP::QS::onIntDisable()) -#define QF_INT_ENABLE() (QP::QS::onIntEnable()) - -// QF critical section -#define QF_CRIT_STAT -#define QF_CRIT_ENTRY() QF_INT_DISABLE() -#define QF_CRIT_EXIT() QF_INT_ENABLE() - -// QF_LOG2 not defined -- use the internal LOG2() implementation - -// include files ------------------------------------------------------------- -#include "qequeue.hpp" // QUTest port uses QEQueue event-queue -#include "qmpool.hpp" // QUTest port uses QMPool memory-pool -#include "qp.hpp" // QP platform-independent public interface - -namespace QP { -namespace QS { -void onIntDisable(); -void onIntEnable(); -} -} -//============================================================================ -// interface used only inside QF implementation, but not in applications - -#ifdef QP_IMPL - - // QUTest scheduler locking (not used) - #define QF_SCHED_STAT_ - #define QF_SCHED_LOCK_(dummy) (static_cast(0)) - #define QF_SCHED_UNLOCK_() (static_cast(0)) - - // native event queue operations - #define QACTIVE_EQUEUE_WAIT_(me_) \ - Q_ASSERT_INCRIT(305, (me_)->m_eQueue.m_frontEvt != nullptr) -#ifndef Q_UNSAFE - #define QACTIVE_EQUEUE_SIGNAL_(me_) \ - (QP::QS::tstPriv_.readySet.insert( \ - static_cast((me_)->m_prio))); \ - QP::QS::tstPriv_.readySet.update_(&QP::QS::tstPriv_.readySet_dis) -#else - #define QACTIVE_EQUEUE_SIGNAL_(me_) \ - (QP::QS::tstPriv_.readySet.insert( \ - static_cast((me_)->m_prio))) -#endif - - // native QF event pool operations - #define QF_EPOOL_TYPE_ QMPool - #define QF_EPOOL_INIT_(p_, poolSto_, poolSize_, evtSize_) \ - (p_).init((poolSto_), (poolSize_), (evtSize_)) - #define QF_EPOOL_EVENT_SIZE_(p_) ((p_).getBlockSize()) - #define QF_EPOOL_GET_(p_, e_, m_, qsId_) \ - ((e_) = static_cast((p_).get((m_), (qsId_)))) - #define QF_EPOOL_PUT_(p_, e_, qsId_) ((p_).put((e_), (qsId_))) - -#endif // QP_IMPL - -#endif // QP_PORT_HPP_ - diff --git a/ports/win32-qutest/qs_port.hpp b/ports/win32-qutest/qs_port.hpp deleted file mode 100644 index 2cf165e8f..000000000 --- a/ports/win32-qutest/qs_port.hpp +++ /dev/null @@ -1,64 +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: 2024-06-06 -//! @version Last updated for: @ref qpcpp_7_4_0 -//! -//! @file -//! @brief QS/C++ port to POSIX/Win32 - -#ifndef QS_PORT_HPP_ -#define QS_PORT_HPP_ - -#if defined(_WIN64) || defined(__LP64__) || defined(_LP64) // 64-bit OS? - #define QS_OBJ_PTR_SIZE 8U - #define QS_FUN_PTR_SIZE 8U -#else // 32-bit OS - #define QS_OBJ_PTR_SIZE 4U - #define QS_FUN_PTR_SIZE 4U -#endif - -namespace QP { -void QS_output(void); // handle the QS output -void QS_rx_input(void); // handle the QS-RX input -} - -//============================================================================ -// 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.hpp" -// *before* "qs.hpp". -#ifndef QP_PORT_HPP_ -#include "qp_port.hpp" // use QS with QP -#endif - -#include "qs.hpp" // QS platform-independent public interface - -#endif // QS_PORT_HPP_ diff --git a/ports/win32-qutest/qutest_port.cpp b/ports/win32-qutest/qutest_port.cpp deleted file mode 100644 index 34bc5a483..000000000 --- a/ports/win32-qutest/qutest_port.cpp +++ /dev/null @@ -1,299 +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: 2024-06-11 -//! @version Last updated for: @ref qpc_7_4_0 -//! -//! @file -//! @brief QUTEST port for Windows, GNU or Visual C++ - -#ifndef Q_SPY - #error "Q_SPY must be defined for QUTest application" -#endif // Q_SPY - -#define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#include "qs_port.hpp" // QS port - -#include "safe_std.h" // portable "safe" / facilities -#include -#include - -// Minimum required Windows version is Windows-XP or newer (0x0501) -#ifdef WINVER -#undef WINVER -#endif -#ifdef _WIN32_WINNT -#undef _WIN32_WINNT -#endif - -#define WINVER _WIN32_WINNT_WINXP -#define _WIN32_WINNT _WIN32_WINNT_WINXP - -#include - -#define QS_TX_SIZE (8*1024) -#define QS_RX_SIZE (2*1024) -#define QS_TX_CHUNK QS_TX_SIZE -#define QS_TIMEOUT_MS 10U - -namespace { // unnamed local namespace - -Q_DEFINE_THIS_MODULE("qutest_port") - -// local variables ........................................................... -static SOCKET l_sock = INVALID_SOCKET; - -} // unnamed local namespace - -//============================================================================ -namespace QP { - -//............................................................................ -bool QS::onStartup(void const *arg) { - - static uint8_t qsBuf[QS_TX_SIZE]; // buffer for QS-TX channel - initBuf(qsBuf, sizeof(qsBuf)); - - static uint8_t qsRxBuf[QS_RX_SIZE]; // buffer for QS-RX channel - rxInitBuf(qsRxBuf, sizeof(qsRxBuf)); - - char hostName[128]; - char const *serviceName = "6601"; // default QSPY server port - char const *src; - char *dst; - int status; - - struct addrinfo *result = NULL; - struct addrinfo *rp = NULL; - struct addrinfo hints; - BOOL sockopt_bool; - ULONG ioctl_opt; - WSADATA wsaData; - - // initialize Windows sockets version 2.2 - if (WSAStartup(MAKEWORD(2, 2), &wsaData) != NO_ERROR) { - FPRINTF_S(stderr, " ERROR %s\n", - "Windows Sockets cannot be initialized"); - goto error; - } - - // extract hostName from 'arg' (hostName:port_remote)... - src = (arg != (void *)0) - ? (char const *)arg - : "localhost"; // default QSPY host - dst = hostName; - while ((*src != '\0') - && (*src != ':') - && (dst < &hostName[sizeof(hostName) - 1])) - { - *dst++ = *src++; - } - *dst = '\0'; // zero-terminate hostName - - // extract serviceName from 'arg' (hostName:serviceName)... - if (*src == ':') { - serviceName = src + 1; - } - //printf(" Connecting to QSPY on Host=%s:%s...\n", - // hostName, serviceName); - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - status = getaddrinfo(hostName, serviceName, &hints, &result); - if (status != 0) { - FPRINTF_S(stderr, - " ERROR cannot resolve host Name=%s:%s,Err=%d\n", - hostName, serviceName, status); - goto error; - } - - for (rp = result; rp != NULL; rp = rp->ai_next) { - l_sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); - if (l_sock != INVALID_SOCKET) { - if (connect(l_sock, rp->ai_addr, static_cast(rp->ai_addrlen)) - == SOCKET_ERROR) - { - closesocket(l_sock); - l_sock = INVALID_SOCKET; - } - break; - } - } - - freeaddrinfo(result); - - // socket could not be opened & connected? - if (l_sock == INVALID_SOCKET) { - FPRINTF_S(stderr, " ERROR cannot connect to QSPY at " - "host=%s:%s\n", - hostName, serviceName); - goto error; - } - - // set the socket to non-blocking mode - ioctl_opt = 1; - if (ioctlsocket(l_sock, FIONBIO, &ioctl_opt) != NO_ERROR) { - FPRINTF_S(stderr, " ERROR %s WASErr=%d\n,", - "Failed to set non-blocking socket", WSAGetLastError()); - QF::stop(); // <== stop and exit the application - goto error; - } - - // configure the socket to reuse the address and not to linger - sockopt_bool = TRUE; - setsockopt(l_sock, SOL_SOCKET, SO_REUSEADDR, - (const char *)&sockopt_bool, sizeof(sockopt_bool)); - sockopt_bool = TRUE; - setsockopt(l_sock, SOL_SOCKET, SO_DONTLINGER, - (const char *)&sockopt_bool, sizeof(sockopt_bool)); - //PRINTF_S(" Connected to QSPY at Host=%s:%d\n", - // hostName, port_remote); - onFlush(); - - return true; // success - -error: - return false; // failure -} -//............................................................................ -void QS::onCleanup() { - Sleep(QS_TIMEOUT_MS * 10U); // allow the last QS output to come out - if (l_sock != INVALID_SOCKET) { - closesocket(l_sock); - l_sock = INVALID_SOCKET; - } - WSACleanup(); - //PRINTF_S("%s\n", " Disconnected from QSPY"); -} -//............................................................................ -void QS::onReset() { - onCleanup(); - //PRINTF_S("\n%s\n", "QS_onReset"); - exit(0); -} -//............................................................................ -void QS::onFlush() { - // NOTE: - // No critical section in QS::onFlush() to avoid nesting of critical sections - // in case QS::onFlush() is called from Q_onError(). - if (l_sock == INVALID_SOCKET) { // socket NOT initialized? - FPRINTF_S(stderr, " ERROR %s\n", - "invalid TCP socket"); - QF::stop(); // <== stop and exit the application - return; - } - - std::uint16_t nBytes = QS_TX_CHUNK; - std::uint8_t const *data; - while ((data = getBlock(&nBytes)) != nullptr) { - for (;;) { // for-ever until break or return - int nSent = send(l_sock, (char const *)data, (int)nBytes, 0); - if (nSent == SOCKET_ERROR) { // sending failed? - int err = WSAGetLastError(); - if (err == WSAEWOULDBLOCK) { - // sleep for the timeout and then loop back - // to send() the SAME data again - Sleep(QS_TIMEOUT_MS); - } - else { // some other socket error... - FPRINTF_S(stderr, " ERROR sending data over TCP," - "errno=%d\n", errno); - QF::stop(); // <== stop and exit the application - return; - } - } - else if (nSent < (int)nBytes) { // sent fewer than requested? - Sleep(QS_TIMEOUT_MS); // sleep for the timeout - // adjust the data and loop back to send() the rest - data += nSent; - nBytes -= (uint16_t)nSent; - } - else { - break; // break out of the for-ever loop - } - } - // set nBytes for the next call to QS::getBlock() - nBytes = QS_TX_CHUNK; - } -} - -//............................................................................ -void QS::onTestLoop() { - fd_set readSet; - FD_ZERO(&readSet); - - rxPriv_.inTestLoop = true; - while (rxPriv_.inTestLoop) { - FD_SET(l_sock, &readSet); - - struct timeval timeout = { - (long)0, (long)(QS_TIMEOUT_MS * 1000) - }; - - // selective, timed blocking on the TCP/IP socket... - int status = select(0, &readSet, (fd_set *)0, (fd_set *)0, &timeout); - if (status == SOCKET_ERROR) { - FPRINTF_S(stderr, - " ERROR socket select,WSAErr=%d", - WSAGetLastError()); - QF::stop(); // <== stop and exit the application - } - else if (FD_ISSET(l_sock, &readSet)) { // socket ready? - status = recv(l_sock, - (char *)QS::rxPriv_.buf, (int)QS::rxPriv_.end, 0); - if (status > 0) { // any data received? - QS::rxPriv_.tail = 0U; - QS::rxPriv_.head = status; // # bytes received - QS::rxParse(); // parse all received bytes - } - } - - onFlush(); - } - // set inTestLoop to true in case calls to QS_onTestLoop() nest, - // which can happen through the calls to QS_TEST_PAUSE(). - rxPriv_.inTestLoop = true; -} - -//............................................................................ -void QS::onIntDisable(void) { - if (tstPriv_.intLock != 0U) { - Q_onError(&Q_this_module_[0], 998); - } - ++tstPriv_.intLock; -} -//............................................................................ -void QS::onIntEnable(void) { - --tstPriv_.intLock; - if (tstPriv_.intLock != 0U) { - Q_onError(&Q_this_module_[0], 999); - } -} - -} // namespace QP - diff --git a/ports/win32-qutest/safe_std.h b/ports/win32-qutest/safe_std.h deleted file mode 100644 index 989212c12..000000000 --- a/ports/win32-qutest/safe_std.h +++ /dev/null @@ -1,115 +0,0 @@ -/** -* @file -* @brief "safe" and facilities -* @cond -****************************************************************************** -* Last updated for version 6.9.0 -* Last updated on 2020-08-24 -* -* Q u a n t u m L e a P s -* ------------------------ -* Modern Embedded Software -* -* Copyright (C) 2005-2020 Quantum Leaps, LLC. All rights reserved. -* -* This program is open source software: you can redistribute it and/or -* modify it under the terms of the GNU General Public License as published -* by the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* Alternatively, this program may be distributed and modified under the -* terms of Quantum Leaps commercial licenses, which expressly supersede -* the GNU General Public License and are specifically designed for -* licensees interested in retaining the proprietary status of their code. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -* -* Contact information: -* -* -****************************************************************************** -* @endcond -*/ -#ifndef SAFE_STD_H -#define SAFE_STD_H - -#include -#include - -/* portable "safe" facilities from and ................*/ -#ifdef _WIN32 /* Windows OS? */ - -#define MEMMOVE_S(dest_, num_, src_, count_) \ - memmove_s(dest_, num_, src_, count_) - -#define STRNCPY_S(dest_, destsiz_, src_) \ - strncpy_s(dest_, destsiz_, src_, _TRUNCATE) - -#define STRCAT_S(dest_, destsiz_, src_) \ - strcat_s(dest_, destsiz_, src_) - -#define SNPRINTF_S(buf_, bufsiz_, format_, ...) \ - _snprintf_s(buf_, bufsiz_, _TRUNCATE, format_, ##__VA_ARGS__) - -#define PRINTF_S(format_, ...) \ - printf_s(format_, ##__VA_ARGS__) - -#define FPRINTF_S(fp_, format_, ...) \ - fprintf_s(fp_, format_, ##__VA_ARGS__) - -#ifdef _MSC_VER -#define FREAD_S(buf_, bufsiz_, elsiz_, count_, fp_) \ - fread_s(buf_, bufsiz_, elsiz_, count_, fp_) -#else -#define FREAD_S(buf_, bufsiz_, elsiz_, count_, fp_) \ - fread(buf_, elsiz_, count_, fp_) -#endif /* _MSC_VER */ - -#define FOPEN_S(fp_, fName_, mode_) \ -if (fopen_s(&fp_, fName_, mode_) != 0) { \ - fp_ = (FILE *)0; \ -} else (void)0 - -#define LOCALTIME_S(tm_, time_) \ - localtime_s(tm_, time_) - -#else /* other OS (Linux, MacOS, etc.) .....................................*/ - -#define MEMMOVE_S(dest_, num_, src_, count_) \ - memmove(dest_, src_, count_) - -#define STRNCPY_S(dest_, destsiz_, src_) do { \ - strncpy(dest_, src_, destsiz_); \ - dest_[(destsiz_) - 1] = '\0'; \ -} while (false) - -#define STRCAT_S(dest_, destsiz_, src_) \ - strcat(dest_, src_) - -#define SNPRINTF_S(buf_, bufsiz_, format_, ...) \ - snprintf(buf_, bufsiz_, format_, ##__VA_ARGS__) - -#define PRINTF_S(format_, ...) \ - printf(format_, ##__VA_ARGS__) - -#define FPRINTF_S(fp_, format_, ...) \ - fprintf(fp_, format_, ##__VA_ARGS__) - -#define FREAD_S(buf_, bufsiz_, elsiz_, count_, fp_) \ - fread(buf_, elsiz_, count_, fp_) - -#define FOPEN_S(fp_, fName_, mode_) \ - (fp_ = fopen(fName_, mode_)) - -#define LOCALTIME_S(tm_, time_) \ - memcpy(tm_, localtime(time_), sizeof(struct tm)) - -#endif /* _WIN32 */ - -#endif /* SAFE_STD_H */ diff --git a/ports/win32-qv/qf_port.cpp b/ports/win32-qv/qf_port.cpp index 6def56571..d026cad75 100644 --- a/ports/win32-qv/qf_port.cpp +++ b/ports/win32-qv/qf_port.cpp @@ -22,8 +22,8 @@ // // //============================================================================ -//! @date Last updated on: 2024-06-11 -//! @version Last updated for: @ref qpcpp_7_4_0 +//! @date Last updated on: 2024-09-19 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QF/C++ port to Win32 (single-threaded, like the QV kernel) @@ -135,14 +135,18 @@ int run() { QF_CRIT_ENTRY(); Q_ASSERT_INCRIT(310, ticker != static_cast(0)); QF_CRIT_EXIT(); + +#ifdef Q_UNSAFE + Q_UNUSED_PAR(ticker); +#endif } // the combined event-loop and background-loop of the QV kernel QF_CRIT_ENTRY(); // produce the QS_QF_RUN trace record - QS_BEGIN_PRE_(QS_QF_RUN, 0U) - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_RUN, 0U) + QS_END_PRE() while (l_isRunning) { Q_ASSERT_INCRIT(300, readySet_.verify_(&readySet_dis_)); @@ -235,7 +239,7 @@ int consoleWaitForKey(void) { // QActive functions ========================================================= void QActive::start(QPrioSpec const prioSpec, - QEvt const * * const qSto, std::uint_fast16_t const qLen, + QEvtPtr * const qSto, std::uint_fast16_t const qLen, void * const stkSto, std::uint_fast16_t const stkSize, void const * const par) { diff --git a/ports/win32-qv/qp_port.hpp b/ports/win32-qv/qp_port.hpp index 06066af53..59d3de561 100644 --- a/ports/win32-qv/qp_port.hpp +++ b/ports/win32-qv/qp_port.hpp @@ -1,34 +1,34 @@ //============================================================================ // 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 // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC . -// // 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: +// 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. // -// Contact information: +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: // // //============================================================================ -//! @date Last updated on: 2024-02-16 -//! @version Last updated for: @ref qpc_7_3_3 +//! @date Last updated on: 2024-09-30 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QP/C++ port to Win32-QV (single-threaded), generic C++11 @@ -36,11 +36,8 @@ #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ -#include // Exact-width types. C++11 Standard - -#ifdef QP_CONFIG -#include "qp_config.hpp" // external QP configuration -#endif +#include // Exact-width types. C++11 Standard +#include "qp_config.hpp" // QP configuration from the application // no-return function specifier (C++11 Standard) #define Q_NORETURN [[ noreturn ]] void @@ -105,8 +102,7 @@ void onClockTick(); #define QF_SCHED_UNLOCK_() static_cast(0) // QF event queue customization for Win32-QV... - #define QACTIVE_EQUEUE_WAIT_(me_) \ - Q_ASSERT_INCRIT(302, (me_)->m_eQueue.m_frontEvt != nullptr) + #define QACTIVE_EQUEUE_WAIT_(me_) (static_cast(0)) #ifndef Q_UNSAFE #define QACTIVE_EQUEUE_SIGNAL_(me_) \ diff --git a/ports/win32-qv/qs_port.cpp b/ports/win32-qv/qs_port.cpp index 2241a5247..4419df6b8 100644 --- a/ports/win32-qv/qs_port.cpp +++ b/ports/win32-qv/qs_port.cpp @@ -23,7 +23,7 @@ // //============================================================================ //! @date Last updated on: 2024-06-11 -//! @version Last updated for: @ref qpcpp_7_4_0 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QS/C++ port to Win32 API diff --git a/ports/win32-qv/qs_port.hpp b/ports/win32-qv/qs_port.hpp index 2cf165e8f..c66fa9711 100644 --- a/ports/win32-qv/qs_port.hpp +++ b/ports/win32-qv/qs_port.hpp @@ -28,7 +28,7 @@ // //============================================================================ //! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_7_4_0 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QS/C++ port to POSIX/Win32 diff --git a/ports/win32/qf_port.cpp b/ports/win32/qf_port.cpp index 94a263ab9..01e593586 100644 --- a/ports/win32/qf_port.cpp +++ b/ports/win32/qf_port.cpp @@ -22,8 +22,8 @@ // // //============================================================================ -//! @date Last updated on: 2024-06-11 -//! @version Last updated for: @ref qpcpp_7_4_0 +//! @date Last updated on: 2024-09-19 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QF/C++ port to Win32 (multithreaded) @@ -102,8 +102,8 @@ int run() { onStartup(); // application-specific startup callback // produce the QS_QF_RUN trace record - QS_BEGIN_PRE_(QS_QF_RUN, 0U) - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_RUN, 0U) + QS_END_PRE() // leave the startup critical section to unblock any active objects // started before calling QF::run() @@ -168,7 +168,7 @@ int consoleWaitForKey(void) { // QActive functions ========================================================= void QActive::start(QPrioSpec const prioSpec, - QEvt const * * const qSto, std::uint_fast16_t const qLen, + QEvtPtr * const qSto, std::uint_fast16_t const qLen, void * const stkSto, std::uint_fast16_t const stkSize, void const * const par) { diff --git a/ports/win32/qp_port.hpp b/ports/win32/qp_port.hpp index 86ad2e042..22c75c195 100644 --- a/ports/win32/qp_port.hpp +++ b/ports/win32/qp_port.hpp @@ -1,34 +1,34 @@ //============================================================================ // 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 // ------------------------ // Modern Embedded Software // -// Copyright (C) 2005 Quantum Leaps, LLC . -// // 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: +// 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. // -// Contact information: +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: // // //============================================================================ -//! @date Last updated on: 2024-02-16 -//! @version Last updated for: @ref qpc_7_3_3 +//! @date Last updated on: 2024-09-30 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QP/C++ port to Win32 (multithreaded), generic C++11 @@ -36,16 +36,12 @@ #ifndef QP_PORT_HPP_ #define QP_PORT_HPP_ -#include // Exact-width types. C++11 Standard - -#ifdef QP_CONFIG -#include "qp_config.hpp" // external QP configuration -#endif +#include // Exact-width types. C++11 Standard +#include "qp_config.hpp" // QP configuration from the application // no-return function specifier (C++11 Standard) #define Q_NORETURN [[ noreturn ]] void - // QActive event queue, os-type, and thread types #define QACTIVE_EQUEUE_TYPE QEQueue #define QACTIVE_OS_OBJ_TYPE void* diff --git a/ports/win32/qs_port.cpp b/ports/win32/qs_port.cpp index 2241a5247..4419df6b8 100644 --- a/ports/win32/qs_port.cpp +++ b/ports/win32/qs_port.cpp @@ -23,7 +23,7 @@ // //============================================================================ //! @date Last updated on: 2024-06-11 -//! @version Last updated for: @ref qpcpp_7_4_0 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QS/C++ port to Win32 API diff --git a/ports/win32/qs_port.hpp b/ports/win32/qs_port.hpp index 2cf165e8f..c66fa9711 100644 --- a/ports/win32/qs_port.hpp +++ b/ports/win32/qs_port.hpp @@ -28,7 +28,7 @@ // //============================================================================ //! @date Last updated on: 2024-06-06 -//! @version Last updated for: @ref qpcpp_7_4_0 +//! @version Last updated for: @ref qpcpp_8_0_0 //! //! @file //! @brief QS/C++ port to POSIX/Win32 diff --git a/qpcpp.qm b/qpcpp.qm index 0e8c2ac70..59e1714b4 100644 --- a/qpcpp.qm +++ b/qpcpp.qm @@ -1,36 +1,39 @@ - + QP/C++ Real-Time Embedded Framework (RTEF) -The model is used to generate the whole QP/C++ source code. +This model is used to generate the whole QP/C++ source code. -Copyright (C) 2005 Quantum Leaps, LLC <state-machine.com>. +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. + Q u a n t u m L e a P s + ------------------------ + Modern Embedded Software -The terms of the open source GNU General Public License version 3 -can be found at: <www.gnu.org/licenses/gpl-3.0> +SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial -The terms of the closed source Quantum Leaps commercial licenses -can be found at: <www.state-machine.com/licensing> +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 copyright notice. +Redistributions in source code must retain this top-level comment block. Plagiarizing this software to sidestep the license obligations is illegal. -Contact information: +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> - Any user of the QP/C++ real-time embedded framework + public qpcpp 2025-12-31 - -Copyright (C) 2005 Quantum Leaps, LLC <state-machine.com>. +Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. Q u a n t u m L e a P s ------------------------ @@ -38,24 +41,23 @@ Copyright (C) 2005 Quantum Leaps, LLC <state-machine.com>. 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: <www.gnu.org/licenses/gpl-3.0> - -The terms of the closed source Quantum Leaps commercial licenses -can be found at: <www.state-machine.com/licensing> +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. -Contact information: +NOTE: +The GPL does NOT permit the incorporation of this code into proprietary +programs. Please contact Quantum Leaps for commercial licensing options, +which expressly supersede the GPL and are designed explicitly for +closed-source distribution. + +Quantum Leaps contact information: <www.state-machine.com/licensing> <info@state-machine.com> -#CEF384A62BD9270573AA82386A5BE6F6E36AD848 +#48B37CF39D4FD9DE279250B31FD388AFD0BE9B40 @@ -80,6 +82,7 @@ Contact information: + //! the current QP version number string in ROM, based on #QP_VERSION_STR {QP_VERSION_STR}; @@ -98,14 +101,10 @@ Contact information: - - - - - {0xE0U}; - + + : std::uint8_t { DYNAMIC }; @@ -116,8 +115,8 @@ Contact information: : sig(s), - refCtr_(0U), - evtTag_(MARKER) + evtTag_(0x01U), + refCtr_(0x0EU) @@ -137,17 +136,16 @@ Contact information: // no event parameters to initialize - - noexcept - - - return (e != nullptr) - && ((e->evtTag_ & 0xF0U) == MARKER); + + const noexcept + std::uint8_t rc = refCtr_; +return (rc <= 2U*QF_MAX_ACTIVE) + && (((evtTag_ ^ rc) & 0x0FU) == 0x0FU); const noexcept - return static_cast<std::uint8_t>(evtTag_) & 0x0FU; + return static_cast<std::uint8_t>(evtTag_ >> 4U); @@ -173,7 +171,7 @@ Contact information: { - QMState const * superstate; + QMState const *superstate; QStateHandler const stateHandler; QActionHandler const entryAction; QActionHandler const exitAction; @@ -183,7 +181,7 @@ Contact information: { - QMState const * target; + QMState const *target; QActionHandler const act[1]; }; @@ -220,7 +218,6 @@ Contact information: : QState { // unhandled and need to "bubble up" Q_RET_SUPER, //!< event passed to superstate to handle - Q_RET_SUPER_SUB, //!< event passed to submachine superstate Q_RET_UNHANDLED, //!< event unhandled due to a guard // handled and do not need to "bubble up" @@ -236,12 +233,10 @@ Contact information: // transitions need to execute transition-action table in QP::QMsm Q_RET_TRAN, //!< regular transition - Q_RET_TRAN_INIT, //!< initial transition in a state or submachine - Q_RET_TRAN_EP, //!< entry-point transition into a submachine + Q_RET_TRAN_INIT, //!< initial transition in a state // transitions that additionally clobber QHsm.m_state Q_RET_TRAN_HIST, //!< transition to history of a given state - Q_RET_TRAN_XP //!< exit-point transition out of a submachine }; @@ -371,25 +366,6 @@ return Q_RET_TRAN_INIT; m_state.obj = hist; m_temp.tatbl = static_cast<QP::QMTranActTable const *>(tatbl); return Q_RET_TRAN_HIST; - - - - noexcept - - - m_temp.tatbl = static_cast<QP::QMTranActTable const *>(tatbl); -return Q_RET_TRAN_EP; - - - - noexcept - - - - - m_state.act = xp; -m_temp.tatbl = static_cast<QP::QMTranActTable const *>(tatbl); -return Q_RET_TRAN_XP; @@ -423,22 +399,6 @@ return Q_RET_EXIT; static_cast<void>(s); // unused parameter return Q_RET_EXIT; - - - noexcept - - - m_temp.obj = s; -return Q_RET_EXIT; - - - - noexcept - - - m_temp.obj = s; -return Q_RET_SUPER_SUB; - @@ -462,22 +422,27 @@ m_temp.fun = initial; QF_CRIT_STAT +QState r; + +// produce QS dictionary for QP::QHsm::top() #ifdef Q_SPY QS_CRIT_ENTRY(); QS_MEM_SYS(); if ((QS::priv_.flags & 0x01U) == 0U) { QS::priv_.flags |= 0x01U; - QS_MEM_APP(); - QS_CRIT_EXIT(); - QS_FUN_DICTIONARY(&QP::QHsm::top); + r = Q_RET_HANDLED; } else { - QS_MEM_APP(); - QS_CRIT_EXIT(); + r = Q_RET_IGNORED; +} +QS_MEM_APP(); +QS_CRIT_EXIT(); +if (r == Q_RET_HANDLED) { + QS_FUN_DICTIONARY(&QP::QHsm::top); } #else Q_UNUSED_PAR(qsId); -#endif +#endif // def Q_SPY QStateHandler t = m_state.fun; @@ -487,18 +452,18 @@ Q_REQUIRE_INCRIT(200, (m_temp.fun != nullptr) QF_CRIT_EXIT(); // execute the top-most initial tran. -QState r = (*m_temp.fun)(this, Q_EVT_CAST(QEvt)); +r = (*m_temp.fun)(this, Q_EVT_CAST(QEvt)); QF_CRIT_ENTRY(); // the top-most initial tran. must be taken Q_ASSERT_INCRIT(210, r == Q_RET_TRAN); QS_MEM_SYS(); -QS_BEGIN_PRE_(QS_QEP_STATE_INIT, qsId) - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(t); // the source state - QS_FUN_PRE_(m_temp.fun); // the target of the initial tran. -QS_END_PRE_() +QS_BEGIN_PRE(QS_QEP_STATE_INIT, qsId) + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(t); // the source state + QS_FUN_PRE(m_temp.fun); // the target of the initial tran. +QS_END_PRE() QS_MEM_APP(); QF_CRIT_EXIT(); @@ -543,11 +508,11 @@ do { if (r == Q_RET_TRAN) { QS_CRIT_ENTRY(); QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QEP_STATE_INIT, qsId) - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(t); // the source state - QS_FUN_PRE_(m_temp.fun); // the target of the initial tran. - QS_END_PRE_() + QS_BEGIN_PRE(QS_QEP_STATE_INIT, qsId) + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(t); // the source state + QS_FUN_PRE(m_temp.fun); // the target of the initial tran. + QS_END_PRE() QS_MEM_APP(); QS_CRIT_EXIT(); } @@ -557,11 +522,11 @@ do { QF_CRIT_ENTRY(); QS_MEM_SYS(); -QS_BEGIN_PRE_(QS_QEP_INIT_TRAN, qsId) - QS_TIME_PRE_(); // time stamp - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(t); // the new active state -QS_END_PRE_() +QS_BEGIN_PRE(QS_QEP_INIT_TRAN, qsId) + QS_TIME_PRE(); // time stamp + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(t); // the new active state +QS_END_PRE() QS_MEM_APP(); QF_CRIT_EXIT(); @@ -594,17 +559,18 @@ QStateHandler t = s; QF_CRIT_STAT QF_CRIT_ENTRY(); -Q_REQUIRE_INCRIT(300, QEvt::verify_(e)); -Q_INVARIANT_INCRIT(302, (s != Q_STATE_CAST(0)) +Q_REQUIRE_INCRIT(300, (e != nullptr) && (s != nullptr)); +Q_INVARIANT_INCRIT(301, + e->verify_() && (m_state.uint == static_cast<std::uintptr_t>(~m_temp.uint))); QS_MEM_SYS(); -QS_BEGIN_PRE_(QS_QEP_DISPATCH, qsId) - QS_TIME_PRE_(); // time stamp - QS_SIG_PRE_(e->sig); // the signal of the event - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(s); // the current state -QS_END_PRE_() +QS_BEGIN_PRE(QS_QEP_DISPATCH, qsId) + QS_TIME_PRE(); // time stamp + QS_SIG_PRE(e->sig); // the signal of the event + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(s); // the current state +QS_END_PRE() QS_MEM_APP(); QF_CRIT_EXIT(); @@ -621,11 +587,11 @@ do { QS_CRIT_ENTRY(); QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QEP_UNHANDLED, qsId) - QS_SIG_PRE_(e->sig); // the signal of the event - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(s); // the current state - QS_END_PRE_() + QS_BEGIN_PRE(QS_QEP_UNHANDLED, qsId) + QS_SIG_PRE(e->sig); // the signal of the event + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(s); // the current state + QS_END_PRE() QS_MEM_APP(); QS_CRIT_EXIT(); @@ -639,9 +605,22 @@ QF_CRIT_ENTRY(); Q_ENSURE_INCRIT(310, ip > 0); QF_CRIT_EXIT(); -if (r >= Q_RET_TRAN) { // regular tran. taken? - QStateHandler path[QHSM_MAX_NEST_DEPTH_]; +if (r >= Q_RET_TRAN) { // tran. (regular or history) taken? +#ifdef Q_SPY + if (r == Q_RET_TRAN_HIST) { // tran. to history? + QS_CRIT_ENTRY(); + QS_MEM_SYS(); + QS_BEGIN_PRE(QS_QEP_TRAN_HIST, qsId) + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(s); // tran. to history source + QS_FUN_PRE(m_temp.fun); // tran. to history target + QS_END_PRE() + QS_MEM_APP(); + QS_CRIT_EXIT(); + } +#endif // Q_SPY + QStateHandler path[QHSM_MAX_NEST_DEPTH_]; path[0] = m_temp.fun; // tran. target path[1] = t; // current state path[2] = s; // tran. source @@ -661,21 +640,7 @@ if (r >= Q_RET_TRAN) { // regular tran. taken? Q_ENSURE_INCRIT(320, ip > 0); QF_CRIT_EXIT(); - ip = hsm_tran(path, qsId); // take the tran. - -#ifdef Q_SPY - if (r == Q_RET_TRAN_HIST) { - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QEP_TRAN_HIST, qsId) - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(t); // the source of the transition - QS_FUN_PRE_(path[0]); // the target of the tran. to history - QS_END_PRE_() - QS_MEM_APP(); - QS_CRIT_EXIT(); - } -#endif // Q_SPY + ip = hsm_tran(&path[0], qsId); // take the tran. // execute state entry actions in the desired order... // note: ip is the fixed upper loop bound @@ -695,11 +660,11 @@ if (r >= Q_RET_TRAN) { // regular tran. taken? QS_CRIT_ENTRY(); QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QEP_STATE_INIT, qsId) - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(t); // the source (pseudo)state - QS_FUN_PRE_(m_temp.fun); // the target of the tran. - QS_END_PRE_() + QS_BEGIN_PRE(QS_QEP_STATE_INIT, qsId) + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(t); // the source (pseudo)state + QS_FUN_PRE(m_temp.fun); // the target of the tran. + QS_END_PRE() QS_MEM_APP(); QS_CRIT_EXIT(); @@ -741,13 +706,13 @@ if (r >= Q_RET_TRAN) { // regular tran. taken? QS_CRIT_ENTRY(); QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QEP_TRAN, qsId) - QS_TIME_PRE_(); // time stamp - QS_SIG_PRE_(e->sig); // the signal of the event - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(s); // the source of the tran. - QS_FUN_PRE_(t); // the new active state - QS_END_PRE_() + QS_BEGIN_PRE(QS_QEP_TRAN, qsId) + QS_TIME_PRE(); // time stamp + QS_SIG_PRE(e->sig); // the signal of the event + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(s); // the source of the tran. + QS_FUN_PRE(t); // the new active state + QS_END_PRE() QS_MEM_APP(); QS_CRIT_EXIT(); } @@ -756,24 +721,24 @@ if (r >= Q_RET_TRAN) { // regular tran. taken? else if (r == Q_RET_HANDLED) { QS_CRIT_ENTRY(); QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QEP_INTERN_TRAN, qsId) - QS_TIME_PRE_(); // time stamp - QS_SIG_PRE_(e->sig); // the signal of the event - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(s); // the source state - QS_END_PRE_() + QS_BEGIN_PRE(QS_QEP_INTERN_TRAN, qsId) + QS_TIME_PRE(); // time stamp + QS_SIG_PRE(e->sig); // the signal of the event + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(s); // the source state + QS_END_PRE() QS_MEM_APP(); QS_CRIT_EXIT(); } else { QS_CRIT_ENTRY(); QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QEP_IGNORED, qsId) - QS_TIME_PRE_(); // time stamp - QS_SIG_PRE_(e->sig); // the signal of the event - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(m_state.fun); // the current state - QS_END_PRE_() + QS_BEGIN_PRE(QS_QEP_IGNORED, qsId) + QS_TIME_PRE(); // time stamp + QS_SIG_PRE(e->sig); // the signal of the event + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(m_state.fun); // the current state + QS_END_PRE() QS_MEM_APP(); QS_CRIT_EXIT(); } @@ -791,8 +756,8 @@ m_temp.uint = ~m_state.uint; QF_CRIT_STAT QF_CRIT_ENTRY(); -Q_INVARIANT_INCRIT(602, m_state.uint - == static_cast<std::uintptr_t>(~m_temp.uint)); +Q_INVARIANT_INCRIT(602, + m_state.uint == static_cast<std::uintptr_t>(~m_temp.uint)); QF_CRIT_EXIT(); bool inState = false; // assume that this HSM is not in 'state' @@ -845,7 +810,7 @@ do { r = QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG); } --lbound; -} while ((r != Q_RET_IGNORED) // QHsm::top() state not reached +} while ((r != Q_RET_IGNORED) // the top state not reached && (lbound > 0)); #ifndef Q_UNSAFE @@ -1063,11 +1028,11 @@ QF_CRIT_ENTRY(); Q_ASSERT_INCRIT(210, r == Q_RET_TRAN_INIT); QS_MEM_SYS(); -QS_BEGIN_PRE_(QS_QEP_STATE_INIT, qsId) - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(m_state.obj->stateHandler); // source state - QS_FUN_PRE_(m_temp.tatbl->target->stateHandler); // target state -QS_END_PRE_() +QS_BEGIN_PRE(QS_QEP_STATE_INIT, qsId) + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(m_state.obj->stateHandler); // source state + QS_FUN_PRE(m_temp.tatbl->target->stateHandler); // target state +QS_END_PRE() QS_MEM_APP(); QF_CRIT_EXIT(); @@ -1087,11 +1052,11 @@ QF_CRIT_ENTRY(); Q_ENSURE_INCRIT(290, lbound > 0); QS_MEM_SYS(); -QS_BEGIN_PRE_(QS_QEP_INIT_TRAN, qsId) - QS_TIME_PRE_(); // time stamp - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(m_state.obj->stateHandler); // the new current state -QS_END_PRE_() +QS_BEGIN_PRE(QS_QEP_INIT_TRAN, qsId) + QS_TIME_PRE(); // time stamp + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(m_state.obj->stateHandler); // the new current state +QS_END_PRE() QS_MEM_APP(); QF_CRIT_EXIT(); @@ -1123,17 +1088,18 @@ QMState const *t = s; QF_CRIT_STAT QF_CRIT_ENTRY(); -Q_REQUIRE_INCRIT(300, QEvt::verify_(e)); -Q_INVARIANT_INCRIT(302, (s != nullptr) +Q_REQUIRE_INCRIT(300, (e != nullptr) && (s != nullptr)); +Q_INVARIANT_INCRIT(301, + e->verify_() && (m_state.uint == static_cast<std::uintptr_t>(~m_temp.uint))); QS_MEM_SYS(); -QS_BEGIN_PRE_(QS_QEP_DISPATCH, qsId) - QS_TIME_PRE_(); // time stamp - QS_SIG_PRE_(e->sig); // the signal of the event - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(s->stateHandler); // the current state handler -QS_END_PRE_() +QS_BEGIN_PRE(QS_QEP_DISPATCH, qsId) + QS_TIME_PRE(); // time stamp + QS_SIG_PRE(e->sig); // the signal of the event + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(s->stateHandler); // the current state handler +QS_END_PRE() QS_MEM_APP(); QF_CRIT_EXIT(); @@ -1152,21 +1118,17 @@ do { else if (r == Q_RET_SUPER) { t = t->superstate; // advance to the superstate } - // event unhandled and passed to a submachine superstate? - else if (r == Q_RET_SUPER_SUB) { - t = m_temp.obj; // current host state of the submachie - } else { // event unhandled due to a guard QF_CRIT_ENTRY(); // event must be unhandled due to a guard evaluating to 'false' Q_ASSERT_INCRIT(310, r == Q_RET_UNHANDLED); QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QEP_UNHANDLED, qsId) - QS_SIG_PRE_(e->sig); // the signal of the event - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(t->stateHandler); // the current state - QS_END_PRE_() + QS_BEGIN_PRE(QS_QEP_UNHANDLED, qsId) + QS_SIG_PRE(e->sig); // the signal of the event + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(t->stateHandler); // the current state + QS_END_PRE() QS_MEM_APP(); QF_CRIT_EXIT(); @@ -1180,96 +1142,62 @@ Q_ENSURE_INCRIT(320, lbound > 0); QF_CRIT_EXIT(); if (r >= Q_RET_TRAN) { // any kind of tran. taken? -#ifdef Q_SPY - QMState const * const ts = t; // tran. source for QS tracing - QF_CRIT_ENTRY(); // the tran. source state must not be nullptr - Q_ASSERT_INCRIT(330, ts != nullptr); + Q_ASSERT_INCRIT(330, t != nullptr); QF_CRIT_EXIT(); -#endif // Q_SPY - - lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound - do { - // save the tran-action table before it gets clobbered - QMTranActTable const * const tatbl = m_temp.tatbl; - QAsmAttr tmp; // temporary to save intermediate values - - // was TRAN, TRAN_INIT, or TRAN_EP taken? - if (r <= Q_RET_TRAN_EP) { - m_temp.obj = nullptr; // clear - exitToTranSource_(s, t, qsId); - r = execTatbl_(tatbl, qsId); - s = m_state.obj; - } - // was a tran. segment to history taken? - else if (r == Q_RET_TRAN_HIST) { - tmp.obj = m_state.obj; // save history - m_state.obj = s; // restore the original state - exitToTranSource_(s, t, qsId); - static_cast<void>(execTatbl_(tatbl, qsId)); - r = enterHistory_(tmp.obj, qsId); - s = m_state.obj; - } - else { - QF_CRIT_ENTRY(); - // must be tran. to exit point - Q_ASSERT_INCRIT(340, r == Q_RET_TRAN_XP); - QF_CRIT_EXIT(); - tmp.act = m_state.act; // save XP action - m_state.obj = s; // restore the original state - r = (*tmp.act)(this); // execute the XP action - if (r == Q_RET_TRAN) { // XP -> TRAN ? -#ifdef Q_SPY - tmp.tatbl = m_temp.tatbl; // save m_temp -#endif // Q_SPY - exitToTranSource_(s, t, qsId); - // take the tran-to-XP segment inside submachine - static_cast<void>(execTatbl_(tatbl, qsId)); - s = m_state.obj; -#ifdef Q_SPY - m_temp.tatbl = tmp.tatbl; // restore m_temp -#endif // Q_SPY - } - else if (r == Q_RET_TRAN_HIST) { // XP -> HIST ? - tmp.obj = m_state.obj; // save the history - m_state.obj = s; // restore the original state -#ifdef Q_SPY - s = m_temp.obj; // save m_temp -#endif // Q_SPY - exitToTranSource_(m_state.obj, t, qsId); - // take the tran-to-XP segment inside submachine - static_cast<void>(execTatbl_(tatbl, qsId)); #ifdef Q_SPY - m_temp.obj = s; // restore m_temp + QMState const * const ts = t; // for saving tran. table #endif // Q_SPY - s = m_state.obj; - m_state.obj = tmp.obj; // restore the history - } - else { - QF_CRIT_ENTRY(); - // TRAN_XP must NOT be followed by any other tran. type - Q_ASSERT_INCRIT(330, r < Q_RET_TRAN); - QF_CRIT_EXIT(); - } - } + QMTranActTable const *tatbl; + + if (r == Q_RET_TRAN_HIST) { // was it tran. to history? + QMState const * const hist = m_state.obj; // save history + m_state.obj = s; // restore the original state + + QS_CRIT_ENTRY(); + QS_MEM_SYS(); + QS_BEGIN_PRE(QS_QEP_TRAN_HIST, qsId) + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(t->stateHandler); // source state handler + QS_FUN_PRE(hist->stateHandler); // target state handler + QS_END_PRE() + QS_MEM_APP(); + QS_CRIT_EXIT(); + + // save the tran-action table before it gets clobbered + tatbl = m_temp.tatbl; + exitToTranSource_(s, t, qsId); + static_cast<void>(execTatbl_(tatbl, qsId)); + r = enterHistory_(hist, qsId); + s = m_state.obj; + t = s; // set target to the current state + } + lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound + while ((r >= Q_RET_TRAN) && (lbound > 0)) { + // save the tran-action table before it gets clobbered + tatbl = m_temp.tatbl; + m_temp.obj = nullptr; // clear + exitToTranSource_(s, t, qsId); + r = execTatbl_(tatbl, qsId); + s = m_state.obj; t = s; // set target to the current state - --lbound; - } while ((r >= Q_RET_TRAN) && (lbound > 0)); + --lbound; + } QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(350, lbound > 0); + Q_ENSURE_INCRIT(360, lbound > 0); QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QEP_TRAN, qsId) - QS_TIME_PRE_(); // time stamp - QS_SIG_PRE_(e->sig); // the signal of the event - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(ts->stateHandler); // the tran. source - QS_FUN_PRE_(s->stateHandler); // the new active state - QS_END_PRE_() + QS_BEGIN_PRE(QS_QEP_TRAN, qsId) + QS_TIME_PRE(); // time stamp + QS_SIG_PRE(e->sig); // the signal of the event + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(ts->stateHandler); // the tran. source + QS_FUN_PRE(s->stateHandler); // the new active state + QS_END_PRE() QS_MEM_APP(); QF_CRIT_EXIT(); @@ -1283,12 +1211,12 @@ else if (r == Q_RET_HANDLED) { Q_ASSERT_INCRIT(380, t != nullptr); QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QEP_INTERN_TRAN, qsId) - QS_TIME_PRE_(); // time stamp - QS_SIG_PRE_(e->sig); // the signal of the event - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(t->stateHandler); // the source state - QS_END_PRE_() + QS_BEGIN_PRE(QS_QEP_INTERN_TRAN, qsId) + QS_TIME_PRE(); // time stamp + QS_SIG_PRE(e->sig); // the signal of the event + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(t->stateHandler); // the source state + QS_END_PRE() QS_MEM_APP(); QF_CRIT_EXIT(); @@ -1296,16 +1224,13 @@ else if (r == Q_RET_HANDLED) { // event bubbled to the 'top' state? else if (t == nullptr) { QS_CRIT_ENTRY(); - // current state can't be nullptr - Q_ASSERT_INCRIT(390, s != nullptr); - QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QEP_IGNORED, qsId) - QS_TIME_PRE_(); // time stamp - QS_SIG_PRE_(e->sig); // the signal of the event - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(s->stateHandler); // the current state - QS_END_PRE_() + QS_BEGIN_PRE(QS_QEP_IGNORED, qsId) + QS_TIME_PRE(); // time stamp + QS_SIG_PRE(e->sig); // the signal of the event + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(s->stateHandler); // the current state + QS_END_PRE() QS_MEM_APP(); QS_CRIT_EXIT(); } @@ -1395,7 +1320,9 @@ if (!isFound) { // still not found? } QF_CRIT_ENTRY(); -Q_ENSURE_INCRIT(690, isFound && (lbound > 0)); +// NOTE: the following postcondition can only succeed when +// (lbound > 0), so no extra check is necessary. +Q_ENSURE_INCRIT(690, isFound); QF_CRIT_EXIT(); return child; // return the child @@ -1427,37 +1354,23 @@ for (; (*a != nullptr) && (lbound > 0); ++a) { QS_CRIT_ENTRY(); QS_MEM_SYS(); if (r == Q_RET_ENTRY) { - QS_BEGIN_PRE_(QS_QEP_STATE_ENTRY, qsId) - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(m_temp.obj->stateHandler); // entered state - QS_END_PRE_() + QS_BEGIN_PRE(QS_QEP_STATE_ENTRY, qsId) + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(m_temp.obj->stateHandler); // entered state + QS_END_PRE() } else if (r == Q_RET_EXIT) { - QS_BEGIN_PRE_(QS_QEP_STATE_EXIT, qsId) - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(m_temp.obj->stateHandler); // exited state - QS_END_PRE_() + QS_BEGIN_PRE(QS_QEP_STATE_EXIT, qsId) + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(m_temp.obj->stateHandler); // exited state + QS_END_PRE() } else if (r == Q_RET_TRAN_INIT) { - QS_BEGIN_PRE_(QS_QEP_STATE_INIT, qsId) - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(tatbl->target->stateHandler); // source - QS_FUN_PRE_(m_temp.tatbl->target->stateHandler); // target - QS_END_PRE_() - } - else if (r == Q_RET_TRAN_EP) { - QS_BEGIN_PRE_(QS_QEP_TRAN_EP, qsId) - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(tatbl->target->stateHandler); // source - QS_FUN_PRE_(m_temp.tatbl->target->stateHandler); // target - QS_END_PRE_() - } - else if (r == Q_RET_TRAN_XP) { - QS_BEGIN_PRE_(QS_QEP_TRAN_XP, qsId) - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(tatbl->target->stateHandler); // source - QS_FUN_PRE_(m_temp.tatbl->target->stateHandler); // target - QS_END_PRE_() + QS_BEGIN_PRE(QS_QEP_STATE_INIT, qsId) + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(tatbl->target->stateHandler); // source + QS_FUN_PRE(m_temp.tatbl->target->stateHandler); // target + QS_END_PRE() } else { // empty @@ -1502,22 +1415,15 @@ for (; (s != ts) && (lbound > 0); --lbound) { QS_CRIT_ENTRY(); QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QEP_STATE_EXIT, qsId) - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(s->stateHandler); // the exited state handler - QS_END_PRE_() + QS_BEGIN_PRE(QS_QEP_STATE_EXIT, qsId) + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(s->stateHandler); // the exited state handler + QS_END_PRE() QS_MEM_APP(); QS_CRIT_EXIT(); } s = s->superstate; // advance to the superstate - - if (s == nullptr) { // reached the top of a submachine? - s = m_temp.obj; // the superstate from QM_SM_EXIT() - QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(880, s != nullptr); // must be valid - QF_CRIT_EXIT(); - } } QF_CRIT_ENTRY(); Q_ENSURE_INCRIT(890, lbound > 0); @@ -1533,35 +1439,20 @@ QF_CRIT_EXIT(); Q_UNUSED_PAR(qsId); #endif -QMState const *s = hist; -QMState const *ts = m_state.obj; // tran. source +// record the entry path from current state to history QMState const *epath[QMSM_MAX_ENTRY_DEPTH_]; - -QF_CRIT_STAT - -QS_CRIT_ENTRY(); -QS_MEM_SYS(); -QS_BEGIN_PRE_(QS_QEP_TRAN_HIST, qsId) - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(ts->stateHandler); // source state handler - QS_FUN_PRE_(hist->stateHandler); // target state handler -QS_END_PRE_() -QS_MEM_APP(); -QS_CRIT_EXIT(); - +QMState const *s = hist; std::int_fast8_t i = 0; // tran. entry path index -while ((s != ts) && (i < QMSM_MAX_ENTRY_DEPTH_)) { +while ((s != m_state.obj) && (i < (QMSM_MAX_ENTRY_DEPTH_ - 1))) { if (s->entryAction != nullptr) { epath[i] = s; ++i; } s = s->superstate; - if (s == nullptr) { - ts = s; // force exit from the for-loop - } } +QF_CRIT_STAT QF_CRIT_ENTRY(); -Q_ASSERT_INCRIT(910, s == ts); +Q_ASSERT_INCRIT(910, s == m_state.obj); QF_CRIT_EXIT(); // retrace the entry path in reverse (desired) order... @@ -1571,10 +1462,10 @@ while (i > 0) { QS_CRIT_ENTRY(); QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QEP_STATE_ENTRY, qsId) - QS_OBJ_PRE_(this); - QS_FUN_PRE_(epath[i]->stateHandler); // entered state handler - QS_END_PRE_() + QS_BEGIN_PRE(QS_QEP_STATE_ENTRY, qsId) + QS_OBJ_PRE(this); + QS_FUN_PRE(epath[i]->stateHandler); // entered state handler + QS_END_PRE() QS_MEM_APP(); QS_CRIT_EXIT(); } @@ -1585,6 +1476,15 @@ m_state.obj = hist; // set current state to the tran. target QState r; if (hist->initAction != nullptr) { r = (*hist->initAction)(this); // execute the tran. action + QS_CRIT_ENTRY(); + QS_MEM_SYS(); + QS_BEGIN_PRE(QS_QEP_STATE_INIT, qsId) + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(hist->stateHandler); // source + QS_FUN_PRE(m_temp.tatbl->target->stateHandler); // target + QS_END_PRE() + QS_MEM_APP(); + QS_CRIT_EXIT(); } else { r = Q_RET_NULL; @@ -1650,17 +1550,6 @@ return r; static QP::QState state_(void * const me, QP::QEvt const * const e); \ static QP::QMState const state_ ## _s - - - - - - - \ - QP::QState state_ ## _h(QP::QEvt const * const e);\ - static QP::QState state_(void * const me, QP::QEvt const * const e); \ - static SM_ ## subm_ const state_ ## _s - @@ -1768,6 +1657,10 @@ return r; = std::uint16_t; + + + = QEvt const *; + = std::uint8_t; @@ -1945,6 +1838,26 @@ return (m_bits[0] == static_cast<QPSetBits>(~dis->m_bits[0])) // friends... + + + + + + + // friends... + + + + // friends... + + + + noexcept + + + : m_ptr_dis(static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(ptr))) + + @@ -2058,7 +1971,7 @@ m_pthre_dis = static_cast<std::uint8_t>(~m_pthre); - + @@ -2073,7 +1986,7 @@ m_pthre_dis = static_cast<std::uint8_t>(~m_pthre); - + @@ -2165,46 +2078,49 @@ Q_UNUSED_PAR(sender); #endif #ifdef Q_UTEST // test? -#if Q_UTEST != 0 // testing QP-stub? +#if (Q_UTEST != 0) // testing QP-stub? if (m_temp.fun == Q_STATE_CAST(0)) { // QActiveDummy? return static_cast<QActiveDummy *>(this)->fakePost(e, margin, sender); } -#endif -#endif +#endif // (Q_UTEST != 0) +#endif // def Q_UTEST QF_CRIT_STAT QF_CRIT_ENTRY(); QF_MEM_SYS(); -#ifndef Q_UNSAFE -Q_REQUIRE_INCRIT(100, QEvt::verify_(e)); - -std::uint8_t const pcopy = static_cast<std::uint8_t>(~m_prio_dis); -Q_INVARIANT_INCRIT(102, m_prio == pcopy); -#endif +Q_REQUIRE_INCRIT(200, e != nullptr); -QEQueueCtr nFree = m_eQueue.m_nFree; // get volatile into temporary +QEQueueCtr tmp = m_eQueue.m_nFree; // get volatile into temporary +#ifndef Q_UNSAFE +QEQueueCtr dis = static_cast<QEQueueCtr>(~m_eQueue.m_nFree_dis); +Q_INVARIANT_INCRIT(201, e->verify_() && (tmp == dis)); +#endif // ndef Q_UNSAFE // test-probe#1 for faking queue overflow QS_TEST_PROBE_DEF(&QActive::post_) QS_TEST_PROBE_ID(1, - nFree = 0U; + tmp = 0U; // fake no free events ) +// required margin available? bool status; if (margin == QF::NO_MARGIN) { - if (nFree > 0U) { + if (tmp > 0U) { // free entries available in the queue? status = true; // can post } - else { + else { // no free entries available status = false; // cannot post - Q_ERROR_INCRIT(110); // must be able to post the event + + // The queue overflows, but QF_NO_MARGIN indicates that + // the "event delivery guarantee" is required. + Q_ERROR_INCRIT(210); // must be able to post the event } } -else if (nFree > static_cast<QEQueueCtr>(margin)) { +else if (tmp > static_cast<QEQueueCtr>(margin)) { status = true; // can post } -else { +else { // the # free entries below the requested margin status = false; // cannot post, but don't assert } @@ -2214,22 +2130,26 @@ if (e->getPoolNum_() != 0U) { } if (status) { // can post the event? + --tmp; // one free entry just used up + + m_eQueue.m_nFree = tmp; // update the original +#ifndef Q_UNSAFE + m_eQueue.m_nFree_dis = static_cast<QEQueueCtr>(~tmp); +#endif // ndef Q_UNSAFE - --nFree; // one free entry just used up - m_eQueue.m_nFree = nFree; // update the original - if (m_eQueue.m_nMin > nFree) { - m_eQueue.m_nMin = nFree; // update minimum so far + if (m_eQueue.m_nMin > tmp) { + m_eQueue.m_nMin = tmp; // update minimum so far } - QS_BEGIN_PRE_(QS_QF_ACTIVE_POST, m_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_(this); // this active object - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_EQC_PRE_(nFree); // # free entries - QS_EQC_PRE_(m_eQueue.m_nMin); // min # free entries - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_ACTIVE_POST, m_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(this); // this active object + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_EQC_PRE(tmp); // # free entries + QS_EQC_PRE(m_eQueue.m_nMin); // min # free entries + QS_END_PRE() #ifdef Q_UTEST // callback to examine the posted event under the same conditions @@ -2244,47 +2164,61 @@ if (status) { // can post the event? QF_CRIT_ENTRY(); QF_MEM_SYS(); } -#endif +#endif // def Q_UTEST - if (m_eQueue.m_frontEvt == nullptr) { // empty queue? + if (m_eQueue.m_frontEvt == nullptr) { // is the queue empty? m_eQueue.m_frontEvt = e; // deliver event directly +#ifndef Q_UNSAFE + Q_INVARIANT_INCRIT(211, m_eQueue.m_frontEvt_dis + == static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(nullptr))); + m_eQueue.m_frontEvt_dis = + static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(e)); +#endif // ndef Q_UNSAFE + #ifdef QXK_HPP_ - if (m_state.act == Q_ACTION_CAST(0)) { // eXtended thread? - QXTHREAD_EQUEUE_SIGNAL_(this); // signal the event queue + if (m_state.act == nullptr) { // eXtended thread? + QXTHREAD_EQUEUE_SIGNAL_(this); // signal eXtended Thread } else { - QACTIVE_EQUEUE_SIGNAL_(this); // signal the event queue + QACTIVE_EQUEUE_SIGNAL_(this); // signal the Active Object } #else - QACTIVE_EQUEUE_SIGNAL_(this); // signal the event queue -#endif + QACTIVE_EQUEUE_SIGNAL_(this); // signal the Active Object +#endif // def QXK_HPP_ } - // queue is not empty, insert event into the ring-buffer - else { - // insert event into the ring buffer (FIFO) - m_eQueue.m_ring[m_eQueue.m_head] = e; + else { // queue was not empty, insert event into the ring-buffer + tmp = m_eQueue.m_head; // get volatile into temporary +#ifndef Q_UNSAFE + dis = static_cast<QEQueueCtr>(~m_eQueue.m_head_dis); + Q_INVARIANT_INCRIT(212, tmp == dis); +#endif // ndef Q_UNSAFE + m_eQueue.m_ring[tmp] = e; // insert e into buffer - if (m_eQueue.m_head == 0U) { // need to wrap head? - m_eQueue.m_head = m_eQueue.m_end; // wrap around + if (tmp == 0U) { // need to wrap the head? + tmp = m_eQueue.m_end; } - // advance the head (counter clockwise) - m_eQueue.m_head = (m_eQueue.m_head - 1U); + --tmp; // advance the head (counter-clockwise) + + m_eQueue.m_head = tmp; // update the original +#ifndef Q_UNSAFE + m_eQueue.m_head_dis = static_cast<QEQueueCtr>(~tmp); +#endif // ndef Q_UNSAFE } QF_MEM_APP(); QF_CRIT_EXIT(); } -else { // cannot post the event - - QS_BEGIN_PRE_(QS_QF_ACTIVE_POST_ATTEMPT, m_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_(this); // this active object - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_EQC_PRE_(nFree); // # free entries - QS_EQC_PRE_(margin); // margin requested - QS_END_PRE_() +else { // event cannot be posted + + QS_BEGIN_PRE(QS_QF_ACTIVE_POST_ATTEMPT, m_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(this); // this active object + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_EQC_PRE(tmp); // # free entries + QS_EQC_PRE(margin); // margin requested + QS_END_PRE() #ifdef Q_UTEST // callback to examine the posted event under the same conditions @@ -2299,14 +2233,14 @@ else { // cannot post the event QF_CRIT_ENTRY(); QF_MEM_SYS(); } -#endif +#endif // def Q_USTEST QF_MEM_APP(); QF_CRIT_EXIT(); #if (QF_MAX_EPOOL > 0U) QF::gc(e); // recycle the event to avoid a leak -#endif +#endif // (QF_MAX_EPOOL > 0U) } return status; @@ -2317,57 +2251,58 @@ return status; #ifdef Q_UTEST // test? -#if Q_UTEST != 0 // testing QP-stub? +#if (Q_UTEST != 0) // testing QP-stub? if (m_temp.fun == Q_STATE_CAST(0)) { // QActiveDummy? static_cast<QActiveDummy *>(this)->QActiveDummy::fakePostLIFO(e); return; } -#endif -#endif +#endif // (Q_UTEST != 0) +#endif // def Q_UTEST QF_CRIT_STAT QF_CRIT_ENTRY(); QF_MEM_SYS(); -#ifndef Q_UNSAFE -Q_REQUIRE_INCRIT(200, QEvt::verify_(e)); - -std::uint8_t const pcopy = static_cast<std::uint8_t>(~m_prio_dis); -Q_INVARIANT_INCRIT(202, m_prio == pcopy); -#endif - -#ifdef QXK_HPP_ -Q_REQUIRE_INCRIT(200, m_state.act != Q_ACTION_CAST(0)); -#endif +Q_REQUIRE_INCRIT(300, e != nullptr); -QEQueueCtr nFree = m_eQueue.m_nFree; // get volatile into temporary +QEQueueCtr tmp = m_eQueue.m_nFree; // get volatile into temporary +#ifndef Q_UNSAFE +QEQueueCtr dis = static_cast<QEQueueCtr>(~m_eQueue.m_nFree_dis); +Q_INVARIANT_INCRIT(301, e->verify_() && (tmp == dis)); +#endif // ndef Q_UNSAFE // test-probe#1 for faking queue overflow QS_TEST_PROBE_DEF(&QActive::postLIFO) QS_TEST_PROBE_ID(1, - nFree = 0U; + tmp = 0U; // fake no free events ) -Q_REQUIRE_INCRIT(201, nFree != 0U); +// The queue must NOT overflow for the LIFO posting policy. +Q_REQUIRE_INCRIT(310, tmp != 0U); -if (e->getPoolNum_() != 0U) { // is it a mutable event? +if (e->getPoolNum_() != 0U) { QEvt_refCtr_inc_(e); // increment the reference counter } ---nFree; // one free entry just used up -m_eQueue.m_nFree = nFree; // update the original -if (m_eQueue.m_nMin > nFree) { - m_eQueue.m_nMin = nFree; // update minimum so far +--tmp; // one free entry just used up + +m_eQueue.m_nFree = tmp; // update the original +#ifndef Q_UNSAFE +m_eQueue.m_nFree_dis = static_cast<QEQueueCtr>(~tmp); +#endif // ndef Q_UNSAFE + +if (m_eQueue.m_nMin > tmp) { + m_eQueue.m_nMin = tmp; // update minimum so far } -QS_BEGIN_PRE_(QS_QF_ACTIVE_POST_LIFO, m_prio) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of this event - QS_OBJ_PRE_(this); // this active object - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_EQC_PRE_(nFree); // # free entries - QS_EQC_PRE_(m_eQueue.m_nMin); // min # free entries -QS_END_PRE_() +QS_BEGIN_PRE(QS_QF_ACTIVE_POST_LIFO, m_prio) + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(e->sig); // the signal of this event + QS_OBJ_PRE(this); // this active object + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_EQC_PRE(tmp); // # free entries + QS_EQC_PRE(m_eQueue.m_nMin); // min # free entries +QS_END_PRE() #ifdef Q_UTEST // callback to examine the posted event under the same conditions @@ -2382,21 +2317,33 @@ if (QS_LOC_CHECK_(m_prio)) { QF_CRIT_ENTRY(); QF_MEM_SYS(); } -#endif +#endif // def Q_UTEST QEvt const * const frontEvt = m_eQueue.m_frontEvt; m_eQueue.m_frontEvt = e; // deliver the event directly to the front +#ifndef Q_UNSAFE +m_eQueue.m_frontEvt_dis = + static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(e)); +#endif // ndef Q_UNSAFE -if (frontEvt == nullptr) { // was the queue empty? - QACTIVE_EQUEUE_SIGNAL_(this); // signal the event queue +if (frontEvt != nullptr) { // was the queue NOT empty? + tmp = m_eQueue.m_tail; // get volatile into temporary; +#ifndef Q_UNSAFE + dis = static_cast<QEQueueCtr>(~m_eQueue.m_tail_dis); + Q_INVARIANT_INCRIT(311, tmp == dis); +#endif // ndef Q_UNSAFE + ++tmp; + if (tmp == m_eQueue.m_end) { // need to wrap the tail? + tmp = 0U; // wrap around + } + m_eQueue.m_tail = tmp; +#ifndef Q_UNSAFE + m_eQueue.m_tail_dis = static_cast<QEQueueCtr>(~tmp); +#endif // ndef Q_UNSAFE + m_eQueue.m_ring[tmp] = frontEvt; } -else { // queue was not empty, leave the event in the ring-buffer - m_eQueue.m_tail = (m_eQueue.m_tail + 1U); - if (m_eQueue.m_tail == m_eQueue.m_end) { // need to wrap the tail? - m_eQueue.m_tail = 0U; // wrap around - } - - m_eQueue.m_ring[m_eQueue.m_tail] = frontEvt; +else { // queue was empty + QACTIVE_EQUEUE_SIGNAL_(this); // signal the event queue } QF_MEM_APP(); @@ -2409,43 +2356,78 @@ QF_CRIT_EXIT(); QF_CRIT_ENTRY(); QF_MEM_SYS(); +// wait for event to arrive directly (depends on QP port) +// NOTE: might use assertion-IDs 400-409 QACTIVE_EQUEUE_WAIT_(this); // wait for event to arrive directly // always remove evt from the front QEvt const * const e = m_eQueue.m_frontEvt; -Q_INVARIANT_INCRIT(312, QEvt::verify_(e)); +QEQueueCtr tmp = m_eQueue.m_nFree; // get volatile into tmp -QEQueueCtr const nFree = m_eQueue.m_nFree + 1U; // get volatile into tmp -m_eQueue.m_nFree = nFree; // update the # free +#ifndef Q_UNSAFE +Q_INVARIANT_INCRIT(410, e != nullptr); // queue must NOT be empty +Q_INVARIANT_INCRIT(411, Q_PTR2UINT_CAST_(e) + == static_cast<std::uintptr_t>(~m_eQueue.m_frontEvt_dis)); +QEQueueCtr dis = static_cast<QEQueueCtr>(~m_eQueue.m_nFree_dis); +Q_INVARIANT_INCRIT(412, tmp == dis); +#endif // ndef Q_UNSAFE + +++tmp; // one more free event in the queue + +m_eQueue.m_nFree = tmp; // update the # free +#ifndef Q_UNSAFE +m_eQueue.m_nFree_dis = static_cast<QEQueueCtr>(~tmp); +#endif // ndef Q_UNSAFE + +if (tmp <= m_eQueue.m_end) { // any events in the ring buffer? + QS_BEGIN_PRE(QS_QF_ACTIVE_GET, m_prio) + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(e->sig); // the signal of this event + QS_OBJ_PRE(this); // this active object + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_EQC_PRE(tmp); // # free entries + QS_END_PRE() -if (nFree <= m_eQueue.m_end) { // any events in the ring buffer? // remove event from the tail - m_eQueue.m_frontEvt = m_eQueue.m_ring[m_eQueue.m_tail]; - if (m_eQueue.m_tail == 0U) { // need to wrap the tail? - m_eQueue.m_tail = m_eQueue.m_end; // wrap around + tmp = m_eQueue.m_tail; // get volatile into temporary +#ifndef Q_UNSAFE + dis = static_cast<QEQueueCtr>(~m_eQueue.m_tail_dis); + Q_INVARIANT_INCRIT(420, tmp == dis); +#endif // ndef Q_UNSAFE + QEvt const * const frontEvt = m_eQueue.m_ring[tmp]; +#ifndef Q_UNSAFE + Q_ASSERT_INCRIT(421, frontEvt != nullptr); + m_eQueue.m_frontEvt_dis = + static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(frontEvt)); +#endif // ndef Q_UNSAFE + m_eQueue.m_frontEvt = frontEvt; // update the original + + if (tmp == 0U) { // need to wrap the tail? + tmp = m_eQueue.m_end; } - m_eQueue.m_tail = (m_eQueue.m_tail - 1U); - - QS_BEGIN_PRE_(QS_QF_ACTIVE_GET, m_prio) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of this event - QS_OBJ_PRE_(this); // this active object - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_EQC_PRE_(nFree); // # free entries - QS_END_PRE_() + --tmp; // advance the tail (counter-clockwise) + + m_eQueue.m_tail = tmp; // update the original +#ifndef Q_UNSAFE + m_eQueue.m_tail_dis = static_cast<QEQueueCtr>(~tmp); +#endif // ndef Q_UNSAFE } else { m_eQueue.m_frontEvt = nullptr; // the queue becomes empty +#ifndef Q_UNSAFE + m_eQueue.m_frontEvt_dis = + static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(nullptr)); +#endif // ndef Q_UNSAFE // all entries in the queue must be free (+1 for fronEvt) - Q_ASSERT_INCRIT(310, nFree == (m_eQueue.m_end + 1U)); - - QS_BEGIN_PRE_(QS_QF_ACTIVE_GET_LAST, m_prio) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of this event - QS_OBJ_PRE_(this); // this active object - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_END_PRE_() + Q_ASSERT_INCRIT(310, tmp == (m_eQueue.m_end + 1U)); + + QS_BEGIN_PRE(QS_QF_ACTIVE_GET_LAST, m_prio) + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(e->sig); // the signal of this event + QS_OBJ_PRE(this); // this active object + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_END_PRE() } QF_MEM_APP(); @@ -2510,12 +2492,12 @@ Q_REQUIRE_INCRIT(200, sig < static_cast<QSignal>(maxPubSignal_)); Q_INVARIANT_INCRIT(202, subscrList_[sig].m_set.verify_(&subscrList_[sig].m_set_dis)); -QS_BEGIN_PRE_(QS_QF_PUBLISH, qsId) - QS_TIME_PRE_(); // the timestamp - QS_OBJ_PRE_(sender); // the sender object - QS_SIG_PRE_(e->sig); // the signal of the event - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr -QS_END_PRE_() +QS_BEGIN_PRE(QS_QF_PUBLISH, qsId) + QS_TIME_PRE(); // the timestamp + QS_OBJ_PRE(sender); // the sender object + QS_SIG_PRE(e->sig); // the signal of the event + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); +QS_END_PRE() // is it a mutable event? if (e->getPoolNum_() != 0U) { @@ -2608,11 +2590,11 @@ Q_REQUIRE_INCRIT(300, (Q_USER_SIG <= sig) Q_INVARIANT_INCRIT(302, subscrList_[sig].m_set.verify_(&subscrList_[sig].m_set_dis)); -QS_BEGIN_PRE_(QS_QF_ACTIVE_SUBSCRIBE, m_prio) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(sig); // the signal of this event - QS_OBJ_PRE_(this); // this active object -QS_END_PRE_() +QS_BEGIN_PRE(QS_QF_ACTIVE_SUBSCRIBE, m_prio) + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(sig); // the signal of this event + QS_OBJ_PRE(this); // this active object +QS_END_PRE() // insert the prio. into the subscriber set subscrList_[sig].m_set.insert(p); @@ -2641,11 +2623,11 @@ Q_REQUIRE_INCRIT(400, (Q_USER_SIG <= sig) Q_INVARIANT_INCRIT(402, subscrList_[sig].m_set.verify_(&subscrList_[sig].m_set_dis)); -QS_BEGIN_PRE_(QS_QF_ACTIVE_UNSUBSCRIBE, m_prio) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(sig); // the signal of this event - QS_OBJ_PRE_(this); // this active object -QS_END_PRE_() +QS_BEGIN_PRE(QS_QF_ACTIVE_UNSUBSCRIBE, m_prio) + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(sig); // the signal of this event + QS_OBJ_PRE(this); // this active object +QS_END_PRE() // remove the prio. from the subscriber set subscrList_[sig].m_set.remove(p); @@ -2681,11 +2663,11 @@ for (enum_t sig = Q_USER_SIG; sig < maxPubSig; ++sig) { #ifndef Q_UNSAFE subscrList_[sig].m_set.update_(&subscrList_[sig].m_set_dis); #endif - QS_BEGIN_PRE_(QS_QF_ACTIVE_UNSUBSCRIBE, m_prio) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(sig); // the signal of this event - QS_OBJ_PRE_(this); // this active object - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_ACTIVE_UNSUBSCRIBE, m_prio) + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(sig); // the signal of this event + QS_OBJ_PRE(this); // this active object + QS_END_PRE() } QF_MEM_APP(); QF_CRIT_EXIT(); @@ -2705,13 +2687,13 @@ for (enum_t sig = Q_USER_SIG; sig < maxPubSig; ++sig) { QS_CRIT_STAT QS_CRIT_ENTRY(); QS_MEM_SYS(); -QS_BEGIN_PRE_(QS_QF_ACTIVE_DEFER, m_prio) - QS_TIME_PRE_(); // time stamp - QS_OBJ_PRE_(this); // this active object - QS_OBJ_PRE_(eq); // the deferred queue - QS_SIG_PRE_(e->sig); // the signal of the event - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr -QS_END_PRE_() +QS_BEGIN_PRE(QS_QF_ACTIVE_DEFER, m_prio) + QS_TIME_PRE(); // time stamp + QS_OBJ_PRE(this); // this active object + QS_OBJ_PRE(eq); // the deferred queue + QS_SIG_PRE(e->sig); // the signal of the event + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); +QS_END_PRE() QS_MEM_APP(); QS_CRIT_EXIT(); @@ -2745,13 +2727,13 @@ if (e != nullptr) { // event available? QEvt_refCtr_dec_(e); // decrement the reference counter } - QS_BEGIN_PRE_(QS_QF_ACTIVE_RECALL, m_prio) - QS_TIME_PRE_(); // time stamp - QS_OBJ_PRE_(this); // this active object - QS_OBJ_PRE_(eq); // the deferred queue - QS_SIG_PRE_(e->sig); // the signal of the event - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_ACTIVE_RECALL, m_prio) + QS_TIME_PRE(); // time stamp + QS_OBJ_PRE(this); // this active object + QS_OBJ_PRE(eq); // the deferred queue + QS_SIG_PRE(e->sig); // the signal of the event + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_END_PRE() QF_MEM_APP(); QF_CRIT_EXIT(); @@ -2762,11 +2744,11 @@ else { QS_CRIT_ENTRY(); QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QF_ACTIVE_RECALL_ATTEMPT, m_prio) - QS_TIME_PRE_(); // time stamp - QS_OBJ_PRE_(this); // this active object - QS_OBJ_PRE_(eq); // the deferred queue - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_ACTIVE_RECALL_ATTEMPT, m_prio) + QS_TIME_PRE(); // time stamp + QS_OBJ_PRE(this); // this active object + QS_OBJ_PRE(eq); // the deferred queue + QS_END_PRE() QS_MEM_APP(); QS_CRIT_EXIT(); @@ -2927,14 +2909,24 @@ m_temp.fun = initial; + + + + + + + + + + @@ -2946,12 +2938,19 @@ m_temp.fun = initial; - : - QEvt(sig), + : QEvt(sig), m_next(nullptr), +#ifndef Q_UNSAFE + m_next_dis(static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(nullptr))), +#endif m_act(act), m_ctr(0U), - m_interval(0U) +#ifndef Q_UNSAFE + m_ctr_dis(static_cast<QTimeEvtCtr>(~static_cast<QTimeEvtCtr>(0U))), +#endif + m_interval(0U), + m_tickRate(0U), + m_flags(0U) QF_CRIT_STAT QF_CRIT_ENTRY(); @@ -2959,49 +2958,59 @@ Q_REQUIRE_INCRIT(300, (sig != 0U) && (tickRate < QF_MAX_TICK_RATE)); QF_CRIT_EXIT(); -// The refCtr_ attribute is not used in time events, so it is -// reused to hold the tickRate as well as other information -refCtr_ = static_cast<std::uint8_t>(tickRate); +// adjust the settings from the QEvt(sig) ctor +evtTag_ = 0x0FU; +refCtr_ = 0U; noexcept - + - - std::uint8_t const tickRate = refCtr_ & TE_TICK_RATE; + + QF_CRIT_STAT +QF_CRIT_ENTRY(); +QF_MEM_SYS(); + +// dynamic range checks +#if (QF_TIMEEVT_CTR_SIZE == 1U) +Q_REQUIRE_INCRIT(400, (nTicks < 0xFFU) && (interval < 0xFFU)); +#elif (QF_TIMEEVT_CTR_SIZE == 2U) +Q_REQUIRE_INCRIT(400, (nTicks < 0xFFFFU) && (interval < 0xFFFFU)); +#endif + +Q_REQUIRE_INCRIT(401, verify_() && (nTicks != 0U)); + QTimeEvtCtr const ctr = m_ctr; +std::uint8_t const tickRate = m_tickRate; #ifdef Q_SPY std::uint_fast8_t const qsId = static_cast<QActive const *>(m_act)->m_prio; -#endif +#endif // def Q_SPY -QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); +Q_REQUIRE_INCRIT(410, (ctr == 0U) + && (m_act != nullptr) + && (tickRate < QF_MAX_TICK_RATE)); -Q_REQUIRE_INCRIT(400, (m_act != nullptr) - && (ctr == 0U) - && (nTicks != 0U) - && (tickRate < static_cast<std::uint8_t>(QF_MAX_TICK_RATE)) - && (sig >= static_cast<QSignal>(Q_USER_SIG))); -#ifdef Q_UNSAFE +#ifndef Q_UNSAFE +Q_INVARIANT_INCRIT(411, ctr == static_cast<QTimeEvtCtr>(~m_ctr_dis)); +#else Q_UNUSED_PAR(ctr); -#endif +#endif // ndef Q_UNSAFE -m_ctr = nTicks; -m_interval = interval; +m_ctr = static_cast<QTimeEvtCtr>(nTicks); +m_interval = static_cast<QTimeEvtCtr>(interval); +#ifndef Q_UNSAFE +m_ctr_dis = static_cast<QTimeEvtCtr>(~nTicks); +#endif // ndef Q_UNSAFE // is the time event unlinked? // NOTE: For the duration of a single clock tick of the specified tick // rate a time event can be disarmed and yet still linked into the list // because un-linking is performed exclusively in the QF_tickX() function. -if (static_cast<std::uint_fast8_t>( - static_cast<std::uint_fast8_t>(refCtr_) & TE_IS_LINKED) == 0U) -{ - // mark as linked - refCtr_ = static_cast<std::uint8_t>(refCtr_ | TE_IS_LINKED); +if ((m_flags & QTE_FLAG_IS_LINKED) == 0U) { + m_flags |= QTE_FLAG_IS_LINKED; // mark as linked // The time event is initially inserted into the separate // "freshly armed" list based on timeEvtHead_[tickRate].act. @@ -3009,18 +3018,32 @@ if (static_cast<std::uint_fast8_t>( // list is appended to the main list of armed time events based on // timeEvtHead_[tickRate].next. Again, this is to keep any // changes to the main list exclusively inside QTimeEvt::tick(). +#ifndef Q_UNSAFE + Q_INVARIANT_INCRIT(420, + Q_PTR2UINT_CAST_(m_next) == + static_cast<std::uintptr_t>(~m_next_dis)); + Q_INVARIANT_INCRIT(411, + Q_PTR2UINT_CAST_(timeEvtHead_[tickRate].m_act) == + static_cast<std::uintptr_t>(~timeEvtHead_dis_[tickRate].m_ptr_dis)); +#endif m_next = timeEvtHead_[tickRate].toTimeEvt(); timeEvtHead_[tickRate].m_act = this; -} - -QS_BEGIN_PRE_(QS_QF_TIMEEVT_ARM, qsId) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this time event object - QS_OBJ_PRE_(m_act); // the active object - QS_TEC_PRE_(nTicks); // the # ticks - QS_TEC_PRE_(interval); // the interval - QS_U8_PRE_(tickRate); // tick rate -QS_END_PRE_() +#ifndef Q_UNSAFE + m_next_dis = + static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(m_next)); + timeEvtHead_dis_[tickRate].m_ptr_dis = + static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(this)); +#endif // ndef Q_UNSAFE +} + +QS_BEGIN_PRE(QS_QF_TIMEEVT_ARM, qsId) + QS_TIME_PRE(); // timestamp + QS_OBJ_PRE(this); // this time event object + QS_OBJ_PRE(m_act); // the active object + QS_TEC_PRE(nTicks); // the # ticks + QS_TEC_PRE(interval); // the interval + QS_U8_PRE(tickRate); // tick rate +QS_END_PRE() QF_MEM_APP(); QF_CRIT_EXIT(); @@ -3028,42 +3051,50 @@ QF_CRIT_EXIT(); noexcept - #ifdef Q_SPY -std::uint_fast8_t const qsId = static_cast<QActive *>(m_act)->m_prio; -#endif - -QF_CRIT_STAT + QF_CRIT_STAT QF_CRIT_ENTRY(); QF_MEM_SYS(); -// is the time event actually armed? -bool wasArmed; -if (m_ctr != 0U) { - wasArmed = true; - refCtr_ = static_cast<std::uint8_t>(refCtr_ | TE_WAS_DISARMED); +Q_REQUIRE_INCRIT(500, verify_()); - QS_BEGIN_PRE_(QS_QF_TIMEEVT_DISARM, qsId) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this time event object - QS_OBJ_PRE_(m_act); // the target AO - QS_TEC_PRE_(m_ctr); // the # ticks - QS_TEC_PRE_(m_interval); // the interval - QS_U8_PRE_(refCtr_& TE_TICK_RATE); // tick rate - QS_END_PRE_() +QTimeEvtCtr const ctr = m_ctr; +#ifndef Q_UNSAFE +Q_INVARIANT_INCRIT(501, ctr == static_cast<QTimeEvtCtr>(~m_ctr_dis)); +#endif // ndef Q_UNSAFE + +#ifdef Q_SPY +std::uint_fast8_t const qsId = static_cast<QActive *>(m_act)->m_prio; +#endif +// was the time event actually armed? +bool wasArmed; +if (ctr != 0U) { + wasArmed = true; + m_flags |= QTE_FLAG_WAS_DISARMED; m_ctr = 0U; // schedule removal from the list +#ifndef Q_UNSAFE + m_ctr_dis = static_cast<QTimeEvtCtr>(~static_cast<QTimeEvtCtr>(0U)); +#endif // ndef Q_UNSAFE + + QS_BEGIN_PRE(QS_QF_TIMEEVT_DISARM, qsId) + QS_TIME_PRE(); // timestamp + QS_OBJ_PRE(this); // this time event object + QS_OBJ_PRE(m_act); // the target AO + QS_TEC_PRE(ctr); // the # ticks + QS_TEC_PRE(m_interval); // the interval + QS_U8_PRE(m_tickRate); // tick rate + QS_END_PRE() } else { // the time event was already disarmed automatically wasArmed = false; - refCtr_ = static_cast<std::uint8_t>(refCtr_ - & static_cast<std::uint8_t>(~TE_WAS_DISARMED)); - - QS_BEGIN_PRE_(QS_QF_TIMEEVT_DISARM_ATTEMPT, qsId) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this time event object - QS_OBJ_PRE_(m_act); // the target AO - QS_U8_PRE_(refCtr_& TE_TICK_RATE); // tick rate - QS_END_PRE_() + m_flags &= static_cast<std::uint8_t>(~QTE_FLAG_WAS_DISARMED); + + QS_BEGIN_PRE(QS_QF_TIMEEVT_DISARM_ATTEMPT, qsId) + QS_TIME_PRE(); // timestamp + QS_OBJ_PRE(this); // this time event object + QS_OBJ_PRE(m_act); // the target AO + QS_U8_PRE(m_tickRate); // tick rate + QS_END_PRE() } QF_MEM_APP(); @@ -3075,36 +3106,50 @@ return wasArmed; noexcept - - std::uint8_t const tickRate = refCtr_ & TE_TICK_RATE; + + QF_CRIT_STAT +QF_CRIT_ENTRY(); +QF_MEM_SYS(); -#ifdef Q_SPY -std::uint_fast8_t const qsId = static_cast<QActive *>(m_act)->m_prio; +// dynamic range checks +#if (QF_TIMEEVT_CTR_SIZE == 1U) +Q_REQUIRE_INCRIT(600, nTicks < 0xFFU); +#elif (QF_TIMEEVT_CTR_SIZE == 2U) +Q_REQUIRE_INCRIT(600, nTicks < 0xFFFFU); #endif -QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); +Q_REQUIRE_INCRIT(601, verify_() && (nTicks != 0U)); + +QTimeEvtCtr const ctr = m_ctr; +std::uint8_t const tickRate = m_tickRate; +#ifdef Q_SPY +std::uint_fast8_t const qsId = static_cast<QActive *>(m_act)->m_prio; +#endif -Q_REQUIRE_INCRIT(600, (m_act != nullptr) - && (tickRate < static_cast<std::uint8_t>(QF_MAX_TICK_RATE)) - && (nTicks != 0U) - && (sig >= static_cast<QSignal>(Q_USER_SIG))); +Q_REQUIRE_INCRIT(610, (m_act != nullptr) + && (tickRate < QF_MAX_TICK_RATE)); + +#ifndef Q_UNSAFE +Q_INVARIANT_INCRIT(602, ctr == static_cast<QTimeEvtCtr>(~m_ctr_dis)); +#endif // ndef Q_UNSAFE +m_ctr = static_cast<QTimeEvtCtr>(nTicks); +#ifndef Q_UNSAFE +m_ctr_dis = static_cast<QTimeEvtCtr>(~nTicks); +#endif // ndef Q_UNSAFE // is the time evt not running? bool wasArmed; -if (m_ctr == 0U) { +if (ctr == 0U) { wasArmed = false; // NOTE: For a duration of a single clock tick of the specified // tick rate a time event can be disarmed and yet still linked into // the list, because unlinking is performed exclusively in the - // QTimeEvt::tickX() function. + // QTimeEvt::tick() function. - // is the time event unlinked? - if (static_cast<std::uint8_t>(refCtr_ & TE_IS_LINKED) == 0U) { - // mark as linked - refCtr_ = static_cast<std::uint8_t>(refCtr_ | TE_IS_LINKED); + // was the time event unlinked? + if ((m_flags & QTE_FLAG_IS_LINKED) == 0U) { + m_flags |= QTE_FLAG_IS_LINKED; // mark as linked // The time event is initially inserted into the separate // "freshly armed" list based on timeEvtHead_[tickRate].act. @@ -3112,23 +3157,36 @@ if (m_ctr == 0U) { // list is appended to the main list of armed time events based on // timeEvtHead_[tickRate].next. Again, this is to keep any // changes to the main list exclusively inside QTimeEvt::tick(). +#ifndef Q_UNSAFE + Q_INVARIANT_INCRIT(620, + Q_PTR2UINT_CAST_(m_next) == + static_cast<std::uintptr_t>(~m_next_dis)); + Q_INVARIANT_INCRIT(611, + Q_PTR2UINT_CAST_(timeEvtHead_[tickRate].m_act) == + static_cast<std::uintptr_t>(~timeEvtHead_dis_[tickRate].m_ptr_dis)); +#endif m_next = timeEvtHead_[tickRate].toTimeEvt(); timeEvtHead_[tickRate].m_act = this; +#ifndef Q_UNSAFE + m_next_dis = + static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(m_next)); + timeEvtHead_dis_[tickRate].m_ptr_dis = + static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(this)); +#endif // ndef Q_UNSAFE } } else { // the time event was armed wasArmed = true; } -m_ctr = nTicks; // re-load the tick counter (shift the phasing) -QS_BEGIN_PRE_(QS_QF_TIMEEVT_REARM, qsId) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this time event object - QS_OBJ_PRE_(m_act); // the target AO - QS_TEC_PRE_(m_ctr); // the # ticks - QS_TEC_PRE_(m_interval); // the interval - QS_2U8_PRE_(tickRate, (wasArmed ? 1U : 0U)); -QS_END_PRE_() +QS_BEGIN_PRE(QS_QF_TIMEEVT_REARM, qsId) + QS_TIME_PRE(); // timestamp + QS_OBJ_PRE(this); // this time event object + QS_OBJ_PRE(m_act); // the target AO + QS_TEC_PRE(nTicks); // the # ticks + QS_TEC_PRE(m_interval); // the interval + QS_2U8_PRE(tickRate, (wasArmed ? 1U : 0U)); +QS_END_PRE() QF_MEM_APP(); QF_CRIT_EXIT(); @@ -3142,13 +3200,13 @@ return wasArmed; QF_CRIT_ENTRY(); QF_MEM_SYS(); -std::uint8_t const isDisarmed = refCtr_ & TE_WAS_DISARMED; -refCtr_ = static_cast<std::uint8_t>(refCtr_ | TE_WAS_DISARMED); +bool const wasDisarmed = (m_flags & QTE_FLAG_WAS_DISARMED) != 0U; +m_flags |= QTE_FLAG_WAS_DISARMED; QF_MEM_APP(); QF_CRIT_EXIT(); -return isDisarmed != 0U; +return wasDisarmed; @@ -3165,6 +3223,11 @@ return isDisarmed != 0U; const noexcept return m_interval; + + + const noexcept + return m_tickRate; + noexcept @@ -3180,45 +3243,75 @@ QF_CRIT_STAT QF_CRIT_ENTRY(); QF_MEM_SYS(); -Q_REQUIRE_INCRIT(100, tickRate < Q_DIM(timeEvtHead_)); +Q_REQUIRE_INCRIT(800, tickRate < Q_DIM(timeEvtHead_)); QTimeEvt *prev = &timeEvtHead_[tickRate]; -QS_BEGIN_PRE_(QS_QF_TICK, 0U) +QS_BEGIN_PRE(QS_QF_TICK, 0U) prev->m_ctr = (prev->m_ctr + 1U); - QS_TEC_PRE_(prev->m_ctr); // tick ctr - QS_U8_PRE_(tickRate); // tick rate -QS_END_PRE_() + QS_TEC_PRE(prev->m_ctr); // tick ctr + QS_U8_PRE(tickRate); // tick rate +QS_END_PRE() // scan the linked-list of time events at this rate... std::uint_fast8_t lbound = 2U*QF_MAX_ACTIVE; // fixed upper loop bound for (; lbound > 0U; --lbound) { - QTimeEvt *e = prev->m_next; // advance down the time evt. list + Q_ASSERT_INCRIT(810, prev != nullptr); // sanity check + + QTimeEvt *te = prev->m_next; // advance down the time evt. list +#ifndef Q_UNSAFE + Q_INVARIANT_INCRIT(811, + Q_PTR2UINT_CAST_(te) == + static_cast<std::uintptr_t>(~prev->m_next_dis)); +#endif // ndef Q_UNSAFE - if (e == nullptr) { // end of the list? + if (te == nullptr) { // end of the list? - // any new time events armed since the last run of tick()? + // any new time events armed since the last QTimeEvt_tick_()? if (timeEvtHead_[tickRate].m_act != nullptr) { - - // sanity check - Q_ASSERT_INCRIT(110, prev != nullptr); +#ifndef Q_UNSAFE + Q_INVARIANT_INCRIT(812, + Q_PTR2UINT_CAST_(timeEvtHead_[tickRate].m_act) == + static_cast<std::uintptr_t>( + ~timeEvtHead_dis_[tickRate].m_ptr_dis)); +#endif // ndef Q_UNSAFE prev->m_next = timeEvtHead_[tickRate].toTimeEvt(); timeEvtHead_[tickRate].m_act = nullptr; - e = prev->m_next; // switch to the new list +#ifndef Q_UNSAFE + prev->m_next_dis = + static_cast<std::uintptr_t>( + ~Q_PTR2UINT_CAST_(prev->m_next)); + timeEvtHead_dis_[tickRate].m_ptr_dis = + static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(nullptr)); +#endif // ndef Q_UNSAFE + + te = prev->m_next; // switch to the new list } else { // all currently armed time events are processed break; // terminate the for-loop } } - // the time event 'e' must be valid - Q_INVARIANT_INCRIT(112, QEvt::verify_(e)); + // the time event 'te' must be valid + Q_ASSERT_INCRIT(820, te != nullptr); + Q_INVARIANT_INCRIT(821, te->verify_()); + + QTimeEvtCtr ctr = te->m_ctr; +#ifndef Q_UNSAFE + Q_INVARIANT_INCRIT(822, ctr == + static_cast<QTimeEvtCtr>(~te->m_ctr_dis)); +#endif // ndef Q_UNSAFE + + if (ctr == 0U) { // time event scheduled for removal? + prev->m_next = te->m_next; +#ifndef Q_UNSAFE + prev->m_next_dis = + static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(te->m_next)); +#endif // ndef Q_UNSAFE + + // mark time event 'te' as NOT linked + te->m_flags &= static_cast<std::uint8_t>(~QTE_FLAG_IS_LINKED); - if (e->m_ctr == 0U) { // time event scheduled for removal? - prev->m_next = e->m_next; - // mark time event 'e' as NOT linked - e->refCtr_ = static_cast<std::uint8_t>(e->refCtr_ - & static_cast<std::uint8_t>(~TE_IS_LINKED)); // do NOT advance the prev pointer QF_MEM_APP(); QF_CRIT_EXIT(); // exit crit. section to reduce latency @@ -3233,75 +3326,86 @@ for (; lbound > 0U; --lbound) { // of critical sections in QF ports, in which it can occur. QF_CRIT_EXIT_NOP(); } - else { - e->m_ctr = (e->m_ctr - 1U); - - if (e->m_ctr == 0U) { // is time evt about to expire? - QActive * const act = e->toActive(); - - if (e->m_interval != 0U) { // periodic time evt? - e->m_ctr = e->m_interval; // rearm the time event - prev = e; // advance to this time event - } - else { // one-shot time event: automatically disarm - prev->m_next = e->m_next; - - // mark time event 'e' as NOT linked - e->refCtr_ = static_cast<std::uint8_t>(e->refCtr_ - & static_cast<std::uint8_t>(~TE_IS_LINKED)); - // do NOT advance the prev pointer - - QS_BEGIN_PRE_(QS_QF_TIMEEVT_AUTO_DISARM, act->m_prio) - QS_OBJ_PRE_(e); // this time event object - QS_OBJ_PRE_(act); // the target AO - QS_U8_PRE_(tickRate); // tick rate - QS_END_PRE_() - } + else if (ctr == 1U) { // is time evt about to expire? + QActive * const act = te->toActive(); + if (te->m_interval != 0U) { // periodic time evt? + te->m_ctr = te->m_interval; // rearm the time event +#ifndef Q_UNSAFE + te->m_ctr_dis = static_cast<QTimeEvtCtr>(~te->m_interval); +#endif // ndef Q_UNSAFE + prev = te; // advance to this time event + } + else { // one-shot time event: automatically disarm + te->m_ctr = 0U; + prev->m_next = te->m_next; +#ifndef Q_UNSAFE + te->m_ctr_dis = + static_cast<QTimeEvtCtr>(~static_cast<QTimeEvtCtr>(0U)); + prev->m_next_dis = + static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(te->m_next)); +#endif // ndef Q_UNSAFE + + // mark time event 'te' as NOT linked + te->m_flags &= + static_cast<std::uint8_t>(~QTE_FLAG_IS_LINKED); + // do NOT advance the prev pointer + + QS_BEGIN_PRE(QS_QF_TIMEEVT_AUTO_DISARM, act->m_prio) + QS_OBJ_PRE(te); // 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->m_prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(e); // the time event object - QS_SIG_PRE_(e->sig); // signal of this time event - QS_OBJ_PRE_(act); // the target AO - QS_U8_PRE_(tickRate); // tick rate - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_TIMEEVT_POST, act->m_prio) + QS_TIME_PRE(); // timestamp + QS_OBJ_PRE(te); // the time event object + QS_SIG_PRE(te->sig); // signal of this time event + QS_OBJ_PRE(act); // the target AO + QS_U8_PRE(tickRate); // tick rate + QS_END_PRE() #ifdef QXK_HPP_ - if (e->sig < Q_USER_SIG) { - QXThread::timeout_(act); - QF_MEM_APP(); - QF_CRIT_EXIT(); - } - else { - QF_MEM_APP(); - QF_CRIT_EXIT(); // exit crit. section before posting - - // act->POST() asserts if the queue overflows - act->POST(e, sender); - } -#else + if (te->sig < Q_USER_SIG) { + QXThread::timeout_(act); + QF_MEM_APP(); + QF_CRIT_EXIT(); + } + else { QF_MEM_APP(); QF_CRIT_EXIT(); // exit crit. section before posting // act->POST() asserts if the queue overflows - act->POST(e, sender); -#endif + act->POST(te, sender); } - else { - prev = e; // advance to this time event +#else + QF_MEM_APP(); + QF_CRIT_EXIT(); // exit crit. section before posting - QF_MEM_APP(); - QF_CRIT_EXIT(); // exit crit. section to reduce latency + // act->POST() asserts if the queue overflows + act->POST(te, sender); +#endif + } + else { // time event keeps timing out + --ctr; // decrement the tick counter + te->m_ctr = ctr; // update the original +#ifndef Q_UNSAFE + te->m_ctr_dis = static_cast<QTimeEvtCtr>(~ctr); +#endif // ndef Q_UNSAFE - // prevent merging critical sections, see NOTE above - QF_CRIT_EXIT_NOP(); - } + prev = te; // advance to this time event + + QF_MEM_APP(); + QF_CRIT_EXIT(); // exit crit. section to reduce latency + + // prevent merging critical sections, see NOTE above + QF_CRIT_EXIT_NOP(); } QF_CRIT_ENTRY(); // re-enter crit. section to continue the loop QF_MEM_SYS(); } -Q_ENSURE_INCRIT(190, lbound > 0U); +Q_ENSURE_INCRIT(890, lbound > 0U); QF_MEM_APP(); QF_CRIT_EXIT(); @@ -3329,7 +3433,7 @@ QF_CRIT_EXIT(); QF_CRIT_STAT QF_CRIT_ENTRY(); -Q_REQUIRE_INCRIT(800, tickRate < QF_MAX_TICK_RATE); +Q_REQUIRE_INCRIT(900, tickRate < QF_MAX_TICK_RATE); QF_CRIT_EXIT(); bool inactive; @@ -3357,16 +3461,19 @@ return inactive; noexcept - : - QEvt(0U), + : QEvt(0U), m_next(nullptr), +#ifndef Q_UNSAFE + m_next_dis(static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(nullptr))), +#endif m_act(nullptr), m_ctr(0U), - m_interval(0U) - -// The refCtr_ attribute is not used in time events, so it is -// reused to hold the tickRate as well as other information -refCtr_ = 0U; // default rate 0 +#ifndef Q_UNSAFE + m_ctr_dis(static_cast<QTimeEvtCtr>(~static_cast<QTimeEvtCtr>(0U))), +#endif + m_interval(0U), + m_tickRate(0U), + m_flags(0U) @@ -3391,7 +3498,10 @@ refCtr_ = 0U; // default rate 0 : QActive(nullptr) // reuse m_head for tick-rate -m_eQueue.m_head = static_cast<QEQueueCtr>(tickRate); +m_eQueue.m_head = static_cast<QEQueueCtr>(tickRate); +#ifndef Q_UNSAFE +m_eQueue.m_head_dis = static_cast<QEQueueCtr>(~tickRate); +#endif // ndef Q_UNSAFE @@ -3408,6 +3518,9 @@ QF_CRIT_ENTRY(); QF_MEM_SYS(); m_eQueue.m_tail = 0U; +#ifndef Q_UNSAFE +m_eQueue.m_tail_dis = static_cast<QEQueueCtr>(~0U); +#endif // ndef Q_UNSAFE QF_MEM_APP(); QF_CRIT_EXIT(); @@ -3433,14 +3546,28 @@ QF_CRIT_STAT QF_CRIT_ENTRY(); QF_MEM_SYS(); -QEQueueCtr nTicks = m_eQueue.m_tail; // save # of ticks -m_eQueue.m_tail = 0U; // clear the # ticks +// get volatile into temporaries +QEQueueCtr nTicks = m_eQueue.m_tail; +QEQueueCtr const tickRate = m_eQueue.m_head; + +#ifndef Q_UNSAFE +Q_REQUIRE_INCRIT(700, nTicks > 0U); +Q_INVARIANT_INCRIT(701, nTicks + == static_cast<QEQueueCtr>(~m_eQueue.m_tail_dis)); +Q_INVARIANT_INCRIT(702, tickRate + == static_cast<QEQueueCtr>(~m_eQueue.m_head_dis)); +#endif // ndef Q_UNSAFE + +m_eQueue.m_tail = 0U; // clear # ticks +#ifndef Q_UNSAFE +m_eQueue.m_tail_dis = static_cast<QEQueueCtr>(~0U); +#endif // ndef Q_UNSAFE QF_MEM_APP(); QF_CRIT_EXIT(); for (; nTicks > 0U; --nTicks) { - QTimeEvt::tick(static_cast<std::uint_fast8_t>(m_eQueue.m_head), + QTimeEvt::tick(static_cast<std::uint_fast8_t>(tickRate), this); } @@ -3453,32 +3580,65 @@ for (; nTicks > 0U; --nTicks) { Q_UNUSED_PAR(sender); #endif +static QEvt const tickEvt(0U); // immutable event + QF_CRIT_STAT QF_CRIT_ENTRY(); QF_MEM_SYS(); -if (m_eQueue.m_frontEvt == nullptr) { +QEQueueCtr nTicks = m_eQueue.m_tail; // get volatile into temporary - static QEvt const tickEvt(0U); // immutable event +if (m_eQueue.m_frontEvt == nullptr) { +#ifndef Q_UNSAFE + Q_REQUIRE_INCRIT(800, nTicks == 0U); + Q_REQUIRE_INCRIT(801, m_eQueue.m_nFree == 1U); + Q_INVARIANT_INCRIT(802, m_eQueue.m_frontEvt_dis + == static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(nullptr))); + Q_INVARIANT_INCRIT(803, + 1U == static_cast<QEQueueCtr>(~m_eQueue.m_nFree_dis)); + Q_INVARIANT_INCRIT(804, + 0U == static_cast<QEQueueCtr>(~m_eQueue.m_tail_dis)); +#endif // ndef Q_UNSAFE m_eQueue.m_frontEvt = &tickEvt; // deliver event directly - m_eQueue.m_nFree = (m_eQueue.m_nFree - 1U); // one less free event + m_eQueue.m_nFree = 0U; +#ifndef Q_UNSAFE + m_eQueue.m_frontEvt_dis = + static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(&tickEvt)); + m_eQueue.m_nFree_dis = static_cast<QEQueueCtr>(~0U); +#endif // ndef Q_UNSAFE QACTIVE_EQUEUE_SIGNAL_(this); // signal the event queue } +else { +#ifndef Q_UNSAFE + Q_REQUIRE_INCRIT(810, (nTicks > 0U) && (nTicks < 0xFFU)); + Q_REQUIRE_INCRIT(811, m_eQueue.m_nFree == 0U); + Q_INVARIANT_INCRIT(812, m_eQueue.m_frontEvt_dis + == static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(&tickEvt))); + Q_INVARIANT_INCRIT(813, + 0U == static_cast<QEQueueCtr>(~m_eQueue.m_nFree_dis)); + Q_INVARIANT_INCRIT(814, + nTicks == static_cast<QEQueueCtr>(~m_eQueue.m_tail_dis)); +#endif // ndef Q_UNSAFE +} -// account for one more tick event -m_eQueue.m_tail = (m_eQueue.m_tail + 1U); +++nTicks; // account for one more tick event -QS_BEGIN_PRE_(QS_QF_ACTIVE_POST, m_prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(sender); // the sender object - QS_SIG_PRE_(0U); // the signal of the event - QS_OBJ_PRE_(this); // this active object - QS_2U8_PRE_(0U, 0U); // poolNum & refCtr - QS_EQC_PRE_(0U); // # free entries - QS_EQC_PRE_(0U); // min # free entries -QS_END_PRE_() +m_eQueue.m_tail = nTicks; // update the original +#ifndef Q_UNSAFE +m_eQueue.m_tail_dis = static_cast<QEQueueCtr>(~nTicks); +#endif // ndef Q_UNSAFE + +QS_BEGIN_PRE(QS_QF_ACTIVE_POST, m_prio) + QS_TIME_PRE(); // timestamp + QS_OBJ_PRE(sender); // the sender object + QS_SIG_PRE(0U); // the signal of the event + QS_OBJ_PRE(this); // this active object + QS_2U8_PRE(0U, 0U); // poolNum & refCtr + QS_EQC_PRE(0U); // # free entries + QS_EQC_PRE(0U); // min # free entries +QS_END_PRE() QF_MEM_APP(); QF_CRIT_EXIT(); @@ -3489,7 +3649,7 @@ QF_CRIT_EXIT(); - + @@ -3498,6 +3658,14 @@ QF_CRIT_EXIT(); + + + + + + + + @@ -3519,6 +3687,12 @@ QF_CRIT_EXIT(); m_head(0U), m_tail(0U), m_nFree(0U), +#ifndef Q_UNSAFE + m_frontEvt_dis(static_cast<std::uintptr_t>(~0U)), + m_head_dis(static_cast<QEQueueCtr>(~0U)), + m_tail_dis(static_cast<QEQueueCtr>(~0U)), + m_nFree_dis(static_cast<QEQueueCtr>(~0U)), +#endif m_nMin(0U) @@ -3546,6 +3720,13 @@ if (qLen > 0U) { m_nFree = static_cast<QEQueueCtr>(qLen + 1U); //+1 for frontEvt m_nMin = m_nFree; +#ifndef Q_UNSAFE +m_frontEvt_dis = static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(m_frontEvt)); +m_head_dis = static_cast<QEQueueCtr>(~m_head); +m_tail_dis = static_cast<QEQueueCtr>(~m_tail); +m_nFree_dis = static_cast<QEQueueCtr>(~m_nFree); +#endif + QF_MEM_APP(); QF_CRIT_EXIT(); @@ -3566,47 +3747,76 @@ QF_CRIT_STAT QF_CRIT_ENTRY(); QF_MEM_SYS(); -Q_REQUIRE_INCRIT(200, QEvt::verify_(e)); +Q_REQUIRE_INCRIT(200, e != nullptr); +Q_INVARIANT_INCRIT(201, e->verify_()); -QEQueueCtr nFree = m_nFree; // get volatile into temporary +QEQueueCtr tmp = m_nFree; // get volatile into temporary +#ifndef Q_UNSAFE +QEQueueCtr dis = static_cast<QEQueueCtr>(~m_nFree_dis); +Q_INVARIANT_INCRIT(201, tmp == dis); +#endif // ndef Q_UNSAFE + +// test-probe#1 for faking queue overflow +QS_TEST_PROBE_DEF(&QEQueue::post) +QS_TEST_PROBE_ID(1, + tmp = 0U; // fake no free events +) // required margin available? bool status; -if (((margin == QF::NO_MARGIN) && (nFree > 0U)) - || (nFree > static_cast<QEQueueCtr>(margin))) +if (((margin == QF::NO_MARGIN) && (tmp > 0U)) + || (tmp > static_cast<QEQueueCtr>(margin))) { // is it a mutable event? if (e->getPoolNum_() != 0U) { QEvt_refCtr_inc_(e); // increment the reference counter } - --nFree; // one free entry just used up - m_nFree = nFree; // update the original - if (m_nMin > nFree) { - m_nMin = nFree; // update minimum so far + --tmp; // one free entry just used up + + m_nFree = tmp; // update the original +#ifndef Q_UNSAFE + m_nFree_dis = static_cast<QEQueueCtr>(~tmp); +#endif // ndef Q_UNSAFE + + if (m_nMin > tmp) { + m_nMin = tmp; // update minimum so far } - QS_BEGIN_PRE_(QS_QF_EQUEUE_POST, qsId) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of this event - QS_OBJ_PRE_(this); // this queue object - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_EQC_PRE_(nFree); // # free entries - QS_EQC_PRE_(m_nMin); // min # free entries - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_EQUEUE_POST, qsId) + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(e->sig); // the signal of the event + QS_OBJ_PRE(this); // this queue object + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_EQC_PRE(tmp); // # free entries + QS_EQC_PRE(m_nMin); // min # free entries + QS_END_PRE() - if (m_frontEvt == nullptr) { // was the queue empty? + if (m_frontEvt == nullptr) { // is the queue empty? m_frontEvt = e; // deliver event directly +#ifndef Q_UNSAFE + Q_INVARIANT_INCRIT(211, m_frontEvt_dis + == static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(nullptr))); + m_frontEvt_dis = static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(e)); +#endif // ndef Q_UNSAFE } else { // queue was not empty, insert event into the ring-buffer - // insert event into the ring buffer (FIFO) - m_ring[m_head] = e; // insert e into buffer + tmp = m_head; // get volatile into temporary +#ifndef Q_UNSAFE + dis = static_cast<QEQueueCtr>(~m_head_dis); + Q_INVARIANT_INCRIT(212, tmp == dis); +#endif // ndef Q_UNSAFE + m_ring[tmp] = e; // insert e into buffer - // need to wrap? - if (m_head == 0U) { - m_head = m_end; // wrap around + if (tmp == 0U) { // need to wrap the head? + tmp = m_end; } - m_head = (m_head - 1U); + --tmp; // advance head (counter-clockwise) + + m_head = tmp; // update the original +#ifndef Q_UNSAFE + m_head_dis = static_cast<QEQueueCtr>(~tmp); +#endif // ndef Q_UNSAFE } status = true; // event posted successfully } @@ -3614,14 +3824,14 @@ else { // event cannot be posted // dropping events must be acceptable Q_ASSERT_INCRIT(210, margin != QF::NO_MARGIN); - QS_BEGIN_PRE_(QS_QF_EQUEUE_POST_ATTEMPT, qsId) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of this event - QS_OBJ_PRE_(this); // this queue object - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_EQC_PRE_(nFree); // # free entries - QS_EQC_PRE_(margin); // margin requested - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_EQUEUE_POST_ATTEMPT, qsId) + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(e->sig); // the signal of this event + QS_OBJ_PRE(this); // this queue object + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_EQC_PRE(tmp); // # free entries + QS_EQC_PRE(margin); // margin requested + QS_END_PRE() status = false; // event not posted } @@ -3646,39 +3856,69 @@ QF_CRIT_STAT QF_CRIT_ENTRY(); QF_MEM_SYS(); -Q_REQUIRE_INCRIT(300, QEvt::verify_(e)); +Q_REQUIRE_INCRIT(300, e != nullptr); +Q_INVARIANT_INCRIT(301, e->verify_()); -QEQueueCtr nFree = m_nFree; // get volatile into temporary -Q_REQUIRE_INCRIT(301, nFree != 0U); +QEQueueCtr tmp = m_nFree; // get volatile into temporary +#ifndef Q_UNSAFE +QEQueueCtr dis = static_cast<QEQueueCtr>(~m_nFree_dis); +Q_INVARIANT_INCRIT(301, tmp == dis); +#endif // ndef Q_UNSAFE + +// test-probe#1 for faking queue overflow +QS_TEST_PROBE_DEF(&QEQueue::postLIFO) +QS_TEST_PROBE_ID(1, + tmp = 0U; // fake no free events +) + +// must be able to LIFO-post the event +Q_REQUIRE_INCRIT(310, tmp != 0U); if (e->getPoolNum_() != 0U) { // is it a mutable event? QEvt_refCtr_inc_(e); // increment the reference counter } ---nFree; // one free entry just used up -m_nFree = nFree; // update the original -if (m_nMin > nFree) { - m_nMin = nFree; // update minimum so far +--tmp; // one free entry just used up + +m_nFree = tmp; // update the original +#ifndef Q_UNSAFE +m_nFree_dis = static_cast<QEQueueCtr>(~tmp); +#endif // ndef Q_UNSAFE + +if (m_nMin > tmp) { + m_nMin = tmp; // update minimum so far } -QS_BEGIN_PRE_(QS_QF_EQUEUE_POST_LIFO, qsId) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of this event - QS_OBJ_PRE_(this); // this queue object - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_EQC_PRE_(nFree); // # free entries - QS_EQC_PRE_(m_nMin); // min # free entries -QS_END_PRE_() +QS_BEGIN_PRE(QS_QF_EQUEUE_POST_LIFO, qsId) + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(e->sig); // the signal of this event + QS_OBJ_PRE(this); // this queue object + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_EQC_PRE(tmp); // # free entries + QS_EQC_PRE(m_nMin); // min # free entries +QS_END_PRE() QEvt const * const frontEvt = m_frontEvt; // read into temporary -m_frontEvt = e; // deliver event directly to the front of the queue +m_frontEvt = e; // deliver the event directly to the front +#ifndef Q_UNSAFE +m_frontEvt_dis = static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(e)); +#endif // ndef Q_UNSAFE -if (frontEvt != nullptr) { // was the queue not empty? - m_tail = (m_tail + 1U); - if (m_tail == m_end) { // need to wrap the tail? - m_tail = 0U; // wrap around - } - m_ring[m_tail] = frontEvt; // buffer the old front evt +if (frontEvt != nullptr) { // was the queue NOT empty? + tmp = m_tail; // get volatile into temporary; +#ifndef Q_UNSAFE + dis = static_cast<QEQueueCtr>(~m_tail_dis); + Q_INVARIANT_INCRIT(311, tmp == dis); +#endif // ndef Q_UNSAFE + ++tmp; + if (tmp == m_end) { // need to wrap the tail? + tmp = 0U; // wrap around + } + m_tail = tmp; +#ifndef Q_UNSAFE + m_tail_dis = static_cast<QEQueueCtr>(~tmp); +#endif + m_ring[tmp] = frontEvt; } QF_MEM_APP(); @@ -3697,43 +3937,71 @@ QF_CRIT_STAT QF_CRIT_ENTRY(); QF_MEM_SYS(); -QEvt const * const e = m_frontEvt; // always remove evt from the front +QEvt const * const e = m_frontEvt; // always remove evt from the front +#ifndef Q_UNSAFE +Q_INVARIANT_INCRIT(411, Q_PTR2UINT_CAST_(e) + == static_cast<std::uintptr_t>(~m_frontEvt_dis)); +#endif // ndef Q_UNSAFE if (e != nullptr) { // was the queue not empty? - Q_INVARIANT_INCRIT(412, QEvt::verify_(e)); + QEQueueCtr tmp = m_nFree; // get volatile into temporary +#ifndef Q_UNSAFE + QEQueueCtr const dis = static_cast<QEQueueCtr>(~m_nFree_dis); + Q_INVARIANT_INCRIT(412, tmp == dis); +#endif // ndef Q_UNSAFE - // use a temporary variable to increment m_nFree - QEQueueCtr const nFree = m_nFree + 1U; - m_nFree = nFree; // update the # free + ++tmp; // one more free event in the queue - // any events in the the ring buffer? - if (nFree <= m_end) { - m_frontEvt = m_ring[m_tail]; // remove from the tail - if (m_tail == 0U) { // need to wrap? - m_tail = m_end; // wrap around + m_nFree = tmp; // update the # free +#ifndef Q_UNSAFE + m_nFree_dis = static_cast<QEQueueCtr>(~tmp); +#endif // ndef Q_UNSAFE + + // any events in the ring buffer? + if (tmp <= m_end) { + + QS_BEGIN_PRE(QS_QF_EQUEUE_GET, qsId) + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(e->sig); // the signal of this event + QS_OBJ_PRE(this); // this queue object + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_EQC_PRE(tmp); // # free entries + QS_END_PRE() + + tmp = m_tail; // get volatile into temporary + QEvt const * const frontEvt = m_ring[tmp]; +#ifndef Q_UNSAFE + Q_ASSERT_INCRIT(421, frontEvt != nullptr); + m_frontEvt_dis = + static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(frontEvt)); +#endif // ndef Q_UNSAFE + m_frontEvt = frontEvt; // update the original + + if (tmp == 0U) { // need to wrap the tail? + tmp = m_end; } - m_tail = (m_tail - 1U); - - QS_BEGIN_PRE_(QS_QF_EQUEUE_GET, qsId) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of this event - QS_OBJ_PRE_(this); // this queue object - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_EQC_PRE_(nFree); // # free entries - QS_END_PRE_() + --tmp; // advance the tail (counter-clockwise) + m_tail = tmp; // update the original +#ifndef Q_UNSAFE + m_tail_dis = static_cast<QEQueueCtr>(~tmp); +#endif // ndef Q_UNSAFE } else { m_frontEvt = nullptr; // queue becomes empty +#ifndef Q_UNSAFE + m_frontEvt_dis = + static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(nullptr)); +#endif // ndef Q_UNSAFE - // all entries in the queue must be free (+1 for fronEvt) - Q_INVARIANT_INCRIT(420, nFree == (m_end + 1U)); + // all entries in the queue must be free (+1 for frontEvt) + Q_INVARIANT_INCRIT(440, tmp == (m_end + 1U)); - QS_BEGIN_PRE_(QS_QF_EQUEUE_GET_LAST, qsId) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of this event - QS_OBJ_PRE_(this); // this queue object - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_EQUEUE_GET_LAST, qsId) + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(e->sig); // the signal of this event + QS_OBJ_PRE(this); // this queue object + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_END_PRE() } } @@ -3750,7 +4018,11 @@ return e; const noexcept - return m_nMin; + #ifndef Q_UNSAFE +return m_nMin; +#else +return 0U; +#endif @@ -3794,7 +4066,11 @@ return e; - + + + + + : m_start(nullptr), @@ -3802,8 +4078,12 @@ return e; m_free_head(nullptr), m_blockSize(0U), m_nTot(0U), - m_nFree(0U), - m_nMin(0U) + m_nFree(0U) +#ifndef Q_UNSAFE + ,m_nMin(0U), + m_free_head_dis(static_cast<std::uintptr_t>(~0U)), + m_nFree_dis(static_cast<QEQueueCtr>(~0U)) +#endif @@ -3818,15 +4098,17 @@ return e; QF_CRIT_ENTRY(); QF_MEM_SYS(); -Q_REQUIRE_INCRIT(100, (poolSto != nullptr) - && (poolSize >= static_cast<std::uint_fast32_t>(sizeof(QFreeBlock))) - && (static_cast<std::uint_fast16_t>(blockSize + sizeof(QFreeBlock)) - > blockSize)); +Q_REQUIRE_INCRIT(100, poolSto != nullptr); +Q_REQUIRE_INCRIT(101, + poolSize >= static_cast<std::uint_fast32_t>(sizeof(QFreeBlock))); +Q_REQUIRE_INCRIT(102, + static_cast<std::uint_fast16_t>(blockSize + sizeof(QFreeBlock)) + > blockSize); m_free_head = static_cast<QFreeBlock *>(poolSto); // find # free blocks in a memory block, NO DIVISION -m_blockSize = static_cast<QMPoolSize>(sizeof(QFreeBlock)); +m_blockSize = static_cast<QMPoolSize>(2U * sizeof(void *)); std::uint_fast16_t nblocks = 1U; while (m_blockSize < static_cast<QMPoolSize>(blockSize)) { m_blockSize += static_cast<QMPoolSize>(sizeof(QFreeBlock)); @@ -3847,7 +4129,7 @@ for (std::uint_fast32_t size = poolSize - m_blockSize; { fb->m_next = &fb[nblocks]; // point next link to next block #ifndef Q_UNSAFE - fb->m_next_dis = ~Q_UINTPTR_CAST_(fb->m_next); + fb->m_next_dis = ~Q_PTR2UINT_CAST_(fb->m_next); #endif fb = fb->m_next; // advance to the next block ++nTot; // one more free block in the pool @@ -3861,16 +4143,20 @@ Q_ENSURE_INCRIT(190, nTot < 0xFFFFU); #endif fb->m_next = nullptr; // the last link points to NULL -#ifndef Q_UNSAFE -fb->m_next_dis = ~Q_UINTPTR_CAST_(fb->m_next); -#endif m_nTot = static_cast<QMPoolCtr>(nTot); m_nFree = m_nTot; // all blocks are free -m_nMin = m_nTot; // the minimum # free blocks m_start = static_cast<QFreeBlock *>(poolSto); // original start m_end = fb; // the last block in this pool +#ifndef Q_UNSAFE +m_free_head_dis = + static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(m_free_head)); +m_nFree_dis = static_cast<QMPoolCtr>(~m_nFree); +m_nMin = m_nTot; // the minimum # free blocks +fb->m_next_dis = ~Q_PTR2UINT_CAST_(fb->m_next); +#endif + QF_MEM_APP(); QF_CRIT_EXIT(); @@ -3889,62 +4175,82 @@ QF_CRIT_STAT QF_CRIT_ENTRY(); QF_MEM_SYS(); -// have more free blocks than the requested margin? -QFreeBlock *fb; -if (m_nFree > static_cast<QMPoolCtr>(margin)) { - fb = m_free_head; // get a free block +// get volatile into temporaries +QFreeBlock *fb = m_free_head; +QMPoolCtr nFree = m_nFree; + +#ifndef Q_UNSAFE +Q_INVARIANT_INCRIT(301, Q_PTR2UINT_CAST_(fb) + == static_cast<std::uintptr_t>(~m_free_head_dis)); +Q_INVARIANT_INCRIT(302, nFree == static_cast<QMPoolCtr>(~m_nFree_dis)); +#endif // ndef Q_UNSAFE - // a free block must be valid - Q_ASSERT_INCRIT(300, fb != nullptr); +// have more free blocks than the requested margin? +if (nFree > static_cast<QMPoolCtr>(margin)) { + Q_ASSERT_INCRIT(310, fb != nullptr); QFreeBlock * const fb_next = fb->m_next; +#ifndef Q_UNSAFE // the free block must have integrity (duplicate inverse storage) - Q_INVARIANT_INCRIT(302, Q_UINTPTR_CAST_(fb_next) - == static_cast<std::uintptr_t>(~fb->m_next_dis)); + Q_INVARIANT_INCRIT(311, Q_PTR2UINT_CAST_(fb_next) + == static_cast<std::uintptr_t>(~fb->m_next_dis)); +#endif // ndef Q_UNSAFE - m_nFree = (m_nFree - 1U); // one free block less - if (m_nFree == 0U) { // is the pool becoming empty? + --nFree; // one less free block + if (nFree == 0U) { // is the pool becoming empty? // pool is becoming empty, so the next free block must be NULL Q_ASSERT_INCRIT(320, fb_next == nullptr); + m_nFree = 0U; +#ifndef Q_UNSAFE + m_nFree_dis = static_cast<QMPoolCtr>(~m_nFree); m_nMin = 0U; // remember that the pool got empty +#endif // ndef Q_UNSAFE } 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(330, + m_nFree = nFree; // update the original +#ifndef Q_UNSAFE + m_nFree_dis = static_cast<QMPoolCtr>(~nFree); + + // The pool is not empty, so the next free-block pointer + // must be in range. + Q_INVARIANT_INCRIT(330, QF_PTR_RANGE_(fb_next, m_start, m_end)); // is the # free blocks the new minimum so far? - if (m_nMin > m_nFree) { - m_nMin = m_nFree; // remember the minimum so far + if (m_nMin > nFree) { + m_nMin = nFree; // remember the minimum so far } +#endif // ndef Q_UNSAFE } m_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_(this); // this memory pool - QS_MPC_PRE_(m_nFree); // # of free blocks in the pool - QS_MPC_PRE_(m_nMin); // min # free blocks ever in the pool - QS_END_PRE_() +#ifndef Q_UNSAFE + m_free_head_dis = + static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(fb_next)); +#endif // ndef Q_UNSAFE + + QS_BEGIN_PRE(QS_QF_MPOOL_GET, qsId) + QS_TIME_PRE(); // timestamp + QS_OBJ_PRE(this); // this memory pool + QS_MPC_PRE(nFree); // # of free blocks in the pool +#ifndef Q_UNSAFE + QS_MPC_PRE(m_nMin); // min # free blocks ever in the pool +#else + QS_MPC_PRE(0U); // min # free blocks (not available) +#endif // ndef Q_UNSAFE + QS_END_PRE() } else { // don't have enough free blocks at this point fb = nullptr; - QS_BEGIN_PRE_(QS_QF_MPOOL_GET_ATTEMPT, qsId) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this memory pool - QS_MPC_PRE_(m_nFree); // # of free blocks in the pool - QS_MPC_PRE_(margin); // the requested margin - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_MPOOL_GET_ATTEMPT, qsId) + QS_TIME_PRE(); // timestamp + QS_OBJ_PRE(this); // this memory pool + QS_MPC_PRE(nFree); // # of free blocks in the pool + QS_MPC_PRE(margin); // the requested margin + QS_END_PRE() } QF_MEM_APP(); @@ -3969,25 +4275,39 @@ QF_CRIT_STAT QF_CRIT_ENTRY(); QF_MEM_SYS(); -Q_REQUIRE_INCRIT(200, (m_nFree < m_nTot) - && QF_PTR_RANGE_(fb, m_start, m_end)); +// get volatile into temporaries +QFreeBlock * const free_head = m_free_head; +QMPoolCtr nFree = m_nFree; -fb->m_next = m_free_head; // link into list #ifndef Q_UNSAFE -fb->m_next_dis = static_cast<std::uintptr_t>( - ~Q_UINTPTR_CAST_(fb->m_next)); -#endif +Q_INVARIANT_INCRIT(401, Q_PTR2UINT_CAST_(free_head) + == static_cast<std::uintptr_t>(~m_free_head_dis)); +Q_INVARIANT_INCRIT(402, nFree == static_cast<QMPoolCtr>(~m_nFree_dis)); + +Q_REQUIRE_INCRIT(410, nFree < m_nTot); +Q_REQUIRE_INCRIT(411, QF_PTR_RANGE_(fb, m_start, m_end)); -// set as new head of the free list -m_free_head = fb; +// the block must not be in the pool already +Q_REQUIRE_INCRIT(412, Q_PTR2UINT_CAST_(fb->m_next) + != static_cast<std::uintptr_t>(~fb->m_next_dis)); +#endif // ndef Q_UNSAFE -m_nFree = m_nFree + 1U; // one more free block in this pool +++nFree; // one more free block in this pool -QS_BEGIN_PRE_(QS_QF_MPOOL_PUT, qsId) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this memory pool - QS_MPC_PRE_(m_nFree); // the # free blocks in the pool -QS_END_PRE_() +m_free_head = fb; // set as new head of the free list +m_nFree = nFree; +fb->m_next = free_head; // link into the list +#ifndef Q_UNSAFE +m_free_head_dis = static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(fb)); +m_nFree_dis = static_cast<QMPoolCtr>(~nFree); +fb->m_next_dis = static_cast<std::uintptr_t>(~Q_PTR2UINT_CAST_(free_head)); +#endif + +QS_BEGIN_PRE(QS_QF_MPOOL_PUT, qsId) + QS_TIME_PRE(); // timestamp + QS_OBJ_PRE(this); // this memory pool + QS_MPC_PRE(nFree); // the # free blocks in the pool +QS_END_PRE() QF_MEM_APP(); QF_CRIT_EXIT(); @@ -4000,7 +4320,11 @@ QF_CRIT_EXIT(); const noexcept - return m_nMin; + #ifndef Q_UNSAFE +return m_nMin; +#else +return 0U; +#endif @@ -4239,17 +4563,17 @@ QF_EPOOL_GET_(priv_.ePool_[poolNum - 1U], e, if (e != nullptr) { // was e allocated correctly? e->sig = static_cast<QSignal>(sig); // set the signal + e->evtTag_ = static_cast<std::uint8_t>((poolNum << 4U) | 0x0FU); e->refCtr_ = 0U; // initialize the reference counter to 0 - e->evtTag_ = static_cast<std::uint8_t>(QEvt::MARKER | poolNum); QS_CRIT_ENTRY(); QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QF_NEW, + QS_BEGIN_PRE(QS_QF_NEW, static_cast<std::uint_fast8_t>(QS_EP_ID) + poolNum) - 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_() + 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() QS_MEM_APP(); QS_CRIT_EXIT(); } @@ -4262,12 +4586,12 @@ else { // event was not allocated Q_ASSERT_INCRIT(320, margin != NO_MARGIN); QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QF_NEW_ATTEMPT, + QS_BEGIN_PRE(QS_QF_NEW_ATTEMPT, static_cast<std::uint_fast8_t>(QS_EP_ID) + poolNum) - 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_() + 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() QS_MEM_APP(); QF_CRIT_EXIT(); @@ -4284,7 +4608,8 @@ return e; QF_CRIT_STAT QF_CRIT_ENTRY(); -Q_REQUIRE_INCRIT(400, QEvt::verify_(e)); +Q_REQUIRE_INCRIT(400, e != nullptr); +Q_INVARIANT_INCRIT(401, e->verify_()); std::uint_fast8_t const poolNum = e->getPoolNum_(); @@ -4293,12 +4618,12 @@ if (poolNum != 0U) { // is it a pool event (mutable)? if (e->refCtr_ > 1U) { // isn't this the last reference? - QS_BEGIN_PRE_(QS_QF_GC_ATTEMPT, + QS_BEGIN_PRE(QS_QF_GC_ATTEMPT, static_cast<std::uint_fast8_t>(QS_EP_ID) + poolNum) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of the event - QS_2U8_PRE_(poolNum, e->refCtr_); // poolNum & refCtr - QS_END_PRE_() + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(e->sig); // the signal of the event + QS_2U8_PRE(poolNum, e->refCtr_); + QS_END_PRE() QEvt_refCtr_dec_(e); // decrement the ref counter @@ -4307,12 +4632,12 @@ if (poolNum != 0U) { // is it a pool event (mutable)? } else { // this is the last reference to this event, recycle it - QS_BEGIN_PRE_(QS_QF_GC, + QS_BEGIN_PRE(QS_QF_GC, static_cast<std::uint_fast8_t>(QS_EP_ID) + poolNum) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of the event - QS_2U8_PRE_(poolNum, e->refCtr_); // poolNum & refCtr - QS_END_PRE_() + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(e->sig); // the signal of the event + QS_2U8_PRE(poolNum, e->refCtr_); + QS_END_PRE() // pool number must be in range Q_ASSERT_INCRIT(410, (poolNum <= priv_.maxPool_) @@ -4349,7 +4674,8 @@ Q_UNUSED_PAR(evtRef); QF_CRIT_STAT QF_CRIT_ENTRY(); -Q_REQUIRE_INCRIT(500, QEvt::verify_(e)); +Q_REQUIRE_INCRIT(500, e != nullptr); +Q_INVARIANT_INCRIT(501, e->verify_()); std::uint_fast8_t const poolNum = e->getPoolNum_(); Q_UNUSED_PAR(poolNum); // might be unused @@ -4360,12 +4686,12 @@ Q_REQUIRE_INCRIT(501, (poolNum != 0U) QEvt_refCtr_inc_(e); // increments the ref counter QS_MEM_SYS(); -QS_BEGIN_PRE_(QS_QF_NEW_REF, +QS_BEGIN_PRE(QS_QF_NEW_REF, static_cast<std::uint_fast8_t>(QS_EP_ID) + poolNum) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of the event - QS_2U8_PRE_(poolNum, e->refCtr_); // poolNum & refCtr -QS_END_PRE_() + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(e->sig); // the signal of the event + QS_2U8_PRE(poolNum, e->refCtr_); +QS_END_PRE() QS_MEM_APP(); QF_CRIT_EXIT(); @@ -4381,19 +4707,20 @@ return e; QF_CRIT_ENTRY(); QEvt const * const e = evtRef; -Q_REQUIRE_INCRIT(600, QEvt::verify_(e)); +Q_REQUIRE_INCRIT(600, e != nullptr); +Q_INVARIANT_INCRIT(601, e->verify_()); #ifdef Q_SPY std::uint_fast8_t const poolNum = e->getPoolNum_(); #endif QS_MEM_SYS(); -QS_BEGIN_PRE_(QS_QF_DELETE_REF, +QS_BEGIN_PRE(QS_QF_DELETE_REF, static_cast<std::uint_fast8_t>(QS_EP_ID) + poolNum) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of the event - QS_2U8_PRE_(poolNum, e->refCtr_); // poolNum & refCtr -QS_END_PRE_() + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(e->sig); // the signal of the event + QS_2U8_PRE(poolNum, e->refCtr_); +QS_END_PRE() QS_MEM_APP(); QF_CRIT_EXIT(); @@ -4738,12 +5065,12 @@ Q_INVARIANT_INCRIT(102, priv_.schedCeil if (ceiling > priv_.schedCeil) { // raising the scheduler ceiling? - QS_BEGIN_PRE_(QS_SCHED_LOCK, 0U) - QS_TIME_PRE_(); // timestamp + QS_BEGIN_PRE(QS_SCHED_LOCK, 0U) + QS_TIME_PRE(); // timestamp // the previous sched ceiling & new sched ceiling - QS_2U8_PRE_(static_cast<std::uint8_t>(priv_.schedCeil), + QS_2U8_PRE(static_cast<std::uint8_t>(priv_.schedCeil), static_cast<std::uint8_t>(ceiling)); - QS_END_PRE_() + QS_END_PRE() priv_.schedCeil = ceiling; #ifndef Q_UNSAFE @@ -4764,11 +5091,11 @@ Q_INVARIANT_INCRIT(202, priv_.schedCeil if (priv_.schedCeil != 0U) { // actually enabling the scheduler? - QS_BEGIN_PRE_(QS_SCHED_UNLOCK, 0U) - QS_TIME_PRE_(); // timestamp + QS_BEGIN_PRE(QS_SCHED_UNLOCK, 0U) + QS_TIME_PRE(); // timestamp // current sched ceiling (old), previous sched ceiling (new) - QS_2U8_PRE_(static_cast<std::uint8_t>(priv_.schedCeil), 0U); - QS_END_PRE_() + QS_2U8_PRE(static_cast<std::uint8_t>(priv_.schedCeil), 0U); + QS_END_PRE() priv_.schedCeil = 0U; #ifndef Q_UNSAFE @@ -4826,7 +5153,13 @@ QV_START(); // port-specific startup of the QV kernel #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) std::uint_fast8_t pprev = 0U; // previous prio. -#endif + +#ifdef QF_ON_CONTEXT_SW +// officially switch to the idle cotext +QF_onContextSw(nullptr, nullptr); +#endif // def QF_ON_CONTEXT_SW + +#endif // (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) for (;;) { // QV event loop... @@ -4846,11 +5179,11 @@ for (;;) { // QV event loop... QActive * const a = QActive::registry_[p]; #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) - QS_BEGIN_PRE_(QS_SCHED_NEXT, p) - QS_TIME_PRE_(); // timestamp - QS_2U8_PRE_(static_cast<std::uint8_t>(p), + QS_BEGIN_PRE(QS_SCHED_NEXT, p) + QS_TIME_PRE(); // timestamp + QS_2U8_PRE(static_cast<std::uint8_t>(p), static_cast<std::uint8_t>(pprev)); - QS_END_PRE_() + QS_END_PRE() #ifdef QF_ON_CONTEXT_SW QF_onContextSw(((pprev != 0U) @@ -4885,10 +5218,10 @@ for (;;) { // QV event loop... else { // no AO ready to run --> idle #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) if (pprev != 0U) { - QS_BEGIN_PRE_(QS_SCHED_IDLE, pprev) - QS_TIME_PRE_(); // timestamp - QS_U8_PRE_(static_cast<std::uint8_t>(pprev)); - QS_END_PRE_() + QS_BEGIN_PRE(QS_SCHED_IDLE, pprev) + QS_TIME_PRE(); // timestamp + QS_U8_PRE(static_cast<std::uint8_t>(pprev)); + QS_END_PRE() #ifdef QF_ON_CONTEXT_SW QF_onContextSw(QActive::registry_[pprev], nullptr); @@ -4926,7 +5259,7 @@ return 0; - + @@ -4972,8 +5305,7 @@ QS_FLUSH(); // flush the trace buffer to the host - \ - Q_ASSERT_INCRIT(310, (me_)->m_eQueue.m_frontEvt != nullptr) + (static_cast<void>(0)) @@ -5015,12 +5347,12 @@ Q_INVARIANT_INCRIT(102, QK_priv_.lockCeil // first store the previous lock prio QSchedStatus stat; if (ceiling > QK_priv_.lockCeil) { // raising the lock ceiling? - QS_BEGIN_PRE_(QS_SCHED_LOCK, QK_priv_.actPrio) - QS_TIME_PRE_(); // timestamp + QS_BEGIN_PRE(QS_SCHED_LOCK, QK_priv_.actPrio) + QS_TIME_PRE(); // timestamp // the previous lock ceiling & new lock ceiling - QS_2U8_PRE_(static_cast<std::uint8_t>(QK_priv_.lockCeil), + QS_2U8_PRE(static_cast<std::uint8_t>(QK_priv_.lockCeil), static_cast<std::uint8_t>(ceiling)); - QS_END_PRE_() + QS_END_PRE() // previous status of the lock stat = static_cast<QSchedStatus>(QK_priv_.lockCeil); @@ -5056,12 +5388,12 @@ if (prevCeil != 0xFFU) { Q_REQUIRE_INCRIT(210, (!QK_ISR_CONTEXT_()) && (QK_priv_.lockCeil > prevCeil)); - QS_BEGIN_PRE_(QS_SCHED_UNLOCK, QK_priv_.actPrio) - QS_TIME_PRE_(); // timestamp + QS_BEGIN_PRE(QS_SCHED_UNLOCK, QK_priv_.actPrio) + QS_TIME_PRE(); // timestamp // current lock ceiling (old), previous lock ceiling (new) - QS_2U8_PRE_(static_cast<std::uint8_t>(QK_priv_.lockCeil), + QS_2U8_PRE(static_cast<std::uint8_t>(QK_priv_.lockCeil), static_cast<std::uint8_t>(prevCeil)); - QS_END_PRE_() + QS_END_PRE() // restore the previous lock ceiling QK_priv_.lockCeil = prevCeil; @@ -5135,6 +5467,11 @@ QK_priv_.lockCeil = 0U; // unlock the QK scheduler QK_priv_.lockCeil_dis = static_cast<std::uint_fast8_t>(~QK_priv_.lockCeil); #endif +#ifdef QF_ON_CONTEXT_SW +// officially switch to the idle context +QF_onContextSw(nullptr, QActive::registry_[QK_priv_.nextPrio]); +#endif + // activate AOs to process events posted so far if (QK_sched_() != 0U) { QK_activate_(); @@ -5159,7 +5496,7 @@ return 0; - + @@ -5332,11 +5669,11 @@ do { #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) if (p != pprev) { // changing threads? - QS_BEGIN_PRE_(QP::QS_SCHED_NEXT, p) - QS_TIME_PRE_(); // timestamp - QS_2U8_PRE_(p, // prio. of the scheduled AO + QS_BEGIN_PRE(QP::QS_SCHED_NEXT, p) + QS_TIME_PRE(); // timestamp + QS_2U8_PRE(p, // prio. of the scheduled AO pprev); // previous prio. - QS_END_PRE_() + QS_END_PRE() #ifdef QF_ON_CONTEXT_SW QF_onContextSw(QP::QActive::registry_[pprev], a); @@ -5411,19 +5748,19 @@ QK_priv_.actThre_dis = static_cast<std::uint_fast8_t>(~QK_priv_.actThre); if (prio_in != 0U) { // resuming an active object? a = QP::QActive::registry_[prio_in]; // pointer to preempted AO - QS_BEGIN_PRE_(QP::QS_SCHED_NEXT, prio_in) - QS_TIME_PRE_(); // timestamp + QS_BEGIN_PRE(QP::QS_SCHED_NEXT, prio_in) + QS_TIME_PRE(); // timestamp // prio. of the resumed AO, previous prio. - QS_2U8_PRE_(prio_in, pprev); - QS_END_PRE_() + QS_2U8_PRE(prio_in, pprev); + QS_END_PRE() } else { // resuming prio.==0 --> idle a = nullptr; // QK idle loop - QS_BEGIN_PRE_(QP::QS_SCHED_IDLE, pprev) - QS_TIME_PRE_(); // timestamp - QS_U8_PRE_(pprev); // previous prio. - QS_END_PRE_() + QS_BEGIN_PRE(QP::QS_SCHED_IDLE, pprev) + QS_TIME_PRE(); // timestamp + QS_U8_PRE(pprev); // previous prio. + QS_END_PRE() } #ifdef QF_ON_CONTEXT_SW @@ -5463,8 +5800,7 @@ QF_onContextSw(QP::QActive::registry_[pprev], a); - \ - Q_ASSERT_INCRIT(320, (me_)->m_eQueue.m_frontEvt != nullptr) + (static_cast<void>(0)) @@ -5496,6938 +5832,891 @@ QF_onContextSw(QP::QActive::registry_[pprev], a); } while (false) - - - - - = std::uint_fast16_t; - - - - {0U}; - - - - - - - - noexcept - - - QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); + + + + + #ifndef QP_HPP_ +#define QP_HPP_ -Q_REQUIRE_INCRIT(100, !QXK_ISR_CONTEXT_()); +//============================================================================ +#define QP_VERSION_STR "8.0.0" +#define QP_VERSION 800U +#define QP_RELEASE 0x7055936FU -QSchedStatus stat; // saved lock status to be returned +//============================================================================ +//! @cond INTERNAL -// is the lock ceiling being raised? -if (ceiling > QXK_priv_.lockCeil) { - QS_BEGIN_PRE_(QS_SCHED_LOCK, 0U) - QS_TIME_PRE_(); // timestamp - // the previous lock ceiling & new lock ceiling - QS_2U8_PRE_(static_cast<std::uint8_t>(QXK_priv_.lockCeil), - static_cast<std::uint8_t>(ceiling)); - QS_END_PRE_() +#ifndef Q_SIGNAL_SIZE +#define Q_SIGNAL_SIZE 2U +#endif - // previous status of the lock - stat = static_cast<QSchedStatus>(QXK_priv_.lockHolder); - stat |= static_cast<QSchedStatus>(QXK_priv_.lockCeil) << 8U; +#ifndef QF_MAX_ACTIVE +#define QF_MAX_ACTIVE 32U +#endif - // new status of the lock - QXK_priv_.lockHolder = (QXK_priv_.curr != nullptr) - ? QXK_priv_.curr->getPrio() - : 0U; - QXK_priv_.lockCeil = ceiling; -} -else { - stat = 0xFFU; // scheduler not locked -} -QF_MEM_APP(); -QF_CRIT_EXIT(); +#if (QF_MAX_ACTIVE > 64U) +#error QF_MAX_ACTIVE exceeds the maximum of 64U; +#endif -return stat; // return the status to be saved in a stack variable - - - - noexcept - - - // has the scheduler been actually locked by the last QXK::schedLock()? -if (stat != 0xFFU) { - std::uint8_t const prevCeil = static_cast<std::uint8_t>(stat >> 8U); - QF_CRIT_STAT - QF_CRIT_ENTRY(); - QF_MEM_SYS(); +#ifndef QF_MAX_TICK_RATE +#define QF_MAX_TICK_RATE 1U +#endif - Q_REQUIRE_INCRIT(200, !QXK_ISR_CONTEXT_()); - Q_REQUIRE_INCRIT(201, QXK_priv_.lockCeil > prevCeil); +#if (QF_MAX_TICK_RATE > 15U) +#error QF_MAX_TICK_RATE exceeds the maximum of 15U; +#endif - QS_BEGIN_PRE_(QS_SCHED_UNLOCK, 0U) - QS_TIME_PRE_(); // timestamp - // ceiling before unlocking & prio after unlocking - QS_2U8_PRE_(QXK_priv_.lockCeil, prevCeil); - QS_END_PRE_() +#ifndef QF_MAX_EPOOL +#define QF_MAX_EPOOL 3U +#endif - // restore the previous lock ceiling and lock holder - QXK_priv_.lockCeil = prevCeil; - QXK_priv_.lockHolder = (stat & 0xFFU); +#if (QF_MAX_EPOOL > 15U) +#error QF_MAX_EPOOL exceeds the maximum of 15U; +#endif - // find if any threads should be run after unlocking the scheduler - if (QXK_sched_() != 0U) { // activation needed? - QXK_activate_(); // synchronously activate basic-thred(s) - } +#ifndef QF_TIMEEVT_CTR_SIZE +#define QF_TIMEEVT_CTR_SIZE 4U +#endif - QF_MEM_APP(); - QF_CRIT_EXIT(); -} - - - - noexcept - QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); +#if (QF_TIMEEVT_CTR_SIZE > 4U) +#error QF_TIMEEVT_CTR_SIZE defined incorrectly, expected 1U, 2U, or 4U; +#endif -Q_REQUIRE_INCRIT(600, QXK_priv_.lockCeil <= QF_MAX_ACTIVE); +#ifndef QF_EVENT_SIZ_SIZE +#define QF_EVENT_SIZ_SIZE 2U +#endif -QP::QActive *curr = QXK_priv_.curr; -if (curr == nullptr) { // basic thread? - curr = QP::QActive::registry_[QXK_priv_.actPrio]; -} +#if (QF_EVENT_SIZ_SIZE > 4U) +#error QF_EVENT_SIZ_SIZE defined incorrectly, expected 1U, 2U, or 4U; +#endif -Q_ASSERT_INCRIT(690, curr != nullptr); +//! @endcond +//============================================================================ -QF_MEM_APP(); -QF_CRIT_EXIT(); +$declare ${glob-types} -return curr; - - - - - - - - - - - - - - - - - {0U}; - - - - noexcept - - - - - : QActive(Q_STATE_CAST(handler)), - m_timeEvt(this, static_cast<QSignal>(QXK::DELAY_SIG), tickRate) +$declare ${QEP} -m_state.act = nullptr; // mark as extended thread - - - - override - - - - - Q_UNUSED_PAR(e); -Q_UNUSED_PAR(qsId); -Q_ERROR_INCRIT(110); - - - - override - - - this->init(nullptr, qsId); - - - - override - - - - - Q_UNUSED_PAR(e); -Q_UNUSED_PAR(qsId); -Q_ERROR_INCRIT(120); - - - - const noexcept - return &m_timeEvt; - - - - noexcept - - - QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); - -QXThread * const thr = QXK_PTR_CAST_(QXThread*, QXK_priv_.curr); - -// precondition, this function: -// - must NOT be called from an ISR; -// - number of ticks cannot be zero -// - be called from an extended thread; -// - the thread must NOT be already blocked on any object. -Q_REQUIRE_INCRIT(800, (!QXK_ISR_CONTEXT_()) - && (nTicks != 0U) - && (thr != nullptr) - && (thr->m_temp.obj == nullptr)); -// - the thread must NOT be holding a scheduler lock. -Q_REQUIRE_INCRIT(801, QXK_priv_.lockHolder != thr->m_prio); - -// remember the blocking object -thr->m_temp.obj = QXK_PTR_CAST_(QMState const*, &thr->m_timeEvt); -thr->teArm_(static_cast<enum_t>(QXK::DELAY_SIG), nTicks); -thr->block_(); - -QF_MEM_APP(); -QF_CRIT_EXIT(); -QF_CRIT_EXIT_NOP(); // BLOCK here +$declare ${QEP-macros} -// after unblocking... -QF_CRIT_ENTRY(); -QF_MEM_SYS(); +$declare ${QF::types} -// the blocking object must be the time event -Q_ASSERT_INCRIT(890, thr->m_temp.obj - == QXK_PTR_CAST_(QMState*, &thr->m_timeEvt)); -thr->m_temp.obj = nullptr; // clear +$declare ${QF::QActive} -QF_MEM_APP(); -QF_CRIT_EXIT(); +$declare ${QF::QMActive} -// signal of zero means that the time event was posted without -// being canceled. -return (thr->m_timeEvt.sig == 0U); - - - - noexcept - QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); +$declare ${QF::QTimeEvt} -bool wasArmed; -if (m_temp.obj == QXK_PTR_CAST_(QMState*, &m_timeEvt)) { - wasArmed = teDisarm_(); - unblock_(); -} -else { - wasArmed = false; -} -QF_MEM_APP(); -QF_CRIT_EXIT(); +$declare ${QF::QTicker} -return wasArmed; - - - - noexcept - - - QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); +$declare ${QF::QF-base} -QXThread * const thr = QXTHREAD_CAST_(QXK_priv_.curr); +$declare ${QF::QF-dyn} -// precondition, this function: -// - must NOT be called from an ISR; -// - be called from an extended thread; -// - the thread must NOT be already blocked on any object. -Q_REQUIRE_INCRIT(500, (!QXK_ISR_CONTEXT_()) - && (thr != nullptr) - && (thr->m_temp.obj == nullptr)); -// - the thread must NOT be holding a scheduler lock. -Q_REQUIRE_INCRIT(501, QXK_priv_.lockHolder != thr->m_prio); +extern "C" { +$declare ${QF-extern-C} +} // extern "C" -// is the queue empty? -if (thr->m_eQueue.m_frontEvt == nullptr) { +$declare ${QF-macros} - // remember the blocking object (the thread's queue) - thr->m_temp.obj = QXK_PTR_CAST_(QMState*, &thr->m_eQueue); +#endif // QP_HPP_ + + + + #ifndef QP_PKG_HPP_ +#define QP_PKG_HPP_ - thr->teArm_(static_cast<enum_t>(QXK::TIMEOUT_SIG), nTicks); - QXK_priv_.readySet.remove( - static_cast<std::uint_fast8_t>(thr->m_prio)); -#ifndef Q_UNSAFE - QXK_priv_.readySet.update_(&QXK_priv_.readySet_dis); -#endif +$declare ${QF::QF-pkg} - static_cast<void>(QXK_sched_()); // synchronous scheduling +#define QF_CONST_CAST_(type_, ptr_) const_cast<type_>(ptr_) +#define Q_PTR2UINT_CAST_(ptr_) (reinterpret_cast<std::uintptr_t>(ptr_)) +#define QF_PTR_RANGE_(x_, min_, max_) (((min_) <= (x_)) && ((x_) <= (max_))) - QF_MEM_APP(); - QF_CRIT_EXIT(); - QF_CRIT_EXIT_NOP(); // BLOCK here +namespace QP { - // after unblocking... - QF_CRIT_ENTRY(); - QF_MEM_SYS(); +// Bitmasks are for the QTimeEvt::flags attribute +constexpr std::uint8_t QTE_FLAG_IS_LINKED {1U << 7U}; +constexpr std::uint8_t QTE_FLAG_WAS_DISARMED {1U << 6U}; - // the blocking object must be this queue - Q_ASSERT_INCRIT(510, thr->m_temp.obj == - QXK_PTR_CAST_(QMState *, &thr->m_eQueue)); - thr->m_temp.obj = nullptr; // clear +inline void QEvt_refCtr_inc_(QEvt const * const e) noexcept { + std::uint8_t rc = e->refCtr_ + 1U; + (QF_CONST_CAST_(QEvt*, e))->refCtr_ = rc; // cast away 'const' +#ifndef Q_UNSAFE + (QF_CONST_CAST_(QEvt*, e))->evtTag_ = (e->evtTag_ & 0xF0U) | ((~rc) & 0x0FU); +#endif } -// is the queue not empty? -QEvt const *e; -if (thr->m_eQueue.m_frontEvt != nullptr) { - e = thr->m_eQueue.m_frontEvt; // remove from the front - QEQueueCtr const nFree = thr->m_eQueue.m_nFree + 1U; - thr->m_eQueue.m_nFree = nFree; // update the # free - - // any events in the ring buffer? - if (nFree <= thr->m_eQueue.m_end) { - - // remove event from the tail - thr->m_eQueue.m_frontEvt = - thr->m_eQueue.m_ring[thr->m_eQueue.m_tail]; - if (thr->m_eQueue.m_tail == 0U) { - thr->m_eQueue.m_tail = thr->m_eQueue.m_end; // wrap - } - // advance the tail (counter clockwise) - thr->m_eQueue.m_tail = (thr->m_eQueue.m_tail - 1U); - - QS_BEGIN_PRE_(QS_QF_ACTIVE_GET, thr->m_prio) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of this event - QS_OBJ_PRE_(&thr); // this active object - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_EQC_PRE_(nFree); // # free entries - QS_END_PRE_() - } - else { - thr->m_eQueue.m_frontEvt = nullptr; // empty queue - - // all entries in the queue must be free (+1 for fronEvt) - Q_ASSERT_INCRIT(520, nFree == (thr->m_eQueue.m_end + 1U)); - - QS_BEGIN_PRE_(QS_QF_ACTIVE_GET_LAST, thr->m_prio) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of this event - QS_OBJ_PRE_(&thr); // this active object - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_END_PRE_() - } -} -else { // the queue is still empty -- the timeout must have fired - e = nullptr; +inline void QEvt_refCtr_dec_(QEvt const * const e) noexcept { + std::uint8_t rc = e->refCtr_ - 1U; + (QF_CONST_CAST_(QEvt*, e))->refCtr_ = rc; // cast away 'const' +#ifndef Q_UNSAFE + (QF_CONST_CAST_(QEvt*, e))->evtTag_ = (e->evtTag_ & 0xF0U) | ((~rc) & 0x0FU); +#endif } -QF_MEM_APP(); -QF_CRIT_EXIT(); -return e; - - - - const noexcept - // NOTE: must be called IN a critical section +} // namespace QP -Q_REQUIRE_INCRIT(600, (QXK_priv_.lockHolder != m_prio)); +#endif // QP_PKG_HPP_ + + + + #ifndef QEQUEUE_HPP_ +#define QEQUEUE_HPP_ -QXK_priv_.readySet.remove(static_cast<std::uint_fast8_t>(m_prio)); -#ifndef Q_UNSAFE -QXK_priv_.readySet.update_(&QXK_priv_.readySet_dis); +#ifndef QF_EQUEUE_CTR_SIZE + #define QF_EQUEUE_CTR_SIZE 1U #endif -static_cast<void>(QXK_sched_()); // schedule other threads - - - - const noexcept - // NOTE: must be called IN a critical section +namespace QP { -QXK_priv_.readySet.insert(static_cast<std::uint_fast8_t>(m_prio)); -#ifndef Q_UNSAFE -QXK_priv_.readySet.update_(&QXK_priv_.readySet_dis); +#if (QF_EQUEUE_CTR_SIZE == 1U) + using QEQueueCtr = std::uint8_t; +#elif (QF_EQUEUE_CTR_SIZE == 2U) + using QEQueueCtr = std::uint16_t; +#else + #error "QF_EQUEUE_CTR_SIZE defined incorrectly, expected 1U or 2U" #endif -if ((!QXK_ISR_CONTEXT_()) // not inside ISR? - && (QActive::registry_[0] != nullptr)) // kernel started? -{ - static_cast<void>(QXK_sched_()); // schedule other threads -} - - - - - - // NOTE: must be called IN a critical section +class QEvt; // forward declaration -// the private time event is now disarmed and not in any queue, -// so it is safe to change its signal. The signal of 0 means -// that the time event has expired. -QXTHREAD_CAST_(act)->m_timeEvt.sig = 0U; +} // namespace QP -QXTHREAD_CAST_(act)->unblock_(); - - - - noexcept - - - - - // NOTE: must be called IN a critical section +$declare ${QF::QEQueue} -// precondition: -// - the time event must be unused -Q_REQUIRE_INCRIT(700, m_timeEvt.m_ctr == 0U); +#endif // QEQUEUE_HPP_ + + + + #ifndef QMPOOL_HPP_ +#define QMPOOL_HPP_ -m_timeEvt.sig = static_cast<QSignal>(sig); +#ifndef QF_MPOOL_SIZ_SIZE + #define QF_MPOOL_SIZ_SIZE 2U +#endif +#ifndef QF_MPOOL_CTR_SIZE + #define QF_MPOOL_CTR_SIZE 2U +#endif -if (nTicks != QXTHREAD_NO_TIMEOUT) { - m_timeEvt.m_ctr = static_cast<QTimeEvtCtr>(nTicks); - m_timeEvt.m_interval = 0U; +namespace QP { - // is the time event unlinked? - // NOTE: For the duration of a single clock tick of the specified tick - // rate a time event can be disarmed and yet still linked in the list, - // because un-linking is performed exclusively in QTimeEvt::tickX(). - if (static_cast<std::uint8_t>(m_timeEvt.refCtr_ & TE_IS_LINKED) == 0U) - { - std::uint_fast8_t const tickRate = - static_cast<std::uint_fast8_t>(m_timeEvt.refCtr_); - Q_ASSERT_INCRIT(710, tickRate < QF_MAX_TICK_RATE); +#if (QF_MPOOL_SIZ_SIZE == 1U) + using QMPoolSize = std::uint8_t; +#elif (QF_MPOOL_SIZ_SIZE == 2U) + using QMPoolSize = std::uint16_t; +#elif (QF_MPOOL_SIZ_SIZE == 4U) + using QMPoolSize = std::uint32_t; +#else + #error "QF_MPOOL_SIZ_SIZE defined incorrectly, expected 1U, 2U, or 4U" +#endif - // mark as linked - m_timeEvt.refCtr_ = static_cast<std::uint8_t>( - m_timeEvt.refCtr_ | TE_IS_LINKED); +#if (QF_MPOOL_CTR_SIZE == 1U) + using QMPoolCtr = std::uint8_t; +#elif (QF_MPOOL_CTR_SIZE == 2U) + using QMPoolCtr = std::uint16_t; +#elif (QF_MPOOL_CTR_SIZE == 4U) + using QMPoolCtr = std::uint32_t; +#else + #error "QF_MPOOL_CTR_SIZE defined incorrectly, expected 1U, 2U, or 4U" +#endif - // The time event is initially inserted into the separate - // "freshly armed" list based on timeEvtHead_[tickRate].act. - // Only later, inside QTimeEvt::tick(), the "freshly armed" - // list is appended to the main list of armed time events based on - // timeEvtHead_[tickRate].next. Again, this is to keep any - // changes to the main list exclusively inside QTimeEvt::tick(). - m_timeEvt.m_next - = QXK_PTR_CAST_(QTimeEvt*, - QTimeEvt::timeEvtHead_[tickRate].m_act); - QTimeEvt::timeEvtHead_[tickRate].m_act = &m_timeEvt; - } -} - - - - noexcept - // NOTE: must be called IN a critical section +} // namespace QP -bool wasArmed; -// is the time evt running? -if (m_timeEvt.m_ctr != 0U) { - wasArmed = true; - // schedule removal from list - m_timeEvt.m_ctr = 0U; -} -// the time event was already automatically disarmed -else { - wasArmed = false; +#define QF_MPOOL_EL(evType_) struct { \ + QP::QFreeBlock sto_[((sizeof(evType_) - 1U) / (2U * sizeof(void *))) + 1U]; \ } -return wasArmed; - - - - noexcept - - - - - - - - - - - - - - - - - - - noexcept - - - - - QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); - -Q_REQUIRE_INCRIT(100, (count <= max_count) - && (0U < max_count) && (max_count <= 0xFFU)); -m_count = static_cast<std::uint8_t>(count); -m_max_count = static_cast<std::uint8_t>(max_count); -m_waitSet.setEmpty(); +$declare ${QF::QFreeBlock} -QF_MEM_APP(); -QF_CRIT_EXIT(); - - - - noexcept - - - QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); +$declare ${QF::QMPool} -QXThread * const curr = QXK_PTR_CAST_(QXThread*, QXK_priv_.curr); - -// precondition, this function: -// - must NOT be called from an ISR; -// - the semaphore must be initialized -// - be called from an extended thread; -// - the thread must NOT be already blocked on any object. -Q_REQUIRE_INCRIT(200, (!QXK_ISR_CONTEXT_()) - && (m_max_count > 0U) - && (curr != nullptr) - && (curr->m_temp.obj == nullptr)); -// - the thread must NOT be holding a scheduler lock. -Q_REQUIRE_INCRIT(201, QXK_priv_.lockHolder != curr->m_prio); - -bool taken = true; // assume that the semaphore will be signaled -if (m_count > 0U) { - m_count = m_count - 1U; // semaphore taken: decrement the count - - QS_BEGIN_PRE_(QS_SEM_TAKE, curr->m_prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this semaphore - QS_2U8_PRE_(curr->m_prio, m_count); - QS_END_PRE_() -} -else { // semaphore not available -- BLOCK the thread - std::uint_fast8_t const p = - static_cast<std::uint_fast8_t>(curr->m_prio); - // remove the curr prio from the ready set (will block) - // and insert to the waiting set on this semaphore - QXK_priv_.readySet.remove(p); -#ifndef Q_UNSAFE - QXK_priv_.readySet.update_(&QXK_priv_.readySet_dis); -#endif - m_waitSet.insert(p); +#endif // QMPOOL_HPP_ + + + + #ifndef QV_HPP_ +#define QV_HPP_ - // remember the blocking object (this semaphore) - curr->m_temp.obj = QXK_PTR_CAST_(QMState*, this); - curr->teArm_(static_cast<enum_t>(QXK::TIMEOUT_SIG), nTicks); +$declare ${QV::QV-base} - QS_BEGIN_PRE_(QS_SEM_BLOCK, curr->m_prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this semaphore - QS_2U8_PRE_(curr->m_prio, m_count); - QS_END_PRE_() +//============================================================================ +// interface used only for internal implementation, but not in applications +#ifdef QP_IMPL - // schedule the next thread if multitasking started - static_cast<void>(QXK_sched_()); // schedule other threads +$declare ${QV-impl} - QF_MEM_APP(); - QF_CRIT_EXIT(); - QF_CRIT_EXIT_NOP(); // BLOCK here !!! +$declare ${QF_EPOOL-impl} - QF_CRIT_ENTRY(); // AFTER unblocking... - QF_MEM_SYS(); +#endif // QP_IMPL - // the blocking object must be this semaphore - Q_ASSERT_INCRIT(240, curr->m_temp.obj - == QXK_PTR_CAST_(QMState*, this)); +#endif // QV_HPP_ + + + + #ifndef QK_HPP_ +#define QK_HPP_ - // did the blocking time-out? (signal of zero means that it did) - if (curr->m_timeEvt.sig == 0U) { - if (m_waitSet.hasElement(p)) { // still waiting? - m_waitSet.remove(p); // remove unblocked thread - taken = false; // the semaphore was NOT taken - } - } - else { // blocking did NOT time out - // the thread must NOT be waiting on this semaphore - Q_ASSERT_INCRIT(250, !m_waitSet.hasElement(p)); - } - curr->m_temp.obj = nullptr; // clear blocking obj. -} -QF_MEM_APP(); -QF_CRIT_EXIT(); +$declare ${QK::QSchedStatus} -return taken; - - - - noexcept - QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); +$declare ${QK::QK-base} -// precondition: -// - the semaphore must be initialized -Q_REQUIRE_INCRIT(300, m_max_count > 0U); +extern "C" { +$declare ${QK-extern-C} +} // extern "C" -#ifdef Q_SPY -QActive const * const curr = QXK_PTR_CAST_(QActive*, QXK_priv_.curr); -#endif // Q_SPY +//============================================================================ +// interface used only for internal implementation, but not in applications +#ifdef QP_IMPL -bool taken; -// is the semaphore available? -if (m_count > 0U) { - m_count = m_count - 1U; // semaphore signaled: decrement - taken = true; - - QS_BEGIN_PRE_(QS_SEM_TAKE, curr->m_prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this semaphore - QS_2U8_PRE_(curr->m_prio, m_count); - QS_END_PRE_() -} -else { // the semaphore is NOT available (would block) - taken = false; - - QS_BEGIN_PRE_(QS_SEM_BLOCK_ATTEMPT, curr->m_prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this semaphore - QS_2U8_PRE_(curr->m_prio, m_count); - QS_END_PRE_() -} -QF_MEM_APP(); -QF_CRIT_EXIT(); +$declare ${QK-impl} -return taken; - - - - noexcept - bool signaled = true; // assume that the semaphore will be signaled +$declare ${QF_EPOOL-impl} -QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); +#endif // QP_IMPL -// precondition: -// - the semaphore must be initialized -Q_REQUIRE_INCRIT(400, m_max_count > 0U); - -// any threads blocked on this semaphore? -if (m_waitSet.notEmpty()) { - // find the highest-prio. thread waiting on this semaphore - std::uint_fast8_t const p = m_waitSet.findMax(); - QXThread * const thr = - QXK_PTR_CAST_(QXThread*, QActive::registry_[p]); - - // assert that the thread: - // - must be registered in QF; - // - must be extended; and - // - must be blocked on this semaphore; - Q_ASSERT_INCRIT(410, (thr != nullptr) - && (thr->m_osObject != nullptr) - && (thr->m_temp.obj - == QXK_PTR_CAST_(QMState*, this))); - - // disarm the internal time event - static_cast<void>(thr->teDisarm_()); - - // make the thread ready to run and remove from the wait-list - QXK_priv_.readySet.insert(p); -#ifndef Q_UNSAFE - QXK_priv_.readySet.update_(&QXK_priv_.readySet_dis); -#endif - m_waitSet.remove(p); - - QS_BEGIN_PRE_(QS_SEM_TAKE, thr->m_prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this semaphore - QS_2U8_PRE_(thr->m_prio, m_count); - QS_END_PRE_() - - if (!QXK_ISR_CONTEXT_()) { // not inside ISR? - static_cast<void>(QXK_sched_()); // schedule other threads - } -} -else if (m_count < m_max_count) { - m_count = m_count + 1U; // semaphore signaled: increment - - QS_BEGIN_PRE_(QS_SEM_SIGNAL, 0U) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this semaphore - QS_2U8_PRE_(0U, m_count); - QS_END_PRE_() -} -else { - signaled = false; // semaphore NOT signaled -} -QF_MEM_APP(); -QF_CRIT_EXIT(); +#endif // QK_HPP_ + + + + #ifndef QSTAMP_HPP_ +#define QSTAMP_HPP_ -return signaled; - - - - - - - - - - - : m_ao(Q_STATE_CAST(0)) - - - - noexcept - - - QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); +namespace QP { +extern char const BUILD_DATE[12]; +extern char const BUILD_TIME[9]; +} // namespace QP -Q_REQUIRE_INCRIT(100, (prioSpec & 0xFF00U) == 0U); +#endif // QSTAMP_HPP_ + + + + #ifndef QPCPP_HPP_ +#define QPCPP_HPP_ -m_ao.m_prio = static_cast<std::uint8_t>(prioSpec & 0xFFU); // QF-prio. -m_ao.m_pthre = 0U; // not used -QActive &ao = m_ao; +//============================================================================ +#include "qp_port.hpp" // QP port from the port directory +#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem +#ifdef Q_SPY // software tracing enabled? + #include "qs_port.hpp" // QS/C++ port from the port directory +#else + #include "qs_dummy.hpp" // QS/C++ dummy (inactive) interface +#endif -QF_MEM_APP(); -QF_CRIT_EXIT(); +//============================================================================ +#ifndef QP_API_VERSION + #define QP_API_VERSION 0 +#endif // QP_API_VERSION -ao.register_(); // register this mutex as AO - - - - noexcept - - - QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); +// QP API compatibility layer... +//============================================================================ +#if (QP_API_VERSION < 750) -QXThread * const curr = QXK_PTR_CAST_(QXThread*, QXK_priv_.curr); - -// precondition, this mutex operation must: -// - NOT be called from an ISR; -// - be called from an eXtended thread; -// - the mutex-prio. must be in range; -// - the thread must NOT be already blocked on any object. -Q_REQUIRE_INCRIT(200, (!QXK_ISR_CONTEXT_()) - && (curr != nullptr) - && (m_ao.m_prio <= QF_MAX_ACTIVE) - && (curr->m_temp.obj == nullptr)); -// also: the thread must NOT be holding a scheduler lock. -Q_REQUIRE_INCRIT(201, QXK_priv_.lockHolder != curr->m_prio); - -// is the mutex available? -bool locked = true; // assume that the mutex will be locked -if (m_ao.m_eQueue.m_nFree == 0U) { - m_ao.m_eQueue.m_nFree = 1U; // mutex lock nesting - - // also: the newly locked mutex must have no holder yet - Q_REQUIRE_INCRIT(203, m_ao.m_osObject == nullptr); - - // set the new mutex holder to the curr thread and - // save the thread's prio in the mutex - // NOTE: reuse the otherwise unused eQueue data member. - m_ao.m_osObject = curr; - m_ao.m_eQueue.m_head = static_cast<QEQueueCtr>(curr->m_prio); - - QS_BEGIN_PRE_(QS_MTX_LOCK, curr->m_prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this mutex - QS_U8_PRE_(static_cast<std::uint8_t>(m_ao.m_eQueue.m_head)); - QS_U8_PRE_(static_cast<std::uint8_t>(m_ao.m_eQueue.m_nFree)); - QS_END_PRE_() - - if (m_ao.m_prio != 0U) { // prio.-ceiling protocol used? - // the holder prio. must be lower than that of the mutex - // and the prio. slot must be occupied by this mutex - Q_ASSERT_INCRIT(210, (curr->m_prio < m_ao.m_prio) - && (QActive::registry_[m_ao.m_prio] == &m_ao)); - - // remove the thread's original prio from the ready set - // and insert the mutex's prio into the ready set - QXK_priv_.readySet.remove( - static_cast<std::uint_fast8_t>(m_ao.m_eQueue.m_head)); - QXK_priv_.readySet.insert( - static_cast<std::uint_fast8_t>(m_ao.m_prio)); -#ifndef Q_UNSAFE - QXK_priv_.readySet.update_(&QXK_priv_.readySet_dis); -#endif - // put the thread into the AO registry in place of the mutex - QActive::registry_[m_ao.m_prio] = curr; +#define QM_SM_STATE_DECL(subm_, state_) error "submachines no longer supported" +#define qm_super_sub(sm_state_) error "submachines no longer supported" +#define qm_tran_ep(tatbl_) error "submachines no longer supported" +#define qm_tran_xp(xp_, tatbl_) error "submachines no longer supported" +#define qm_sm_exit(sm_state_) error "submachines no longer supported" - // set thread's prio to that of the mutex - curr->m_prio = m_ao.m_prio; -#ifndef Q_UNSAFE - curr->m_prio_dis = static_cast<std::uint8_t>(~curr->m_prio); +#ifdef QEVT_DYN_CTOR +//! @deprecated #QEVT_DYN_CTOR, please use #QEVT_PAR_INIT +#define QEVT_PAR_INIT #endif - } -} -// is the mutex locked by this thread already (nested locking)? -else if (m_ao.m_osObject == curr) { - - // the nesting level beyond the arbitrary but high bound - // most likely means cyclic or recursive locking of a mutex. - Q_ASSERT_INCRIT(220, m_ao.m_eQueue.m_nFree < 0xFFU); - - // lock one more level - m_ao.m_eQueue.m_nFree = m_ao.m_eQueue.m_nFree + 1U; - - QS_BEGIN_PRE_(QS_MTX_LOCK, curr->m_prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this mutex - QS_U8_PRE_(static_cast<std::uint8_t>(m_ao.m_eQueue.m_head)); - QS_U8_PRE_(static_cast<std::uint8_t>(m_ao.m_eQueue.m_nFree)); - QS_END_PRE_() -} -else { // the mutex is already locked by a different thread - // the mutex holder must be valid - Q_ASSERT_INCRIT(230, m_ao.m_osObject != nullptr); - - if (m_ao.m_prio != 0U) { // prio.-ceiling protocol used? - // the prio slot must be occupied by the thr. holding the mutex - Q_ASSERT_INCRIT(240, QActive::registry_[m_ao.m_prio] - == QXK_PTR_CAST_(QActive const *, m_ao.m_osObject)); - } - // remove the curr thread's prio from the ready set (will block) - // and insert it to the waiting set on this mutex - std::uint_fast8_t const p = - static_cast<std::uint_fast8_t>(curr->m_prio); - QXK_priv_.readySet.remove(p); -#ifndef Q_UNSAFE - QXK_priv_.readySet.update_(&QXK_priv_.readySet_dis); -#endif - m_waitSet.insert(p); +//! @deprecated plain 'char' is no longer forbidden in MISRA/AUTOSAR-C++ +using char_t = char; - // set the blocking object (this mutex) - curr->m_temp.obj = QXK_PTR_CAST_(QMState*, this); - curr->teArm_(static_cast<enum_t>(QXK::TIMEOUT_SIG), nTicks); +//! @deprecated assertion failure handler +//! Use Q_onError() instead. +#define Q_onAssert(module_, id_) Q_onError(module_, id_) - QS_BEGIN_PRE_(QS_MTX_BLOCK, curr->m_prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this mutex - QS_2U8_PRE_(static_cast<std::uint8_t>(m_ao.m_eQueue.m_head), - curr->m_prio); - QS_END_PRE_() +//! @deprecated #Q_NASSERT preprocessor switch to disable QP assertions +#ifdef Q_NASSERT - // schedule the next thread if multitasking started - static_cast<void>(QXK_sched_()); // schedule other threads + // #Q_UNSAFE now replaces the functionality of Q_NASSERT + #define Q_UNSAFE - QF_MEM_APP(); - QF_CRIT_EXIT(); - QF_CRIT_EXIT_NOP(); // BLOCK here !!! + //! @deprecated general purpose assertion with user-specified ID + //! number that **always** evaluates the `expr_` expression. + #define Q_ALLEGE_ID(id_, expr_) (static_cast<void>(expr_)) - // AFTER unblocking... - QF_CRIT_ENTRY(); - QF_MEM_SYS(); - // the blocking object must be this mutex - Q_ASSERT_INCRIT(250, curr->m_temp.obj - == QXK_PTR_CAST_(QMState*, this)); - - // did the blocking time-out? (signal of zero means that it did) - if (curr->m_timeEvt.sig == 0U) { - if (m_waitSet.hasElement(p)) { // still waiting? - m_waitSet.remove(p); // remove unblocked thread - locked = false; // the mutex was NOT locked - } - } - else { // blocking did NOT time out - // the thread must NOT be waiting on this mutex - Q_ASSERT_INCRIT(260, !m_waitSet.hasElement(p)); - } - curr->m_temp.obj = nullptr; // clear blocking obj. -} -QF_MEM_APP(); -QF_CRIT_EXIT(); +#elif defined Q_UNSAFE -return locked; - - - - noexcept - QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); + //! @deprecated general purpose assertion with user-specified ID + //! number that **always** evaluates the `expr_` expression. + #define Q_ALLEGE_ID(id_, expr_) (static_cast<void>(expr_)) -QActive *curr = QXK_priv_.curr; -if (curr == nullptr) { // called from a basic thread? - curr = QActive::registry_[QXK_priv_.actPrio]; -} +#else // QP FuSa Subsystem enabled -// precondition, this mutex must: -// - NOT be called from an ISR; -// - the calling thread must be valid; -// - the mutex-prio. must be in range -Q_REQUIRE_INCRIT(300, (!QXK_ISR_CONTEXT_()) - && (curr != nullptr) - && (m_ao.m_prio <= QF_MAX_ACTIVE)); -// also: the thread must NOT be holding a scheduler lock. -Q_REQUIRE_INCRIT(301, - QXK_priv_.lockHolder != static_cast<std::uint_fast8_t>(curr->m_prio)); - -// is the mutex available? -if (m_ao.m_eQueue.m_nFree == 0U) { - m_ao.m_eQueue.m_nFree = 1U; // mutex lock nesting - - // also the newly locked mutex must have no holder yet - Q_REQUIRE_INCRIT(303, m_ao.m_osObject == nullptr); - - // set the new mutex holder to the curr thread and - // save the thread's prio in the mutex - // NOTE: reuse the otherwise unused eQueue data member. - m_ao.m_osObject = curr; - m_ao.m_eQueue.m_head = static_cast<QEQueueCtr>(curr->m_prio); - - QS_BEGIN_PRE_(QS_MTX_LOCK, curr->m_prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this mutex - QS_U8_PRE_(static_cast<std::uint8_t>(m_ao.m_eQueue.m_head)); - QS_U8_PRE_(static_cast<std::uint8_t>(m_ao.m_eQueue.m_nFree)); - QS_END_PRE_() - - if (m_ao.m_prio != 0U) { // prio.-ceiling protocol used? - // the holder prio. must be lower than that of the mutex - // and the prio. slot must be occupied by this mutex - Q_ASSERT_INCRIT(310, (curr->m_prio < m_ao.m_prio) - && (QActive::registry_[m_ao.m_prio] == &m_ao)); - - // remove the thread's original prio from the ready set - // and insert the mutex's prio into the ready set - QXK_priv_.readySet.remove( - static_cast<std::uint_fast8_t>(m_ao.m_eQueue.m_head)); - QXK_priv_.readySet.insert( - static_cast<std::uint_fast8_t>(m_ao.m_prio)); -#ifndef Q_UNSAFE - QXK_priv_.readySet.update_(&QXK_priv_.readySet_dis); -#endif - // put the thread into the AO registry in place of the mutex - QActive::registry_[m_ao.m_prio] = curr; + //! @deprecated general purpose assertion with user-specified ID + //! number that **always** evaluates the `expr_` expression. + //! @note + //! The use of this macro is no longer recommended. + #define Q_ALLEGE_ID(id_, expr_) if (!(expr_)) { \ + QF_CRIT_STAT \ + QF_CRIT_ENTRY(); \ + Q_onError(&Q_this_module_[0], (id_)); \ + QF_CRIT_EXIT(); \ + } else ((void)0) - // set thread's prio to that of the mutex - curr->m_prio = m_ao.m_prio; -#ifndef Q_UNSAFE - curr->m_prio_dis = static_cast<std::uint8_t>(~curr->m_prio); #endif - } -} -// is the mutex locked by this thread already (nested locking)? -else if (m_ao.m_osObject == curr) { - // the nesting level must not exceed the specified bound - Q_ASSERT_INCRIT(320, m_ao.m_eQueue.m_nFree < 0xFFU); - - // lock one more level - m_ao.m_eQueue.m_nFree = m_ao.m_eQueue.m_nFree + 1U; - - QS_BEGIN_PRE_(QS_MTX_LOCK, curr->m_prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this mutex - QS_U8_PRE_(static_cast<std::uint8_t>(m_ao.m_eQueue.m_head)); - QS_U8_PRE_(static_cast<std::uint8_t>(m_ao.m_eQueue.m_nFree)); - QS_END_PRE_() -} -else { // the mutex is already locked by a different thread - if (m_ao.m_prio != 0U) { // prio.-ceiling protocol used? - // the prio slot must be occupied by the thr. holding the mutex - Q_ASSERT_INCRIT(330, QActive::registry_[m_ao.m_prio] - == QXK_PTR_CAST_(QActive const *, m_ao.m_osObject)); - } - QS_BEGIN_PRE_(QS_MTX_BLOCK_ATTEMPT, curr->m_prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this mutex - QS_2U8_PRE_(static_cast<std::uint8_t>(m_ao.m_eQueue.m_head), - curr->m_prio); // trying thread prio - QS_END_PRE_() +//! @deprecated general purpose assertion without ID number +//! that **always** evaluates the `expr_` expression. +//! Instead of ID number, this macro is based on the standard +//! `__LINE__` macro. +//! +//! @note The use of this macro is no longer recommended. +#define Q_ALLEGE(expr_) Q_ALLEGE_ID(__LINE__, (expr_)) - curr = nullptr; // means that mutex is NOT available -} -QF_MEM_APP(); -QF_CRIT_EXIT(); +//! Static (compile-time) assertion. +//! +//! @deprecated +//! Use Q_ASSERT_STATIC() or better yet `static_assert()` instead. +//! +#define Q_ASSERT_COMPILE(expr_) Q_ASSERT_STATIC(expr_) -return curr != nullptr; - - - - noexcept - QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); +//! @deprecated use QP::QF::NO_MARGIN instead +#define QF_NO_MARGIN QP::QF::NO_MARGIN -QActive *curr = QXK_priv_.curr; -if (curr == nullptr) { // called from a basic thread? - curr = QActive::registry_[QXK_priv_.actPrio]; -} +//============================================================================ +#if (QP_API_VERSION < 691) -Q_REQUIRE_INCRIT(400, (!QXK_ISR_CONTEXT_()) - && (curr != nullptr)); -Q_REQUIRE_INCRIT(401, m_ao.m_eQueue.m_nFree > 0U); -Q_REQUIRE_INCRIT(403, m_ao.m_osObject == curr); +//! @deprecated enable the QS global filter +#define QS_FILTER_ON(rec_) QS_GLB_FILTER((rec_)) -// is this the last nesting level? -if (m_ao.m_eQueue.m_nFree == 1U) { +//! @deprecated disable the QS global filter +#define QS_FILTER_OFF(rec_) QS_GLB_FILTER(-(rec_)) - if (m_ao.m_prio != 0U) { // prio.-ceiling protocol used? +//! @deprecated enable the QS local filter for SM (state machine) object +#define QS_FILTER_SM_OBJ(obj_) (static_cast<void>(0)) - Q_ASSERT_INCRIT(410, m_ao.m_prio < QF_MAX_ACTIVE); +//! @deprecated enable the QS local filter for AO (active objects) +#define QS_FILTER_AO_OBJ(obj_) (static_cast<void>(0)) - // restore the holding thread's prio from the mutex - curr->m_prio = - static_cast<std::uint8_t>(m_ao.m_eQueue.m_head); -#ifndef Q_UNSAFE - curr->m_prio_dis = static_cast<std::uint8_t>(~curr->m_prio); -#endif +//! @deprecated enable the QS local filter for MP (memory pool) object +#define QS_FILTER_MP_OBJ(obj_) (static_cast<void>(0)) - // put the mutex back into the AO registry - QActive::registry_[m_ao.m_prio] = &m_ao; +//! @deprecated enable the QS local filter for EQ (event queue) object +#define QS_FILTER_EQ_OBJ(obj_) (static_cast<void>(0)) - // remove the mutex' prio from the ready set - // and insert the original thread's prio. - QXK_priv_.readySet.remove( - static_cast<std::uint_fast8_t>(m_ao.m_prio)); - QXK_priv_.readySet.insert( - static_cast<std::uint_fast8_t>(m_ao.m_eQueue.m_head)); -#ifndef Q_UNSAFE - QXK_priv_.readySet.update_(&QXK_priv_.readySet_dis); -#endif - } +//! @deprecated enable the QS local filter for TE (time event) object +#define QS_FILTER_TE_OBJ(obj_) (static_cast<void>(0)) - QS_BEGIN_PRE_(QS_MTX_UNLOCK, curr->m_prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this mutex - QS_2U8_PRE_(static_cast<std::uint8_t>(m_ao.m_eQueue.m_head), - 0U); - QS_END_PRE_() - - // are any other threads waiting on this mutex? - if (m_waitSet.notEmpty()) { - // find the highest-prio. thread waiting on this mutex - std::uint_fast8_t const p = m_waitSet.findMax(); - - // remove this thread from waiting on the mutex - // and insert it into the ready set. - m_waitSet.remove(p); - QXK_priv_.readySet.insert(p); -#ifndef Q_UNSAFE - QXK_priv_.readySet.update_(&QXK_priv_.readySet_dis); -#endif +#ifdef Q_SPY - QXThread * const thr = - QXK_PTR_CAST_(QXThread*, QActive::registry_[p]); - - // the waiting thread must: - // - be registered in QF - // - have the prio. corresponding to the registration - // - be an extended thread - // - be blocked on this mutex - Q_ASSERT_INCRIT(420, (thr != nullptr) - && (thr->m_prio == static_cast<std::uint8_t>(p)) - && (thr->m_state.act == Q_ACTION_CAST(0)) - && (thr->m_temp.obj == QXK_PTR_CAST_(QMState*, this))); - - // disarm the internal time event - static_cast<void>(thr->teDisarm_()); - - // set the new mutex holder to the curr thread and - // save the thread's prio in the mutex - // NOTE: reuse the otherwise unused eQueue data member. - m_ao.m_osObject = thr; - m_ao.m_eQueue.m_head = static_cast<QEQueueCtr>(thr->m_prio); - - QS_BEGIN_PRE_(QS_MTX_LOCK, thr->m_prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this mutex - QS_U8_PRE_(static_cast<std::uint8_t>(m_ao.m_eQueue.m_head)); - QS_U8_PRE_(static_cast<std::uint8_t>(m_ao.m_eQueue.m_nFree)); - QS_END_PRE_() - - if (m_ao.m_prio != 0U) { // prio.-ceiling protocol used? - // the holder prio. must be lower than that of the mutex - Q_ASSERT_INCRIT(430, (m_ao.m_prio < QF_MAX_ACTIVE) - && (thr->m_prio < m_ao.m_prio)); - - // put the thread into AO registry in place of the mutex - QActive::registry_[m_ao.m_prio] = thr; - } - } - else { // no threads are waiting for this mutex - m_ao.m_eQueue.m_nFree = 0U; // free up the nesting count +//! @deprecated local Filter for a generic application object `obj_`. +#define QS_FILTER_AP_OBJ(obj_) \ + (QP::QS::filt_.loc_AP = (obj_)) - // the mutex no longer held by any thread - m_ao.m_osObject = nullptr; - m_ao.m_eQueue.m_head = 0U; - m_ao.m_eQueue.m_tail = 0U; +//! @deprecated begin of a user QS record, instead use QS_BEGIN_ID() +#define QS_BEGIN(rec_, obj_) \ + if (QS_GLB_FILTER_(rec_) && \ + ((QP::QS::filt_.loc[QP::QS::AP_OBJ] == nullptr) \ + || (QP::QS::filt_.loc_AP == (obj_)))) \ + { \ + QS_CRIT_STAT \ + QS_CRIT_ENTRY(); \ + QP::QS::beginRec_(static_cast<std::uint_fast8_t>(rec_)); \ + QS_TIME_PRE(); - if (m_ao.m_prio != 0U) { // prio.-ceiling protocol used? - // the AO priority must be in range - Q_ASSERT_INCRIT(440, m_ao.m_prio < QF_MAX_ACTIVE); +//! @deprecated output hex-formatted std::uint32_t to the QS record +#define QS_U32_HEX(width_, data_) \ + (QP::QS::u32_fmt_(static_cast<std::uint8_t>( \ + (static_cast<std::uint8_t>((width_) << 4)) | QS_HEX_FMT), (data_))) - // put the mutex back at the original mutex slot - QActive::registry_[m_ao.m_prio] = &m_ao; - } - } +#else - // schedule the next thread if multitasking started - if (QXK_sched_() != 0U) { // activation needed? - QXK_activate_(); // synchronously activate basic-thred(s) - } -} -else { // releasing one level of nested mutex lock - // unlock one level - m_ao.m_eQueue.m_nFree = m_ao.m_eQueue.m_nFree - 1U; - - QS_BEGIN_PRE_(QS_MTX_UNLOCK_ATTEMPT, curr->m_prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this mutex - QS_U8_PRE_(static_cast<std::uint8_t>(m_ao.m_eQueue.m_head)); - QS_U8_PRE_(static_cast<std::uint8_t>(m_ao.m_eQueue.m_nFree)); - QS_END_PRE_() -} -QF_MEM_APP(); -QF_CRIT_EXIT(); - - - - - - - bzero_(&QF::priv_, sizeof(QF::priv_)); -bzero_(&QXK_priv_, sizeof(QXK_priv_)); -bzero_(&QActive::registry_[0], sizeof(QActive::registry_)); +#define QS_FILTER_AP_OBJ(obj_) (static_cast<void>(0)) +#define QS_BEGIN(rec_, obj_) if (false) { +#define QS_U32_HEX(width_, data_) (Q_UNUSED_PAR(0)) -#ifndef Q_UNSAFE -QXK_priv_.readySet.update_(&QXK_priv_.readySet_dis); -#endif +#endif // def Q_SPY -// setup the QXK scheduler as initially locked and not running -QXK_priv_.lockCeil = (QF_MAX_ACTIVE + 1U); // scheduler locked +//============================================================================ +#if (QP_API_VERSION < 680) -// storage capable for holding a blank QActive object (const in ROM) -static void* const - idle_ao[((sizeof(QActive) + sizeof(void*)) - 1U) / sizeof(void*)] - = { nullptr }; +//! @deprecated +//! Macro to specify a tran. in the "me->" impl-strategy. +//! Instead use the new impl-strategy without the "me->" pointer, where +//! you call tran(Q_STATE_CAST(target_)). +#define Q_TRAN(target_) (me->tran(Q_STATE_CAST(target_))) -// register the idle AO object (cast 'const' away) -QActive::registry_[0] = QF_CONST_CAST_(QActive*, - reinterpret_cast<QActive const*>(idle_ao)); +//! @deprecated +//! Macro to specify a tran-to-history in the "me->" impl-strategy. +//! Instead use the new impl-strategy without the "me->" pointer, where +//! you call tran_hist(Q_STATE_CAST(hist_)). +#define Q_TRAN_HIST(hist_) (me->tran_hist((hist_))) -#ifdef QXK_INIT -QXK_INIT(); // port-specific initialization of the QXK kernel -#endif - - - - onCleanup(); // cleanup callback -// nothing else to do for the QXK preemptive kernel - - - - #ifdef Q_SPY -QS_SIG_DICTIONARY(QXK::DELAY_SIG, nullptr); -QS_SIG_DICTIONARY(QXK::TIMEOUT_SIG, nullptr); +//! @deprecated +//! Macro to specify the superstate in the "me->" impl-strategy. +//! Instead use the new impl-strategy without the "me->" pointer, where +//! you call super(state_)). +#define Q_SUPER(state_) (me->super(Q_STATE_CAST(state_))) -// produce the QS_QF_RUN trace record -QF_INT_DISABLE(); -QF_MEM_SYS(); -QS::beginRec_(QS_REC_NUM_(QS_QF_RUN)); -QS::endRec_(); -QF_MEM_APP(); -QF_INT_ENABLE(); -#endif // Q_SPY +//! @deprecated +//! Macro to call in a QM state entry-handler. Applicable only to QMSMs. +//! Instead use the new impl-strategy without the "me->" pointer, where +//! the QM-generated code calls qm_entry(Q_STATE_CAST(state_)). +#define QM_ENTRY(state_) (me->qm_entry((state_))) -onStartup(); // application-specific startup callback +//! @deprecated +//! Macro to call in a QM state exit-handler. Applicable only to QMSMs. +//! Instead use the new impl-strategy without the "me->" pointer, where +//! the QM-generated code calls qm_exit(Q_STATE_CAST(state_)). +#define QM_EXIT(state_) (me->qm_exit((state_))) -QF_INT_DISABLE(); -QF_MEM_SYS(); +//! @deprecated +//! Macro to call in a QM state-handler when it executes a tran. +//! Instead use the new impl-strategy without the "me->" pointer, where +//! the QM-generated code calls qm_tran((tatbl_)). +#define QM_TRAN(tatbl_) (me->qm_tran((tatbl_))) -#ifdef QXK_START -QXK_START(); // port-specific startup of the QXK kernel -#endif +//! @deprecated +//! Macro to call in a QM state-handler when it executes an initial tran. +//! Instead use the new impl-strategy without the "me->" pointer, where +//! the QM-generated code calls qm_tran_init((tatbl_)). +#define QM_TRAN_INIT(tatbl_) (me->qm_tran_init((tatbl_))) -QXK_priv_.lockCeil = 0U; // unlock the QXK scheduler +//! @deprecated +//! Macro to call in a QM state-handler when it executes a tran-to-history. +//! Instead use the new impl-strategy without the "me->" pointer, where +//! the QM-generated code calls qm_tran_hist((history_), (tatbl_)). +#define QM_TRAN_HIST(history_, tatbl_) \ + (me->qm_tran_hist((history_), (tatbl_))) -// activate AOs to process events posted so far -if (QXK_sched_() != 0U) { - QXK_activate_(); -} +#endif // QP_API_VERSION < 680 +#endif // QP_API_VERSION < 691 +#endif // QP_API_VERSION < 750 -QF_MEM_APP(); -QF_INT_ENABLE(); +#endif // QPCPP_HPP_ + + + + + + + + + #define QP_IMPL // this is QP implementation +#include "qp_port.hpp" // QP port +#include "qp_pkg.hpp" // QP package-scope interface +#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem +#ifdef Q_SPY // QS software tracing enabled? + #include "qs_port.hpp" // QS port + #include "qs_pkg.hpp" // QS facilities for pre-defined trace records +#else + #include "qs_dummy.hpp" // disable the QS software tracing +#endif // Q_SPY -for (;;) { // QXK idle loop... - QXK::onIdle(); // application-specific QXK idle callback -} +//============================================================================ +//! @cond INTERNAL -#ifdef __GNUC__ // GNU compiler? -return 0; -#endif - - - - - - - - - - - - - - - - - - - QF_CRIT_STAT -QF_CRIT_ENTRY(); -Q_REQUIRE_INCRIT(300, (!QXK_ISR_CONTEXT_()) - && ((prioSpec & 0xFF00U) == 0U)); -QF_CRIT_EXIT(); +// unnamed namespace for local definitions with internal linkage +namespace { +Q_DEFINE_THIS_MODULE("qep_hsm") -m_prio = static_cast<std::uint8_t>(prioSpec & 0xFFU); // QF-prio. -m_pthre = 0U; // not used -register_(); // make QF aware of this QActive/QXThread +// immutable events corresponding to the reserved signals. +static QP::QEvt const l_reservedEvt_[4] { + QP::QEvt(static_cast<QP::QSignal>(QP::QHsm::Q_EMPTY_SIG)), + QP::QEvt(static_cast<QP::QSignal>(QP::QHsm::Q_ENTRY_SIG)), + QP::QEvt(static_cast<QP::QSignal>(QP::QHsm::Q_EXIT_SIG)), + QP::QEvt(static_cast<QP::QSignal>(QP::QHsm::Q_INIT_SIG)) +}; -if (stkSto == nullptr) { // starting basic thread (AO)? - m_eQueue.init(qSto, qLen); // init the built-in queue - m_osObject = nullptr; // no private stack for AO +// maximum depth of state nesting in a QHsm (including the top level) +// must be >= 3 +static constexpr std::int_fast8_t QHSM_MAX_NEST_DEPTH_ {6}; - this->init(par, m_prio); // top-most initial tran. (virtual call) - QS_FLUSH(); // flush the trace buffer to the host +} // unnamed namespace - // see if this AO needs to be scheduled if QXK is already running - QF_CRIT_ENTRY(); - QF_MEM_SYS(); - if (QXK_priv_.lockCeil <= QF_MAX_ACTIVE) { // scheduler running? - if (QXK_sched_() != 0U) { // activation needed? - QXK_activate_(); // synchronously activate basic-thred(s) - } - } - QF_MEM_APP(); - QF_CRIT_EXIT(); -} -else { // starting QXThread +// helper macro to handle reserved event in an QHsm +#define QHSM_RESERVED_EVT_(state_, sig_) \ + ((*(state_))(this, &l_reservedEvt_[(sig_)])) - // is storage for the queue buffer provided? - if (qSto != nullptr) { - m_eQueue.init(qSto, qLen); - } +// helper macro to trace state entry +#define QS_STATE_ENTRY_(state_, qsId_) \ + QS_CRIT_ENTRY(); \ + QS_MEM_SYS(); \ + QS_BEGIN_PRE(QS_QEP_STATE_ENTRY, (qsId_)) \ + QS_OBJ_PRE(this); \ + QS_FUN_PRE(state_); \ + QS_END_PRE() \ + QS_MEM_APP(); \ + QS_CRIT_EXIT() - // extended threads provide their thread function in place of - // the top-most initial tran. 'm_temp.act' - QXK_PTR_CAST_(QXThread*, this)->stackInit_(m_temp.thr, - stkSto, stkSize); +// helper macro to trace state exit +#define QS_STATE_EXIT_(state_, qsId_) \ + QS_CRIT_ENTRY(); \ + QS_MEM_SYS(); \ + QS_BEGIN_PRE(QS_QEP_STATE_EXIT, (qsId_)) \ + QS_OBJ_PRE(this); \ + QS_FUN_PRE(state_); \ + QS_END_PRE() \ + QS_MEM_APP(); \ + QS_CRIT_EXIT() - // the new thread is not blocked on any object - m_temp.obj = nullptr; +//! @endcond - QF_CRIT_ENTRY(); - QF_MEM_SYS(); +//============================================================================ - // extended-thread becomes ready immediately - QXK_priv_.readySet.insert(static_cast<std::uint_fast8_t>(m_prio)); - #ifndef Q_UNSAFE - QXK_priv_.readySet.update_(&QXK_priv_.readySet_dis); - #endif +$define ${QEP::versionStr[]} - // see if this thread needs to be scheduled in case QXK is running - if (QXK_priv_.lockCeil <= QF_MAX_ACTIVE) { - static_cast<void>(QXK_sched_()); // schedule other threads - } - QF_MEM_APP(); - QF_CRIT_EXIT(); -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - noexcept - Q_INVARIANT_INCRIT(402, - QXK_priv_.readySet.verify_(&QXK_priv_.readySet_dis)); +$define ${QEP::QHsm} + + + + #define QP_IMPL // this is QP implementation +#include "qp_port.hpp" // QP port +#include "qp_pkg.hpp" // QP package-scope interface +#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem +#ifdef Q_SPY // QS software tracing enabled? + #include "qs_port.hpp" // QS port + #include "qs_pkg.hpp" // QS facilities for pre-defined trace records +#else + #include "qs_dummy.hpp" // disable the QS software tracing +#endif // Q_SPY -std::uint_fast8_t p; -if (QXK_priv_.readySet.isEmpty()) { - p = 0U; // no activation needed -} -else { - // find the highest-prio thread ready to run - p = QXK_priv_.readySet.findMax(); - if (p <= QXK_priv_.lockCeil) { - // prio. of the thread holding the lock - p = static_cast<std::uint_fast8_t>( - QP::QActive::registry_[QXK_priv_.lockHolder]->getPrio()); - if (p != 0U) { - Q_ASSERT_INCRIT(410, QXK_priv_.readySet.hasElement(p)); - } - } -} -QP::QActive const * const curr = QXK_priv_.curr; -QP::QActive * const next = QP::QActive::registry_[p]; +//============================================================================ +//! @cond INTERNAL -// the next thread found must be registered in QF -Q_ASSERT_INCRIT(420, next != nullptr); +// unnamed namespace for local definitions with internal linkage +namespace { -// is the current thread a basic-thread? -if (curr == nullptr) { +Q_DEFINE_THIS_MODULE("qep_msm") - // is the new prio. above the active prio.? - if (p > QXK_priv_.actPrio) { - QXK_priv_.next = next; // set the next AO to activate +// top-state object for QMsm-style state machines +QP::QMState const l_msm_top_s = { + nullptr, + nullptr, + nullptr, + nullptr, + nullptr +}; - if (next->getOsObject() != nullptr) { // is next extended? - QXK_CONTEXT_SWITCH_(); - p = 0U; // no activation needed - } - } - else { // below the active prio. - QXK_priv_.next = nullptr; - p = 0U; // no activation needed - } -} -else { // currently executing an extended-thread - // is the current thread different from the next? - if (curr != next) { - QXK_priv_.next = next; - QXK_CONTEXT_SWITCH_(); - } - else { // current is the same as next - QXK_priv_.next = nullptr; // no need to context-switch - } - p = 0U; // no activation needed -} +// maximum depth of state nesting in a QMsm (including the top level) +static constexpr std::int_fast8_t QMSM_MAX_NEST_DEPTH_ {8}; -return p; - - - - noexcept - std::uint_fast8_t const prio_in = QXK_priv_.actPrio; -QP::QActive *next = QXK_priv_.next; // the next AO (basic-thread) to run +// maximum length of transition-action array +static constexpr std::int_fast8_t QMSM_MAX_TRAN_LENGTH_ {2*QMSM_MAX_NEST_DEPTH_}; -Q_REQUIRE_INCRIT(500, (next != nullptr) && (prio_in <= QF_MAX_ACTIVE)); +// maximum depth of entry levels in a MSM for tran. to history. +static constexpr std::int_fast8_t QMSM_MAX_ENTRY_DEPTH_ {4}; -// QXK Context switch callback defined or QS tracing enabled? -#if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) -QXK_contextSw_(next); -#endif // QF_ON_CONTEXT_SW || Q_SPY +} // unnamed namespace -QXK_priv_.next = nullptr; // clear the next AO -QXK_priv_.curr = nullptr; // current is basic-thread +//! @endcond +//============================================================================ -// prio. of the next thread -std::uint_fast8_t p = next->getPrio(); +$define ${QEP::QMsm} + + + + #define QP_IMPL // this is QP implementation +#include "qp_port.hpp" // QP port +#include "qp_pkg.hpp" // QP package-scope interface +#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem +#ifdef Q_SPY // QS software tracing enabled? + #include "qs_port.hpp" // QS port + #include "qs_pkg.hpp" // QS facilities for pre-defined trace records +#else + #include "qs_dummy.hpp" // disable the QS software tracing +#endif // Q_SPY -// loop until no more ready-to-run AOs of higher prio than the initial -do { - QXK_priv_.actPrio = p; // next active prio +// unnamed namespace for local definitions with internal linkage +namespace { +//Q_DEFINE_THIS_MODULE("qf_act") +} // unnamed namespace - QF_MEM_APP(); - QF_INT_ENABLE(); // unconditionally enable interrupts +$define ${QF::QActive::registry_[QF_MAX_ACTIVE + 1U]} - QP::QEvt const * const e = next->get_(); - // NOTE QActive::get_() performs QS_MEM_APP() before return +$define ${QF::QF-pkg} +$define ${QF::types::QF_LOG2} +#ifndef Q_UNSAFE +$define ${QF::types::QPtrDis} +#endif + + + + #define QP_IMPL // this is QP implementation +#include "qp_port.hpp" // QP port +#include "qp_pkg.hpp" // QP package-scope interface +#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem +#ifdef Q_SPY // QS software tracing enabled? + #include "qs_port.hpp" // QS port + #include "qs_pkg.hpp" // QS facilities for pre-defined trace records +#else + #include "qs_dummy.hpp" // disable the QS software tracing +#endif // Q_SPY - // dispatch event (virtual call) - next->dispatch(e, next->getPrio()); -#if (QF_MAX_EPOOL > 0U) - QP::QF::gc(e); -#endif +//============================================================================ +// unnamed namespace for local definitions with internal linkage +namespace { +Q_DEFINE_THIS_MODULE("qf_actq") +} // unnamed namespace - QF_INT_DISABLE(); // unconditionally disable interrupts - QF_MEM_SYS(); +$define ${QF::QActive::post_} - // check internal integrity (duplicate inverse storage) - Q_INVARIANT_INCRIT(502, - QXK_priv_.readySet.verify_(&QXK_priv_.readySet_dis)); +$define ${QF::QActive::postLIFO} - if (next->getEQueue().isEmpty()) { // empty queue? - QXK_priv_.readySet.remove(p); -#ifndef Q_UNSAFE - QXK_priv_.readySet.update_(&QXK_priv_.readySet_dis); -#endif - } +$define ${QF::QActive::get_} - if (QXK_priv_.readySet.isEmpty()) { - QXK_priv_.next = nullptr; - next = QP::QActive::registry_[0]; - p = 0U; // no activation needed - } - else { - // find next highest-prio below the lock ceiling - p = QXK_priv_.readySet.findMax(); - if (p <= QXK_priv_.lockCeil) { - p = QXK_priv_.lockHolder; - if (p != 0U) { - Q_ASSERT_INCRIT(510, QXK_priv_.readySet.hasElement(p)); - } - } +$define ${QF::QTicker} + + + + #define QP_IMPL // this is QP implementation +#include "qp_port.hpp" // QP port +#include "qp_pkg.hpp" // QP package-scope interface +#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem +#ifdef Q_SPY // QS software tracing enabled? + #include "qs_port.hpp" // QS port + #include "qs_pkg.hpp" // QS facilities for pre-defined trace records +#else + #include "qs_dummy.hpp" // disable the QS software tracing +#endif // Q_SPY - // set the next thread and ensure that it is registered - next = QP::QActive::registry_[p]; - Q_ASSERT_INCRIT(520, next != nullptr); +// unnamed namespace for local definitions with internal linkage +namespace { +Q_DEFINE_THIS_MODULE("qf_defer") +} // unnamed namespace - // is next a basic thread? - if (next->getOsObject() == nullptr) { - // is the next prio. above the initial prio.? - if (p > QP::QActive::registry_[prio_in]->getPrio()) { -#if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) - if (p != QXK_priv_.actPrio) { // changing threads? - QXK_contextSw_(next); - } -#endif // QF_ON_CONTEXT_SW || Q_SPY - QXK_priv_.next = next; - } - else { - QXK_priv_.next = nullptr; - p = 0U; // no activation needed - } - } - else { // next is the extended-thread - QXK_priv_.next = next; - QXK_CONTEXT_SWITCH_(); - p = 0U; // no activation needed - } - } -} while (p != 0U); // while activation needed +$define ${QF::QActive::defer} -// restore the active prio. -QXK_priv_.actPrio = prio_in; +$define ${QF::QActive::recall} -#if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) -if (next->getOsObject() == nullptr) { - QXK_contextSw_((prio_in == 0U) - ? nullptr - : QP::QActive::registry_[prio_in]); -} -#endif // QF_ON_CONTEXT_SW || Q_SPY - - - - - - #ifdef Q_SPY -std::uint_fast8_t const prev_prio = (QXK_priv_.prev != nullptr) - ? QXK_priv_.prev->getPrio() - : 0U; -if (next != nullptr) { // next is NOT idle? - std::uint_fast8_t const next_prio = next->getPrio(); - QS_BEGIN_PRE_(QP::QS_SCHED_NEXT, next_prio) - QS_TIME_PRE_(); // timestamp - QS_2U8_PRE_(next_prio, prev_prio); - QS_END_PRE_() -} -else { // going to idle - QS_BEGIN_PRE_(QP::QS_SCHED_IDLE, prev_prio) - QS_TIME_PRE_(); // timestamp - QS_U8_PRE_(prev_prio); - QS_END_PRE_() -} -#endif // Q_SPY - -#ifdef QF_ON_CONTEXT_SW -QF_onContextSw(QXK_priv_.prev, next); -#endif // QF_ON_CONTEXT_SW - -QXK_priv_.prev = next; // update the previous thread - - - - QF_CRIT_STAT -QF_CRIT_ENTRY(); - -QP::QXThread const * const thr = QXTHREAD_CAST_(QXK_priv_.curr); - -Q_REQUIRE_INCRIT(900, (!QXK_ISR_CONTEXT_()) - && (thr != nullptr)); // current thread must be extended -Q_REQUIRE_INCRIT(901, QXK_priv_.lockHolder != thr->getPrio()); - -std::uint_fast8_t const p = - static_cast<std::uint_fast8_t>(thr->getPrio()); - -QF_MEM_SYS(); -QP::QActive::registry_[p] = nullptr; -QXK_priv_.readySet.remove(p); -#ifndef Q_UNSAFE -QXK_priv_.readySet.update_(&QXK_priv_.readySet_dis); -#endif - -static_cast<void>(QXK_sched_()); // schedule other threads - -QF_MEM_APP(); -QF_CRIT_EXIT(); - - - - - - - QSchedStatus lockStat_; - - - - - - do { \ - if (QXK_ISR_CONTEXT_()) { \ - lockStat_ = 0xFFU; \ - } else { \ - lockStat_ = QXK::schedLock((ceil_)); \ - } \ -} while (false) - - - - do { \ - if (lockStat_ != 0xFFU) { \ - QXK::schedUnlock(lockStat_); \ - } \ -} while (false) - - - - // QXK native event queue waiting - - - \ - Q_ASSERT_INCRIT(310, (me_)->m_eQueue.m_frontEvt != nullptr) - - - - // QXK native event queue signalling - - - do { \ - QXK_priv_.readySet.insert( \ - static_cast<std::uint_fast8_t>((me_)->m_prio)); \ - QXK_priv_.readySet.update_(&QXK_priv_.readySet_dis); \ - if (!QXK_ISR_CONTEXT_()) { \ - if (QXK_sched_() != 0U) { \ - QXK_activate_(); \ - } \ - } \ -} while (false) - - - - // QXK native event queue signalling - - - do { \ - QXK_priv_.readySet.insert( \ - static_cast<std::uint_fast8_t>((me_)->m_prio)); \ - if (!QXK_ISR_CONTEXT_()) { \ - if (QXK_sched_() != 0U) { \ - QXK_activate_(); \ - } \ - } \ -} while (false) - - - - - - do { \ - if ((me_)->m_temp.obj == QXK_PTR_CAST_(QMState*, &(me_)->m_eQueue)) { \ - static_cast<void>(QXTHREAD_CAST_(me_)->teDisarm_()); \ - QXK_priv_.readySet.insert( \ - static_cast<std::uint_fast8_t>((me_)->m_prio)); \ - QXK_priv_.readySet.update_(&QXK_priv_.readySet_dis); \ - if (!QXK_ISR_CONTEXT_()) { \ - static_cast<void>(QXK_sched_()); \ - } \ - } \ -} while (false) - - - - - - do { \ - if ((me_)->m_temp.obj == QXK_PTR_CAST_(QMState*, &(me_)->m_eQueue)) { \ - static_cast<void>(QXTHREAD_CAST_(me_)->teDisarm_()); \ - QXK_priv_.readySet.insert( \ - static_cast<std::uint_fast8_t>((me_)->m_prio)); \ - if (!QXK_ISR_CONTEXT_()) { \ - static_cast<void>(QXK_sched_()); \ - } \ - } \ -} while (false) - - - - - - (static_cast<QP::QXThread *>(ptr_)) - - - - <type_> - - - - - (reinterpret_cast<type_>(ptr_)) - - - - - - - - - //! pre-defined QS record IDs - : std::int8_t { - // [0] QS session (not maskable) - QS_EMPTY, //!< QS record for cleanly starting a session - - // [1] SM records - QS_QEP_STATE_ENTRY, //!< a state was entered - QS_QEP_STATE_EXIT, //!< a state was exited - QS_QEP_STATE_INIT, //!< an initial transition was taken in a state - QS_QEP_INIT_TRAN, //!< the top-most initial transition was taken - QS_QEP_INTERN_TRAN, //!< an internal transition was taken - QS_QEP_TRAN, //!< a regular transition was taken - QS_QEP_IGNORED, //!< an event was ignored (silently discarded) - QS_QEP_DISPATCH, //!< an event was dispatched (begin of RTC step) - QS_QEP_UNHANDLED, //!< an event was un-handled due to a guard - - // [10] Active Object (AO) records - QS_QF_ACTIVE_DEFER, //!< AO deferred an event - QS_QF_ACTIVE_RECALL, //!< AO recalled an event - QS_QF_ACTIVE_SUBSCRIBE, //!< an AO subscribed to an event - QS_QF_ACTIVE_UNSUBSCRIBE, //!< an AO unsubscribed to an event - QS_QF_ACTIVE_POST, //!< an event was posted (FIFO) directly to AO - QS_QF_ACTIVE_POST_LIFO, //!< an event was posted (LIFO) directly to AO - QS_QF_ACTIVE_GET, //!< AO got an event and its queue is not empty - QS_QF_ACTIVE_GET_LAST,//!< AO got an event and its queue is empty - QS_QF_ACTIVE_RECALL_ATTEMPT, //!< AO attempted to recall an event - - // [19] Event Queue (EQ) records - QS_QF_EQUEUE_POST, //!< an event was posted (FIFO) to a raw queue - QS_QF_EQUEUE_POST_LIFO, //!< an event was posted (LIFO) to a raw queue - QS_QF_EQUEUE_GET, //!< get an event and queue still not empty - QS_QF_EQUEUE_GET_LAST,//!< get the last event from the queue - - // [23] Framework (QF) records - QS_QF_NEW_ATTEMPT, //!< an attempt to allocate an event failed - - // [24] Memory Pool (MP) records - QS_QF_MPOOL_GET, //!< a memory block was removed from memory pool - QS_QF_MPOOL_PUT, //!< a memory block was returned to memory pool - - // [26] Additional Framework (QF) records - QS_QF_PUBLISH, //!< an event was published to active objects - QS_QF_NEW_REF, //!< new event reference was created - QS_QF_NEW, //!< new event was created - QS_QF_GC_ATTEMPT, //!< garbage collection attempt - QS_QF_GC, //!< garbage collection - QS_QF_TICK, //!< QTimeEvt tick was called - - // [32] Time Event (TE) records - QS_QF_TIMEEVT_ARM, //!< a time event was armed - QS_QF_TIMEEVT_AUTO_DISARM, //!< a time event expired and was disarmed - QS_QF_TIMEEVT_DISARM_ATTEMPT,//!< attempt to disarm a disarmed QTimeEvt - QS_QF_TIMEEVT_DISARM, //!< true disarming of an armed time event - QS_QF_TIMEEVT_REARM, //!< rearming of a time event - QS_QF_TIMEEVT_POST, //!< a time event posted itself directly to an AO - - // [38] Additional Framework (QF) records - QS_QF_DELETE_REF, //!< an event reference is about to be deleted - QS_QF_CRIT_ENTRY, //!< critical section was entered - QS_QF_CRIT_EXIT, //!< critical section was exited - QS_QF_ISR_ENTRY, //!< an ISR was entered - QS_QF_ISR_EXIT, //!< an ISR was exited - QS_QF_INT_DISABLE, //!< interrupts were disabled - QS_QF_INT_ENABLE, //!< interrupts were enabled - - // [45] Additional Active Object (AO) records - QS_QF_ACTIVE_POST_ATTEMPT,//!< attempt to post an evt to AO failed - - // [46] Additional Event Queue (EQ) records - QS_QF_EQUEUE_POST_ATTEMPT,//!< attempt to post evt to QEQueue failed - - // [47] Additional Memory Pool (MP) records - QS_QF_MPOOL_GET_ATTEMPT, //!< attempt to get a memory block failed - - // [48] Scheduler (SC) records - QS_SCHED_PREEMPT, //!< scheduler asynchronously preempted a task - QS_SCHED_RESTORE, //!< scheduler restored preempted task - QS_SCHED_LOCK, //!< scheduler was locked - QS_SCHED_UNLOCK, //!< scheduler was unlocked - QS_SCHED_NEXT, //!< scheduler started next task - QS_SCHED_IDLE, //!< scheduler restored the idle task - - // [54] Miscellaneous QS records (not maskable) - QS_ENUM_DICT, //!< enumeration dictionary entry - - // [55] Additional QEP records - QS_QEP_TRAN_HIST, //!< a tran. to history was taken - QS_QEP_TRAN_EP, //!< a tran. to entry point into a submachine - QS_QEP_TRAN_XP, //!< a tran. to exit point out of a submachine - - // [58] Miscellaneous QS records (not maskable) - QS_TEST_PAUSED, //!< test has been paused - QS_TEST_PROBE_GET, //!< reports that Test-Probe has been used - QS_SIG_DICT, //!< signal dictionary entry - QS_OBJ_DICT, //!< object dictionary entry - QS_FUN_DICT, //!< function dictionary entry - QS_USR_DICT, //!< user QS record dictionary entry - QS_TARGET_INFO, //!< reports the Target information - QS_TARGET_DONE, //!< reports completion of a user callback - QS_RX_STATUS, //!< reports QS data receive status - QS_QUERY_DATA, //!< reports the data from "current object" query - QS_PEEK_DATA, //!< reports the data from the PEEK query - QS_ASSERT_FAIL, //!< assertion failed in the code - QS_QF_RUN, //!< QF_run() was entered - - // [71] Semaphore (SEM) records - QS_SEM_TAKE, //!< a semaphore was taken by a thread - QS_SEM_BLOCK, //!< a semaphore blocked a thread - QS_SEM_SIGNAL, //!< a semaphore was signaled - QS_SEM_BLOCK_ATTEMPT, //!< a semaphore blocked was attempted - - // [75] Mutex (MTX) records - QS_MTX_LOCK, //!< a mutex was locked - QS_MTX_BLOCK, //!< a mutex blocked a thread - QS_MTX_UNLOCK, //!< a mutex was unlocked - QS_MTX_LOCK_ATTEMPT, //!< a mutex lock was attempted - QS_MTX_BLOCK_ATTEMPT, //!< a mutex blocking was attempted - QS_MTX_UNLOCK_ATTEMPT,//!< a mutex unlock was attempted - - // [81] - QS_PRE_MAX //!< the # predefined signals -}; - - - - //! QS-TX record groups for QS_GLB_FILTER() - : std::int16_t { - QS_ALL_RECORDS = 0xF0,//!< all maskable QS records - QS_SM_RECORDS, //!< State Machine QS records - QS_AO_RECORDS, //!< Active Object QS records - QS_EQ_RECORDS, //!< Event Queues QS records - QS_MP_RECORDS, //!< Memory Pools QS records - QS_TE_RECORDS, //!< Time Events QS records - QS_QF_RECORDS, //!< QF QS records - QS_SC_RECORDS, //!< Scheduler QS records - QS_SEM_RECORDS, //!< Semaphore QS records - QS_MTX_RECORDS, //!< Mutex QS records - QS_U0_RECORDS, //!< User Group 100-104 records - QS_U1_RECORDS, //!< User Group 105-109 records - QS_U2_RECORDS, //!< User Group 110-114 records - QS_U3_RECORDS, //!< User Group 115-119 records - QS_U4_RECORDS, //!< User Group 120-124 records - QS_UA_RECORDS //!< All User records -}; - - - - //! QS user record group offsets for QS_GLB_FILTER() - : std::int16_t { - QS_USER = 100, //!< the first record available to QS users - QS_USER0 = QS_USER, //!< offset for User Group 0 - QS_USER1 = QS_USER0 + 5, //!< offset for User Group 1 - QS_USER2 = QS_USER1 + 5, //!< offset for User Group 2 - QS_USER3 = QS_USER2 + 5, //!< offset for User Group 3 - QS_USER4 = QS_USER3 + 5 //!< offset for User Group 4 -}; - - - - //! QS ID offsets for QS_LOC_FILTER() - : std::int16_t { - QS_AO_ID = 0, //!< offset for AO priorities - QS_EP_ID = 64, //!< offset for event-pool IDs - QS_EQ_ID = 80, //!< offset for event-queue IDs - QS_AP_ID = 96 //!< offset for Application-specific IDs -}; - - - - //! QS ID groups for QS_LOC_FILTER() - : std::int16_t { - QS_ALL_IDS = 0xF0, //!< all QS IDs - QS_AO_IDS = 0x80 + QS_AO_ID, //!< AO IDs (priorities) - QS_EP_IDS = 0x80 + QS_EP_ID, //!< event-pool IDs - QS_EQ_IDS = 0x80 + QS_EQ_ID, //!< event-queue IDs - QS_AP_IDS = 0x80 + QS_AP_ID //!< Application-specific IDs -}; - - - - { - std::uint8_t m_prio; //!< prio. (qsId) for the QS "local filter" - - // get the prio. (qsId) from the QSpyId object - std::uint_fast8_t getPrio() const noexcept { - return static_cast<std::uint_fast8_t>(m_prio); - } -}; - - - - = std::uint16_t; - - - - = std::uint32_t; - - - - = std::uint64_t; - - - - = std::uint16_t; - - - - = std::uint32_t; - - - - = std::uint64_t; - - - - = void (*)(); - - - - = std::uint16_t; - - - - = std::uint32_t; - - - - = std::uint16_t; - - - - = std::uint32_t; - - - - - - - - - - - - - - - - - - - //! Enumerates data elements for app-specific trace records - : std::uint8_t { - I8_ENUM_T, //!< signed 8-bit integer or enum format - U8_T, //!< unsigned 8-bit integer format - I16_T, //!< signed 16-bit integer format - U16_T, //!< unsigned 16-bit integer format - I32_T, //!< signed 32-bit integer format - U32_T, //!< unsigned 32-bit integer format - F32_T, //!< 32-bit floating point format - F64_T, //!< 64-bit floating point format - STR_T, //!< zero-terminated ASCII string format - MEM_T, //!< up to 255-bytes memory block format - SIG_T, //!< event signal format - OBJ_T, //!< object pointer format - FUN_T, //!< function pointer format - I64_T, //!< signed 64-bit integer format - U64_T //!< unsigned 64-bit integer format -}; - - - - - - union TCast { - T_IN in; - T_OUT out; -} u = { in }; -return u.out; - - - - noexcept - - - - - priv_.buf = sto; -priv_.end = static_cast<QSCtr>(stoSize); -priv_.head = 0U; -priv_.tail = 0U; -priv_.used = 0U; -priv_.seq = 0U; -priv_.chksum = 0U; -priv_.critNest = 0U; - -glbFilter_(-static_cast<enum_t>(QS_ALL_RECORDS));// all global filters OFF -locFilter_(static_cast<enum_t>(QS_ALL_IDS)); // all local filters ON -priv_.locFilter_AP = nullptr; // deprecated "AP-filter" - -// produce an empty record to "flush" the QS trace buffer -beginRec_(QS_REC_NUM_(QS_EMPTY)); -endRec_(); - -// produce the reset record to inform QSPY of a new session -target_info_pre_(0xFFU); - -// hold off flushing after successful initialization (see QS_INIT()) - - - - noexcept - // NOTE: Must be called IN critical section. -// Also requires system-level memory access (QF_MEM_SYS()). - -std::uint16_t ret; -if (priv_.used == 0U) { - ret = QS_EOD; // set End-Of-Data -} -else { - std::uint8_t const * const buf = priv_.buf; // put in a temporary - QSCtr tail = priv_.tail; // put in a temporary (register) - ret = static_cast<std::uint16_t>(buf[tail]); // set the byte to return - ++tail; // advance the tail - if (tail == priv_.end) { // tail wrap around? - tail = 0U; - } - priv_.tail = tail; // update the tail - priv_.used = (priv_.used - 1U); // one less byte used -} -return ret; // return the byte or EOD - - - - noexcept - - - // NOTE: Must be called IN critical section. -// Also requires system-level memory access (QF_MEM_SYS()). - -QSCtr const used = priv_.used; // put in a temporary (register) -std::uint8_t *buf; - -// any bytes used in the ring buffer? -if (used != 0U) { - QSCtr tail = priv_.tail; // put in a temporary (register) - QSCtr const end = priv_.end; // put in a temporary (register) - QSCtr n = static_cast<QSCtr>(end - tail); - if (n > used) { - n = used; - } - if (n > static_cast<QSCtr>(*pNbytes)) { - n = static_cast<QSCtr>(*pNbytes); - } - *pNbytes = static_cast<std::uint16_t>(n); // n-bytes available - buf = priv_.buf; - buf = &buf[tail]; // the bytes are at the tail - - priv_.used = static_cast<QSCtr>(used - n); - tail += n; - if (tail == end) { - tail = 0U; - } - priv_.tail = tail; -} -else { // no bytes available - *pNbytes = 0U; // no bytes available right now - buf = nullptr; // no bytes available right now -} -return buf; - - - - - - - - - - - - - - - - - - - - //! Kinds of objects used QS-RX - : std::uint8_t { - SM_OBJ, //!< state machine object - AO_OBJ, //!< active object - MP_OBJ, //!< event pool object - EQ_OBJ, //!< raw queue object - TE_OBJ, //!< time event object - AP_OBJ, //!< generic Application-specific object - MAX_OBJ -}; - - - - //! Object combinations for QS-RX - : std::uint8_t { - SM_AO_OBJ = MAX_OBJ //!< combination of SM and AO -}; - - - - noexcept - - - - - rxPriv_.buf = &sto[0]; -rxPriv_.end = static_cast<QSCtr>(stoSize); -rxPriv_.head = 0U; -rxPriv_.tail = 0U; - -rxPriv_.currObj[QS::SM_OBJ] = nullptr; -rxPriv_.currObj[QS::AO_OBJ] = nullptr; -rxPriv_.currObj[QS::MP_OBJ] = nullptr; -rxPriv_.currObj[QS::EQ_OBJ] = nullptr; -rxPriv_.currObj[QS::TE_OBJ] = nullptr; -rxPriv_.currObj[QS::AP_OBJ] = nullptr; - -tran_(WAIT4_SEQ); -QP::QS::rxPriv_.esc = 0U; -QP::QS::rxPriv_.seq = 0U; -QP::QS::rxPriv_.chksum = 0U; - -beginRec_(static_cast<std::uint_fast8_t>(QS_OBJ_DICT)); - QS_OBJ_PRE_(&rxPriv_); - QS_STR_PRE_("QS_RX"); -endRec_(); -// no QS_REC_DONE(), because QS is not running yet - -#ifdef Q_UTEST -tstPriv_.tpNum = 0U; -tstPriv_.testTime = 0U; -#endif // Q_UTEST - - - - noexcept - - - // NOTE: does not need critical section -// But requires system-level memory access (QF_MEM_SYS()). - -QSCtr head = rxPriv_.head + 1U; -if (head == rxPriv_.end) { - head = 0U; -} -if (head != rxPriv_.tail) { // buffer NOT full? - rxPriv_.buf[rxPriv_.head] = b; - rxPriv_.head = head; - return true; // byte placed in the buffer -} -else { - return false; // byte NOT placed in the buffer -} - - - - QSCtr tail = rxPriv_.tail; -while (rxPriv_.head != tail) { // QS-RX buffer NOT empty? - std::uint8_t b = rxPriv_.buf[tail]; - - ++tail; - if (tail == rxPriv_.end) { - tail = 0U; - } - rxPriv_.tail = tail; // update the tail to a *valid* index - - if (QP::QS::rxPriv_.esc != 0U) { // escaped byte arrived? - QP::QS::rxPriv_.esc = 0U; - b ^= QS_ESC_XOR; - - QP::QS::rxPriv_.chksum += b; - rxParseData_(b); - } - else if (b == QS_ESC) { - QP::QS::rxPriv_.esc = 1U; - } - else if (b == QS_FRAME) { - // get ready for the next frame - b = QP::QS::rxPriv_.state; // save the current state in b - QP::QS::rxPriv_.esc = 0U; - tran_(WAIT4_SEQ); - - if (QP::QS::rxPriv_.chksum == QS_GOOD_CHKSUM) { - QP::QS::rxPriv_.chksum = 0U; - rxHandleGoodFrame_(b); - } - else { // bad checksum - QP::QS::rxPriv_.chksum = 0U; - rxReportError_(0x41U); - rxHandleBadFrame_(b); - } - } - else { - QP::QS::rxPriv_.chksum += b; - rxParseData_(b); - } -} - - - - - - - - QS_CRIT_STAT -QS_CRIT_ENTRY(); -Q_REQUIRE_INCRIT(300, obj_kind < Q_DIM(rxPriv_.currObj)); - -QS_MEM_SYS(); - -rxPriv_.currObj[obj_kind] = obj_ptr; - -QS_MEM_APP(); -QS_CRIT_EXIT(); - - - - noexcept - // NOTE: Must be called IN critical section. -// Also requires system-level memory access (QF_MEM_SYS()). - -QSCtr const head = rxPriv_.head; -std::uint16_t nFree; -if (head == rxPriv_.tail) { // buffer empty? - nFree = static_cast<std::uint16_t>(rxPriv_.end - 1U); -} -else if (head < rxPriv_.tail) { - nFree = static_cast<std::uint16_t>(rxPriv_.tail - head - 1U); -} -else { - nFree = static_cast<std::uint16_t>(rxPriv_.end + rxPriv_.tail - - head - 1U); -} -return nFree; - - - - - - - - - - - - - - - - - - - - - - { - QSFun addr; - std::uint32_t data; - std::uint8_t idx; -}; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Clear the internal QF variables, so that the framework can start -// correctly even if the startup code fails to clear the uninitialized -// data (as is required by the C++ Standard). -bzero_(&QF::priv_, sizeof(QF::priv_)); -bzero_(&QS::tstPriv_, sizeof(QS::tstPriv_)); -bzero_(&QActive::registry_[0], sizeof(QActive::registry_)); - -#ifndef Q_UNSAFE -QS::tstPriv_.readySet.update_(&QS::tstPriv_.readySet_dis); -#endif - - - - QS::onReset(); - - - - // function dictionaries for the standard API -QS_FUN_DICTIONARY(&QActive::post_); -QS_FUN_DICTIONARY(&QActive::postLIFO); -QS_FUN_DICTIONARY(&QS::processTestEvts_); - -QS_CRIT_STAT -QS_CRIT_ENTRY(); -QS_MEM_SYS(); - -// produce the QS_QF_RUN trace record -QS_BEGIN_PRE_(QS_QF_RUN, 0U) -QS_END_PRE_() - -QS_MEM_APP(); -QS_CRIT_EXIT(); - -QS::processTestEvts_(); // process all events posted so far -QS::onTestLoop(); // run the unit test -QS::onCleanup(); // application cleanup -return 0; // return no error - - - - - - - - - - - - - - - - - - - Q_UNUSED_PAR(stkSto); -Q_UNUSED_PAR(stkSize); - -m_prio = static_cast<std::uint8_t>(prioSpec & 0xFFU); // QF-priol -m_pthre = static_cast<std::uint8_t>(prioSpec >> 8U); // preemption-thre. -register_(); // make QF aware of this AO - -m_eQueue.init(qSto, qLen); // initialize QEQueue of this AO - -this->init(par, m_prio); // take the top-most initial tran. (virtual) - - - - unsubscribeAll(); // unsubscribe from all events -unregister_(); // remove this object from QF - - - - - - - - - - - QS_CRIT_STAT -QS_CRIT_ENTRY(); -QS_MEM_SYS(); - -QTimeEvt *prev = &QTimeEvt::timeEvtHead_[tickRate]; - -QS_BEGIN_PRE_(QS_QF_TICK, 0U) - prev->m_ctr = (prev->m_ctr + 1U); - QS_TEC_PRE_(prev->m_ctr); // tick ctr - QS_U8_PRE_(tickRate); // tick rate -QS_END_PRE_() - -// is current Time Event object provided? -QTimeEvt *t = static_cast<QTimeEvt *>(QS::rxPriv_.currObj[QS::TE_OBJ]); -if (t != nullptr) { - - // the time event must be armed - Q_ASSERT_INCRIT(810, t->m_ctr != 0U); - - QActive * const act = static_cast<QActive *>(t->m_act); - - // the recipient AO must be provided - Q_ASSERT_INCRIT(820, act != nullptr); - - // periodic time evt? - if (t->m_interval != 0U) { - t->m_ctr = t->m_interval; // rearm the time event - } - else { // one-shot time event: automatically disarm - t->m_ctr = 0U; // auto-disarm - // mark time event 't' as NOT linked - t->refCtr_ = static_cast<std::uint8_t>(t->refCtr_ - & static_cast<std::uint8_t>(~TE_IS_LINKED)); - - QS_BEGIN_PRE_(QS_QF_TIMEEVT_AUTO_DISARM, act->m_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->m_prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(t); // the time event object - QS_SIG_PRE_(t->sig); // signal of this time event - QS_OBJ_PRE_(act); // the target AO - QS_U8_PRE_(tickRate); // tick rate - QS_END_PRE_() - QS_MEM_APP(); - QS_CRIT_EXIT(); // exit critical section before posting - - // asserts if queue overflows - static_cast<void>(act->POST(t, sender)); - - QS_CRIT_ENTRY(); - QS_MEM_SYS(); -} - -// update the linked list of time events -for (;;) { - t = prev->m_next; // advance down the time evt. list - - // end of the list? - if (t == nullptr) { - - // any new time events armed since the last run of tick()? - if (QTimeEvt::timeEvtHead_[tickRate].m_act != nullptr) { - - // sanity check - Q_ASSERT_INCRIT(830, prev != nullptr); - prev->m_next = QTimeEvt::timeEvtHead_[tickRate].toTimeEvt(); - QTimeEvt::timeEvtHead_[tickRate].m_act = nullptr; - t = prev->m_next; // switch to the new list - } - else { - break; // all currently armed time evts. processed - } - } - - // time event scheduled for removal? - if (t->m_ctr == 0U) { - prev->m_next = t->m_next; - // mark time event 't' as NOT linked - t->refCtr_ = static_cast<std::uint8_t>(t->refCtr_ - & static_cast<std::uint8_t>(~TE_IS_LINKED)); - // do NOT advance the prev pointer - QS_MEM_APP(); - QS_CRIT_EXIT(); // exit crit. section to reduce latency - } - else { - prev = t; // advance to this time event - QS_MEM_APP(); - QS_CRIT_EXIT(); // exit crit. section to reduce latency - } - QS_CRIT_ENTRY(); // re-enter crit. section to continue - QS_MEM_SYS(); -} - -QS_MEM_APP(); -QS_CRIT_EXIT(); - - - - - - - : QAsm() - - - - override - - - - - Q_UNUSED_PAR(e); - -#ifdef Q_SPY -if ((QS::priv_.flags & 0x01U) == 0U) { - QS::priv_.flags |= 0x01U; - QS_FUN_DICTIONARY(&QP::QHsm::top); -} -#else -Q_UNUSED_PAR(qsId); -#endif - -QS_CRIT_STAT -QS_CRIT_ENTRY(); -QS_MEM_SYS(); -QS_BEGIN_PRE_(QS_QEP_STATE_INIT, qsId) - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(m_state.fun); // the source state - QS_FUN_PRE_(m_temp.fun); // the target of the initial tran. -QS_END_PRE_() -QS_MEM_APP(); -QS_CRIT_EXIT(); - - - - override - - - - - QS_CRIT_STAT -QS_CRIT_ENTRY(); -QS_MEM_SYS(); -QS_BEGIN_PRE_(QS_QEP_DISPATCH, qsId) - QS_TIME_PRE_(); // time stamp - QS_SIG_PRE_(e->sig); // the signal of the event - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(m_state.fun); // the current state -QS_END_PRE_() -QS_MEM_APP(); -QS_CRIT_EXIT(); - - - - - - - - - : QActive(nullptr) - - - - override - - - - - Q_UNUSED_PAR(e); -Q_UNUSED_PAR(qsId); - -#ifdef Q_SPY -if ((QS::priv_.flags & 0x01U) == 0U) { - QS::priv_.flags |= 0x01U; - QS_FUN_DICTIONARY(&QP::QHsm::top); -} -#endif - -QS_CRIT_STAT -QS_CRIT_ENTRY(); -QS_MEM_SYS(); -QS_BEGIN_PRE_(QS_QEP_STATE_INIT, m_prio) - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(m_state.fun); // the source state - QS_FUN_PRE_(m_temp.fun); // the target of the initial tran. -QS_END_PRE_() -QS_MEM_APP(); -QS_CRIT_EXIT(); - - - - override - - - - - QS_CRIT_STAT -QS_CRIT_ENTRY(); -QS_MEM_SYS(); -QS_BEGIN_PRE_(QS_QEP_DISPATCH, qsId) - QS_TIME_PRE_(); // time stamp - QS_SIG_PRE_(e->sig); // the signal of the event - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(m_state.fun); // the current state -QS_END_PRE_() -QS_MEM_APP(); -QS_CRIT_EXIT(); - - - - noexcept - - - - - - - QS_TEST_PROBE_DEF(&QActive::post_) - -QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); - -// test-probe#1 for faking queue overflow -bool status = true; -QS_TEST_PROBE_ID(1, - status = false; - if (margin == QF::NO_MARGIN) { - // fake assertion Mod=qf_actq,Loc=110 - Q_onError("qf_actq", 110); - } -) - -// is it a mutable event? -if (e->getPoolNum_() != 0U) { - QEvt_refCtr_inc_(e); -} - -std::uint_fast8_t const rec = - (status ? static_cast<std::uint8_t>(QS_QF_ACTIVE_POST) - : static_cast<std::uint8_t>(QS_QF_ACTIVE_POST_ATTEMPT)); -QS_BEGIN_PRE_(rec, m_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_(this); // this active object - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_EQC_PRE_(0U); // # free entries - QS_EQC_PRE_(margin); // margin requested -QS_END_PRE_() - -QF_MEM_APP(); -QF_CRIT_EXIT(); - -// callback to examine the posted event under the same conditions -// as producing the #QS_QF_ACTIVE_POST trace record, which are: -// the local filter for this AO ('m_prio') is set -if (QS_LOC_CHECK_(m_prio)) { - QS::onTestPost(sender, this, e, status); -} - -// recycle the event immediately, because it was not really posted -#if (QF_MAX_EPOOL > 0U) -QF::gc(e); -#endif - -return status; - - - - noexcept - - - QS_TEST_PROBE_DEF(&QActive::postLIFO) - -QF_CRIT_STAT -QF_CRIT_ENTRY(); -QF_MEM_SYS(); - -// test-probe#1 for faking queue overflow -QS_TEST_PROBE_ID(1, - // fake assertion Mod=qf_actq,Loc=210 - Q_onError("qf_actq", 210); -) - -// is it a mutable event? -if (e->getPoolNum_() != 0U) { - QEvt_refCtr_inc_(e); -} - -QS_BEGIN_PRE_(QS_QF_ACTIVE_POST_LIFO, m_prio) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of this event - QS_OBJ_PRE_(this); // this active object - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_EQC_PRE_(0U); // # free entries - QS_EQC_PRE_(0U); // min # free entries -QS_END_PRE_() - -QF_MEM_APP(); -QF_CRIT_EXIT(); - -// callback to examine the posted event under the same conditions -// as producing the #QS_QF_ACTIVE_POST trace record, which are: -// the local filter for this AO ('m_prio') is set -if (QS_LOC_CHECK_(m_prio)) { - QS::onTestPost(nullptr, this, e, true); -} -// recycle the event immediately, because it was not really posted -#if (QF_MAX_EPOOL > 0U) -QF::gc(e); -#endif - - - - - - - - - - - (QP::QS::onStartup(arg_)) - - - - (QP::QS::onCleanup()) - - - - (QP::QS::doOutput()) - - - - (QP::QS::doInput()) - - - - - - \ - (QP::QS::glbFilter_(static_cast<std::int_fast16_t>(rec_))) - - - - - - \ - (QP::QS::locFilter_(static_cast<std::int_fast16_t>(qsId_))) - - - - - - - - \ -if (QS_GLB_CHECK_(rec_) && QS_LOC_CHECK_(qsId_)) { \ - QS_CRIT_STAT \ - QS_CRIT_ENTRY(); \ - QS_MEM_SYS(); \ - QP::QS::beginRec_(static_cast<std::uint_fast8_t>(rec_)); \ - QS_TIME_PRE_(); { - - - - } \ - QP::QS::endRec_(); \ - QS_MEM_APP(); \ - QS_CRIT_EXIT(); \ -} - - - - (QP::QS::onFlush()) - - - - - - - - \ -if (QS_GLB_CHECK_(rec_) && QS_LOC_CHECK_(qsId_)) { \ - QP::QS::beginRec_(rec_); \ - QS_TIME_PRE_(); { - - - - } \ - QP::QS::endRec_(); \ -} - - - - - - \ -((static_cast<std::uint_fast8_t>(QP::QS::filt_.glb[ \ - static_cast<std::uint_fast8_t>(rec_) >> 3U]) \ - & (static_cast<std::uint_fast8_t>(1U) \ - << (static_cast<std::uint_fast8_t>(rec_) & 7U))) != 0U) - - - - - - \ -((static_cast<std::uint_fast8_t>(QP::QS::filt_.loc \ - [static_cast<std::uint_fast8_t>(qsId_) >> 3U]) \ - & (static_cast<std::uint_fast8_t>(1U) \ - << (static_cast<std::uint_fast8_t>(qsId_) & 7U))) != 0U) - - - - (static_cast<void>(0)) - - - - - - - - \ -(QP::QS::u8_fmt_(static_cast<std::uint8_t>( \ - (static_cast<std::uint8_t>(((width_) << 4U) & 0x7U)) \ - | static_cast<std::uint8_t>(QP::QS::I8_ENUM_T)), (data_))) - - - - - - - - \ -(QP::QS::u8_fmt_(static_cast<std::uint8_t>( \ - (static_cast<std::uint8_t>((width_) << 4U)) \ - | static_cast<std::uint8_t>(QP::QS::U8_T)), (data_))) - - - - - - - - \ -(QP::QS::u16_fmt_(static_cast<std::uint8_t>( \ - (static_cast<std::uint8_t>((width_) << 4U)) \ - | static_cast<std::uint8_t>(QP::QS::I16_T)), (data_))) - - - - - - - - \ -(QP::QS::u16_fmt_(static_cast<std::uint8_t>((((width_) << 4U)) \ - | static_cast<std::uint8_t>(QP::QS::U16_T)), (data_))) - - - - - - - - \ -(QP::QS::u32_fmt_( \ - static_cast<std::uint8_t>((static_cast<std::uint8_t>((width_) << 4U)) \ - | static_cast<std::uint8_t>(QP::QS::I32_T)), (data_))) - - - - - - - - \ -(QP::QS::u32_fmt_(static_cast<std::uint8_t>( \ - (static_cast<std::uint8_t>((width_) << 4U)) \ - | static_cast<std::uint8_t>(QP::QS::U32_T)), (data_))) - - - - - - - - \ -(QP::QS::u64_fmt_(static_cast<std::uint8_t>( \ - (static_cast<std::uint8_t>((width_) << 4U)) \ - | static_cast<std::uint8_t>(QP::QS::I64_T)), (data_))) - - - - - - - - \ -(QP::QS::u64_fmt_(static_cast<std::uint8_t>( \ - (static_cast<std::uint8_t>((width_) << 4U)) \ - | static_cast<std::uint8_t>(QP::QS::U64_T)), (data_))) - - - - - - - - \ -(QP::QS::f32_fmt_(static_cast<std::uint8_t>( \ - (static_cast<std::uint8_t>((width_) << 4U)) \ - | static_cast<std::uint8_t>(QP::QS::F32_T)), (data_))) - - - - - - - - \ -(QP::QS::f64_fmt_(static_cast<std::uint8_t>( \ - (static_cast<std::uint8_t>((width_) << 4U)) \ - | static_cast<std::uint8_t>(QP::QS::F64_T)), (data_))) - - - - - - (QP::QS::str_fmt_(str_)) - - - - - - - - (QP::QS::mem_fmt_((mem_), (size_))) - - - - - - - - \ - (QP::QS::u8_fmt_(static_cast<std::uint8_t>(0x80U | ((group_) << 4U)) \ - | static_cast<std::uint8_t>(QP::QS::I8_ENUM_T),\ - static_cast<std::uint8_t>(value_))) - - - - (QP::QS::u16_raw_(QP::QS::onGetTime())) - - - - (QP::QS::u32_raw_(QP::QS::onGetTime())) - - - - - - (QP::QS::u16_fmt_(QP::QS::OBJ_T, \ - reinterpret_cast<std::uint16_t>(obj_))) - - - - - - (QP::QS::u32_fmt_(QP::QS::OBJ_T, \ - reinterpret_cast<std::uint32_t>(obj_))) - - - - - - (QP::QS::u64_fmt_(QP::QS::OBJ_T, \ - reinterpret_cast<std::uint64_t>(obj_))) - - - - - - (QP::QS::u16_fmt_(QP::QS::FUN_T, \ - reinterpret_cast<std::uint16_t>(fun_))) - - - - - - (QP::QS::u32_fmt_(QP::QS::FUN_T, \ - reinterpret_cast<std::uint32_t>(fun_))) - - - - - - (QP::QS::u64_fmt_(QP::QS::FUN_T, \ - reinterpret_cast<std::uint64_t>(fun_))) - - - - - - - - \ - QP::QS::u8_fmt_(QP::QS::SIG_T, static_cast<std::uint8_t>(sig_)); \ - QP::QS::obj_raw_(obj_) - - - - - - - - \ - QP::QS::u16_fmt_(QP::QS::SIG_T, static_cast<std::uint16_t>(sig_)); \ - QP::QS::obj_raw_(obj_) - - - - - - - - \ - QP::QS::u32_fmt_(QP::QS::SIG_T, static_cast<std::uint32_t>(sig_)); \ - QP::QS::obj_raw_(obj_) - - - - - - - - \ - (QP::QS::sig_dict_pre_((sig_), (obj_), #sig_)) - - - - - - \ - (QP::QS::obj_dict_pre_((obj_), #obj_)) - - - - - - - - \ - (QP::QS::obj_arr_dict_pre_((obj_), (idx_), #obj_)) - - - - - - \ - (QP::QS::fun_dict_pre_( \ - QP::QS::force_cast<void (*)()>(fun_), #fun_)) - - - - - - \ - (QP::QS::usr_dict_pre_((rec_), #rec_)) - - - - - - - - \ - (QP::QS::enum_dict_pre_((value_), (group_), #value_)) - - - - (QP::QS::crit_entry_pre_()) - - - - (QP::QS::crit_exit_pre_()) - - - - - - - - \ - (QP::QS::isr_entry_pre_((isrnest_), (prio_))) - - - - - - - - \ - (QP::QS::isr_exit_pre_((isrnest_), (prio_))) - - - - - - (code_) - - - - - - - - - - \ - (QP::QS::assertion_pre_((module_), (id_), (delay_))) - - - - (static_cast<std::uint16_t>(0xFFFFU)) - - - - (static_cast<std::uint8_t>(7U)) - - - - (static_cast<std::uint8_t>(0x0FU)) - - - - QF_CRIT_STAT - - - - QF_CRIT_ENTRY() - - - - QF_CRIT_EXIT() - - - - QF_MEM_SYS() - - - - QF_MEM_APP() - - - - - - - #ifndef QP_HPP_ -#define QP_HPP_ - -//============================================================================ -#define QP_VERSION_STR "7.4.0-rc.3" -#define QP_VERSION 740U -#define QP_RELEASE 0x7092C3BBU - -//============================================================================ -//! @cond INTERNAL - -#ifndef Q_SIGNAL_SIZE -#define Q_SIGNAL_SIZE 2U -#endif // ndef Q_SIGNAL_SIZE - -#ifndef QF_MAX_ACTIVE -#define QF_MAX_ACTIVE 32U -#endif - -#if (QF_MAX_ACTIVE > 64U) -#error QF_MAX_ACTIVE exceeds the maximum of 64U; -#endif - -#ifndef QF_MAX_TICK_RATE -#define QF_MAX_TICK_RATE 1U -#endif - -#if (QF_MAX_TICK_RATE > 15U) -#error QF_MAX_TICK_RATE exceeds the maximum of 15U; -#endif - -#ifndef QF_MAX_EPOOL -#define QF_MAX_EPOOL 3U -#endif - -#if (QF_MAX_EPOOL > 15U) -#error QF_MAX_EPOOL exceeds the maximum of 15U; -#endif - -#ifndef QF_TIMEEVT_CTR_SIZE -#define QF_TIMEEVT_CTR_SIZE 4U -#endif - -#if (QF_TIMEEVT_CTR_SIZE > 4U) -#error QF_TIMEEVT_CTR_SIZE defined incorrectly, expected 1U, 2U, or 4U; -#endif - -#ifndef QF_EVENT_SIZ_SIZE -#define QF_EVENT_SIZ_SIZE 2U -#endif - -#if (QF_EVENT_SIZ_SIZE > 4U) -#error QF_EVENT_SIZ_SIZE defined incorrectly, expected 1U, 2U, or 4U; -#endif - -//! @endcond -//============================================================================ -$declare ${glob-types} - -$declare ${QEP} - -$declare ${QEP-macros} - -$declare ${QF::types} - -$declare ${QF::QActive} - -$declare ${QF::QMActive} - -$declare ${QF::QTimeEvt} - -$declare ${QF::QTicker} - -$declare ${QF::QF-base} - -$declare ${QF::QF-dyn} - -extern "C" { -$declare ${QF-extern-C} -} // extern "C" - -$declare ${QF-macros} - -#endif // QP_HPP_ - - - - #ifndef QP_PKG_HPP_ -#define QP_PKG_HPP_ - -$declare ${QF::QF-pkg} - -#define QF_CONST_CAST_(type_, ptr_) const_cast<type_>(ptr_) -#define QF_PTR_RANGE_(x_, min_, max_) (((min_) <= (x_)) && ((x_) <= (max_))) -#define Q_UINTPTR_CAST_(ptr_) (reinterpret_cast<std::uintptr_t>(ptr_)) -#define Q_ACTION_CAST(act_) (reinterpret_cast<QP::QActionHandler>(act_)) - -namespace QP { - -// Bitmasks are for the QTimeEvt::refCtr_ attribute (inherited from QEvt). -// In QTimeEvt this attribute is NOT used for reference counting. -constexpr std::uint8_t TE_IS_LINKED = 1U << 7U; // flag -constexpr std::uint8_t TE_WAS_DISARMED = 1U << 6U; // flag -constexpr std::uint8_t TE_TICK_RATE = 0x0FU; // bitmask - -inline void QEvt_refCtr_inc_(QEvt const * const e) noexcept { - (QF_CONST_CAST_(QEvt*, e))->refCtr_ = e->refCtr_ + 1U; -} - -inline void QEvt_refCtr_dec_(QEvt const * const e) noexcept { - (QF_CONST_CAST_(QEvt*, e))->refCtr_ = e->refCtr_ - 1U; -} - -} // namespace QP - -#endif // QP_PKG_HPP_ - - - - #ifndef QEQUEUE_HPP_ -#define QEQUEUE_HPP_ - -#ifndef QF_EQUEUE_CTR_SIZE - #define QF_EQUEUE_CTR_SIZE 1U -#endif - -namespace QP { - -#if (QF_EQUEUE_CTR_SIZE == 1U) - using QEQueueCtr = std::uint8_t; -#elif (QF_EQUEUE_CTR_SIZE == 2U) - using QEQueueCtr = std::uint16_t; -#elif (QF_EQUEUE_CTR_SIZE == 4U) - using QEQueueCtr = std::uint32_t; -#else - #error "QF_EQUEUE_CTR_SIZE defined incorrectly, expected 1U, 2U, or 4U" -#endif - -class QEvt; // forward declaration - -} // namespace QP - -$declare ${QF::QEQueue} - -#endif // QEQUEUE_HPP_ - - - - #ifndef QMPOOL_HPP_ -#define QMPOOL_HPP_ - -#ifndef QF_MPOOL_SIZ_SIZE - #define QF_MPOOL_SIZ_SIZE 2U -#endif -#ifndef QF_MPOOL_CTR_SIZE - #define QF_MPOOL_CTR_SIZE 2U -#endif - -namespace QP { - -#if (QF_MPOOL_SIZ_SIZE == 1U) - using QMPoolSize = std::uint8_t; -#elif (QF_MPOOL_SIZ_SIZE == 2U) - using QMPoolSize = std::uint16_t; -#elif (QF_MPOOL_SIZ_SIZE == 4U) - using QMPoolSize = std::uint32_t; -#else - #error "QF_MPOOL_SIZ_SIZE defined incorrectly, expected 1U, 2U, or 4U" -#endif - -#if (QF_MPOOL_CTR_SIZE == 1U) - using QMPoolCtr = std::uint8_t; -#elif (QF_MPOOL_CTR_SIZE == 2U) - using QMPoolCtr = std::uint16_t; -#elif (QF_MPOOL_CTR_SIZE == 4U) - using QMPoolCtr = std::uint32_t; -#else - #error "QF_MPOOL_CTR_SIZE defined incorrectly, expected 1U, 2U, or 4U" -#endif - -} // namespace QP - -#define QF_MPOOL_EL(evType_) struct { \ - QP::QFreeBlock sto_[((sizeof(evType_) - 1U) \ - / sizeof(QP::QFreeBlock)) + 1U]; } -$declare ${QF::QFreeBlock} - -$declare ${QF::QMPool} - -#endif // QMPOOL_HPP_ - - - - #ifndef QV_HPP_ -#define QV_HPP_ - -$declare ${QV::QV-base} - -//============================================================================ -// interface used only for internal implementation, but not in applications -#ifdef QP_IMPL - -$declare ${QV-impl} - -$declare ${QF_EPOOL-impl} - -#endif // QP_IMPL - -#endif // QV_HPP_ - - - - #ifndef QK_HPP_ -#define QK_HPP_ - -$declare ${QK::QSchedStatus} - -$declare ${QK::QK-base} - -extern "C" { -$declare ${QK-extern-C} -} // extern "C" - -//============================================================================ -// interface used only for internal implementation, but not in applications -#ifdef QP_IMPL - -$declare ${QK-impl} - -$declare ${QF_EPOOL-impl} - -#endif // QP_IMPL - -#endif // QK_HPP_ - - - - #ifndef QXK_HPP_ -#define QXK_HPP_ - -$declare ${QXK::QSchedStatus} - -$declare ${QXK::QXTHREAD_NO_TIMEOUT} - -$declare ${QXK::QXK-base} - -$declare ${QXK::QXThread} - -$declare ${QXK::QXSemaphore} - -$declare ${QXK::QXMutex} - -extern "C" { -$declare ${QXK-extern-C} -} // extern "C" - -//============================================================================ -// interface used only for internal implementation, but not in applications -#ifdef QP_IMPL - -$declare ${QXK-impl} - -$declare ${QF_EPOOL-impl} - -namespace QP { -namespace QXK { -enum TimeoutSigs : QSignal { - DELAY_SIG = 1U, - TIMEOUT_SIG -}; -} // namespace QXK -} // namespace QP - -#endif // QP_IMPL - -#endif // QXK_HPP_ - - - - #ifndef QS_HPP_ -#define QS_HPP_ - -#ifndef Q_SPY -#error "Q_SPY must be defined to include qs.hpp" -#endif - -//============================================================================ -//! @cond INTERNAL - -#ifndef QS_CTR_SIZE -#define QS_CTR_SIZE 2U -#endif - -#ifndef QS_TIME_SIZE -#define QS_TIME_SIZE 4U -#endif - -//! @endcond -//============================================================================ - -$declare ${QS::types} -$declare ${QS::filters} -$declare ${QS-macros} - -//============================================================================ -//! @cond INTERNAL - -namespace QP { -namespace QS { - -struct Attr { - void const * locFilter_AP; //!< @deprecated - std::uint8_t * buf; - QSCtr end; - QSCtr volatile head; - QSCtr volatile tail; - QSCtr volatile used; - std::uint8_t volatile seq; - std::uint8_t volatile chksum; - std::uint8_t volatile critNest; - std::uint8_t flags; -}; - -extern Attr priv_; - -void glbFilter_(std::int_fast16_t const filter) noexcept; -void locFilter_(std::int_fast16_t const filter) noexcept; - -void beginRec_(std::uint_fast8_t const rec) noexcept; -void endRec_() noexcept; - -void u8_raw_(std::uint8_t const d) noexcept; -void u8u8_raw_(std::uint8_t const d1, std::uint8_t const d2) noexcept; -void u16_raw_(std::uint16_t d) noexcept; -void u32_raw_(std::uint32_t d) noexcept; -void u64_raw_(std::uint64_t d) noexcept; -void obj_raw_(void const * const obj) noexcept; -void str_raw_(char const * s) noexcept; - -void u8_fmt_(std::uint8_t const format, std::uint8_t const d) noexcept; -void u16_fmt_(std::uint8_t format, std::uint16_t d) noexcept; -void u32_fmt_(std::uint8_t format, - std::uint32_t d) noexcept; -void u64_fmt_(std::uint8_t format, std::uint64_t d) noexcept; -void f32_fmt_(std::uint8_t format, float32_t f) noexcept; -void f64_fmt_(std::uint8_t format, float64_t d) noexcept; -void str_fmt_(char const * s) noexcept; -void mem_fmt_(std::uint8_t const * blk, std::uint8_t size) noexcept; - -void sig_dict_pre_(QSignal const sig, void const * const obj, - char const * const name) noexcept; -void obj_dict_pre_(void const * const obj, - char const * const name) noexcept; -void obj_arr_dict_pre_(void const * const obj, - std::uint_fast16_t const idx, - char const * const name) noexcept; -void fun_dict_pre_(QSpyFunPtr fun, - char const * const name) noexcept; -void usr_dict_pre_(enum_t const rec, char const * const name) noexcept; -void enum_dict_pre_(enum_t const value, std::uint8_t const group, - char const * const name) noexcept; - -void assertion_pre_(char const * const module, int_t const id, - std::uint32_t const delay) noexcept; -void crit_entry_pre_() noexcept; -void crit_exit_pre_() noexcept; -void isr_entry_pre_(std::uint8_t const isrnest, - std::uint8_t const prio) noexcept; -void isr_exit_pre_(std::uint8_t const isrnest, - std::uint8_t const prio) noexcept; - -void target_info_pre_(std::uint8_t const isReset); - -} // namespace QS -} // namespace QP - -//! @endcond -//============================================================================ - -$declare ${QS::QS-TX} - -//============================================================================ -#ifdef Q_UTEST - -$declare ${QS::QUTest} - -#define QUTEST_ON_POST 124 - -//============================================================================ -//! @cond INTERNAL - -namespace QP { -namespace QS { - -struct TestAttr { - TProbe tpBuf[16]; - std::uint8_t tpNum; - QSTimeCtr testTime; - QPSet readySet; - QPSet readySet_dis; - std::uint_fast8_t intLock; -}; - -extern TestAttr tstPriv_; - -void test_pause_(); -std::uint32_t getTestProbe_(QSpyFunPtr const api) noexcept; - -} // namespace QS -} // namespace QP - -//! @endcond -//============================================================================ - -// QP-stub for QUTest -// NOTE: The QP-stub is needed for unit testing QP applications, -// but might NOT be needed for testing QP itself. -#if (Q_UTEST != 0) - -$declare ${QS::QUTest-stub::QHsmDummy} -$declare ${QS::QUTest-stub::QActiveDummy} - -#endif // Q_UTEST != 0 - -#define QS_TEST_PROBE_DEF(fun_) \ - std::uint32_t const qs_tp_ = \ - QP::QS::getTestProbe_(QP::QS::force_cast<void (*)()>(fun_)); - -#define QS_TEST_PROBE(code_) \ - if (qs_tp_ != 0U) { code_ } - -#define QS_TEST_PROBE_ID(id_, code_) \ - if (qs_tp_ == static_cast<std::uint32_t>(id_)) { code_ } - -#define QS_TEST_PAUSE() (QP::QS::test_pause_()) - -#else // Q_UTEST not defined - -// dummy definitions when not building for QUTEST -#define QS_TEST_PROBE_DEF(fun_) -#define QS_TEST_PROBE(code_) -#define QS_TEST_PROBE_ID(id_, code_) -#define QS_TEST_PAUSE() (static_cast<void>(0)) - -#endif // Q_UTEST - -//============================================================================ -//! @cond INTERNAL - -namespace QP { -namespace QS { - -//............................................................................ -struct CmdVar { - std::uint32_t param1; - std::uint32_t param2; - std::uint32_t param3; - std::uint8_t idx; - std::uint8_t cmdId; -}; - -struct TickVar { - std::uint_fast8_t rate; -}; - -struct PeekVar { - std::uint16_t offs; - std::uint8_t size; - std::uint8_t num; - std::uint8_t idx; -}; - -struct PokeVar { - std::uint32_t data; - std::uint16_t offs; - std::uint8_t size; - std::uint8_t num; - std::uint8_t idx; - std::uint8_t fill; -}; - -struct FltVar { - std::uint8_t data[16]; - std::uint8_t idx; - std::uint8_t recId; // global/local -}; - -struct ObjVar { - QSObj addr; - std::uint8_t idx; - std::uint8_t kind; // see qs.hpp, enum QSpyObjKind - std::uint8_t recId; -}; - -struct EvtVar { - QP::QEvt *e; - std::uint8_t *p; - QP::QSignal sig; - std::uint16_t len; - std::uint8_t prio; - std::uint8_t idx; -}; - -struct RxAttr { - void * currObj[8]; - std::uint8_t * buf; - QSCtr end; - QSCtr volatile head; - QSCtr volatile tail; - std::uint8_t state; - std::uint8_t esc; - std::uint8_t seq; - std::uint8_t chksum; -#ifdef Q_UTEST - bool inTestLoop; -#endif - union Variant { - CmdVar cmd; - TickVar tick; - PeekVar peek; - PokeVar poke; - FltVar flt; - ObjVar obj; - EvtVar evt; -#ifdef Q_UTEST - QP::QS::TProbe tp; -#endif // Q_UTEST - } var; -} ; - -extern RxAttr rxPriv_; - -} // namespace QS -} // namespace QP - -//! @endcond -//============================================================================ - -$declare ${QS::QS-RX} - -#endif // QS_HPP_ - - - - #ifndef QS_DUMMY_HPP_ -#define QS_DUMMY_HPP_ - -#ifdef Q_SPY -#error "Q_SPY must NOT be defined to include qs_dummy.hpp" -#endif - -#define QS_INIT(arg_) (true) -#define QS_EXIT() static_cast<void>(0) -#define QS_DUMP() static_cast<void>(0) -#define QS_GLB_FILTER(rec_) static_cast<void>(0) -#define QS_LOC_FILTER(qsId_) static_cast<void>(0) - -#define QS_GET_BYTE(pByte_) (0xFFFFU) -#define QS_GET_BLOCK(pSize_) (nullptr) - -#define QS_BEGIN_ID(rec_, qsId_) if (false) { -#define QS_END() } -#define QS_BEGIN_INCRIT(rec_, qsId_) if (false) { -#define QS_END_INCRIT() } - -#define QS_I8(width_, data_) static_cast<void>(0) -#define QS_U8(width_, data_) static_cast<void>(0) -#define QS_I16(width_, data_) static_cast<void>(0) -#define QS_U16(width_, data_) static_cast<void>(0) -#define QS_I32(width_, data_) static_cast<void>(0) -#define QS_U32(width_, data_) static_cast<void>(0) -#define QS_F32(width_, data_) static_cast<void>(0) -#define QS_F64(width_, data_) static_cast<void>(0) -#define QS_I64(width_, data_) static_cast<void>(0) -#define QS_U64(width_, data_) static_cast<void>(0) -#define QS_ENUM(group_, value_) static_cast<void>(0) -#define QS_STR(str_) static_cast<void>(0) -#define QS_MEM(mem_, size_) static_cast<void>(0) -#define QS_SIG(sig_, obj_) static_cast<void>(0) -#define QS_OBJ(obj_) static_cast<void>(0) -#define QS_FUN(fun_) static_cast<void>(0) - -#define QS_SIG_DICTIONARY(sig_, obj_) static_cast<void>(0) -#define QS_OBJ_DICTIONARY(obj_) static_cast<void>(0) -#define QS_OBJ_ARR_DICTIONARY(obj_, idx_) static_cast<void>(0) -#define QS_FUN_DICTIONARY(fun_) static_cast<void>(0) -#define QS_USR_DICTIONARY(rec_) static_cast<void>(0) -#define QS_ENUM_DICTIONARY(value_, group_) static_cast<void>(0) -#define QS_ASSERTION(module_, loc_, delay_) static_cast<void>(0) -#define QS_FLUSH() static_cast<void>(0) - -#define QS_TEST_PROBE_DEF(fun_) -#define QS_TEST_PROBE(code_) -#define QS_TEST_PROBE_ID(id_, code_) -#define QS_TEST_PAUSE() static_cast<void>(0) - -#define QS_OUTPUT() static_cast<void>(0) -#define QS_RX_INPUT() static_cast<void>(0) -#define QS_ONLY(code_) static_cast<void>(0) - -//============================================================================ -// interface used only for internal implementation, but not in applications -#ifdef QP_IMPL - // predefined QS trace records - #define QS_BEGIN_PRE_(rec_, qsId_) if (false) { - #define QS_END_PRE_() } - #define QS_BEGIN_PRE_(rec_, qsId_) if (false) { - #define QS_END_PRE_() } - #define QS_U8_PRE_(data_) static_cast<void>(0) - #define QS_2U8_PRE_(data1_, data2_) static_cast<void>(0) - #define QS_U16_PRE_(data_) static_cast<void>(0) - #define QS_U32_PRE_(data_) static_cast<void>(0) - #define QS_TIME_PRE_() static_cast<void>(0) - #define QS_SIG_PRE_(sig_) static_cast<void>(0) - #define QS_EVS_PRE_(size_) static_cast<void>(0) - #define QS_OBJ_PRE_(obj_) static_cast<void>(0) - #define QS_FUN_PRE_(fun_) static_cast<void>(0) - #define QS_EQC_PRE_(ctr_) static_cast<void>(0) - #define QS_MPC_PRE_(ctr_) static_cast<void>(0) - #define QS_MPS_PRE_(size_) static_cast<void>(0) - #define QS_TEC_PRE_(ctr_) static_cast<void>(0) - - #define QS_CRIT_STAT - #define QS_CRIT_ENTRY() static_cast<void>(0) - #define QS_CRIT_EXIT() static_cast<void>(0) - - #define QS_MEM_SYS() static_cast<void>(0) - #define QS_MEM_APP() static_cast<void>(0) - - #define QS_TR_CRIT_ENTRY() static_cast<void>(0) - #define QS_TR_CRIT_EXIT() static_cast<void>(0) - #define QS_TR_ISR_ENTRY(isrnest_, prio_) static_cast<void>(0) - #define QS_Tr_ISR_EXIT(isrnest_, prio_) static_cast<void>(0) -#endif // QP_IMPL - -#endif // QS_DUMMY_HPP_ - - - - #ifndef QS_PKG_HPP_ -#define QS_PKG_HPP_ - -//============================================================================ -//! @cond INTERNAL - -namespace QP { - -//! QS received record types (RX channel) -enum QSpyRxRecords : std::uint8_t { - QS_RX_INFO, //!< query Target info (ver, config, tstamp) - QS_RX_COMMAND, //!< execute a user-defined command in the Target - QS_RX_RESET, //!< reset the Target - QS_RX_TICK, //!< call system clock tick in the Target - QS_RX_PEEK, //!< peek Target memory - QS_RX_POKE, //!< poke Target memory - QS_RX_FILL, //!< fill Target memory - QS_RX_TEST_SETUP, //!< test setup - QS_RX_TEST_TEARDOWN, //!< test teardown - QS_RX_TEST_PROBE, //!< set a Test-Probe in the Target - QS_RX_GLB_FILTER, //!< set global filters in the Target - QS_RX_LOC_FILTER, //!< set local filters in the Target - QS_RX_AO_FILTER, //!< set local AO filter in the Target - QS_RX_CURR_OBJ, //!< set the "current-object" in the Target - QS_RX_TEST_CONTINUE, //!< continue a test after QS_TEST_PAUSE() - QS_RX_QUERY_CURR, //!< query the "current object" in the Target - QS_RX_EVENT //!< inject an event to the Target -}; - -constexpr std::uint8_t QS_FRAME {0x7EU}; -constexpr std::uint8_t QS_ESC {0x7DU}; -constexpr std::uint8_t QS_ESC_XOR {0x20U}; -constexpr std::uint8_t QS_GOOD_CHKSUM {0xFFU}; - -} // namespace QP - -//---------------------------------------------------------------------------- -#define QS_BEGIN_PRE_(rec_, qsId_) \ - if (QS_GLB_CHECK_(rec_) && QS_LOC_CHECK_(qsId_)) { \ - QP::QS::beginRec_(static_cast<std::uint_fast8_t>(rec_)); -#define QS_END_PRE_() QP::QS::endRec_(); } - -#define QS_U8_PRE_(data_) \ - (QP::QS::u8_raw_(static_cast<std::uint8_t>(data_))) -#define QS_2U8_PRE_(data1_, data2_) \ - (QP::QS::u8u8_raw_(static_cast<std::uint8_t>(data1_), \ - static_cast<std::uint8_t>(data2_))) -#define QS_U16_PRE_(data_) \ - (QP::QS::u16_raw_(static_cast<std::uint16_t>(data_))) -#define QS_U32_PRE_(data_) \ - (QP::QS::u32_raw_(static_cast<std::uint32_t>(data_))) -#define QS_STR_PRE_(msg_) (QP::QS::str_raw_(msg_)) -#define QS_OBJ_PRE_(obj_) (QP::QS::obj_raw_(obj_)) - -#if (!defined Q_SIGNAL_SIZE || (Q_SIGNAL_SIZE == 1U)) - #define QS_SIG_PRE_(sig_) \ - (QP::QS::u8_raw_(static_cast<std::uint8_t>(sig_))) -#elif (Q_SIGNAL_SIZE == 2U) - #define QS_SIG_PRE_(sig_) \ - (QP::QS::u16_raw_(static_cast<std::uint16_t>(sig_))) -#elif (Q_SIGNAL_SIZE == 4U) - #define QS_SIG_PRE_(sig_) \ - (QP::QS::u32_raw_(static_cast<std::uint32_t>(sig_))) -#endif - -#if (!defined QS_FUN_PTR_SIZE || (QS_FUN_PTR_SIZE == 2U)) - #define QS_FUN_PRE_(fun_) \ - (QP::QS::u16_raw_(reinterpret_cast<std::uint16_t>(fun_))) -#elif (QS_FUN_PTR_SIZE == 4U) - #define QS_FUN_PRE_(fun_) \ - (QP::QS::u32_raw_(reinterpret_cast<std::uint32_t>(fun_))) -#elif (QS_FUN_PTR_SIZE == 8U) - #define QS_FUN_PRE_(fun_) \ - (QP::QS::u64_raw_(reinterpret_cast<std::uint64_t>(fun_))) -#else - #define QS_FUN_PRE_(fun_) \ - (QP::QS::u32_raw_(reinterpret_cast<std::uint32_t>(fun_))) -#endif - -//---------------------------------------------------------------------------- -#if (!defined QF_EQUEUE_CTR_SIZE || (QF_EQUEUE_CTR_SIZE == 1U)) - #define QS_EQC_PRE_(ctr_) \ - QP::QS::u8_raw_(static_cast<std::uint8_t>(ctr_)) -#elif (QF_EQUEUE_CTR_SIZE == 2U) - #define QS_EQC_PRE_(ctr_) \ - QP::QS::u16_raw_(static_cast<std::uint16_t>(ctr_)) -#elif (QF_EQUEUE_CTR_SIZE == 4U) - #define QS_EQC_PRE_(ctr_) \ - QP::QS::u32_raw_(static_cast<std::uint32_t>(ctr_)) -#else - #error "QF_EQUEUE_CTR_SIZE not defined" -#endif - -#if (!defined QF_EVENT_SIZ_SIZE || (QF_EVENT_SIZ_SIZE == 1U)) - #define QS_EVS_PRE_(size_) \ - QP::QS::u8_raw_(static_cast<std::uint8_t>(size_)) -#elif (QF_EVENT_SIZ_SIZE == 2U) - #define QS_EVS_PRE_(size_) \ - QP::QS::u16_raw_(static_cast<std::uint16_t>(size_)) -#elif (QF_EVENT_SIZ_SIZE == 4U) - #define QS_EVS_PRE_(size_) \ - QP::QS::u32_raw_(static_cast<std::uint32_t>(size_)) -#endif - -#if (!defined QF_MPOOL_SIZ_SIZE || (QF_MPOOL_SIZ_SIZE == 1U)) - #define QS_MPS_PRE_(size_) \ - QP::QS::u8_raw_(static_cast<std::uint8_t>(size_)) -#elif (QF_MPOOL_SIZ_SIZE == 2U) - #define QS_MPS_PRE_(size_) \ - QP::QS::u16_raw_(static_cast<std::uint16_t>(size_)) -#elif (QF_MPOOL_SIZ_SIZE == 4U) - #define QS_MPS_PRE_(size_) \ - QP::QS::u32_raw_(static_cast<std::uint32_t>(size_)) -#endif - -#if (!defined QF_MPOOL_CTR_SIZE || (QF_MPOOL_CTR_SIZE == 1U)) - #define QS_MPC_PRE_(ctr_) \ - QP::QS::u8_raw_(static_cast<std::uint8_t>(ctr_)) -#elif (QF_MPOOL_CTR_SIZE == 2U) - #define QS_MPC_PRE_(ctr_) \ - QP::QS::u16_raw_(static_cast<std::uint16_t>(ctr_)) -#elif (QF_MPOOL_CTR_SIZE == 4U) - #define QS_MPC_PRE_(ctr_) \ - QP::QS::u32_raw_(static_cast<std::uint32_t>(ctr_)) -#endif - -#if (!defined QF_TIMEEVT_CTR_SIZE || (QF_TIMEEVT_CTR_SIZE == 1U)) - #define QS_TEC_PRE_(ctr_) \ - QP::QS::u8_raw_(static_cast<std::uint8_t>(ctr_)) -#elif (QF_TIMEEVT_CTR_SIZE == 2U) - #define QS_TEC_PRE_(ctr_) \ - QP::QS::u16_raw_(static_cast<std::uint16_t>(ctr_)) -#elif (QF_TIMEEVT_CTR_SIZE == 4U) - #define QS_TEC_PRE_(ctr_) \ - QP::QS::u32_raw_(static_cast<std::uint32_t>(ctr_)) -#endif - -#define QS_REC_NUM_(enum_) (static_cast<std::uint_fast8_t>(enum_)) - -//---------------------------------------------------------------------------- -#define QS_INSERT_BYTE_(b_) \ - buf[head] = (b_); \ - ++head; \ - if (head == end) { \ - head = 0U; \ - } - -#define QS_INSERT_ESC_BYTE_(b_) \ - chksum = static_cast<std::uint8_t>(chksum + (b_)); \ - if (((b_) != QS_FRAME) && ((b_) != QS_ESC)) { \ - QS_INSERT_BYTE_(b_) \ - } \ - else { \ - QS_INSERT_BYTE_(QS_ESC) \ - QS_INSERT_BYTE_(static_cast<std::uint8_t>((b_) ^ QS_ESC_XOR)) \ - priv_.used = priv_.used + 1U; \ - } - -//---------------------------------------------------------------------------- -#if (defined Q_UTEST) && (Q_UTEST != 0) -namespace QP { -namespace QS { - -void processTestEvts_(); - -} // namespace QS -} // namespace QP -#endif // Q_UTEST != 0 - -//! @endcond -//============================================================================ - -#endif // QS_PKG_HPP_ - - - - #ifndef QSTAMP_HPP_ -#define QSTAMP_HPP_ - -namespace QP { -extern char const BUILD_DATE[12]; -extern char const BUILD_TIME[9]; -} // namespace QP - -#endif // QSTAMP_HPP_ - - - - #ifndef QPCPP_HPP_ -#define QPCPP_HPP_ - -//============================================================================ -#include "qp_port.hpp" // QP port from the port directory -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // software tracing enabled? - #include "qs_port.hpp" // QS/C++ port from the port directory -#else - #include "qs_dummy.hpp" // QS/C++ dummy (inactive) interface -#endif - -//============================================================================ -#ifndef QP_API_VERSION - -#define QP_API_VERSION 0 - -#endif // QP_API_VERSION - -//============================================================================ -// QP/C++ API compatibility layer... - -#if (QP_API_VERSION < 740) - -#ifdef QEVT_DYN_CTOR -//! @deprecated #QEVT_DYN_CTOR, please use #QEVT_PAR_INIT -#define QEVT_PAR_INIT -#endif - -//! @deprecated plain 'char' is no longer forbidden in MISRA/AUTOSAR-C++ -using char_t = char; - -//! @deprecated assertion failure handler -//! Use Q_onError() instead. -#define Q_onAssert(module_, id_) Q_onError(module_, id_) - -//! @deprecated #Q_NASSERT preprocessor switch to disable QP assertions -#ifdef Q_NASSERT - - // #Q_UNSAFE now replaces the functionality of Q_NASSERT - #define Q_UNSAFE - - //! @deprecated general purpose assertion with user-specified ID - //! number that **always** evaluates the `expr_` expression. - #define Q_ALLEGE_ID(id_, expr_) ((void)(expr_)) - -#else // QP FuSa Subsystem enabled - - //! @deprecated general purpose assertion with user-specified ID - //! number that **always** evaluates the `expr_` expression. - //! @note - //! The use of this macro is no longer recommended. - #define Q_ALLEGE_ID(id_, expr_) if (!(expr_)) { \ - QF_CRIT_STAT \ - QF_CRIT_ENTRY(); \ - Q_onError(&Q_this_module_[0], (id_)); \ - QF_CRIT_EXIT(); \ - } else ((void)0) - -#endif - -//! @deprecated general purpose assertion without ID number -//! that **always** evaluates the `expr_` expression. -//! Instead of ID number, this macro is based on the standard -//! `__LINE__` macro. -//! -//! @note The use of this macro is no longer recommended. -#define Q_ALLEGE(expr_) Q_ALLEGE_ID(__LINE__, (expr_)) - -//! Static (compile-time) assertion. -//! -//! @deprecated -//! Use Q_ASSERT_STATIC() or better yet `static_assert()` instead. -//! -#define Q_ASSERT_COMPILE(expr_) Q_ASSERT_STATIC(expr_) - -//! @deprecated use QP::QF::NO_MARGIN instead -#define QF_NO_MARGIN QP::QF::NO_MARGIN - -//============================================================================ -#if (QP_API_VERSION < 691) - -//! @deprecated enable the QS global filter -#define QS_FILTER_ON(rec_) QS_GLB_FILTER((rec_)) - -//! @deprecated disable the QS global filter -#define QS_FILTER_OFF(rec_) QS_GLB_FILTER(-(rec_)) - -//! @deprecated enable the QS local filter for SM (state machine) object -#define QS_FILTER_SM_OBJ(obj_) (static_cast<void>(0)) - -//! @deprecated enable the QS local filter for AO (active objects) -#define QS_FILTER_AO_OBJ(obj_) (static_cast<void>(0)) - -//! @deprecated enable the QS local filter for MP (memory pool) object -#define QS_FILTER_MP_OBJ(obj_) (static_cast<void>(0)) - -//! @deprecated enable the QS local filter for EQ (event queue) object -#define QS_FILTER_EQ_OBJ(obj_) (static_cast<void>(0)) - -//! @deprecated enable the QS local filter for TE (time event) object -#define QS_FILTER_TE_OBJ(obj_) (static_cast<void>(0)) - -#ifdef Q_SPY - -//! @deprecated local Filter for a generic application object `obj_`. -#define QS_FILTER_AP_OBJ(obj_) \ - (QP::QS::filt_.loc_AP = (obj_)) - -//! @deprecated begin of a user QS record, instead use QS_BEGIN_ID() -#define QS_BEGIN(rec_, obj_) \ - if (QS_GLB_FILTER_(rec_) && \ - ((QP::QS::filt_.loc[QP::QS::AP_OBJ] == nullptr) \ - || (QP::QS::filt_.loc_AP == (obj_)))) \ - { \ - QS_CRIT_STAT \ - QS_CRIT_ENTRY(); \ - QP::QS::beginRec_(static_cast<std::uint_fast8_t>(rec_)); \ - QS_TIME_PRE_(); - -//! @deprecated output hex-formatted std::uint32_t to the QS record -#define QS_U32_HEX(width_, data_) \ - (QP::QS::u32_fmt_(static_cast<std::uint8_t>( \ - (static_cast<std::uint8_t>((width_) << 4)) | QS_HEX_FMT), (data_))) - -#else - -#define QS_FILTER_AP_OBJ(obj_) (static_cast<void>(0)) -#define QS_BEGIN(rec_, obj_) if (false) { -#define QS_U32_HEX(width_, data_) (Q_UNUSED_PAR(0)) - -#endif // def Q_SPY - -//============================================================================ -#if (QP_API_VERSION < 680) - -//! @deprecated -//! Macro to specify a tran. in the "me->" impl-strategy. -//! Instead use the new impl-strategy without the "me->" pointer, where -//! you call tran(Q_STATE_CAST(target_)). -#define Q_TRAN(target_) (me->tran(Q_STATE_CAST(target_))) - -//! @deprecated -//! Macro to specify a tran-to-history in the "me->" impl-strategy. -//! Instead use the new impl-strategy without the "me->" pointer, where -//! you call tran_hist(Q_STATE_CAST(hist_)). -#define Q_TRAN_HIST(hist_) (me->tran_hist((hist_))) - -//! @deprecated -//! Macro to specify the superstate in the "me->" impl-strategy. -//! Instead use the new impl-strategy without the "me->" pointer, where -//! you call super(state_)). -#define Q_SUPER(state_) (me->super(Q_STATE_CAST(state_))) - -//! @deprecated -//! Macro to call in a QM state entry-handler. Applicable only to QMSMs. -//! Instead use the new impl-strategy without the "me->" pointer, where -//! the QM-generated code calls qm_entry(Q_STATE_CAST(state_)). -#define QM_ENTRY(state_) (me->qm_entry((state_))) - -//! @deprecated -//! Macro to call in a QM state exit-handler. Applicable only to QMSMs. -//! Instead use the new impl-strategy without the "me->" pointer, where -//! the QM-generated code calls qm_exit(Q_STATE_CAST(state_)). -#define QM_EXIT(state_) (me->qm_exit((state_))) - -//! @deprecated -//! Macro to call in a QM submachine exit-handler. Applicable only to QMSMs. -//! Instead use the new impl-strategy without the "me->" pointer, where -//! the QM-generated code calls qm_sm_exit(Q_STATE_CAST(state_)). -#define QM_SM_EXIT(state_) (me->qm_sm_exit((state_))) - -//! @deprecated -//! Macro to call in a QM state-handler when it executes a tran. -//! Instead use the new impl-strategy without the "me->" pointer, where -//! the QM-generated code calls qm_tran((tatbl_)). -#define QM_TRAN(tatbl_) (me->qm_tran((tatbl_))) - -//! @deprecated -//! Macro to call in a QM state-handler when it executes an initial tran. -//! Instead use the new impl-strategy without the "me->" pointer, where -//! the QM-generated code calls qm_tran_init((tatbl_)). -#define QM_TRAN_INIT(tatbl_) (me->qm_tran_init((tatbl_))) - -//! @deprecated -//! Macro to call in a QM state-handler when it executes a tran-to-history. -//! Instead use the new impl-strategy without the "me->" pointer, where -//! the QM-generated code calls qm_tran_hist((history_), (tatbl_)). -#define QM_TRAN_HIST(history_, tatbl_) \ - (me->qm_tran_hist((history_), (tatbl_))) - -//! @deprecated -//! Macro to call in a QM state-handler when it executes an initial tran. -//! Instead use the new impl-strategy without the "me->" pointer, where -//! the QM-generated code calls qm_tran_ep((tatbl_)). -#define QM_TRAN_EP(tatbl_) (me->qm_tran_ep((tatbl_))) - -//! @deprecated -//! Macro to call in a QM state-handler when it executes a tran-to-exit-point. -//! Instead use the new impl-strategy without the "me->" pointer, where -//! the QM-generated code calls qm_tran_xp((xp_), (tatbl_)). -#define QM_TRAN_XP(xp_, tatbl_) (me->qm_tran_xp((xp_), (tatbl_))) - -//! @deprecated -//! Designates the superstate of a given state in a subclass of QP::QMsm. -//! Instead use the new impl-strategy without the "me->" pointer, where -//! the QM-generated code calls qm_super_sub((state_)). -#define QM_SUPER_SUB(state_) (me->qm_super_sub((state_))) - -#endif // QP_API_VERSION < 680 -#endif // QP_API_VERSION < 691 -#endif // QP_API_VERSION < 700 - -#endif // QPCPP_HPP_ - - - - - - - - - #define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // QS software tracing enabled? - #include "qs_port.hpp" // QS port - #include "qs_pkg.hpp" // QS facilities for pre-defined trace records -#else - #include "qs_dummy.hpp" // disable the QS software tracing -#endif // Q_SPY - -//============================================================================ -//! @cond INTERNAL - -// unnamed namespace for local definitions with internal linkage -namespace { -Q_DEFINE_THIS_MODULE("qep_hsm") - -// immutable events corresponding to the reserved signals. -static QP::QEvt const l_reservedEvt_[4] { - QP::QEvt(static_cast<QP::QSignal>(QP::QHsm::Q_EMPTY_SIG)), - QP::QEvt(static_cast<QP::QSignal>(QP::QHsm::Q_ENTRY_SIG)), - QP::QEvt(static_cast<QP::QSignal>(QP::QHsm::Q_EXIT_SIG)), - QP::QEvt(static_cast<QP::QSignal>(QP::QHsm::Q_INIT_SIG)) -}; - -} // unnamed namespace - -// helper macro to handle reserved event in an QHsm -#define QHSM_RESERVED_EVT_(state_, sig_) \ - ((*(state_))(this, &l_reservedEvt_[(sig_)])) - -// helper macro to trace state entry -#define QS_STATE_ENTRY_(state_, qsId_) \ - QS_CRIT_ENTRY(); \ - QS_MEM_SYS(); \ - QS_BEGIN_PRE_(QS_QEP_STATE_ENTRY, (qsId_)) \ - QS_OBJ_PRE_(this); \ - QS_FUN_PRE_(state_); \ - QS_END_PRE_() \ - QS_MEM_APP(); \ - QS_CRIT_EXIT() - -// helper macro to trace state exit -#define QS_STATE_EXIT_(state_, qsId_) \ - QS_CRIT_ENTRY(); \ - QS_MEM_SYS(); \ - QS_BEGIN_PRE_(QS_QEP_STATE_EXIT, (qsId_)) \ - QS_OBJ_PRE_(this); \ - QS_FUN_PRE_(state_); \ - QS_END_PRE_() \ - QS_MEM_APP(); \ - QS_CRIT_EXIT() - -//! @endcond - -// maximum depth of state nesting in a QHsm (including the top level) -// must be >= 3 -static constexpr std::int_fast8_t QHSM_MAX_NEST_DEPTH_ {6}; -//============================================================================ - -$define ${QEP::versionStr[]} - -$define ${QEP::QHsm} - - - - #define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // QS software tracing enabled? - #include "qs_port.hpp" // QS port - #include "qs_pkg.hpp" // QS facilities for pre-defined trace records -#else - #include "qs_dummy.hpp" // disable the QS software tracing -#endif // Q_SPY - -//============================================================================ -//! @cond INTERNAL - -// unnamed namespace for local definitions with internal linkage -namespace { - -Q_DEFINE_THIS_MODULE("qep_msm") - -// top-state object for QMsm-style state machines -QP::QMState const l_msm_top_s = { - nullptr, - nullptr, - nullptr, - nullptr, - nullptr -}; - -} // unnamed namespace - -//! @endcond - -// maximum depth of state nesting in a QMsm (including the top level) -static constexpr std::int_fast8_t QMSM_MAX_NEST_DEPTH_ {8}; - -// maximum length of transition-action array -static constexpr std::int_fast8_t QMSM_MAX_TRAN_LENGTH_ {2*QMSM_MAX_NEST_DEPTH_}; - -// maximum depth of entry levels in a MSM for tran. to history. -static constexpr std::int_fast8_t QMSM_MAX_ENTRY_DEPTH_ {4}; -//============================================================================ - -$define ${QEP::QMsm} - - - - #define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // QS software tracing enabled? - #include "qs_port.hpp" // QS port - #include "qs_pkg.hpp" // QS facilities for pre-defined trace records -#else - #include "qs_dummy.hpp" // disable the QS software tracing -#endif // Q_SPY - -// unnamed namespace for local definitions with internal linkage -namespace { -//Q_DEFINE_THIS_MODULE("qf_act") -} // unnamed namespace - -$define ${QF::QActive::registry_[QF_MAX_ACTIVE + 1U]} - -$define ${QF::QF-pkg} - -$define ${QF::types::QF_LOG2} - - - - #define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // QS software tracing enabled? - #include "qs_port.hpp" // QS port - #include "qs_pkg.hpp" // QS facilities for pre-defined trace records -#else - #include "qs_dummy.hpp" // disable the QS software tracing -#endif // Q_SPY - -//============================================================================ -// unnamed namespace for local definitions with internal linkage -namespace { -Q_DEFINE_THIS_MODULE("qf_actq") -} // unnamed namespace - -$define ${QF::QActive::post_} - -$define ${QF::QActive::postLIFO} - -$define ${QF::QActive::get_} - -$define ${QF::QTicker} - - - - #define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // QS software tracing enabled? - #include "qs_port.hpp" // QS port - #include "qs_pkg.hpp" // QS facilities for pre-defined trace records -#else - #include "qs_dummy.hpp" // disable the QS software tracing -#endif // Q_SPY - -// unnamed namespace for local definitions with internal linkage -namespace { -Q_DEFINE_THIS_MODULE("qf_defer") -} // unnamed namespace - -$define ${QF::QActive::defer} - -$define ${QF::QActive::recall} - -$define ${QF::QActive::flushDeferred} - - - - #define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // QS software tracing enabled? - #include "qs_port.hpp" // QS port - #include "qs_pkg.hpp" // QS facilities for pre-defined trace records -#else - #include "qs_dummy.hpp" // disable the QS software tracing -#endif // Q_SPY - -#if (QF_MAX_EPOOL > 0U) // mutable events configured? - -// unnamed namespace for local definitions with internal linkage -namespace { -Q_DEFINE_THIS_MODULE("qf_dyn") -} // unnamed namespace - -$define ${QF::QF-dyn} - -#endif // (QF_MAX_EPOOL > 0U) mutable events configured - - - - #define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // QS software tracing enabled? - #include "qs_port.hpp" // QS port - #include "qs_pkg.hpp" // QS facilities for pre-defined trace records -#else - #include "qs_dummy.hpp" // disable the QS software tracing -#endif // Q_SPY - -// unnamed namespace for local definitions with internal linkage -namespace { -Q_DEFINE_THIS_MODULE("qf_mem") -} // unnamed namespace - -$define ${QF::QMPool} - - - - #define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // QS software tracing enabled? - #include "qs_port.hpp" // QS port - #include "qs_pkg.hpp" // QS facilities for pre-defined trace records -#else - #include "qs_dummy.hpp" // disable the QS software tracing -#endif // Q_SPY - -// unnamed namespace for local definitions with internal linkage -namespace { -Q_DEFINE_THIS_MODULE("qf_qact") -} // unnamed namespace - -$define ${QF::QActive::QActive} - -$define ${QF::QActive::register_} - -$define ${QF::QActive::unregister_} - - - - #define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // QS software tracing enabled? - #include "qs_port.hpp" // QS port - #include "qs_pkg.hpp" // QS facilities for pre-defined trace records -#else - #include "qs_dummy.hpp" // disable the QS software tracing -#endif // Q_SPY - -// unnamed namespace for local definitions with internal linkage -namespace { -//Q_DEFINE_THIS_MODULE("qf_qmact") -} // unnamed namespace - -$define ${QF::QMActive} - - - - #define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // QS software tracing enabled? - #include "qs_port.hpp" // QS port - #include "qs_pkg.hpp" // QS facilities for pre-defined trace records -#else - #include "qs_dummy.hpp" // disable the QS software tracing -#endif // Q_SPY - -// unnamed namespace for local definitions with internal linkage -namespace { -Q_DEFINE_THIS_MODULE("qf_qeq") -} // unnamed namespace - -$define ${QF::QEQueue} - - - - #define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // QS software tracing enabled? - #include "qs_port.hpp" // QS port - #include "qs_pkg.hpp" // QS facilities for pre-defined trace records -#else - #include "qs_dummy.hpp" // disable the QS software tracing -#endif // Q_SPY - -// unnamed namespace for local definitions with internal linkage -namespace { -Q_DEFINE_THIS_MODULE("qf_ps") -} // unnamed namespace - -$define ${QF::QActive::subscrList_} - -$define ${QF::QActive::maxPubSignal_} - -$define ${QF::QActive::psInit} - -$define ${QF::QActive::publish_} - -$define ${QF::QActive::subscribe} - -$define ${QF::QActive::unsubscribe} - -$define ${QF::QActive::unsubscribeAll} - - - - #define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // QS software tracing enabled? - #include "qs_port.hpp" // QS port - #include "qs_pkg.hpp" // QS facilities for pre-defined trace records -#else - #include "qs_dummy.hpp" // disable the QS software tracing -#endif // Q_SPY - -// unnamed namespace for local definitions with internal linkage -namespace { -Q_DEFINE_THIS_MODULE("qf_time") -} // unnamed namespace - -$define ${QF::QTimeEvt} - - - - - - - #define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // QS software tracing enabled? - #include "qs_port.hpp" // QS port - #include "qs_pkg.hpp" // QS facilities for pre-defined trace records -#else - #include "qs_dummy.hpp" // disable the QS software tracing -#endif // Q_SPY - -// protection against including this source file in a wrong project -#ifndef QV_HPP_ - #error "Source file included in a project NOT based on the QV kernel" -#endif // QV_HPP_ - -// unnamed namespace for local definitions with internal linkage -namespace { -Q_DEFINE_THIS_MODULE("qv") -} // unnamed namespace - -$define ${QV::QV-base} - -$define ${QV::QF-cust} - -$define ${QV::QActive} - - - - - - - #define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // QS software tracing enabled? - #include "qs_port.hpp" // QS port - #include "qs_pkg.hpp" // QS facilities for pre-defined trace records -#else - #include "qs_dummy.hpp" // disable the QS software tracing -#endif // Q_SPY - -// protection against including this source file in a wrong project -#ifndef QK_HPP_ - #error "Source file included in a project NOT based on the QK kernel" -#endif // QK_HPP_ - -// unnamed namespace for local definitions with internal linkage -namespace { -Q_DEFINE_THIS_MODULE("qk") -} // unnamed namespace - -$define ${QK::QK-base} - -extern "C" { -$define ${QK-extern-C} -} // extern "C" - -$define ${QK::QF-cust} - -$define ${QK::QActive} - - - - - - - #define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // QS software tracing enabled? - #include "qs_port.hpp" // QS port - #include "qs_pkg.hpp" // QS facilities for pre-defined trace records -#else - #include "qs_dummy.hpp" // disable the QS software tracing -#endif // Q_SPY - -// protection against including this source file in a wrong project -#ifndef QXK_HPP_ - #error "Source file included in a project NOT based on the QXK kernel" -#endif // QXK_HPP_ - -// unnamed namespace for local definitions with internal linkage -namespace { -Q_DEFINE_THIS_MODULE("qxk") -} // unnamed namespace - -$define ${QXK::QXK-base} - -extern "C" { -$define ${QXK-extern-C} -} // extern "C" - -$define ${QXK::QF-cust} - -$define ${QXK::QActive} - - - - #define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // QS software tracing enabled? - #include "qs_port.hpp" // QS port - #include "qs_pkg.hpp" // QS facilities for pre-defined trace records -#else - #include "qs_dummy.hpp" // disable the QS software tracing -#endif // Q_SPY - -// protection against including this source file in a wrong project -#ifndef QXK_HPP_ - #error "Source file included in a project NOT based on the QXK kernel" -#endif // QXK_HPP_ - -// unnamed namespace for local definitions with internal linkage -namespace { -Q_DEFINE_THIS_MODULE("qxk_mutex") -} // unnamed namespace - -$define ${QXK::QXMutex} - - - - #define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // QS software tracing enabled? - #include "qs_port.hpp" // QS port - #include "qs_pkg.hpp" // QS facilities for pre-defined trace records -#else - #include "qs_dummy.hpp" // disable the QS software tracing -#endif // Q_SPY - -// protection against including this source file in a wrong project -#ifndef QXK_HPP_ - #error "Source file included in a project NOT based on the QXK kernel" -#endif // QXK_HPP_ - -// unnamed namespace for local definitions with internal linkage -namespace { -Q_DEFINE_THIS_MODULE("qxk_sema") -} // unnamed namespace - -$define ${QXK::QXSemaphore} - - - - #define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // QS software tracing enabled? - #include "qs_port.hpp" // QS port - #include "qs_pkg.hpp" // QS facilities for pre-defined trace records -#else - #include "qs_dummy.hpp" // disable the QS software tracing -#endif // Q_SPY - -// protection against including this source file in a wrong project -#ifndef QXK_HPP_ - #error "Source file included in a project NOT based on the QXK kernel" -#endif // QXK_HPP_ - -// unnamed namespace for local definitions with internal linkage -namespace { -Q_DEFINE_THIS_MODULE("qxk_xthr") -} // unnamed namespace - -$define ${QXK::QXThread} - - - - - - - #define QP_IMPL // this is QP implementation -#include "qs_port.hpp" // QS port -#include "qs_pkg.hpp" // QS package-scope internal interface -#include "qstamp.hpp" // QP time-stamp -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem - -// unnamed namespace for local definitions with internal linkage -namespace { -Q_DEFINE_THIS_MODULE("qs") -} // unnamed namespace - -$define ${QS::QS-TX} - -#ifndef QF_MEM_ISOLATE -$define ${QS::filters} -#endif - -//============================================================================ -//! @cond INTERNAL - -namespace QP { -namespace QS { - -//............................................................................ -Attr priv_; - -//............................................................................ -void glbFilter_(std::int_fast16_t const filter) noexcept { - bool const isRemove = (filter < 0); - std::uint16_t const rec = isRemove - ? static_cast<std::uint16_t>(-filter) - : static_cast<std::uint16_t>(filter); - switch (rec) { - case QS_ALL_RECORDS: { - std::uint8_t const tmp = (isRemove ? 0x00U : 0xFFU); - std::uint_fast8_t i; - // set all global filters (partially unrolled loop) - for (i = 0U; i < Q_DIM(filt_.glb); i += 4U) { - filt_.glb[i ] = tmp; - filt_.glb[i + 1U] = tmp; - filt_.glb[i + 2U] = tmp; - filt_.glb[i + 3U] = tmp; - } - if (isRemove) { - // leave the "not maskable" filters enabled, - // see qs.h, Miscellaneous QS records (not maskable) - // - filt_.glb[0] = 0x01U; - filt_.glb[6] = 0x40U; - filt_.glb[7] = 0xFCU; - filt_.glb[8] = 0x7FU; - } - else { - // never turn the last 3 records on (0x7D, 0x7E, 0x7F) - filt_.glb[15] = 0x1FU; - } - break; - } - case QS_SM_RECORDS: - if (isRemove) { - filt_.glb[0] &= static_cast<std::uint8_t>(~0xFEU & 0xFFU); - filt_.glb[1] &= static_cast<std::uint8_t>(~0x03U & 0xFFU); - filt_.glb[6] &= static_cast<std::uint8_t>(~0x80U & 0xFFU); - filt_.glb[7] &= static_cast<std::uint8_t>(~0x03U & 0xFFU); - } - else { - filt_.glb[0] |= 0xFEU; - filt_.glb[1] |= 0x03U; - filt_.glb[6] |= 0x80U; - filt_.glb[7] |= 0x03U; - } - break; - case QS_AO_RECORDS: - if (isRemove) { - filt_.glb[1] &= static_cast<std::uint8_t>(~0xFCU & 0xFFU); - filt_.glb[2] &= static_cast<std::uint8_t>(~0x07U & 0xFFU); - filt_.glb[5] &= static_cast<std::uint8_t>(~0x20U & 0xFFU); - } - else { - filt_.glb[1] |= 0xFCU; - filt_.glb[2] |= 0x07U; - filt_.glb[5] |= 0x20U; - } - break; - case QS_EQ_RECORDS: - if (isRemove) { - filt_.glb[2] &= static_cast<std::uint8_t>(~0x78U & 0xFFU); - filt_.glb[5] &= static_cast<std::uint8_t>(~0x40U & 0xFFU); - } - else { - filt_.glb[2] |= 0x78U; - filt_.glb[5] |= 0x40U; - } - break; - case QS_MP_RECORDS: - if (isRemove) { - filt_.glb[3] &= static_cast<std::uint8_t>(~0x03U & 0xFFU); - filt_.glb[5] &= static_cast<std::uint8_t>(~0x80U & 0xFFU); - } - else { - filt_.glb[3] |= 0x03U; - filt_.glb[5] |= 0x80U; - } - break; - case QS_QF_RECORDS: - if (isRemove) { - filt_.glb[2] &= static_cast<std::uint8_t>(~0x80U & 0xFFU); - filt_.glb[3] &= static_cast<std::uint8_t>(~0xFCU & 0xFFU); - filt_.glb[4] &= static_cast<std::uint8_t>(~0xC0U & 0xFFU); - filt_.glb[5] &= static_cast<std::uint8_t>(~0x1FU & 0xFFU); - } - else { - filt_.glb[2] |= 0x80U; - filt_.glb[3] |= 0xFCU; - filt_.glb[4] |= 0xC0U; - filt_.glb[5] |= 0x1FU; - } - break; - case QS_TE_RECORDS: - if (isRemove) { - filt_.glb[4] &= static_cast<std::uint8_t>(~0x3FU & 0xFFU); - } - else { - filt_.glb[4] |= 0x3FU; - } - break; - case QS_SC_RECORDS: - if (isRemove) { - filt_.glb[6] &= static_cast<std::uint8_t>(~0x3FU & 0xFFU); - } - else { - filt_.glb[6] |= 0x3FU; - } - break; - case QS_SEM_RECORDS: - if (isRemove) { - filt_.glb[8] &= static_cast<std::uint8_t>(~0x80U & 0xFFU); - filt_.glb[9] &= static_cast<std::uint8_t>(~0x07U & 0xFFU); - } - else { - filt_.glb[8] |= 0x80U; - filt_.glb[9] |= 0x07U; - } - break; - case QS_MTX_RECORDS: - if (isRemove) { - filt_.glb[9] &= static_cast<std::uint8_t>(~0xF8U & 0xFFU); - filt_.glb[10] &= static_cast<std::uint8_t>(~0x01U & 0xFFU); - } - else { - filt_.glb[9] |= 0xF8U; - filt_.glb[10] |= 0x01U; - } - break; - case QS_U0_RECORDS: - if (isRemove) { - filt_.glb[12] &= static_cast<std::uint8_t>(~0xF0U & 0xFFU); - filt_.glb[13] &= static_cast<std::uint8_t>(~0x01U & 0xFFU); - } - else { - filt_.glb[12] |= 0xF0U; - filt_.glb[13] |= 0x01U; - } - break; - case QS_U1_RECORDS: - if (isRemove) { - filt_.glb[13] &= static_cast<std::uint8_t>(~0x3EU & 0xFFU); - } - else { - filt_.glb[13] |= 0x3EU; - } - break; - case QS_U2_RECORDS: - if (isRemove) { - filt_.glb[13] &= static_cast<std::uint8_t>(~0xC0U & 0xFFU); - filt_.glb[14] &= static_cast<std::uint8_t>(~0x07U & 0xFFU); - } - else { - filt_.glb[13] |= 0xC0U; - filt_.glb[14] |= 0x07U; - } - break; - case QS_U3_RECORDS: - if (isRemove) { - filt_.glb[14] &= static_cast<std::uint8_t>(~0xF8U & 0xFFU); - } - else { - filt_.glb[14] |= 0xF8U; - } - break; - case QS_U4_RECORDS: - if (isRemove) { - filt_.glb[15] &= static_cast<std::uint8_t>(~0x1FU & 0xFFU); - } - else { - filt_.glb[15] |= 0x1FU; - } - break; - case QS_UA_RECORDS: - if (isRemove) { - filt_.glb[12] &= static_cast<std::uint8_t>(~0xF0U & 0xFFU); - filt_.glb[13] = 0U; - filt_.glb[14] = 0U; - filt_.glb[15] &= static_cast<std::uint8_t>(~0x1FU & 0xFFU); - } - else { - filt_.glb[12] |= 0xF0U; - filt_.glb[13] |= 0xFFU; - filt_.glb[14] |= 0xFFU; - filt_.glb[15] |= 0x1FU; - } - break; - default: { - QS_CRIT_STAT - QS_CRIT_ENTRY(); - // QS rec number must be below 0x7D, so no need for escaping - Q_ASSERT_INCRIT(210, rec < 0x7DU); - QS_CRIT_EXIT(); - - if (isRemove) { - filt_.glb[rec >> 3U] - &= static_cast<std::uint8_t>(~(1U << (rec & 7U)) & 0xFFU); - } - else { - filt_.glb[rec >> 3U] - |= static_cast<std::uint8_t>(1U << (rec & 7U)); - // never turn the last 3 records on (0x7D, 0x7E, 0x7F) - filt_.glb[15] &= 0x1FU; - } - break; - } - } -} - -//............................................................................ -void locFilter_(std::int_fast16_t const filter) noexcept { - bool const isRemove = (filter < 0); - std::uint16_t const qsId = isRemove - ? static_cast<std::uint16_t>(-filter) - : static_cast<std::uint16_t>(filter); - std::uint8_t const tmp = (isRemove ? 0x00U : 0xFFU); - std::uint_fast8_t i; - switch (qsId) { - case QS_ALL_IDS: - // set all local filters (partially unrolled loop) - for (i = 0U; i < Q_DIM(filt_.loc); i += 4U) { - filt_.loc[i ] = tmp; - filt_.loc[i + 1U] = tmp; - filt_.loc[i + 2U] = tmp; - filt_.loc[i + 3U] = tmp; - } - break; - case QS_AO_IDS: - for (i = 0U; i < 8U; i += 4U) { - filt_.loc[i ] = tmp; - filt_.loc[i + 1U] = tmp; - filt_.loc[i + 2U] = tmp; - filt_.loc[i + 3U] = tmp; - } - break; - case QS_EP_IDS: - i = 8U; - filt_.loc[i ] = tmp; - filt_.loc[i + 1U] = tmp; - break; - case QS_AP_IDS: - i = 12U; - filt_.loc[i ] = tmp; - filt_.loc[i + 1U] = tmp; - filt_.loc[i + 2U] = tmp; - filt_.loc[i + 3U] = tmp; - break; - default: { - QS_CRIT_STAT - QS_CRIT_ENTRY(); - // qsId must be in range - Q_ASSERT_INCRIT(310, qsId < 0x7FU); - QS_CRIT_EXIT(); - if (isRemove) { - filt_.loc[qsId >> 3U] &= - static_cast<std::uint8_t>( - ~(1U << (qsId & 7U)) & 0xFFU); - } - else { - filt_.loc[qsId >> 3U] - |= (1U << (qsId & 7U)); - } - break; - } - } - filt_.loc[0] |= 0x01U; // leave QS_ID == 0 always on -} - -//............................................................................ -void beginRec_(std::uint_fast8_t const rec) noexcept { - std::uint8_t const b = priv_.seq + 1U; - std::uint8_t chksum = 0U; // reset the checksum - std::uint8_t * const buf = priv_.buf; // put in a temporary (register) - QSCtr head = priv_.head; // put in a temporary (register) - QSCtr const end = priv_.end; // put in a temporary (register) - - priv_.seq = b; // store the incremented sequence num - priv_.used = (priv_.used + 2U); // 2 bytes about to be added - - QS_INSERT_ESC_BYTE_(b) - - chksum += static_cast<std::uint8_t>(rec); - QS_INSERT_BYTE_(static_cast<std::uint8_t>(rec)) // no need for escaping - - priv_.head = head; // save the head - priv_.chksum = chksum; // save the checksum -} - -//............................................................................ -void endRec_() noexcept { - std::uint8_t * const buf = priv_.buf; // put in a temporary (register) - QSCtr head = priv_.head; - QSCtr const end = priv_.end; - std::uint8_t b = priv_.chksum; - b ^= 0xFFU; // invert the bits in the checksum - - priv_.used = (priv_.used + 2U); // 2 bytes about to be added - - if ((b != QS_FRAME) && (b != QS_ESC)) { - QS_INSERT_BYTE_(b) - } - else { - QS_INSERT_BYTE_(QS_ESC) - QS_INSERT_BYTE_(b ^ QS_ESC_XOR) - priv_.used = (priv_.used + 1U); // account for the ESC byte - } - - QS_INSERT_BYTE_(QS_FRAME) // do not escape this QS_FRAME - - priv_.head = head; // save the head - if (priv_.used > end) { // overrun over the old data? - priv_.used = end; // the whole buffer is used - priv_.tail = head; // shift the tail to the old data - } -} - -//............................................................................ -void u8_raw_(std::uint8_t const d) noexcept { - std::uint8_t chksum = priv_.chksum; // put in a temporary (register) - std::uint8_t * const buf = priv_.buf; // put in a temporary (register) - QSCtr head = priv_.head; // put in a temporary (register) - QSCtr const end = priv_.end; // put in a temporary (register) - - priv_.used = (priv_.used + 1U); // 1 byte about to be added - QS_INSERT_ESC_BYTE_(d) - - priv_.head = head; // save the head - priv_.chksum = chksum; // save the checksum -} - -//............................................................................ -void u8u8_raw_( - std::uint8_t const d1, - std::uint8_t const d2) noexcept -{ - std::uint8_t chksum = priv_.chksum; // put in a temporary (register) - std::uint8_t * const buf = priv_.buf; // put in a temporary (register) - QSCtr head = priv_.head; // put in a temporary (register) - QSCtr const end = priv_.end; // put in a temporary (register) - - priv_.used = (priv_.used + 2U); // 2 bytes about to be added - QS_INSERT_ESC_BYTE_(d1) - QS_INSERT_ESC_BYTE_(d2) - - priv_.head = head; // save the head - priv_.chksum = chksum; // save the checksum -} - -//............................................................................ -void u16_raw_(std::uint16_t d) noexcept { - std::uint8_t b = static_cast<std::uint8_t>(d); - std::uint8_t chksum = priv_.chksum; // put in a temporary (register) - std::uint8_t * const buf = priv_.buf; // put in a temporary (register) - QSCtr head = priv_.head; // put in a temporary (register) - QSCtr const end = priv_.end; // put in a temporary (register) - - priv_.used = (priv_.used + 2U); // 2 bytes about to be added - - QS_INSERT_ESC_BYTE_(b) - - d >>= 8U; - b = static_cast<std::uint8_t>(d); - QS_INSERT_ESC_BYTE_(b) - - priv_.head = head; // save the head - priv_.chksum = chksum; // save the checksum -} - -//............................................................................ -void u32_raw_(std::uint32_t d) noexcept { - std::uint8_t chksum = priv_.chksum; // put in a temporary (register) - std::uint8_t * const buf = priv_.buf; // put in a temporary (register) - QSCtr head = priv_.head; // put in a temporary (register) - QSCtr const end = priv_.end; // put in a temporary (register) - - priv_.used = (priv_.used + 4U); // 4 bytes about to be added - for (std::uint_fast8_t i = 4U; i != 0U; --i) { - std::uint8_t const b = static_cast<std::uint8_t>(d); - QS_INSERT_ESC_BYTE_(b) - d >>= 8U; - } - - priv_.head = head; // save the head - priv_.chksum = chksum; // save the checksum -} - -//............................................................................ -void obj_raw_(void const * const obj) noexcept { - #if (QS_OBJ_PTR_SIZE == 1U) - u8_raw_(reinterpret_cast<std::uint8_t>(obj)); - #elif (QS_OBJ_PTR_SIZE == 2U) - u16_raw_(reinterpret_cast<std::uint16_t>(obj)); - #elif (QS_OBJ_PTR_SIZE == 4U) - u32_raw_(reinterpret_cast<std::uint32_t>(obj)); - #elif (QS_OBJ_PTR_SIZE == 8U) - u64_raw_(reinterpret_cast<std::uint64_t>(obj)); - #else - u32_raw_(reinterpret_cast<std::uint32_t>(obj)); - #endif -} - -//............................................................................ -void str_raw_(char const * s) noexcept { - std::uint8_t b = static_cast<std::uint8_t>(*s); - std::uint8_t chksum = priv_.chksum; // put in a temporary (register) - std::uint8_t * const buf = priv_.buf; // put in a temporary (register) - QSCtr head = priv_.head; // put in a temporary (register) - QSCtr const end = priv_.end; // put in a temporary (register) - QSCtr used = priv_.used; // put in a temporary (register) - - while (b != 0U) { - chksum += b; // update checksum - QS_INSERT_BYTE_(b) // ASCII characters don't need escaping - ++s; - b = static_cast<std::uint8_t>(*s); - ++used; - } - QS_INSERT_BYTE_(0U) // zero-terminate the string - ++used; - - priv_.head = head; // save the head - priv_.chksum = chksum; // save the checksum - priv_.used = used; // save # of used buffer space -} - -//............................................................................ -void u8_fmt_( - std::uint8_t const format, - std::uint8_t const d) noexcept -{ - std::uint8_t chksum = priv_.chksum; // put in a temporary (register) - std::uint8_t *const buf = priv_.buf; // put in a temporary (register) - QSCtr head = priv_.head; // put in a temporary (register) - QSCtr const end = priv_.end; // put in a temporary (register) - - priv_.used = (priv_.used + 2U); // 2 bytes about to be added - - QS_INSERT_ESC_BYTE_(format) - QS_INSERT_ESC_BYTE_(d) - - priv_.head = head; // save the head - priv_.chksum = chksum; // save the checksum -} - -//............................................................................ -void u16_fmt_( - std::uint8_t format, - std::uint16_t d) noexcept -{ - std::uint8_t chksum = priv_.chksum; // put in a temporary (register) - std::uint8_t * const buf = priv_.buf; // put in a temporary (register) - QSCtr head = priv_.head; // put in a temporary (register) - QSCtr const end = priv_.end; // put in a temporary (register) - - priv_.used = (priv_.used + 3U); // 3 bytes about to be added - - QS_INSERT_ESC_BYTE_(format) - - format = static_cast<std::uint8_t>(d); - QS_INSERT_ESC_BYTE_(format) - - d >>= 8U; - format = static_cast<std::uint8_t>(d); - QS_INSERT_ESC_BYTE_(format) - - priv_.head = head; // save the head - priv_.chksum = chksum; // save the checksum -} - -//............................................................................ -void u32_fmt_( - std::uint8_t format, - std::uint32_t d) noexcept -{ - std::uint8_t chksum = priv_.chksum; // put in a temporary (register) - std::uint8_t * const buf = priv_.buf; // put in a temporary (register) - QSCtr head = priv_.head; // put in a temporary (register) - QSCtr const end = priv_.end; // put in a temporary (register) - - priv_.used = (priv_.used + 5U); // 5 bytes about to be added - QS_INSERT_ESC_BYTE_(format) // insert the format byte - - for (std::uint_fast8_t i = 4U; i != 0U; --i) { - format = static_cast<std::uint8_t>(d); - QS_INSERT_ESC_BYTE_(format) - d >>= 8U; - } - - priv_.head = head; // save the head - priv_.chksum = chksum; // save the checksum -} - -//............................................................................ -void str_fmt_(char const * s) noexcept { - std::uint8_t b = static_cast<std::uint8_t>(*s); - std::uint8_t chksum = static_cast<std::uint8_t>( - priv_.chksum + static_cast<std::uint8_t>(STR_T)); - std::uint8_t * const buf = priv_.buf; // put in a temporary (register) - QSCtr head = priv_.head; // put in a temporary (register) - QSCtr const end = priv_.end; // put in a temporary (register) - QSCtr used = priv_.used; // put in a temporary (register) - - used += 2U; // the format byte and the terminating-0 - - QS_INSERT_BYTE_(static_cast<std::uint8_t>(STR_T)) - while (b != 0U) { - // ASCII characters don't need escaping - chksum += b; // update checksum - QS_INSERT_BYTE_(b) - ++s; - b = static_cast<std::uint8_t>(*s); - ++used; - } - QS_INSERT_BYTE_(0U) // zero-terminate the string - - priv_.head = head; // save the head - priv_.chksum = chksum; // save the checksum - priv_.used = used; // save # of used buffer space -} - -//............................................................................ -void mem_fmt_( - std::uint8_t const * blk, - std::uint8_t size) noexcept -{ - std::uint8_t b = static_cast<std::uint8_t>(MEM_T); - std::uint8_t chksum = priv_.chksum + b; - std::uint8_t * const buf = priv_.buf; // put in a temporary (register) - QSCtr head = priv_.head; // put in a temporary (register) - QSCtr const end = priv_.end; // put in a temporary (register) - - priv_.used = (priv_.used + size + 2U); // size+2 bytes to be added - - QS_INSERT_BYTE_(b) - QS_INSERT_ESC_BYTE_(size) - - // output the 'size' number of bytes - for (; size != 0U; --size) { - b = *blk; - QS_INSERT_ESC_BYTE_(b) - ++blk; - } - - priv_.head = head; // save the head - priv_.chksum = chksum; // save the checksum -} - -//............................................................................ -void sig_dict_pre_( - QSignal const sig, - void const * const obj, - char const * const name) noexcept -{ - QS_CRIT_STAT - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - - beginRec_(static_cast<std::uint_fast8_t>(QS_SIG_DICT)); - QS_SIG_PRE_(sig); - QS_OBJ_PRE_(obj); - QS_STR_PRE_((*name == '&') ? &name[1] : name); - endRec_(); - - QS_MEM_APP(); - QS_CRIT_EXIT(); - onFlush(); -} - -//............................................................................ -void obj_dict_pre_( - void const * const obj, - char const * const name) noexcept -{ - QS_CRIT_STAT - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - - beginRec_(static_cast<std::uint_fast8_t>(QS_OBJ_DICT)); - QS_OBJ_PRE_(obj); - QS_STR_PRE_((*name == '&') ? &name[1] : name); - endRec_(); - - QS_MEM_APP(); - QS_CRIT_EXIT(); - onFlush(); -} - -//............................................................................ -void obj_arr_dict_pre_( - void const * const obj, - std::uint_fast16_t const idx, - char const * const name) noexcept -{ - QS_CRIT_STAT - QS_CRIT_ENTRY(); - Q_REQUIRE_INCRIT(400, idx < 1000U); - QS_CRIT_EXIT(); - - // format idx into a char buffer as "xxx\0" - std::uint8_t idx_str[4]; - std::uint_fast16_t tmp = idx; - std::uint8_t i; - idx_str[3] = 0U; // zero-terminate - idx_str[2] = static_cast<std::uint8_t>( - static_cast<std::uint8_t>('0') + (tmp % 10U)); - tmp /= 10U; - idx_str[1] = static_cast<std::uint8_t>( - static_cast<std::uint8_t>('0') + (tmp % 10U)); - if (idx_str[1] == static_cast<std::uint8_t>('0')) { - i = 2U; - } - else { - tmp /= 10U; - idx_str[0] = static_cast<std::uint8_t>( - static_cast<std::uint8_t>('0') + (tmp % 10U)); - if (idx_str[0] == static_cast<std::uint8_t>('0')) { - i = 1U; - } - else { - i = 0U; - } - } - - std::uint8_t j = ((*name == '&') ? 1U : 0U); - - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - - beginRec_(static_cast<std::uint_fast8_t>(QS_OBJ_DICT)); - QS_OBJ_PRE_(obj); - for (; name[j] != '\0'; ++j) { - QS_U8_PRE_(name[j]); - if (name[j] == '[') { - ++j; - break; - } - } - for (; idx_str[i] != 0U; ++i) { - QS_U8_PRE_(idx_str[i]); - } - // skip chars until ']' - for (; name[j] != '\0'; ++j) { - if (name[j] == ']') { - break; - } - } - for (; name[j] != '\0'; ++j) { - QS_U8_PRE_(name[j]); - } - QS_U8_PRE_(0U); // zero-terminate - endRec_(); - - QS_MEM_APP(); - QS_CRIT_EXIT(); - onFlush(); -} - -//............................................................................ -void fun_dict_pre_( - QSpyFunPtr fun, - char const * const name) noexcept -{ - QS_CRIT_STAT - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - - beginRec_(static_cast<std::uint_fast8_t>(QS_FUN_DICT)); - QS_FUN_PRE_(fun); - QS_STR_PRE_((*name == '&') ? &name[1] : name); - endRec_(); - - QS_MEM_APP(); - QS_CRIT_EXIT(); - onFlush(); -} - -//............................................................................ -void usr_dict_pre_( - enum_t const rec, - char const * const name) noexcept -{ - QS_CRIT_STAT - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - - beginRec_(static_cast<std::uint_fast8_t>(QS_USR_DICT)); - QS_U8_PRE_(rec); - QS_STR_PRE_(name); - endRec_(); - - QS_MEM_APP(); - QS_CRIT_EXIT(); - onFlush(); -} - -//............................................................................ -void enum_dict_pre_( - enum_t const value, - std::uint8_t const group, - char const * const name) noexcept -{ - QS_CRIT_STAT - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - - beginRec_(static_cast<std::uint_fast8_t>(QS_ENUM_DICT)); - QS_2U8_PRE_(static_cast<std::uint8_t>(value), group); - QS_STR_PRE_(name); - endRec_(); - - QS_MEM_APP(); - QS_CRIT_EXIT(); - onFlush(); -} - -//............................................................................ -void assertion_pre_( - char const * const module, - int_t const id, - std::uint32_t const delay) noexcept -{ - // NOTE: called in a critical section - - beginRec_(static_cast<std::uint_fast8_t>(QS_ASSERT_FAIL)); - QS_TIME_PRE_(); - QS_U16_PRE_(id); - QS_STR_PRE_((module != nullptr) ? module : "?"); - endRec_(); - onFlush(); - - // busy-wait until all QS data makes it over to the host - for (std::uint32_t volatile ctr = delay; ctr > 0U; ) { - ctr = (ctr - 1U); - } - QS::onCleanup(); -} - -//............................................................................ -void crit_entry_pre_() noexcept { - beginRec_(static_cast<std::uint_fast8_t>(QS_QF_CRIT_ENTRY)); - QS_TIME_PRE_(); - priv_.critNest = (priv_.critNest + 1U); - QS_U8_PRE_(priv_.critNest); - endRec_(); -} - -//............................................................................ -void crit_exit_pre_() noexcept { - beginRec_(static_cast<std::uint_fast8_t>(QS_QF_CRIT_EXIT)); - QS_TIME_PRE_(); - QS_U8_PRE_(QS::priv_.critNest); - priv_.critNest = (priv_.critNest - 1U); - endRec_(); -} - -//............................................................................ -void isr_entry_pre_( - std::uint8_t const isrnest, - std::uint8_t const prio) noexcept -{ - beginRec_(static_cast<std::uint_fast8_t>(QS_QF_ISR_ENTRY)); - QS_TIME_PRE_(); - QS_U8_PRE_(isrnest); - QS_U8_PRE_(prio); - endRec_(); -} - -//............................................................................ -void isr_exit_pre_( - std::uint8_t const isrnest, - std::uint8_t const prio) noexcept -{ - beginRec_(static_cast<std::uint_fast8_t>(QS_QF_ISR_EXIT)); - QS_TIME_PRE_(); - QS_U8_PRE_(isrnest); - QS_U8_PRE_(prio); - endRec_(); -} - -//............................................................................ -void target_info_pre_(std::uint8_t const isReset) { - // NOTE: called in a critical section - - static constexpr std::uint8_t ZERO = static_cast<std::uint8_t>('0'); - static std::uint8_t const * const TIME = - reinterpret_cast<std::uint8_t const *>(&BUILD_TIME[0]); - static std::uint8_t const * const DATE = - reinterpret_cast<std::uint8_t const *>(&BUILD_DATE[0]); - - beginRec_(static_cast<std::uint_fast8_t>(QS_TARGET_INFO)); - u8_raw_(isReset); - - static union { - std::uint16_t u16; - std::uint8_t u8[2]; - } endian_test; - endian_test.u16 = 0x0102U; - // big endian ? add the 0x8000U flag - QS_U16_PRE_(((endian_test.u8[0] == 0x01U) - ? (0x8000U | QP_VERSION) - : QP_VERSION)); // target endianness + version number - - // send the object sizes... - u8_raw_(Q_SIGNAL_SIZE - | static_cast<std::uint8_t>(QF_EVENT_SIZ_SIZE << 4U)); - -#ifdef QF_EQUEUE_CTR_SIZE - u8_raw_(QF_EQUEUE_CTR_SIZE - | static_cast<std::uint8_t>(QF_TIMEEVT_CTR_SIZE << 4U)); -#else - QS::u8_raw_(static_cast<std::uint8_t>(QF_TIMEEVT_CTR_SIZE << 4U)); -#endif // ifdef QF_EQUEUE_CTR_SIZE - -#ifdef QF_MPOOL_CTR_SIZE - QS::u8_raw_(QF_MPOOL_SIZ_SIZE - | static_cast<std::uint8_t>(QF_MPOOL_CTR_SIZE << 4U)); -#else - QS::u8_raw_(0U); -#endif // ifdef QF_MPOOL_CTR_SIZE - - QS::u8_raw_(QS_OBJ_PTR_SIZE | (QS_FUN_PTR_SIZE << 4U)); - QS::u8_raw_(QS_TIME_SIZE); - - // send the bounds... - QS::u8_raw_(QF_MAX_ACTIVE); - QS::u8_raw_(QF_MAX_EPOOL | (QF_MAX_TICK_RATE << 4U)); - - // send the build time in three bytes (sec, min, hour)... - QS::u8_raw_((10U * (TIME[6] - ZERO)) + (TIME[7] - ZERO)); - QS::u8_raw_((10U * (TIME[3] - ZERO)) + (TIME[4] - ZERO)); - if (BUILD_TIME[0] == static_cast<std::uint8_t>(' ')) { - QS::u8_raw_(TIME[1] - ZERO); - } - else { - QS::u8_raw_((10U * (TIME[0] - ZERO)) + (TIME[1] - ZERO)); - } - - // send the build date in three bytes (day, month, year) ... - if (BUILD_DATE[4] == static_cast<std::uint8_t>(' ')) { - QS::u8_raw_(DATE[5] - ZERO); - } - else { - QS::u8_raw_((10U * (DATE[4] - ZERO)) + (DATE[5] - ZERO)); - } - // convert the 3-letter month to a number 1-12 ... - std::uint8_t b; - switch (DATE[0] + DATE[1] + DATE[2]) { - case 'J' + 'a' +'n': - b = 1U; - break; - case 'F' + 'e' + 'b': - b = 2U; - break; - case 'M' + 'a' +'r': - b = 3U; - break; - case 'A' + 'p' + 'r': - b = 4U; - break; - case 'M' + 'a' + 'y': - b = 5U; - break; - case 'J' + 'u' + 'n': - b = 6U; - break; - case 'J' + 'u' + 'l': - b = 7U; - break; - case 'A' + 'u' + 'g': - b = 8U; - break; - case 'S' + 'e' + 'p': - b = 9U; - break; - case 'O' + 'c' + 't': - b = 10U; - break; - case 'N' + 'o' + 'v': - b = 11U; - break; - case 'D' + 'e' + 'c': - b = 12U; - break; - default: - b = 0U; - break; - } - QS::u8_raw_(b); // store the month - QS::u8_raw_((10U * (DATE[9] - ZERO)) + (DATE[10] - ZERO)); - QS::endRec_(); -} - -} // namespace QS -} // namespace QP - -//! @endcond - - - - #define QP_IMPL // this is QF/QK implementation -#include "qs_port.hpp" // QS port -#include "qs_pkg.hpp" // QS package-scope internal interface - -//============================================================================ -//! @cond INTERNAL - -namespace QP { -namespace QS { - -//${QS::QS-tx-64bit::u64_raw_} ............................................... -void u64_raw_(std::uint64_t d) noexcept { - std::uint8_t chksum = priv_.chksum; - std::uint8_t * const buf = priv_.buf; - QSCtr head = priv_.head; - QSCtr const end = priv_.end; - - priv_.used = (priv_.used + 8U); // 8 bytes are about to be added - for (std::int_fast8_t i = 8U; i != 0U; --i) { - std::uint8_t const b = static_cast<std::uint8_t>(d); - QS_INSERT_ESC_BYTE_(b) - d >>= 8U; - } - - priv_.head = head; // save the head - priv_.chksum = chksum; // save the checksum -} - -//${QS::QS-tx-64bit::u64_fmt_} ............................................... -void u64_fmt_( - std::uint8_t format, - std::uint64_t d) noexcept -{ - std::uint8_t chksum = priv_.chksum; - std::uint8_t * const buf = priv_.buf; - QSCtr head = priv_.head; - QSCtr const end = priv_.end; - - priv_.used = (priv_.used + 9U); // 9 bytes are about to be added - QS_INSERT_ESC_BYTE_(format) // insert the format byte - - for (std::int_fast8_t i = 8U; i != 0U; --i) { - format = static_cast<std::uint8_t>(d); - QS_INSERT_ESC_BYTE_(format) - d >>= 8U; - } - - priv_.head = head; // save the head - priv_.chksum = chksum; // save the checksum -} - -} // namespace QS -} // namespace QP - -//! @endcond - - - - #define QP_IMPL // this is QF/QK implementation -#include "qs_port.hpp" // QS port -#include "qs_pkg.hpp" // QS package-scope internal interface - -//============================================================================ -//! @cond INTERNAL - -namespace QP { -namespace QS { - -//${QS::QS-tx-fp::f32_fmt_} .................................................. -void f32_fmt_( - std::uint8_t format, - float32_t f) noexcept -{ - union F32Rep { - float32_t f; - std::uint32_t u; - } fu32; // the internal binary representation - std::uint8_t chksum = priv_.chksum; // put in a temporary (register) - std::uint8_t * const buf = priv_.buf; // put in a temporary (register) - QSCtr head = priv_.head; // put in a temporary (register) - QSCtr const end = priv_.end; // put in a temporary (register) - - fu32.f = f; // assign the binary representation - - priv_.used = (priv_.used + 5U); // 5 bytes about to be added - QS_INSERT_ESC_BYTE_(format) // insert the format byte - - for (std::uint_fast8_t i = 4U; i != 0U; --i) { - format = static_cast<std::uint8_t>(fu32.u); - QS_INSERT_ESC_BYTE_(format) - fu32.u >>= 8U; - } - - priv_.head = head; // save the head - priv_.chksum = chksum; // save the checksum -} - -//${QS::QS-tx-fp::f64_fmt_} .................................................. -void f64_fmt_( - std::uint8_t format, - float64_t d) noexcept -{ - union F64Rep { - float64_t d; - std::uint32_t u[2]; - } fu64; // the internal binary representation - std::uint8_t chksum = priv_.chksum; - std::uint8_t * const buf = priv_.buf; - QSCtr head = priv_.head; - QSCtr const end = priv_.end; - std::uint32_t i; - // static constant untion to detect endianness of the machine - static union U32Rep { - std::uint32_t u32; - std::uint8_t u8; - } const endian = { 1U }; - - fu64.d = d; // assign the binary representation - - // is this a big-endian machine? - if (endian.u8 == 0U) { - // swap fu64.u[0] <-> fu64.u[1]... - i = fu64.u[0]; - fu64.u[0] = fu64.u[1]; - fu64.u[1] = i; - } - - priv_.used = (priv_.used + 9U); // 9 bytes about to be added - QS_INSERT_ESC_BYTE_(format) // insert the format byte - - // output 4 bytes from fu64.u[0]... - for (i = 4U; i != 0U; --i) { - QS_INSERT_ESC_BYTE_(static_cast<std::uint8_t>(fu64.u[0])) - fu64.u[0] >>= 8U; - } - - // output 4 bytes from fu64.u[1]... - for (i = 4U; i != 0U; --i) { - QS_INSERT_ESC_BYTE_(static_cast<std::uint8_t>(fu64.u[1])) - fu64.u[1] >>= 8U; - } - - priv_.head = head; // update the head - priv_.chksum = chksum; // update the checksum -} - -} // namespace QS -} // namespace QP - -//! @endcond - - - - #define QP_IMPL // this is QP implementation -#include "qs_port.hpp" // QS port -#include "qs_pkg.hpp" // QS package-scope internal interface -#include "qp_pkg.hpp" // QP package-scope interface -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem - -//============================================================================ -//! @cond INTERNAL - -namespace { // unnamed local namespace - -Q_DEFINE_THIS_MODULE("qs_rx") - -enum RxStateEnum : std::uint8_t { - ERROR_STATE, - WAIT4_SEQ, - WAIT4_REC, - WAIT4_INFO_FRAME, - WAIT4_CMD_ID, - WAIT4_CMD_PARAM1, - WAIT4_CMD_PARAM2, - WAIT4_CMD_PARAM3, - WAIT4_CMD_FRAME, - WAIT4_RESET_FRAME, - WAIT4_TICK_RATE, - WAIT4_TICK_FRAME, - WAIT4_PEEK_OFFS, - WAIT4_PEEK_SIZE, - WAIT4_PEEK_NUM, - WAIT4_PEEK_FRAME, - WAIT4_POKE_OFFS, - WAIT4_POKE_SIZE, - WAIT4_POKE_NUM, - WAIT4_POKE_DATA, - WAIT4_POKE_FRAME, - WAIT4_FILL_DATA, - WAIT4_FILL_FRAME, - WAIT4_FILTER_LEN, - WAIT4_FILTER_DATA, - WAIT4_FILTER_FRAME, - WAIT4_OBJ_KIND, - WAIT4_OBJ_ADDR, - WAIT4_OBJ_FRAME, - WAIT4_QUERY_KIND, - WAIT4_QUERY_FRAME, - WAIT4_EVT_PRIO, - WAIT4_EVT_SIG, - WAIT4_EVT_LEN, - WAIT4_EVT_PAR, - WAIT4_EVT_FRAME - -#ifdef Q_UTEST - , - WAIT4_TEST_SETUP_FRAME, - WAIT4_TEST_TEARDOWN_FRAME, - WAIT4_TEST_PROBE_DATA, - WAIT4_TEST_PROBE_ADDR, - WAIT4_TEST_PROBE_FRAME, - WAIT4_TEST_CONTINUE_FRAME -#endif // Q_UTEST -}; - -// internal helper functions... -static void rxParseData_(std::uint8_t const b) noexcept; -static void rxHandleGoodFrame_(std::uint8_t const state); -static void rxHandleBadFrame_(std::uint8_t const state) noexcept; -static void rxReportAck_(enum QP::QSpyRxRecords const recId) noexcept; -static void rxReportError_(std::uint8_t const code) noexcept; -static void rxReportDone_(enum QP::QSpyRxRecords const recId) noexcept; -static void queryCurrObj_(std::uint8_t obj_kind) noexcept; -static void rxPoke_() noexcept; - -// Internal QS-RX function to take a tran. in the QS-RX FSM -static inline void tran_(RxStateEnum const target) noexcept { - QP::QS::rxPriv_.state = static_cast<std::uint8_t>(target); -} - -} // unnamed namespace - -#ifndef QF_MEM_ISOLATE -namespace QP { -namespace QS { -RxAttr rxPriv_; -} // namespace QS -} // namespace QP -#endif // QF_MEM_ISOLATE - -//! @endcond -//============================================================================ - -$define ${QS::QS-RX} - -//============================================================================ -//! @cond INTERNAL -namespace { // unnamed local namespace - -//............................................................................ -static void rxParseData_(std::uint8_t const b) noexcept { - switch (QP::QS::rxPriv_.state) { - case WAIT4_SEQ: { - ++QP::QS::rxPriv_.seq; - if (QP::QS::rxPriv_.seq != b) { // not the expected sequence? - rxReportError_(0x42U); - QP::QS::rxPriv_.seq = b; // update the sequence - } - tran_(WAIT4_REC); - break; - } - case WAIT4_REC: { - switch (b) { - case QP::QS_RX_INFO: - tran_(WAIT4_INFO_FRAME); - break; - case QP::QS_RX_COMMAND: - tran_(WAIT4_CMD_ID); - break; - case QP::QS_RX_RESET: - tran_(WAIT4_RESET_FRAME); - break; - case QP::QS_RX_TICK: - tran_(WAIT4_TICK_RATE); - break; - case QP::QS_RX_PEEK: - if (QP::QS::rxPriv_.currObj[QP::QS::AP_OBJ] != nullptr) { - QP::QS::rxPriv_.var.peek.offs = 0U; - QP::QS::rxPriv_.var.peek.idx = 0U; - tran_(WAIT4_PEEK_OFFS); - } - else { - rxReportError_( - static_cast<std::uint8_t>(QP::QS_RX_PEEK)); - tran_(ERROR_STATE); - } - break; - case QP::QS_RX_POKE: - case QP::QS_RX_FILL: - QP::QS::rxPriv_.var.poke.fill = - (b == static_cast<std::uint8_t>(QP::QS_RX_FILL)) - ? 1U : 0U; - if (QP::QS::rxPriv_.currObj[QP::QS::AP_OBJ] != nullptr) { - QP::QS::rxPriv_.var.poke.offs = 0U; - QP::QS::rxPriv_.var.poke.idx = 0U; - tran_(WAIT4_POKE_OFFS); - } - else { - rxReportError_( - (QP::QS::rxPriv_.var.poke.fill != 0U) - ? static_cast<std::uint8_t>(QP::QS_RX_FILL) - : static_cast<std::uint8_t>(QP::QS_RX_POKE)); - tran_(ERROR_STATE); - } - break; - case QP::QS_RX_GLB_FILTER: // intentionally fall-through - case QP::QS_RX_LOC_FILTER: - QP::QS::rxPriv_.var.flt.recId = b; - tran_(WAIT4_FILTER_LEN); - break; - case QP::QS_RX_AO_FILTER: // intentionally fall-through - case QP::QS_RX_CURR_OBJ: - QP::QS::rxPriv_.var.obj.recId = b; - tran_(WAIT4_OBJ_KIND); - break; - case QP::QS_RX_QUERY_CURR: - QP::QS::rxPriv_.var.obj.recId = - static_cast<std::uint8_t>(QP::QS_RX_QUERY_CURR); - tran_(WAIT4_QUERY_KIND); - break; - case QP::QS_RX_EVENT: - tran_(WAIT4_EVT_PRIO); - break; - -#ifdef Q_UTEST - case QP::QS_RX_TEST_SETUP: - tran_(WAIT4_TEST_SETUP_FRAME); - break; - case QP::QS_RX_TEST_TEARDOWN: - tran_(WAIT4_TEST_TEARDOWN_FRAME); - break; - case QP::QS_RX_TEST_CONTINUE: - tran_(WAIT4_TEST_CONTINUE_FRAME); - break; - case QP::QS_RX_TEST_PROBE: - if (QP::QS::tstPriv_.tpNum - < static_cast<std::uint8_t>( - (sizeof(QP::QS::tstPriv_.tpBuf) - / sizeof(QP::QS::tstPriv_.tpBuf[0])))) - { - QP::QS::rxPriv_.var.tp.data = 0U; - QP::QS::rxPriv_.var.tp.idx = 0U; - tran_(WAIT4_TEST_PROBE_DATA); - } - else { // the # Test-Probes exceeded - rxReportError_( - static_cast<std::uint8_t>(QP::QS_RX_TEST_PROBE)); - tran_(ERROR_STATE); - } - break; -#endif // Q_UTEST - - default: - rxReportError_(0x43U); - tran_(ERROR_STATE); - break; - } - break; - } - case WAIT4_INFO_FRAME: { - // keep ignoring the data until a frame is collected - break; - } - case WAIT4_CMD_ID: { - QP::QS::rxPriv_.var.cmd.cmdId = b; - QP::QS::rxPriv_.var.cmd.idx = 0U; - QP::QS::rxPriv_.var.cmd.param1 = 0U; - QP::QS::rxPriv_.var.cmd.param2 = 0U; - QP::QS::rxPriv_.var.cmd.param3 = 0U; - tran_(WAIT4_CMD_PARAM1); - break; - } - case WAIT4_CMD_PARAM1: { - QP::QS::rxPriv_.var.cmd.param1 |= - (static_cast<std::uint32_t>(b) << QP::QS::rxPriv_.var.cmd.idx); - QP::QS::rxPriv_.var.cmd.idx += 8U; - if (QP::QS::rxPriv_.var.cmd.idx == (8U * 4U)) { - QP::QS::rxPriv_.var.cmd.idx = 0U; - tran_(WAIT4_CMD_PARAM2); - } - break; - } - case WAIT4_CMD_PARAM2: { - QP::QS::rxPriv_.var.cmd.param2 |= - static_cast<std::uint32_t>(b) << QP::QS::rxPriv_.var.cmd.idx; - QP::QS::rxPriv_.var.cmd.idx += 8U; - if (QP::QS::rxPriv_.var.cmd.idx == (8U * 4U)) { - QP::QS::rxPriv_.var.cmd.idx = 0U; - tran_(WAIT4_CMD_PARAM3); - } - break; - } - case WAIT4_CMD_PARAM3: { - QP::QS::rxPriv_.var.cmd.param3 |= - static_cast<std::uint32_t>(b) << QP::QS::rxPriv_.var.cmd.idx; - QP::QS::rxPriv_.var.cmd.idx += 8U; - if (QP::QS::rxPriv_.var.cmd.idx == (8U * 4U)) { - QP::QS::rxPriv_.var.cmd.idx = 0U; - tran_(WAIT4_CMD_FRAME); - } - break; - } - case WAIT4_CMD_FRAME: { - // keep ignoring the data until a frame is collected - break; - } - case WAIT4_RESET_FRAME: { - // keep ignoring the data until a frame is collected - break; - } - case WAIT4_TICK_RATE: { - QP::QS::rxPriv_.var.tick.rate = static_cast<std::uint_fast8_t>(b); - tran_(WAIT4_TICK_FRAME); - break; - } - case WAIT4_TICK_FRAME: { - // keep ignoring the data until a frame is collected - break; - } - case WAIT4_PEEK_OFFS: { - if (QP::QS::rxPriv_.var.peek.idx == 0U) { - QP::QS::rxPriv_.var.peek.offs = static_cast<std::uint16_t>(b); - QP::QS::rxPriv_.var.peek.idx += 8U; - } - else { - QP::QS::rxPriv_.var.peek.offs |= static_cast<std::uint16_t>( - static_cast<std::uint16_t>(b) << 8U); - tran_(WAIT4_PEEK_SIZE); - } - break; - } - case WAIT4_PEEK_SIZE: { - if ((b == 1U) || (b == 2U) || (b == 4U)) { - QP::QS::rxPriv_.var.peek.size = b; - tran_(WAIT4_PEEK_NUM); - } - else { - rxReportError_(static_cast<std::uint8_t>(QP::QS_RX_PEEK)); - tran_(ERROR_STATE); - } - break; - } - case WAIT4_PEEK_NUM: { - QP::QS::rxPriv_.var.peek.num = b; - tran_(WAIT4_PEEK_FRAME); - break; - } - case WAIT4_PEEK_FRAME: { - // keep ignoring the data until a frame is collected - break; - } - case WAIT4_POKE_OFFS: { - if (QP::QS::rxPriv_.var.poke.idx == 0U) { - QP::QS::rxPriv_.var.poke.offs = static_cast<std::uint16_t>(b); - QP::QS::rxPriv_.var.poke.idx = 1U; - } - else { - QP::QS::rxPriv_.var.poke.offs |= static_cast<std::uint16_t>( - static_cast<std::uint16_t>(b) << 8U); - tran_(WAIT4_POKE_SIZE); - } - break; - } - case WAIT4_POKE_SIZE: { - if ((b == 1U) || (b == 2U) || (b == 4U)) { - QP::QS::rxPriv_.var.poke.size = b; - tran_(WAIT4_POKE_NUM); - } - else { - rxReportError_((QP::QS::rxPriv_.var.poke.fill != 0U) - ? static_cast<std::uint8_t>(QP::QS_RX_FILL) - : static_cast<std::uint8_t>(QP::QS_RX_POKE)); - tran_(ERROR_STATE); - } - break; - } - case WAIT4_POKE_NUM: { - if (b > 0U) { - QP::QS::rxPriv_.var.poke.num = b; - QP::QS::rxPriv_.var.poke.data = 0U; - QP::QS::rxPriv_.var.poke.idx = 0U; - tran_((QP::QS::rxPriv_.var.poke.fill != 0U) - ? WAIT4_FILL_DATA - : WAIT4_POKE_DATA); - } - else { - rxReportError_((QP::QS::rxPriv_.var.poke.fill != 0U) - ? static_cast<std::uint8_t>(QP::QS_RX_FILL) - : static_cast<std::uint8_t>(QP::QS_RX_POKE)); - tran_(ERROR_STATE); - } - break; - } - case WAIT4_FILL_DATA: { - QP::QS::rxPriv_.var.poke.data |= - static_cast<std::uint32_t>(b) << QP::QS::rxPriv_.var.poke.idx; - QP::QS::rxPriv_.var.poke.idx += 8U; - if ((QP::QS::rxPriv_.var.poke.idx >> 3U) == QP::QS::rxPriv_.var.poke.size) { - tran_(WAIT4_FILL_FRAME); - } - break; - } - case WAIT4_POKE_DATA: { - QP::QS::rxPriv_.var.poke.data |= - static_cast<std::uint32_t>(b) << QP::QS::rxPriv_.var.poke.idx; - QP::QS::rxPriv_.var.poke.idx += 8U; - if ((QP::QS::rxPriv_.var.poke.idx >> 3U) == QP::QS::rxPriv_.var.poke.size) { - rxPoke_(); - --QP::QS::rxPriv_.var.poke.num; - if (QP::QS::rxPriv_.var.poke.num == 0U) { - tran_(WAIT4_POKE_FRAME); - } - } - break; - } - case WAIT4_FILL_FRAME: { - // keep ignoring the data until a frame is collected - break; - } - case WAIT4_POKE_FRAME: { - // keep ignoring the data until a frame is collected - break; - } - case WAIT4_FILTER_LEN: { - if (b == static_cast<std::uint8_t>(sizeof(QP::QS::rxPriv_.var.flt.data))) { - QP::QS::rxPriv_.var.flt.idx = 0U; - tran_(WAIT4_FILTER_DATA); - } - else { - rxReportError_(QP::QS::rxPriv_.var.flt.recId); - tran_(ERROR_STATE); - } - break; - } - case WAIT4_FILTER_DATA: { - QP::QS::rxPriv_.var.flt.data[QP::QS::rxPriv_.var.flt.idx] = b; - ++QP::QS::rxPriv_.var.flt.idx; - if (QP::QS::rxPriv_.var.flt.idx == sizeof(QP::QS::rxPriv_.var.flt.data)) { - tran_(WAIT4_FILTER_FRAME); - } - break; - } - case WAIT4_FILTER_FRAME: { - // keep ignoring the data until a frame is collected - break; - } - case WAIT4_OBJ_KIND: { - if (b <= static_cast<std::uint8_t>(QP::QS::SM_AO_OBJ)) { - QP::QS::rxPriv_.var.obj.kind = b; - QP::QS::rxPriv_.var.obj.addr = 0U; - QP::QS::rxPriv_.var.obj.idx = 0U; - tran_(WAIT4_OBJ_ADDR); - } - else { - rxReportError_(QP::QS::rxPriv_.var.obj.recId); - tran_(ERROR_STATE); - } - break; - } - case WAIT4_OBJ_ADDR: { - QP::QS::rxPriv_.var.obj.addr |= - static_cast<QP::QSObj>(b) << QP::QS::rxPriv_.var.obj.idx; - QP::QS::rxPriv_.var.obj.idx += 8U; - if (QP::QS::rxPriv_.var.obj.idx - == (8U * static_cast<unsigned>(QS_OBJ_PTR_SIZE))) - { - tran_(WAIT4_OBJ_FRAME); - } - break; - } - case WAIT4_OBJ_FRAME: { - // keep ignoring the data until a frame is collected - break; - } - case WAIT4_QUERY_KIND: { - if (b < static_cast<std::uint8_t>(QP::QS::MAX_OBJ)) { - QP::QS::rxPriv_.var.obj.kind = b; - tran_(WAIT4_QUERY_FRAME); - } - else { - rxReportError_(QP::QS::rxPriv_.var.obj.recId); - tran_(ERROR_STATE); - } - break; - } - case WAIT4_QUERY_FRAME: { - // keep ignoring the data until a frame is collected - break; - } - case WAIT4_EVT_PRIO: { - QP::QS::rxPriv_.var.evt.prio = b; - QP::QS::rxPriv_.var.evt.sig = 0U; - QP::QS::rxPriv_.var.evt.idx = 0U; - tran_(WAIT4_EVT_SIG); - break; - } - case WAIT4_EVT_SIG: { - QP::QS::rxPriv_.var.evt.sig |= static_cast<QP::QSignal>( - static_cast<std::uint32_t>(b) << QP::QS::rxPriv_.var.evt.idx); - QP::QS::rxPriv_.var.evt.idx += 8U; - if (QP::QS::rxPriv_.var.evt.idx - == (8U *static_cast<unsigned>(Q_SIGNAL_SIZE))) - { - QP::QS::rxPriv_.var.evt.len = 0U; - QP::QS::rxPriv_.var.evt.idx = 0U; - tran_(WAIT4_EVT_LEN); - } - break; - } - case WAIT4_EVT_LEN: { - QP::QS::rxPriv_.var.evt.len |= static_cast<std::uint16_t>( - static_cast<unsigned>(b) << QP::QS::rxPriv_.var.evt.idx); - QP::QS::rxPriv_.var.evt.idx += 8U; - if (QP::QS::rxPriv_.var.evt.idx == (8U * 2U)) { - if ((QP::QS::rxPriv_.var.evt.len + sizeof(QP::QEvt)) - <= QP::QF::poolGetMaxBlockSize()) - { - // report Ack before generating any other QS records - rxReportAck_(QP::QS_RX_EVENT); - - QP::QS::rxPriv_.var.evt.e = QP::QF::newX_( - (static_cast<std::uint_fast16_t>(QP::QS::rxPriv_.var.evt.len) - + sizeof(QP::QEvt)), - 0U, // margin - static_cast<enum_t>(QP::QS::rxPriv_.var.evt.sig)); - // event allocated? - if (QP::QS::rxPriv_.var.evt.e != nullptr) { - QP::QS::rxPriv_.var.evt.p = - reinterpret_cast<std::uint8_t *>(QP::QS::rxPriv_.var.evt.e); - QP::QS::rxPriv_.var.evt.p = &QP::QS::rxPriv_.var.evt.p[sizeof(QP::QEvt)]; - if (QP::QS::rxPriv_.var.evt.len > 0U) { - tran_(WAIT4_EVT_PAR); - } - else { - tran_(WAIT4_EVT_FRAME); - } - } - else { - rxReportError_( - static_cast<std::uint8_t>(QP::QS_RX_EVENT)); - tran_(ERROR_STATE); - } - } - else { - rxReportError_( - static_cast<std::uint8_t>(QP::QS_RX_EVENT)); - tran_(ERROR_STATE); - } - } - break; - } - case WAIT4_EVT_PAR: { // event parameters - *QP::QS::rxPriv_.var.evt.p = b; - ++QP::QS::rxPriv_.var.evt.p; - --QP::QS::rxPriv_.var.evt.len; - if (QP::QS::rxPriv_.var.evt.len == 0U) { - tran_(WAIT4_EVT_FRAME); - } - break; - } - case WAIT4_EVT_FRAME: { - // keep ignoring the data until a frame is collected - break; - } - -#ifdef Q_UTEST - case WAIT4_TEST_SETUP_FRAME: { - // keep ignoring the data until a frame is collected - break; - } - case WAIT4_TEST_TEARDOWN_FRAME: { - // keep ignoring the data until a frame is collected - break; - } - case WAIT4_TEST_CONTINUE_FRAME: { - // keep ignoring the data until a frame is collected - break; - } - case WAIT4_TEST_PROBE_DATA: { - QP::QS::rxPriv_.var.tp.data |= - (static_cast<QP::QSFun>(b) << QP::QS::rxPriv_.var.tp.idx); - QP::QS::rxPriv_.var.tp.idx += 8U; - if (QP::QS::rxPriv_.var.tp.idx == (8U * sizeof(std::uint32_t))) { - QP::QS::rxPriv_.var.tp.addr = 0U; - QP::QS::rxPriv_.var.tp.idx = 0U; - tran_(WAIT4_TEST_PROBE_ADDR); - } - break; - } - case WAIT4_TEST_PROBE_ADDR: { - QP::QS::rxPriv_.var.tp.addr |= - (static_cast<std::uint32_t>(b) << QP::QS::rxPriv_.var.tp.idx); - QP::QS::rxPriv_.var.tp.idx += 8U; - if (QP::QS::rxPriv_.var.tp.idx - == (8U * static_cast<unsigned>(QS_FUN_PTR_SIZE))) - { - tran_(WAIT4_TEST_PROBE_FRAME); - } - break; - } - case WAIT4_TEST_PROBE_FRAME: { - // keep ignoring the data until a frame is collected - break; - } -#endif // Q_UTEST - - case ERROR_STATE: { - // keep ignoring the data until a good frame is collected - break; - } - default: { // unexpected or unimplemented state - rxReportError_(0x45U); - tran_(ERROR_STATE); - break; - } - } -} - -//............................................................................ -void rxHandleGoodFrame_(std::uint8_t const state) { - std::uint8_t i; - std::uint8_t *ptr; - QS_CRIT_STAT - - switch (state) { - case WAIT4_INFO_FRAME: { - // no need to report Ack or Done - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QP::QS::target_info_pre_(0U); // send only Target info - QS_MEM_APP(); - QS_CRIT_EXIT(); - break; - } - case WAIT4_RESET_FRAME: { - // no need to report Ack or Done, because Target resets - QP::QS::onReset(); // reset the Target - break; - } - case WAIT4_CMD_PARAM1: // intentionally fall-through - case WAIT4_CMD_PARAM2: // intentionally fall-through - case WAIT4_CMD_PARAM3: // intentionally fall-through - case WAIT4_CMD_FRAME: { - rxReportAck_(QP::QS_RX_COMMAND); - QP::QS::onCommand(QP::QS::rxPriv_.var.cmd.cmdId, QP::QS::rxPriv_.var.cmd.param1, - QP::QS::rxPriv_.var.cmd.param2, QP::QS::rxPriv_.var.cmd.param3); -#ifdef Q_UTEST - #if Q_UTEST != 0 - QP::QS::processTestEvts_(); // process all events produced - #endif // Q_UTEST != 0 -#endif // Q_UTEST - rxReportDone_(QP::QS_RX_COMMAND); - break; - } - case WAIT4_TICK_FRAME: { - rxReportAck_(QP::QS_RX_TICK); -#ifdef Q_UTEST - QP::QTimeEvt::tick1_( - static_cast<std::uint_fast8_t>(QP::QS::rxPriv_.var.tick.rate), - &QP::QS::rxPriv_); - #if Q_UTEST != 0 - QP::QS::processTestEvts_(); // process all events produced - #endif // Q_UTEST != 0 -#else - QP::QTimeEvt::tick( - static_cast<std::uint_fast8_t>(QP::QS::rxPriv_.var.tick.rate), - &QP::QS::rxPriv_); -#endif // Q_UTEST - rxReportDone_(QP::QS_RX_TICK); - break; - } - case WAIT4_PEEK_FRAME: { - // no need to report Ack or Done - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QP::QS::beginRec_(static_cast<std::uint_fast8_t>( - QP::QS_PEEK_DATA)); - ptr = static_cast<std::uint8_t*>( - QP::QS::rxPriv_.currObj[QP::QS::AP_OBJ]); - ptr = &ptr[QP::QS::rxPriv_.var.peek.offs]; - QS_TIME_PRE_(); // timestamp - QS_U16_PRE_(QP::QS::rxPriv_.var.peek.offs); // data offset - QS_U8_PRE_(QP::QS::rxPriv_.var.peek.size); // data size - QS_U8_PRE_(QP::QS::rxPriv_.var.peek.num); // number of data items - for (i = 0U; i < QP::QS::rxPriv_.var.peek.num; ++i) { - switch (QP::QS::rxPriv_.var.peek.size) { - case 1: - QS_U8_PRE_(ptr[i]); - break; - case 2: - QS_U16_PRE_( - reinterpret_cast<std::uint16_t*>(ptr)[i]); - break; - case 4: - QS_U32_PRE_( - reinterpret_cast<std::uint32_t*>(ptr)[i]); - break; - default: - // intentionally empty - break; - } - } - QP::QS::endRec_(); - QS_MEM_APP(); - QS_CRIT_EXIT(); - - QS_REC_DONE(); // user callback (if defined) - break; - } - case WAIT4_POKE_DATA: { - // received less than expected poke data items - rxReportError_(static_cast<std::uint8_t>(QP::QS_RX_POKE)); - break; - } - case WAIT4_POKE_FRAME: { - rxReportAck_(QP::QS_RX_POKE); - // no need to report done - break; - } - case WAIT4_FILL_FRAME: { - rxReportAck_(QP::QS_RX_FILL); - ptr = static_cast<std::uint8_t *>( - QP::QS::rxPriv_.currObj[QP::QS::AP_OBJ]); - ptr = &ptr[QP::QS::rxPriv_.var.poke.offs]; - for (i = 0U; i < QP::QS::rxPriv_.var.poke.num; ++i) { - switch (QP::QS::rxPriv_.var.poke.size) { - case 1: - ptr[i] = - static_cast<std::uint8_t>(QP::QS::rxPriv_.var.poke.data); - break; - case 2: - reinterpret_cast<std::uint16_t *>(ptr)[i] = - static_cast<std::uint16_t>(QP::QS::rxPriv_.var.poke.data); - break; - case 4: - reinterpret_cast<std::uint32_t *>(ptr)[i] = - QP::QS::rxPriv_.var.poke.data; - break; - default: - // intentionally empty - break; - } - } - break; - } - case WAIT4_FILTER_FRAME: { - rxReportAck_(static_cast<enum QP::QSpyRxRecords>( - QP::QS::rxPriv_.var.flt.recId)); - - // apply the received filters - if (QP::QS::rxPriv_.var.flt.recId - == static_cast<std::uint8_t>(QP::QS_RX_GLB_FILTER)) - { - for (i = 0U; - i < static_cast<std::uint8_t>(sizeof(QP::QS::filt_.glb)); - ++i) - { - QP::QS::filt_.glb[i] = QP::QS::rxPriv_.var.flt.data[i]; - } - // leave the "not maskable" filters enabled, - // see qs.hpp, Miscellaneous QS records (not maskable) - QP::QS::filt_.glb[0] |= 0x01U; - QP::QS::filt_.glb[7] |= 0xFCU; - QP::QS::filt_.glb[8] |= 0x7FU; - - // never enable the last 3 records (0x7D, 0x7E, 0x7F) - QP::QS::filt_.glb[15] &= 0x1FU; - } - else if (QP::QS::rxPriv_.var.flt.recId - == static_cast<std::uint8_t>(QP::QS_RX_LOC_FILTER)) - { - for (i = 0U; i < Q_DIM(QP::QS::filt_.loc); ++i) { - QP::QS::filt_.loc[i] = QP::QS::rxPriv_.var.flt.data[i]; - } - // leave QS_ID == 0 always on - QP::QS::filt_.loc[0] |= 0x01U; - } - else { - rxReportError_(QP::QS::rxPriv_.var.flt.recId); - } - // no need to report Done - break; - } - case WAIT4_OBJ_FRAME: { - i = QP::QS::rxPriv_.var.obj.kind; - if (i < static_cast<std::uint8_t>(QP::QS::MAX_OBJ)) { - if (QP::QS::rxPriv_.var.obj.recId - == static_cast<std::uint8_t>(QP::QS_RX_CURR_OBJ)) - { - QP::QS::rxPriv_.currObj[i] = - reinterpret_cast<void *>(QP::QS::rxPriv_.var.obj.addr); - rxReportAck_(QP::QS_RX_CURR_OBJ); - } - else if (QP::QS::rxPriv_.var.obj.recId - == static_cast<std::uint8_t>(QP::QS_RX_AO_FILTER)) - { - if (QP::QS::rxPriv_.var.obj.addr != 0U) { - std::int_fast16_t const filter = - static_cast<std::int_fast16_t>( - reinterpret_cast<QP::QActive *>( - QP::QS::rxPriv_.var.obj.addr)->getPrio()); - QP::QS::locFilter_((i == 0) - ? filter - :-filter); - rxReportAck_(QP::QS_RX_AO_FILTER); - } - else { - rxReportError_(static_cast<enum_t>( - QP::QS_RX_AO_FILTER)); - } - } - else { - rxReportError_(QP::QS::rxPriv_.var.obj.recId); - } - } - // both SM and AO - else if (i == static_cast<std::uint8_t>(QP::QS::SM_AO_OBJ)) { - if (QP::QS::rxPriv_.var.obj.recId - == static_cast<std::uint8_t>(QP::QS_RX_CURR_OBJ)) - { - QP::QS::rxPriv_.currObj[QP::QS::SM_OBJ] - = reinterpret_cast<void *>(QP::QS::rxPriv_.var.obj.addr); - QP::QS::rxPriv_.currObj[QP::QS::AO_OBJ] - = reinterpret_cast<void *>(QP::QS::rxPriv_.var.obj.addr); - } - rxReportAck_( - static_cast<enum QP::QSpyRxRecords>(QP::QS::rxPriv_.var.obj.recId)); - } - else { - rxReportError_(QP::QS::rxPriv_.var.obj.recId); - } - break; - } - case WAIT4_QUERY_FRAME: { - queryCurrObj_(QP::QS::rxPriv_.var.obj.kind); - break; - } - case WAIT4_EVT_FRAME: { - // NOTE: Ack was already reported in the WAIT4_EVT_LEN state -#ifdef Q_UTEST - QP::QS::onTestEvt(QP::QS::rxPriv_.var.evt.e); // "massage" the event -#endif // Q_UTEST - // use 'i' as status, 0 == success,no-recycle - i = 0U; - - if (QP::QS::rxPriv_.var.evt.prio == 0U) { // publish - QP::QActive::publish_(QP::QS::rxPriv_.var.evt.e, &QP::QS::rxPriv_, 0U); - } - else if (QP::QS::rxPriv_.var.evt.prio < QF_MAX_ACTIVE) { - if (!QP::QActive::registry_[QP::QS::rxPriv_.var.evt.prio]->POST_X( - QP::QS::rxPriv_.var.evt.e, - 0U, // margin - &QP::QS::rxPriv_)) - { - // failed QACTIVE_POST() recycles the event - i = 0x80U; // failure status, no recycle - } - } - else if (QP::QS::rxPriv_.var.evt.prio == 255U) { - // dispatch to the current SM object - if (QP::QS::rxPriv_.currObj[QP::QS::SM_OBJ] != nullptr) { - // increment the ref-ctr to simulate the situation - // when the event is just retrieved from a queue. - // This is expected for the following QF::gc() call. - QP::QEvt_refCtr_inc_(QP::QS::rxPriv_.var.evt.e); - - static_cast<QP::QAsm *>( - QP::QS::rxPriv_.currObj[QP::QS::SM_OBJ]) - ->dispatch(QP::QS::rxPriv_.var.evt.e, 0U); - i = 0x01U; // success, recycle - } - else { - i = 0x81U; // failure, recycle - } - } - else if (QP::QS::rxPriv_.var.evt.prio == 254U) { - // init the current SM object" - if (QP::QS::rxPriv_.currObj[QP::QS::SM_OBJ] != nullptr) { - // increment the ref-ctr to simulate the situation - // when the event is just retrieved from a queue. - // This is expected for the following QF::gc() call. - QP::QEvt_refCtr_inc_(QP::QS::rxPriv_.var.evt.e); - - static_cast<QP::QAsm *>( - QP::QS::rxPriv_.currObj[QP::QS::SM_OBJ]) - ->init(QP::QS::rxPriv_.var.evt.e, 0U); - i = 0x01U; // success, recycle - } - else { - i = 0x81U; // failure, recycle - } - } - else if (QP::QS::rxPriv_.var.evt.prio == 253U) { - // post to the current AO - if (QP::QS::rxPriv_.currObj[QP::QS::AO_OBJ] != nullptr) { - if (!static_cast<QP::QActive *>( - QP::QS::rxPriv_.currObj[QP::QS::AO_OBJ])->POST_X( - QP::QS::rxPriv_.var.evt.e, - 0U, // margin - &QP::QS::rxPriv_)) - { - // failed QACTIVE_POST() recycles the event - i = 0x80U; // failure, no recycle - } - } - else { - i = 0x81U; // failure, recycle - } - } - else { - i = 0x81U; // failure, recycle - } - -#if (QF_MAX_EPOOL > 0U) - // recycle needed? - if ((i & 1U) != 0U) { - QP::QF::gc(QP::QS::rxPriv_.var.evt.e); - } -#endif - // failure? - if ((i & 0x80U) != 0U) { - rxReportError_(static_cast<std::uint8_t>(QP::QS_RX_EVENT)); - } - else { -#ifdef Q_UTEST - #if Q_UTEST != 0 - QP::QS::processTestEvts_(); // process all events produced - #endif // Q_UTEST != 0 -#endif // Q_UTEST - rxReportDone_(QP::QS_RX_EVENT); - } - break; - } - -#ifdef Q_UTEST - case WAIT4_TEST_SETUP_FRAME: { - rxReportAck_(QP::QS_RX_TEST_SETUP); - QP::QS::tstPriv_.tpNum = 0U; // clear Test-Probes - QP::QS::tstPriv_.testTime = 0U; //clear time tick - // don't clear current objects - QP::QS::onTestSetup(); // application-specific test setup - // no need to report Done - break; - } - case WAIT4_TEST_TEARDOWN_FRAME: { - rxReportAck_(QP::QS_RX_TEST_TEARDOWN); - QP::QS::onTestTeardown(); // application-specific test teardown - // no need to report Done - break; - } - case WAIT4_TEST_CONTINUE_FRAME: { - rxReportAck_(QP::QS_RX_TEST_CONTINUE); - QP::QS::rxPriv_.inTestLoop = false; // exit the QUTest loop - // no need to report Done - break; - } - case WAIT4_TEST_PROBE_FRAME: { - rxReportAck_(QP::QS_RX_TEST_PROBE); - Q_ASSERT_INCRIT(815, - QP::QS::tstPriv_.tpNum - < (sizeof(QP::QS::tstPriv_.tpBuf) - / sizeof(QP::QS::tstPriv_.tpBuf[0]))); - QP::QS::tstPriv_.tpBuf[QP::QS::tstPriv_.tpNum] = QP::QS::rxPriv_.var.tp; - ++QP::QS::tstPriv_.tpNum; - // no need to report Done - break; - } -#endif // Q_UTEST +$define ${QF::QActive::flushDeferred} + + + + #define QP_IMPL // this is QP implementation +#include "qp_port.hpp" // QP port +#include "qp_pkg.hpp" // QP package-scope interface +#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem +#ifdef Q_SPY // QS software tracing enabled? + #include "qs_port.hpp" // QS port + #include "qs_pkg.hpp" // QS facilities for pre-defined trace records +#else + #include "qs_dummy.hpp" // disable the QS software tracing +#endif // Q_SPY - case ERROR_STATE: { - // keep ignoring all bytes until new frame - break; - } - default: { - rxReportError_(0x47U); - break; - } - } -} +#if (QF_MAX_EPOOL > 0U) // mutable events configured? -//............................................................................ -static void rxHandleBadFrame_(std::uint8_t const state) noexcept { - rxReportError_(0x50U); // error for all bad frames - switch (state) { - case WAIT4_EVT_FRAME: { - QS_CRIT_STAT - QS_CRIT_ENTRY(); - Q_ASSERT_INCRIT(910, QP::QS::rxPriv_.var.evt.e != nullptr); - QS_CRIT_EXIT(); -#if (QF_MAX_EPOOL > 0U) - QP::QF::gc(QP::QS::rxPriv_.var.evt.e); // don't leak allocated evt -#endif - break; - } - default: { - // intentionally empty - break; - } - } -} +// unnamed namespace for local definitions with internal linkage +namespace { +Q_DEFINE_THIS_MODULE("qf_dyn") +} // unnamed namespace -//............................................................................ -static void rxReportAck_(enum QP::QSpyRxRecords const recId) noexcept { - QS_CRIT_STAT - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QP::QS::beginRec_(static_cast<std::uint_fast8_t>(QP::QS_RX_STATUS)); - QS_U8_PRE_(recId); // record ID - QP::QS::endRec_(); - QS_MEM_APP(); - QS_CRIT_EXIT(); - QS_REC_DONE(); // user callback (if defined) -} +$define ${QF::QF-dyn} -//............................................................................ -static void rxReportError_(std::uint8_t const code) noexcept { - QS_CRIT_STAT - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QP::QS::beginRec_(static_cast<std::uint_fast8_t>(QP::QS_RX_STATUS)); - QS_U8_PRE_(0x80U | code); // error code - QP::QS::endRec_(); - QS_MEM_APP(); - QS_CRIT_EXIT(); - QS_REC_DONE(); // user callback (if defined) -} +#endif // (QF_MAX_EPOOL > 0U) mutable events configured + + + + #define QP_IMPL // this is QP implementation +#include "qp_port.hpp" // QP port +#include "qp_pkg.hpp" // QP package-scope interface +#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem +#ifdef Q_SPY // QS software tracing enabled? + #include "qs_port.hpp" // QS port + #include "qs_pkg.hpp" // QS facilities for pre-defined trace records +#else + #include "qs_dummy.hpp" // disable the QS software tracing +#endif // Q_SPY -//............................................................................ -static void rxReportDone_(enum QP::QSpyRxRecords const recId) noexcept { - QS_CRIT_STAT - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QP::QS::beginRec_(static_cast<std::uint_fast8_t>(QP::QS_TARGET_DONE)); - QS_TIME_PRE_(); // timestamp - QS_U8_PRE_(recId); // record ID - QP::QS::endRec_(); - QS_MEM_APP(); - QS_CRIT_EXIT(); - QS_REC_DONE(); // user callback (if defined) -} +// unnamed namespace for local definitions with internal linkage +namespace { +Q_DEFINE_THIS_MODULE("qf_mem") +} // unnamed namespace -//............................................................................ -static void queryCurrObj_(std::uint8_t obj_kind) noexcept { - QS_CRIT_STAT - QS_CRIT_ENTRY(); - Q_REQUIRE_INCRIT(800, obj_kind < Q_DIM(QP::QS::rxPriv_.currObj)); - QS_CRIT_EXIT(); +$define ${QF::QMPool} + + + + #define QP_IMPL // this is QP implementation +#include "qp_port.hpp" // QP port +#include "qp_pkg.hpp" // QP package-scope interface +#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem +#ifdef Q_SPY // QS software tracing enabled? + #include "qs_port.hpp" // QS port + #include "qs_pkg.hpp" // QS facilities for pre-defined trace records +#else + #include "qs_dummy.hpp" // disable the QS software tracing +#endif // Q_SPY - if (QP::QS::rxPriv_.currObj[obj_kind] != nullptr) { - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QP::QS::beginRec_(static_cast<std::uint_fast8_t>(QP::QS_QUERY_DATA)); - QS_TIME_PRE_(); // timestamp - QS_U8_PRE_(obj_kind); // object kind - QS_OBJ_PRE_(QP::QS::rxPriv_.currObj[obj_kind]); // object pointer - switch (obj_kind) { - case QP::QS::SM_OBJ: // intentionally fall through - case QP::QS::AO_OBJ: - QS_FUN_PRE_(reinterpret_cast<QP::QHsm *>( - QP::QS::rxPriv_.currObj[obj_kind])->getStateHandler()); - break; - case QP::QS::MP_OBJ: - QS_MPC_PRE_(reinterpret_cast<QP::QMPool *>( - QP::QS::rxPriv_.currObj[obj_kind])->getNFree()); - QS_MPC_PRE_(reinterpret_cast<QP::QMPool *>( - QP::QS::rxPriv_.currObj[obj_kind])->getNMin()); - break; - case QP::QS::EQ_OBJ: - QS_EQC_PRE_(reinterpret_cast<QP::QEQueue *>( - QP::QS::rxPriv_.currObj[obj_kind])->getNFree()); - QS_EQC_PRE_(reinterpret_cast<QP::QEQueue *>( - QP::QS::rxPriv_.currObj[obj_kind])->getNMin()); - break; - case QP::QS::TE_OBJ: - QS_OBJ_PRE_(reinterpret_cast<QP::QTimeEvt *>( - QP::QS::rxPriv_.currObj[obj_kind])->getAct()); - QS_TEC_PRE_(reinterpret_cast<QP::QTimeEvt *>( - QP::QS::rxPriv_.currObj[obj_kind])->getCtr()); - QS_TEC_PRE_(reinterpret_cast<QP::QTimeEvt *>( - QP::QS::rxPriv_.currObj[obj_kind])->getInterval()); - QS_SIG_PRE_(reinterpret_cast<QP::QTimeEvt *>( - QP::QS::rxPriv_.currObj[obj_kind])->sig); - QS_U8_PRE_ (reinterpret_cast<QP::QTimeEvt *>( - QP::QS::rxPriv_.currObj[obj_kind])->refCtr_); - break; - default: - // intentionally empty - break; - } - QP::QS::endRec_(); - QS_MEM_APP(); - QS_CRIT_EXIT(); - QS_REC_DONE(); // user callback (if defined) - } - else { - rxReportError_(static_cast<std::uint8_t>(QP::QS_RX_AO_FILTER)); - } -} +// unnamed namespace for local definitions with internal linkage +namespace { +Q_DEFINE_THIS_MODULE("qf_qact") +} // unnamed namespace -//............................................................................ -static void rxPoke_() noexcept { - std::uint8_t * ptr = - static_cast<std::uint8_t *>(QP::QS::rxPriv_.currObj[QP::QS::AP_OBJ]); - ptr = &ptr[QP::QS::rxPriv_.var.poke.offs]; - switch (QP::QS::rxPriv_.var.poke.size) { - case 1: - *ptr = static_cast<std::uint8_t>(QP::QS::rxPriv_.var.poke.data); - break; - case 2: - *reinterpret_cast<std::uint16_t *>(ptr) - = static_cast<std::uint16_t>(QP::QS::rxPriv_.var.poke.data); - break; - case 4: - *reinterpret_cast<std::uint32_t *>(ptr) = QP::QS::rxPriv_.var.poke.data; - break; - default: - Q_ERROR_ID(900); - break; - } +$define ${QF::QActive::QActive} - QP::QS::rxPriv_.var.poke.data = 0U; - QP::QS::rxPriv_.var.poke.idx = 0U; - QP::QS::rxPriv_.var.poke.offs += static_cast<std::uint16_t>(QP::QS::rxPriv_.var.poke.size); -} +$define ${QF::QActive::register_} + +$define ${QF::QActive::unregister_} + + + + #define QP_IMPL // this is QP implementation +#include "qp_port.hpp" // QP port +#include "qp_pkg.hpp" // QP package-scope interface +#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem +#ifdef Q_SPY // QS software tracing enabled? + #include "qs_port.hpp" // QS port + #include "qs_pkg.hpp" // QS facilities for pre-defined trace records +#else + #include "qs_dummy.hpp" // disable the QS software tracing +#endif // Q_SPY +// unnamed namespace for local definitions with internal linkage +namespace { +//Q_DEFINE_THIS_MODULE("qf_qmact") } // unnamed namespace -//! @endcond +$define ${QF::QMActive} - - - // only build when Q_UTEST is defined -#ifdef Q_UTEST - -#define QP_IMPL // this is QP implementation + + + #define QP_IMPL // this is QP implementation #include "qp_port.hpp" // QP port #include "qp_pkg.hpp" // QP package-scope interface #include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#include "qs_port.hpp" // QS port -#include "qs_pkg.hpp" // QS package-scope internal interface +#ifdef Q_SPY // QS software tracing enabled? + #include "qs_port.hpp" // QS port + #include "qs_pkg.hpp" // QS facilities for pre-defined trace records +#else + #include "qs_dummy.hpp" // disable the QS software tracing +#endif // Q_SPY -$define ${QS::QUTest} +// unnamed namespace for local definitions with internal linkage +namespace { +Q_DEFINE_THIS_MODULE("qf_qeq") +} // unnamed namespace -//============================================================================ -//! @cond INTERNAL +$define ${QF::QEQueue} + + + + #define QP_IMPL // this is QP implementation +#include "qp_port.hpp" // QP port +#include "qp_pkg.hpp" // QP package-scope interface +#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem +#ifdef Q_SPY // QS software tracing enabled? + #include "qs_port.hpp" // QS port + #include "qs_pkg.hpp" // QS facilities for pre-defined trace records +#else + #include "qs_dummy.hpp" // disable the QS software tracing +#endif // Q_SPY -namespace QP { -namespace QS { +// unnamed namespace for local definitions with internal linkage +namespace { +Q_DEFINE_THIS_MODULE("qf_ps") +} // unnamed namespace -TestAttr tstPriv_; +$define ${QF::QActive::subscrList_} -//............................................................................ -void test_pause_() { - beginRec_(static_cast<std::uint_fast8_t>(QS_TEST_PAUSED)); - endRec_(); - onTestLoop(); -} +$define ${QF::QActive::maxPubSignal_} -//............................................................................ -std::uint32_t getTestProbe_(QSpyFunPtr const api) noexcept { - std::uint32_t data = 0U; - for (std::uint8_t i = 0U; i < tstPriv_.tpNum; ++i) { - if (tstPriv_.tpBuf[i].addr == reinterpret_cast<QSFun>(api)) { - data = tstPriv_.tpBuf[i].data; - - QS_CRIT_STAT - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QS::beginRec_(static_cast<std::uint_fast8_t>(QS_TEST_PROBE_GET)); - QS_TIME_PRE_(); // timestamp - QS_FUN_PRE_(api); // the calling API - QS_U32_PRE_(data); // the Test-Probe data - QS::endRec_(); - - QS_REC_DONE(); // user callback (if defined) - - --tstPriv_.tpNum; // one less Test-Probe - // move all remaining entries in the buffer up by one - for (std::uint8_t j = i; j < tstPriv_.tpNum; ++j) { - tstPriv_.tpBuf[j] = tstPriv_.tpBuf[j + 1U]; - } - QS_MEM_APP(); - QS_CRIT_EXIT(); - break; // we are done (Test-Probe retrieved) - } - } - return data; -} +$define ${QF::QActive::psInit} -//............................................................................ -QSTimeCtr onGetTime() { - return (++tstPriv_.testTime); -} +$define ${QF::QActive::publish_} -} // namespace QS -} // namespace QP +$define ${QF::QActive::subscribe} -//............................................................................ -extern "C" { +$define ${QF::QActive::unsubscribe} -Q_NORETURN Q_onError( - char const * const module, - int_t const id) -{ - // NOTE: called in a critical section - - QP::QS::beginRec_(static_cast<std::uint_fast8_t>(QP::QS_ASSERT_FAIL)); - QS_TIME_PRE_(); - QS_U16_PRE_(id); - QS_STR_PRE_((module != nullptr) ? module : "?"); - QP::QS::endRec_(); - QP::QS::onFlush(); // flush the assertion record to the host - - QP::QS::onCleanup(); // cleanup after the failure - QP::QS::onReset(); // reset the target to prevent it from continuing - for (;;) { // onReset() should not return, but to ensure no-return... - } -} +$define ${QF::QActive::unsubscribeAll} + + + + #define QP_IMPL // this is QP implementation +#include "qp_port.hpp" // QP port +#include "qp_pkg.hpp" // QP package-scope interface +#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem +#ifdef Q_SPY // QS software tracing enabled? + #include "qs_port.hpp" // QS port + #include "qs_pkg.hpp" // QS facilities for pre-defined trace records +#else + #include "qs_dummy.hpp" // disable the QS software tracing +#endif // Q_SPY -} // extern "C" +// unnamed namespace for local definitions with internal linkage +namespace { +Q_DEFINE_THIS_MODULE("qf_time") +} // unnamed namespace -//! @endcond -//============================================================================ +$define ${QF::QTimeEvt} + + + + + + + #define QP_IMPL // this is QP implementation +#include "qp_port.hpp" // QP port +#include "qp_pkg.hpp" // QP package-scope interface +#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem +#ifdef Q_SPY // QS software tracing enabled? + #include "qs_port.hpp" // QS port + #include "qs_pkg.hpp" // QS facilities for pre-defined trace records +#else + #include "qs_dummy.hpp" // disable the QS software tracing +#endif // Q_SPY -// QP-stub for QUTest -// NOTE: The QP-stub is needed for unit testing QP applications, but might -// NOT be needed for testing QP itself. In that case, the build process -// can define Q_UTEST=0 to exclude the QP-stub from the build. -#if Q_UTEST != 0 +// protection against including this source file in a wrong project +#ifndef QV_HPP_ + #error "Source file included in a project NOT based on the QV kernel" +#endif // QV_HPP_ // unnamed namespace for local definitions with internal linkage namespace { -Q_DEFINE_THIS_MODULE("qutest") +Q_DEFINE_THIS_MODULE("qv") } // unnamed namespace -namespace QP { -namespace QS { +$define ${QV::QV-base} -void processTestEvts_() { - QS_TEST_PROBE_DEF(&QS::processTestEvts_) +$define ${QV::QF-cust} - // return immediately (do nothing) for Test Probe != 0 - QS_TEST_PROBE(return;) +$define ${QV::QActive} + + + + + + + #define QP_IMPL // this is QP implementation +#include "qp_port.hpp" // QP port +#include "qp_pkg.hpp" // QP package-scope interface +#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem +#ifdef Q_SPY // QS software tracing enabled? + #include "qs_port.hpp" // QS port + #include "qs_pkg.hpp" // QS facilities for pre-defined trace records +#else + #include "qs_dummy.hpp" // disable the QS software tracing +#endif // Q_SPY - while (tstPriv_.readySet.notEmpty()) { - std::uint_fast8_t const p = tstPriv_.readySet.findMax(); - QActive * const a = QActive::registry_[p]; +// protection against including this source file in a wrong project +#ifndef QK_HPP_ + #error "Source file included in a project NOT based on the QK kernel" +#endif // QK_HPP_ - QEvt const * const e = a->get_(); - a->dispatch(e, a->getPrio()); - #if (QF_MAX_EPOOL > 0U) - QF::gc(e); - #endif - if (a->getEQueue().isEmpty()) { // empty queue? - tstPriv_.readySet.remove(p); -#ifndef Q_UNSAFE - tstPriv_.readySet.update_(&tstPriv_.readySet_dis); -#endif - } - } -} +// unnamed namespace for local definitions with internal linkage +namespace { +Q_DEFINE_THIS_MODULE("qk") +} // unnamed namespace -} // namespace QS -} // namespace QP +$define ${QK::QK-base} -$define ${QS::QUTest-stub} +extern "C" { +$define ${QK-extern-C} +} // extern "C" -#endif // Q_UTEST != 0 +$define ${QK::QF-cust} -#endif // def Q_UTEST +$define ${QK::QActive} + + + #include "qstamp.hpp" diff --git a/qpcpp.sha1 b/qpcpp.sha1 index 44ba1901c..35a61dd6e 100644 --- a/qpcpp.sha1 +++ b/qpcpp.sha1 @@ -1,174 +1,132 @@ -177ecb5725a327d05728c48484a164e43a407045 *qpcpp.qm -2e6071600db5ae5eace4cc524f9ed4f5310056ce *include/qequeue.hpp -2ae88474c60e5ae739bafc1131f54ce9f1bba25b *include/qk.hpp -8c49c0fb49ede99f2277e70e9340709a65d15f85 *include/qmpool.hpp -16e02c12f65e037960d3994379aeddc618fba499 *include/qp.hpp -c25d74292c78eb2af68fe8c39e854141d739fba1 *include/qp_pkg.hpp -eef6f6b93ce2066f02be0217d4953045ce102878 *include/qpcpp.hpp -9bf9ae3586f8828c372ab79771839bd3c76e5b5e *include/qs.hpp -b6b1f1c52727bec4c6a50b030ad9277f93ac0eee *include/qs_dummy.hpp -5930fa07c97bec69b4a453b794fb3fe38b113c54 *include/qs_pkg.hpp +a37f690d75dac83d45b5da3082d28f188191fd9a *qpcpp.qm +46578fc304c597329289978acee1027c8c533335 *include/qequeue.hpp +1a8e0b05536b89c1cd3806782ae1a21dd4ceca69 *include/qk.hpp +cb1c39aabacb619060924356f7c8e900686538e0 *include/qmpool.hpp +e0d974faef6b60cc455e49abb32d43128b8c79cf *include/qp.hpp +bf47a939e525fa575673f89b8106bcee166240a2 *include/qp_pkg.hpp +e5b0d14c9e6994b82a5cd9200bde46bd179bfb20 *include/qpcpp.hpp +88220a7d892fee54053b467b596dc6b536aaf8be *include/qs_dummy.hpp 49d2620b0afa9e74d73680495c3e8a931e5d8f73 *include/qsafe.h -9c528d4b4df88afc07bf67423ca3e79fb4918bb8 *include/qstamp.hpp -0b08c2aabdc19b71f943cf7a7dd33250f22c2945 *include/qv.hpp -0648d5e24f1954beef908b7fc57e344b01643d14 *include/qxk.hpp +09e9ffe95120ba17a49d7039b5316f2614710dab *include/qstamp.hpp +73749ed396bbc0419971769a47069448c8136960 *include/qv.hpp +0199f3eeb6c02b8cc890ee4c6f6d344569a0858f *include/README.md 71899ce74eeb04f333ed00d53f87719f722a39ab *src/qf/CMakeLists.txt -55c2256457431d6b7c2024ec934a52a33cc4e5ce *src/qf/qep_hsm.cpp -4c49ee7b7b1f1cffc07e8e3c6677d279f3861c83 *src/qf/qep_msm.cpp -20e2a785f80fc9839b7f2774e64ec5414929e918 *src/qf/qf_act.cpp -23569b7f1e7ec95d32b13288be4793d303ad2a73 *src/qf/qf_actq.cpp -3a916b17accb3aea38ec52832e69646173ccd742 *src/qf/qf_defer.cpp -ba3fce3be3b54181a4c26150c85f97f96202205e *src/qf/qf_dyn.cpp -9673b82c3fcfacaa4a8cc7114788aefb533ae48c *src/qf/qf_mem.cpp -28afacb4cc1b7203de98bab206035211c0f5b6f7 *src/qf/qf_ps.cpp -285c65565add1d4aa184158462f0d835671b22eb *src/qf/qf_qact.cpp -cb7c3aa7c650a299b4175c857817acf804664857 *src/qf/qf_qeq.cpp -68e63e88041f8e23b0c92564bd633ba25388be81 *src/qf/qf_qmact.cpp -80073e0d6617065e2cafcd620dbded07dbc4384b *src/qf/qf_time.cpp +81b54ca9a4dff44d24c0f3cd687aaa58afe634ab *src/qf/qep_hsm.cpp +13cb63db437dd4f176dd846eda49bda9827ca571 *src/qf/qep_msm.cpp +62f87a60d04e1c98f40162a166ec14a1f2f1252f *src/qf/qf_act.cpp +07671fb85e9b2492b0ea37b853d7e0eea42bf637 *src/qf/qf_actq.cpp +ed83f5f8b3533cc97ffc2a85aeeb63f29b4f1dd8 *src/qf/qf_defer.cpp +f41d8815460d26f5bbf89e40dcb607b6a3ddeaa8 *src/qf/qf_dyn.cpp +974493184d40e0a2f698c6e63e0bc450343ef591 *src/qf/qf_mem.cpp +ef51e4840107b0ed6ec97e170ac2689e1b1fdb95 *src/qf/qf_ps.cpp +08b490d7505a7ff6fe493058975eb9f0a82daa3d *src/qf/qf_qact.cpp +23892cde4fd7226e899026884e07b01e32d0aef4 *src/qf/qf_qeq.cpp +5fc4874b74779641454e2d8e7960a5bf3d130115 *src/qf/qf_qmact.cpp +7aedf35884943f3add9f39e57e5ea4ad7344d110 *src/qf/qf_time.cpp 7cdab433e81612862fd27f0cf792d38e1197d064 *src/qk/CMakeLists.txt -322f669b6c31379ee234141c2b1253d981c830b7 *src/qk/qk.cpp -deacd749f11cd2037eca58b373771926542043dc *src/qs/CMakeLists.txt -421f1ce59e46b133d8c7856cf075dcbe8b9d9556 *src/qs/qs.cpp -187b926c741f464b35a407b2ff2981ec369ef021 *src/qs/qs_64bit.cpp -ed5a372e9e2e3afb9f461eea98b8186c5961750a *src/qs/qs_fp.cpp -e1d617212d16e22cd5d4a8f8f865a085b651f5f9 *src/qs/qs_rx.cpp -2d78c7f2a02d6502d3e60c2821aaa89e27298196 *src/qs/qstamp.cpp -c8b80e5e03da6e634805b50e33c507bd80cd743b *src/qs/qutest.cpp +1be4743dc14186779abb96b4bd16ba9a99d3314d *src/qk/qk.cpp +eb28260d471fc752ca54b2c1e2d763f28432c2c1 *src/qs/CMakeLists.txt +8008d9c24757b2bb02e85123aa89a3a33090921d *src/qs/qstamp.cpp b6d93a16f5b176d3da4888a7efb265730337f46d *src/qv/CMakeLists.txt -443611940cc593d0ae99d5830fa248de5012aa00 *src/qv/qv.cpp -3aaa8b6ad54430fbaffc05ff8db9599a93fe937b *src/qxk/CMakeLists.txt -1490ee94697d3a926001a839217b796bc9fb5faa *src/qxk/qxk.cpp -2a81fac57cd1ac12ecbe122025dd73b5072d5244 *src/qxk/qxk_mutex.cpp -348325d168c70a911d0cdc11b119f4ef9cdc90ef *src/qxk/qxk_sema.cpp -966ebe4f01f474848620baa8cfd1254a7ce989c1 *src/qxk/qxk_xthr.cpp -3f351bb2031113a81c1620194f6fe0fc2917c76a *ports/lint-plus/au-autosar.lnt -e6d522114c96ede0cfbde013b36d3581e7df5627 *ports/lint-plus/au-autosar19.lnt -4558a0e1e95b69c7de9820bca7df5344fde67008 *ports/lint-plus/au-ds.lnt -9b67d35df023e44c615ac4d7ee1874d270b70a72 *ports/lint-plus/au-ql-cpp11.lnt -321437ad9c561173bf25ce169ab32d7bd01fda76 *ports/lint-plus/options.lnt -8380f483db36126a1b3795951652a9a8ec79f59d *ports/lint-plus/qpcpp.lnt -e34234a143dd399e89cb6bc11d6e92c685dfa263 *ports/lint-plus/std.lnt -b565376c4d6ae4c4fc4958e7ee5331fa6b6750a0 *ports/arm-cm/qk/armclang/qk_port.cpp -4e98e600b710f77aa7f32bec53b7a0259312b456 *ports/arm-cm/qk/armclang/qp_port.hpp -cfe1a9761c511b20d3d150838676d45b205c7250 *ports/arm-cm/qk/armclang/qs_port.hpp -6f6eeb15b1a4a66134caa4e6cd4032da1da19994 *ports/arm-cm/qk/config/qp_config.hpp -3347687dc2c2dc4f2a48bdc561ee044878b24d3a *ports/arm-cm/qk/gnu/qk_port.cpp -33ddbc5ec98e157dec00fd11feb0344bce27e6c7 *ports/arm-cm/qk/gnu/qp_port.hpp -cfe1a9761c511b20d3d150838676d45b205c7250 *ports/arm-cm/qk/gnu/qs_port.hpp -793d2cec036ab48dc97a397edd1478422a785a76 *ports/arm-cm/qk/iar/qk_port.cpp -9e4df6a7a8a9129c4d5f172c3a7d03bce5e411fc *ports/arm-cm/qk/iar/qp_port.hpp -cfe1a9761c511b20d3d150838676d45b205c7250 *ports/arm-cm/qk/iar/qs_port.hpp -09d2b947160e2ff16c100d70836a7be87d4b0db1 *ports/arm-cm/qv/armclang/qp_port.hpp -cfe1a9761c511b20d3d150838676d45b205c7250 *ports/arm-cm/qv/armclang/qs_port.hpp -8d99fb5c034a07d7f46b1cb360c0f82e97a2641c *ports/arm-cm/qv/armclang/qv_port.cpp -dbf368108461876f08366cd1053e0e63dbfc48a6 *ports/arm-cm/qv/config/qp_config.hpp -e6041df9484089f042fc25ad6a1d702668b0ceee *ports/arm-cm/qv/gnu/qp_port.hpp -cfe1a9761c511b20d3d150838676d45b205c7250 *ports/arm-cm/qv/gnu/qs_port.hpp -3ccc1c58ca526756a6beda2bd4e4e0f3caf14c92 *ports/arm-cm/qv/gnu/qv_port.cpp -2d2ece614aa774b1150d6ce70f8bf1724e37737e *ports/arm-cm/qv/iar/qp_port.hpp -cfe1a9761c511b20d3d150838676d45b205c7250 *ports/arm-cm/qv/iar/qs_port.hpp -78ae3caf4c57487a1db9cb97688afffca58ca766 *ports/arm-cm/qv/iar/qv_port.cpp -37f45a5dbd4e6bf6066b486e9383bb5cdbabfe61 *ports/arm-cm/qxk/armclang/qp_port.hpp -cfe1a9761c511b20d3d150838676d45b205c7250 *ports/arm-cm/qxk/armclang/qs_port.hpp -48bc2fc055cf02be83397932a747dbb90d62364c *ports/arm-cm/qxk/armclang/qxk_port.cpp -cd549016afb588697c02221ab8744b21204de8ca *ports/arm-cm/qxk/config/qp_config.hpp -8bd351b5cf9812e360ee59847fa29e9ed3b1ebd8 *ports/arm-cm/qxk/gnu/qp_port.hpp -cfe1a9761c511b20d3d150838676d45b205c7250 *ports/arm-cm/qxk/gnu/qs_port.hpp -e1fdfe215b948a5eb6d738fc64f224b0e26cf35e *ports/arm-cm/qxk/gnu/qxk_port.cpp -2434762e98492bfc63772f2e007084ccd91ab736 *ports/arm-cm/qxk/iar/qp_port.hpp -cfe1a9761c511b20d3d150838676d45b205c7250 *ports/arm-cm/qxk/iar/qs_port.hpp -c9e7c3b12ef3ac5f0d69f3662ca180c25b80e400 *ports/arm-cm/qxk/iar/qxk_port.cpp -00668f089ea2ef1ab4fc55282ce7da1b15e7d52a *ports/arm-cm/qutest/qp_port.hpp -cfe1a9761c511b20d3d150838676d45b205c7250 *ports/arm-cm/qutest/qs_port.hpp -65525e2121b0ebcac2e6704941d5b5d853175f72 *ports/arm-cr/qk/config/qp_config.hpp -f3d55e2065ce75b4574b696ab8256437565c0ca6 *ports/arm-cr/qk/gnu/qp_port.hpp -cfe1a9761c511b20d3d150838676d45b205c7250 *ports/arm-cr/qk/gnu/qs_port.hpp -87f58f713b57cdae93d4f7c19ef6fd304e135e5e *ports/arm-cr/qk/iar/qp_port.hpp -cfe1a9761c511b20d3d150838676d45b205c7250 *ports/arm-cr/qk/iar/qs_port.hpp -f82d516d0d164ace1734ab51ba1c416ca9c94913 *ports/arm-cr/qk/ti/qp_port.hpp -cfe1a9761c511b20d3d150838676d45b205c7250 *ports/arm-cr/qk/ti/qs_port.hpp -a3f7369a4415abd06b6f590849c4e26637caab45 *ports/arm-cr/qv/gnu/qp_port.hpp -cfe1a9761c511b20d3d150838676d45b205c7250 *ports/arm-cr/qv/gnu/qs_port.hpp -1aaf2e12dffc15336f0e634705cf1215e2bc2f5d *ports/arm-cr/qv/iar/qp_port.hpp -cfe1a9761c511b20d3d150838676d45b205c7250 *ports/arm-cr/qv/iar/qs_port.hpp -73f6b8ad6ce3c90dfe57275863bc7fdf2ccec475 *ports/arm-cr/qv/ti/qp_port.hpp -cfe1a9761c511b20d3d150838676d45b205c7250 *ports/arm-cr/qv/ti/qs_port.hpp -b0921eaced95677e51cf95a723f070e8ac959db3 *ports/msp430/qk/qp_port.hpp -6f79670155f0a351e863b9eb3418784d93f2bee6 *ports/msp430/qk/qs_port.hpp -120d367708bca0c57283dce82903cc9086cedf69 *ports/msp430/qv/qp_port.hpp -6f79670155f0a351e863b9eb3418784d93f2bee6 *ports/msp430/qv/qs_port.hpp -89e524cfe36f094ce0be2dce0591ebcc8df21c1a *ports/msp430/qutest/qp_port.hpp -6f79670155f0a351e863b9eb3418784d93f2bee6 *ports/msp430/qutest/qs_port.hpp -ad510a3ba925e8d70c379e789eaae2600a13c713 *ports/config/qp_config.hpp +f530563e062ff7ea84763f6e799bf4ca1cb73054 *src/qv/qv.cpp +8456ce45995423dd872685229539618abaa9c580 *ports/arm-cm/qk/armclang/qk_port.cpp +94a289a5f900afaeb47b5454824bc4911df8014f *ports/arm-cm/qk/armclang/qp_port.hpp +5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qk/armclang/qs_port.hpp +fafeded481e004677bfa6eb7cce7e4c4dbd5fd2f *ports/arm-cm/qk/config/qp_config.hpp +f94a3fb033b87de04efec19e25c5630b82e9d749 *ports/arm-cm/qk/gnu/qk_port.cpp +1c35b7f6a992d0a4755080903d2a2fd5aa06c923 *ports/arm-cm/qk/gnu/qp_port.hpp +5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qk/gnu/qs_port.hpp +f52bee74512d5c2016eaf20996eee10e52a5d71f *ports/arm-cm/qk/iar/qk_port.cpp +458994edab3235f9d9a9faf78485ecb4edc3bdd1 *ports/arm-cm/qk/iar/qp_port.hpp +5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qk/iar/qs_port.hpp +f59663361efec401c02436eabfe6931729d98b1d *ports/arm-cm/qv/armclang/qp_port.hpp +5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qv/armclang/qs_port.hpp +c225966c8601a651196e3e30af7d0dce6079d610 *ports/arm-cm/qv/armclang/qv_port.cpp +d7f22b95fc3b2228a669c5b9167bc3021156a8c7 *ports/arm-cm/qv/config/qp_config.hpp +fffed0cc5c1180df7550f579268ab7c528f3afda *ports/arm-cm/qv/gnu/qp_port.hpp +5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qv/gnu/qs_port.hpp +bd87c7c78142119968ae65dda01ba75b3170ca08 *ports/arm-cm/qv/gnu/qv_port.cpp +cf46244c7dfb6185f2c01cfdba4d699bf01388e7 *ports/arm-cm/qv/iar/qp_port.hpp +5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cm/qv/iar/qs_port.hpp +421f4bc740a150dae18672f22633bef822119071 *ports/arm-cm/qv/iar/qv_port.cpp +7341172192afc119dc3188b51e64b6cb33dc4f23 *ports/arm-cr/qk/config/qp_config.hpp +53378c89dd07cdf1b5fc1428938a2bf33ef9c897 *ports/arm-cr/qk/gnu/qp_port.hpp +5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cr/qk/gnu/qs_port.hpp +a8f4351725564e449206909176d09bc58cd6f45d *ports/arm-cr/qk/iar/qp_port.hpp +5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cr/qk/iar/qs_port.hpp +7203200deaa5dbb4746434d4a3d79a160d4ccf4b *ports/arm-cr/qk/ti/qp_port.hpp +5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cr/qk/ti/qs_port.hpp +b79ee5fda27709554b5dbdc3162d59787af85ecb *ports/arm-cr/qv/gnu/qp_port.hpp +5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cr/qv/gnu/qs_port.hpp +fafbe56ae4266a412cb1b6db6e146fbfe5022b4a *ports/arm-cr/qv/iar/qp_port.hpp +5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cr/qv/iar/qs_port.hpp +78d39f7479a0ea046e77607740e4211d9e4cb60f *ports/arm-cr/qv/ti/qp_port.hpp +5597ed8e115824f146a12f18c8142371bfa1852a *ports/arm-cr/qv/ti/qs_port.hpp +bc080e68d0edfc28da2df882ed3661cf99f2942c *ports/msp430/qk/qp_port.hpp +197ec45394793b79a29afe5bb31b6de1ad78ad00 *ports/msp430/qk/qs_port.hpp +7b2654746a747c427b5ee1dd7f8b4b82c372a040 *ports/msp430/qv/qp_port.hpp +197ec45394793b79a29afe5bb31b6de1ad78ad00 *ports/msp430/qv/qs_port.hpp +650f628d87a39c559a87c6f849c58fb9a8e777a7 *ports/msp430/qutest/qp_port.hpp +197ec45394793b79a29afe5bb31b6de1ad78ad00 *ports/msp430/qutest/qs_port.hpp +59011c6a3cbf07a38f1a74139cef1a82f22cc475 *ports/config/qp_config.hpp b6b5d23c618976a6fbed51dc5a13e227928e1d4b *ports/embos/CMakeLists.txt -9f3bb4cf50397f734bc5740b055eec077bccc357 *ports/embos/qf_port.cpp -37096dbc6315825e267bf5a34be812073aa90cd8 *ports/embos/qp_port.hpp -cfe1a9761c511b20d3d150838676d45b205c7250 *ports/embos/qs_port.hpp +0b5ad806f47800c1481c9af3d88c1bff3cb1d784 *ports/embos/qf_port.cpp +5e28aa0e89239f970e4b5e85be4e5c3b6a34dd69 *ports/embos/qp_port.hpp +5597ed8e115824f146a12f18c8142371bfa1852a *ports/embos/qs_port.hpp e4f00894f86806af6d88d38e831a8fc0ad36059e *ports/freertos/CMakeLists.txt -ee42541a957ccd8b0b2f01659f64dba84e04754c *ports/freertos/qf_port.cpp -7120c7e5041012b16ab0531275024bf17c4ce618 *ports/freertos/qp_port.hpp -cfe1a9761c511b20d3d150838676d45b205c7250 *ports/freertos/qs_port.hpp +699baf504d4d3df68b0e66196c48516490e795be *ports/freertos/qf_port.cpp +c7efbc2cc8425c0e21d5bd892584b3e2ff7a145b *ports/freertos/qp_port.hpp +5597ed8e115824f146a12f18c8142371bfa1852a *ports/freertos/qs_port.hpp 18df978f665338c757f1a2a284c2acc779bd59d3 *ports/threadx/CMakeLists.txt -e0dc43a58ea3615da2978b4ea0a99e90d845b9b7 *ports/threadx/qf_port.cpp -4e4a9f2affa7efc00340d112258289fa7fc0cc27 *ports/threadx/qp_port.hpp -cfe1a9761c511b20d3d150838676d45b205c7250 *ports/threadx/qs_port.hpp +90717daaf983e8425a9939d17f732ce3d4646bb4 *ports/threadx/qf_port.cpp +f0d61f6806b0207e56dd75f8aaac55c4b1393996 *ports/threadx/qp_port.hpp +5597ed8e115824f146a12f18c8142371bfa1852a *ports/threadx/qs_port.hpp 46699d3c8ad92f9c98ea5e03e72d4190a7794aa4 *ports/threadx/README.md 0ab8b95f50fa767b951c6f56efe86789623b7127 *ports/uc-os2/CMakeLists.txt -f412a6f5052b46f51b4f09fd8e3a3ca9de602618 *ports/uc-os2/qf_port.cpp -26d2bd9adcc0a8acb6170e61ab8d96470c5275f2 *ports/uc-os2/qp_port.hpp -cfe1a9761c511b20d3d150838676d45b205c7250 *ports/uc-os2/qs_port.hpp +3624f6191213536a8be528185d97d1e35b1fa369 *ports/uc-os2/qf_port.cpp +528d3c2c337c639f3879d24da74369facea0bca6 *ports/uc-os2/qp_port.hpp +5597ed8e115824f146a12f18c8142371bfa1852a *ports/uc-os2/qs_port.hpp 227dedab24f1e20440103a0cabc210b4b5adedef *ports/qep-only/CMakeLists.txt -ac6a491b0a46d98d9ac71650b8a8d7c2928966ef *ports/qep-only/qp_port.hpp +6d75bdbb41cd68d2fcab63d0eb8ff91f96f52c24 *ports/qep-only/qp_port.hpp 7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/qep-only/safe_std.h 12255313ebcf963d29d91bee4c917bb6ab2f9e1d *ports/posix/CMakeLists.txt -53f52015c5004c8c0b11153a8e0805c98062ce1e *ports/posix/qf_port.cpp -16ec40a97c24a62810f3c0e68c1d67de3eb35789 *ports/posix/qp_port.hpp -843c109ccdfbde8e17e5feb02c7496fff6e5487d *ports/posix/qs_port.cpp -fb77ed4a0eee6f8646175015cfec3118daa4e628 *ports/posix/qs_port.hpp +9119c0c12ecc34d41cba8da898496c1f99ea47ac *ports/posix/qf_port.cpp +56956443bf38d12075ce2ddc53f8a0e8b86f135b *ports/posix/qp_port.hpp +66922bad40ecb6b213858f935849569713457f71 *ports/posix/qs_port.cpp +f38e2f9bfe4df4d44a8f9a5fa2c0b2dfd79f35ae *ports/posix/qs_port.hpp e6a5523e16619370638f6305687cd480d1e3744b *ports/posix/README.md 7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/posix/safe_std.h 493900b9aa5475785c65458332995a184690d43f *ports/posix-qv/CMakeLists.txt -54a0330e57b4264a5ace751d60e297293678eaca *ports/posix-qv/qf_port.cpp -68169dc5881bae6225e90b19a0ae046d70dac1e8 *ports/posix-qv/qp_port.hpp -843c109ccdfbde8e17e5feb02c7496fff6e5487d *ports/posix-qv/qs_port.cpp -fb77ed4a0eee6f8646175015cfec3118daa4e628 *ports/posix-qv/qs_port.hpp +819137bb54242fd0279ed152fe874decb9fd3c16 *ports/posix-qv/qf_port.cpp +f458af1511007d6ba2a4a0a0e40d74e03719ceb1 *ports/posix-qv/qp_port.hpp +66922bad40ecb6b213858f935849569713457f71 *ports/posix-qv/qs_port.cpp +f38e2f9bfe4df4d44a8f9a5fa2c0b2dfd79f35ae *ports/posix-qv/qs_port.hpp e2e295c371bc14f0089a888b07d98c657dea07bf *ports/posix-qv/README.md 7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/posix-qv/safe_std.h -c9969a454b540a3b1abd3dd5cc46fb211663310e *ports/posix-qutest/CMakeLists.txt -14da384ceb62638144284b967a0b7676bcb52342 *ports/posix-qutest/qp_port.hpp -fb77ed4a0eee6f8646175015cfec3118daa4e628 *ports/posix-qutest/qs_port.hpp -b69c5ff6ec8991799d39fdfd59e2bbf9e43b05bd *ports/posix-qutest/qutest_port.cpp -301e58e2d6ccd284cfdcf6e141f47bd062197b43 *ports/posix-qutest/README.md -7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/posix-qutest/safe_std.h 06b76c6c30ea880876b47ee27115178ff62ea66b *ports/win32/CMakeLists.txt -3745b1372e47dc83a8edf0cd2d8119a32287b020 *ports/win32/qf_port.cpp -6f89d4e61a8c8fcfc011a6249cfff7ac1f9ea5d1 *ports/win32/qp_port.hpp -1c90a44ac27d3c8160701079b3836bc62062a579 *ports/win32/qs_port.cpp -fb77ed4a0eee6f8646175015cfec3118daa4e628 *ports/win32/qs_port.hpp +48dfd18fce993f237138d5d99f2fb0e385efbe93 *ports/win32/qf_port.cpp +ea88910c991455756433cff5338a62ed3d181bf2 *ports/win32/qp_port.hpp +6e6aef4b105bd807de96922fcb5698b695fce7e2 *ports/win32/qs_port.cpp +f38e2f9bfe4df4d44a8f9a5fa2c0b2dfd79f35ae *ports/win32/qs_port.hpp 40f18295a0013cbba3c6b270d1d70748ec1d325a *ports/win32/qwin_gui.c ddc62932b46bbc0ad147193d0dd7efa28127c6c4 *ports/win32/qwin_gui.h ad6de94157c477eacb61f321870b5f8c1a09a5cd *ports/win32/README.md 7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/win32/safe_std.h dd5b9a8736e1a1171f7d8565e29e1acb6f7a9691 *ports/win32-qv/CMakeLists.txt -b260fc1f47aa10623382322875663551ae16b7f1 *ports/win32-qv/qf_port.cpp -c6e39540639997556ddb6858cf85829537494b48 *ports/win32-qv/qp_port.hpp -1c90a44ac27d3c8160701079b3836bc62062a579 *ports/win32-qv/qs_port.cpp -fb77ed4a0eee6f8646175015cfec3118daa4e628 *ports/win32-qv/qs_port.hpp +55381dce63d87ddee340d5a153f6054c4fbf5c0e *ports/win32-qv/qf_port.cpp +b2c8d14a04c2bbf3f6f0f3dae097e485a55dc008 *ports/win32-qv/qp_port.hpp +6e6aef4b105bd807de96922fcb5698b695fce7e2 *ports/win32-qv/qs_port.cpp +f38e2f9bfe4df4d44a8f9a5fa2c0b2dfd79f35ae *ports/win32-qv/qs_port.hpp 40f18295a0013cbba3c6b270d1d70748ec1d325a *ports/win32-qv/qwin_gui.c ddc62932b46bbc0ad147193d0dd7efa28127c6c4 *ports/win32-qv/qwin_gui.h ddd27415c3d1df6d8c210966e8915c407b15bf58 *ports/win32-qv/README.md 7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/win32-qv/safe_std.h -3c23c06f425a8d8dbb18d1f191ac6cab483a8e51 *ports/win32-qutest/CMakeLists.txt -14da384ceb62638144284b967a0b7676bcb52342 *ports/win32-qutest/qp_port.hpp -fb77ed4a0eee6f8646175015cfec3118daa4e628 *ports/win32-qutest/qs_port.hpp -6418e967242f6d8a808862807b4f60ddd2579e86 *ports/win32-qutest/qutest_port.cpp -7235457eb9529f9fe2459ce869e63294ec5c5df6 *ports/win32-qutest/safe_std.h 76dd9078dc4311d53d3862d44177a8660258da6d *zephyr/CMakeLists.txt 36a0252cf0bfd6be0d345c48c00b2300f8917f05 *zephyr/Kconfig 2eb2a922e18b4760a68151ebee1b6282d20b4692 *zephyr/module.yml -9c6ebea7bb82578de1c53f86f5127d228a132e11 *zephyr/qf_port.cpp +36ceff869a883b6cb0a262755e3bf03d790f3a87 *zephyr/qf_port.cpp 109c291df50110f185adc17bcdf8becc0a79346c *zephyr/qp-zephyr.jpg -805a18d9b2da84ba6ba43ed6160c956a867b4ce1 *zephyr/qp_port.hpp +76548c9e125899106122946cdba17b7da1a32c91 *zephyr/qp_port.hpp d414f620c05844bbad1988f0951509856acc63db *zephyr/qs_port.hpp -5a3a6e2b5b6c845428191b15b72679a26bf8cb79 *zephyr/qutest_port.cpp +50863abaf410b184dbe28b36f6e63b74e26af26e *zephyr/qutest_port.cpp 791248d57ce8dfa6497728c7c2d0734c2c581625 *zephyr/README.md diff --git a/qpcpp_sha1.bat b/qpcpp_sha1.bat index e2aeff377..427925f8a 100644 --- a/qpcpp_sha1.bat +++ b/qpcpp_sha1.bat @@ -16,7 +16,6 @@ goto end @sha1sum qpcpp.qm ^ include/* ^ src/qf/* src/qk/* src/qs/* src/qv/* src/qxk/* ^ - ports/lint-plus/*.lnt ^ ports/arm-cm/qk/armclang/* ports/arm-cm/qk/config/* ports/arm-cm/qk/gnu/* ports/arm-cm/qk/iar/* ^ ports/arm-cm/qv/armclang/* ports/arm-cm/qv/config/* ports/arm-cm/qv/gnu/* ports/arm-cm/qv/iar/* ^ ports/arm-cm/qxk/armclang/* ports/arm-cm/qxk/config/* ports/arm-cm/qxk/gnu/* ports/arm-cm/qxk/iar/* ^ diff --git a/src/README.md b/src/README.md new file mode 100644 index 000000000..4993634c8 --- /dev/null +++ b/src/README.md @@ -0,0 +1,45 @@ +# Files Missing from the QP/C++ GPL Distribution +Due to the widespread non-compliance with the GPL, as well as infringement +on the [dual-licensing model of QP frameworks][Lic], the following files +have been **removed from the open-source GPL distribution**: + +``` +qpcpp +| ++---include +| qs.hpp +| qs_pkg.hpp +| qxk.hpp +| +\---src + | + +---qs + | qs.cpp + | qs_64bit.cpp + | qs_fp.cpp + | qs_rx.cpp + | qutest.cpp + | + \---qxk + qxk.cpp + qxk_mutex.cpp + qxk_sema.cpp + qxk_xthr.cpp +``` + +> NOTE: These files are available to the [commercial licensees][Cust] with +the active Support Term. Please contact [Quantum Leaps technical support][Sup] +to get the complete QP/C++ framework distribution. + +# QP/C++ Framework Evaluation +To request **evaluation** of the complete QP/C++ framework, please contact +Quantum Leaps at: +- https://www.state-machine.com/contact + +# Quantum Leaps Licensing: +To learn more about the open source and commercial licensing options: +- https://www.state-machine.com/licensing + + [Lic]: + [Cust]: + [Sup]: diff --git a/src/qf/qep_hsm.cpp b/src/qf/qep_hsm.cpp index d7fc96630..5879b8c7a 100644 --- a/src/qf/qep_hsm.cpp +++ b/src/qf/qep_hsm.cpp @@ -3,17 +3,10 @@ // Model: qpcpp.qm // File: ${src::qf::qep_hsm.cpp} // -// This code has been generated by QM 6.2.0 . +// This code has been generated by QM 7.0.0 . // DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. // -// This code is covered by the following QP license: -// License # : LicenseRef-QL-dual -// Issued to : Any user of the QP/C++ real-time embedded framework -// Framework(s) : qpcpp -// Support ends : 2025-12-31 -// License scope: -// -// Copyright (C) 2005 Quantum Leaps, LLC . +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // Q u a n t u m L e a P s // ------------------------ @@ -21,21 +14,20 @@ // // 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: +// 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. // -// Contact information: +// NOTE: +// The GPL does NOT permit the incorporation of this code into proprietary +// programs. Please contact Quantum Leaps for commercial licensing options, +// which expressly supersede the GPL and are designed explicitly for +// closed-source distribution. +// +// Quantum Leaps contact information: // // // @@ -66,6 +58,10 @@ static QP::QEvt const l_reservedEvt_[4] { QP::QEvt(static_cast(QP::QHsm::Q_INIT_SIG)) }; +// maximum depth of state nesting in a QHsm (including the top level) +// must be >= 3 +static constexpr std::int_fast8_t QHSM_MAX_NEST_DEPTH_ {6}; + } // unnamed namespace // helper macro to handle reserved event in an QHsm @@ -76,10 +72,10 @@ static QP::QEvt const l_reservedEvt_[4] { #define QS_STATE_ENTRY_(state_, qsId_) \ QS_CRIT_ENTRY(); \ QS_MEM_SYS(); \ - QS_BEGIN_PRE_(QS_QEP_STATE_ENTRY, (qsId_)) \ - QS_OBJ_PRE_(this); \ - QS_FUN_PRE_(state_); \ - QS_END_PRE_() \ + QS_BEGIN_PRE(QS_QEP_STATE_ENTRY, (qsId_)) \ + QS_OBJ_PRE(this); \ + QS_FUN_PRE(state_); \ + QS_END_PRE() \ QS_MEM_APP(); \ QS_CRIT_EXIT() @@ -87,18 +83,15 @@ static QP::QEvt const l_reservedEvt_[4] { #define QS_STATE_EXIT_(state_, qsId_) \ QS_CRIT_ENTRY(); \ QS_MEM_SYS(); \ - QS_BEGIN_PRE_(QS_QEP_STATE_EXIT, (qsId_)) \ - QS_OBJ_PRE_(this); \ - QS_FUN_PRE_(state_); \ - QS_END_PRE_() \ + QS_BEGIN_PRE(QS_QEP_STATE_EXIT, (qsId_)) \ + QS_OBJ_PRE(this); \ + QS_FUN_PRE(state_); \ + QS_END_PRE() \ QS_MEM_APP(); \ QS_CRIT_EXIT() //! @endcond -// maximum depth of state nesting in a QHsm (including the top level) -// must be >= 3 -static constexpr std::int_fast8_t QHSM_MAX_NEST_DEPTH_ {6}; //============================================================================ //$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv @@ -133,22 +126,27 @@ void QHsm::init( { QF_CRIT_STAT + QState r; + + // produce QS dictionary for QP::QHsm::top() #ifdef Q_SPY QS_CRIT_ENTRY(); QS_MEM_SYS(); if ((QS::priv_.flags & 0x01U) == 0U) { QS::priv_.flags |= 0x01U; - QS_MEM_APP(); - QS_CRIT_EXIT(); - QS_FUN_DICTIONARY(&QP::QHsm::top); + r = Q_RET_HANDLED; } else { - QS_MEM_APP(); - QS_CRIT_EXIT(); + r = Q_RET_IGNORED; + } + QS_MEM_APP(); + QS_CRIT_EXIT(); + if (r == Q_RET_HANDLED) { + QS_FUN_DICTIONARY(&QP::QHsm::top); } #else Q_UNUSED_PAR(qsId); - #endif + #endif // def Q_SPY QStateHandler t = m_state.fun; @@ -158,18 +156,18 @@ void QHsm::init( QF_CRIT_EXIT(); // execute the top-most initial tran. - QState r = (*m_temp.fun)(this, Q_EVT_CAST(QEvt)); + r = (*m_temp.fun)(this, Q_EVT_CAST(QEvt)); QF_CRIT_ENTRY(); // the top-most initial tran. must be taken Q_ASSERT_INCRIT(210, r == Q_RET_TRAN); QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QEP_STATE_INIT, qsId) - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(t); // the source state - QS_FUN_PRE_(m_temp.fun); // the target of the initial tran. - QS_END_PRE_() + QS_BEGIN_PRE(QS_QEP_STATE_INIT, qsId) + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(t); // the source state + QS_FUN_PRE(m_temp.fun); // the target of the initial tran. + QS_END_PRE() QS_MEM_APP(); QF_CRIT_EXIT(); @@ -214,11 +212,11 @@ void QHsm::init( if (r == Q_RET_TRAN) { QS_CRIT_ENTRY(); QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QEP_STATE_INIT, qsId) - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(t); // the source state - QS_FUN_PRE_(m_temp.fun); // the target of the initial tran. - QS_END_PRE_() + QS_BEGIN_PRE(QS_QEP_STATE_INIT, qsId) + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(t); // the source state + QS_FUN_PRE(m_temp.fun); // the target of the initial tran. + QS_END_PRE() QS_MEM_APP(); QS_CRIT_EXIT(); } @@ -228,11 +226,11 @@ void QHsm::init( QF_CRIT_ENTRY(); QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QEP_INIT_TRAN, qsId) - QS_TIME_PRE_(); // time stamp - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(t); // the new active state - QS_END_PRE_() + QS_BEGIN_PRE(QS_QEP_INIT_TRAN, qsId) + QS_TIME_PRE(); // time stamp + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(t); // the new active state + QS_END_PRE() QS_MEM_APP(); QF_CRIT_EXIT(); @@ -257,17 +255,18 @@ void QHsm::dispatch( QF_CRIT_STAT QF_CRIT_ENTRY(); - Q_REQUIRE_INCRIT(300, QEvt::verify_(e)); - Q_INVARIANT_INCRIT(302, (s != Q_STATE_CAST(0)) + Q_REQUIRE_INCRIT(300, (e != nullptr) && (s != nullptr)); + Q_INVARIANT_INCRIT(301, + e->verify_() && (m_state.uint == static_cast(~m_temp.uint))); QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QEP_DISPATCH, qsId) - QS_TIME_PRE_(); // time stamp - QS_SIG_PRE_(e->sig); // the signal of the event - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(s); // the current state - QS_END_PRE_() + QS_BEGIN_PRE(QS_QEP_DISPATCH, qsId) + QS_TIME_PRE(); // time stamp + QS_SIG_PRE(e->sig); // the signal of the event + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(s); // the current state + QS_END_PRE() QS_MEM_APP(); QF_CRIT_EXIT(); @@ -284,11 +283,11 @@ void QHsm::dispatch( QS_CRIT_ENTRY(); QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QEP_UNHANDLED, qsId) - QS_SIG_PRE_(e->sig); // the signal of the event - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(s); // the current state - QS_END_PRE_() + QS_BEGIN_PRE(QS_QEP_UNHANDLED, qsId) + QS_SIG_PRE(e->sig); // the signal of the event + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(s); // the current state + QS_END_PRE() QS_MEM_APP(); QS_CRIT_EXIT(); @@ -302,9 +301,22 @@ void QHsm::dispatch( Q_ENSURE_INCRIT(310, ip > 0); QF_CRIT_EXIT(); - if (r >= Q_RET_TRAN) { // regular tran. taken? - QStateHandler path[QHSM_MAX_NEST_DEPTH_]; + if (r >= Q_RET_TRAN) { // tran. (regular or history) taken? + #ifdef Q_SPY + if (r == Q_RET_TRAN_HIST) { // tran. to history? + QS_CRIT_ENTRY(); + QS_MEM_SYS(); + QS_BEGIN_PRE(QS_QEP_TRAN_HIST, qsId) + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(s); // tran. to history source + QS_FUN_PRE(m_temp.fun); // tran. to history target + QS_END_PRE() + QS_MEM_APP(); + QS_CRIT_EXIT(); + } + #endif // Q_SPY + QStateHandler path[QHSM_MAX_NEST_DEPTH_]; path[0] = m_temp.fun; // tran. target path[1] = t; // current state path[2] = s; // tran. source @@ -324,21 +336,7 @@ void QHsm::dispatch( Q_ENSURE_INCRIT(320, ip > 0); QF_CRIT_EXIT(); - ip = hsm_tran(path, qsId); // take the tran. - - #ifdef Q_SPY - if (r == Q_RET_TRAN_HIST) { - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QEP_TRAN_HIST, qsId) - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(t); // the source of the transition - QS_FUN_PRE_(path[0]); // the target of the tran. to history - QS_END_PRE_() - QS_MEM_APP(); - QS_CRIT_EXIT(); - } - #endif // Q_SPY + ip = hsm_tran(&path[0], qsId); // take the tran. // execute state entry actions in the desired order... // note: ip is the fixed upper loop bound @@ -358,11 +356,11 @@ void QHsm::dispatch( QS_CRIT_ENTRY(); QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QEP_STATE_INIT, qsId) - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(t); // the source (pseudo)state - QS_FUN_PRE_(m_temp.fun); // the target of the tran. - QS_END_PRE_() + QS_BEGIN_PRE(QS_QEP_STATE_INIT, qsId) + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(t); // the source (pseudo)state + QS_FUN_PRE(m_temp.fun); // the target of the tran. + QS_END_PRE() QS_MEM_APP(); QS_CRIT_EXIT(); @@ -404,13 +402,13 @@ void QHsm::dispatch( QS_CRIT_ENTRY(); QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QEP_TRAN, qsId) - QS_TIME_PRE_(); // time stamp - QS_SIG_PRE_(e->sig); // the signal of the event - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(s); // the source of the tran. - QS_FUN_PRE_(t); // the new active state - QS_END_PRE_() + QS_BEGIN_PRE(QS_QEP_TRAN, qsId) + QS_TIME_PRE(); // time stamp + QS_SIG_PRE(e->sig); // the signal of the event + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(s); // the source of the tran. + QS_FUN_PRE(t); // the new active state + QS_END_PRE() QS_MEM_APP(); QS_CRIT_EXIT(); } @@ -419,24 +417,24 @@ void QHsm::dispatch( else if (r == Q_RET_HANDLED) { QS_CRIT_ENTRY(); QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QEP_INTERN_TRAN, qsId) - QS_TIME_PRE_(); // time stamp - QS_SIG_PRE_(e->sig); // the signal of the event - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(s); // the source state - QS_END_PRE_() + QS_BEGIN_PRE(QS_QEP_INTERN_TRAN, qsId) + QS_TIME_PRE(); // time stamp + QS_SIG_PRE(e->sig); // the signal of the event + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(s); // the source state + QS_END_PRE() QS_MEM_APP(); QS_CRIT_EXIT(); } else { QS_CRIT_ENTRY(); QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QEP_IGNORED, qsId) - QS_TIME_PRE_(); // time stamp - QS_SIG_PRE_(e->sig); // the signal of the event - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(m_state.fun); // the current state - QS_END_PRE_() + QS_BEGIN_PRE(QS_QEP_IGNORED, qsId) + QS_TIME_PRE(); // time stamp + QS_SIG_PRE(e->sig); // the signal of the event + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(m_state.fun); // the current state + QS_END_PRE() QS_MEM_APP(); QS_CRIT_EXIT(); } @@ -452,8 +450,8 @@ void QHsm::dispatch( bool QHsm::isIn(QStateHandler const state) noexcept { QF_CRIT_STAT QF_CRIT_ENTRY(); - Q_INVARIANT_INCRIT(602, m_state.uint - == static_cast(~m_temp.uint)); + Q_INVARIANT_INCRIT(602, + m_state.uint == static_cast(~m_temp.uint)); QF_CRIT_EXIT(); bool inState = false; // assume that this HSM is not in 'state' @@ -504,7 +502,7 @@ QStateHandler QHsm::childState(QStateHandler const parent) noexcept { r = QHSM_RESERVED_EVT_(m_temp.fun, Q_EMPTY_SIG); } --lbound; - } while ((r != Q_RET_IGNORED) // QHsm::top() state not reached + } while ((r != Q_RET_IGNORED) // the top state not reached && (lbound > 0)); #ifndef Q_UNSAFE diff --git a/src/qf/qep_msm.cpp b/src/qf/qep_msm.cpp index 3742adec6..0a6c30e36 100644 --- a/src/qf/qep_msm.cpp +++ b/src/qf/qep_msm.cpp @@ -3,17 +3,10 @@ // Model: qpcpp.qm // File: ${src::qf::qep_msm.cpp} // -// This code has been generated by QM 6.2.0 . +// This code has been generated by QM 7.0.0 . // DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. // -// This code is covered by the following QP license: -// License # : LicenseRef-QL-dual -// Issued to : Any user of the QP/C++ real-time embedded framework -// Framework(s) : qpcpp -// Support ends : 2025-12-31 -// License scope: -// -// Copyright (C) 2005 Quantum Leaps, LLC . +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // Q u a n t u m L e a P s // ------------------------ @@ -21,21 +14,20 @@ // // 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: +// 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. // -// Contact information: +// NOTE: +// The GPL does NOT permit the incorporation of this code into proprietary +// programs. Please contact Quantum Leaps for commercial licensing options, +// which expressly supersede the GPL and are designed explicitly for +// closed-source distribution. +// +// Quantum Leaps contact information: // // // @@ -68,10 +60,6 @@ QP::QMState const l_msm_top_s = { nullptr }; -} // unnamed namespace - -//! @endcond - // maximum depth of state nesting in a QMsm (including the top level) static constexpr std::int_fast8_t QMSM_MAX_NEST_DEPTH_ {8}; @@ -80,6 +68,10 @@ static constexpr std::int_fast8_t QMSM_MAX_TRAN_LENGTH_ {2*QMSM_MAX_NEST_DEPTH_} // maximum depth of entry levels in a MSM for tran. to history. static constexpr std::int_fast8_t QMSM_MAX_ENTRY_DEPTH_ {4}; + +} // unnamed namespace + +//! @endcond //============================================================================ //$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv @@ -124,11 +116,11 @@ void QMsm::init( Q_ASSERT_INCRIT(210, r == Q_RET_TRAN_INIT); QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QEP_STATE_INIT, qsId) - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(m_state.obj->stateHandler); // source state - QS_FUN_PRE_(m_temp.tatbl->target->stateHandler); // target state - QS_END_PRE_() + QS_BEGIN_PRE(QS_QEP_STATE_INIT, qsId) + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(m_state.obj->stateHandler); // source state + QS_FUN_PRE(m_temp.tatbl->target->stateHandler); // target state + QS_END_PRE() QS_MEM_APP(); QF_CRIT_EXIT(); @@ -148,11 +140,11 @@ void QMsm::init( Q_ENSURE_INCRIT(290, lbound > 0); QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QEP_INIT_TRAN, qsId) - QS_TIME_PRE_(); // time stamp - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(m_state.obj->stateHandler); // the new current state - QS_END_PRE_() + QS_BEGIN_PRE(QS_QEP_INIT_TRAN, qsId) + QS_TIME_PRE(); // time stamp + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(m_state.obj->stateHandler); // the new current state + QS_END_PRE() QS_MEM_APP(); QF_CRIT_EXIT(); @@ -176,17 +168,18 @@ void QMsm::dispatch( QF_CRIT_STAT QF_CRIT_ENTRY(); - Q_REQUIRE_INCRIT(300, QEvt::verify_(e)); - Q_INVARIANT_INCRIT(302, (s != nullptr) + Q_REQUIRE_INCRIT(300, (e != nullptr) && (s != nullptr)); + Q_INVARIANT_INCRIT(301, + e->verify_() && (m_state.uint == static_cast(~m_temp.uint))); QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QEP_DISPATCH, qsId) - QS_TIME_PRE_(); // time stamp - QS_SIG_PRE_(e->sig); // the signal of the event - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(s->stateHandler); // the current state handler - QS_END_PRE_() + QS_BEGIN_PRE(QS_QEP_DISPATCH, qsId) + QS_TIME_PRE(); // time stamp + QS_SIG_PRE(e->sig); // the signal of the event + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(s->stateHandler); // the current state handler + QS_END_PRE() QS_MEM_APP(); QF_CRIT_EXIT(); @@ -205,21 +198,17 @@ void QMsm::dispatch( else if (r == Q_RET_SUPER) { t = t->superstate; // advance to the superstate } - // event unhandled and passed to a submachine superstate? - else if (r == Q_RET_SUPER_SUB) { - t = m_temp.obj; // current host state of the submachie - } else { // event unhandled due to a guard QF_CRIT_ENTRY(); // event must be unhandled due to a guard evaluating to 'false' Q_ASSERT_INCRIT(310, r == Q_RET_UNHANDLED); QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QEP_UNHANDLED, qsId) - QS_SIG_PRE_(e->sig); // the signal of the event - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(t->stateHandler); // the current state - QS_END_PRE_() + QS_BEGIN_PRE(QS_QEP_UNHANDLED, qsId) + QS_SIG_PRE(e->sig); // the signal of the event + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(t->stateHandler); // the current state + QS_END_PRE() QS_MEM_APP(); QF_CRIT_EXIT(); @@ -233,96 +222,62 @@ void QMsm::dispatch( QF_CRIT_EXIT(); if (r >= Q_RET_TRAN) { // any kind of tran. taken? - #ifdef Q_SPY - QMState const * const ts = t; // tran. source for QS tracing - QF_CRIT_ENTRY(); // the tran. source state must not be nullptr - Q_ASSERT_INCRIT(330, ts != nullptr); + Q_ASSERT_INCRIT(330, t != nullptr); QF_CRIT_EXIT(); - #endif // Q_SPY - lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound - do { - // save the tran-action table before it gets clobbered - QMTranActTable const * const tatbl = m_temp.tatbl; - QAsmAttr tmp; // temporary to save intermediate values - - // was TRAN, TRAN_INIT, or TRAN_EP taken? - if (r <= Q_RET_TRAN_EP) { - m_temp.obj = nullptr; // clear - exitToTranSource_(s, t, qsId); - r = execTatbl_(tatbl, qsId); - s = m_state.obj; - } - // was a tran. segment to history taken? - else if (r == Q_RET_TRAN_HIST) { - tmp.obj = m_state.obj; // save history - m_state.obj = s; // restore the original state - exitToTranSource_(s, t, qsId); - static_cast(execTatbl_(tatbl, qsId)); - r = enterHistory_(tmp.obj, qsId); - s = m_state.obj; - } - else { - QF_CRIT_ENTRY(); - // must be tran. to exit point - Q_ASSERT_INCRIT(340, r == Q_RET_TRAN_XP); - QF_CRIT_EXIT(); - - tmp.act = m_state.act; // save XP action - m_state.obj = s; // restore the original state - r = (*tmp.act)(this); // execute the XP action - if (r == Q_RET_TRAN) { // XP -> TRAN ? - #ifdef Q_SPY - tmp.tatbl = m_temp.tatbl; // save m_temp - #endif // Q_SPY - exitToTranSource_(s, t, qsId); - // take the tran-to-XP segment inside submachine - static_cast(execTatbl_(tatbl, qsId)); - s = m_state.obj; - #ifdef Q_SPY - m_temp.tatbl = tmp.tatbl; // restore m_temp - #endif // Q_SPY - } - else if (r == Q_RET_TRAN_HIST) { // XP -> HIST ? - tmp.obj = m_state.obj; // save the history - m_state.obj = s; // restore the original state #ifdef Q_SPY - s = m_temp.obj; // save m_temp + QMState const * const ts = t; // for saving tran. table #endif // Q_SPY - exitToTranSource_(m_state.obj, t, qsId); - // take the tran-to-XP segment inside submachine - static_cast(execTatbl_(tatbl, qsId)); - #ifdef Q_SPY - m_temp.obj = s; // restore m_temp - #endif // Q_SPY - s = m_state.obj; - m_state.obj = tmp.obj; // restore the history - } - else { - QF_CRIT_ENTRY(); - // TRAN_XP must NOT be followed by any other tran. type - Q_ASSERT_INCRIT(330, r < Q_RET_TRAN); - QF_CRIT_EXIT(); - } - } + QMTranActTable const *tatbl; + + if (r == Q_RET_TRAN_HIST) { // was it tran. to history? + QMState const * const hist = m_state.obj; // save history + m_state.obj = s; // restore the original state + QS_CRIT_ENTRY(); + QS_MEM_SYS(); + QS_BEGIN_PRE(QS_QEP_TRAN_HIST, qsId) + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(t->stateHandler); // source state handler + QS_FUN_PRE(hist->stateHandler); // target state handler + QS_END_PRE() + QS_MEM_APP(); + QS_CRIT_EXIT(); + + // save the tran-action table before it gets clobbered + tatbl = m_temp.tatbl; + exitToTranSource_(s, t, qsId); + static_cast(execTatbl_(tatbl, qsId)); + r = enterHistory_(hist, qsId); + s = m_state.obj; + t = s; // set target to the current state + } + + lbound = QMSM_MAX_NEST_DEPTH_; // fixed upper loop bound + while ((r >= Q_RET_TRAN) && (lbound > 0)) { + // save the tran-action table before it gets clobbered + tatbl = m_temp.tatbl; + m_temp.obj = nullptr; // clear + exitToTranSource_(s, t, qsId); + r = execTatbl_(tatbl, qsId); + s = m_state.obj; t = s; // set target to the current state - --lbound; - } while ((r >= Q_RET_TRAN) && (lbound > 0)); + --lbound; + } QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(350, lbound > 0); + Q_ENSURE_INCRIT(360, lbound > 0); QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QEP_TRAN, qsId) - QS_TIME_PRE_(); // time stamp - QS_SIG_PRE_(e->sig); // the signal of the event - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(ts->stateHandler); // the tran. source - QS_FUN_PRE_(s->stateHandler); // the new active state - QS_END_PRE_() + QS_BEGIN_PRE(QS_QEP_TRAN, qsId) + QS_TIME_PRE(); // time stamp + QS_SIG_PRE(e->sig); // the signal of the event + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(ts->stateHandler); // the tran. source + QS_FUN_PRE(s->stateHandler); // the new active state + QS_END_PRE() QS_MEM_APP(); QF_CRIT_EXIT(); @@ -336,12 +291,12 @@ void QMsm::dispatch( Q_ASSERT_INCRIT(380, t != nullptr); QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QEP_INTERN_TRAN, qsId) - QS_TIME_PRE_(); // time stamp - QS_SIG_PRE_(e->sig); // the signal of the event - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(t->stateHandler); // the source state - QS_END_PRE_() + QS_BEGIN_PRE(QS_QEP_INTERN_TRAN, qsId) + QS_TIME_PRE(); // time stamp + QS_SIG_PRE(e->sig); // the signal of the event + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(t->stateHandler); // the source state + QS_END_PRE() QS_MEM_APP(); QF_CRIT_EXIT(); @@ -349,16 +304,13 @@ void QMsm::dispatch( // event bubbled to the 'top' state? else if (t == nullptr) { QS_CRIT_ENTRY(); - // current state can't be nullptr - Q_ASSERT_INCRIT(390, s != nullptr); - QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QEP_IGNORED, qsId) - QS_TIME_PRE_(); // time stamp - QS_SIG_PRE_(e->sig); // the signal of the event - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(s->stateHandler); // the current state - QS_END_PRE_() + QS_BEGIN_PRE(QS_QEP_IGNORED, qsId) + QS_TIME_PRE(); // time stamp + QS_SIG_PRE(e->sig); // the signal of the event + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(s->stateHandler); // the current state + QS_END_PRE() QS_MEM_APP(); QS_CRIT_EXIT(); } @@ -439,7 +391,9 @@ QMState const * QMsm::childStateObj(QMState const * const parent) const noexcept } QF_CRIT_ENTRY(); - Q_ENSURE_INCRIT(690, isFound && (lbound > 0)); + // NOTE: the following postcondition can only succeed when + // (lbound > 0), so no extra check is necessary. + Q_ENSURE_INCRIT(690, isFound); QF_CRIT_EXIT(); return child; // return the child @@ -471,37 +425,23 @@ QState QMsm::execTatbl_( QS_CRIT_ENTRY(); QS_MEM_SYS(); if (r == Q_RET_ENTRY) { - QS_BEGIN_PRE_(QS_QEP_STATE_ENTRY, qsId) - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(m_temp.obj->stateHandler); // entered state - QS_END_PRE_() + QS_BEGIN_PRE(QS_QEP_STATE_ENTRY, qsId) + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(m_temp.obj->stateHandler); // entered state + QS_END_PRE() } else if (r == Q_RET_EXIT) { - QS_BEGIN_PRE_(QS_QEP_STATE_EXIT, qsId) - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(m_temp.obj->stateHandler); // exited state - QS_END_PRE_() + QS_BEGIN_PRE(QS_QEP_STATE_EXIT, qsId) + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(m_temp.obj->stateHandler); // exited state + QS_END_PRE() } else if (r == Q_RET_TRAN_INIT) { - QS_BEGIN_PRE_(QS_QEP_STATE_INIT, qsId) - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(tatbl->target->stateHandler); // source - QS_FUN_PRE_(m_temp.tatbl->target->stateHandler); // target - QS_END_PRE_() - } - else if (r == Q_RET_TRAN_EP) { - QS_BEGIN_PRE_(QS_QEP_TRAN_EP, qsId) - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(tatbl->target->stateHandler); // source - QS_FUN_PRE_(m_temp.tatbl->target->stateHandler); // target - QS_END_PRE_() - } - else if (r == Q_RET_TRAN_XP) { - QS_BEGIN_PRE_(QS_QEP_TRAN_XP, qsId) - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(tatbl->target->stateHandler); // source - QS_FUN_PRE_(m_temp.tatbl->target->stateHandler); // target - QS_END_PRE_() + QS_BEGIN_PRE(QS_QEP_STATE_INIT, qsId) + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(tatbl->target->stateHandler); // source + QS_FUN_PRE(m_temp.tatbl->target->stateHandler); // target + QS_END_PRE() } else { // empty @@ -545,22 +485,15 @@ void QMsm::exitToTranSource_( QS_CRIT_ENTRY(); QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QEP_STATE_EXIT, qsId) - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(s->stateHandler); // the exited state handler - QS_END_PRE_() + QS_BEGIN_PRE(QS_QEP_STATE_EXIT, qsId) + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(s->stateHandler); // the exited state handler + QS_END_PRE() QS_MEM_APP(); QS_CRIT_EXIT(); } s = s->superstate; // advance to the superstate - - if (s == nullptr) { // reached the top of a submachine? - s = m_temp.obj; // the superstate from QM_SM_EXIT() - QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(880, s != nullptr); // must be valid - QF_CRIT_EXIT(); - } } QF_CRIT_ENTRY(); Q_ENSURE_INCRIT(890, lbound > 0); @@ -576,35 +509,20 @@ QState QMsm::enterHistory_( Q_UNUSED_PAR(qsId); #endif - QMState const *s = hist; - QMState const *ts = m_state.obj; // tran. source + // record the entry path from current state to history QMState const *epath[QMSM_MAX_ENTRY_DEPTH_]; - - QF_CRIT_STAT - - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QEP_TRAN_HIST, qsId) - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(ts->stateHandler); // source state handler - QS_FUN_PRE_(hist->stateHandler); // target state handler - QS_END_PRE_() - QS_MEM_APP(); - QS_CRIT_EXIT(); - + QMState const *s = hist; std::int_fast8_t i = 0; // tran. entry path index - while ((s != ts) && (i < QMSM_MAX_ENTRY_DEPTH_)) { + while ((s != m_state.obj) && (i < (QMSM_MAX_ENTRY_DEPTH_ - 1))) { if (s->entryAction != nullptr) { epath[i] = s; ++i; } s = s->superstate; - if (s == nullptr) { - ts = s; // force exit from the for-loop - } } + QF_CRIT_STAT QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(910, s == ts); + Q_ASSERT_INCRIT(910, s == m_state.obj); QF_CRIT_EXIT(); // retrace the entry path in reverse (desired) order... @@ -614,10 +532,10 @@ QState QMsm::enterHistory_( QS_CRIT_ENTRY(); QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QEP_STATE_ENTRY, qsId) - QS_OBJ_PRE_(this); - QS_FUN_PRE_(epath[i]->stateHandler); // entered state handler - QS_END_PRE_() + QS_BEGIN_PRE(QS_QEP_STATE_ENTRY, qsId) + QS_OBJ_PRE(this); + QS_FUN_PRE(epath[i]->stateHandler); // entered state handler + QS_END_PRE() QS_MEM_APP(); QS_CRIT_EXIT(); } @@ -628,6 +546,15 @@ QState QMsm::enterHistory_( QState r; if (hist->initAction != nullptr) { r = (*hist->initAction)(this); // execute the tran. action + QS_CRIT_ENTRY(); + QS_MEM_SYS(); + QS_BEGIN_PRE(QS_QEP_STATE_INIT, qsId) + QS_OBJ_PRE(this); // this state machine object + QS_FUN_PRE(hist->stateHandler); // source + QS_FUN_PRE(m_temp.tatbl->target->stateHandler); // target + QS_END_PRE() + QS_MEM_APP(); + QS_CRIT_EXIT(); } else { r = Q_RET_NULL; diff --git a/src/qf/qf_act.cpp b/src/qf/qf_act.cpp index 909ab7bda..f0c8de6ef 100644 --- a/src/qf/qf_act.cpp +++ b/src/qf/qf_act.cpp @@ -3,17 +3,10 @@ // Model: qpcpp.qm // File: ${src::qf::qf_act.cpp} // -// This code has been generated by QM 6.2.0 . +// This code has been generated by QM 7.0.0 . // DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. // -// This code is covered by the following QP license: -// License # : LicenseRef-QL-dual -// Issued to : Any user of the QP/C++ real-time embedded framework -// Framework(s) : qpcpp -// Support ends : 2025-12-31 -// License scope: -// -// Copyright (C) 2005 Quantum Leaps, LLC . +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // Q u a n t u m L e a P s // ------------------------ @@ -21,21 +14,20 @@ // // 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: +// 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. // -// Contact information: +// NOTE: +// The GPL does NOT permit the incorporation of this code into proprietary +// programs. Please contact Quantum Leaps for commercial licensing options, +// which expressly supersede the GPL and are designed explicitly for +// closed-source distribution. +// +// Quantum Leaps contact information: // // // @@ -91,7 +83,6 @@ void bzero_( } // namespace QF } // namespace QP //$enddef${QF::QF-pkg} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - //$define${QF::types::QF_LOG2} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv namespace QP { @@ -130,3 +121,17 @@ std::uint_fast8_t QF_LOG2(QP::QPSetBits x) noexcept { } // namespace QP //$enddef${QF::types::QF_LOG2} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +#ifndef Q_UNSAFE +//$define${QF::types::QPtrDis} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +namespace QP { + +//${QF::types::QPtrDis} ...................................................... + +//${QF::types::QPtrDis::QPtrDis} ............................................. +QPtrDis::QPtrDis(void const * const ptr) noexcept + : m_ptr_dis(static_cast(~Q_PTR2UINT_CAST_(ptr))) +{} + +} // namespace QP +//$enddef${QF::types::QPtrDis} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +#endif diff --git a/src/qf/qf_actq.cpp b/src/qf/qf_actq.cpp index 35889ed2d..a1b49acef 100644 --- a/src/qf/qf_actq.cpp +++ b/src/qf/qf_actq.cpp @@ -3,17 +3,10 @@ // Model: qpcpp.qm // File: ${src::qf::qf_actq.cpp} // -// This code has been generated by QM 6.2.0 . +// This code has been generated by QM 7.0.0 . // DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. // -// This code is covered by the following QP license: -// License # : LicenseRef-QL-dual -// Issued to : Any user of the QP/C++ real-time embedded framework -// Framework(s) : qpcpp -// Support ends : 2025-12-31 -// License scope: -// -// Copyright (C) 2005 Quantum Leaps, LLC . +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // Q u a n t u m L e a P s // ------------------------ @@ -21,21 +14,20 @@ // // 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: +// 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. // -// Contact information: +// NOTE: +// The GPL does NOT permit the incorporation of this code into proprietary +// programs. Please contact Quantum Leaps for commercial licensing options, +// which expressly supersede the GPL and are designed explicitly for +// closed-source distribution. +// +// Quantum Leaps contact information: // // // @@ -77,46 +69,49 @@ bool QActive::post_( #endif #ifdef Q_UTEST // test? - #if Q_UTEST != 0 // testing QP-stub? + #if (Q_UTEST != 0) // testing QP-stub? if (m_temp.fun == Q_STATE_CAST(0)) { // QActiveDummy? return static_cast(this)->fakePost(e, margin, sender); } - #endif - #endif + #endif // (Q_UTEST != 0) + #endif // def Q_UTEST QF_CRIT_STAT QF_CRIT_ENTRY(); QF_MEM_SYS(); - #ifndef Q_UNSAFE - Q_REQUIRE_INCRIT(100, QEvt::verify_(e)); - - std::uint8_t const pcopy = static_cast(~m_prio_dis); - Q_INVARIANT_INCRIT(102, m_prio == pcopy); - #endif + Q_REQUIRE_INCRIT(200, e != nullptr); - QEQueueCtr nFree = m_eQueue.m_nFree; // get volatile into temporary + QEQueueCtr tmp = m_eQueue.m_nFree; // get volatile into temporary + #ifndef Q_UNSAFE + QEQueueCtr dis = static_cast(~m_eQueue.m_nFree_dis); + Q_INVARIANT_INCRIT(201, e->verify_() && (tmp == dis)); + #endif // ndef Q_UNSAFE // test-probe#1 for faking queue overflow QS_TEST_PROBE_DEF(&QActive::post_) QS_TEST_PROBE_ID(1, - nFree = 0U; + tmp = 0U; // fake no free events ) + // required margin available? bool status; if (margin == QF::NO_MARGIN) { - if (nFree > 0U) { + if (tmp > 0U) { // free entries available in the queue? status = true; // can post } - else { + else { // no free entries available status = false; // cannot post - Q_ERROR_INCRIT(110); // must be able to post the event + + // The queue overflows, but QF_NO_MARGIN indicates that + // the "event delivery guarantee" is required. + Q_ERROR_INCRIT(210); // must be able to post the event } } - else if (nFree > static_cast(margin)) { + else if (tmp > static_cast(margin)) { status = true; // can post } - else { + else { // the # free entries below the requested margin status = false; // cannot post, but don't assert } @@ -126,22 +121,26 @@ bool QActive::post_( } if (status) { // can post the event? + --tmp; // one free entry just used up + + m_eQueue.m_nFree = tmp; // update the original + #ifndef Q_UNSAFE + m_eQueue.m_nFree_dis = static_cast(~tmp); + #endif // ndef Q_UNSAFE - --nFree; // one free entry just used up - m_eQueue.m_nFree = nFree; // update the original - if (m_eQueue.m_nMin > nFree) { - m_eQueue.m_nMin = nFree; // update minimum so far + if (m_eQueue.m_nMin > tmp) { + m_eQueue.m_nMin = tmp; // update minimum so far } - QS_BEGIN_PRE_(QS_QF_ACTIVE_POST, m_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_(this); // this active object - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_EQC_PRE_(nFree); // # free entries - QS_EQC_PRE_(m_eQueue.m_nMin); // min # free entries - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_ACTIVE_POST, m_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(this); // this active object + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_EQC_PRE(tmp); // # free entries + QS_EQC_PRE(m_eQueue.m_nMin); // min # free entries + QS_END_PRE() #ifdef Q_UTEST // callback to examine the posted event under the same conditions @@ -156,47 +155,61 @@ bool QActive::post_( QF_CRIT_ENTRY(); QF_MEM_SYS(); } - #endif + #endif // def Q_UTEST - if (m_eQueue.m_frontEvt == nullptr) { // empty queue? + if (m_eQueue.m_frontEvt == nullptr) { // is the queue empty? m_eQueue.m_frontEvt = e; // deliver event directly + #ifndef Q_UNSAFE + Q_INVARIANT_INCRIT(211, m_eQueue.m_frontEvt_dis + == static_cast(~Q_PTR2UINT_CAST_(nullptr))); + m_eQueue.m_frontEvt_dis = + static_cast(~Q_PTR2UINT_CAST_(e)); + #endif // ndef Q_UNSAFE + #ifdef QXK_HPP_ - if (m_state.act == Q_ACTION_CAST(0)) { // eXtended thread? - QXTHREAD_EQUEUE_SIGNAL_(this); // signal the event queue + if (m_state.act == nullptr) { // eXtended thread? + QXTHREAD_EQUEUE_SIGNAL_(this); // signal eXtended Thread } else { - QACTIVE_EQUEUE_SIGNAL_(this); // signal the event queue + QACTIVE_EQUEUE_SIGNAL_(this); // signal the Active Object } #else - QACTIVE_EQUEUE_SIGNAL_(this); // signal the event queue - #endif + QACTIVE_EQUEUE_SIGNAL_(this); // signal the Active Object + #endif // def QXK_HPP_ } - // queue is not empty, insert event into the ring-buffer - else { - // insert event into the ring buffer (FIFO) - m_eQueue.m_ring[m_eQueue.m_head] = e; + else { // queue was not empty, insert event into the ring-buffer + tmp = m_eQueue.m_head; // get volatile into temporary + #ifndef Q_UNSAFE + dis = static_cast(~m_eQueue.m_head_dis); + Q_INVARIANT_INCRIT(212, tmp == dis); + #endif // ndef Q_UNSAFE + m_eQueue.m_ring[tmp] = e; // insert e into buffer - if (m_eQueue.m_head == 0U) { // need to wrap head? - m_eQueue.m_head = m_eQueue.m_end; // wrap around + if (tmp == 0U) { // need to wrap the head? + tmp = m_eQueue.m_end; } - // advance the head (counter clockwise) - m_eQueue.m_head = (m_eQueue.m_head - 1U); + --tmp; // advance the head (counter-clockwise) + + m_eQueue.m_head = tmp; // update the original + #ifndef Q_UNSAFE + m_eQueue.m_head_dis = static_cast(~tmp); + #endif // ndef Q_UNSAFE } QF_MEM_APP(); QF_CRIT_EXIT(); } - else { // cannot post the event - - QS_BEGIN_PRE_(QS_QF_ACTIVE_POST_ATTEMPT, m_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_(this); // this active object - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_EQC_PRE_(nFree); // # free entries - QS_EQC_PRE_(margin); // margin requested - QS_END_PRE_() + else { // event cannot be posted + + QS_BEGIN_PRE(QS_QF_ACTIVE_POST_ATTEMPT, m_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(this); // this active object + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_EQC_PRE(tmp); // # free entries + QS_EQC_PRE(margin); // margin requested + QS_END_PRE() #ifdef Q_UTEST // callback to examine the posted event under the same conditions @@ -211,14 +224,14 @@ bool QActive::post_( QF_CRIT_ENTRY(); QF_MEM_SYS(); } - #endif + #endif // def Q_USTEST QF_MEM_APP(); QF_CRIT_EXIT(); #if (QF_MAX_EPOOL > 0U) QF::gc(e); // recycle the event to avoid a leak - #endif + #endif // (QF_MAX_EPOOL > 0U) } return status; @@ -233,57 +246,58 @@ namespace QP { //${QF::QActive::postLIFO} ................................................... void QActive::postLIFO(QEvt const * const e) noexcept { #ifdef Q_UTEST // test? - #if Q_UTEST != 0 // testing QP-stub? + #if (Q_UTEST != 0) // testing QP-stub? if (m_temp.fun == Q_STATE_CAST(0)) { // QActiveDummy? static_cast(this)->QActiveDummy::fakePostLIFO(e); return; } - #endif - #endif + #endif // (Q_UTEST != 0) + #endif // def Q_UTEST QF_CRIT_STAT QF_CRIT_ENTRY(); QF_MEM_SYS(); - #ifndef Q_UNSAFE - Q_REQUIRE_INCRIT(200, QEvt::verify_(e)); + Q_REQUIRE_INCRIT(300, e != nullptr); - std::uint8_t const pcopy = static_cast(~m_prio_dis); - Q_INVARIANT_INCRIT(202, m_prio == pcopy); - #endif - - #ifdef QXK_HPP_ - Q_REQUIRE_INCRIT(200, m_state.act != Q_ACTION_CAST(0)); - #endif - - QEQueueCtr nFree = m_eQueue.m_nFree; // get volatile into temporary + QEQueueCtr tmp = m_eQueue.m_nFree; // get volatile into temporary + #ifndef Q_UNSAFE + QEQueueCtr dis = static_cast(~m_eQueue.m_nFree_dis); + Q_INVARIANT_INCRIT(301, e->verify_() && (tmp == dis)); + #endif // ndef Q_UNSAFE // test-probe#1 for faking queue overflow QS_TEST_PROBE_DEF(&QActive::postLIFO) QS_TEST_PROBE_ID(1, - nFree = 0U; + tmp = 0U; // fake no free events ) - Q_REQUIRE_INCRIT(201, nFree != 0U); + // The queue must NOT overflow for the LIFO posting policy. + Q_REQUIRE_INCRIT(310, tmp != 0U); - if (e->getPoolNum_() != 0U) { // is it a mutable event? + if (e->getPoolNum_() != 0U) { QEvt_refCtr_inc_(e); // increment the reference counter } - --nFree; // one free entry just used up - m_eQueue.m_nFree = nFree; // update the original - if (m_eQueue.m_nMin > nFree) { - m_eQueue.m_nMin = nFree; // update minimum so far + --tmp; // one free entry just used up + + m_eQueue.m_nFree = tmp; // update the original + #ifndef Q_UNSAFE + m_eQueue.m_nFree_dis = static_cast(~tmp); + #endif // ndef Q_UNSAFE + + if (m_eQueue.m_nMin > tmp) { + m_eQueue.m_nMin = tmp; // update minimum so far } - QS_BEGIN_PRE_(QS_QF_ACTIVE_POST_LIFO, m_prio) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of this event - QS_OBJ_PRE_(this); // this active object - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_EQC_PRE_(nFree); // # free entries - QS_EQC_PRE_(m_eQueue.m_nMin); // min # free entries - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_ACTIVE_POST_LIFO, m_prio) + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(e->sig); // the signal of this event + QS_OBJ_PRE(this); // this active object + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_EQC_PRE(tmp); // # free entries + QS_EQC_PRE(m_eQueue.m_nMin); // min # free entries + QS_END_PRE() #ifdef Q_UTEST // callback to examine the posted event under the same conditions @@ -298,21 +312,33 @@ void QActive::postLIFO(QEvt const * const e) noexcept { QF_CRIT_ENTRY(); QF_MEM_SYS(); } - #endif + #endif // def Q_UTEST QEvt const * const frontEvt = m_eQueue.m_frontEvt; m_eQueue.m_frontEvt = e; // deliver the event directly to the front + #ifndef Q_UNSAFE + m_eQueue.m_frontEvt_dis = + static_cast(~Q_PTR2UINT_CAST_(e)); + #endif // ndef Q_UNSAFE - if (frontEvt == nullptr) { // was the queue empty? - QACTIVE_EQUEUE_SIGNAL_(this); // signal the event queue - } - else { // queue was not empty, leave the event in the ring-buffer - m_eQueue.m_tail = (m_eQueue.m_tail + 1U); - if (m_eQueue.m_tail == m_eQueue.m_end) { // need to wrap the tail? - m_eQueue.m_tail = 0U; // wrap around + if (frontEvt != nullptr) { // was the queue NOT empty? + tmp = m_eQueue.m_tail; // get volatile into temporary; + #ifndef Q_UNSAFE + dis = static_cast(~m_eQueue.m_tail_dis); + Q_INVARIANT_INCRIT(311, tmp == dis); + #endif // ndef Q_UNSAFE + ++tmp; + if (tmp == m_eQueue.m_end) { // need to wrap the tail? + tmp = 0U; // wrap around } - - m_eQueue.m_ring[m_eQueue.m_tail] = frontEvt; + m_eQueue.m_tail = tmp; + #ifndef Q_UNSAFE + m_eQueue.m_tail_dis = static_cast(~tmp); + #endif // ndef Q_UNSAFE + m_eQueue.m_ring[tmp] = frontEvt; + } + else { // queue was empty + QACTIVE_EQUEUE_SIGNAL_(this); // signal the event queue } QF_MEM_APP(); @@ -331,43 +357,78 @@ QEvt const * QActive::get_() noexcept { QF_CRIT_ENTRY(); QF_MEM_SYS(); + // wait for event to arrive directly (depends on QP port) + // NOTE: might use assertion-IDs 400-409 QACTIVE_EQUEUE_WAIT_(this); // wait for event to arrive directly // always remove evt from the front QEvt const * const e = m_eQueue.m_frontEvt; - Q_INVARIANT_INCRIT(312, QEvt::verify_(e)); + QEQueueCtr tmp = m_eQueue.m_nFree; // get volatile into tmp + + #ifndef Q_UNSAFE + Q_INVARIANT_INCRIT(410, e != nullptr); // queue must NOT be empty + Q_INVARIANT_INCRIT(411, Q_PTR2UINT_CAST_(e) + == static_cast(~m_eQueue.m_frontEvt_dis)); + QEQueueCtr dis = static_cast(~m_eQueue.m_nFree_dis); + Q_INVARIANT_INCRIT(412, tmp == dis); + #endif // ndef Q_UNSAFE + + ++tmp; // one more free event in the queue - QEQueueCtr const nFree = m_eQueue.m_nFree + 1U; // get volatile into tmp - m_eQueue.m_nFree = nFree; // update the # free + m_eQueue.m_nFree = tmp; // update the # free + #ifndef Q_UNSAFE + m_eQueue.m_nFree_dis = static_cast(~tmp); + #endif // ndef Q_UNSAFE + + if (tmp <= m_eQueue.m_end) { // any events in the ring buffer? + QS_BEGIN_PRE(QS_QF_ACTIVE_GET, m_prio) + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(e->sig); // the signal of this event + QS_OBJ_PRE(this); // this active object + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_EQC_PRE(tmp); // # free entries + QS_END_PRE() - if (nFree <= m_eQueue.m_end) { // any events in the ring buffer? // remove event from the tail - m_eQueue.m_frontEvt = m_eQueue.m_ring[m_eQueue.m_tail]; - if (m_eQueue.m_tail == 0U) { // need to wrap the tail? - m_eQueue.m_tail = m_eQueue.m_end; // wrap around + tmp = m_eQueue.m_tail; // get volatile into temporary + #ifndef Q_UNSAFE + dis = static_cast(~m_eQueue.m_tail_dis); + Q_INVARIANT_INCRIT(420, tmp == dis); + #endif // ndef Q_UNSAFE + QEvt const * const frontEvt = m_eQueue.m_ring[tmp]; + #ifndef Q_UNSAFE + Q_ASSERT_INCRIT(421, frontEvt != nullptr); + m_eQueue.m_frontEvt_dis = + static_cast(~Q_PTR2UINT_CAST_(frontEvt)); + #endif // ndef Q_UNSAFE + m_eQueue.m_frontEvt = frontEvt; // update the original + + if (tmp == 0U) { // need to wrap the tail? + tmp = m_eQueue.m_end; } - m_eQueue.m_tail = (m_eQueue.m_tail - 1U); - - QS_BEGIN_PRE_(QS_QF_ACTIVE_GET, m_prio) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of this event - QS_OBJ_PRE_(this); // this active object - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_EQC_PRE_(nFree); // # free entries - QS_END_PRE_() + --tmp; // advance the tail (counter-clockwise) + + m_eQueue.m_tail = tmp; // update the original + #ifndef Q_UNSAFE + m_eQueue.m_tail_dis = static_cast(~tmp); + #endif // ndef Q_UNSAFE } else { m_eQueue.m_frontEvt = nullptr; // the queue becomes empty + #ifndef Q_UNSAFE + m_eQueue.m_frontEvt_dis = + static_cast(~Q_PTR2UINT_CAST_(nullptr)); + #endif // ndef Q_UNSAFE // all entries in the queue must be free (+1 for fronEvt) - Q_ASSERT_INCRIT(310, nFree == (m_eQueue.m_end + 1U)); - - QS_BEGIN_PRE_(QS_QF_ACTIVE_GET_LAST, m_prio) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of this event - QS_OBJ_PRE_(this); // this active object - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_END_PRE_() + Q_ASSERT_INCRIT(310, tmp == (m_eQueue.m_end + 1U)); + + QS_BEGIN_PRE(QS_QF_ACTIVE_GET_LAST, m_prio) + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(e->sig); // the signal of this event + QS_OBJ_PRE(this); // this active object + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_END_PRE() } QF_MEM_APP(); @@ -390,6 +451,9 @@ QTicker::QTicker(std::uint_fast8_t const tickRate) noexcept { // reuse m_head for tick-rate m_eQueue.m_head = static_cast(tickRate); + #ifndef Q_UNSAFE + m_eQueue.m_head_dis = static_cast(~tickRate); + #endif // ndef Q_UNSAFE } //${QF::QTicker::init} ....................................................... @@ -405,6 +469,9 @@ void QTicker::init( QF_MEM_SYS(); m_eQueue.m_tail = 0U; + #ifndef Q_UNSAFE + m_eQueue.m_tail_dis = static_cast(~0U); + #endif // ndef Q_UNSAFE QF_MEM_APP(); QF_CRIT_EXIT(); @@ -422,14 +489,28 @@ void QTicker::dispatch( QF_CRIT_ENTRY(); QF_MEM_SYS(); - QEQueueCtr nTicks = m_eQueue.m_tail; // save # of ticks - m_eQueue.m_tail = 0U; // clear the # ticks + // get volatile into temporaries + QEQueueCtr nTicks = m_eQueue.m_tail; + QEQueueCtr const tickRate = m_eQueue.m_head; + + #ifndef Q_UNSAFE + Q_REQUIRE_INCRIT(700, nTicks > 0U); + Q_INVARIANT_INCRIT(701, nTicks + == static_cast(~m_eQueue.m_tail_dis)); + Q_INVARIANT_INCRIT(702, tickRate + == static_cast(~m_eQueue.m_head_dis)); + #endif // ndef Q_UNSAFE + + m_eQueue.m_tail = 0U; // clear # ticks + #ifndef Q_UNSAFE + m_eQueue.m_tail_dis = static_cast(~0U); + #endif // ndef Q_UNSAFE QF_MEM_APP(); QF_CRIT_EXIT(); for (; nTicks > 0U; --nTicks) { - QTimeEvt::tick(static_cast(m_eQueue.m_head), + QTimeEvt::tick(static_cast(tickRate), this); } } @@ -440,32 +521,65 @@ void QTicker::trig_(void const * const sender) noexcept { Q_UNUSED_PAR(sender); #endif + static QEvt const tickEvt(0U); // immutable event + QF_CRIT_STAT QF_CRIT_ENTRY(); QF_MEM_SYS(); - if (m_eQueue.m_frontEvt == nullptr) { + QEQueueCtr nTicks = m_eQueue.m_tail; // get volatile into temporary - static QEvt const tickEvt(0U); // immutable event + if (m_eQueue.m_frontEvt == nullptr) { + #ifndef Q_UNSAFE + Q_REQUIRE_INCRIT(800, nTicks == 0U); + Q_REQUIRE_INCRIT(801, m_eQueue.m_nFree == 1U); + Q_INVARIANT_INCRIT(802, m_eQueue.m_frontEvt_dis + == static_cast(~Q_PTR2UINT_CAST_(nullptr))); + Q_INVARIANT_INCRIT(803, + 1U == static_cast(~m_eQueue.m_nFree_dis)); + Q_INVARIANT_INCRIT(804, + 0U == static_cast(~m_eQueue.m_tail_dis)); + #endif // ndef Q_UNSAFE m_eQueue.m_frontEvt = &tickEvt; // deliver event directly - m_eQueue.m_nFree = (m_eQueue.m_nFree - 1U); // one less free event + m_eQueue.m_nFree = 0U; + #ifndef Q_UNSAFE + m_eQueue.m_frontEvt_dis = + static_cast(~Q_PTR2UINT_CAST_(&tickEvt)); + m_eQueue.m_nFree_dis = static_cast(~0U); + #endif // ndef Q_UNSAFE QACTIVE_EQUEUE_SIGNAL_(this); // signal the event queue } + else { + #ifndef Q_UNSAFE + Q_REQUIRE_INCRIT(810, (nTicks > 0U) && (nTicks < 0xFFU)); + Q_REQUIRE_INCRIT(811, m_eQueue.m_nFree == 0U); + Q_INVARIANT_INCRIT(812, m_eQueue.m_frontEvt_dis + == static_cast(~Q_PTR2UINT_CAST_(&tickEvt))); + Q_INVARIANT_INCRIT(813, + 0U == static_cast(~m_eQueue.m_nFree_dis)); + Q_INVARIANT_INCRIT(814, + nTicks == static_cast(~m_eQueue.m_tail_dis)); + #endif // ndef Q_UNSAFE + } - // account for one more tick event - m_eQueue.m_tail = (m_eQueue.m_tail + 1U); - - QS_BEGIN_PRE_(QS_QF_ACTIVE_POST, m_prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(sender); // the sender object - QS_SIG_PRE_(0U); // the signal of the event - QS_OBJ_PRE_(this); // this active object - QS_2U8_PRE_(0U, 0U); // poolNum & refCtr - QS_EQC_PRE_(0U); // # free entries - QS_EQC_PRE_(0U); // min # free entries - QS_END_PRE_() + ++nTicks; // account for one more tick event + + m_eQueue.m_tail = nTicks; // update the original + #ifndef Q_UNSAFE + m_eQueue.m_tail_dis = static_cast(~nTicks); + #endif // ndef Q_UNSAFE + + QS_BEGIN_PRE(QS_QF_ACTIVE_POST, m_prio) + QS_TIME_PRE(); // timestamp + QS_OBJ_PRE(sender); // the sender object + QS_SIG_PRE(0U); // the signal of the event + QS_OBJ_PRE(this); // this active object + QS_2U8_PRE(0U, 0U); // poolNum & refCtr + QS_EQC_PRE(0U); // # free entries + QS_EQC_PRE(0U); // min # free entries + QS_END_PRE() QF_MEM_APP(); QF_CRIT_EXIT(); diff --git a/src/qf/qf_defer.cpp b/src/qf/qf_defer.cpp index 4a00f8ec5..5cfdcc411 100644 --- a/src/qf/qf_defer.cpp +++ b/src/qf/qf_defer.cpp @@ -3,17 +3,10 @@ // Model: qpcpp.qm // File: ${src::qf::qf_defer.cpp} // -// This code has been generated by QM 6.2.0 . +// This code has been generated by QM 7.0.0 . // DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. // -// This code is covered by the following QP license: -// License # : LicenseRef-QL-dual -// Issued to : Any user of the QP/C++ real-time embedded framework -// Framework(s) : qpcpp -// Support ends : 2025-12-31 -// License scope: -// -// Copyright (C) 2005 Quantum Leaps, LLC . +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // Q u a n t u m L e a P s // ------------------------ @@ -21,21 +14,20 @@ // // 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: +// 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. // -// Contact information: +// NOTE: +// The GPL does NOT permit the incorporation of this code into proprietary +// programs. Please contact Quantum Leaps for commercial licensing options, +// which expressly supersede the GPL and are designed explicitly for +// closed-source distribution. +// +// Quantum Leaps contact information: // // // @@ -75,13 +67,13 @@ bool QActive::defer( QS_CRIT_STAT QS_CRIT_ENTRY(); QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QF_ACTIVE_DEFER, m_prio) - QS_TIME_PRE_(); // time stamp - QS_OBJ_PRE_(this); // this active object - QS_OBJ_PRE_(eq); // the deferred queue - QS_SIG_PRE_(e->sig); // the signal of the event - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_ACTIVE_DEFER, m_prio) + QS_TIME_PRE(); // time stamp + QS_OBJ_PRE(this); // this active object + QS_OBJ_PRE(eq); // the deferred queue + QS_SIG_PRE(e->sig); // the signal of the event + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_END_PRE() QS_MEM_APP(); QS_CRIT_EXIT(); @@ -119,13 +111,13 @@ bool QActive::recall(QEQueue * const eq) noexcept { QEvt_refCtr_dec_(e); // decrement the reference counter } - QS_BEGIN_PRE_(QS_QF_ACTIVE_RECALL, m_prio) - QS_TIME_PRE_(); // time stamp - QS_OBJ_PRE_(this); // this active object - QS_OBJ_PRE_(eq); // the deferred queue - QS_SIG_PRE_(e->sig); // the signal of the event - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_ACTIVE_RECALL, m_prio) + QS_TIME_PRE(); // time stamp + QS_OBJ_PRE(this); // this active object + QS_OBJ_PRE(eq); // the deferred queue + QS_SIG_PRE(e->sig); // the signal of the event + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_END_PRE() QF_MEM_APP(); QF_CRIT_EXIT(); @@ -136,11 +128,11 @@ bool QActive::recall(QEQueue * const eq) noexcept { QS_CRIT_ENTRY(); QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QF_ACTIVE_RECALL_ATTEMPT, m_prio) - QS_TIME_PRE_(); // time stamp - QS_OBJ_PRE_(this); // this active object - QS_OBJ_PRE_(eq); // the deferred queue - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_ACTIVE_RECALL_ATTEMPT, m_prio) + QS_TIME_PRE(); // time stamp + QS_OBJ_PRE(this); // this active object + QS_OBJ_PRE(eq); // the deferred queue + QS_END_PRE() QS_MEM_APP(); QS_CRIT_EXIT(); diff --git a/src/qf/qf_dyn.cpp b/src/qf/qf_dyn.cpp index 1f06fe432..22facab54 100644 --- a/src/qf/qf_dyn.cpp +++ b/src/qf/qf_dyn.cpp @@ -3,17 +3,10 @@ // Model: qpcpp.qm // File: ${src::qf::qf_dyn.cpp} // -// This code has been generated by QM 6.2.0 . +// This code has been generated by QM 7.0.0 . // DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. // -// This code is covered by the following QP license: -// License # : LicenseRef-QL-dual -// Issued to : Any user of the QP/C++ real-time embedded framework -// Framework(s) : qpcpp -// Support ends : 2025-12-31 -// License scope: -// -// Copyright (C) 2005 Quantum Leaps, LLC . +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // Q u a n t u m L e a P s // ------------------------ @@ -21,21 +14,20 @@ // // 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: +// 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. // -// Contact information: +// NOTE: +// The GPL does NOT permit the incorporation of this code into proprietary +// programs. Please contact Quantum Leaps for commercial licensing options, +// which expressly supersede the GPL and are designed explicitly for +// closed-source distribution. +// +// Quantum Leaps contact information: // // // @@ -178,17 +170,17 @@ QEvt * newX_( if (e != nullptr) { // was e allocated correctly? e->sig = static_cast(sig); // set the signal + e->evtTag_ = static_cast((poolNum << 4U) | 0x0FU); e->refCtr_ = 0U; // initialize the reference counter to 0 - e->evtTag_ = static_cast(QEvt::MARKER | poolNum); QS_CRIT_ENTRY(); QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QF_NEW, + QS_BEGIN_PRE(QS_QF_NEW, static_cast(QS_EP_ID) + poolNum) - 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_() + 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() QS_MEM_APP(); QS_CRIT_EXIT(); } @@ -201,12 +193,12 @@ QEvt * newX_( Q_ASSERT_INCRIT(320, margin != NO_MARGIN); QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QF_NEW_ATTEMPT, + QS_BEGIN_PRE(QS_QF_NEW_ATTEMPT, static_cast(QS_EP_ID) + poolNum) - 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_() + 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() QS_MEM_APP(); QF_CRIT_EXIT(); @@ -221,7 +213,8 @@ QEvt * newX_( void gc(QEvt const * const e) noexcept { QF_CRIT_STAT QF_CRIT_ENTRY(); - Q_REQUIRE_INCRIT(400, QEvt::verify_(e)); + Q_REQUIRE_INCRIT(400, e != nullptr); + Q_INVARIANT_INCRIT(401, e->verify_()); std::uint_fast8_t const poolNum = e->getPoolNum_(); @@ -230,12 +223,12 @@ void gc(QEvt const * const e) noexcept { if (e->refCtr_ > 1U) { // isn't this the last reference? - QS_BEGIN_PRE_(QS_QF_GC_ATTEMPT, + QS_BEGIN_PRE(QS_QF_GC_ATTEMPT, static_cast(QS_EP_ID) + poolNum) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of the event - QS_2U8_PRE_(poolNum, e->refCtr_); // poolNum & refCtr - QS_END_PRE_() + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(e->sig); // the signal of the event + QS_2U8_PRE(poolNum, e->refCtr_); + QS_END_PRE() QEvt_refCtr_dec_(e); // decrement the ref counter @@ -244,12 +237,12 @@ void gc(QEvt const * const e) noexcept { } else { // this is the last reference to this event, recycle it - QS_BEGIN_PRE_(QS_QF_GC, + QS_BEGIN_PRE(QS_QF_GC, static_cast(QS_EP_ID) + poolNum) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of the event - QS_2U8_PRE_(poolNum, e->refCtr_); // poolNum & refCtr - QS_END_PRE_() + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(e->sig); // the signal of the event + QS_2U8_PRE(poolNum, e->refCtr_); + QS_END_PRE() // pool number must be in range Q_ASSERT_INCRIT(410, (poolNum <= priv_.maxPool_) @@ -285,7 +278,8 @@ QEvt const * newRef_( QF_CRIT_STAT QF_CRIT_ENTRY(); - Q_REQUIRE_INCRIT(500, QEvt::verify_(e)); + Q_REQUIRE_INCRIT(500, e != nullptr); + Q_INVARIANT_INCRIT(501, e->verify_()); std::uint_fast8_t const poolNum = e->getPoolNum_(); Q_UNUSED_PAR(poolNum); // might be unused @@ -296,12 +290,12 @@ QEvt const * newRef_( QEvt_refCtr_inc_(e); // increments the ref counter QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QF_NEW_REF, + QS_BEGIN_PRE(QS_QF_NEW_REF, static_cast(QS_EP_ID) + poolNum) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of the event - QS_2U8_PRE_(poolNum, e->refCtr_); // poolNum & refCtr - QS_END_PRE_() + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(e->sig); // the signal of the event + QS_2U8_PRE(poolNum, e->refCtr_); + QS_END_PRE() QS_MEM_APP(); QF_CRIT_EXIT(); @@ -315,19 +309,20 @@ void deleteRef_(QEvt const * const evtRef) noexcept { QF_CRIT_ENTRY(); QEvt const * const e = evtRef; - Q_REQUIRE_INCRIT(600, QEvt::verify_(e)); + Q_REQUIRE_INCRIT(600, e != nullptr); + Q_INVARIANT_INCRIT(601, e->verify_()); #ifdef Q_SPY std::uint_fast8_t const poolNum = e->getPoolNum_(); #endif QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QF_DELETE_REF, + QS_BEGIN_PRE(QS_QF_DELETE_REF, static_cast(QS_EP_ID) + poolNum) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of the event - QS_2U8_PRE_(poolNum, e->refCtr_); // poolNum & refCtr - QS_END_PRE_() + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(e->sig); // the signal of the event + QS_2U8_PRE(poolNum, e->refCtr_); + QS_END_PRE() QS_MEM_APP(); QF_CRIT_EXIT(); diff --git a/src/qf/qf_mem.cpp b/src/qf/qf_mem.cpp index abe3f3823..8c56db061 100644 --- a/src/qf/qf_mem.cpp +++ b/src/qf/qf_mem.cpp @@ -3,17 +3,10 @@ // Model: qpcpp.qm // File: ${src::qf::qf_mem.cpp} // -// This code has been generated by QM 6.2.0 . +// This code has been generated by QM 7.0.0 . // DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. // -// This code is covered by the following QP license: -// License # : LicenseRef-QL-dual -// Issued to : Any user of the QP/C++ real-time embedded framework -// Framework(s) : qpcpp -// Support ends : 2025-12-31 -// License scope: -// -// Copyright (C) 2005 Quantum Leaps, LLC . +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // Q u a n t u m L e a P s // ------------------------ @@ -21,21 +14,20 @@ // // 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: +// 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. // -// Contact information: +// NOTE: +// The GPL does NOT permit the incorporation of this code into proprietary +// programs. Please contact Quantum Leaps for commercial licensing options, +// which expressly supersede the GPL and are designed explicitly for +// closed-source distribution. +// +// Quantum Leaps contact information: // // // @@ -77,15 +69,17 @@ void QMPool::init( QF_CRIT_ENTRY(); QF_MEM_SYS(); - Q_REQUIRE_INCRIT(100, (poolSto != nullptr) - && (poolSize >= static_cast(sizeof(QFreeBlock))) - && (static_cast(blockSize + sizeof(QFreeBlock)) - > blockSize)); + Q_REQUIRE_INCRIT(100, poolSto != nullptr); + Q_REQUIRE_INCRIT(101, + poolSize >= static_cast(sizeof(QFreeBlock))); + Q_REQUIRE_INCRIT(102, + static_cast(blockSize + sizeof(QFreeBlock)) + > blockSize); m_free_head = static_cast(poolSto); // find # free blocks in a memory block, NO DIVISION - m_blockSize = static_cast(sizeof(QFreeBlock)); + m_blockSize = static_cast(2U * sizeof(void *)); std::uint_fast16_t nblocks = 1U; while (m_blockSize < static_cast(blockSize)) { m_blockSize += static_cast(sizeof(QFreeBlock)); @@ -106,7 +100,7 @@ void QMPool::init( { fb->m_next = &fb[nblocks]; // point next link to next block #ifndef Q_UNSAFE - fb->m_next_dis = ~Q_UINTPTR_CAST_(fb->m_next); + fb->m_next_dis = ~Q_PTR2UINT_CAST_(fb->m_next); #endif fb = fb->m_next; // advance to the next block ++nTot; // one more free block in the pool @@ -120,16 +114,20 @@ void QMPool::init( #endif fb->m_next = nullptr; // the last link points to NULL - #ifndef Q_UNSAFE - fb->m_next_dis = ~Q_UINTPTR_CAST_(fb->m_next); - #endif m_nTot = static_cast(nTot); m_nFree = m_nTot; // all blocks are free - m_nMin = m_nTot; // the minimum # free blocks m_start = static_cast(poolSto); // original start m_end = fb; // the last block in this pool + #ifndef Q_UNSAFE + m_free_head_dis = + static_cast(~Q_PTR2UINT_CAST_(m_free_head)); + m_nFree_dis = static_cast(~m_nFree); + m_nMin = m_nTot; // the minimum # free blocks + fb->m_next_dis = ~Q_PTR2UINT_CAST_(fb->m_next); + #endif + QF_MEM_APP(); QF_CRIT_EXIT(); } @@ -147,62 +145,82 @@ void * QMPool::get( QF_CRIT_ENTRY(); QF_MEM_SYS(); - // have more free blocks than the requested margin? - QFreeBlock *fb; - if (m_nFree > static_cast(margin)) { - fb = m_free_head; // get a free block + // get volatile into temporaries + QFreeBlock *fb = m_free_head; + QMPoolCtr nFree = m_nFree; + + #ifndef Q_UNSAFE + Q_INVARIANT_INCRIT(301, Q_PTR2UINT_CAST_(fb) + == static_cast(~m_free_head_dis)); + Q_INVARIANT_INCRIT(302, nFree == static_cast(~m_nFree_dis)); + #endif // ndef Q_UNSAFE - // a free block must be valid - Q_ASSERT_INCRIT(300, fb != nullptr); + // have more free blocks than the requested margin? + if (nFree > static_cast(margin)) { + Q_ASSERT_INCRIT(310, fb != nullptr); QFreeBlock * const fb_next = fb->m_next; + #ifndef Q_UNSAFE // the free block must have integrity (duplicate inverse storage) - Q_INVARIANT_INCRIT(302, Q_UINTPTR_CAST_(fb_next) - == static_cast(~fb->m_next_dis)); + Q_INVARIANT_INCRIT(311, Q_PTR2UINT_CAST_(fb_next) + == static_cast(~fb->m_next_dis)); + #endif // ndef Q_UNSAFE - m_nFree = (m_nFree - 1U); // one free block less - if (m_nFree == 0U) { // is the pool becoming empty? + --nFree; // one less free block + if (nFree == 0U) { // is the pool becoming empty? // pool is becoming empty, so the next free block must be NULL Q_ASSERT_INCRIT(320, fb_next == nullptr); + m_nFree = 0U; + #ifndef Q_UNSAFE + m_nFree_dis = static_cast(~m_nFree); m_nMin = 0U; // remember that the pool got empty + #endif // ndef Q_UNSAFE } 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(330, + m_nFree = nFree; // update the original + #ifndef Q_UNSAFE + m_nFree_dis = static_cast(~nFree); + + // The pool is not empty, so the next free-block pointer + // must be in range. + Q_INVARIANT_INCRIT(330, QF_PTR_RANGE_(fb_next, m_start, m_end)); // is the # free blocks the new minimum so far? - if (m_nMin > m_nFree) { - m_nMin = m_nFree; // remember the minimum so far + if (m_nMin > nFree) { + m_nMin = nFree; // remember the minimum so far } + #endif // ndef Q_UNSAFE } m_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_(this); // this memory pool - QS_MPC_PRE_(m_nFree); // # of free blocks in the pool - QS_MPC_PRE_(m_nMin); // min # free blocks ever in the pool - QS_END_PRE_() + #ifndef Q_UNSAFE + m_free_head_dis = + static_cast(~Q_PTR2UINT_CAST_(fb_next)); + #endif // ndef Q_UNSAFE + + QS_BEGIN_PRE(QS_QF_MPOOL_GET, qsId) + QS_TIME_PRE(); // timestamp + QS_OBJ_PRE(this); // this memory pool + QS_MPC_PRE(nFree); // # of free blocks in the pool + #ifndef Q_UNSAFE + QS_MPC_PRE(m_nMin); // min # free blocks ever in the pool + #else + QS_MPC_PRE(0U); // min # free blocks (not available) + #endif // ndef Q_UNSAFE + QS_END_PRE() } else { // don't have enough free blocks at this point fb = nullptr; - QS_BEGIN_PRE_(QS_QF_MPOOL_GET_ATTEMPT, qsId) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this memory pool - QS_MPC_PRE_(m_nFree); // # of free blocks in the pool - QS_MPC_PRE_(margin); // the requested margin - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_MPOOL_GET_ATTEMPT, qsId) + QS_TIME_PRE(); // timestamp + QS_OBJ_PRE(this); // this memory pool + QS_MPC_PRE(nFree); // # of free blocks in the pool + QS_MPC_PRE(margin); // the requested margin + QS_END_PRE() } QF_MEM_APP(); @@ -226,25 +244,39 @@ void QMPool::put( QF_CRIT_ENTRY(); QF_MEM_SYS(); - Q_REQUIRE_INCRIT(200, (m_nFree < m_nTot) - && QF_PTR_RANGE_(fb, m_start, m_end)); + // get volatile into temporaries + QFreeBlock * const free_head = m_free_head; + QMPoolCtr nFree = m_nFree; - fb->m_next = m_free_head; // link into list #ifndef Q_UNSAFE - fb->m_next_dis = static_cast( - ~Q_UINTPTR_CAST_(fb->m_next)); - #endif + Q_INVARIANT_INCRIT(401, Q_PTR2UINT_CAST_(free_head) + == static_cast(~m_free_head_dis)); + Q_INVARIANT_INCRIT(402, nFree == static_cast(~m_nFree_dis)); + + Q_REQUIRE_INCRIT(410, nFree < m_nTot); + Q_REQUIRE_INCRIT(411, QF_PTR_RANGE_(fb, m_start, m_end)); - // set as new head of the free list - m_free_head = fb; + // the block must not be in the pool already + Q_REQUIRE_INCRIT(412, Q_PTR2UINT_CAST_(fb->m_next) + != static_cast(~fb->m_next_dis)); + #endif // ndef Q_UNSAFE - m_nFree = m_nFree + 1U; // one more free block in this pool + ++nFree; // one more free block in this pool + + m_free_head = fb; // set as new head of the free list + m_nFree = nFree; + fb->m_next = free_head; // link into the list + #ifndef Q_UNSAFE + m_free_head_dis = static_cast(~Q_PTR2UINT_CAST_(fb)); + m_nFree_dis = static_cast(~nFree); + fb->m_next_dis = static_cast(~Q_PTR2UINT_CAST_(free_head)); + #endif - QS_BEGIN_PRE_(QS_QF_MPOOL_PUT, qsId) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this memory pool - QS_MPC_PRE_(m_nFree); // the # free blocks in the pool - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_MPOOL_PUT, qsId) + QS_TIME_PRE(); // timestamp + QS_OBJ_PRE(this); // this memory pool + QS_MPC_PRE(nFree); // the # free blocks in the pool + QS_END_PRE() QF_MEM_APP(); QF_CRIT_EXIT(); diff --git a/src/qf/qf_ps.cpp b/src/qf/qf_ps.cpp index db13977de..6cb579cca 100644 --- a/src/qf/qf_ps.cpp +++ b/src/qf/qf_ps.cpp @@ -3,17 +3,10 @@ // Model: qpcpp.qm // File: ${src::qf::qf_ps.cpp} // -// This code has been generated by QM 6.2.0 . +// This code has been generated by QM 7.0.0 . // DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. // -// This code is covered by the following QP license: -// License # : LicenseRef-QL-dual -// Issued to : Any user of the QP/C++ real-time embedded framework -// Framework(s) : qpcpp -// Support ends : 2025-12-31 -// License scope: -// -// Copyright (C) 2005 Quantum Leaps, LLC . +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // Q u a n t u m L e a P s // ------------------------ @@ -21,21 +14,20 @@ // // 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: +// 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. // -// Contact information: +// NOTE: +// The GPL does NOT permit the incorporation of this code into proprietary +// programs. Please contact Quantum Leaps for commercial licensing options, +// which expressly supersede the GPL and are designed explicitly for +// closed-source distribution. +// +// Quantum Leaps contact information: // // // @@ -123,12 +115,12 @@ void QActive::publish_( Q_INVARIANT_INCRIT(202, subscrList_[sig].m_set.verify_(&subscrList_[sig].m_set_dis)); - QS_BEGIN_PRE_(QS_QF_PUBLISH, qsId) - QS_TIME_PRE_(); // the timestamp - QS_OBJ_PRE_(sender); // the sender object - QS_SIG_PRE_(e->sig); // the signal of the event - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_PUBLISH, qsId) + QS_TIME_PRE(); // the timestamp + QS_OBJ_PRE(sender); // the sender object + QS_SIG_PRE(e->sig); // the signal of the event + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_END_PRE() // is it a mutable event? if (e->getPoolNum_() != 0U) { @@ -225,11 +217,11 @@ void QActive::subscribe(enum_t const sig) const noexcept { Q_INVARIANT_INCRIT(302, subscrList_[sig].m_set.verify_(&subscrList_[sig].m_set_dis)); - QS_BEGIN_PRE_(QS_QF_ACTIVE_SUBSCRIBE, m_prio) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(sig); // the signal of this event - QS_OBJ_PRE_(this); // this active object - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_ACTIVE_SUBSCRIBE, m_prio) + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(sig); // the signal of this event + QS_OBJ_PRE(this); // this active object + QS_END_PRE() // insert the prio. into the subscriber set subscrList_[sig].m_set.insert(p); @@ -262,11 +254,11 @@ void QActive::unsubscribe(enum_t const sig) const noexcept { Q_INVARIANT_INCRIT(402, subscrList_[sig].m_set.verify_(&subscrList_[sig].m_set_dis)); - QS_BEGIN_PRE_(QS_QF_ACTIVE_UNSUBSCRIBE, m_prio) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(sig); // the signal of this event - QS_OBJ_PRE_(this); // this active object - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_ACTIVE_UNSUBSCRIBE, m_prio) + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(sig); // the signal of this event + QS_OBJ_PRE(this); // this active object + QS_END_PRE() // remove the prio. from the subscriber set subscrList_[sig].m_set.remove(p); @@ -308,11 +300,11 @@ void QActive::unsubscribeAll() const noexcept { #ifndef Q_UNSAFE subscrList_[sig].m_set.update_(&subscrList_[sig].m_set_dis); #endif - QS_BEGIN_PRE_(QS_QF_ACTIVE_UNSUBSCRIBE, m_prio) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(sig); // the signal of this event - QS_OBJ_PRE_(this); // this active object - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_ACTIVE_UNSUBSCRIBE, m_prio) + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(sig); // the signal of this event + QS_OBJ_PRE(this); // this active object + QS_END_PRE() } QF_MEM_APP(); QF_CRIT_EXIT(); diff --git a/src/qf/qf_qact.cpp b/src/qf/qf_qact.cpp index a09d72847..43bdd2141 100644 --- a/src/qf/qf_qact.cpp +++ b/src/qf/qf_qact.cpp @@ -3,17 +3,10 @@ // Model: qpcpp.qm // File: ${src::qf::qf_qact.cpp} // -// This code has been generated by QM 6.2.0 . +// This code has been generated by QM 7.0.0 . // DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. // -// This code is covered by the following QP license: -// License # : LicenseRef-QL-dual -// Issued to : Any user of the QP/C++ real-time embedded framework -// Framework(s) : qpcpp -// Support ends : 2025-12-31 -// License scope: -// -// Copyright (C) 2005 Quantum Leaps, LLC . +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // Q u a n t u m L e a P s // ------------------------ @@ -21,21 +14,20 @@ // // 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: +// 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. // -// Contact information: +// NOTE: +// The GPL does NOT permit the incorporation of this code into proprietary +// programs. Please contact Quantum Leaps for commercial licensing options, +// which expressly supersede the GPL and are designed explicitly for +// closed-source distribution. +// +// Quantum Leaps contact information: // // // diff --git a/src/qf/qf_qeq.cpp b/src/qf/qf_qeq.cpp index 18473f967..4fb160d0e 100644 --- a/src/qf/qf_qeq.cpp +++ b/src/qf/qf_qeq.cpp @@ -3,17 +3,10 @@ // Model: qpcpp.qm // File: ${src::qf::qf_qeq.cpp} // -// This code has been generated by QM 6.2.0 . +// This code has been generated by QM 7.0.0 . // DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. // -// This code is covered by the following QP license: -// License # : LicenseRef-QL-dual -// Issued to : Any user of the QP/C++ real-time embedded framework -// Framework(s) : qpcpp -// Support ends : 2025-12-31 -// License scope: -// -// Copyright (C) 2005 Quantum Leaps, LLC . +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // Q u a n t u m L e a P s // ------------------------ @@ -21,21 +14,20 @@ // // 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: +// 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. // -// Contact information: +// NOTE: +// The GPL does NOT permit the incorporation of this code into proprietary +// programs. Please contact Quantum Leaps for commercial licensing options, +// which expressly supersede the GPL and are designed explicitly for +// closed-source distribution. +// +// Quantum Leaps contact information: // // // @@ -90,6 +82,13 @@ void QEQueue::init( m_nFree = static_cast(qLen + 1U); //+1 for frontEvt m_nMin = m_nFree; + #ifndef Q_UNSAFE + m_frontEvt_dis = static_cast(~Q_PTR2UINT_CAST_(m_frontEvt)); + m_head_dis = static_cast(~m_head); + m_tail_dis = static_cast(~m_tail); + m_nFree_dis = static_cast(~m_nFree); + #endif + QF_MEM_APP(); QF_CRIT_EXIT(); } @@ -108,47 +107,76 @@ bool QEQueue::post( QF_CRIT_ENTRY(); QF_MEM_SYS(); - Q_REQUIRE_INCRIT(200, QEvt::verify_(e)); + Q_REQUIRE_INCRIT(200, e != nullptr); + Q_INVARIANT_INCRIT(201, e->verify_()); - QEQueueCtr nFree = m_nFree; // get volatile into temporary + QEQueueCtr tmp = m_nFree; // get volatile into temporary + #ifndef Q_UNSAFE + QEQueueCtr dis = static_cast(~m_nFree_dis); + Q_INVARIANT_INCRIT(201, tmp == dis); + #endif // ndef Q_UNSAFE + + // test-probe#1 for faking queue overflow + QS_TEST_PROBE_DEF(&QEQueue::post) + QS_TEST_PROBE_ID(1, + tmp = 0U; // fake no free events + ) // required margin available? bool status; - if (((margin == QF::NO_MARGIN) && (nFree > 0U)) - || (nFree > static_cast(margin))) + if (((margin == QF::NO_MARGIN) && (tmp > 0U)) + || (tmp > static_cast(margin))) { // is it a mutable event? if (e->getPoolNum_() != 0U) { QEvt_refCtr_inc_(e); // increment the reference counter } - --nFree; // one free entry just used up - m_nFree = nFree; // update the original - if (m_nMin > nFree) { - m_nMin = nFree; // update minimum so far + --tmp; // one free entry just used up + + m_nFree = tmp; // update the original + #ifndef Q_UNSAFE + m_nFree_dis = static_cast(~tmp); + #endif // ndef Q_UNSAFE + + if (m_nMin > tmp) { + m_nMin = tmp; // update minimum so far } - QS_BEGIN_PRE_(QS_QF_EQUEUE_POST, qsId) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of this event - QS_OBJ_PRE_(this); // this queue object - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_EQC_PRE_(nFree); // # free entries - QS_EQC_PRE_(m_nMin); // min # free entries - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_EQUEUE_POST, qsId) + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(e->sig); // the signal of the event + QS_OBJ_PRE(this); // this queue object + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_EQC_PRE(tmp); // # free entries + QS_EQC_PRE(m_nMin); // min # free entries + QS_END_PRE() - if (m_frontEvt == nullptr) { // was the queue empty? + if (m_frontEvt == nullptr) { // is the queue empty? m_frontEvt = e; // deliver event directly + #ifndef Q_UNSAFE + Q_INVARIANT_INCRIT(211, m_frontEvt_dis + == static_cast(~Q_PTR2UINT_CAST_(nullptr))); + m_frontEvt_dis = static_cast(~Q_PTR2UINT_CAST_(e)); + #endif // ndef Q_UNSAFE } else { // queue was not empty, insert event into the ring-buffer - // insert event into the ring buffer (FIFO) - m_ring[m_head] = e; // insert e into buffer - - // need to wrap? - if (m_head == 0U) { - m_head = m_end; // wrap around + tmp = m_head; // get volatile into temporary + #ifndef Q_UNSAFE + dis = static_cast(~m_head_dis); + Q_INVARIANT_INCRIT(212, tmp == dis); + #endif // ndef Q_UNSAFE + m_ring[tmp] = e; // insert e into buffer + + if (tmp == 0U) { // need to wrap the head? + tmp = m_end; } - m_head = (m_head - 1U); + --tmp; // advance head (counter-clockwise) + + m_head = tmp; // update the original + #ifndef Q_UNSAFE + m_head_dis = static_cast(~tmp); + #endif // ndef Q_UNSAFE } status = true; // event posted successfully } @@ -156,14 +184,14 @@ bool QEQueue::post( // dropping events must be acceptable Q_ASSERT_INCRIT(210, margin != QF::NO_MARGIN); - QS_BEGIN_PRE_(QS_QF_EQUEUE_POST_ATTEMPT, qsId) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of this event - QS_OBJ_PRE_(this); // this queue object - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_EQC_PRE_(nFree); // # free entries - QS_EQC_PRE_(margin); // margin requested - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_EQUEUE_POST_ATTEMPT, qsId) + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(e->sig); // the signal of this event + QS_OBJ_PRE(this); // this queue object + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_EQC_PRE(tmp); // # free entries + QS_EQC_PRE(margin); // margin requested + QS_END_PRE() status = false; // event not posted } @@ -187,39 +215,69 @@ void QEQueue::postLIFO( QF_CRIT_ENTRY(); QF_MEM_SYS(); - Q_REQUIRE_INCRIT(300, QEvt::verify_(e)); + Q_REQUIRE_INCRIT(300, e != nullptr); + Q_INVARIANT_INCRIT(301, e->verify_()); - QEQueueCtr nFree = m_nFree; // get volatile into temporary - Q_REQUIRE_INCRIT(301, nFree != 0U); + QEQueueCtr tmp = m_nFree; // get volatile into temporary + #ifndef Q_UNSAFE + QEQueueCtr dis = static_cast(~m_nFree_dis); + Q_INVARIANT_INCRIT(301, tmp == dis); + #endif // ndef Q_UNSAFE + + // test-probe#1 for faking queue overflow + QS_TEST_PROBE_DEF(&QEQueue::postLIFO) + QS_TEST_PROBE_ID(1, + tmp = 0U; // fake no free events + ) + + // must be able to LIFO-post the event + Q_REQUIRE_INCRIT(310, tmp != 0U); if (e->getPoolNum_() != 0U) { // is it a mutable event? QEvt_refCtr_inc_(e); // increment the reference counter } - --nFree; // one free entry just used up - m_nFree = nFree; // update the original - if (m_nMin > nFree) { - m_nMin = nFree; // update minimum so far + --tmp; // one free entry just used up + + m_nFree = tmp; // update the original + #ifndef Q_UNSAFE + m_nFree_dis = static_cast(~tmp); + #endif // ndef Q_UNSAFE + + if (m_nMin > tmp) { + m_nMin = tmp; // update minimum so far } - QS_BEGIN_PRE_(QS_QF_EQUEUE_POST_LIFO, qsId) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of this event - QS_OBJ_PRE_(this); // this queue object - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_EQC_PRE_(nFree); // # free entries - QS_EQC_PRE_(m_nMin); // min # free entries - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_EQUEUE_POST_LIFO, qsId) + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(e->sig); // the signal of this event + QS_OBJ_PRE(this); // this queue object + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_EQC_PRE(tmp); // # free entries + QS_EQC_PRE(m_nMin); // min # free entries + QS_END_PRE() QEvt const * const frontEvt = m_frontEvt; // read into temporary - m_frontEvt = e; // deliver event directly to the front of the queue - - if (frontEvt != nullptr) { // was the queue not empty? - m_tail = (m_tail + 1U); - if (m_tail == m_end) { // need to wrap the tail? - m_tail = 0U; // wrap around + m_frontEvt = e; // deliver the event directly to the front + #ifndef Q_UNSAFE + m_frontEvt_dis = static_cast(~Q_PTR2UINT_CAST_(e)); + #endif // ndef Q_UNSAFE + + if (frontEvt != nullptr) { // was the queue NOT empty? + tmp = m_tail; // get volatile into temporary; + #ifndef Q_UNSAFE + dis = static_cast(~m_tail_dis); + Q_INVARIANT_INCRIT(311, tmp == dis); + #endif // ndef Q_UNSAFE + ++tmp; + if (tmp == m_end) { // need to wrap the tail? + tmp = 0U; // wrap around } - m_ring[m_tail] = frontEvt; // buffer the old front evt + m_tail = tmp; + #ifndef Q_UNSAFE + m_tail_dis = static_cast(~tmp); + #endif + m_ring[tmp] = frontEvt; } QF_MEM_APP(); @@ -236,43 +294,71 @@ QEvt const * QEQueue::get(std::uint_fast8_t const qsId) noexcept { QF_CRIT_ENTRY(); QF_MEM_SYS(); - QEvt const * const e = m_frontEvt; // always remove evt from the front + QEvt const * const e = m_frontEvt; // always remove evt from the front + #ifndef Q_UNSAFE + Q_INVARIANT_INCRIT(411, Q_PTR2UINT_CAST_(e) + == static_cast(~m_frontEvt_dis)); + #endif // ndef Q_UNSAFE if (e != nullptr) { // was the queue not empty? - Q_INVARIANT_INCRIT(412, QEvt::verify_(e)); - - // use a temporary variable to increment m_nFree - QEQueueCtr const nFree = m_nFree + 1U; - m_nFree = nFree; // update the # free - - // any events in the the ring buffer? - if (nFree <= m_end) { - m_frontEvt = m_ring[m_tail]; // remove from the tail - if (m_tail == 0U) { // need to wrap? - m_tail = m_end; // wrap around + QEQueueCtr tmp = m_nFree; // get volatile into temporary + #ifndef Q_UNSAFE + QEQueueCtr const dis = static_cast(~m_nFree_dis); + Q_INVARIANT_INCRIT(412, tmp == dis); + #endif // ndef Q_UNSAFE + + ++tmp; // one more free event in the queue + + m_nFree = tmp; // update the # free + #ifndef Q_UNSAFE + m_nFree_dis = static_cast(~tmp); + #endif // ndef Q_UNSAFE + + // any events in the ring buffer? + if (tmp <= m_end) { + + QS_BEGIN_PRE(QS_QF_EQUEUE_GET, qsId) + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(e->sig); // the signal of this event + QS_OBJ_PRE(this); // this queue object + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_EQC_PRE(tmp); // # free entries + QS_END_PRE() + + tmp = m_tail; // get volatile into temporary + QEvt const * const frontEvt = m_ring[tmp]; + #ifndef Q_UNSAFE + Q_ASSERT_INCRIT(421, frontEvt != nullptr); + m_frontEvt_dis = + static_cast(~Q_PTR2UINT_CAST_(frontEvt)); + #endif // ndef Q_UNSAFE + m_frontEvt = frontEvt; // update the original + + if (tmp == 0U) { // need to wrap the tail? + tmp = m_end; } - m_tail = (m_tail - 1U); - - QS_BEGIN_PRE_(QS_QF_EQUEUE_GET, qsId) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of this event - QS_OBJ_PRE_(this); // this queue object - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_EQC_PRE_(nFree); // # free entries - QS_END_PRE_() + --tmp; // advance the tail (counter-clockwise) + m_tail = tmp; // update the original + #ifndef Q_UNSAFE + m_tail_dis = static_cast(~tmp); + #endif // ndef Q_UNSAFE } else { m_frontEvt = nullptr; // queue becomes empty - - // all entries in the queue must be free (+1 for fronEvt) - Q_INVARIANT_INCRIT(420, nFree == (m_end + 1U)); - - QS_BEGIN_PRE_(QS_QF_EQUEUE_GET_LAST, qsId) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of this event - QS_OBJ_PRE_(this); // this queue object - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_END_PRE_() + #ifndef Q_UNSAFE + m_frontEvt_dis = + static_cast(~Q_PTR2UINT_CAST_(nullptr)); + #endif // ndef Q_UNSAFE + + // all entries in the queue must be free (+1 for frontEvt) + Q_INVARIANT_INCRIT(440, tmp == (m_end + 1U)); + + QS_BEGIN_PRE(QS_QF_EQUEUE_GET_LAST, qsId) + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(e->sig); // the signal of this event + QS_OBJ_PRE(this); // this queue object + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_END_PRE() } } diff --git a/src/qf/qf_qmact.cpp b/src/qf/qf_qmact.cpp index b1cfed55c..535251ad8 100644 --- a/src/qf/qf_qmact.cpp +++ b/src/qf/qf_qmact.cpp @@ -3,17 +3,10 @@ // Model: qpcpp.qm // File: ${src::qf::qf_qmact.cpp} // -// This code has been generated by QM 6.2.0 . +// This code has been generated by QM 7.0.0 . // DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. // -// This code is covered by the following QP license: -// License # : LicenseRef-QL-dual -// Issued to : Any user of the QP/C++ real-time embedded framework -// Framework(s) : qpcpp -// Support ends : 2025-12-31 -// License scope: -// -// Copyright (C) 2005 Quantum Leaps, LLC . +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // Q u a n t u m L e a P s // ------------------------ @@ -21,21 +14,20 @@ // // 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: +// 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. // -// Contact information: +// NOTE: +// The GPL does NOT permit the incorporation of this code into proprietary +// programs. Please contact Quantum Leaps for commercial licensing options, +// which expressly supersede the GPL and are designed explicitly for +// closed-source distribution. +// +// Quantum Leaps contact information: // // // diff --git a/src/qf/qf_time.cpp b/src/qf/qf_time.cpp index 5e14cb013..6f3cf51c3 100644 --- a/src/qf/qf_time.cpp +++ b/src/qf/qf_time.cpp @@ -3,17 +3,10 @@ // Model: qpcpp.qm // File: ${src::qf::qf_time.cpp} // -// This code has been generated by QM 6.2.0 . +// This code has been generated by QM 7.0.0 . // DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. // -// This code is covered by the following QP license: -// License # : LicenseRef-QL-dual -// Issued to : Any user of the QP/C++ real-time embedded framework -// Framework(s) : qpcpp -// Support ends : 2025-12-31 -// License scope: -// -// Copyright (C) 2005 Quantum Leaps, LLC . +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // Q u a n t u m L e a P s // ------------------------ @@ -21,21 +14,20 @@ // // 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: +// 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. // -// Contact information: +// NOTE: +// The GPL does NOT permit the incorporation of this code into proprietary +// programs. Please contact Quantum Leaps for commercial licensing options, +// which expressly supersede the GPL and are designed explicitly for +// closed-source distribution. +// +// Quantum Leaps contact information: // // // @@ -68,17 +60,28 @@ namespace QP { //${QF::QTimeEvt} ............................................................ QTimeEvt QTimeEvt::timeEvtHead_[QF_MAX_TICK_RATE]; +#ifndef Q_UNSAFE +QPtrDis QTimeEvt::timeEvtHead_dis_[QF_MAX_TICK_RATE]; +#endif // ndef Q_UNSAFE + //${QF::QTimeEvt::QTimeEvt} .................................................. QTimeEvt::QTimeEvt( QActive * const act, QSignal const sig, std::uint_fast8_t const tickRate) noexcept - : - QEvt(sig), + : QEvt(sig), m_next(nullptr), +#ifndef Q_UNSAFE + m_next_dis(static_cast(~Q_PTR2UINT_CAST_(nullptr))), +#endif m_act(act), m_ctr(0U), - m_interval(0U) +#ifndef Q_UNSAFE + m_ctr_dis(static_cast(~static_cast(0U))), +#endif + m_interval(0U), + m_tickRate(0U), + m_flags(0U) { QF_CRIT_STAT QF_CRIT_ENTRY(); @@ -86,48 +89,58 @@ QTimeEvt::QTimeEvt( && (tickRate < QF_MAX_TICK_RATE)); QF_CRIT_EXIT(); - // The refCtr_ attribute is not used in time events, so it is - // reused to hold the tickRate as well as other information - refCtr_ = static_cast(tickRate); + // adjust the settings from the QEvt(sig) ctor + evtTag_ = 0x0FU; + refCtr_ = 0U; } //${QF::QTimeEvt::armX} ...................................................... void QTimeEvt::armX( - QTimeEvtCtr const nTicks, - QTimeEvtCtr const interval) noexcept + std::uint32_t const nTicks, + std::uint32_t const interval) noexcept { - std::uint8_t const tickRate = refCtr_ & TE_TICK_RATE; + QF_CRIT_STAT + QF_CRIT_ENTRY(); + QF_MEM_SYS(); + + // dynamic range checks + #if (QF_TIMEEVT_CTR_SIZE == 1U) + Q_REQUIRE_INCRIT(400, (nTicks < 0xFFU) && (interval < 0xFFU)); + #elif (QF_TIMEEVT_CTR_SIZE == 2U) + Q_REQUIRE_INCRIT(400, (nTicks < 0xFFFFU) && (interval < 0xFFFFU)); + #endif + + Q_REQUIRE_INCRIT(401, verify_() && (nTicks != 0U)); + QTimeEvtCtr const ctr = m_ctr; + std::uint8_t const tickRate = m_tickRate; #ifdef Q_SPY std::uint_fast8_t const qsId = static_cast(m_act)->m_prio; - #endif + #endif // def Q_SPY - QF_CRIT_STAT - QF_CRIT_ENTRY(); - QF_MEM_SYS(); + Q_REQUIRE_INCRIT(410, (ctr == 0U) + && (m_act != nullptr) + && (tickRate < QF_MAX_TICK_RATE)); - Q_REQUIRE_INCRIT(400, (m_act != nullptr) - && (ctr == 0U) - && (nTicks != 0U) - && (tickRate < static_cast(QF_MAX_TICK_RATE)) - && (sig >= static_cast(Q_USER_SIG))); - #ifdef Q_UNSAFE + #ifndef Q_UNSAFE + Q_INVARIANT_INCRIT(411, ctr == static_cast(~m_ctr_dis)); + #else Q_UNUSED_PAR(ctr); - #endif + #endif // ndef Q_UNSAFE - m_ctr = nTicks; - m_interval = interval; + m_ctr = static_cast(nTicks); + m_interval = static_cast(interval); + #ifndef Q_UNSAFE + m_ctr_dis = static_cast(~nTicks); + #endif // ndef Q_UNSAFE // is the time event unlinked? // NOTE: For the duration of a single clock tick of the specified tick // rate a time event can be disarmed and yet still linked into the list // because un-linking is performed exclusively in the QF_tickX() function. - if (static_cast( - static_cast(refCtr_) & TE_IS_LINKED) == 0U) - { - // mark as linked - refCtr_ = static_cast(refCtr_ | TE_IS_LINKED); + if ((m_flags & QTE_FLAG_IS_LINKED) == 0U) { + m_flags |= QTE_FLAG_IS_LINKED; // mark as linked // The time event is initially inserted into the separate // "freshly armed" list based on timeEvtHead_[tickRate].act. @@ -135,18 +148,32 @@ void QTimeEvt::armX( // list is appended to the main list of armed time events based on // timeEvtHead_[tickRate].next. Again, this is to keep any // changes to the main list exclusively inside QTimeEvt::tick(). + #ifndef Q_UNSAFE + Q_INVARIANT_INCRIT(420, + Q_PTR2UINT_CAST_(m_next) == + static_cast(~m_next_dis)); + Q_INVARIANT_INCRIT(411, + Q_PTR2UINT_CAST_(timeEvtHead_[tickRate].m_act) == + static_cast(~timeEvtHead_dis_[tickRate].m_ptr_dis)); + #endif m_next = timeEvtHead_[tickRate].toTimeEvt(); timeEvtHead_[tickRate].m_act = this; + #ifndef Q_UNSAFE + m_next_dis = + static_cast(~Q_PTR2UINT_CAST_(m_next)); + timeEvtHead_dis_[tickRate].m_ptr_dis = + static_cast(~Q_PTR2UINT_CAST_(this)); + #endif // ndef Q_UNSAFE } - QS_BEGIN_PRE_(QS_QF_TIMEEVT_ARM, qsId) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this time event object - QS_OBJ_PRE_(m_act); // the active object - QS_TEC_PRE_(nTicks); // the # ticks - QS_TEC_PRE_(interval); // the interval - QS_U8_PRE_(tickRate); // tick rate - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_TIMEEVT_ARM, qsId) + QS_TIME_PRE(); // timestamp + QS_OBJ_PRE(this); // this time event object + QS_OBJ_PRE(m_act); // the active object + QS_TEC_PRE(nTicks); // the # ticks + QS_TEC_PRE(interval); // the interval + QS_U8_PRE(tickRate); // tick rate + QS_END_PRE() QF_MEM_APP(); QF_CRIT_EXIT(); @@ -154,42 +181,50 @@ void QTimeEvt::armX( //${QF::QTimeEvt::disarm} .................................................... bool QTimeEvt::disarm() noexcept { - #ifdef Q_SPY - std::uint_fast8_t const qsId = static_cast(m_act)->m_prio; - #endif - QF_CRIT_STAT QF_CRIT_ENTRY(); QF_MEM_SYS(); - // is the time event actually armed? - bool wasArmed; - if (m_ctr != 0U) { - wasArmed = true; - refCtr_ = static_cast(refCtr_ | TE_WAS_DISARMED); + Q_REQUIRE_INCRIT(500, verify_()); - QS_BEGIN_PRE_(QS_QF_TIMEEVT_DISARM, qsId) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this time event object - QS_OBJ_PRE_(m_act); // the target AO - QS_TEC_PRE_(m_ctr); // the # ticks - QS_TEC_PRE_(m_interval); // the interval - QS_U8_PRE_(refCtr_& TE_TICK_RATE); // tick rate - QS_END_PRE_() + QTimeEvtCtr const ctr = m_ctr; + #ifndef Q_UNSAFE + Q_INVARIANT_INCRIT(501, ctr == static_cast(~m_ctr_dis)); + #endif // ndef Q_UNSAFE + #ifdef Q_SPY + std::uint_fast8_t const qsId = static_cast(m_act)->m_prio; + #endif + + // was the time event actually armed? + bool wasArmed; + if (ctr != 0U) { + wasArmed = true; + m_flags |= QTE_FLAG_WAS_DISARMED; m_ctr = 0U; // schedule removal from the list + #ifndef Q_UNSAFE + m_ctr_dis = static_cast(~static_cast(0U)); + #endif // ndef Q_UNSAFE + + QS_BEGIN_PRE(QS_QF_TIMEEVT_DISARM, qsId) + QS_TIME_PRE(); // timestamp + QS_OBJ_PRE(this); // this time event object + QS_OBJ_PRE(m_act); // the target AO + QS_TEC_PRE(ctr); // the # ticks + QS_TEC_PRE(m_interval); // the interval + QS_U8_PRE(m_tickRate); // tick rate + QS_END_PRE() } else { // the time event was already disarmed automatically wasArmed = false; - refCtr_ = static_cast(refCtr_ - & static_cast(~TE_WAS_DISARMED)); - - QS_BEGIN_PRE_(QS_QF_TIMEEVT_DISARM_ATTEMPT, qsId) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this time event object - QS_OBJ_PRE_(m_act); // the target AO - QS_U8_PRE_(refCtr_& TE_TICK_RATE); // tick rate - QS_END_PRE_() + m_flags &= static_cast(~QTE_FLAG_WAS_DISARMED); + + QS_BEGIN_PRE(QS_QF_TIMEEVT_DISARM_ATTEMPT, qsId) + QS_TIME_PRE(); // timestamp + QS_OBJ_PRE(this); // this time event object + QS_OBJ_PRE(m_act); // the target AO + QS_U8_PRE(m_tickRate); // tick rate + QS_END_PRE() } QF_MEM_APP(); @@ -199,36 +234,50 @@ bool QTimeEvt::disarm() noexcept { } //${QF::QTimeEvt::rearm} ..................................................... -bool QTimeEvt::rearm(QTimeEvtCtr const nTicks) noexcept { - std::uint8_t const tickRate = refCtr_ & TE_TICK_RATE; +bool QTimeEvt::rearm(std::uint32_t const nTicks) noexcept { + QF_CRIT_STAT + QF_CRIT_ENTRY(); + QF_MEM_SYS(); + // dynamic range checks + #if (QF_TIMEEVT_CTR_SIZE == 1U) + Q_REQUIRE_INCRIT(600, nTicks < 0xFFU); + #elif (QF_TIMEEVT_CTR_SIZE == 2U) + Q_REQUIRE_INCRIT(600, nTicks < 0xFFFFU); + #endif + + Q_REQUIRE_INCRIT(601, verify_() && (nTicks != 0U)); + + QTimeEvtCtr const ctr = m_ctr; + std::uint8_t const tickRate = m_tickRate; #ifdef Q_SPY std::uint_fast8_t const qsId = static_cast(m_act)->m_prio; #endif - QF_CRIT_STAT - QF_CRIT_ENTRY(); - QF_MEM_SYS(); + Q_REQUIRE_INCRIT(610, (m_act != nullptr) + && (tickRate < QF_MAX_TICK_RATE)); - Q_REQUIRE_INCRIT(600, (m_act != nullptr) - && (tickRate < static_cast(QF_MAX_TICK_RATE)) - && (nTicks != 0U) - && (sig >= static_cast(Q_USER_SIG))); + #ifndef Q_UNSAFE + Q_INVARIANT_INCRIT(602, ctr == static_cast(~m_ctr_dis)); + #endif // ndef Q_UNSAFE + m_ctr = static_cast(nTicks); + #ifndef Q_UNSAFE + m_ctr_dis = static_cast(~nTicks); + #endif // ndef Q_UNSAFE // is the time evt not running? bool wasArmed; - if (m_ctr == 0U) { + if (ctr == 0U) { wasArmed = false; // NOTE: For a duration of a single clock tick of the specified // tick rate a time event can be disarmed and yet still linked into // the list, because unlinking is performed exclusively in the - // QTimeEvt::tickX() function. + // QTimeEvt::tick() function. - // is the time event unlinked? - if (static_cast(refCtr_ & TE_IS_LINKED) == 0U) { - // mark as linked - refCtr_ = static_cast(refCtr_ | TE_IS_LINKED); + // was the time event unlinked? + if ((m_flags & QTE_FLAG_IS_LINKED) == 0U) { + m_flags |= QTE_FLAG_IS_LINKED; // mark as linked // The time event is initially inserted into the separate // "freshly armed" list based on timeEvtHead_[tickRate].act. @@ -236,23 +285,36 @@ bool QTimeEvt::rearm(QTimeEvtCtr const nTicks) noexcept { // list is appended to the main list of armed time events based on // timeEvtHead_[tickRate].next. Again, this is to keep any // changes to the main list exclusively inside QTimeEvt::tick(). + #ifndef Q_UNSAFE + Q_INVARIANT_INCRIT(620, + Q_PTR2UINT_CAST_(m_next) == + static_cast(~m_next_dis)); + Q_INVARIANT_INCRIT(611, + Q_PTR2UINT_CAST_(timeEvtHead_[tickRate].m_act) == + static_cast(~timeEvtHead_dis_[tickRate].m_ptr_dis)); + #endif m_next = timeEvtHead_[tickRate].toTimeEvt(); timeEvtHead_[tickRate].m_act = this; + #ifndef Q_UNSAFE + m_next_dis = + static_cast(~Q_PTR2UINT_CAST_(m_next)); + timeEvtHead_dis_[tickRate].m_ptr_dis = + static_cast(~Q_PTR2UINT_CAST_(this)); + #endif // ndef Q_UNSAFE } } else { // the time event was armed wasArmed = true; } - m_ctr = nTicks; // re-load the tick counter (shift the phasing) - QS_BEGIN_PRE_(QS_QF_TIMEEVT_REARM, qsId) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this time event object - QS_OBJ_PRE_(m_act); // the target AO - QS_TEC_PRE_(m_ctr); // the # ticks - QS_TEC_PRE_(m_interval); // the interval - QS_2U8_PRE_(tickRate, (wasArmed ? 1U : 0U)); - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_TIMEEVT_REARM, qsId) + QS_TIME_PRE(); // timestamp + QS_OBJ_PRE(this); // this time event object + QS_OBJ_PRE(m_act); // the target AO + QS_TEC_PRE(nTicks); // the # ticks + QS_TEC_PRE(m_interval); // the interval + QS_2U8_PRE(tickRate, (wasArmed ? 1U : 0U)); + QS_END_PRE() QF_MEM_APP(); QF_CRIT_EXIT(); @@ -266,13 +328,13 @@ bool QTimeEvt::wasDisarmed() noexcept { QF_CRIT_ENTRY(); QF_MEM_SYS(); - std::uint8_t const isDisarmed = refCtr_ & TE_WAS_DISARMED; - refCtr_ = static_cast(refCtr_ | TE_WAS_DISARMED); + bool const wasDisarmed = (m_flags & QTE_FLAG_WAS_DISARMED) != 0U; + m_flags |= QTE_FLAG_WAS_DISARMED; QF_MEM_APP(); QF_CRIT_EXIT(); - return isDisarmed != 0U; + return wasDisarmed; } //${QF::QTimeEvt::tick} ...................................................... @@ -288,45 +350,75 @@ void QTimeEvt::tick( QF_CRIT_ENTRY(); QF_MEM_SYS(); - Q_REQUIRE_INCRIT(100, tickRate < Q_DIM(timeEvtHead_)); + Q_REQUIRE_INCRIT(800, tickRate < Q_DIM(timeEvtHead_)); QTimeEvt *prev = &timeEvtHead_[tickRate]; - QS_BEGIN_PRE_(QS_QF_TICK, 0U) + QS_BEGIN_PRE(QS_QF_TICK, 0U) prev->m_ctr = (prev->m_ctr + 1U); - QS_TEC_PRE_(prev->m_ctr); // tick ctr - QS_U8_PRE_(tickRate); // tick rate - QS_END_PRE_() + QS_TEC_PRE(prev->m_ctr); // tick ctr + QS_U8_PRE(tickRate); // tick rate + QS_END_PRE() // scan the linked-list of time events at this rate... std::uint_fast8_t lbound = 2U*QF_MAX_ACTIVE; // fixed upper loop bound for (; lbound > 0U; --lbound) { - QTimeEvt *e = prev->m_next; // advance down the time evt. list + Q_ASSERT_INCRIT(810, prev != nullptr); // sanity check - if (e == nullptr) { // end of the list? + QTimeEvt *te = prev->m_next; // advance down the time evt. list + #ifndef Q_UNSAFE + Q_INVARIANT_INCRIT(811, + Q_PTR2UINT_CAST_(te) == + static_cast(~prev->m_next_dis)); + #endif // ndef Q_UNSAFE - // any new time events armed since the last run of tick()? - if (timeEvtHead_[tickRate].m_act != nullptr) { + if (te == nullptr) { // end of the list? - // sanity check - Q_ASSERT_INCRIT(110, prev != nullptr); + // any new time events armed since the last QTimeEvt_tick_()? + if (timeEvtHead_[tickRate].m_act != nullptr) { + #ifndef Q_UNSAFE + Q_INVARIANT_INCRIT(812, + Q_PTR2UINT_CAST_(timeEvtHead_[tickRate].m_act) == + static_cast( + ~timeEvtHead_dis_[tickRate].m_ptr_dis)); + #endif // ndef Q_UNSAFE prev->m_next = timeEvtHead_[tickRate].toTimeEvt(); timeEvtHead_[tickRate].m_act = nullptr; - e = prev->m_next; // switch to the new list + #ifndef Q_UNSAFE + prev->m_next_dis = + static_cast( + ~Q_PTR2UINT_CAST_(prev->m_next)); + timeEvtHead_dis_[tickRate].m_ptr_dis = + static_cast(~Q_PTR2UINT_CAST_(nullptr)); + #endif // ndef Q_UNSAFE + + te = prev->m_next; // switch to the new list } else { // all currently armed time events are processed break; // terminate the for-loop } } - // the time event 'e' must be valid - Q_INVARIANT_INCRIT(112, QEvt::verify_(e)); + // the time event 'te' must be valid + Q_ASSERT_INCRIT(820, te != nullptr); + Q_INVARIANT_INCRIT(821, te->verify_()); + + QTimeEvtCtr ctr = te->m_ctr; + #ifndef Q_UNSAFE + Q_INVARIANT_INCRIT(822, ctr == + static_cast(~te->m_ctr_dis)); + #endif // ndef Q_UNSAFE + + if (ctr == 0U) { // time event scheduled for removal? + prev->m_next = te->m_next; + #ifndef Q_UNSAFE + prev->m_next_dis = + static_cast(~Q_PTR2UINT_CAST_(te->m_next)); + #endif // ndef Q_UNSAFE + + // mark time event 'te' as NOT linked + te->m_flags &= static_cast(~QTE_FLAG_IS_LINKED); - if (e->m_ctr == 0U) { // time event scheduled for removal? - prev->m_next = e->m_next; - // mark time event 'e' as NOT linked - e->refCtr_ = static_cast(e->refCtr_ - & static_cast(~TE_IS_LINKED)); // do NOT advance the prev pointer QF_MEM_APP(); QF_CRIT_EXIT(); // exit crit. section to reduce latency @@ -341,75 +433,86 @@ void QTimeEvt::tick( // of critical sections in QF ports, in which it can occur. QF_CRIT_EXIT_NOP(); } - else { - e->m_ctr = (e->m_ctr - 1U); - - if (e->m_ctr == 0U) { // is time evt about to expire? - QActive * const act = e->toActive(); - - if (e->m_interval != 0U) { // periodic time evt? - e->m_ctr = e->m_interval; // rearm the time event - prev = e; // advance to this time event - } - else { // one-shot time event: automatically disarm - prev->m_next = e->m_next; - - // mark time event 'e' as NOT linked - e->refCtr_ = static_cast(e->refCtr_ - & static_cast(~TE_IS_LINKED)); - // do NOT advance the prev pointer - - QS_BEGIN_PRE_(QS_QF_TIMEEVT_AUTO_DISARM, act->m_prio) - QS_OBJ_PRE_(e); // 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->m_prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(e); // the time event object - QS_SIG_PRE_(e->sig); // signal of this time event - QS_OBJ_PRE_(act); // the target AO - QS_U8_PRE_(tickRate); // tick rate - QS_END_PRE_() + else if (ctr == 1U) { // is time evt about to expire? + QActive * const act = te->toActive(); + if (te->m_interval != 0U) { // periodic time evt? + te->m_ctr = te->m_interval; // rearm the time event + #ifndef Q_UNSAFE + te->m_ctr_dis = static_cast(~te->m_interval); + #endif // ndef Q_UNSAFE + prev = te; // advance to this time event + } + else { // one-shot time event: automatically disarm + te->m_ctr = 0U; + prev->m_next = te->m_next; + #ifndef Q_UNSAFE + te->m_ctr_dis = + static_cast(~static_cast(0U)); + prev->m_next_dis = + static_cast(~Q_PTR2UINT_CAST_(te->m_next)); + #endif // ndef Q_UNSAFE + + // mark time event 'te' as NOT linked + te->m_flags &= + static_cast(~QTE_FLAG_IS_LINKED); + // do NOT advance the prev pointer + + QS_BEGIN_PRE(QS_QF_TIMEEVT_AUTO_DISARM, act->m_prio) + QS_OBJ_PRE(te); // 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->m_prio) + QS_TIME_PRE(); // timestamp + QS_OBJ_PRE(te); // the time event object + QS_SIG_PRE(te->sig); // signal of this time event + QS_OBJ_PRE(act); // the target AO + QS_U8_PRE(tickRate); // tick rate + QS_END_PRE() #ifdef QXK_HPP_ - if (e->sig < Q_USER_SIG) { - QXThread::timeout_(act); - QF_MEM_APP(); - QF_CRIT_EXIT(); - } - else { - QF_MEM_APP(); - QF_CRIT_EXIT(); // exit crit. section before posting - - // act->POST() asserts if the queue overflows - act->POST(e, sender); - } - #else + if (te->sig < Q_USER_SIG) { + QXThread::timeout_(act); + QF_MEM_APP(); + QF_CRIT_EXIT(); + } + else { QF_MEM_APP(); QF_CRIT_EXIT(); // exit crit. section before posting // act->POST() asserts if the queue overflows - act->POST(e, sender); - #endif + act->POST(te, sender); } - else { - prev = e; // advance to this time event + #else + QF_MEM_APP(); + QF_CRIT_EXIT(); // exit crit. section before posting - QF_MEM_APP(); - QF_CRIT_EXIT(); // exit crit. section to reduce latency + // act->POST() asserts if the queue overflows + act->POST(te, sender); + #endif + } + else { // time event keeps timing out + --ctr; // decrement the tick counter + te->m_ctr = ctr; // update the original + #ifndef Q_UNSAFE + te->m_ctr_dis = static_cast(~ctr); + #endif // ndef Q_UNSAFE - // prevent merging critical sections, see NOTE above - QF_CRIT_EXIT_NOP(); - } + prev = te; // advance to this time event + + QF_MEM_APP(); + QF_CRIT_EXIT(); // exit crit. section to reduce latency + + // prevent merging critical sections, see NOTE above + QF_CRIT_EXIT_NOP(); } QF_CRIT_ENTRY(); // re-enter crit. section to continue the loop QF_MEM_SYS(); } - Q_ENSURE_INCRIT(190, lbound > 0U); + Q_ENSURE_INCRIT(890, lbound > 0U); QF_MEM_APP(); QF_CRIT_EXIT(); } @@ -418,7 +521,7 @@ void QTimeEvt::tick( bool QTimeEvt::noActive(std::uint_fast8_t const tickRate) noexcept { QF_CRIT_STAT QF_CRIT_ENTRY(); - Q_REQUIRE_INCRIT(800, tickRate < QF_MAX_TICK_RATE); + Q_REQUIRE_INCRIT(900, tickRate < QF_MAX_TICK_RATE); QF_CRIT_EXIT(); bool inactive; @@ -436,17 +539,20 @@ bool QTimeEvt::noActive(std::uint_fast8_t const tickRate) noexcept { //${QF::QTimeEvt::QTimeEvt} .................................................. QTimeEvt::QTimeEvt() noexcept - : - QEvt(0U), + : QEvt(0U), m_next(nullptr), +#ifndef Q_UNSAFE + m_next_dis(static_cast(~Q_PTR2UINT_CAST_(nullptr))), +#endif m_act(nullptr), m_ctr(0U), - m_interval(0U) -{ - // The refCtr_ attribute is not used in time events, so it is - // reused to hold the tickRate as well as other information - refCtr_ = 0U; // default rate 0 -} +#ifndef Q_UNSAFE + m_ctr_dis(static_cast(~static_cast(0U))), +#endif + m_interval(0U), + m_tickRate(0U), + m_flags(0U) +{} } // namespace QP //$enddef${QF::QTimeEvt} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/qk/qk.cpp b/src/qk/qk.cpp index 444efddaf..8d9a74186 100644 --- a/src/qk/qk.cpp +++ b/src/qk/qk.cpp @@ -3,17 +3,10 @@ // Model: qpcpp.qm // File: ${src::qk::qk.cpp} // -// This code has been generated by QM 6.2.0 . +// This code has been generated by QM 7.0.0 . // DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. // -// This code is covered by the following QP license: -// License # : LicenseRef-QL-dual -// Issued to : Any user of the QP/C++ real-time embedded framework -// Framework(s) : qpcpp -// Support ends : 2025-12-31 -// License scope: -// -// Copyright (C) 2005 Quantum Leaps, LLC . +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // Q u a n t u m L e a P s // ------------------------ @@ -21,21 +14,20 @@ // // 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: +// 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. // -// Contact information: +// NOTE: +// The GPL does NOT permit the incorporation of this code into proprietary +// programs. Please contact Quantum Leaps for commercial licensing options, +// which expressly supersede the GPL and are designed explicitly for +// closed-source distribution. +// +// Quantum Leaps contact information: // // // @@ -84,12 +76,12 @@ QSchedStatus schedLock(std::uint_fast8_t const ceiling) noexcept { // first store the previous lock prio QSchedStatus stat; if (ceiling > QK_priv_.lockCeil) { // raising the lock ceiling? - QS_BEGIN_PRE_(QS_SCHED_LOCK, QK_priv_.actPrio) - QS_TIME_PRE_(); // timestamp + QS_BEGIN_PRE(QS_SCHED_LOCK, QK_priv_.actPrio) + QS_TIME_PRE(); // timestamp // the previous lock ceiling & new lock ceiling - QS_2U8_PRE_(static_cast(QK_priv_.lockCeil), + QS_2U8_PRE(static_cast(QK_priv_.lockCeil), static_cast(ceiling)); - QS_END_PRE_() + QS_END_PRE() // previous status of the lock stat = static_cast(QK_priv_.lockCeil); @@ -123,12 +115,12 @@ void schedUnlock(QSchedStatus const prevCeil) noexcept { Q_REQUIRE_INCRIT(210, (!QK_ISR_CONTEXT_()) && (QK_priv_.lockCeil > prevCeil)); - QS_BEGIN_PRE_(QS_SCHED_UNLOCK, QK_priv_.actPrio) - QS_TIME_PRE_(); // timestamp + QS_BEGIN_PRE(QS_SCHED_UNLOCK, QK_priv_.actPrio) + QS_TIME_PRE(); // timestamp // current lock ceiling (old), previous lock ceiling (new) - QS_2U8_PRE_(static_cast(QK_priv_.lockCeil), + QS_2U8_PRE(static_cast(QK_priv_.lockCeil), static_cast(prevCeil)); - QS_END_PRE_() + QS_END_PRE() // restore the previous lock ceiling QK_priv_.lockCeil = prevCeil; @@ -257,11 +249,11 @@ void QK_activate_() noexcept { #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) if (p != pprev) { // changing threads? - QS_BEGIN_PRE_(QP::QS_SCHED_NEXT, p) - QS_TIME_PRE_(); // timestamp - QS_2U8_PRE_(p, // prio. of the scheduled AO + QS_BEGIN_PRE(QP::QS_SCHED_NEXT, p) + QS_TIME_PRE(); // timestamp + QS_2U8_PRE(p, // prio. of the scheduled AO pprev); // previous prio. - QS_END_PRE_() + QS_END_PRE() #ifdef QF_ON_CONTEXT_SW QF_onContextSw(QP::QActive::registry_[pprev], a); @@ -336,19 +328,19 @@ void QK_activate_() noexcept { if (prio_in != 0U) { // resuming an active object? a = QP::QActive::registry_[prio_in]; // pointer to preempted AO - QS_BEGIN_PRE_(QP::QS_SCHED_NEXT, prio_in) - QS_TIME_PRE_(); // timestamp + QS_BEGIN_PRE(QP::QS_SCHED_NEXT, prio_in) + QS_TIME_PRE(); // timestamp // prio. of the resumed AO, previous prio. - QS_2U8_PRE_(prio_in, pprev); - QS_END_PRE_() + QS_2U8_PRE(prio_in, pprev); + QS_END_PRE() } else { // resuming prio.==0 --> idle a = nullptr; // QK idle loop - QS_BEGIN_PRE_(QP::QS_SCHED_IDLE, pprev) - QS_TIME_PRE_(); // timestamp - QS_U8_PRE_(pprev); // previous prio. - QS_END_PRE_() + QS_BEGIN_PRE(QP::QS_SCHED_IDLE, pprev) + QS_TIME_PRE(); // timestamp + QS_U8_PRE(pprev); // previous prio. + QS_END_PRE() } #ifdef QF_ON_CONTEXT_SW @@ -418,6 +410,11 @@ int_t run() { QK_priv_.lockCeil_dis = static_cast(~QK_priv_.lockCeil); #endif + #ifdef QF_ON_CONTEXT_SW + // officially switch to the idle context + QF_onContextSw(nullptr, QActive::registry_[QK_priv_.nextPrio]); + #endif + // activate AOs to process events posted so far if (QK_sched_() != 0U) { QK_activate_(); @@ -447,7 +444,7 @@ namespace QP { //${QK::QActive::start} ...................................................... void QActive::start( QPrioSpec const prioSpec, - QEvt const * * const qSto, + QEvtPtr * const qSto, std::uint_fast16_t const qLen, void * const stkSto, std::uint_fast16_t const stkSize, diff --git a/src/qs/CMakeLists.txt b/src/qs/CMakeLists.txt index 9d9b96b0a..a47efd275 100644 --- a/src/qs/CMakeLists.txt +++ b/src/qs/CMakeLists.txt @@ -1,9 +1,15 @@ # ./src/qs -target_sources(qpcpp PRIVATE - "$<$:${CMAKE_CURRENT_SOURCE_DIR}/qs_64bit.cpp>" - "$<$:${CMAKE_CURRENT_SOURCE_DIR}/qs_fp.cpp>" - "$<$:${CMAKE_CURRENT_SOURCE_DIR}/qs_rx.cpp>" - "$<$:${CMAKE_CURRENT_SOURCE_DIR}/qstamp.cpp>" - "$<$:${CMAKE_CURRENT_SOURCE_DIR}/qs.cpp>" - "$<$,$>:${CMAKE_CURRENT_SOURCE_DIR}/qutest.cpp>" -) +if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/qs.cpp) + target_sources(qpcpp PRIVATE + "$<$:${CMAKE_CURRENT_SOURCE_DIR}/qs_64bit.cpp>" + "$<$:${CMAKE_CURRENT_SOURCE_DIR}/qs_fp.cpp>" + "$<$:${CMAKE_CURRENT_SOURCE_DIR}/qs_rx.cpp>" + "$<$:${CMAKE_CURRENT_SOURCE_DIR}/qstamp.cpp>" + "$<$:${CMAKE_CURRENT_SOURCE_DIR}/qs.cpp>" + "$<$,$>:${CMAKE_CURRENT_SOURCE_DIR}/qutest.cpp>" + ) +else() + target_sources(qpcpp PRIVATE + "$<$:${CMAKE_CURRENT_SOURCE_DIR}/qstamp.cpp>" + ) +endif() diff --git a/src/qs/qs.cpp b/src/qs/qs.cpp deleted file mode 100644 index 45be15e31..000000000 --- a/src/qs/qs.cpp +++ /dev/null @@ -1,1072 +0,0 @@ -//$file${src::qs::qs.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// -// Model: qpcpp.qm -// File: ${src::qs::qs.cpp} -// -// This code has been generated by QM 6.2.0 . -// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. -// -// This code is covered by the following QP license: -// License # : LicenseRef-QL-dual -// Issued to : Any user of the QP/C++ real-time embedded framework -// Framework(s) : qpcpp -// Support ends : 2025-12-31 -// License scope: -// -// Copyright (C) 2005 Quantum Leaps, LLC . -// -// 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 -// -// 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: -// -// -// -//$endhead${src::qs::qs.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -#define QP_IMPL // this is QP implementation -#include "qs_port.hpp" // QS port -#include "qs_pkg.hpp" // QS package-scope internal interface -#include "qstamp.hpp" // QP time-stamp -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem - -// unnamed namespace for local definitions with internal linkage -namespace { -Q_DEFINE_THIS_MODULE("qs") -} // unnamed namespace - -//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// Check for the minimum required QP version -#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U)) -#error qpcpp version 7.3.0 or higher required -#endif -//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//$define${QS::QS-TX} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { -namespace QS { - -//${QS::QS-TX::initBuf} ...................................................... -void initBuf( - std::uint8_t * const sto, - std::uint_fast32_t const stoSize) noexcept -{ - priv_.buf = sto; - priv_.end = static_cast(stoSize); - priv_.head = 0U; - priv_.tail = 0U; - priv_.used = 0U; - priv_.seq = 0U; - priv_.chksum = 0U; - priv_.critNest = 0U; - - glbFilter_(-static_cast(QS_ALL_RECORDS));// all global filters OFF - locFilter_(static_cast(QS_ALL_IDS)); // all local filters ON - priv_.locFilter_AP = nullptr; // deprecated "AP-filter" - - // produce an empty record to "flush" the QS trace buffer - beginRec_(QS_REC_NUM_(QS_EMPTY)); - endRec_(); - - // produce the reset record to inform QSPY of a new session - target_info_pre_(0xFFU); - - // hold off flushing after successful initialization (see QS_INIT()) -} - -//${QS::QS-TX::getByte} ...................................................... -std::uint16_t getByte() noexcept { - // NOTE: Must be called IN critical section. - // Also requires system-level memory access (QF_MEM_SYS()). - - std::uint16_t ret; - if (priv_.used == 0U) { - ret = QS_EOD; // set End-Of-Data - } - else { - std::uint8_t const * const buf = priv_.buf; // put in a temporary - QSCtr tail = priv_.tail; // put in a temporary (register) - ret = static_cast(buf[tail]); // set the byte to return - ++tail; // advance the tail - if (tail == priv_.end) { // tail wrap around? - tail = 0U; - } - priv_.tail = tail; // update the tail - priv_.used = (priv_.used - 1U); // one less byte used - } - return ret; // return the byte or EOD -} - -//${QS::QS-TX::getBlock} ..................................................... -std::uint8_t const * getBlock(std::uint16_t * const pNbytes) noexcept { - // NOTE: Must be called IN critical section. - // Also requires system-level memory access (QF_MEM_SYS()). - - QSCtr const used = priv_.used; // put in a temporary (register) - std::uint8_t *buf; - - // any bytes used in the ring buffer? - if (used != 0U) { - QSCtr tail = priv_.tail; // put in a temporary (register) - QSCtr const end = priv_.end; // put in a temporary (register) - QSCtr n = static_cast(end - tail); - if (n > used) { - n = used; - } - if (n > static_cast(*pNbytes)) { - n = static_cast(*pNbytes); - } - *pNbytes = static_cast(n); // n-bytes available - buf = priv_.buf; - buf = &buf[tail]; // the bytes are at the tail - - priv_.used = static_cast(used - n); - tail += n; - if (tail == end) { - tail = 0U; - } - priv_.tail = tail; - } - else { // no bytes available - *pNbytes = 0U; // no bytes available right now - buf = nullptr; // no bytes available right now - } - return buf; -} - -} // namespace QS -} // namespace QP -//$enddef${QS::QS-TX} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -#ifndef QF_MEM_ISOLATE -//$define${QS::filters} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { -namespace QS { - -//${QS::filters::filt_} ...................................................... -Filter filt_; - -} // namespace QS -} // namespace QP -//$enddef${QS::filters} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -#endif - -//============================================================================ -//! @cond INTERNAL - -namespace QP { -namespace QS { - -//............................................................................ -Attr priv_; - -//............................................................................ -void glbFilter_(std::int_fast16_t const filter) noexcept { - bool const isRemove = (filter < 0); - std::uint16_t const rec = isRemove - ? static_cast(-filter) - : static_cast(filter); - switch (rec) { - case QS_ALL_RECORDS: { - std::uint8_t const tmp = (isRemove ? 0x00U : 0xFFU); - std::uint_fast8_t i; - // set all global filters (partially unrolled loop) - for (i = 0U; i < Q_DIM(filt_.glb); i += 4U) { - filt_.glb[i ] = tmp; - filt_.glb[i + 1U] = tmp; - filt_.glb[i + 2U] = tmp; - filt_.glb[i + 3U] = tmp; - } - if (isRemove) { - // leave the "not maskable" filters enabled, - // see qs.h, Miscellaneous QS records (not maskable) - // - filt_.glb[0] = 0x01U; - filt_.glb[6] = 0x40U; - filt_.glb[7] = 0xFCU; - filt_.glb[8] = 0x7FU; - } - else { - // never turn the last 3 records on (0x7D, 0x7E, 0x7F) - filt_.glb[15] = 0x1FU; - } - break; - } - case QS_SM_RECORDS: - if (isRemove) { - filt_.glb[0] &= static_cast(~0xFEU & 0xFFU); - filt_.glb[1] &= static_cast(~0x03U & 0xFFU); - filt_.glb[6] &= static_cast(~0x80U & 0xFFU); - filt_.glb[7] &= static_cast(~0x03U & 0xFFU); - } - else { - filt_.glb[0] |= 0xFEU; - filt_.glb[1] |= 0x03U; - filt_.glb[6] |= 0x80U; - filt_.glb[7] |= 0x03U; - } - break; - case QS_AO_RECORDS: - if (isRemove) { - filt_.glb[1] &= static_cast(~0xFCU & 0xFFU); - filt_.glb[2] &= static_cast(~0x07U & 0xFFU); - filt_.glb[5] &= static_cast(~0x20U & 0xFFU); - } - else { - filt_.glb[1] |= 0xFCU; - filt_.glb[2] |= 0x07U; - filt_.glb[5] |= 0x20U; - } - break; - case QS_EQ_RECORDS: - if (isRemove) { - filt_.glb[2] &= static_cast(~0x78U & 0xFFU); - filt_.glb[5] &= static_cast(~0x40U & 0xFFU); - } - else { - filt_.glb[2] |= 0x78U; - filt_.glb[5] |= 0x40U; - } - break; - case QS_MP_RECORDS: - if (isRemove) { - filt_.glb[3] &= static_cast(~0x03U & 0xFFU); - filt_.glb[5] &= static_cast(~0x80U & 0xFFU); - } - else { - filt_.glb[3] |= 0x03U; - filt_.glb[5] |= 0x80U; - } - break; - case QS_QF_RECORDS: - if (isRemove) { - filt_.glb[2] &= static_cast(~0x80U & 0xFFU); - filt_.glb[3] &= static_cast(~0xFCU & 0xFFU); - filt_.glb[4] &= static_cast(~0xC0U & 0xFFU); - filt_.glb[5] &= static_cast(~0x1FU & 0xFFU); - } - else { - filt_.glb[2] |= 0x80U; - filt_.glb[3] |= 0xFCU; - filt_.glb[4] |= 0xC0U; - filt_.glb[5] |= 0x1FU; - } - break; - case QS_TE_RECORDS: - if (isRemove) { - filt_.glb[4] &= static_cast(~0x3FU & 0xFFU); - } - else { - filt_.glb[4] |= 0x3FU; - } - break; - case QS_SC_RECORDS: - if (isRemove) { - filt_.glb[6] &= static_cast(~0x3FU & 0xFFU); - } - else { - filt_.glb[6] |= 0x3FU; - } - break; - case QS_SEM_RECORDS: - if (isRemove) { - filt_.glb[8] &= static_cast(~0x80U & 0xFFU); - filt_.glb[9] &= static_cast(~0x07U & 0xFFU); - } - else { - filt_.glb[8] |= 0x80U; - filt_.glb[9] |= 0x07U; - } - break; - case QS_MTX_RECORDS: - if (isRemove) { - filt_.glb[9] &= static_cast(~0xF8U & 0xFFU); - filt_.glb[10] &= static_cast(~0x01U & 0xFFU); - } - else { - filt_.glb[9] |= 0xF8U; - filt_.glb[10] |= 0x01U; - } - break; - case QS_U0_RECORDS: - if (isRemove) { - filt_.glb[12] &= static_cast(~0xF0U & 0xFFU); - filt_.glb[13] &= static_cast(~0x01U & 0xFFU); - } - else { - filt_.glb[12] |= 0xF0U; - filt_.glb[13] |= 0x01U; - } - break; - case QS_U1_RECORDS: - if (isRemove) { - filt_.glb[13] &= static_cast(~0x3EU & 0xFFU); - } - else { - filt_.glb[13] |= 0x3EU; - } - break; - case QS_U2_RECORDS: - if (isRemove) { - filt_.glb[13] &= static_cast(~0xC0U & 0xFFU); - filt_.glb[14] &= static_cast(~0x07U & 0xFFU); - } - else { - filt_.glb[13] |= 0xC0U; - filt_.glb[14] |= 0x07U; - } - break; - case QS_U3_RECORDS: - if (isRemove) { - filt_.glb[14] &= static_cast(~0xF8U & 0xFFU); - } - else { - filt_.glb[14] |= 0xF8U; - } - break; - case QS_U4_RECORDS: - if (isRemove) { - filt_.glb[15] &= static_cast(~0x1FU & 0xFFU); - } - else { - filt_.glb[15] |= 0x1FU; - } - break; - case QS_UA_RECORDS: - if (isRemove) { - filt_.glb[12] &= static_cast(~0xF0U & 0xFFU); - filt_.glb[13] = 0U; - filt_.glb[14] = 0U; - filt_.glb[15] &= static_cast(~0x1FU & 0xFFU); - } - else { - filt_.glb[12] |= 0xF0U; - filt_.glb[13] |= 0xFFU; - filt_.glb[14] |= 0xFFU; - filt_.glb[15] |= 0x1FU; - } - break; - default: { - QS_CRIT_STAT - QS_CRIT_ENTRY(); - // QS rec number must be below 0x7D, so no need for escaping - Q_ASSERT_INCRIT(210, rec < 0x7DU); - QS_CRIT_EXIT(); - - if (isRemove) { - filt_.glb[rec >> 3U] - &= static_cast(~(1U << (rec & 7U)) & 0xFFU); - } - else { - filt_.glb[rec >> 3U] - |= static_cast(1U << (rec & 7U)); - // never turn the last 3 records on (0x7D, 0x7E, 0x7F) - filt_.glb[15] &= 0x1FU; - } - break; - } - } -} - -//............................................................................ -void locFilter_(std::int_fast16_t const filter) noexcept { - bool const isRemove = (filter < 0); - std::uint16_t const qsId = isRemove - ? static_cast(-filter) - : static_cast(filter); - std::uint8_t const tmp = (isRemove ? 0x00U : 0xFFU); - std::uint_fast8_t i; - switch (qsId) { - case QS_ALL_IDS: - // set all local filters (partially unrolled loop) - for (i = 0U; i < Q_DIM(filt_.loc); i += 4U) { - filt_.loc[i ] = tmp; - filt_.loc[i + 1U] = tmp; - filt_.loc[i + 2U] = tmp; - filt_.loc[i + 3U] = tmp; - } - break; - case QS_AO_IDS: - for (i = 0U; i < 8U; i += 4U) { - filt_.loc[i ] = tmp; - filt_.loc[i + 1U] = tmp; - filt_.loc[i + 2U] = tmp; - filt_.loc[i + 3U] = tmp; - } - break; - case QS_EP_IDS: - i = 8U; - filt_.loc[i ] = tmp; - filt_.loc[i + 1U] = tmp; - break; - case QS_AP_IDS: - i = 12U; - filt_.loc[i ] = tmp; - filt_.loc[i + 1U] = tmp; - filt_.loc[i + 2U] = tmp; - filt_.loc[i + 3U] = tmp; - break; - default: { - QS_CRIT_STAT - QS_CRIT_ENTRY(); - // qsId must be in range - Q_ASSERT_INCRIT(310, qsId < 0x7FU); - QS_CRIT_EXIT(); - if (isRemove) { - filt_.loc[qsId >> 3U] &= - static_cast( - ~(1U << (qsId & 7U)) & 0xFFU); - } - else { - filt_.loc[qsId >> 3U] - |= (1U << (qsId & 7U)); - } - break; - } - } - filt_.loc[0] |= 0x01U; // leave QS_ID == 0 always on -} - -//............................................................................ -void beginRec_(std::uint_fast8_t const rec) noexcept { - std::uint8_t const b = priv_.seq + 1U; - std::uint8_t chksum = 0U; // reset the checksum - std::uint8_t * const buf = priv_.buf; // put in a temporary (register) - QSCtr head = priv_.head; // put in a temporary (register) - QSCtr const end = priv_.end; // put in a temporary (register) - - priv_.seq = b; // store the incremented sequence num - priv_.used = (priv_.used + 2U); // 2 bytes about to be added - - QS_INSERT_ESC_BYTE_(b) - - chksum += static_cast(rec); - QS_INSERT_BYTE_(static_cast(rec)) // no need for escaping - - priv_.head = head; // save the head - priv_.chksum = chksum; // save the checksum -} - -//............................................................................ -void endRec_() noexcept { - std::uint8_t * const buf = priv_.buf; // put in a temporary (register) - QSCtr head = priv_.head; - QSCtr const end = priv_.end; - std::uint8_t b = priv_.chksum; - b ^= 0xFFU; // invert the bits in the checksum - - priv_.used = (priv_.used + 2U); // 2 bytes about to be added - - if ((b != QS_FRAME) && (b != QS_ESC)) { - QS_INSERT_BYTE_(b) - } - else { - QS_INSERT_BYTE_(QS_ESC) - QS_INSERT_BYTE_(b ^ QS_ESC_XOR) - priv_.used = (priv_.used + 1U); // account for the ESC byte - } - - QS_INSERT_BYTE_(QS_FRAME) // do not escape this QS_FRAME - - priv_.head = head; // save the head - if (priv_.used > end) { // overrun over the old data? - priv_.used = end; // the whole buffer is used - priv_.tail = head; // shift the tail to the old data - } -} - -//............................................................................ -void u8_raw_(std::uint8_t const d) noexcept { - std::uint8_t chksum = priv_.chksum; // put in a temporary (register) - std::uint8_t * const buf = priv_.buf; // put in a temporary (register) - QSCtr head = priv_.head; // put in a temporary (register) - QSCtr const end = priv_.end; // put in a temporary (register) - - priv_.used = (priv_.used + 1U); // 1 byte about to be added - QS_INSERT_ESC_BYTE_(d) - - priv_.head = head; // save the head - priv_.chksum = chksum; // save the checksum -} - -//............................................................................ -void u8u8_raw_( - std::uint8_t const d1, - std::uint8_t const d2) noexcept -{ - std::uint8_t chksum = priv_.chksum; // put in a temporary (register) - std::uint8_t * const buf = priv_.buf; // put in a temporary (register) - QSCtr head = priv_.head; // put in a temporary (register) - QSCtr const end = priv_.end; // put in a temporary (register) - - priv_.used = (priv_.used + 2U); // 2 bytes about to be added - QS_INSERT_ESC_BYTE_(d1) - QS_INSERT_ESC_BYTE_(d2) - - priv_.head = head; // save the head - priv_.chksum = chksum; // save the checksum -} - -//............................................................................ -void u16_raw_(std::uint16_t d) noexcept { - std::uint8_t b = static_cast(d); - std::uint8_t chksum = priv_.chksum; // put in a temporary (register) - std::uint8_t * const buf = priv_.buf; // put in a temporary (register) - QSCtr head = priv_.head; // put in a temporary (register) - QSCtr const end = priv_.end; // put in a temporary (register) - - priv_.used = (priv_.used + 2U); // 2 bytes about to be added - - QS_INSERT_ESC_BYTE_(b) - - d >>= 8U; - b = static_cast(d); - QS_INSERT_ESC_BYTE_(b) - - priv_.head = head; // save the head - priv_.chksum = chksum; // save the checksum -} - -//............................................................................ -void u32_raw_(std::uint32_t d) noexcept { - std::uint8_t chksum = priv_.chksum; // put in a temporary (register) - std::uint8_t * const buf = priv_.buf; // put in a temporary (register) - QSCtr head = priv_.head; // put in a temporary (register) - QSCtr const end = priv_.end; // put in a temporary (register) - - priv_.used = (priv_.used + 4U); // 4 bytes about to be added - for (std::uint_fast8_t i = 4U; i != 0U; --i) { - std::uint8_t const b = static_cast(d); - QS_INSERT_ESC_BYTE_(b) - d >>= 8U; - } - - priv_.head = head; // save the head - priv_.chksum = chksum; // save the checksum -} - -//............................................................................ -void obj_raw_(void const * const obj) noexcept { - #if (QS_OBJ_PTR_SIZE == 1U) - u8_raw_(reinterpret_cast(obj)); - #elif (QS_OBJ_PTR_SIZE == 2U) - u16_raw_(reinterpret_cast(obj)); - #elif (QS_OBJ_PTR_SIZE == 4U) - u32_raw_(reinterpret_cast(obj)); - #elif (QS_OBJ_PTR_SIZE == 8U) - u64_raw_(reinterpret_cast(obj)); - #else - u32_raw_(reinterpret_cast(obj)); - #endif -} - -//............................................................................ -void str_raw_(char const * s) noexcept { - std::uint8_t b = static_cast(*s); - std::uint8_t chksum = priv_.chksum; // put in a temporary (register) - std::uint8_t * const buf = priv_.buf; // put in a temporary (register) - QSCtr head = priv_.head; // put in a temporary (register) - QSCtr const end = priv_.end; // put in a temporary (register) - QSCtr used = priv_.used; // put in a temporary (register) - - while (b != 0U) { - chksum += b; // update checksum - QS_INSERT_BYTE_(b) // ASCII characters don't need escaping - ++s; - b = static_cast(*s); - ++used; - } - QS_INSERT_BYTE_(0U) // zero-terminate the string - ++used; - - priv_.head = head; // save the head - priv_.chksum = chksum; // save the checksum - priv_.used = used; // save # of used buffer space -} - -//............................................................................ -void u8_fmt_( - std::uint8_t const format, - std::uint8_t const d) noexcept -{ - std::uint8_t chksum = priv_.chksum; // put in a temporary (register) - std::uint8_t *const buf = priv_.buf; // put in a temporary (register) - QSCtr head = priv_.head; // put in a temporary (register) - QSCtr const end = priv_.end; // put in a temporary (register) - - priv_.used = (priv_.used + 2U); // 2 bytes about to be added - - QS_INSERT_ESC_BYTE_(format) - QS_INSERT_ESC_BYTE_(d) - - priv_.head = head; // save the head - priv_.chksum = chksum; // save the checksum -} - -//............................................................................ -void u16_fmt_( - std::uint8_t format, - std::uint16_t d) noexcept -{ - std::uint8_t chksum = priv_.chksum; // put in a temporary (register) - std::uint8_t * const buf = priv_.buf; // put in a temporary (register) - QSCtr head = priv_.head; // put in a temporary (register) - QSCtr const end = priv_.end; // put in a temporary (register) - - priv_.used = (priv_.used + 3U); // 3 bytes about to be added - - QS_INSERT_ESC_BYTE_(format) - - format = static_cast(d); - QS_INSERT_ESC_BYTE_(format) - - d >>= 8U; - format = static_cast(d); - QS_INSERT_ESC_BYTE_(format) - - priv_.head = head; // save the head - priv_.chksum = chksum; // save the checksum -} - -//............................................................................ -void u32_fmt_( - std::uint8_t format, - std::uint32_t d) noexcept -{ - std::uint8_t chksum = priv_.chksum; // put in a temporary (register) - std::uint8_t * const buf = priv_.buf; // put in a temporary (register) - QSCtr head = priv_.head; // put in a temporary (register) - QSCtr const end = priv_.end; // put in a temporary (register) - - priv_.used = (priv_.used + 5U); // 5 bytes about to be added - QS_INSERT_ESC_BYTE_(format) // insert the format byte - - for (std::uint_fast8_t i = 4U; i != 0U; --i) { - format = static_cast(d); - QS_INSERT_ESC_BYTE_(format) - d >>= 8U; - } - - priv_.head = head; // save the head - priv_.chksum = chksum; // save the checksum -} - -//............................................................................ -void str_fmt_(char const * s) noexcept { - std::uint8_t b = static_cast(*s); - std::uint8_t chksum = static_cast( - priv_.chksum + static_cast(STR_T)); - std::uint8_t * const buf = priv_.buf; // put in a temporary (register) - QSCtr head = priv_.head; // put in a temporary (register) - QSCtr const end = priv_.end; // put in a temporary (register) - QSCtr used = priv_.used; // put in a temporary (register) - - used += 2U; // the format byte and the terminating-0 - - QS_INSERT_BYTE_(static_cast(STR_T)) - while (b != 0U) { - // ASCII characters don't need escaping - chksum += b; // update checksum - QS_INSERT_BYTE_(b) - ++s; - b = static_cast(*s); - ++used; - } - QS_INSERT_BYTE_(0U) // zero-terminate the string - - priv_.head = head; // save the head - priv_.chksum = chksum; // save the checksum - priv_.used = used; // save # of used buffer space -} - -//............................................................................ -void mem_fmt_( - std::uint8_t const * blk, - std::uint8_t size) noexcept -{ - std::uint8_t b = static_cast(MEM_T); - std::uint8_t chksum = priv_.chksum + b; - std::uint8_t * const buf = priv_.buf; // put in a temporary (register) - QSCtr head = priv_.head; // put in a temporary (register) - QSCtr const end = priv_.end; // put in a temporary (register) - - priv_.used = (priv_.used + size + 2U); // size+2 bytes to be added - - QS_INSERT_BYTE_(b) - QS_INSERT_ESC_BYTE_(size) - - // output the 'size' number of bytes - for (; size != 0U; --size) { - b = *blk; - QS_INSERT_ESC_BYTE_(b) - ++blk; - } - - priv_.head = head; // save the head - priv_.chksum = chksum; // save the checksum -} - -//............................................................................ -void sig_dict_pre_( - QSignal const sig, - void const * const obj, - char const * const name) noexcept -{ - QS_CRIT_STAT - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - - beginRec_(static_cast(QS_SIG_DICT)); - QS_SIG_PRE_(sig); - QS_OBJ_PRE_(obj); - QS_STR_PRE_((*name == '&') ? &name[1] : name); - endRec_(); - - QS_MEM_APP(); - QS_CRIT_EXIT(); - onFlush(); -} - -//............................................................................ -void obj_dict_pre_( - void const * const obj, - char const * const name) noexcept -{ - QS_CRIT_STAT - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - - beginRec_(static_cast(QS_OBJ_DICT)); - QS_OBJ_PRE_(obj); - QS_STR_PRE_((*name == '&') ? &name[1] : name); - endRec_(); - - QS_MEM_APP(); - QS_CRIT_EXIT(); - onFlush(); -} - -//............................................................................ -void obj_arr_dict_pre_( - void const * const obj, - std::uint_fast16_t const idx, - char const * const name) noexcept -{ - QS_CRIT_STAT - QS_CRIT_ENTRY(); - Q_REQUIRE_INCRIT(400, idx < 1000U); - QS_CRIT_EXIT(); - - // format idx into a char buffer as "xxx\0" - std::uint8_t idx_str[4]; - std::uint_fast16_t tmp = idx; - std::uint8_t i; - idx_str[3] = 0U; // zero-terminate - idx_str[2] = static_cast( - static_cast('0') + (tmp % 10U)); - tmp /= 10U; - idx_str[1] = static_cast( - static_cast('0') + (tmp % 10U)); - if (idx_str[1] == static_cast('0')) { - i = 2U; - } - else { - tmp /= 10U; - idx_str[0] = static_cast( - static_cast('0') + (tmp % 10U)); - if (idx_str[0] == static_cast('0')) { - i = 1U; - } - else { - i = 0U; - } - } - - std::uint8_t j = ((*name == '&') ? 1U : 0U); - - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - - beginRec_(static_cast(QS_OBJ_DICT)); - QS_OBJ_PRE_(obj); - for (; name[j] != '\0'; ++j) { - QS_U8_PRE_(name[j]); - if (name[j] == '[') { - ++j; - break; - } - } - for (; idx_str[i] != 0U; ++i) { - QS_U8_PRE_(idx_str[i]); - } - // skip chars until ']' - for (; name[j] != '\0'; ++j) { - if (name[j] == ']') { - break; - } - } - for (; name[j] != '\0'; ++j) { - QS_U8_PRE_(name[j]); - } - QS_U8_PRE_(0U); // zero-terminate - endRec_(); - - QS_MEM_APP(); - QS_CRIT_EXIT(); - onFlush(); -} - -//............................................................................ -void fun_dict_pre_( - QSpyFunPtr fun, - char const * const name) noexcept -{ - QS_CRIT_STAT - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - - beginRec_(static_cast(QS_FUN_DICT)); - QS_FUN_PRE_(fun); - QS_STR_PRE_((*name == '&') ? &name[1] : name); - endRec_(); - - QS_MEM_APP(); - QS_CRIT_EXIT(); - onFlush(); -} - -//............................................................................ -void usr_dict_pre_( - enum_t const rec, - char const * const name) noexcept -{ - QS_CRIT_STAT - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - - beginRec_(static_cast(QS_USR_DICT)); - QS_U8_PRE_(rec); - QS_STR_PRE_(name); - endRec_(); - - QS_MEM_APP(); - QS_CRIT_EXIT(); - onFlush(); -} - -//............................................................................ -void enum_dict_pre_( - enum_t const value, - std::uint8_t const group, - char const * const name) noexcept -{ - QS_CRIT_STAT - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - - beginRec_(static_cast(QS_ENUM_DICT)); - QS_2U8_PRE_(static_cast(value), group); - QS_STR_PRE_(name); - endRec_(); - - QS_MEM_APP(); - QS_CRIT_EXIT(); - onFlush(); -} - -//............................................................................ -void assertion_pre_( - char const * const module, - int_t const id, - std::uint32_t const delay) noexcept -{ - // NOTE: called in a critical section - - beginRec_(static_cast(QS_ASSERT_FAIL)); - QS_TIME_PRE_(); - QS_U16_PRE_(id); - QS_STR_PRE_((module != nullptr) ? module : "?"); - endRec_(); - onFlush(); - - // busy-wait until all QS data makes it over to the host - for (std::uint32_t volatile ctr = delay; ctr > 0U; ) { - ctr = (ctr - 1U); - } - QS::onCleanup(); -} - -//............................................................................ -void crit_entry_pre_() noexcept { - beginRec_(static_cast(QS_QF_CRIT_ENTRY)); - QS_TIME_PRE_(); - priv_.critNest = (priv_.critNest + 1U); - QS_U8_PRE_(priv_.critNest); - endRec_(); -} - -//............................................................................ -void crit_exit_pre_() noexcept { - beginRec_(static_cast(QS_QF_CRIT_EXIT)); - QS_TIME_PRE_(); - QS_U8_PRE_(QS::priv_.critNest); - priv_.critNest = (priv_.critNest - 1U); - endRec_(); -} - -//............................................................................ -void isr_entry_pre_( - std::uint8_t const isrnest, - std::uint8_t const prio) noexcept -{ - beginRec_(static_cast(QS_QF_ISR_ENTRY)); - QS_TIME_PRE_(); - QS_U8_PRE_(isrnest); - QS_U8_PRE_(prio); - endRec_(); -} - -//............................................................................ -void isr_exit_pre_( - std::uint8_t const isrnest, - std::uint8_t const prio) noexcept -{ - beginRec_(static_cast(QS_QF_ISR_EXIT)); - QS_TIME_PRE_(); - QS_U8_PRE_(isrnest); - QS_U8_PRE_(prio); - endRec_(); -} - -//............................................................................ -void target_info_pre_(std::uint8_t const isReset) { - // NOTE: called in a critical section - - static constexpr std::uint8_t ZERO = static_cast('0'); - static std::uint8_t const * const TIME = - reinterpret_cast(&BUILD_TIME[0]); - static std::uint8_t const * const DATE = - reinterpret_cast(&BUILD_DATE[0]); - - beginRec_(static_cast(QS_TARGET_INFO)); - u8_raw_(isReset); - - static union { - std::uint16_t u16; - std::uint8_t u8[2]; - } endian_test; - endian_test.u16 = 0x0102U; - // big endian ? add the 0x8000U flag - QS_U16_PRE_(((endian_test.u8[0] == 0x01U) - ? (0x8000U | QP_VERSION) - : QP_VERSION)); // target endianness + version number - - // send the object sizes... - u8_raw_(Q_SIGNAL_SIZE - | static_cast(QF_EVENT_SIZ_SIZE << 4U)); - -#ifdef QF_EQUEUE_CTR_SIZE - u8_raw_(QF_EQUEUE_CTR_SIZE - | static_cast(QF_TIMEEVT_CTR_SIZE << 4U)); -#else - QS::u8_raw_(static_cast(QF_TIMEEVT_CTR_SIZE << 4U)); -#endif // ifdef QF_EQUEUE_CTR_SIZE - -#ifdef QF_MPOOL_CTR_SIZE - QS::u8_raw_(QF_MPOOL_SIZ_SIZE - | static_cast(QF_MPOOL_CTR_SIZE << 4U)); -#else - QS::u8_raw_(0U); -#endif // ifdef QF_MPOOL_CTR_SIZE - - QS::u8_raw_(QS_OBJ_PTR_SIZE | (QS_FUN_PTR_SIZE << 4U)); - QS::u8_raw_(QS_TIME_SIZE); - - // send the bounds... - QS::u8_raw_(QF_MAX_ACTIVE); - QS::u8_raw_(QF_MAX_EPOOL | (QF_MAX_TICK_RATE << 4U)); - - // send the build time in three bytes (sec, min, hour)... - QS::u8_raw_((10U * (TIME[6] - ZERO)) + (TIME[7] - ZERO)); - QS::u8_raw_((10U * (TIME[3] - ZERO)) + (TIME[4] - ZERO)); - if (BUILD_TIME[0] == static_cast(' ')) { - QS::u8_raw_(TIME[1] - ZERO); - } - else { - QS::u8_raw_((10U * (TIME[0] - ZERO)) + (TIME[1] - ZERO)); - } - - // send the build date in three bytes (day, month, year) ... - if (BUILD_DATE[4] == static_cast(' ')) { - QS::u8_raw_(DATE[5] - ZERO); - } - else { - QS::u8_raw_((10U * (DATE[4] - ZERO)) + (DATE[5] - ZERO)); - } - // convert the 3-letter month to a number 1-12 ... - std::uint8_t b; - switch (DATE[0] + DATE[1] + DATE[2]) { - case 'J' + 'a' +'n': - b = 1U; - break; - case 'F' + 'e' + 'b': - b = 2U; - break; - case 'M' + 'a' +'r': - b = 3U; - break; - case 'A' + 'p' + 'r': - b = 4U; - break; - case 'M' + 'a' + 'y': - b = 5U; - break; - case 'J' + 'u' + 'n': - b = 6U; - break; - case 'J' + 'u' + 'l': - b = 7U; - break; - case 'A' + 'u' + 'g': - b = 8U; - break; - case 'S' + 'e' + 'p': - b = 9U; - break; - case 'O' + 'c' + 't': - b = 10U; - break; - case 'N' + 'o' + 'v': - b = 11U; - break; - case 'D' + 'e' + 'c': - b = 12U; - break; - default: - b = 0U; - break; - } - QS::u8_raw_(b); // store the month - QS::u8_raw_((10U * (DATE[9] - ZERO)) + (DATE[10] - ZERO)); - QS::endRec_(); -} - -} // namespace QS -} // namespace QP - -//! @endcond diff --git a/src/qs/qs_64bit.cpp b/src/qs/qs_64bit.cpp deleted file mode 100644 index be957c817..000000000 --- a/src/qs/qs_64bit.cpp +++ /dev/null @@ -1,97 +0,0 @@ -//$file${src::qs::qs_64bit.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// -// Model: qpcpp.qm -// File: ${src::qs::qs_64bit.cpp} -// -// This code has been generated by QM 6.2.0 . -// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. -// -// This code is covered by the following QP license: -// License # : LicenseRef-QL-dual -// Issued to : Any user of the QP/C++ real-time embedded framework -// Framework(s) : qpcpp -// Support ends : 2025-12-31 -// License scope: -// -// Copyright (C) 2005 Quantum Leaps, LLC . -// -// 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 -// -// 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: -// -// -// -//$endhead${src::qs::qs_64bit.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -#define QP_IMPL // this is QF/QK implementation -#include "qs_port.hpp" // QS port -#include "qs_pkg.hpp" // QS package-scope internal interface - -//============================================================================ -//! @cond INTERNAL - -namespace QP { -namespace QS { - -//${QS::QS-tx-64bit::u64_raw_} ............................................... -void u64_raw_(std::uint64_t d) noexcept { - std::uint8_t chksum = priv_.chksum; - std::uint8_t * const buf = priv_.buf; - QSCtr head = priv_.head; - QSCtr const end = priv_.end; - - priv_.used = (priv_.used + 8U); // 8 bytes are about to be added - for (std::int_fast8_t i = 8U; i != 0U; --i) { - std::uint8_t const b = static_cast(d); - QS_INSERT_ESC_BYTE_(b) - d >>= 8U; - } - - priv_.head = head; // save the head - priv_.chksum = chksum; // save the checksum -} - -//${QS::QS-tx-64bit::u64_fmt_} ............................................... -void u64_fmt_( - std::uint8_t format, - std::uint64_t d) noexcept -{ - std::uint8_t chksum = priv_.chksum; - std::uint8_t * const buf = priv_.buf; - QSCtr head = priv_.head; - QSCtr const end = priv_.end; - - priv_.used = (priv_.used + 9U); // 9 bytes are about to be added - QS_INSERT_ESC_BYTE_(format) // insert the format byte - - for (std::int_fast8_t i = 8U; i != 0U; --i) { - format = static_cast(d); - QS_INSERT_ESC_BYTE_(format) - d >>= 8U; - } - - priv_.head = head; // save the head - priv_.chksum = chksum; // save the checksum -} - -} // namespace QS -} // namespace QP - -//! @endcond diff --git a/src/qs/qs_fp.cpp b/src/qs/qs_fp.cpp deleted file mode 100644 index a013aed59..000000000 --- a/src/qs/qs_fp.cpp +++ /dev/null @@ -1,134 +0,0 @@ -//$file${src::qs::qs_fp.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// -// Model: qpcpp.qm -// File: ${src::qs::qs_fp.cpp} -// -// This code has been generated by QM 6.2.0 . -// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. -// -// This code is covered by the following QP license: -// License # : LicenseRef-QL-dual -// Issued to : Any user of the QP/C++ real-time embedded framework -// Framework(s) : qpcpp -// Support ends : 2025-12-31 -// License scope: -// -// Copyright (C) 2005 Quantum Leaps, LLC . -// -// 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 -// -// 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: -// -// -// -//$endhead${src::qs::qs_fp.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -#define QP_IMPL // this is QF/QK implementation -#include "qs_port.hpp" // QS port -#include "qs_pkg.hpp" // QS package-scope internal interface - -//============================================================================ -//! @cond INTERNAL - -namespace QP { -namespace QS { - -//${QS::QS-tx-fp::f32_fmt_} .................................................. -void f32_fmt_( - std::uint8_t format, - float32_t f) noexcept -{ - union F32Rep { - float32_t f; - std::uint32_t u; - } fu32; // the internal binary representation - std::uint8_t chksum = priv_.chksum; // put in a temporary (register) - std::uint8_t * const buf = priv_.buf; // put in a temporary (register) - QSCtr head = priv_.head; // put in a temporary (register) - QSCtr const end = priv_.end; // put in a temporary (register) - - fu32.f = f; // assign the binary representation - - priv_.used = (priv_.used + 5U); // 5 bytes about to be added - QS_INSERT_ESC_BYTE_(format) // insert the format byte - - for (std::uint_fast8_t i = 4U; i != 0U; --i) { - format = static_cast(fu32.u); - QS_INSERT_ESC_BYTE_(format) - fu32.u >>= 8U; - } - - priv_.head = head; // save the head - priv_.chksum = chksum; // save the checksum -} - -//${QS::QS-tx-fp::f64_fmt_} .................................................. -void f64_fmt_( - std::uint8_t format, - float64_t d) noexcept -{ - union F64Rep { - float64_t d; - std::uint32_t u[2]; - } fu64; // the internal binary representation - std::uint8_t chksum = priv_.chksum; - std::uint8_t * const buf = priv_.buf; - QSCtr head = priv_.head; - QSCtr const end = priv_.end; - std::uint32_t i; - // static constant untion to detect endianness of the machine - static union U32Rep { - std::uint32_t u32; - std::uint8_t u8; - } const endian = { 1U }; - - fu64.d = d; // assign the binary representation - - // is this a big-endian machine? - if (endian.u8 == 0U) { - // swap fu64.u[0] <-> fu64.u[1]... - i = fu64.u[0]; - fu64.u[0] = fu64.u[1]; - fu64.u[1] = i; - } - - priv_.used = (priv_.used + 9U); // 9 bytes about to be added - QS_INSERT_ESC_BYTE_(format) // insert the format byte - - // output 4 bytes from fu64.u[0]... - for (i = 4U; i != 0U; --i) { - QS_INSERT_ESC_BYTE_(static_cast(fu64.u[0])) - fu64.u[0] >>= 8U; - } - - // output 4 bytes from fu64.u[1]... - for (i = 4U; i != 0U; --i) { - QS_INSERT_ESC_BYTE_(static_cast(fu64.u[1])) - fu64.u[1] >>= 8U; - } - - priv_.head = head; // update the head - priv_.chksum = chksum; // update the checksum -} - -} // namespace QS -} // namespace QP - -//! @endcond diff --git a/src/qs/qs_rx.cpp b/src/qs/qs_rx.cpp deleted file mode 100644 index 387933903..000000000 --- a/src/qs/qs_rx.cpp +++ /dev/null @@ -1,1245 +0,0 @@ -//$file${src::qs::qs_rx.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// -// Model: qpcpp.qm -// File: ${src::qs::qs_rx.cpp} -// -// This code has been generated by QM 6.2.0 . -// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. -// -// This code is covered by the following QP license: -// License # : LicenseRef-QL-dual -// Issued to : Any user of the QP/C++ real-time embedded framework -// Framework(s) : qpcpp -// Support ends : 2025-12-31 -// License scope: -// -// Copyright (C) 2005 Quantum Leaps, LLC . -// -// 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 -// -// 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: -// -// -// -//$endhead${src::qs::qs_rx.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -#define QP_IMPL // this is QP implementation -#include "qs_port.hpp" // QS port -#include "qs_pkg.hpp" // QS package-scope internal interface -#include "qp_pkg.hpp" // QP package-scope interface -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem - -//============================================================================ -//! @cond INTERNAL - -namespace { // unnamed local namespace - -Q_DEFINE_THIS_MODULE("qs_rx") - -enum RxStateEnum : std::uint8_t { - ERROR_STATE, - WAIT4_SEQ, - WAIT4_REC, - WAIT4_INFO_FRAME, - WAIT4_CMD_ID, - WAIT4_CMD_PARAM1, - WAIT4_CMD_PARAM2, - WAIT4_CMD_PARAM3, - WAIT4_CMD_FRAME, - WAIT4_RESET_FRAME, - WAIT4_TICK_RATE, - WAIT4_TICK_FRAME, - WAIT4_PEEK_OFFS, - WAIT4_PEEK_SIZE, - WAIT4_PEEK_NUM, - WAIT4_PEEK_FRAME, - WAIT4_POKE_OFFS, - WAIT4_POKE_SIZE, - WAIT4_POKE_NUM, - WAIT4_POKE_DATA, - WAIT4_POKE_FRAME, - WAIT4_FILL_DATA, - WAIT4_FILL_FRAME, - WAIT4_FILTER_LEN, - WAIT4_FILTER_DATA, - WAIT4_FILTER_FRAME, - WAIT4_OBJ_KIND, - WAIT4_OBJ_ADDR, - WAIT4_OBJ_FRAME, - WAIT4_QUERY_KIND, - WAIT4_QUERY_FRAME, - WAIT4_EVT_PRIO, - WAIT4_EVT_SIG, - WAIT4_EVT_LEN, - WAIT4_EVT_PAR, - WAIT4_EVT_FRAME - -#ifdef Q_UTEST - , - WAIT4_TEST_SETUP_FRAME, - WAIT4_TEST_TEARDOWN_FRAME, - WAIT4_TEST_PROBE_DATA, - WAIT4_TEST_PROBE_ADDR, - WAIT4_TEST_PROBE_FRAME, - WAIT4_TEST_CONTINUE_FRAME -#endif // Q_UTEST -}; - -// internal helper functions... -static void rxParseData_(std::uint8_t const b) noexcept; -static void rxHandleGoodFrame_(std::uint8_t const state); -static void rxHandleBadFrame_(std::uint8_t const state) noexcept; -static void rxReportAck_(enum QP::QSpyRxRecords const recId) noexcept; -static void rxReportError_(std::uint8_t const code) noexcept; -static void rxReportDone_(enum QP::QSpyRxRecords const recId) noexcept; -static void queryCurrObj_(std::uint8_t obj_kind) noexcept; -static void rxPoke_() noexcept; - -// Internal QS-RX function to take a tran. in the QS-RX FSM -static inline void tran_(RxStateEnum const target) noexcept { - QP::QS::rxPriv_.state = static_cast(target); -} - -} // unnamed namespace - -#ifndef QF_MEM_ISOLATE -namespace QP { -namespace QS { -RxAttr rxPriv_; -} // namespace QS -} // namespace QP -#endif // QF_MEM_ISOLATE - -//! @endcond -//============================================================================ - -//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// Check for the minimum required QP version -#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U)) -#error qpcpp version 7.3.0 or higher required -#endif -//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//$define${QS::QS-RX} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { -namespace QS { - -//${QS::QS-RX::rxInitBuf} .................................................... -void rxInitBuf( - std::uint8_t * const sto, - std::uint16_t const stoSize) noexcept -{ - rxPriv_.buf = &sto[0]; - rxPriv_.end = static_cast(stoSize); - rxPriv_.head = 0U; - rxPriv_.tail = 0U; - - rxPriv_.currObj[QS::SM_OBJ] = nullptr; - rxPriv_.currObj[QS::AO_OBJ] = nullptr; - rxPriv_.currObj[QS::MP_OBJ] = nullptr; - rxPriv_.currObj[QS::EQ_OBJ] = nullptr; - rxPriv_.currObj[QS::TE_OBJ] = nullptr; - rxPriv_.currObj[QS::AP_OBJ] = nullptr; - - tran_(WAIT4_SEQ); - QP::QS::rxPriv_.esc = 0U; - QP::QS::rxPriv_.seq = 0U; - QP::QS::rxPriv_.chksum = 0U; - - beginRec_(static_cast(QS_OBJ_DICT)); - QS_OBJ_PRE_(&rxPriv_); - QS_STR_PRE_("QS_RX"); - endRec_(); - // no QS_REC_DONE(), because QS is not running yet - - #ifdef Q_UTEST - tstPriv_.tpNum = 0U; - tstPriv_.testTime = 0U; - #endif // Q_UTEST -} - -//${QS::QS-RX::rxParse} ...................................................... -void rxParse() { - QSCtr tail = rxPriv_.tail; - while (rxPriv_.head != tail) { // QS-RX buffer NOT empty? - std::uint8_t b = rxPriv_.buf[tail]; - - ++tail; - if (tail == rxPriv_.end) { - tail = 0U; - } - rxPriv_.tail = tail; // update the tail to a *valid* index - - if (QP::QS::rxPriv_.esc != 0U) { // escaped byte arrived? - QP::QS::rxPriv_.esc = 0U; - b ^= QS_ESC_XOR; - - QP::QS::rxPriv_.chksum += b; - rxParseData_(b); - } - else if (b == QS_ESC) { - QP::QS::rxPriv_.esc = 1U; - } - else if (b == QS_FRAME) { - // get ready for the next frame - b = QP::QS::rxPriv_.state; // save the current state in b - QP::QS::rxPriv_.esc = 0U; - tran_(WAIT4_SEQ); - - if (QP::QS::rxPriv_.chksum == QS_GOOD_CHKSUM) { - QP::QS::rxPriv_.chksum = 0U; - rxHandleGoodFrame_(b); - } - else { // bad checksum - QP::QS::rxPriv_.chksum = 0U; - rxReportError_(0x41U); - rxHandleBadFrame_(b); - } - } - else { - QP::QS::rxPriv_.chksum += b; - rxParseData_(b); - } - } -} - -//${QS::QS-RX::setCurrObj} ................................................... -void setCurrObj( - std::uint8_t const obj_kind, - void * const obj_ptr) -{ - QS_CRIT_STAT - QS_CRIT_ENTRY(); - Q_REQUIRE_INCRIT(300, obj_kind < Q_DIM(rxPriv_.currObj)); - - QS_MEM_SYS(); - - rxPriv_.currObj[obj_kind] = obj_ptr; - - QS_MEM_APP(); - QS_CRIT_EXIT(); -} - -//${QS::QS-RX::rxGetNfree} ................................................... -std::uint16_t rxGetNfree() noexcept { - // NOTE: Must be called IN critical section. - // Also requires system-level memory access (QF_MEM_SYS()). - - QSCtr const head = rxPriv_.head; - std::uint16_t nFree; - if (head == rxPriv_.tail) { // buffer empty? - nFree = static_cast(rxPriv_.end - 1U); - } - else if (head < rxPriv_.tail) { - nFree = static_cast(rxPriv_.tail - head - 1U); - } - else { - nFree = static_cast(rxPriv_.end + rxPriv_.tail - - head - 1U); - } - return nFree; -} - -} // namespace QS -} // namespace QP -//$enddef${QS::QS-RX} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -//============================================================================ -//! @cond INTERNAL -namespace { // unnamed local namespace - -//............................................................................ -static void rxParseData_(std::uint8_t const b) noexcept { - switch (QP::QS::rxPriv_.state) { - case WAIT4_SEQ: { - ++QP::QS::rxPriv_.seq; - if (QP::QS::rxPriv_.seq != b) { // not the expected sequence? - rxReportError_(0x42U); - QP::QS::rxPriv_.seq = b; // update the sequence - } - tran_(WAIT4_REC); - break; - } - case WAIT4_REC: { - switch (b) { - case QP::QS_RX_INFO: - tran_(WAIT4_INFO_FRAME); - break; - case QP::QS_RX_COMMAND: - tran_(WAIT4_CMD_ID); - break; - case QP::QS_RX_RESET: - tran_(WAIT4_RESET_FRAME); - break; - case QP::QS_RX_TICK: - tran_(WAIT4_TICK_RATE); - break; - case QP::QS_RX_PEEK: - if (QP::QS::rxPriv_.currObj[QP::QS::AP_OBJ] != nullptr) { - QP::QS::rxPriv_.var.peek.offs = 0U; - QP::QS::rxPriv_.var.peek.idx = 0U; - tran_(WAIT4_PEEK_OFFS); - } - else { - rxReportError_( - static_cast(QP::QS_RX_PEEK)); - tran_(ERROR_STATE); - } - break; - case QP::QS_RX_POKE: - case QP::QS_RX_FILL: - QP::QS::rxPriv_.var.poke.fill = - (b == static_cast(QP::QS_RX_FILL)) - ? 1U : 0U; - if (QP::QS::rxPriv_.currObj[QP::QS::AP_OBJ] != nullptr) { - QP::QS::rxPriv_.var.poke.offs = 0U; - QP::QS::rxPriv_.var.poke.idx = 0U; - tran_(WAIT4_POKE_OFFS); - } - else { - rxReportError_( - (QP::QS::rxPriv_.var.poke.fill != 0U) - ? static_cast(QP::QS_RX_FILL) - : static_cast(QP::QS_RX_POKE)); - tran_(ERROR_STATE); - } - break; - case QP::QS_RX_GLB_FILTER: // intentionally fall-through - case QP::QS_RX_LOC_FILTER: - QP::QS::rxPriv_.var.flt.recId = b; - tran_(WAIT4_FILTER_LEN); - break; - case QP::QS_RX_AO_FILTER: // intentionally fall-through - case QP::QS_RX_CURR_OBJ: - QP::QS::rxPriv_.var.obj.recId = b; - tran_(WAIT4_OBJ_KIND); - break; - case QP::QS_RX_QUERY_CURR: - QP::QS::rxPriv_.var.obj.recId = - static_cast(QP::QS_RX_QUERY_CURR); - tran_(WAIT4_QUERY_KIND); - break; - case QP::QS_RX_EVENT: - tran_(WAIT4_EVT_PRIO); - break; - -#ifdef Q_UTEST - case QP::QS_RX_TEST_SETUP: - tran_(WAIT4_TEST_SETUP_FRAME); - break; - case QP::QS_RX_TEST_TEARDOWN: - tran_(WAIT4_TEST_TEARDOWN_FRAME); - break; - case QP::QS_RX_TEST_CONTINUE: - tran_(WAIT4_TEST_CONTINUE_FRAME); - break; - case QP::QS_RX_TEST_PROBE: - if (QP::QS::tstPriv_.tpNum - < static_cast( - (sizeof(QP::QS::tstPriv_.tpBuf) - / sizeof(QP::QS::tstPriv_.tpBuf[0])))) - { - QP::QS::rxPriv_.var.tp.data = 0U; - QP::QS::rxPriv_.var.tp.idx = 0U; - tran_(WAIT4_TEST_PROBE_DATA); - } - else { // the # Test-Probes exceeded - rxReportError_( - static_cast(QP::QS_RX_TEST_PROBE)); - tran_(ERROR_STATE); - } - break; -#endif // Q_UTEST - - default: - rxReportError_(0x43U); - tran_(ERROR_STATE); - break; - } - break; - } - case WAIT4_INFO_FRAME: { - // keep ignoring the data until a frame is collected - break; - } - case WAIT4_CMD_ID: { - QP::QS::rxPriv_.var.cmd.cmdId = b; - QP::QS::rxPriv_.var.cmd.idx = 0U; - QP::QS::rxPriv_.var.cmd.param1 = 0U; - QP::QS::rxPriv_.var.cmd.param2 = 0U; - QP::QS::rxPriv_.var.cmd.param3 = 0U; - tran_(WAIT4_CMD_PARAM1); - break; - } - case WAIT4_CMD_PARAM1: { - QP::QS::rxPriv_.var.cmd.param1 |= - (static_cast(b) << QP::QS::rxPriv_.var.cmd.idx); - QP::QS::rxPriv_.var.cmd.idx += 8U; - if (QP::QS::rxPriv_.var.cmd.idx == (8U * 4U)) { - QP::QS::rxPriv_.var.cmd.idx = 0U; - tran_(WAIT4_CMD_PARAM2); - } - break; - } - case WAIT4_CMD_PARAM2: { - QP::QS::rxPriv_.var.cmd.param2 |= - static_cast(b) << QP::QS::rxPriv_.var.cmd.idx; - QP::QS::rxPriv_.var.cmd.idx += 8U; - if (QP::QS::rxPriv_.var.cmd.idx == (8U * 4U)) { - QP::QS::rxPriv_.var.cmd.idx = 0U; - tran_(WAIT4_CMD_PARAM3); - } - break; - } - case WAIT4_CMD_PARAM3: { - QP::QS::rxPriv_.var.cmd.param3 |= - static_cast(b) << QP::QS::rxPriv_.var.cmd.idx; - QP::QS::rxPriv_.var.cmd.idx += 8U; - if (QP::QS::rxPriv_.var.cmd.idx == (8U * 4U)) { - QP::QS::rxPriv_.var.cmd.idx = 0U; - tran_(WAIT4_CMD_FRAME); - } - break; - } - case WAIT4_CMD_FRAME: { - // keep ignoring the data until a frame is collected - break; - } - case WAIT4_RESET_FRAME: { - // keep ignoring the data until a frame is collected - break; - } - case WAIT4_TICK_RATE: { - QP::QS::rxPriv_.var.tick.rate = static_cast(b); - tran_(WAIT4_TICK_FRAME); - break; - } - case WAIT4_TICK_FRAME: { - // keep ignoring the data until a frame is collected - break; - } - case WAIT4_PEEK_OFFS: { - if (QP::QS::rxPriv_.var.peek.idx == 0U) { - QP::QS::rxPriv_.var.peek.offs = static_cast(b); - QP::QS::rxPriv_.var.peek.idx += 8U; - } - else { - QP::QS::rxPriv_.var.peek.offs |= static_cast( - static_cast(b) << 8U); - tran_(WAIT4_PEEK_SIZE); - } - break; - } - case WAIT4_PEEK_SIZE: { - if ((b == 1U) || (b == 2U) || (b == 4U)) { - QP::QS::rxPriv_.var.peek.size = b; - tran_(WAIT4_PEEK_NUM); - } - else { - rxReportError_(static_cast(QP::QS_RX_PEEK)); - tran_(ERROR_STATE); - } - break; - } - case WAIT4_PEEK_NUM: { - QP::QS::rxPriv_.var.peek.num = b; - tran_(WAIT4_PEEK_FRAME); - break; - } - case WAIT4_PEEK_FRAME: { - // keep ignoring the data until a frame is collected - break; - } - case WAIT4_POKE_OFFS: { - if (QP::QS::rxPriv_.var.poke.idx == 0U) { - QP::QS::rxPriv_.var.poke.offs = static_cast(b); - QP::QS::rxPriv_.var.poke.idx = 1U; - } - else { - QP::QS::rxPriv_.var.poke.offs |= static_cast( - static_cast(b) << 8U); - tran_(WAIT4_POKE_SIZE); - } - break; - } - case WAIT4_POKE_SIZE: { - if ((b == 1U) || (b == 2U) || (b == 4U)) { - QP::QS::rxPriv_.var.poke.size = b; - tran_(WAIT4_POKE_NUM); - } - else { - rxReportError_((QP::QS::rxPriv_.var.poke.fill != 0U) - ? static_cast(QP::QS_RX_FILL) - : static_cast(QP::QS_RX_POKE)); - tran_(ERROR_STATE); - } - break; - } - case WAIT4_POKE_NUM: { - if (b > 0U) { - QP::QS::rxPriv_.var.poke.num = b; - QP::QS::rxPriv_.var.poke.data = 0U; - QP::QS::rxPriv_.var.poke.idx = 0U; - tran_((QP::QS::rxPriv_.var.poke.fill != 0U) - ? WAIT4_FILL_DATA - : WAIT4_POKE_DATA); - } - else { - rxReportError_((QP::QS::rxPriv_.var.poke.fill != 0U) - ? static_cast(QP::QS_RX_FILL) - : static_cast(QP::QS_RX_POKE)); - tran_(ERROR_STATE); - } - break; - } - case WAIT4_FILL_DATA: { - QP::QS::rxPriv_.var.poke.data |= - static_cast(b) << QP::QS::rxPriv_.var.poke.idx; - QP::QS::rxPriv_.var.poke.idx += 8U; - if ((QP::QS::rxPriv_.var.poke.idx >> 3U) == QP::QS::rxPriv_.var.poke.size) { - tran_(WAIT4_FILL_FRAME); - } - break; - } - case WAIT4_POKE_DATA: { - QP::QS::rxPriv_.var.poke.data |= - static_cast(b) << QP::QS::rxPriv_.var.poke.idx; - QP::QS::rxPriv_.var.poke.idx += 8U; - if ((QP::QS::rxPriv_.var.poke.idx >> 3U) == QP::QS::rxPriv_.var.poke.size) { - rxPoke_(); - --QP::QS::rxPriv_.var.poke.num; - if (QP::QS::rxPriv_.var.poke.num == 0U) { - tran_(WAIT4_POKE_FRAME); - } - } - break; - } - case WAIT4_FILL_FRAME: { - // keep ignoring the data until a frame is collected - break; - } - case WAIT4_POKE_FRAME: { - // keep ignoring the data until a frame is collected - break; - } - case WAIT4_FILTER_LEN: { - if (b == static_cast(sizeof(QP::QS::rxPriv_.var.flt.data))) { - QP::QS::rxPriv_.var.flt.idx = 0U; - tran_(WAIT4_FILTER_DATA); - } - else { - rxReportError_(QP::QS::rxPriv_.var.flt.recId); - tran_(ERROR_STATE); - } - break; - } - case WAIT4_FILTER_DATA: { - QP::QS::rxPriv_.var.flt.data[QP::QS::rxPriv_.var.flt.idx] = b; - ++QP::QS::rxPriv_.var.flt.idx; - if (QP::QS::rxPriv_.var.flt.idx == sizeof(QP::QS::rxPriv_.var.flt.data)) { - tran_(WAIT4_FILTER_FRAME); - } - break; - } - case WAIT4_FILTER_FRAME: { - // keep ignoring the data until a frame is collected - break; - } - case WAIT4_OBJ_KIND: { - if (b <= static_cast(QP::QS::SM_AO_OBJ)) { - QP::QS::rxPriv_.var.obj.kind = b; - QP::QS::rxPriv_.var.obj.addr = 0U; - QP::QS::rxPriv_.var.obj.idx = 0U; - tran_(WAIT4_OBJ_ADDR); - } - else { - rxReportError_(QP::QS::rxPriv_.var.obj.recId); - tran_(ERROR_STATE); - } - break; - } - case WAIT4_OBJ_ADDR: { - QP::QS::rxPriv_.var.obj.addr |= - static_cast(b) << QP::QS::rxPriv_.var.obj.idx; - QP::QS::rxPriv_.var.obj.idx += 8U; - if (QP::QS::rxPriv_.var.obj.idx - == (8U * static_cast(QS_OBJ_PTR_SIZE))) - { - tran_(WAIT4_OBJ_FRAME); - } - break; - } - case WAIT4_OBJ_FRAME: { - // keep ignoring the data until a frame is collected - break; - } - case WAIT4_QUERY_KIND: { - if (b < static_cast(QP::QS::MAX_OBJ)) { - QP::QS::rxPriv_.var.obj.kind = b; - tran_(WAIT4_QUERY_FRAME); - } - else { - rxReportError_(QP::QS::rxPriv_.var.obj.recId); - tran_(ERROR_STATE); - } - break; - } - case WAIT4_QUERY_FRAME: { - // keep ignoring the data until a frame is collected - break; - } - case WAIT4_EVT_PRIO: { - QP::QS::rxPriv_.var.evt.prio = b; - QP::QS::rxPriv_.var.evt.sig = 0U; - QP::QS::rxPriv_.var.evt.idx = 0U; - tran_(WAIT4_EVT_SIG); - break; - } - case WAIT4_EVT_SIG: { - QP::QS::rxPriv_.var.evt.sig |= static_cast( - static_cast(b) << QP::QS::rxPriv_.var.evt.idx); - QP::QS::rxPriv_.var.evt.idx += 8U; - if (QP::QS::rxPriv_.var.evt.idx - == (8U *static_cast(Q_SIGNAL_SIZE))) - { - QP::QS::rxPriv_.var.evt.len = 0U; - QP::QS::rxPriv_.var.evt.idx = 0U; - tran_(WAIT4_EVT_LEN); - } - break; - } - case WAIT4_EVT_LEN: { - QP::QS::rxPriv_.var.evt.len |= static_cast( - static_cast(b) << QP::QS::rxPriv_.var.evt.idx); - QP::QS::rxPriv_.var.evt.idx += 8U; - if (QP::QS::rxPriv_.var.evt.idx == (8U * 2U)) { - if ((QP::QS::rxPriv_.var.evt.len + sizeof(QP::QEvt)) - <= QP::QF::poolGetMaxBlockSize()) - { - // report Ack before generating any other QS records - rxReportAck_(QP::QS_RX_EVENT); - - QP::QS::rxPriv_.var.evt.e = QP::QF::newX_( - (static_cast(QP::QS::rxPriv_.var.evt.len) - + sizeof(QP::QEvt)), - 0U, // margin - static_cast(QP::QS::rxPriv_.var.evt.sig)); - // event allocated? - if (QP::QS::rxPriv_.var.evt.e != nullptr) { - QP::QS::rxPriv_.var.evt.p = - reinterpret_cast(QP::QS::rxPriv_.var.evt.e); - QP::QS::rxPriv_.var.evt.p = &QP::QS::rxPriv_.var.evt.p[sizeof(QP::QEvt)]; - if (QP::QS::rxPriv_.var.evt.len > 0U) { - tran_(WAIT4_EVT_PAR); - } - else { - tran_(WAIT4_EVT_FRAME); - } - } - else { - rxReportError_( - static_cast(QP::QS_RX_EVENT)); - tran_(ERROR_STATE); - } - } - else { - rxReportError_( - static_cast(QP::QS_RX_EVENT)); - tran_(ERROR_STATE); - } - } - break; - } - case WAIT4_EVT_PAR: { // event parameters - *QP::QS::rxPriv_.var.evt.p = b; - ++QP::QS::rxPriv_.var.evt.p; - --QP::QS::rxPriv_.var.evt.len; - if (QP::QS::rxPriv_.var.evt.len == 0U) { - tran_(WAIT4_EVT_FRAME); - } - break; - } - case WAIT4_EVT_FRAME: { - // keep ignoring the data until a frame is collected - break; - } - -#ifdef Q_UTEST - case WAIT4_TEST_SETUP_FRAME: { - // keep ignoring the data until a frame is collected - break; - } - case WAIT4_TEST_TEARDOWN_FRAME: { - // keep ignoring the data until a frame is collected - break; - } - case WAIT4_TEST_CONTINUE_FRAME: { - // keep ignoring the data until a frame is collected - break; - } - case WAIT4_TEST_PROBE_DATA: { - QP::QS::rxPriv_.var.tp.data |= - (static_cast(b) << QP::QS::rxPriv_.var.tp.idx); - QP::QS::rxPriv_.var.tp.idx += 8U; - if (QP::QS::rxPriv_.var.tp.idx == (8U * sizeof(std::uint32_t))) { - QP::QS::rxPriv_.var.tp.addr = 0U; - QP::QS::rxPriv_.var.tp.idx = 0U; - tran_(WAIT4_TEST_PROBE_ADDR); - } - break; - } - case WAIT4_TEST_PROBE_ADDR: { - QP::QS::rxPriv_.var.tp.addr |= - (static_cast(b) << QP::QS::rxPriv_.var.tp.idx); - QP::QS::rxPriv_.var.tp.idx += 8U; - if (QP::QS::rxPriv_.var.tp.idx - == (8U * static_cast(QS_FUN_PTR_SIZE))) - { - tran_(WAIT4_TEST_PROBE_FRAME); - } - break; - } - case WAIT4_TEST_PROBE_FRAME: { - // keep ignoring the data until a frame is collected - break; - } -#endif // Q_UTEST - - case ERROR_STATE: { - // keep ignoring the data until a good frame is collected - break; - } - default: { // unexpected or unimplemented state - rxReportError_(0x45U); - tran_(ERROR_STATE); - break; - } - } -} - -//............................................................................ -void rxHandleGoodFrame_(std::uint8_t const state) { - std::uint8_t i; - std::uint8_t *ptr; - QS_CRIT_STAT - - switch (state) { - case WAIT4_INFO_FRAME: { - // no need to report Ack or Done - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QP::QS::target_info_pre_(0U); // send only Target info - QS_MEM_APP(); - QS_CRIT_EXIT(); - break; - } - case WAIT4_RESET_FRAME: { - // no need to report Ack or Done, because Target resets - QP::QS::onReset(); // reset the Target - break; - } - case WAIT4_CMD_PARAM1: // intentionally fall-through - case WAIT4_CMD_PARAM2: // intentionally fall-through - case WAIT4_CMD_PARAM3: // intentionally fall-through - case WAIT4_CMD_FRAME: { - rxReportAck_(QP::QS_RX_COMMAND); - QP::QS::onCommand(QP::QS::rxPriv_.var.cmd.cmdId, QP::QS::rxPriv_.var.cmd.param1, - QP::QS::rxPriv_.var.cmd.param2, QP::QS::rxPriv_.var.cmd.param3); -#ifdef Q_UTEST - #if Q_UTEST != 0 - QP::QS::processTestEvts_(); // process all events produced - #endif // Q_UTEST != 0 -#endif // Q_UTEST - rxReportDone_(QP::QS_RX_COMMAND); - break; - } - case WAIT4_TICK_FRAME: { - rxReportAck_(QP::QS_RX_TICK); -#ifdef Q_UTEST - QP::QTimeEvt::tick1_( - static_cast(QP::QS::rxPriv_.var.tick.rate), - &QP::QS::rxPriv_); - #if Q_UTEST != 0 - QP::QS::processTestEvts_(); // process all events produced - #endif // Q_UTEST != 0 -#else - QP::QTimeEvt::tick( - static_cast(QP::QS::rxPriv_.var.tick.rate), - &QP::QS::rxPriv_); -#endif // Q_UTEST - rxReportDone_(QP::QS_RX_TICK); - break; - } - case WAIT4_PEEK_FRAME: { - // no need to report Ack or Done - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QP::QS::beginRec_(static_cast( - QP::QS_PEEK_DATA)); - ptr = static_cast( - QP::QS::rxPriv_.currObj[QP::QS::AP_OBJ]); - ptr = &ptr[QP::QS::rxPriv_.var.peek.offs]; - QS_TIME_PRE_(); // timestamp - QS_U16_PRE_(QP::QS::rxPriv_.var.peek.offs); // data offset - QS_U8_PRE_(QP::QS::rxPriv_.var.peek.size); // data size - QS_U8_PRE_(QP::QS::rxPriv_.var.peek.num); // number of data items - for (i = 0U; i < QP::QS::rxPriv_.var.peek.num; ++i) { - switch (QP::QS::rxPriv_.var.peek.size) { - case 1: - QS_U8_PRE_(ptr[i]); - break; - case 2: - QS_U16_PRE_( - reinterpret_cast(ptr)[i]); - break; - case 4: - QS_U32_PRE_( - reinterpret_cast(ptr)[i]); - break; - default: - // intentionally empty - break; - } - } - QP::QS::endRec_(); - QS_MEM_APP(); - QS_CRIT_EXIT(); - - QS_REC_DONE(); // user callback (if defined) - break; - } - case WAIT4_POKE_DATA: { - // received less than expected poke data items - rxReportError_(static_cast(QP::QS_RX_POKE)); - break; - } - case WAIT4_POKE_FRAME: { - rxReportAck_(QP::QS_RX_POKE); - // no need to report done - break; - } - case WAIT4_FILL_FRAME: { - rxReportAck_(QP::QS_RX_FILL); - ptr = static_cast( - QP::QS::rxPriv_.currObj[QP::QS::AP_OBJ]); - ptr = &ptr[QP::QS::rxPriv_.var.poke.offs]; - for (i = 0U; i < QP::QS::rxPriv_.var.poke.num; ++i) { - switch (QP::QS::rxPriv_.var.poke.size) { - case 1: - ptr[i] = - static_cast(QP::QS::rxPriv_.var.poke.data); - break; - case 2: - reinterpret_cast(ptr)[i] = - static_cast(QP::QS::rxPriv_.var.poke.data); - break; - case 4: - reinterpret_cast(ptr)[i] = - QP::QS::rxPriv_.var.poke.data; - break; - default: - // intentionally empty - break; - } - } - break; - } - case WAIT4_FILTER_FRAME: { - rxReportAck_(static_cast( - QP::QS::rxPriv_.var.flt.recId)); - - // apply the received filters - if (QP::QS::rxPriv_.var.flt.recId - == static_cast(QP::QS_RX_GLB_FILTER)) - { - for (i = 0U; - i < static_cast(sizeof(QP::QS::filt_.glb)); - ++i) - { - QP::QS::filt_.glb[i] = QP::QS::rxPriv_.var.flt.data[i]; - } - // leave the "not maskable" filters enabled, - // see qs.hpp, Miscellaneous QS records (not maskable) - QP::QS::filt_.glb[0] |= 0x01U; - QP::QS::filt_.glb[7] |= 0xFCU; - QP::QS::filt_.glb[8] |= 0x7FU; - - // never enable the last 3 records (0x7D, 0x7E, 0x7F) - QP::QS::filt_.glb[15] &= 0x1FU; - } - else if (QP::QS::rxPriv_.var.flt.recId - == static_cast(QP::QS_RX_LOC_FILTER)) - { - for (i = 0U; i < Q_DIM(QP::QS::filt_.loc); ++i) { - QP::QS::filt_.loc[i] = QP::QS::rxPriv_.var.flt.data[i]; - } - // leave QS_ID == 0 always on - QP::QS::filt_.loc[0] |= 0x01U; - } - else { - rxReportError_(QP::QS::rxPriv_.var.flt.recId); - } - // no need to report Done - break; - } - case WAIT4_OBJ_FRAME: { - i = QP::QS::rxPriv_.var.obj.kind; - if (i < static_cast(QP::QS::MAX_OBJ)) { - if (QP::QS::rxPriv_.var.obj.recId - == static_cast(QP::QS_RX_CURR_OBJ)) - { - QP::QS::rxPriv_.currObj[i] = - reinterpret_cast(QP::QS::rxPriv_.var.obj.addr); - rxReportAck_(QP::QS_RX_CURR_OBJ); - } - else if (QP::QS::rxPriv_.var.obj.recId - == static_cast(QP::QS_RX_AO_FILTER)) - { - if (QP::QS::rxPriv_.var.obj.addr != 0U) { - std::int_fast16_t const filter = - static_cast( - reinterpret_cast( - QP::QS::rxPriv_.var.obj.addr)->getPrio()); - QP::QS::locFilter_((i == 0) - ? filter - :-filter); - rxReportAck_(QP::QS_RX_AO_FILTER); - } - else { - rxReportError_(static_cast( - QP::QS_RX_AO_FILTER)); - } - } - else { - rxReportError_(QP::QS::rxPriv_.var.obj.recId); - } - } - // both SM and AO - else if (i == static_cast(QP::QS::SM_AO_OBJ)) { - if (QP::QS::rxPriv_.var.obj.recId - == static_cast(QP::QS_RX_CURR_OBJ)) - { - QP::QS::rxPriv_.currObj[QP::QS::SM_OBJ] - = reinterpret_cast(QP::QS::rxPriv_.var.obj.addr); - QP::QS::rxPriv_.currObj[QP::QS::AO_OBJ] - = reinterpret_cast(QP::QS::rxPriv_.var.obj.addr); - } - rxReportAck_( - static_cast(QP::QS::rxPriv_.var.obj.recId)); - } - else { - rxReportError_(QP::QS::rxPriv_.var.obj.recId); - } - break; - } - case WAIT4_QUERY_FRAME: { - queryCurrObj_(QP::QS::rxPriv_.var.obj.kind); - break; - } - case WAIT4_EVT_FRAME: { - // NOTE: Ack was already reported in the WAIT4_EVT_LEN state -#ifdef Q_UTEST - QP::QS::onTestEvt(QP::QS::rxPriv_.var.evt.e); // "massage" the event -#endif // Q_UTEST - // use 'i' as status, 0 == success,no-recycle - i = 0U; - - if (QP::QS::rxPriv_.var.evt.prio == 0U) { // publish - QP::QActive::publish_(QP::QS::rxPriv_.var.evt.e, &QP::QS::rxPriv_, 0U); - } - else if (QP::QS::rxPriv_.var.evt.prio < QF_MAX_ACTIVE) { - if (!QP::QActive::registry_[QP::QS::rxPriv_.var.evt.prio]->POST_X( - QP::QS::rxPriv_.var.evt.e, - 0U, // margin - &QP::QS::rxPriv_)) - { - // failed QACTIVE_POST() recycles the event - i = 0x80U; // failure status, no recycle - } - } - else if (QP::QS::rxPriv_.var.evt.prio == 255U) { - // dispatch to the current SM object - if (QP::QS::rxPriv_.currObj[QP::QS::SM_OBJ] != nullptr) { - // increment the ref-ctr to simulate the situation - // when the event is just retrieved from a queue. - // This is expected for the following QF::gc() call. - QP::QEvt_refCtr_inc_(QP::QS::rxPriv_.var.evt.e); - - static_cast( - QP::QS::rxPriv_.currObj[QP::QS::SM_OBJ]) - ->dispatch(QP::QS::rxPriv_.var.evt.e, 0U); - i = 0x01U; // success, recycle - } - else { - i = 0x81U; // failure, recycle - } - } - else if (QP::QS::rxPriv_.var.evt.prio == 254U) { - // init the current SM object" - if (QP::QS::rxPriv_.currObj[QP::QS::SM_OBJ] != nullptr) { - // increment the ref-ctr to simulate the situation - // when the event is just retrieved from a queue. - // This is expected for the following QF::gc() call. - QP::QEvt_refCtr_inc_(QP::QS::rxPriv_.var.evt.e); - - static_cast( - QP::QS::rxPriv_.currObj[QP::QS::SM_OBJ]) - ->init(QP::QS::rxPriv_.var.evt.e, 0U); - i = 0x01U; // success, recycle - } - else { - i = 0x81U; // failure, recycle - } - } - else if (QP::QS::rxPriv_.var.evt.prio == 253U) { - // post to the current AO - if (QP::QS::rxPriv_.currObj[QP::QS::AO_OBJ] != nullptr) { - if (!static_cast( - QP::QS::rxPriv_.currObj[QP::QS::AO_OBJ])->POST_X( - QP::QS::rxPriv_.var.evt.e, - 0U, // margin - &QP::QS::rxPriv_)) - { - // failed QACTIVE_POST() recycles the event - i = 0x80U; // failure, no recycle - } - } - else { - i = 0x81U; // failure, recycle - } - } - else { - i = 0x81U; // failure, recycle - } - -#if (QF_MAX_EPOOL > 0U) - // recycle needed? - if ((i & 1U) != 0U) { - QP::QF::gc(QP::QS::rxPriv_.var.evt.e); - } -#endif - // failure? - if ((i & 0x80U) != 0U) { - rxReportError_(static_cast(QP::QS_RX_EVENT)); - } - else { -#ifdef Q_UTEST - #if Q_UTEST != 0 - QP::QS::processTestEvts_(); // process all events produced - #endif // Q_UTEST != 0 -#endif // Q_UTEST - rxReportDone_(QP::QS_RX_EVENT); - } - break; - } - -#ifdef Q_UTEST - case WAIT4_TEST_SETUP_FRAME: { - rxReportAck_(QP::QS_RX_TEST_SETUP); - QP::QS::tstPriv_.tpNum = 0U; // clear Test-Probes - QP::QS::tstPriv_.testTime = 0U; //clear time tick - // don't clear current objects - QP::QS::onTestSetup(); // application-specific test setup - // no need to report Done - break; - } - case WAIT4_TEST_TEARDOWN_FRAME: { - rxReportAck_(QP::QS_RX_TEST_TEARDOWN); - QP::QS::onTestTeardown(); // application-specific test teardown - // no need to report Done - break; - } - case WAIT4_TEST_CONTINUE_FRAME: { - rxReportAck_(QP::QS_RX_TEST_CONTINUE); - QP::QS::rxPriv_.inTestLoop = false; // exit the QUTest loop - // no need to report Done - break; - } - case WAIT4_TEST_PROBE_FRAME: { - rxReportAck_(QP::QS_RX_TEST_PROBE); - Q_ASSERT_INCRIT(815, - QP::QS::tstPriv_.tpNum - < (sizeof(QP::QS::tstPriv_.tpBuf) - / sizeof(QP::QS::tstPriv_.tpBuf[0]))); - QP::QS::tstPriv_.tpBuf[QP::QS::tstPriv_.tpNum] = QP::QS::rxPriv_.var.tp; - ++QP::QS::tstPriv_.tpNum; - // no need to report Done - break; - } -#endif // Q_UTEST - - case ERROR_STATE: { - // keep ignoring all bytes until new frame - break; - } - default: { - rxReportError_(0x47U); - break; - } - } -} - -//............................................................................ -static void rxHandleBadFrame_(std::uint8_t const state) noexcept { - rxReportError_(0x50U); // error for all bad frames - switch (state) { - case WAIT4_EVT_FRAME: { - QS_CRIT_STAT - QS_CRIT_ENTRY(); - Q_ASSERT_INCRIT(910, QP::QS::rxPriv_.var.evt.e != nullptr); - QS_CRIT_EXIT(); -#if (QF_MAX_EPOOL > 0U) - QP::QF::gc(QP::QS::rxPriv_.var.evt.e); // don't leak allocated evt -#endif - break; - } - default: { - // intentionally empty - break; - } - } -} - -//............................................................................ -static void rxReportAck_(enum QP::QSpyRxRecords const recId) noexcept { - QS_CRIT_STAT - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QP::QS::beginRec_(static_cast(QP::QS_RX_STATUS)); - QS_U8_PRE_(recId); // record ID - QP::QS::endRec_(); - QS_MEM_APP(); - QS_CRIT_EXIT(); - QS_REC_DONE(); // user callback (if defined) -} - -//............................................................................ -static void rxReportError_(std::uint8_t const code) noexcept { - QS_CRIT_STAT - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QP::QS::beginRec_(static_cast(QP::QS_RX_STATUS)); - QS_U8_PRE_(0x80U | code); // error code - QP::QS::endRec_(); - QS_MEM_APP(); - QS_CRIT_EXIT(); - QS_REC_DONE(); // user callback (if defined) -} - -//............................................................................ -static void rxReportDone_(enum QP::QSpyRxRecords const recId) noexcept { - QS_CRIT_STAT - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QP::QS::beginRec_(static_cast(QP::QS_TARGET_DONE)); - QS_TIME_PRE_(); // timestamp - QS_U8_PRE_(recId); // record ID - QP::QS::endRec_(); - QS_MEM_APP(); - QS_CRIT_EXIT(); - QS_REC_DONE(); // user callback (if defined) -} - -//............................................................................ -static void queryCurrObj_(std::uint8_t obj_kind) noexcept { - QS_CRIT_STAT - QS_CRIT_ENTRY(); - Q_REQUIRE_INCRIT(800, obj_kind < Q_DIM(QP::QS::rxPriv_.currObj)); - QS_CRIT_EXIT(); - - if (QP::QS::rxPriv_.currObj[obj_kind] != nullptr) { - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QP::QS::beginRec_(static_cast(QP::QS_QUERY_DATA)); - QS_TIME_PRE_(); // timestamp - QS_U8_PRE_(obj_kind); // object kind - QS_OBJ_PRE_(QP::QS::rxPriv_.currObj[obj_kind]); // object pointer - switch (obj_kind) { - case QP::QS::SM_OBJ: // intentionally fall through - case QP::QS::AO_OBJ: - QS_FUN_PRE_(reinterpret_cast( - QP::QS::rxPriv_.currObj[obj_kind])->getStateHandler()); - break; - case QP::QS::MP_OBJ: - QS_MPC_PRE_(reinterpret_cast( - QP::QS::rxPriv_.currObj[obj_kind])->getNFree()); - QS_MPC_PRE_(reinterpret_cast( - QP::QS::rxPriv_.currObj[obj_kind])->getNMin()); - break; - case QP::QS::EQ_OBJ: - QS_EQC_PRE_(reinterpret_cast( - QP::QS::rxPriv_.currObj[obj_kind])->getNFree()); - QS_EQC_PRE_(reinterpret_cast( - QP::QS::rxPriv_.currObj[obj_kind])->getNMin()); - break; - case QP::QS::TE_OBJ: - QS_OBJ_PRE_(reinterpret_cast( - QP::QS::rxPriv_.currObj[obj_kind])->getAct()); - QS_TEC_PRE_(reinterpret_cast( - QP::QS::rxPriv_.currObj[obj_kind])->getCtr()); - QS_TEC_PRE_(reinterpret_cast( - QP::QS::rxPriv_.currObj[obj_kind])->getInterval()); - QS_SIG_PRE_(reinterpret_cast( - QP::QS::rxPriv_.currObj[obj_kind])->sig); - QS_U8_PRE_ (reinterpret_cast( - QP::QS::rxPriv_.currObj[obj_kind])->refCtr_); - break; - default: - // intentionally empty - break; - } - QP::QS::endRec_(); - QS_MEM_APP(); - QS_CRIT_EXIT(); - QS_REC_DONE(); // user callback (if defined) - } - else { - rxReportError_(static_cast(QP::QS_RX_AO_FILTER)); - } -} - -//............................................................................ -static void rxPoke_() noexcept { - std::uint8_t * ptr = - static_cast(QP::QS::rxPriv_.currObj[QP::QS::AP_OBJ]); - ptr = &ptr[QP::QS::rxPriv_.var.poke.offs]; - switch (QP::QS::rxPriv_.var.poke.size) { - case 1: - *ptr = static_cast(QP::QS::rxPriv_.var.poke.data); - break; - case 2: - *reinterpret_cast(ptr) - = static_cast(QP::QS::rxPriv_.var.poke.data); - break; - case 4: - *reinterpret_cast(ptr) = QP::QS::rxPriv_.var.poke.data; - break; - default: - Q_ERROR_ID(900); - break; - } - - QP::QS::rxPriv_.var.poke.data = 0U; - QP::QS::rxPriv_.var.poke.idx = 0U; - QP::QS::rxPriv_.var.poke.offs += static_cast(QP::QS::rxPriv_.var.poke.size); -} - -} // unnamed namespace - -//! @endcond diff --git a/src/qs/qstamp.cpp b/src/qs/qstamp.cpp index 6e6d73ded..dea2155b8 100644 --- a/src/qs/qstamp.cpp +++ b/src/qs/qstamp.cpp @@ -3,17 +3,10 @@ // Model: qpcpp.qm // File: ${src::qs::qstamp.cpp} // -// This code has been generated by QM 6.2.0 . +// This code has been generated by QM 7.0.0 . // DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. // -// This code is covered by the following QP license: -// License # : LicenseRef-QL-dual -// Issued to : Any user of the QP/C++ real-time embedded framework -// Framework(s) : qpcpp -// Support ends : 2025-12-31 -// License scope: -// -// Copyright (C) 2005 Quantum Leaps, LLC . +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // Q u a n t u m L e a P s // ------------------------ @@ -21,21 +14,20 @@ // // 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: +// 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. // -// Contact information: +// NOTE: +// The GPL does NOT permit the incorporation of this code into proprietary +// programs. Please contact Quantum Leaps for commercial licensing options, +// which expressly supersede the GPL and are designed explicitly for +// closed-source distribution. +// +// Quantum Leaps contact information: // // // diff --git a/src/qs/qutest.cpp b/src/qs/qutest.cpp deleted file mode 100644 index c934c6078..000000000 --- a/src/qs/qutest.cpp +++ /dev/null @@ -1,590 +0,0 @@ -//$file${src::qs::qutest.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// -// Model: qpcpp.qm -// File: ${src::qs::qutest.cpp} -// -// This code has been generated by QM 6.2.0 . -// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. -// -// This code is covered by the following QP license: -// License # : LicenseRef-QL-dual -// Issued to : Any user of the QP/C++ real-time embedded framework -// Framework(s) : qpcpp -// Support ends : 2025-12-31 -// License scope: -// -// Copyright (C) 2005 Quantum Leaps, LLC . -// -// 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 -// -// 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: -// -// -// -//$endhead${src::qs::qutest.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -// only build when Q_UTEST is defined -#ifdef Q_UTEST - -#define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#include "qs_port.hpp" // QS port -#include "qs_pkg.hpp" // QS package-scope internal interface - -//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// Check for the minimum required QP version -#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U)) -#error qpcpp version 7.3.0 or higher required -#endif -//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//$define${QS::QUTest} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { -namespace QS { - -} // namespace QS -} // namespace QP -//$enddef${QS::QUTest} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -//============================================================================ -//! @cond INTERNAL - -namespace QP { -namespace QS { - -TestAttr tstPriv_; - -//............................................................................ -void test_pause_() { - beginRec_(static_cast(QS_TEST_PAUSED)); - endRec_(); - onTestLoop(); -} - -//............................................................................ -std::uint32_t getTestProbe_(QSpyFunPtr const api) noexcept { - std::uint32_t data = 0U; - for (std::uint8_t i = 0U; i < tstPriv_.tpNum; ++i) { - if (tstPriv_.tpBuf[i].addr == reinterpret_cast(api)) { - data = tstPriv_.tpBuf[i].data; - - QS_CRIT_STAT - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QS::beginRec_(static_cast(QS_TEST_PROBE_GET)); - QS_TIME_PRE_(); // timestamp - QS_FUN_PRE_(api); // the calling API - QS_U32_PRE_(data); // the Test-Probe data - QS::endRec_(); - - QS_REC_DONE(); // user callback (if defined) - - --tstPriv_.tpNum; // one less Test-Probe - // move all remaining entries in the buffer up by one - for (std::uint8_t j = i; j < tstPriv_.tpNum; ++j) { - tstPriv_.tpBuf[j] = tstPriv_.tpBuf[j + 1U]; - } - QS_MEM_APP(); - QS_CRIT_EXIT(); - break; // we are done (Test-Probe retrieved) - } - } - return data; -} - -//............................................................................ -QSTimeCtr onGetTime() { - return (++tstPriv_.testTime); -} - -} // namespace QS -} // namespace QP - -//............................................................................ -extern "C" { - -Q_NORETURN Q_onError( - char const * const module, - int_t const id) -{ - // NOTE: called in a critical section - - QP::QS::beginRec_(static_cast(QP::QS_ASSERT_FAIL)); - QS_TIME_PRE_(); - QS_U16_PRE_(id); - QS_STR_PRE_((module != nullptr) ? module : "?"); - QP::QS::endRec_(); - QP::QS::onFlush(); // flush the assertion record to the host - - QP::QS::onCleanup(); // cleanup after the failure - QP::QS::onReset(); // reset the target to prevent it from continuing - for (;;) { // onReset() should not return, but to ensure no-return... - } -} - -} // extern "C" - -//! @endcond -//============================================================================ - -// QP-stub for QUTest -// NOTE: The QP-stub is needed for unit testing QP applications, but might -// NOT be needed for testing QP itself. In that case, the build process -// can define Q_UTEST=0 to exclude the QP-stub from the build. -#if Q_UTEST != 0 - -// unnamed namespace for local definitions with internal linkage -namespace { -Q_DEFINE_THIS_MODULE("qutest") -} // unnamed namespace - -namespace QP { -namespace QS { - -void processTestEvts_() { - QS_TEST_PROBE_DEF(&QS::processTestEvts_) - - // return immediately (do nothing) for Test Probe != 0 - QS_TEST_PROBE(return;) - - while (tstPriv_.readySet.notEmpty()) { - std::uint_fast8_t const p = tstPriv_.readySet.findMax(); - QActive * const a = QActive::registry_[p]; - - QEvt const * const e = a->get_(); - a->dispatch(e, a->getPrio()); - #if (QF_MAX_EPOOL > 0U) - QF::gc(e); - #endif - if (a->getEQueue().isEmpty()) { // empty queue? - tstPriv_.readySet.remove(p); -#ifndef Q_UNSAFE - tstPriv_.readySet.update_(&tstPriv_.readySet_dis); -#endif - } - } -} - -} // namespace QS -} // namespace QP - -//$define${QS::QUTest-stub} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { -namespace QF { - -//${QS::QUTest-stub::QF::init} ............................................... -void init() { - // Clear the internal QF variables, so that the framework can start - // correctly even if the startup code fails to clear the uninitialized - // data (as is required by the C++ Standard). - bzero_(&QF::priv_, sizeof(QF::priv_)); - bzero_(&QS::tstPriv_, sizeof(QS::tstPriv_)); - bzero_(&QActive::registry_[0], sizeof(QActive::registry_)); - - #ifndef Q_UNSAFE - QS::tstPriv_.readySet.update_(&QS::tstPriv_.readySet_dis); - #endif -} - -//${QS::QUTest-stub::QF::stop} ............................................... -void stop() { - QS::onReset(); -} - -//${QS::QUTest-stub::QF::run} ................................................ -int_t run() { - // function dictionaries for the standard API - QS_FUN_DICTIONARY(&QActive::post_); - QS_FUN_DICTIONARY(&QActive::postLIFO); - QS_FUN_DICTIONARY(&QS::processTestEvts_); - - QS_CRIT_STAT - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - - // produce the QS_QF_RUN trace record - QS_BEGIN_PRE_(QS_QF_RUN, 0U) - QS_END_PRE_() - - QS_MEM_APP(); - QS_CRIT_EXIT(); - - QS::processTestEvts_(); // process all events posted so far - QS::onTestLoop(); // run the unit test - QS::onCleanup(); // application cleanup - return 0; // return no error -} - -} // namespace QF - -//${QS::QUTest-stub::QActive} ................................................ - -//${QS::QUTest-stub::QActive::start} ......................................... -void QActive::start( - QPrioSpec const prioSpec, - QEvt const * * const qSto, - std::uint_fast16_t const qLen, - void * const stkSto, - std::uint_fast16_t const stkSize, - void const * const par) -{ - Q_UNUSED_PAR(stkSto); - Q_UNUSED_PAR(stkSize); - - m_prio = static_cast(prioSpec & 0xFFU); // QF-priol - m_pthre = static_cast(prioSpec >> 8U); // preemption-thre. - register_(); // make QF aware of this AO - - m_eQueue.init(qSto, qLen); // initialize QEQueue of this AO - - this->init(par, m_prio); // take the top-most initial tran. (virtual) -} - -//${QS::QUTest-stub::QActive::stop} .......................................... -#ifdef QACTIVE_CAN_STOP -void QActive::stop() { - unsubscribeAll(); // unsubscribe from all events - unregister_(); // remove this object from QF -} - -#endif // def QACTIVE_CAN_STOP - -//${QS::QUTest-stub::QTimeEvt} ............................................... - -//${QS::QUTest-stub::QTimeEvt::tick1_} ....................................... -void QTimeEvt::tick1_( - std::uint_fast8_t const tickRate, - void const * const sender) -{ - QS_CRIT_STAT - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - - QTimeEvt *prev = &QTimeEvt::timeEvtHead_[tickRate]; - - QS_BEGIN_PRE_(QS_QF_TICK, 0U) - prev->m_ctr = (prev->m_ctr + 1U); - QS_TEC_PRE_(prev->m_ctr); // tick ctr - QS_U8_PRE_(tickRate); // tick rate - QS_END_PRE_() - - // is current Time Event object provided? - QTimeEvt *t = static_cast(QS::rxPriv_.currObj[QS::TE_OBJ]); - if (t != nullptr) { - - // the time event must be armed - Q_ASSERT_INCRIT(810, t->m_ctr != 0U); - - QActive * const act = static_cast(t->m_act); - - // the recipient AO must be provided - Q_ASSERT_INCRIT(820, act != nullptr); - - // periodic time evt? - if (t->m_interval != 0U) { - t->m_ctr = t->m_interval; // rearm the time event - } - else { // one-shot time event: automatically disarm - t->m_ctr = 0U; // auto-disarm - // mark time event 't' as NOT linked - t->refCtr_ = static_cast(t->refCtr_ - & static_cast(~TE_IS_LINKED)); - - QS_BEGIN_PRE_(QS_QF_TIMEEVT_AUTO_DISARM, act->m_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->m_prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(t); // the time event object - QS_SIG_PRE_(t->sig); // signal of this time event - QS_OBJ_PRE_(act); // the target AO - QS_U8_PRE_(tickRate); // tick rate - QS_END_PRE_() - QS_MEM_APP(); - QS_CRIT_EXIT(); // exit critical section before posting - - // asserts if queue overflows - static_cast(act->POST(t, sender)); - - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - } - - // update the linked list of time events - for (;;) { - t = prev->m_next; // advance down the time evt. list - - // end of the list? - if (t == nullptr) { - - // any new time events armed since the last run of tick()? - if (QTimeEvt::timeEvtHead_[tickRate].m_act != nullptr) { - - // sanity check - Q_ASSERT_INCRIT(830, prev != nullptr); - prev->m_next = QTimeEvt::timeEvtHead_[tickRate].toTimeEvt(); - QTimeEvt::timeEvtHead_[tickRate].m_act = nullptr; - t = prev->m_next; // switch to the new list - } - else { - break; // all currently armed time evts. processed - } - } - - // time event scheduled for removal? - if (t->m_ctr == 0U) { - prev->m_next = t->m_next; - // mark time event 't' as NOT linked - t->refCtr_ = static_cast(t->refCtr_ - & static_cast(~TE_IS_LINKED)); - // do NOT advance the prev pointer - QS_MEM_APP(); - QS_CRIT_EXIT(); // exit crit. section to reduce latency - } - else { - prev = t; // advance to this time event - QS_MEM_APP(); - QS_CRIT_EXIT(); // exit crit. section to reduce latency - } - QS_CRIT_ENTRY(); // re-enter crit. section to continue - QS_MEM_SYS(); - } - - QS_MEM_APP(); - QS_CRIT_EXIT(); -} - -//${QS::QUTest-stub::QHsmDummy} .............................................. - -//${QS::QUTest-stub::QHsmDummy::QHsmDummy} ................................... -QHsmDummy::QHsmDummy() -: QAsm() -{} - -//${QS::QUTest-stub::QHsmDummy::init} ........................................ -void QHsmDummy::init( - void const * const e, - std::uint_fast8_t const qsId) -{ - Q_UNUSED_PAR(e); - - #ifdef Q_SPY - if ((QS::priv_.flags & 0x01U) == 0U) { - QS::priv_.flags |= 0x01U; - QS_FUN_DICTIONARY(&QP::QHsm::top); - } - #else - Q_UNUSED_PAR(qsId); - #endif - - QS_CRIT_STAT - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QEP_STATE_INIT, qsId) - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(m_state.fun); // the source state - QS_FUN_PRE_(m_temp.fun); // the target of the initial tran. - QS_END_PRE_() - QS_MEM_APP(); - QS_CRIT_EXIT(); -} - -//${QS::QUTest-stub::QHsmDummy::dispatch} .................................... -void QHsmDummy::dispatch( - QEvt const * const e, - std::uint_fast8_t const qsId) -{ - QS_CRIT_STAT - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QEP_DISPATCH, qsId) - QS_TIME_PRE_(); // time stamp - QS_SIG_PRE_(e->sig); // the signal of the event - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(m_state.fun); // the current state - QS_END_PRE_() - QS_MEM_APP(); - QS_CRIT_EXIT(); -} - -//${QS::QUTest-stub::QActiveDummy} ........................................... - -//${QS::QUTest-stub::QActiveDummy::QActiveDummy} ............................. -QActiveDummy::QActiveDummy() -: QActive(nullptr) -{} - -//${QS::QUTest-stub::QActiveDummy::init} ..................................... -void QActiveDummy::init( - void const * const e, - std::uint_fast8_t const qsId) -{ - Q_UNUSED_PAR(e); - Q_UNUSED_PAR(qsId); - - #ifdef Q_SPY - if ((QS::priv_.flags & 0x01U) == 0U) { - QS::priv_.flags |= 0x01U; - QS_FUN_DICTIONARY(&QP::QHsm::top); - } - #endif - - QS_CRIT_STAT - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QEP_STATE_INIT, m_prio) - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(m_state.fun); // the source state - QS_FUN_PRE_(m_temp.fun); // the target of the initial tran. - QS_END_PRE_() - QS_MEM_APP(); - QS_CRIT_EXIT(); -} - -//${QS::QUTest-stub::QActiveDummy::dispatch} ................................. -void QActiveDummy::dispatch( - QEvt const * const e, - std::uint_fast8_t const qsId) -{ - QS_CRIT_STAT - QS_CRIT_ENTRY(); - QS_MEM_SYS(); - QS_BEGIN_PRE_(QS_QEP_DISPATCH, qsId) - QS_TIME_PRE_(); // time stamp - QS_SIG_PRE_(e->sig); // the signal of the event - QS_OBJ_PRE_(this); // this state machine object - QS_FUN_PRE_(m_state.fun); // the current state - QS_END_PRE_() - QS_MEM_APP(); - QS_CRIT_EXIT(); -} - -//${QS::QUTest-stub::QActiveDummy::fakePost} ................................. -bool QActiveDummy::fakePost( - QEvt const * const e, - std::uint_fast16_t const margin, - void const * const sender) noexcept -{ - QS_TEST_PROBE_DEF(&QActive::post_) - - QF_CRIT_STAT - QF_CRIT_ENTRY(); - QF_MEM_SYS(); - - // test-probe#1 for faking queue overflow - bool status = true; - QS_TEST_PROBE_ID(1, - status = false; - if (margin == QF::NO_MARGIN) { - // fake assertion Mod=qf_actq,Loc=110 - Q_onError("qf_actq", 110); - } - ) - - // is it a mutable event? - if (e->getPoolNum_() != 0U) { - QEvt_refCtr_inc_(e); - } - - std::uint_fast8_t const rec = - (status ? static_cast(QS_QF_ACTIVE_POST) - : static_cast(QS_QF_ACTIVE_POST_ATTEMPT)); - QS_BEGIN_PRE_(rec, m_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_(this); // this active object - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_EQC_PRE_(0U); // # free entries - QS_EQC_PRE_(margin); // margin requested - QS_END_PRE_() - - QF_MEM_APP(); - QF_CRIT_EXIT(); - - // callback to examine the posted event under the same conditions - // as producing the #QS_QF_ACTIVE_POST trace record, which are: - // the local filter for this AO ('m_prio') is set - if (QS_LOC_CHECK_(m_prio)) { - QS::onTestPost(sender, this, e, status); - } - - // recycle the event immediately, because it was not really posted - #if (QF_MAX_EPOOL > 0U) - QF::gc(e); - #endif - - return status; -} - -//${QS::QUTest-stub::QActiveDummy::fakePostLIFO} ............................. -void QActiveDummy::fakePostLIFO(QEvt const * const e) noexcept { - QS_TEST_PROBE_DEF(&QActive::postLIFO) - - QF_CRIT_STAT - QF_CRIT_ENTRY(); - QF_MEM_SYS(); - - // test-probe#1 for faking queue overflow - QS_TEST_PROBE_ID(1, - // fake assertion Mod=qf_actq,Loc=210 - Q_onError("qf_actq", 210); - ) - - // is it a mutable event? - if (e->getPoolNum_() != 0U) { - QEvt_refCtr_inc_(e); - } - - QS_BEGIN_PRE_(QS_QF_ACTIVE_POST_LIFO, m_prio) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of this event - QS_OBJ_PRE_(this); // this active object - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_EQC_PRE_(0U); // # free entries - QS_EQC_PRE_(0U); // min # free entries - QS_END_PRE_() - - QF_MEM_APP(); - QF_CRIT_EXIT(); - - // callback to examine the posted event under the same conditions - // as producing the #QS_QF_ACTIVE_POST trace record, which are: - // the local filter for this AO ('m_prio') is set - if (QS_LOC_CHECK_(m_prio)) { - QS::onTestPost(nullptr, this, e, true); - } - // recycle the event immediately, because it was not really posted - #if (QF_MAX_EPOOL > 0U) - QF::gc(e); - #endif -} - -} // namespace QP -//$enddef${QS::QUTest-stub} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -#endif // Q_UTEST != 0 - -#endif // def Q_UTEST diff --git a/src/qv/qv.cpp b/src/qv/qv.cpp index 8c2506813..c8efcba49 100644 --- a/src/qv/qv.cpp +++ b/src/qv/qv.cpp @@ -3,17 +3,10 @@ // Model: qpcpp.qm // File: ${src::qv::qv.cpp} // -// This code has been generated by QM 6.2.0 . +// This code has been generated by QM 7.0.0 . // DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. // -// This code is covered by the following QP license: -// License # : LicenseRef-QL-dual -// Issued to : Any user of the QP/C++ real-time embedded framework -// Framework(s) : qpcpp -// Support ends : 2025-12-31 -// License scope: -// -// Copyright (C) 2005 Quantum Leaps, LLC . +// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. // // Q u a n t u m L e a P s // ------------------------ @@ -21,21 +14,20 @@ // // 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: +// 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. // -// Contact information: +// NOTE: +// The GPL does NOT permit the incorporation of this code into proprietary +// programs. Please contact Quantum Leaps for commercial licensing options, +// which expressly supersede the GPL and are designed explicitly for +// closed-source distribution. +// +// Quantum Leaps contact information: // // // @@ -85,12 +77,12 @@ void schedDisable(std::uint_fast8_t const ceiling) { if (ceiling > priv_.schedCeil) { // raising the scheduler ceiling? - QS_BEGIN_PRE_(QS_SCHED_LOCK, 0U) - QS_TIME_PRE_(); // timestamp + QS_BEGIN_PRE(QS_SCHED_LOCK, 0U) + QS_TIME_PRE(); // timestamp // the previous sched ceiling & new sched ceiling - QS_2U8_PRE_(static_cast(priv_.schedCeil), + QS_2U8_PRE(static_cast(priv_.schedCeil), static_cast(ceiling)); - QS_END_PRE_() + QS_END_PRE() priv_.schedCeil = ceiling; #ifndef Q_UNSAFE @@ -112,11 +104,11 @@ void schedEnable() { if (priv_.schedCeil != 0U) { // actually enabling the scheduler? - QS_BEGIN_PRE_(QS_SCHED_UNLOCK, 0U) - QS_TIME_PRE_(); // timestamp + QS_BEGIN_PRE(QS_SCHED_UNLOCK, 0U) + QS_TIME_PRE(); // timestamp // current sched ceiling (old), previous sched ceiling (new) - QS_2U8_PRE_(static_cast(priv_.schedCeil), 0U); - QS_END_PRE_() + QS_2U8_PRE(static_cast(priv_.schedCeil), 0U); + QS_END_PRE() priv_.schedCeil = 0U; #ifndef Q_UNSAFE @@ -180,7 +172,13 @@ int_t run() { #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) std::uint_fast8_t pprev = 0U; // previous prio. - #endif + + #ifdef QF_ON_CONTEXT_SW + // officially switch to the idle cotext + QF_onContextSw(nullptr, nullptr); + #endif // def QF_ON_CONTEXT_SW + + #endif // (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) for (;;) { // QV event loop... @@ -200,11 +198,11 @@ int_t run() { QActive * const a = QActive::registry_[p]; #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) - QS_BEGIN_PRE_(QS_SCHED_NEXT, p) - QS_TIME_PRE_(); // timestamp - QS_2U8_PRE_(static_cast(p), + QS_BEGIN_PRE(QS_SCHED_NEXT, p) + QS_TIME_PRE(); // timestamp + QS_2U8_PRE(static_cast(p), static_cast(pprev)); - QS_END_PRE_() + QS_END_PRE() #ifdef QF_ON_CONTEXT_SW QF_onContextSw(((pprev != 0U) @@ -239,10 +237,10 @@ int_t run() { else { // no AO ready to run --> idle #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) if (pprev != 0U) { - QS_BEGIN_PRE_(QS_SCHED_IDLE, pprev) - QS_TIME_PRE_(); // timestamp - QS_U8_PRE_(static_cast(pprev)); - QS_END_PRE_() + QS_BEGIN_PRE(QS_SCHED_IDLE, pprev) + QS_TIME_PRE(); // timestamp + QS_U8_PRE(static_cast(pprev)); + QS_END_PRE() #ifdef QF_ON_CONTEXT_SW QF_onContextSw(QActive::registry_[pprev], nullptr); @@ -285,7 +283,7 @@ namespace QP { //${QV::QActive::start} ...................................................... void QActive::start( QPrioSpec const prioSpec, - QEvt const * * const qSto, + QEvtPtr * const qSto, std::uint_fast16_t const qLen, void * const stkSto, std::uint_fast16_t const stkSize, diff --git a/src/qxk/CMakeLists.txt b/src/qxk/CMakeLists.txt deleted file mode 100644 index 3939f6a68..000000000 --- a/src/qxk/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -# ./src/qf -target_sources(qpcpp PRIVATE - qxk_mutex.cpp - qxk_sema.cpp - qxk_xthr.cpp - qxk.cpp -) diff --git a/src/qxk/qxk.cpp b/src/qxk/qxk.cpp deleted file mode 100644 index 8d8dc5a22..000000000 --- a/src/qxk/qxk.cpp +++ /dev/null @@ -1,554 +0,0 @@ -//$file${src::qxk::qxk.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// -// Model: qpcpp.qm -// File: ${src::qxk::qxk.cpp} -// -// This code has been generated by QM 6.2.0 . -// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. -// -// This code is covered by the following QP license: -// License # : LicenseRef-QL-dual -// Issued to : Any user of the QP/C++ real-time embedded framework -// Framework(s) : qpcpp -// Support ends : 2025-12-31 -// License scope: -// -// Copyright (C) 2005 Quantum Leaps, LLC . -// -// 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 -// -// 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: -// -// -// -//$endhead${src::qxk::qxk.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -#define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // QS software tracing enabled? - #include "qs_port.hpp" // QS port - #include "qs_pkg.hpp" // QS facilities for pre-defined trace records -#else - #include "qs_dummy.hpp" // disable the QS software tracing -#endif // Q_SPY - -// protection against including this source file in a wrong project -#ifndef QXK_HPP_ - #error "Source file included in a project NOT based on the QXK kernel" -#endif // QXK_HPP_ - -// unnamed namespace for local definitions with internal linkage -namespace { -Q_DEFINE_THIS_MODULE("qxk") -} // unnamed namespace - -//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// Check for the minimum required QP version -#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U)) -#error qpcpp version 7.3.0 or higher required -#endif -//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//$define${QXK::QXK-base} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { -namespace QXK { - -//${QXK::QXK-base::schedLock} ................................................ -QSchedStatus schedLock(std::uint_fast8_t const ceiling) noexcept { - QF_CRIT_STAT - QF_CRIT_ENTRY(); - QF_MEM_SYS(); - - Q_REQUIRE_INCRIT(100, !QXK_ISR_CONTEXT_()); - - QSchedStatus stat; // saved lock status to be returned - - // is the lock ceiling being raised? - if (ceiling > QXK_priv_.lockCeil) { - QS_BEGIN_PRE_(QS_SCHED_LOCK, 0U) - QS_TIME_PRE_(); // timestamp - // the previous lock ceiling & new lock ceiling - QS_2U8_PRE_(static_cast(QXK_priv_.lockCeil), - static_cast(ceiling)); - QS_END_PRE_() - - // previous status of the lock - stat = static_cast(QXK_priv_.lockHolder); - stat |= static_cast(QXK_priv_.lockCeil) << 8U; - - // new status of the lock - QXK_priv_.lockHolder = (QXK_priv_.curr != nullptr) - ? QXK_priv_.curr->getPrio() - : 0U; - QXK_priv_.lockCeil = ceiling; - } - else { - stat = 0xFFU; // scheduler not locked - } - QF_MEM_APP(); - QF_CRIT_EXIT(); - - return stat; // return the status to be saved in a stack variable -} - -//${QXK::QXK-base::schedUnlock} .............................................. -void schedUnlock(QSchedStatus const stat) noexcept { - // has the scheduler been actually locked by the last QXK::schedLock()? - if (stat != 0xFFU) { - std::uint8_t const prevCeil = static_cast(stat >> 8U); - QF_CRIT_STAT - QF_CRIT_ENTRY(); - QF_MEM_SYS(); - - Q_REQUIRE_INCRIT(200, !QXK_ISR_CONTEXT_()); - Q_REQUIRE_INCRIT(201, QXK_priv_.lockCeil > prevCeil); - - QS_BEGIN_PRE_(QS_SCHED_UNLOCK, 0U) - QS_TIME_PRE_(); // timestamp - // ceiling before unlocking & prio after unlocking - QS_2U8_PRE_(QXK_priv_.lockCeil, prevCeil); - QS_END_PRE_() - - // restore the previous lock ceiling and lock holder - QXK_priv_.lockCeil = prevCeil; - QXK_priv_.lockHolder = (stat & 0xFFU); - - // find if any threads should be run after unlocking the scheduler - if (QXK_sched_() != 0U) { // activation needed? - QXK_activate_(); // synchronously activate basic-thred(s) - } - - QF_MEM_APP(); - QF_CRIT_EXIT(); - } -} - -//${QXK::QXK-base::current} .................................................. -QP::QActive * current() noexcept { - QF_CRIT_STAT - QF_CRIT_ENTRY(); - QF_MEM_SYS(); - - Q_REQUIRE_INCRIT(600, QXK_priv_.lockCeil <= QF_MAX_ACTIVE); - - QP::QActive *curr = QXK_priv_.curr; - if (curr == nullptr) { // basic thread? - curr = QP::QActive::registry_[QXK_priv_.actPrio]; - } - - Q_ASSERT_INCRIT(690, curr != nullptr); - - QF_MEM_APP(); - QF_CRIT_EXIT(); - - return curr; -} - -} // namespace QXK -} // namespace QP -//$enddef${QXK::QXK-base} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -extern "C" { -//$define${QXK-extern-C} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv - -//${QXK-extern-C::QXK_priv_} ................................................. -QXK_Attr QXK_priv_; - -//${QXK-extern-C::QXK_sched_} ................................................ -std::uint_fast8_t QXK_sched_() noexcept { - Q_INVARIANT_INCRIT(402, - QXK_priv_.readySet.verify_(&QXK_priv_.readySet_dis)); - - std::uint_fast8_t p; - if (QXK_priv_.readySet.isEmpty()) { - p = 0U; // no activation needed - } - else { - // find the highest-prio thread ready to run - p = QXK_priv_.readySet.findMax(); - if (p <= QXK_priv_.lockCeil) { - // prio. of the thread holding the lock - p = static_cast( - QP::QActive::registry_[QXK_priv_.lockHolder]->getPrio()); - if (p != 0U) { - Q_ASSERT_INCRIT(410, QXK_priv_.readySet.hasElement(p)); - } - } - } - QP::QActive const * const curr = QXK_priv_.curr; - QP::QActive * const next = QP::QActive::registry_[p]; - - // the next thread found must be registered in QF - Q_ASSERT_INCRIT(420, next != nullptr); - - // is the current thread a basic-thread? - if (curr == nullptr) { - - // is the new prio. above the active prio.? - if (p > QXK_priv_.actPrio) { - QXK_priv_.next = next; // set the next AO to activate - - if (next->getOsObject() != nullptr) { // is next extended? - QXK_CONTEXT_SWITCH_(); - p = 0U; // no activation needed - } - } - else { // below the active prio. - QXK_priv_.next = nullptr; - p = 0U; // no activation needed - } - } - else { // currently executing an extended-thread - // is the current thread different from the next? - if (curr != next) { - QXK_priv_.next = next; - QXK_CONTEXT_SWITCH_(); - } - else { // current is the same as next - QXK_priv_.next = nullptr; // no need to context-switch - } - p = 0U; // no activation needed - } - - return p; -} - -//${QXK-extern-C::QXK_activate_} ............................................. -void QXK_activate_() noexcept { - std::uint_fast8_t const prio_in = QXK_priv_.actPrio; - QP::QActive *next = QXK_priv_.next; // the next AO (basic-thread) to run - - Q_REQUIRE_INCRIT(500, (next != nullptr) && (prio_in <= QF_MAX_ACTIVE)); - - // QXK Context switch callback defined or QS tracing enabled? - #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) - QXK_contextSw_(next); - #endif // QF_ON_CONTEXT_SW || Q_SPY - - QXK_priv_.next = nullptr; // clear the next AO - QXK_priv_.curr = nullptr; // current is basic-thread - - // prio. of the next thread - std::uint_fast8_t p = next->getPrio(); - - // loop until no more ready-to-run AOs of higher prio than the initial - do { - QXK_priv_.actPrio = p; // next active prio - - QF_MEM_APP(); - QF_INT_ENABLE(); // unconditionally enable interrupts - - QP::QEvt const * const e = next->get_(); - // NOTE QActive::get_() performs QS_MEM_APP() before return - - // dispatch event (virtual call) - next->dispatch(e, next->getPrio()); - #if (QF_MAX_EPOOL > 0U) - QP::QF::gc(e); - #endif - - QF_INT_DISABLE(); // unconditionally disable interrupts - QF_MEM_SYS(); - - // check internal integrity (duplicate inverse storage) - Q_INVARIANT_INCRIT(502, - QXK_priv_.readySet.verify_(&QXK_priv_.readySet_dis)); - - if (next->getEQueue().isEmpty()) { // empty queue? - QXK_priv_.readySet.remove(p); - #ifndef Q_UNSAFE - QXK_priv_.readySet.update_(&QXK_priv_.readySet_dis); - #endif - } - - if (QXK_priv_.readySet.isEmpty()) { - QXK_priv_.next = nullptr; - next = QP::QActive::registry_[0]; - p = 0U; // no activation needed - } - else { - // find next highest-prio below the lock ceiling - p = QXK_priv_.readySet.findMax(); - if (p <= QXK_priv_.lockCeil) { - p = QXK_priv_.lockHolder; - if (p != 0U) { - Q_ASSERT_INCRIT(510, QXK_priv_.readySet.hasElement(p)); - } - } - - // set the next thread and ensure that it is registered - next = QP::QActive::registry_[p]; - Q_ASSERT_INCRIT(520, next != nullptr); - - // is next a basic thread? - if (next->getOsObject() == nullptr) { - // is the next prio. above the initial prio.? - if (p > QP::QActive::registry_[prio_in]->getPrio()) { - #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) - if (p != QXK_priv_.actPrio) { // changing threads? - QXK_contextSw_(next); - } - #endif // QF_ON_CONTEXT_SW || Q_SPY - QXK_priv_.next = next; - } - else { - QXK_priv_.next = nullptr; - p = 0U; // no activation needed - } - } - else { // next is the extended-thread - QXK_priv_.next = next; - QXK_CONTEXT_SWITCH_(); - p = 0U; // no activation needed - } - } - } while (p != 0U); // while activation needed - - // restore the active prio. - QXK_priv_.actPrio = prio_in; - - #if (defined QF_ON_CONTEXT_SW) || (defined Q_SPY) - if (next->getOsObject() == nullptr) { - QXK_contextSw_((prio_in == 0U) - ? nullptr - : QP::QActive::registry_[prio_in]); - } - #endif // QF_ON_CONTEXT_SW || Q_SPY -} - -//${QXK-extern-C::QXK_contextSw_} ............................................ -void QXK_contextSw_(QP::QActive * const next) { - #ifdef Q_SPY - std::uint_fast8_t const prev_prio = (QXK_priv_.prev != nullptr) - ? QXK_priv_.prev->getPrio() - : 0U; - if (next != nullptr) { // next is NOT idle? - std::uint_fast8_t const next_prio = next->getPrio(); - QS_BEGIN_PRE_(QP::QS_SCHED_NEXT, next_prio) - QS_TIME_PRE_(); // timestamp - QS_2U8_PRE_(next_prio, prev_prio); - QS_END_PRE_() - } - else { // going to idle - QS_BEGIN_PRE_(QP::QS_SCHED_IDLE, prev_prio) - QS_TIME_PRE_(); // timestamp - QS_U8_PRE_(prev_prio); - QS_END_PRE_() - } - #endif // Q_SPY - - #ifdef QF_ON_CONTEXT_SW - QF_onContextSw(QXK_priv_.prev, next); - #endif // QF_ON_CONTEXT_SW - - QXK_priv_.prev = next; // update the previous thread -} - -//${QXK-extern-C::QXK_threadExit_} ........................................... -void QXK_threadExit_() { - QF_CRIT_STAT - QF_CRIT_ENTRY(); - - QP::QXThread const * const thr = QXTHREAD_CAST_(QXK_priv_.curr); - - Q_REQUIRE_INCRIT(900, (!QXK_ISR_CONTEXT_()) - && (thr != nullptr)); // current thread must be extended - Q_REQUIRE_INCRIT(901, QXK_priv_.lockHolder != thr->getPrio()); - - std::uint_fast8_t const p = - static_cast(thr->getPrio()); - - QF_MEM_SYS(); - QP::QActive::registry_[p] = nullptr; - QXK_priv_.readySet.remove(p); - #ifndef Q_UNSAFE - QXK_priv_.readySet.update_(&QXK_priv_.readySet_dis); - #endif - - static_cast(QXK_sched_()); // schedule other threads - - QF_MEM_APP(); - QF_CRIT_EXIT(); -} -//$enddef${QXK-extern-C} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -} // extern "C" - -//$define${QXK::QF-cust} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { -namespace QF { - -//${QXK::QF-cust::init} ...................................................... -void init() { - bzero_(&QF::priv_, sizeof(QF::priv_)); - bzero_(&QXK_priv_, sizeof(QXK_priv_)); - bzero_(&QActive::registry_[0], sizeof(QActive::registry_)); - - #ifndef Q_UNSAFE - QXK_priv_.readySet.update_(&QXK_priv_.readySet_dis); - #endif - - // setup the QXK scheduler as initially locked and not running - QXK_priv_.lockCeil = (QF_MAX_ACTIVE + 1U); // scheduler locked - - // storage capable for holding a blank QActive object (const in ROM) - static void* const - idle_ao[((sizeof(QActive) + sizeof(void*)) - 1U) / sizeof(void*)] - = { nullptr }; - - // register the idle AO object (cast 'const' away) - QActive::registry_[0] = QF_CONST_CAST_(QActive*, - reinterpret_cast(idle_ao)); - - #ifdef QXK_INIT - QXK_INIT(); // port-specific initialization of the QXK kernel - #endif -} - -//${QXK::QF-cust::stop} ...................................................... -void stop() { - onCleanup(); // cleanup callback - // nothing else to do for the QXK preemptive kernel -} - -//${QXK::QF-cust::run} ....................................................... -int_t run() { - #ifdef Q_SPY - QS_SIG_DICTIONARY(QXK::DELAY_SIG, nullptr); - QS_SIG_DICTIONARY(QXK::TIMEOUT_SIG, nullptr); - - // produce the QS_QF_RUN trace record - QF_INT_DISABLE(); - QF_MEM_SYS(); - QS::beginRec_(QS_REC_NUM_(QS_QF_RUN)); - QS::endRec_(); - QF_MEM_APP(); - QF_INT_ENABLE(); - #endif // Q_SPY - - onStartup(); // application-specific startup callback - - QF_INT_DISABLE(); - QF_MEM_SYS(); - - #ifdef QXK_START - QXK_START(); // port-specific startup of the QXK kernel - #endif - - QXK_priv_.lockCeil = 0U; // unlock the QXK scheduler - - // activate AOs to process events posted so far - if (QXK_sched_() != 0U) { - QXK_activate_(); - } - - QF_MEM_APP(); - QF_INT_ENABLE(); - - for (;;) { // QXK idle loop... - QXK::onIdle(); // application-specific QXK idle callback - } - - #ifdef __GNUC__ // GNU compiler? - return 0; - #endif -} - -} // namespace QF -} // namespace QP -//$enddef${QXK::QF-cust} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -//$define${QXK::QActive} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { - -//${QXK::QActive} ............................................................ - -//${QXK::QActive::start} ..................................................... -void QActive::start( - QPrioSpec const prioSpec, - QEvt const * * const qSto, - std::uint_fast16_t const qLen, - void * const stkSto, - std::uint_fast16_t const stkSize, - void const * const par) -{ - QF_CRIT_STAT - QF_CRIT_ENTRY(); - Q_REQUIRE_INCRIT(300, (!QXK_ISR_CONTEXT_()) - && ((prioSpec & 0xFF00U) == 0U)); - QF_CRIT_EXIT(); - - m_prio = static_cast(prioSpec & 0xFFU); // QF-prio. - m_pthre = 0U; // not used - register_(); // make QF aware of this QActive/QXThread - - if (stkSto == nullptr) { // starting basic thread (AO)? - m_eQueue.init(qSto, qLen); // init the built-in queue - m_osObject = nullptr; // no private stack for AO - - this->init(par, m_prio); // top-most initial tran. (virtual call) - QS_FLUSH(); // flush the trace buffer to the host - - // see if this AO needs to be scheduled if QXK is already running - QF_CRIT_ENTRY(); - QF_MEM_SYS(); - if (QXK_priv_.lockCeil <= QF_MAX_ACTIVE) { // scheduler running? - if (QXK_sched_() != 0U) { // activation needed? - QXK_activate_(); // synchronously activate basic-thred(s) - } - } - QF_MEM_APP(); - QF_CRIT_EXIT(); - } - else { // starting QXThread - - // is storage for the queue buffer provided? - if (qSto != nullptr) { - m_eQueue.init(qSto, qLen); - } - - // extended threads provide their thread function in place of - // the top-most initial tran. 'm_temp.act' - QXK_PTR_CAST_(QXThread*, this)->stackInit_(m_temp.thr, - stkSto, stkSize); - - // the new thread is not blocked on any object - m_temp.obj = nullptr; - - QF_CRIT_ENTRY(); - QF_MEM_SYS(); - - // extended-thread becomes ready immediately - QXK_priv_.readySet.insert(static_cast(m_prio)); - #ifndef Q_UNSAFE - QXK_priv_.readySet.update_(&QXK_priv_.readySet_dis); - #endif - - // see if this thread needs to be scheduled in case QXK is running - if (QXK_priv_.lockCeil <= QF_MAX_ACTIVE) { - static_cast(QXK_sched_()); // schedule other threads - } - QF_MEM_APP(); - QF_CRIT_EXIT(); - } -} - -} // namespace QP -//$enddef${QXK::QActive} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/qxk/qxk_mutex.cpp b/src/qxk/qxk_mutex.cpp deleted file mode 100644 index 219e04f8a..000000000 --- a/src/qxk/qxk_mutex.cpp +++ /dev/null @@ -1,489 +0,0 @@ -//$file${src::qxk::qxk_mutex.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// -// Model: qpcpp.qm -// File: ${src::qxk::qxk_mutex.cpp} -// -// This code has been generated by QM 6.2.0 . -// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. -// -// This code is covered by the following QP license: -// License # : LicenseRef-QL-dual -// Issued to : Any user of the QP/C++ real-time embedded framework -// Framework(s) : qpcpp -// Support ends : 2025-12-31 -// License scope: -// -// Copyright (C) 2005 Quantum Leaps, LLC . -// -// 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 -// -// 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: -// -// -// -//$endhead${src::qxk::qxk_mutex.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -#define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // QS software tracing enabled? - #include "qs_port.hpp" // QS port - #include "qs_pkg.hpp" // QS facilities for pre-defined trace records -#else - #include "qs_dummy.hpp" // disable the QS software tracing -#endif // Q_SPY - -// protection against including this source file in a wrong project -#ifndef QXK_HPP_ - #error "Source file included in a project NOT based on the QXK kernel" -#endif // QXK_HPP_ - -// unnamed namespace for local definitions with internal linkage -namespace { -Q_DEFINE_THIS_MODULE("qxk_mutex") -} // unnamed namespace - -//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// Check for the minimum required QP version -#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U)) -#error qpcpp version 7.3.0 or higher required -#endif -//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//$define${QXK::QXMutex} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { - -//${QXK::QXMutex} ............................................................ - -//${QXK::QXMutex::QXMutex} ................................................... -QXMutex::QXMutex() - : m_ao(Q_STATE_CAST(0)) -{} - -//${QXK::QXMutex::init} ...................................................... -void QXMutex::init(QPrioSpec const prioSpec) noexcept { - QF_CRIT_STAT - QF_CRIT_ENTRY(); - QF_MEM_SYS(); - - Q_REQUIRE_INCRIT(100, (prioSpec & 0xFF00U) == 0U); - - m_ao.m_prio = static_cast(prioSpec & 0xFFU); // QF-prio. - m_ao.m_pthre = 0U; // not used - QActive &ao = m_ao; - - QF_MEM_APP(); - QF_CRIT_EXIT(); - - ao.register_(); // register this mutex as AO -} - -//${QXK::QXMutex::lock} ...................................................... -bool QXMutex::lock(QTimeEvtCtr const nTicks) noexcept { - QF_CRIT_STAT - QF_CRIT_ENTRY(); - QF_MEM_SYS(); - - QXThread * const curr = QXK_PTR_CAST_(QXThread*, QXK_priv_.curr); - - // precondition, this mutex operation must: - // - NOT be called from an ISR; - // - be called from an eXtended thread; - // - the mutex-prio. must be in range; - // - the thread must NOT be already blocked on any object. - Q_REQUIRE_INCRIT(200, (!QXK_ISR_CONTEXT_()) - && (curr != nullptr) - && (m_ao.m_prio <= QF_MAX_ACTIVE) - && (curr->m_temp.obj == nullptr)); - // also: the thread must NOT be holding a scheduler lock. - Q_REQUIRE_INCRIT(201, QXK_priv_.lockHolder != curr->m_prio); - - // is the mutex available? - bool locked = true; // assume that the mutex will be locked - if (m_ao.m_eQueue.m_nFree == 0U) { - m_ao.m_eQueue.m_nFree = 1U; // mutex lock nesting - - // also: the newly locked mutex must have no holder yet - Q_REQUIRE_INCRIT(203, m_ao.m_osObject == nullptr); - - // set the new mutex holder to the curr thread and - // save the thread's prio in the mutex - // NOTE: reuse the otherwise unused eQueue data member. - m_ao.m_osObject = curr; - m_ao.m_eQueue.m_head = static_cast(curr->m_prio); - - QS_BEGIN_PRE_(QS_MTX_LOCK, curr->m_prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this mutex - QS_U8_PRE_(static_cast(m_ao.m_eQueue.m_head)); - QS_U8_PRE_(static_cast(m_ao.m_eQueue.m_nFree)); - QS_END_PRE_() - - if (m_ao.m_prio != 0U) { // prio.-ceiling protocol used? - // the holder prio. must be lower than that of the mutex - // and the prio. slot must be occupied by this mutex - Q_ASSERT_INCRIT(210, (curr->m_prio < m_ao.m_prio) - && (QActive::registry_[m_ao.m_prio] == &m_ao)); - - // remove the thread's original prio from the ready set - // and insert the mutex's prio into the ready set - QXK_priv_.readySet.remove( - static_cast(m_ao.m_eQueue.m_head)); - QXK_priv_.readySet.insert( - static_cast(m_ao.m_prio)); - #ifndef Q_UNSAFE - QXK_priv_.readySet.update_(&QXK_priv_.readySet_dis); - #endif - // put the thread into the AO registry in place of the mutex - QActive::registry_[m_ao.m_prio] = curr; - - // set thread's prio to that of the mutex - curr->m_prio = m_ao.m_prio; - #ifndef Q_UNSAFE - curr->m_prio_dis = static_cast(~curr->m_prio); - #endif - } - } - // is the mutex locked by this thread already (nested locking)? - else if (m_ao.m_osObject == curr) { - - // the nesting level beyond the arbitrary but high bound - // most likely means cyclic or recursive locking of a mutex. - Q_ASSERT_INCRIT(220, m_ao.m_eQueue.m_nFree < 0xFFU); - - // lock one more level - m_ao.m_eQueue.m_nFree = m_ao.m_eQueue.m_nFree + 1U; - - QS_BEGIN_PRE_(QS_MTX_LOCK, curr->m_prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this mutex - QS_U8_PRE_(static_cast(m_ao.m_eQueue.m_head)); - QS_U8_PRE_(static_cast(m_ao.m_eQueue.m_nFree)); - QS_END_PRE_() - } - else { // the mutex is already locked by a different thread - // the mutex holder must be valid - Q_ASSERT_INCRIT(230, m_ao.m_osObject != nullptr); - - if (m_ao.m_prio != 0U) { // prio.-ceiling protocol used? - // the prio slot must be occupied by the thr. holding the mutex - Q_ASSERT_INCRIT(240, QActive::registry_[m_ao.m_prio] - == QXK_PTR_CAST_(QActive const *, m_ao.m_osObject)); - } - - // remove the curr thread's prio from the ready set (will block) - // and insert it to the waiting set on this mutex - std::uint_fast8_t const p = - static_cast(curr->m_prio); - QXK_priv_.readySet.remove(p); - #ifndef Q_UNSAFE - QXK_priv_.readySet.update_(&QXK_priv_.readySet_dis); - #endif - m_waitSet.insert(p); - - // set the blocking object (this mutex) - curr->m_temp.obj = QXK_PTR_CAST_(QMState*, this); - curr->teArm_(static_cast(QXK::TIMEOUT_SIG), nTicks); - - QS_BEGIN_PRE_(QS_MTX_BLOCK, curr->m_prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this mutex - QS_2U8_PRE_(static_cast(m_ao.m_eQueue.m_head), - curr->m_prio); - QS_END_PRE_() - - // schedule the next thread if multitasking started - static_cast(QXK_sched_()); // schedule other threads - - QF_MEM_APP(); - QF_CRIT_EXIT(); - QF_CRIT_EXIT_NOP(); // BLOCK here !!! - - // AFTER unblocking... - QF_CRIT_ENTRY(); - QF_MEM_SYS(); - // the blocking object must be this mutex - Q_ASSERT_INCRIT(250, curr->m_temp.obj - == QXK_PTR_CAST_(QMState*, this)); - - // did the blocking time-out? (signal of zero means that it did) - if (curr->m_timeEvt.sig == 0U) { - if (m_waitSet.hasElement(p)) { // still waiting? - m_waitSet.remove(p); // remove unblocked thread - locked = false; // the mutex was NOT locked - } - } - else { // blocking did NOT time out - // the thread must NOT be waiting on this mutex - Q_ASSERT_INCRIT(260, !m_waitSet.hasElement(p)); - } - curr->m_temp.obj = nullptr; // clear blocking obj. - } - QF_MEM_APP(); - QF_CRIT_EXIT(); - - return locked; -} - -//${QXK::QXMutex::tryLock} ................................................... -bool QXMutex::tryLock() noexcept { - QF_CRIT_STAT - QF_CRIT_ENTRY(); - QF_MEM_SYS(); - - QActive *curr = QXK_priv_.curr; - if (curr == nullptr) { // called from a basic thread? - curr = QActive::registry_[QXK_priv_.actPrio]; - } - - // precondition, this mutex must: - // - NOT be called from an ISR; - // - the calling thread must be valid; - // - the mutex-prio. must be in range - Q_REQUIRE_INCRIT(300, (!QXK_ISR_CONTEXT_()) - && (curr != nullptr) - && (m_ao.m_prio <= QF_MAX_ACTIVE)); - // also: the thread must NOT be holding a scheduler lock. - Q_REQUIRE_INCRIT(301, - QXK_priv_.lockHolder != static_cast(curr->m_prio)); - - // is the mutex available? - if (m_ao.m_eQueue.m_nFree == 0U) { - m_ao.m_eQueue.m_nFree = 1U; // mutex lock nesting - - // also the newly locked mutex must have no holder yet - Q_REQUIRE_INCRIT(303, m_ao.m_osObject == nullptr); - - // set the new mutex holder to the curr thread and - // save the thread's prio in the mutex - // NOTE: reuse the otherwise unused eQueue data member. - m_ao.m_osObject = curr; - m_ao.m_eQueue.m_head = static_cast(curr->m_prio); - - QS_BEGIN_PRE_(QS_MTX_LOCK, curr->m_prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this mutex - QS_U8_PRE_(static_cast(m_ao.m_eQueue.m_head)); - QS_U8_PRE_(static_cast(m_ao.m_eQueue.m_nFree)); - QS_END_PRE_() - - if (m_ao.m_prio != 0U) { // prio.-ceiling protocol used? - // the holder prio. must be lower than that of the mutex - // and the prio. slot must be occupied by this mutex - Q_ASSERT_INCRIT(310, (curr->m_prio < m_ao.m_prio) - && (QActive::registry_[m_ao.m_prio] == &m_ao)); - - // remove the thread's original prio from the ready set - // and insert the mutex's prio into the ready set - QXK_priv_.readySet.remove( - static_cast(m_ao.m_eQueue.m_head)); - QXK_priv_.readySet.insert( - static_cast(m_ao.m_prio)); - #ifndef Q_UNSAFE - QXK_priv_.readySet.update_(&QXK_priv_.readySet_dis); - #endif - // put the thread into the AO registry in place of the mutex - QActive::registry_[m_ao.m_prio] = curr; - - // set thread's prio to that of the mutex - curr->m_prio = m_ao.m_prio; - #ifndef Q_UNSAFE - curr->m_prio_dis = static_cast(~curr->m_prio); - #endif - } - } - // is the mutex locked by this thread already (nested locking)? - else if (m_ao.m_osObject == curr) { - // the nesting level must not exceed the specified bound - Q_ASSERT_INCRIT(320, m_ao.m_eQueue.m_nFree < 0xFFU); - - // lock one more level - m_ao.m_eQueue.m_nFree = m_ao.m_eQueue.m_nFree + 1U; - - QS_BEGIN_PRE_(QS_MTX_LOCK, curr->m_prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this mutex - QS_U8_PRE_(static_cast(m_ao.m_eQueue.m_head)); - QS_U8_PRE_(static_cast(m_ao.m_eQueue.m_nFree)); - QS_END_PRE_() - } - else { // the mutex is already locked by a different thread - if (m_ao.m_prio != 0U) { // prio.-ceiling protocol used? - // the prio slot must be occupied by the thr. holding the mutex - Q_ASSERT_INCRIT(330, QActive::registry_[m_ao.m_prio] - == QXK_PTR_CAST_(QActive const *, m_ao.m_osObject)); - } - - QS_BEGIN_PRE_(QS_MTX_BLOCK_ATTEMPT, curr->m_prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this mutex - QS_2U8_PRE_(static_cast(m_ao.m_eQueue.m_head), - curr->m_prio); // trying thread prio - QS_END_PRE_() - - curr = nullptr; // means that mutex is NOT available - } - QF_MEM_APP(); - QF_CRIT_EXIT(); - - return curr != nullptr; -} - -//${QXK::QXMutex::unlock} .................................................... -void QXMutex::unlock() noexcept { - QF_CRIT_STAT - QF_CRIT_ENTRY(); - QF_MEM_SYS(); - - QActive *curr = QXK_priv_.curr; - if (curr == nullptr) { // called from a basic thread? - curr = QActive::registry_[QXK_priv_.actPrio]; - } - - Q_REQUIRE_INCRIT(400, (!QXK_ISR_CONTEXT_()) - && (curr != nullptr)); - Q_REQUIRE_INCRIT(401, m_ao.m_eQueue.m_nFree > 0U); - Q_REQUIRE_INCRIT(403, m_ao.m_osObject == curr); - - // is this the last nesting level? - if (m_ao.m_eQueue.m_nFree == 1U) { - - if (m_ao.m_prio != 0U) { // prio.-ceiling protocol used? - - Q_ASSERT_INCRIT(410, m_ao.m_prio < QF_MAX_ACTIVE); - - // restore the holding thread's prio from the mutex - curr->m_prio = - static_cast(m_ao.m_eQueue.m_head); - #ifndef Q_UNSAFE - curr->m_prio_dis = static_cast(~curr->m_prio); - #endif - - // put the mutex back into the AO registry - QActive::registry_[m_ao.m_prio] = &m_ao; - - // remove the mutex' prio from the ready set - // and insert the original thread's prio. - QXK_priv_.readySet.remove( - static_cast(m_ao.m_prio)); - QXK_priv_.readySet.insert( - static_cast(m_ao.m_eQueue.m_head)); - #ifndef Q_UNSAFE - QXK_priv_.readySet.update_(&QXK_priv_.readySet_dis); - #endif - } - - QS_BEGIN_PRE_(QS_MTX_UNLOCK, curr->m_prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this mutex - QS_2U8_PRE_(static_cast(m_ao.m_eQueue.m_head), - 0U); - QS_END_PRE_() - - // are any other threads waiting on this mutex? - if (m_waitSet.notEmpty()) { - // find the highest-prio. thread waiting on this mutex - std::uint_fast8_t const p = m_waitSet.findMax(); - - // remove this thread from waiting on the mutex - // and insert it into the ready set. - m_waitSet.remove(p); - QXK_priv_.readySet.insert(p); - #ifndef Q_UNSAFE - QXK_priv_.readySet.update_(&QXK_priv_.readySet_dis); - #endif - - QXThread * const thr = - QXK_PTR_CAST_(QXThread*, QActive::registry_[p]); - - // the waiting thread must: - // - be registered in QF - // - have the prio. corresponding to the registration - // - be an extended thread - // - be blocked on this mutex - Q_ASSERT_INCRIT(420, (thr != nullptr) - && (thr->m_prio == static_cast(p)) - && (thr->m_state.act == Q_ACTION_CAST(0)) - && (thr->m_temp.obj == QXK_PTR_CAST_(QMState*, this))); - - // disarm the internal time event - static_cast(thr->teDisarm_()); - - // set the new mutex holder to the curr thread and - // save the thread's prio in the mutex - // NOTE: reuse the otherwise unused eQueue data member. - m_ao.m_osObject = thr; - m_ao.m_eQueue.m_head = static_cast(thr->m_prio); - - QS_BEGIN_PRE_(QS_MTX_LOCK, thr->m_prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this mutex - QS_U8_PRE_(static_cast(m_ao.m_eQueue.m_head)); - QS_U8_PRE_(static_cast(m_ao.m_eQueue.m_nFree)); - QS_END_PRE_() - - if (m_ao.m_prio != 0U) { // prio.-ceiling protocol used? - // the holder prio. must be lower than that of the mutex - Q_ASSERT_INCRIT(430, (m_ao.m_prio < QF_MAX_ACTIVE) - && (thr->m_prio < m_ao.m_prio)); - - // put the thread into AO registry in place of the mutex - QActive::registry_[m_ao.m_prio] = thr; - } - } - else { // no threads are waiting for this mutex - m_ao.m_eQueue.m_nFree = 0U; // free up the nesting count - - // the mutex no longer held by any thread - m_ao.m_osObject = nullptr; - m_ao.m_eQueue.m_head = 0U; - m_ao.m_eQueue.m_tail = 0U; - - if (m_ao.m_prio != 0U) { // prio.-ceiling protocol used? - // the AO priority must be in range - Q_ASSERT_INCRIT(440, m_ao.m_prio < QF_MAX_ACTIVE); - - // put the mutex back at the original mutex slot - QActive::registry_[m_ao.m_prio] = &m_ao; - } - } - - // schedule the next thread if multitasking started - if (QXK_sched_() != 0U) { // activation needed? - QXK_activate_(); // synchronously activate basic-thred(s) - } - } - else { // releasing one level of nested mutex lock - // unlock one level - m_ao.m_eQueue.m_nFree = m_ao.m_eQueue.m_nFree - 1U; - - QS_BEGIN_PRE_(QS_MTX_UNLOCK_ATTEMPT, curr->m_prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this mutex - QS_U8_PRE_(static_cast(m_ao.m_eQueue.m_head)); - QS_U8_PRE_(static_cast(m_ao.m_eQueue.m_nFree)); - QS_END_PRE_() - } - QF_MEM_APP(); - QF_CRIT_EXIT(); -} - -} // namespace QP -//$enddef${QXK::QXMutex} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/qxk/qxk_sema.cpp b/src/qxk/qxk_sema.cpp deleted file mode 100644 index 94641b41e..000000000 --- a/src/qxk/qxk_sema.cpp +++ /dev/null @@ -1,287 +0,0 @@ -//$file${src::qxk::qxk_sema.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// -// Model: qpcpp.qm -// File: ${src::qxk::qxk_sema.cpp} -// -// This code has been generated by QM 6.2.0 . -// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. -// -// This code is covered by the following QP license: -// License # : LicenseRef-QL-dual -// Issued to : Any user of the QP/C++ real-time embedded framework -// Framework(s) : qpcpp -// Support ends : 2025-12-31 -// License scope: -// -// Copyright (C) 2005 Quantum Leaps, LLC . -// -// 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 -// -// 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: -// -// -// -//$endhead${src::qxk::qxk_sema.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -#define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // QS software tracing enabled? - #include "qs_port.hpp" // QS port - #include "qs_pkg.hpp" // QS facilities for pre-defined trace records -#else - #include "qs_dummy.hpp" // disable the QS software tracing -#endif // Q_SPY - -// protection against including this source file in a wrong project -#ifndef QXK_HPP_ - #error "Source file included in a project NOT based on the QXK kernel" -#endif // QXK_HPP_ - -// unnamed namespace for local definitions with internal linkage -namespace { -Q_DEFINE_THIS_MODULE("qxk_sema") -} // unnamed namespace - -//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// Check for the minimum required QP version -#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U)) -#error qpcpp version 7.3.0 or higher required -#endif -//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//$define${QXK::QXSemaphore} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { - -//${QXK::QXSemaphore} ........................................................ - -//${QXK::QXSemaphore::init} .................................................. -void QXSemaphore::init( - std::uint_fast8_t const count, - std::uint_fast8_t const max_count) noexcept -{ - QF_CRIT_STAT - QF_CRIT_ENTRY(); - QF_MEM_SYS(); - - Q_REQUIRE_INCRIT(100, (count <= max_count) - && (0U < max_count) && (max_count <= 0xFFU)); - - m_count = static_cast(count); - m_max_count = static_cast(max_count); - m_waitSet.setEmpty(); - - QF_MEM_APP(); - QF_CRIT_EXIT(); -} - -//${QXK::QXSemaphore::wait} .................................................. -bool QXSemaphore::wait(QTimeEvtCtr const nTicks) noexcept { - QF_CRIT_STAT - QF_CRIT_ENTRY(); - QF_MEM_SYS(); - - QXThread * const curr = QXK_PTR_CAST_(QXThread*, QXK_priv_.curr); - - // precondition, this function: - // - must NOT be called from an ISR; - // - the semaphore must be initialized - // - be called from an extended thread; - // - the thread must NOT be already blocked on any object. - Q_REQUIRE_INCRIT(200, (!QXK_ISR_CONTEXT_()) - && (m_max_count > 0U) - && (curr != nullptr) - && (curr->m_temp.obj == nullptr)); - // - the thread must NOT be holding a scheduler lock. - Q_REQUIRE_INCRIT(201, QXK_priv_.lockHolder != curr->m_prio); - - bool taken = true; // assume that the semaphore will be signaled - if (m_count > 0U) { - m_count = m_count - 1U; // semaphore taken: decrement the count - - QS_BEGIN_PRE_(QS_SEM_TAKE, curr->m_prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this semaphore - QS_2U8_PRE_(curr->m_prio, m_count); - QS_END_PRE_() - } - else { // semaphore not available -- BLOCK the thread - std::uint_fast8_t const p = - static_cast(curr->m_prio); - // remove the curr prio from the ready set (will block) - // and insert to the waiting set on this semaphore - QXK_priv_.readySet.remove(p); - #ifndef Q_UNSAFE - QXK_priv_.readySet.update_(&QXK_priv_.readySet_dis); - #endif - m_waitSet.insert(p); - - // remember the blocking object (this semaphore) - curr->m_temp.obj = QXK_PTR_CAST_(QMState*, this); - curr->teArm_(static_cast(QXK::TIMEOUT_SIG), nTicks); - - QS_BEGIN_PRE_(QS_SEM_BLOCK, curr->m_prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this semaphore - QS_2U8_PRE_(curr->m_prio, m_count); - QS_END_PRE_() - - // schedule the next thread if multitasking started - static_cast(QXK_sched_()); // schedule other threads - - QF_MEM_APP(); - QF_CRIT_EXIT(); - QF_CRIT_EXIT_NOP(); // BLOCK here !!! - - QF_CRIT_ENTRY(); // AFTER unblocking... - QF_MEM_SYS(); - - // the blocking object must be this semaphore - Q_ASSERT_INCRIT(240, curr->m_temp.obj - == QXK_PTR_CAST_(QMState*, this)); - - // did the blocking time-out? (signal of zero means that it did) - if (curr->m_timeEvt.sig == 0U) { - if (m_waitSet.hasElement(p)) { // still waiting? - m_waitSet.remove(p); // remove unblocked thread - taken = false; // the semaphore was NOT taken - } - } - else { // blocking did NOT time out - // the thread must NOT be waiting on this semaphore - Q_ASSERT_INCRIT(250, !m_waitSet.hasElement(p)); - } - curr->m_temp.obj = nullptr; // clear blocking obj. - } - QF_MEM_APP(); - QF_CRIT_EXIT(); - - return taken; -} - -//${QXK::QXSemaphore::tryWait} ............................................... -bool QXSemaphore::tryWait() noexcept { - QF_CRIT_STAT - QF_CRIT_ENTRY(); - QF_MEM_SYS(); - - // precondition: - // - the semaphore must be initialized - Q_REQUIRE_INCRIT(300, m_max_count > 0U); - - #ifdef Q_SPY - QActive const * const curr = QXK_PTR_CAST_(QActive*, QXK_priv_.curr); - #endif // Q_SPY - - bool taken; - // is the semaphore available? - if (m_count > 0U) { - m_count = m_count - 1U; // semaphore signaled: decrement - taken = true; - - QS_BEGIN_PRE_(QS_SEM_TAKE, curr->m_prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this semaphore - QS_2U8_PRE_(curr->m_prio, m_count); - QS_END_PRE_() - } - else { // the semaphore is NOT available (would block) - taken = false; - - QS_BEGIN_PRE_(QS_SEM_BLOCK_ATTEMPT, curr->m_prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this semaphore - QS_2U8_PRE_(curr->m_prio, m_count); - QS_END_PRE_() - } - QF_MEM_APP(); - QF_CRIT_EXIT(); - - return taken; -} - -//${QXK::QXSemaphore::signal} ................................................ -bool QXSemaphore::signal() noexcept { - bool signaled = true; // assume that the semaphore will be signaled - - QF_CRIT_STAT - QF_CRIT_ENTRY(); - QF_MEM_SYS(); - - // precondition: - // - the semaphore must be initialized - Q_REQUIRE_INCRIT(400, m_max_count > 0U); - - // any threads blocked on this semaphore? - if (m_waitSet.notEmpty()) { - // find the highest-prio. thread waiting on this semaphore - std::uint_fast8_t const p = m_waitSet.findMax(); - QXThread * const thr = - QXK_PTR_CAST_(QXThread*, QActive::registry_[p]); - - // assert that the thread: - // - must be registered in QF; - // - must be extended; and - // - must be blocked on this semaphore; - Q_ASSERT_INCRIT(410, (thr != nullptr) - && (thr->m_osObject != nullptr) - && (thr->m_temp.obj - == QXK_PTR_CAST_(QMState*, this))); - - // disarm the internal time event - static_cast(thr->teDisarm_()); - - // make the thread ready to run and remove from the wait-list - QXK_priv_.readySet.insert(p); - #ifndef Q_UNSAFE - QXK_priv_.readySet.update_(&QXK_priv_.readySet_dis); - #endif - m_waitSet.remove(p); - - QS_BEGIN_PRE_(QS_SEM_TAKE, thr->m_prio) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this semaphore - QS_2U8_PRE_(thr->m_prio, m_count); - QS_END_PRE_() - - if (!QXK_ISR_CONTEXT_()) { // not inside ISR? - static_cast(QXK_sched_()); // schedule other threads - } - } - else if (m_count < m_max_count) { - m_count = m_count + 1U; // semaphore signaled: increment - - QS_BEGIN_PRE_(QS_SEM_SIGNAL, 0U) - QS_TIME_PRE_(); // timestamp - QS_OBJ_PRE_(this); // this semaphore - QS_2U8_PRE_(0U, m_count); - QS_END_PRE_() - } - else { - signaled = false; // semaphore NOT signaled - } - QF_MEM_APP(); - QF_CRIT_EXIT(); - - return signaled; -} - -} // namespace QP -//$enddef${QXK::QXSemaphore} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/qxk/qxk_xthr.cpp b/src/qxk/qxk_xthr.cpp deleted file mode 100644 index a8e0a5336..000000000 --- a/src/qxk/qxk_xthr.cpp +++ /dev/null @@ -1,374 +0,0 @@ -//$file${src::qxk::qxk_xthr.cpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// -// Model: qpcpp.qm -// File: ${src::qxk::qxk_xthr.cpp} -// -// This code has been generated by QM 6.2.0 . -// DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. -// -// This code is covered by the following QP license: -// License # : LicenseRef-QL-dual -// Issued to : Any user of the QP/C++ real-time embedded framework -// Framework(s) : qpcpp -// Support ends : 2025-12-31 -// License scope: -// -// Copyright (C) 2005 Quantum Leaps, LLC . -// -// 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 -// -// 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: -// -// -// -//$endhead${src::qxk::qxk_xthr.cpp} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -#define QP_IMPL // this is QP implementation -#include "qp_port.hpp" // QP port -#include "qp_pkg.hpp" // QP package-scope interface -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY // QS software tracing enabled? - #include "qs_port.hpp" // QS port - #include "qs_pkg.hpp" // QS facilities for pre-defined trace records -#else - #include "qs_dummy.hpp" // disable the QS software tracing -#endif // Q_SPY - -// protection against including this source file in a wrong project -#ifndef QXK_HPP_ - #error "Source file included in a project NOT based on the QXK kernel" -#endif // QXK_HPP_ - -// unnamed namespace for local definitions with internal linkage -namespace { -Q_DEFINE_THIS_MODULE("qxk_xthr") -} // unnamed namespace - -//$skip${QP_VERSION} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -// Check for the minimum required QP version -#if (QP_VERSION < 730U) || (QP_VERSION != ((QP_RELEASE^4294967295U)%0x2710U)) -#error qpcpp version 7.3.0 or higher required -#endif -//$endskip${QP_VERSION} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -//$define${QXK::QXThread} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -namespace QP { - -//${QXK::QXThread} ........................................................... - -//${QXK::QXThread::QXThread} ................................................. -QXThread::QXThread( - QXThreadHandler const handler, - std::uint_fast8_t const tickRate) noexcept - : QActive(Q_STATE_CAST(handler)), - m_timeEvt(this, static_cast(QXK::DELAY_SIG), tickRate) -{ - m_state.act = nullptr; // mark as extended thread -} - -//${QXK::QXThread::init} ..................................................... -void QXThread::init( - void const * const e, - std::uint_fast8_t const qsId) -{ - Q_UNUSED_PAR(e); - Q_UNUSED_PAR(qsId); - Q_ERROR_INCRIT(110); -} - -//${QXK::QXThread::dispatch} ................................................. -void QXThread::dispatch( - QEvt const * const e, - std::uint_fast8_t const qsId) -{ - Q_UNUSED_PAR(e); - Q_UNUSED_PAR(qsId); - Q_ERROR_INCRIT(120); -} - -//${QXK::QXThread::delay} .................................................... -bool QXThread::delay(QTimeEvtCtr const nTicks) noexcept { - QF_CRIT_STAT - QF_CRIT_ENTRY(); - QF_MEM_SYS(); - - QXThread * const thr = QXK_PTR_CAST_(QXThread*, QXK_priv_.curr); - - // precondition, this function: - // - must NOT be called from an ISR; - // - number of ticks cannot be zero - // - be called from an extended thread; - // - the thread must NOT be already blocked on any object. - Q_REQUIRE_INCRIT(800, (!QXK_ISR_CONTEXT_()) - && (nTicks != 0U) - && (thr != nullptr) - && (thr->m_temp.obj == nullptr)); - // - the thread must NOT be holding a scheduler lock. - Q_REQUIRE_INCRIT(801, QXK_priv_.lockHolder != thr->m_prio); - - // remember the blocking object - thr->m_temp.obj = QXK_PTR_CAST_(QMState const*, &thr->m_timeEvt); - thr->teArm_(static_cast(QXK::DELAY_SIG), nTicks); - thr->block_(); - - QF_MEM_APP(); - QF_CRIT_EXIT(); - QF_CRIT_EXIT_NOP(); // BLOCK here - - // after unblocking... - QF_CRIT_ENTRY(); - QF_MEM_SYS(); - - // the blocking object must be the time event - Q_ASSERT_INCRIT(890, thr->m_temp.obj - == QXK_PTR_CAST_(QMState*, &thr->m_timeEvt)); - thr->m_temp.obj = nullptr; // clear - - QF_MEM_APP(); - QF_CRIT_EXIT(); - - // signal of zero means that the time event was posted without - // being canceled. - return (thr->m_timeEvt.sig == 0U); -} - -//${QXK::QXThread::delayCancel} .............................................. -bool QXThread::delayCancel() noexcept { - QF_CRIT_STAT - QF_CRIT_ENTRY(); - QF_MEM_SYS(); - - bool wasArmed; - if (m_temp.obj == QXK_PTR_CAST_(QMState*, &m_timeEvt)) { - wasArmed = teDisarm_(); - unblock_(); - } - else { - wasArmed = false; - } - QF_MEM_APP(); - QF_CRIT_EXIT(); - - return wasArmed; -} - -//${QXK::QXThread::queueGet} ................................................. -QEvt const * QXThread::queueGet(QTimeEvtCtr const nTicks) noexcept { - QF_CRIT_STAT - QF_CRIT_ENTRY(); - QF_MEM_SYS(); - - QXThread * const thr = QXTHREAD_CAST_(QXK_priv_.curr); - - // precondition, this function: - // - must NOT be called from an ISR; - // - be called from an extended thread; - // - the thread must NOT be already blocked on any object. - Q_REQUIRE_INCRIT(500, (!QXK_ISR_CONTEXT_()) - && (thr != nullptr) - && (thr->m_temp.obj == nullptr)); - // - the thread must NOT be holding a scheduler lock. - Q_REQUIRE_INCRIT(501, QXK_priv_.lockHolder != thr->m_prio); - - // is the queue empty? - if (thr->m_eQueue.m_frontEvt == nullptr) { - - // remember the blocking object (the thread's queue) - thr->m_temp.obj = QXK_PTR_CAST_(QMState*, &thr->m_eQueue); - - thr->teArm_(static_cast(QXK::TIMEOUT_SIG), nTicks); - QXK_priv_.readySet.remove( - static_cast(thr->m_prio)); - #ifndef Q_UNSAFE - QXK_priv_.readySet.update_(&QXK_priv_.readySet_dis); - #endif - - static_cast(QXK_sched_()); // synchronous scheduling - - QF_MEM_APP(); - QF_CRIT_EXIT(); - QF_CRIT_EXIT_NOP(); // BLOCK here - - // after unblocking... - QF_CRIT_ENTRY(); - QF_MEM_SYS(); - - // the blocking object must be this queue - Q_ASSERT_INCRIT(510, thr->m_temp.obj == - QXK_PTR_CAST_(QMState *, &thr->m_eQueue)); - thr->m_temp.obj = nullptr; // clear - } - - // is the queue not empty? - QEvt const *e; - if (thr->m_eQueue.m_frontEvt != nullptr) { - e = thr->m_eQueue.m_frontEvt; // remove from the front - QEQueueCtr const nFree = thr->m_eQueue.m_nFree + 1U; - thr->m_eQueue.m_nFree = nFree; // update the # free - - // any events in the ring buffer? - if (nFree <= thr->m_eQueue.m_end) { - - // remove event from the tail - thr->m_eQueue.m_frontEvt = - thr->m_eQueue.m_ring[thr->m_eQueue.m_tail]; - if (thr->m_eQueue.m_tail == 0U) { - thr->m_eQueue.m_tail = thr->m_eQueue.m_end; // wrap - } - // advance the tail (counter clockwise) - thr->m_eQueue.m_tail = (thr->m_eQueue.m_tail - 1U); - - QS_BEGIN_PRE_(QS_QF_ACTIVE_GET, thr->m_prio) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of this event - QS_OBJ_PRE_(&thr); // this active object - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_EQC_PRE_(nFree); // # free entries - QS_END_PRE_() - } - else { - thr->m_eQueue.m_frontEvt = nullptr; // empty queue - - // all entries in the queue must be free (+1 for fronEvt) - Q_ASSERT_INCRIT(520, nFree == (thr->m_eQueue.m_end + 1U)); - - QS_BEGIN_PRE_(QS_QF_ACTIVE_GET_LAST, thr->m_prio) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of this event - QS_OBJ_PRE_(&thr); // this active object - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // poolNum & refCtr - QS_END_PRE_() - } - } - else { // the queue is still empty -- the timeout must have fired - e = nullptr; - } - QF_MEM_APP(); - QF_CRIT_EXIT(); - - return e; -} - -//${QXK::QXThread::block_} ................................................... -void QXThread::block_() const noexcept { - // NOTE: must be called IN a critical section - - Q_REQUIRE_INCRIT(600, (QXK_priv_.lockHolder != m_prio)); - - QXK_priv_.readySet.remove(static_cast(m_prio)); - #ifndef Q_UNSAFE - QXK_priv_.readySet.update_(&QXK_priv_.readySet_dis); - #endif - - static_cast(QXK_sched_()); // schedule other threads -} - -//${QXK::QXThread::unblock_} ................................................. -void QXThread::unblock_() const noexcept { - // NOTE: must be called IN a critical section - - QXK_priv_.readySet.insert(static_cast(m_prio)); - #ifndef Q_UNSAFE - QXK_priv_.readySet.update_(&QXK_priv_.readySet_dis); - #endif - - if ((!QXK_ISR_CONTEXT_()) // not inside ISR? - && (QActive::registry_[0] != nullptr)) // kernel started? - { - static_cast(QXK_sched_()); // schedule other threads - } -} - -//${QXK::QXThread::timeout_} ................................................. -void QXThread::timeout_(QActive * const act) { - // NOTE: must be called IN a critical section - - // the private time event is now disarmed and not in any queue, - // so it is safe to change its signal. The signal of 0 means - // that the time event has expired. - QXTHREAD_CAST_(act)->m_timeEvt.sig = 0U; - - QXTHREAD_CAST_(act)->unblock_(); -} - -//${QXK::QXThread::teArm_} ................................................... -void QXThread::teArm_( - enum_t const sig, - QTimeEvtCtr const nTicks) noexcept -{ - // NOTE: must be called IN a critical section - - // precondition: - // - the time event must be unused - Q_REQUIRE_INCRIT(700, m_timeEvt.m_ctr == 0U); - - m_timeEvt.sig = static_cast(sig); - - if (nTicks != QXTHREAD_NO_TIMEOUT) { - m_timeEvt.m_ctr = static_cast(nTicks); - m_timeEvt.m_interval = 0U; - - // is the time event unlinked? - // NOTE: For the duration of a single clock tick of the specified tick - // rate a time event can be disarmed and yet still linked in the list, - // because un-linking is performed exclusively in QTimeEvt::tickX(). - if (static_cast(m_timeEvt.refCtr_ & TE_IS_LINKED) == 0U) - { - std::uint_fast8_t const tickRate = - static_cast(m_timeEvt.refCtr_); - Q_ASSERT_INCRIT(710, tickRate < QF_MAX_TICK_RATE); - - // mark as linked - m_timeEvt.refCtr_ = static_cast( - m_timeEvt.refCtr_ | TE_IS_LINKED); - - // The time event is initially inserted into the separate - // "freshly armed" list based on timeEvtHead_[tickRate].act. - // Only later, inside QTimeEvt::tick(), the "freshly armed" - // list is appended to the main list of armed time events based on - // timeEvtHead_[tickRate].next. Again, this is to keep any - // changes to the main list exclusively inside QTimeEvt::tick(). - m_timeEvt.m_next - = QXK_PTR_CAST_(QTimeEvt*, - QTimeEvt::timeEvtHead_[tickRate].m_act); - QTimeEvt::timeEvtHead_[tickRate].m_act = &m_timeEvt; - } - } -} - -//${QXK::QXThread::teDisarm_} ................................................ -bool QXThread::teDisarm_() noexcept { - // NOTE: must be called IN a critical section - - bool wasArmed; - // is the time evt running? - if (m_timeEvt.m_ctr != 0U) { - wasArmed = true; - // schedule removal from list - m_timeEvt.m_ctr = 0U; - } - // the time event was already automatically disarmed - else { - wasArmed = false; - } - return wasArmed; -} - -} // namespace QP -//$enddef${QXK::QXThread} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/test/et/et.c b/test/et/et.c deleted file mode 100644 index 6732b745d..000000000 --- a/test/et/et.c +++ /dev/null @@ -1,174 +0,0 @@ -//============================================================================ -// ET: embedded test (super-simple embedded testing framework) -// GitHub: https://github.com/QuantumLeaps/Embedded-Test -// -// Q u a n t u m L e a P s -// ------------------------ -// Modern Embedded Software -// -// Copyright (C) 2005 Quantum Leaps, . -// -// SPDX-License-Identifier: MIT -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. -//============================================================================ -#include "et.h" // ET: embedded test - -//.......................................................................... -static void print_str(char const *str); -static void print_dec(unsigned const num); -static void print_summary(unsigned ok); -static void test_end(void); -static int str_cmp(char const *str1, char const *str2); - -static unsigned l_test_count; -static unsigned l_skip_count; -static unsigned l_skip_last; - -static char const *l_expect_assert_module; -static int l_expect_assert_label; - -//.......................................................................... -int main(int argc, char *argv[]) { - ET_onInit(argc, argv); - - print_str("\nET embedded test " ET_VERSION - ", https://github.com/QuantumLeaps/ET\n"); - print_str("---------------- group: "); - print_str(ET_group_); - print_str(" -----------------\n"); - - ET_run_(); - - test_end(); - print_summary(1U); - - ET_onExit(0); // success -} - -//.......................................................................... -int ET_test_(char const *title, int skip) { - test_end(); - ++l_test_count; - ET_onPrintChar('['); - print_dec(l_test_count); - print_str("] \""); - print_str(title); - print_str("\" "); - if (skip) { - ++l_skip_count; - } - else { - setup(); - ET_onPrintChar('.'); - } - l_skip_last = skip; - return skip == 0; -} -//.......................................................................... -static void test_end(void) { - if (l_expect_assert_module != (char const *)0) { - ET_fail("Expected Assertion didn't fire", - l_expect_assert_module, l_expect_assert_label); - } - else if (l_test_count > 0) { - if (l_skip_last) { - print_str(" SKIPPED\n"); - l_skip_last = 0; - } - else { - teardown(); - print_str(". PASSED\n"); - } - } -} -//.......................................................................... -void ET_fail(char const *cond, char const *group, int line) { - print_str(" FAILED\n--> "); - print_str(group); - ET_onPrintChar(':'); - print_dec(line); - ET_onPrintChar(' '); - print_str(cond); - ET_onPrintChar('\n'); - print_summary(0U); - - ET_onExit(-1); // failure -} -//.......................................................................... -void ET_expect_assert(char const *module, int label) { - l_expect_assert_module = module; - l_expect_assert_label = label; -} -//.......................................................................... -void ET_verify_assert_(char const *module, int label) { - if ((l_expect_assert_label == label) - && (str_cmp(module, l_expect_assert_module) == 0)) - { - l_expect_assert_module = (char const *)0; - test_end(); - print_str("Assertion (expected) --> Exiting\n"); - print_summary(1U); - - ET_onExit(0); // success - } - else { - ET_fail("Unexpected assertion", module, label); - } -} - -//.......................................................................... -static void print_summary(unsigned ok) { - print_str("------------ "); - print_dec(l_test_count); - print_str(" test(s), "); - print_dec(l_skip_count); - print_str(" skipped -------------\n"); - print_str(ok ? "OK\n" : "FAILED\n"); -} -//.......................................................................... -static void print_str(char const *str) { - for (; *str != '\0'; ++str) { - ET_onPrintChar(*str); - } -} - -//.......................................................................... -static void print_dec(unsigned const num) { - // find power of 10 of the first decimal digit of the number - unsigned pwr10 = 1U; - for (; num > (pwr10 * 9U); pwr10 *= 10U) { - } - // print the decimal digits of the number... - do { - ET_onPrintChar((char)('0' + ((num / pwr10) % 10U))); - pwr10 /= 10U; - } while (pwr10 != 0U); -} - -//.......................................................................... -static int str_cmp(char const *str1, char const *str2) { - while (*str1 == *str2++) { - if (*str1++ == '\0') { - return 0; - } - } - --str2; - return *(unsigned char *)str1 - *(unsigned char *)str2; -} diff --git a/test/et/et.h b/test/et/et.h deleted file mode 100644 index bed2eeeda..000000000 --- a/test/et/et.h +++ /dev/null @@ -1,92 +0,0 @@ -//============================================================================ -// ET: embedded test (super-simple embedded testing framework) -// GitHub: https://github.com/QuantumLeaps/Embedded-Test -// -// Q u a n t u m L e a P s -// ------------------------ -// Modern Embedded Software -// -// Copyright (C) 2005 Quantum Leaps, . -// -// SPDX-License-Identifier: MIT -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. -//============================================================================ -#ifndef ET_H_ -#define ET_H_ - -// Embedded Test (ET) version -#define ET_VERSION "2.0.0" - -//! macro to define a test group -#define TEST_GROUP(name_) \ - char const ET_group_[] = name_; \ - void ET_run_(void) - -// macro to start a new test -#define TEST(title_) \ - if (ET_test_(title_, 0)) - -// macro to skip a test -#define SKIP_TEST(title_) \ - if (ET_test_(title_, 1)) - -//! macro to verify a test expectation -#define VERIFY(cond_) \ - ((cond_) ? (void)0 : ET_fail(#cond_, &ET_group_[0], __LINE__)) - -#define VERIFY_ASSERT(module_, label_) \ - ET_verify_assert_((module_), (label_)) - -//! macro to force a failure of a test -#define FAIL(note_) \ - (ET_fail(note_, &ET_group_[0], __LINE__)) - -#ifndef ARRAY_NELEM -//! convenience macro to provide the number of elements in the array a_ -#define ARRAY_NELEM(a_) (sizeof(a_) / sizeof((a_)[0])) -#endif // ARRAY_NELEM - -#ifdef __cplusplus -extern "C" { -#endif - -void setup(void); //!< called right before each test -void teardown(void); //!< called right after each test - -// callback functions to be implemented in the ET board support packages -void ET_onInit(int argc, char *argv[]); -void ET_onPrintChar(char const ch); -void ET_onExit(int err); - -// public helpers -void ET_fail(char const *cond, char const *group, int line); -void ET_expect_assert(char const *module, int label); -void ET_verify_assert_(char const *module, int label); - -// private helpers -void ET_run_(void); -int ET_test_(char const *title, int skip); -extern char const ET_group_[]; - -#ifdef __cplusplus -} -#endif - -#endif // ET_H_ diff --git a/test/et/et_host.c b/test/et/et_host.c deleted file mode 100644 index 5b6af46f0..000000000 --- a/test/et/et_host.c +++ /dev/null @@ -1,48 +0,0 @@ -//============================================================================ -// Embedded Test (ET) implementation for host computers (Windows, Linux, macOS) -// GitHub: https://github.com/QuantumLeaps/Embedded-Test -// -// Q u a n t u m L e a P s -// ------------------------ -// Modern Embedded Software -// -// Copyright (C) 2005 Quantum Leaps, . -// -// SPDX-License-Identifier: MIT -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. -//============================================================================ -#include "et.h" // ET: embedded test - -#include // for fputc() and stdout -#include // for exit() - -//.......................................................................... -void ET_onInit(int argc, char *argv[]) { - (void)argc; - (void)argv; -} -//.......................................................................... -void ET_onPrintChar(char const ch) { - fputc(ch, stdout); -} -//.......................................................................... -void ET_onExit(int err) { - exit(err); -} diff --git a/test/qk/README.txt b/test/qk/README.txt deleted file mode 100644 index 2476f0642..000000000 --- a/test/qk/README.txt +++ /dev/null @@ -1,13 +0,0 @@ -This directory contains tests of the QK kernel. -These are SYSTEM tests, where QP is not stubbed-out, but -rather the actual QP code is used instead. - -NOTE: -The tests run only on embedded targets and do NOT -run on the host computer. - -NOTE: -To avoid stubbing-out the QP framework, the tests -define Q_UTEST=0 - - diff --git a/test/qk/test_sched/bsp.hpp b/test/qk/test_sched/bsp.hpp deleted file mode 100644 index bf7b2d407..000000000 --- a/test/qk/test_sched/bsp.hpp +++ /dev/null @@ -1,66 +0,0 @@ -//============================================================================ -// Product: BSP for system-testing QXK -// Last updated for version 7.3.0 -// Last updated on 2023-09-06 -// -// 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: -// -// -//============================================================================ -#ifndef BSP_HPP_ -#define BSP_HPP_ - -namespace BSP { - -void init(void); -void terminate(int16_t const result); - -// for testing... -void trace(QP::QActive const *thr, char const *msg); -void wait4PB1(void); -void ledOn(void); -void ledOff(void); -void trigISR(void); - -uint32_t romRead(int32_t offset, uint32_t fromEnd); -void romWrite(int32_t offset, uint32_t fromEnd, uint32_t value); - -uint32_t ramRead(int32_t offset, uint32_t fromEnd); -void ramWrite(int32_t offset, uint32_t fromEnd, uint32_t value); - -} // namespace BSP - -enum TestSignals { - TEST0_SIG = QP::Q_USER_SIG, - TEST1_SIG, - TEST2_SIG, - TEST3_SIG, - MAX_PUB_SIG, // the last published signal - - MAX_SIG // the last signal -}; - -#endif // BSP_HPP_ - diff --git a/test/qk/test_sched/bsp_efm32pg1b.cpp b/test/qk/test_sched/bsp_efm32pg1b.cpp deleted file mode 100644 index 412d6dc7d..000000000 --- a/test/qk/test_sched/bsp_efm32pg1b.cpp +++ /dev/null @@ -1,375 +0,0 @@ -//============================================================================ -// Product: BSP for system-testing of QK kernel, EFM32-SLSTK3401A board -// Last updated for version 7.2.0 -// Last updated on 2022-12-13 -// -// Q u a n t u m L e a P s -// ------------------------ -// Modern Embedded Software -// -// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -// -// This program is open source software: you can redistribute it and/or -// modify it under the terms of the GNU General Public License as published -// by the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Alternatively, this program may be distributed and modified under the -// terms of Quantum Leaps commercial licenses, which expressly supersede -// the GNU General Public License and are specifically designed for -// licensees interested in retaining the proprietary status of their code. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -// Contact information: -// -// -//============================================================================ -#include "qpcpp.hpp" -#include "bsp.hpp" - -#include "em_device.h" // the device specific header (SiLabs) -#include "em_cmu.h" // Clock Management Unit (SiLabs) -#include "em_gpio.h" // GPIO (SiLabs) -#include "em_usart.h" // USART (SiLabs) -// add other drivers if necessary... - -namespace { - -Q_DEFINE_THIS_FILE - -// Local-scope objects ------------------------------------------------------- -#define LED_PORT gpioPortF -#define LED0_PIN 4 -#define LED1_PIN 5 - -#define PB_PORT gpioPortF -#define PB0_PIN 6 -#define PB1_PIN 7 - -#ifdef Q_SPY - - // QSpy source IDs - static QP::QSpyId const l_SysTick_Handler = { 100U }; - static QP::QSpyId const l_test_ISR = { 101U }; - - enum AppRecords { // application-specific trace records - CONTEXT_SW = QP::QS_USER1, - TRACE_MSG - }; - -#endif - -} // unnamed namespace - -// ISRs used in this project ================================================= -extern "C" { - -//............................................................................ -void SysTick_Handler(void); // prototype -void SysTick_Handler(void) { - QK_ISR_ENTRY(); // inform QK about entering an ISR - - QP::QTimeEvt::TICK_X(0U, &l_SysTick_Handler); - //the_Ticker0->TRIG(&l_SysTick_Handler); - - QK_ISR_EXIT(); // inform QK about exiting an ISR -} -//............................................................................ -void GPIO_EVEN_IRQHandler(void); // prototype -void GPIO_EVEN_IRQHandler(void) { - QK_ISR_ENTRY(); // inform QK about entering an ISR - - // for testing... - static QP::QEvt const t1(TEST1_SIG); - QP::QF::PUBLISH(&t1, &l_test_ISR); - - QK_ISR_EXIT(); // inform QK about exiting an ISR -} - -} // extern "C" - -// BSP functions ============================================================= - -// MPU setup for EFM32PG1B200F256GM48 MCU -static void EFM32PG182_MPU_setup(void) { - // The following MPU configuration contains the general EFM32PG1 memory - // map described in the EFM32PG1 Data Sheet Figure 3.2. EFM32PG1 Memory Map - // - // Please note that the actual STM32 MCUs provide much less Flash and SRAM - // than the maximums configured here. This means that actual MCUs have - // unmapped memory regions (e.g., beyond the actual SRAM). Attempts to - // access these regions causes the HardFault exception, which is the - // desired behavior. - // - static struct { - uint32_t rbar; - uint32_t rasr; - } const mpu_setup[] = { - - { // region #0: Flash: base=0x0000'0000, size=512M=2^(28+1) - 0x00000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 0U), // region #0 - (28U << MPU_RASR_SIZE_Pos) // 2^(18+1) region - | (0x6U << MPU_RASR_AP_Pos) // PA:ro/UA:ro - | (1U << MPU_RASR_C_Pos) // C=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - { // region #1: SRAM: base=0x2000'0000, size=512M=2^(28+1) - 0x20000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 1U), // region #1 - (28U << MPU_RASR_SIZE_Pos) // 2^(28+1) region - | (0x3U << MPU_RASR_AP_Pos) // PA:rw/UA:rw - | (1U << MPU_RASR_XN_Pos) // XN=1 - | (1U << MPU_RASR_S_Pos) // S=1 - | (1U << MPU_RASR_C_Pos) // C=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - // region #3: (not configured) - { MPU_RBAR_VALID_Msk | (MPU_RBAR_REGION_Msk & 2U), 0U }, - - { // region #3: Peripherals: base=0x4000'0000, size=512M=2^(28+1) - 0x40000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 3U), // region #3 - (28U << MPU_RASR_SIZE_Pos) // 2^(28+1) region - | (0x3U << MPU_RASR_AP_Pos) // PA:rw/UA:rw - | (1U << MPU_RASR_XN_Pos) // XN=1 - | (1U << MPU_RASR_S_Pos) // S=1 - | (1U << MPU_RASR_B_Pos) // B=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - { // region #4: Priv. Periph: base=0xE000'0000, size=512M=2^(28+1) - 0xE0000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 4U), // region #4 - (28U << MPU_RASR_SIZE_Pos) // 2^(28+1) region - | (0x3U << MPU_RASR_AP_Pos) // PA:rw/UA:rw - | (1U << MPU_RASR_XN_Pos) // XN=1 - | (1U << MPU_RASR_S_Pos) // S=1 - | (1U << MPU_RASR_B_Pos) // B=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - { // region #5: Ext RAM: base=0x6000'0000, size=1G=2^(29+1) - 0x60000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 5U), // region #5 - (29U << MPU_RASR_SIZE_Pos) // 2^(28+1) region - | (0x3U << MPU_RASR_AP_Pos) // PA:rw/UA:rw - | (1U << MPU_RASR_XN_Pos) // XN=1 - | (1U << MPU_RASR_S_Pos) // S=1 - | (1U << MPU_RASR_B_Pos) // B=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - { // region #6: Ext Dev: base=0xA000'0000, size=1G=2^(29+1) - 0xA0000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 6U), // region #6 - (29U << MPU_RASR_SIZE_Pos) // 2^(28+1) region - | (0x3U << MPU_RASR_AP_Pos) // PA:rw/UA:rw - | (1U << MPU_RASR_XN_Pos) // XN=1 - | (1U << MPU_RASR_S_Pos) // S=1 - | (1U << MPU_RASR_B_Pos) // B=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - { // region #7: NULL-pointer: base=0x000'0000, size=256B, NOTE0 - 0x00000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 7U), // region #7 - (7U << MPU_RASR_SIZE_Pos) // 2^(7+1)=256B region - | (0x0U << MPU_RASR_AP_Pos) // PA:na/UA:na - | (1U << MPU_RASR_XN_Pos) // XN=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - }; - - // enable the MemManage_Handler for MPU exception - SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; - - __DSB(); - MPU->CTRL = 0U; // disable the MPU - for (uint_fast8_t n = 0U; n < Q_DIM(mpu_setup); ++n) { - MPU->RBAR = mpu_setup[n].rbar; - MPU->RASR = mpu_setup[n].rasr; - } - MPU->CTRL = MPU_CTRL_ENABLE_Msk; // enable the MPU - __ISB(); - __DSB(); -} -//............................................................................ -void BSP::init(void) { - // setup the MPU... - EFM32PG182_MPU_setup(); - - // NOTE: SystemInit() already called from the startup code - // but SystemCoreClock needs to be updated - // - SystemCoreClockUpdate(); - - // NOTE: The VFP (hardware Floating Point) unit is configured by QK - - // enable clock for to the peripherals used by this application... - CMU_ClockEnable(cmuClock_HFPER, true); - CMU_ClockEnable(cmuClock_GPIO, true); - CMU_ClockEnable(cmuClock_HFPER, true); - CMU_ClockEnable(cmuClock_GPIO, true); - - // configure the LEDs - GPIO_PinModeSet(LED_PORT, LED0_PIN, gpioModePushPull, 0); - GPIO_PinModeSet(LED_PORT, LED1_PIN, gpioModePushPull, 0); - GPIO_PinOutClear(LED_PORT, LED0_PIN); - GPIO_PinOutClear(LED_PORT, LED1_PIN); - - // configure the Buttons - GPIO_PinModeSet(PB_PORT, PB0_PIN, gpioModeInputPull, 1); - GPIO_PinModeSet(PB_PORT, PB1_PIN, gpioModeInputPull, 1); - - // initialize the QS software tracing... - if (!QS_INIT(nullptr)) { // initialize the QS software tracing - Q_ERROR(); - } - QS_OBJ_DICTIONARY(&l_SysTick_Handler); - QS_OBJ_DICTIONARY(&l_test_ISR); - - QS_USR_DICTIONARY(CONTEXT_SW); - QS_USR_DICTIONARY(TRACE_MSG); -} -//............................................................................ -void BSP::terminate(int16_t result) { - Q_UNUSED_PAR(result); -} -//............................................................................ -void BSP::ledOn(void) { - GPIO->P[LED_PORT].DOUT = GPIO->P[LED_PORT].DOUT | (1U << LED1_PIN); -} -//............................................................................ -void BSP::ledOff(void) { - GPIO->P[LED_PORT].DOUT = GPIO->P[LED_PORT].DOUT & ~(1U << LED1_PIN); -} -//............................................................................ -void BSP::trigISR(void) { - NVIC_SetPendingIRQ(GPIO_EVEN_IRQn); -} -//............................................................................ -void BSP::trace(QP::QActive const *thr, char const *msg) { - QS_BEGIN_ID(TRACE_MSG, 0U) - QS_OBJ(thr); - QS_STR(msg); - QS_END() -} -//............................................................................ -uint32_t BSP::romRead(int32_t offset, uint32_t fromEnd) { - int32_t const rom_base = (fromEnd == 0U) - ? 0x100 // don't include the NULL-ptr region - : 0x40000 - 4; - return *(uint32_t volatile *)(rom_base + offset); -} -//............................................................................ -void BSP::romWrite(int32_t offset, uint32_t fromEnd, uint32_t value) { - int32_t const rom_base = (fromEnd == 0U) - ? 0x100 // don't include the NULL-ptr region - : 0x40000 - 4; - *(uint32_t volatile *)(rom_base + offset) = value; -} - -//............................................................................ -uint32_t BSP::ramRead(int32_t offset, uint32_t fromEnd) { - int32_t const ram_base = (fromEnd == 0U) - ? 0x20000000 - : 0x20008000 - 4; - return *(uint32_t volatile *)(ram_base + offset); -} -//............................................................................ -void BSP::ramWrite(int32_t offset, uint32_t fromEnd, uint32_t value) { - int32_t const ram_base = (fromEnd == 0U) - ? 0x20000000 - : 0x20008000 - 4; - *(uint32_t volatile *)(ram_base + offset) = value; -} - -// namespace QP ============================================================== -namespace QP { - -// QF callbacks -------------------------------------------------------------- -void QF::onStartup(void) { - // assign all priority bits for preemption-prio. and none to sub-prio. - NVIC_SetPriorityGrouping(0U); - - // set priorities of ALL ISRs used in the system - NVIC_SetPriority(USART0_RX_IRQn, 0U); // kernel UNAWARE interrupt - NVIC_SetPriority(GPIO_EVEN_IRQn, QF_AWARE_ISR_CMSIS_PRI + 0U); - NVIC_SetPriority(SysTick_IRQn, QF_AWARE_ISR_CMSIS_PRI + 1U); - // ... - - // enable IRQs... - NVIC_EnableIRQ(GPIO_EVEN_IRQn); -} -//............................................................................ -void QF::onCleanup(void) { -} -//............................................................................ -void QK::onIdle(void) { -#ifdef Q_SPY - QS::rxParse(); // parse all the received bytes - QS::doOutput(); -#elif defined NDEBUG - // Put the CPU and peripherals to the low-power mode. - // you might need to customize the clock management for your application, - // see the datasheet for your particular Cortex-M3 MCU. - // - __WFI(); // Wait-For-Interrupt -#endif -} - -// QS callbacks ============================================================== -//............................................................................ -void QTimeEvt::tick1_( - uint_fast8_t const tickRate, - void const * const sender) -{ - QF_INT_DISABLE(); - // TODO pend the SysTick - *Q_UINT2PTR_CAST(uint32_t, 0xE000ED04U) = (1U << 26U); - QF_INT_ENABLE(); -} - -//---------------------------------------------------------------------------- - -} // namespace QP - -extern "C" { -//............................................................................ -#ifdef QF_ON_CONTEXT_SW -// NOTE: the context-switch callback is called with interrupts DISABLED -void QF_onContextSw(QP::QActive *prev, QP::QActive *next) { - QS_BEGIN_INCRIT(CONTEXT_SW, 0U) // no critical section! - QS_OBJ(prev); - QS_OBJ(next); - QS_END_INCRIT() -} -#endif // QF_ON_CONTEXT_SW - -} // extern "C" - -//============================================================================ -// NOTE0: -// The MPU protection against NULL-pointer dereferencing sets up a no-access -// MPU region #7 around the NULL address (0x0). This works even though the -// Vector Table also resides at address 0x0. However, the *size* of the -// no-access region should not exceed the size of the Vector Table. In this -// case, the size is set to 2^(7+1)==256 bytes, which does not contain any -// data that the CPU would legitimately read with the LDR instruction. diff --git a/test/qk/test_sched/bsp_nucleo-c031c6.cpp b/test/qk/test_sched/bsp_nucleo-c031c6.cpp deleted file mode 100644 index 974491981..000000000 --- a/test/qk/test_sched/bsp_nucleo-c031c6.cpp +++ /dev/null @@ -1,362 +0,0 @@ -//============================================================================ -// Product: BSP for system-testing of QK kernel, NUCLEO-C031C6 board -// Last updated for version 7.3.0 -// Last updated on 2023-07-18 -// -// Q u a n t u m L e a P s -// ------------------------ -// Modern Embedded Software -// -// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -// -// This program is open source software: you can redistribute it and/or -// modify it under the terms of the GNU General Public License as published -// by the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Alternatively, this program may be distributed and modified under the -// terms of Quantum Leaps commercial licenses, which expressly supersede -// the GNU General Public License and are specifically designed for -// licensees interested in retaining the proprietary status of their code. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -// Contact information: -// -// -//============================================================================ -#include "qpcpp.hpp" -#include "bsp.hpp" - -#include "stm32c0xx.h" // CMSIS-compliant header file for the MCU used -// add other drivers if necessary... - -namespace { - -Q_DEFINE_THIS_FILE - -// Local-scope objects ----------------------------------------------------- -// LED pins available on the board (just one user LED LD4--Green on PA.5) -#define LD4_PIN 5U - -// Button pins available on the board (just one user Button B1 on PC.13) -#define B1_PIN 13U - -#ifdef Q_SPY - - // QSpy source IDs - static QP::QSpyId const l_SysTick_Handler = { 100U }; - static QP::QSpyId const l_test_ISR = { 101U }; - - enum AppRecords { // application-specific trace records - CONTEXT_SW = QP::QS_USER1, - TRACE_MSG - }; - -#endif - -} // unnamed namespace - -// ISRs used in this project ================================================= -extern "C" { - -//............................................................................ -void SysTick_Handler(void); // prototype -void SysTick_Handler(void) { - QK_ISR_ENTRY(); // inform QK about entering an ISR - - QP::QTimeEvt::TICK_X(0U, &l_SysTick_Handler); - //the_Ticker0->TRIG(&l_SysTick_Handler); - - QK_ISR_EXIT(); // inform QK about exiting an ISR -} -//............................................................................ -void EXTI0_1_IRQHandler(void); // prototype -void EXTI0_1_IRQHandler(void) { - QK_ISR_ENTRY(); // inform QK about entering an ISR - - // for testing... - static QP::QEvt const t1(TEST1_SIG); - QP::QF::PUBLISH(&t1, &l_test_ISR); - - QK_ISR_EXIT(); // inform QK about exiting an ISR -} - -} // extern "C" - -// BSP functions ============================================================= - -static void STM32C031C6_MPU_setup(void) { - // The following MPU configuration contains the general STM32 memory model - // as described in the ST AppNote AN4838 "Managing memory protection unit - // in STM32 MCUs", Figure 2. Cortex-M0+/M3/M4/M7 processor memory map. - // - // Please note that the actual STM32 MCUs provide much less Flash and SRAM - // than the maximums configured here. This means that actual MCUs have - // unmapped memory regions (e.g., beyond the actual SRAM). Attempts to - // access these regions causes the HardFault exception, which is the - // desired behavior. - // - static struct { - uint32_t rbar; - uint32_t rasr; - } const mpu_setup[] = { - - { // region #0: Flash: base=0x0000'0000, size=512M=2^(28+1) - 0x00000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 0U), // region #0 - (28U << MPU_RASR_SIZE_Pos) // 2^(18+1) region - | (0x6U << MPU_RASR_AP_Pos) // PA:ro/UA:ro - | (1U << MPU_RASR_C_Pos) // C=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - { // region #1: SRAM: base=0x2000'0000, size=512M=2^(28+1) - 0x20000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 1U), // region #1 - (28U << MPU_RASR_SIZE_Pos) // 2^(28+1) region - | (0x3U << MPU_RASR_AP_Pos) // PA:rw/UA:rw - | (1U << MPU_RASR_XN_Pos) // XN=1 - | (1U << MPU_RASR_S_Pos) // S=1 - | (1U << MPU_RASR_C_Pos) // C=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - // region #3: (not configured) - { MPU_RBAR_VALID_Msk | (MPU_RBAR_REGION_Msk & 2U), 0U }, - - { // region #3: Peripherals: base=0x4000'0000, size=512M=2^(28+1) - 0x40000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 3U), // region #3 - (28U << MPU_RASR_SIZE_Pos) // 2^(28+1) region - | (0x3U << MPU_RASR_AP_Pos) // PA:rw/UA:rw - | (1U << MPU_RASR_XN_Pos) // XN=1 - | (1U << MPU_RASR_S_Pos) // S=1 - | (1U << MPU_RASR_B_Pos) // B=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - { // region #4: Priv. Periph: base=0xE000'0000, size=512M=2^(28+1) - 0xE0000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 4U), // region #4 - (28U << MPU_RASR_SIZE_Pos) // 2^(28+1) region - | (0x3U << MPU_RASR_AP_Pos) // PA:rw/UA:rw - | (1U << MPU_RASR_XN_Pos) // XN=1 - | (1U << MPU_RASR_S_Pos) // S=1 - | (1U << MPU_RASR_B_Pos) // B=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - { // region #5: Ext RAM: base=0x6000'0000, size=1G=2^(29+1) - 0x60000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 5U), // region #5 - (29U << MPU_RASR_SIZE_Pos) // 2^(28+1) region - | (0x3U << MPU_RASR_AP_Pos) // PA:rw/UA:rw - | (1U << MPU_RASR_XN_Pos) // XN=1 - | (1U << MPU_RASR_S_Pos) // S=1 - | (1U << MPU_RASR_B_Pos) // B=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - { // region #6: Ext Dev: base=0xA000'0000, size=1G=2^(29+1) - 0xA0000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 6U), // region #6 - (29U << MPU_RASR_SIZE_Pos) // 2^(28+1) region - | (0x3U << MPU_RASR_AP_Pos) // PA:rw/UA:rw - | (1U << MPU_RASR_XN_Pos) // XN=1 - | (1U << MPU_RASR_S_Pos) // S=1 - | (1U << MPU_RASR_B_Pos) // B=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - { // region #7: NULL-pointer: base=0x000'0000, size=128M=2^(26+1) - // NOTE: this region extends to 0x080'0000, which is where - // the ROM is re-mapped by STM32 - 0x00000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 7U), // region #7 - (26U << MPU_RASR_SIZE_Pos) // 2^(26+1)=128M region - | (0x0U << MPU_RASR_AP_Pos) // PA:na/UA:na - | (1U << MPU_RASR_XN_Pos) // XN=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - }; - - MPU->CTRL = 0U; // disable the MPU - for (uint_fast8_t n = 0U; n < Q_DIM(mpu_setup); ++n) { - MPU->RBAR = mpu_setup[n].rbar; - MPU->RASR = mpu_setup[n].rasr; - } - MPU->CTRL = MPU_CTRL_PRIVDEFENA_Msk // enable background region - | MPU_CTRL_ENABLE_Msk; // enable the MPU - __ISB(); - __DSB(); -} -//............................................................................ -void BSP::init(void) { - // setup the MPU... - STM32C031C6_MPU_setup(); - - // initialize the QS software tracing... - if (!QS_INIT(nullptr)) { // initialize the QS software tracing - Q_ERROR(); - } - - // dictionaries... - QS_OBJ_DICTIONARY(&l_SysTick_Handler); - QS_OBJ_DICTIONARY(&l_test_ISR); - - QS_USR_DICTIONARY(CONTEXT_SW); - QS_USR_DICTIONARY(TRACE_MSG); -} -//............................................................................ -void BSP::terminate(int16_t result) { - Q_UNUSED_PAR(result); -} -//............................................................................ -void BSP::ledOn(void) { - GPIOA->BSRR = (1U << LD4_PIN); // turn LD4 on -} -//............................................................................ -void BSP::ledOff(void) { - GPIOA->BSRR = (1U << (LD4_PIN + 16U)); // turn LD4 off -} -//............................................................................ -void BSP::trigISR(void) { - NVIC_SetPendingIRQ(EXTI0_1_IRQn); -} -//............................................................................ -void BSP::trace(QP::QActive const *thr, char const *msg) { - QS_BEGIN_ID(TRACE_MSG, 0U) - QS_OBJ(thr); - QS_STR(msg); - QS_END() -} -//............................................................................ -uint32_t BSP::romRead(int32_t offset, uint32_t fromEnd) { - int32_t const rom_base = (fromEnd == 0U) - ? 0x08000000 - : 0x08008000 - 4; - return *(uint32_t volatile *)(rom_base + offset); -} -//............................................................................ -void BSP::romWrite(int32_t offset, uint32_t fromEnd, uint32_t value) { - int32_t const rom_base = (fromEnd == 0U) - ? 0x08000000 - : 0x08008000 - 4; - *(uint32_t volatile *)(rom_base + offset) = value; -} - -//............................................................................ -uint32_t BSP::ramRead(int32_t offset, uint32_t fromEnd) { - int32_t const ram_base = (fromEnd == 0U) - ? 0x20000000 - : 0x20003000 - 4; - return *(uint32_t volatile *)(ram_base + offset); -} -//............................................................................ -void BSP::ramWrite(int32_t offset, uint32_t fromEnd, uint32_t value) { - int32_t const ram_base = (fromEnd == 0U) - ? 0x20000000 - : 0x20003000 - 4; - *(uint32_t volatile *)(ram_base + offset) = value; -} - -// namespace QP ============================================================== -namespace QP { - -// QF callbacks -------------------------------------------------------------- -void QF::onStartup(void) { - // NOTE: SystemInit() has been already called from the startup code - // but SystemCoreClock needs to be updated - // - SystemCoreClockUpdate(); - - //NOTE: don't start ticking for these tests - //SysTick_Config(SystemCoreClock / BSP_TICKS_PER_SEC); - - // assign all priority bits for preemption-prio. and none to sub-prio. - // NOTE: this might have been changed by STM32Cube. - NVIC_SetPriorityGrouping(0U); - - // set priorities of ALL ISRs used in the system - NVIC_SetPriority(SysTick_IRQn, QF_AWARE_ISR_CMSIS_PRI + 0U); - NVIC_SetPriority(EXTI0_1_IRQn, QF_AWARE_ISR_CMSIS_PRI + 1U); - // NOTE: priority of UART IRQ used for QS-RX is set in qutest_port.c - // ... - - // enable IRQs... - NVIC_EnableIRQ(EXTI0_1_IRQn); -} -//............................................................................ -void QF::onCleanup(void) { -} -//............................................................................ -void QK::onIdle(void) { -#ifdef Q_SPY - QS::rxParse(); // parse all the received bytes - QS::doOutput(); -#elif defined NDEBUG - // Put the CPU and peripherals to the low-power mode. - // you might need to customize the clock management for your application, - // see the datasheet for your particular Cortex-M3 MCU. - // - __WFI(); // Wait-For-Interrupt -#endif -} - -// QS callbacks ============================================================== -//............................................................................ -void QTimeEvt::tick1_( - uint_fast8_t const tickRate, - void const * const sender) -{ - QF_INT_DISABLE(); - // TODO pend the SysTick - *Q_UINT2PTR_CAST(uint32_t, 0xE000ED04U) = (1U << 26U); - QF_INT_ENABLE(); -} - -//---------------------------------------------------------------------------- - -} // namespace QP - -extern "C" { -//............................................................................ -#ifdef QF_ON_CONTEXT_SW -// NOTE: the context-switch callback is called with interrupts DISABLED -void QF_onContextSw(QP::QActive *prev, QP::QActive *next) { - QS_BEGIN_INCRIT(CONTEXT_SW, 0U) // no critical section! - QS_OBJ(prev); - QS_OBJ(next); - QS_END_INCRIT() -} -#endif // QF_ON_CONTEXT_SW - -} // extern "C" - -//============================================================================ -// NOTE0: -// The MPU protection against NULL-pointer dereferencing sets up a no-access -// MPU region #7 around the NULL address (0x0). The size of this region is set -// to 2^(26+1)==0x0800'0000, because that is the address of Flash in STM32. -// -// REMARK: STM32 MCUs automatically relocate the Flash memory and the Vector -// Table in it to address 0x0800'0000 at startup. However, even though the -// region 0..0x0800'0000 is un-mapped after the relocation, the read access -// is still allowed and causes no CPU exception. Therefore setting up the MPU -// to protect that region is necessary. -// diff --git a/test/qk/test_sched/bsp_nucleo-h743zi.cpp b/test/qk/test_sched/bsp_nucleo-h743zi.cpp deleted file mode 100644 index cb555ed33..000000000 --- a/test/qk/test_sched/bsp_nucleo-h743zi.cpp +++ /dev/null @@ -1,307 +0,0 @@ -//============================================================================ -// Product: BSP for system-testing of QK kernel, NUCLEO-H743ZI board -// Last updated for version 7.2.0 -// Last updated on 2022-12-25 -// -// Q u a n t u m L e a P s -// ------------------------ -// Modern Embedded Software -// -// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -// -// This program is open source software: you can redistribute it and/or -// modify it under the terms of the GNU General Public License as published -// by the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Alternatively, this program may be distributed and modified under the -// terms of Quantum Leaps commercial licenses, which expressly supersede -// the GNU General Public License and are specifically designed for -// licensees interested in retaining the proprietary status of their code. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -// Contact information: -// -// -//============================================================================ -#include "qpcpp.hpp" -#include "bsp.hpp" - -// STM32CubeH7 include files -#include "stm32h7xx_hal.h" -#include "stm32h7xx_nucleo_144.h" -// add other drivers if necessary... - -namespace { - -Q_DEFINE_THIS_FILE - -#ifdef Q_SPY - - // QSpy source IDs - static QP::QSpyId const l_SysTick_Handler = { 100U }; - static QP::QSpyId const l_test_ISR = { 101U }; - - enum AppRecords { // application-specific trace records - CONTEXT_SW = QP::QS_USER1, - TRACE_MSG - }; - -#endif - -} // unnamed namespace - -// ISRs used in this project ================================================= -extern "C" { - -//............................................................................ -void SysTick_Handler(void); // prototype -void SysTick_Handler(void) { - QK_ISR_ENTRY(); // inform QK about entering an ISR - - QP::QTimeEvt::TICK_X(0U, &l_SysTick_Handler); - //the_Ticker0->TRIG(&l_SysTick_Handler); - - QK_ISR_EXIT(); // inform QK about exiting an ISR -} -//............................................................................ -void EXTI0_IRQHandler(void); // prototype -void EXTI0_IRQHandler(void) { // for testing, NOTE03 - QK_ISR_ENTRY(); // inform QK about entering an ISR - - // for testing... - static QP::QEvt const t1(TEST1_SIG); - QP::QF::PUBLISH(&t1, &l_test_ISR); - - QK_ISR_EXIT(); // inform QK about exiting an ISR -} - -} // extern "C" - -// BSP functions ============================================================= -// MPU setup for STM32H743ZI MCU -static void STM32H743ZI_MPU_setup(void) { - // The following MPU configuration contains just a generic ROM - // region (with read-only access) and NULL-pointer protection region. - // Otherwise, the MPU will fall back on the background region (PRIVDEFENA). - // - static struct { - std::uint32_t rbar; - std::uint32_t rasr; - } const mpu_setup[] = { - - { // region #0: Flash: base=0x0000'0000, size=512M=2^(28+1) - 0x00000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 0U), // region #0 - (28U << MPU_RASR_SIZE_Pos) // 2^(18+1) region - | (0x6U << MPU_RASR_AP_Pos) // PA:ro/UA:ro - | (1U << MPU_RASR_C_Pos) // C=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - { // region #7: NULL-pointer: base=0x000'0000, size=128M=2^(26+1) - // NOTE: this region extends to 0x080'0000, which is where - // the ROM is re-mapped by STM32 - // - 0x00000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 7U), // region #7 - (26U << MPU_RASR_SIZE_Pos) // 2^(26+1)=128M region - | (0x0U << MPU_RASR_AP_Pos) // PA:na/UA:na - | (1U << MPU_RASR_XN_Pos) // XN=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - }; - - // enable the MemManage_Handler for MPU exception - SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; - - __DSB(); - MPU->CTRL = 0U; // disable the MPU */ - for (std::uint_fast8_t n = 0U; n < Q_DIM(mpu_setup); ++n) { - MPU->RBAR = mpu_setup[n].rbar; - MPU->RASR = mpu_setup[n].rasr; - } - MPU->CTRL = MPU_CTRL_ENABLE_Msk // enable the MPU */ - | MPU_CTRL_PRIVDEFENA_Msk; // enable background region */ - __ISB(); - __DSB(); -} -//............................................................................ -void BSP::init(void) { - // setup the MPU... - STM32H743ZI_MPU_setup(); - - // NOTE: SystemInit() has been already called from the startup code - // but SystemCoreClock needs to be updated - // - SystemCoreClockUpdate(); - - SCB_EnableICache(); // Enable I-Cache - SCB_EnableDCache(); // Enable D-Cache - - // Configure Flash prefetch and Instr. cache through ART accelerator -#if (ART_ACCLERATOR_ENABLE != 0) - __HAL_FLASH_ART_ENABLE(); -#endif // ART_ACCLERATOR_ENABLE - - // Configure the LEDs - BSP_LED_Init(LED1); - BSP_LED_Init(LED2); - BSP_LED_Init(LED3); - - // Configure the User Button in GPIO Mode - BSP_PB_Init(BUTTON_USER, BUTTON_MODE_GPIO); - - // initialize the QS software tracing... - if (!QS_INIT(nullptr)) { - Q_ERROR(); - } - - // dictionaries... - QS_OBJ_DICTIONARY(&l_SysTick_Handler); - QS_OBJ_DICTIONARY(&l_test_ISR); - - QS_USR_DICTIONARY(CONTEXT_SW); - QS_USR_DICTIONARY(TRACE_MSG); -} -//............................................................................ -void BSP::terminate(int16_t result) { - Q_UNUSED_PAR(result); -} -//............................................................................ -void BSP::ledOn(void) { - BSP_LED_On(LED1); -} -//............................................................................ -void BSP::ledOff(void) { - BSP_LED_Off(LED1); -} -//............................................................................ -void BSP::trigISR(void) { - NVIC_SetPendingIRQ(EXTI0_IRQn); -} -//............................................................................ -void BSP::trace(QP::QActive const *thr, char const *msg) { - QS_BEGIN_ID(TRACE_MSG, 0U) - QS_OBJ(thr); - QS_STR(msg); - QS_END() -} -//............................................................................ -uint32_t BSP::romRead(int32_t offset, uint32_t fromEnd) { - int32_t const rom_base = (fromEnd == 0U) - ? 0x08000000 - : 0x08200000 - 4; - return *(uint32_t volatile *)(rom_base + offset); -} -//............................................................................ -void BSP::romWrite(int32_t offset, uint32_t fromEnd, uint32_t value) { - int32_t const rom_base = (fromEnd == 0U) - ? 0x08000000 - : 0x08200000 - 4; - *(uint32_t volatile *)(rom_base + offset) = value; -} - -//............................................................................ -uint32_t BSP::ramRead(int32_t offset, uint32_t fromEnd) { - int32_t const ram_base = (fromEnd == 0U) - ? 0x20000000 - : 0x20020000 - 4; - return *(uint32_t volatile *)(ram_base + offset); -} -//............................................................................ -void BSP::ramWrite(int32_t offset, uint32_t fromEnd, uint32_t value) { - int32_t const ram_base = (fromEnd == 0U) - ? 0x20000000 - : 0x20020000 - 4; - *(uint32_t volatile *)(ram_base + offset) = value; -} - -// namespace QP ============================================================== -namespace QP { - -// QF callbacks -------------------------------------------------------------- -void QF::onStartup(void) { - //NOTE: don't start ticking for these tests - //SysTick_Config(SystemCoreClock / BSP_TICKS_PER_SEC); - - // assign all priority bits for preemption-prio. and none to sub-prio. - NVIC_SetPriorityGrouping(0U); - - // set priorities of ALL ISRs used in the system - NVIC_SetPriority(USART2_IRQn, 0U); - NVIC_SetPriority(SysTick_IRQn, QF_AWARE_ISR_CMSIS_PRI + 0U); - NVIC_SetPriority(EXTI0_IRQn, QF_AWARE_ISR_CMSIS_PRI + 1U); - // ... - - // enable IRQs... - NVIC_EnableIRQ(EXTI0_IRQn); -} -//............................................................................ -void QF::onCleanup(void) { -} -//............................................................................ -void QK::onIdle(void) { -#ifdef Q_SPY - QS::rxParse(); // parse all the received bytes - QS::doOutput(); -#elif defined NDEBUG - // Put the CPU and peripherals to the low-power mode. - // you might need to customize the clock management for your application, - // see the datasheet for your particular Cortex-M3 MCU. - // - __WFI(); // Wait-For-Interrupt -#endif -} - -// QS callbacks ============================================================== -//............................................................................ -void QTimeEvt::tick1_( - uint_fast8_t const tickRate, - void const * const sender) -{ - QF_INT_DISABLE(); - // TODO pend the SysTick - *Q_UINT2PTR_CAST(uint32_t, 0xE000ED04U) = (1U << 26U); - QF_INT_ENABLE(); -} - -//---------------------------------------------------------------------------- - -} // namespace QP - -extern "C" { -//............................................................................ -#ifdef QF_ON_CONTEXT_SW -// NOTE: the context-switch callback is called with interrupts DISABLED -void QF_onContextSw(QP::QActive *prev, QP::QActive *next) { - QS_BEGIN_INCRIT(CONTEXT_SW, 0U) // no critical section! - QS_OBJ(prev); - QS_OBJ(next); - QS_END_INCRIT() -} -#endif // QF_ON_CONTEXT_SW - -} // extern "C" - -//============================================================================ -// NOTE0: -// The MPU protection against NULL-pointer dereferencing sets up a no-access -// MPU region #7 around the NULL address (0x0). The size of this region is set -// to 2^(26+1)==0x0800'0000, because that is the address of Flash in STM32. -// -// REMARK: STM32 MCUs automatically relocate the Flash memory and the Vector -// Table in it to address 0x0800'0000 at startup. However, even though the -// region 0..0x0800'0000 is un-mapped after the relocation, the read access -// is still allowed and causes no CPU exception. Therefore setting up the MPU -// to protect that region is necessary. -// diff --git a/test/qk/test_sched/bsp_nucleo-l053r8.cpp b/test/qk/test_sched/bsp_nucleo-l053r8.cpp deleted file mode 100644 index bc5c4cb01..000000000 --- a/test/qk/test_sched/bsp_nucleo-l053r8.cpp +++ /dev/null @@ -1,381 +0,0 @@ -//============================================================================ -// Product: BSP for system-testing of QK kernel, NUCLEO-L053R8 board -// Last updated for version 7.2.1 -// Last updated on 2023-01-26 -// -// Q u a n t u m L e a P s -// ------------------------ -// Modern Embedded Software -// -// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -// -// This program is open source software: you can redistribute it and/or -// modify it under the terms of the GNU General Public License as published -// by the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Alternatively, this program may be distributed and modified under the -// terms of Quantum Leaps commercial licenses, which expressly supersede -// the GNU General Public License and are specifically designed for -// licensees interested in retaining the proprietary status of their code. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -// Contact information: -// -// -//============================================================================ -#include "qpcpp.hpp" -#include "bsp.hpp" - -#include "stm32l0xx.h" // CMSIS-compliant header file for the MCU used -// add other drivers if necessary... - -namespace { - -Q_DEFINE_THIS_FILE - -// Local-scope objects ------------------------------------------------------- -// LED pins available on the board (just one user LED LD2--Green on PA.5) -#define LED_LD2 (1U << 5) - -// Button pins available on the board (just one user Button B1 on PC.13) -#define BTN_B1 (1U << 13) - -#ifdef Q_SPY - - // QSpy source IDs - static QP::QSpyId const l_SysTick_Handler = { 100U }; - static QP::QSpyId const l_test_ISR = { 101U }; - - enum AppRecords { // application-specific trace records - CONTEXT_SW = QP::QS_USER1, - TRACE_MSG - }; - -#endif - -} // unnamed namespace - -// ISRs used in this project ================================================= -extern "C" { - -//............................................................................ -void SysTick_Handler(void); // prototype -void SysTick_Handler(void) { - QK_ISR_ENTRY(); // inform QK about entering an ISR - - QP::QTimeEvt::TICK_X(0U, &l_SysTick_Handler); - //the_Ticker0->TRIG(&l_SysTick_Handler); - - QK_ISR_EXIT(); // inform QK about exiting an ISR -} -//............................................................................ -void EXTI0_1_IRQHandler(void); // prototype -void EXTI0_1_IRQHandler(void) { - QK_ISR_ENTRY(); // inform QK about entering an ISR - - // for testing... - static QP::QEvt const t1(TEST1_SIG); - QP::QF::PUBLISH(&t1, &l_test_ISR); - - QK_ISR_EXIT(); // inform QK about exiting an ISR -} - -} // extern "C" - -// BSP functions ============================================================= - -static void STM32L053R8_MPU_setup(void) { - // The following MPU configuration contains the general STM32 memory model - // as described in the ST AppNote AN4838 "Managing memory protection unit - // in STM32 MCUs", Figure 2. Cortex-M0+/M3/M4/M7 processor memory map. - // - // Please note that the actual STM32 MCUs provide much less Flash and SRAM - // than the maximums configured here. This means that actual MCUs have - // unmapped memory regions (e.g., beyond the actual SRAM). Attempts to - // access these regions causes the HardFault exception, which is the - // desired behavior. - // - static struct { - uint32_t rbar; - uint32_t rasr; - } const mpu_setup[] = { - - { // region #0: Flash: base=0x0000'0000, size=512M=2^(28+1) - 0x00000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 0U), // region #0 - (28U << MPU_RASR_SIZE_Pos) // 2^(18+1) region - | (0x6U << MPU_RASR_AP_Pos) // PA:ro/UA:ro - | (1U << MPU_RASR_C_Pos) // C=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - { // region #1: SRAM: base=0x2000'0000, size=512M=2^(28+1) - 0x20000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 1U), // region #1 - (28U << MPU_RASR_SIZE_Pos) // 2^(28+1) region - | (0x3U << MPU_RASR_AP_Pos) // PA:rw/UA:rw - | (1U << MPU_RASR_XN_Pos) // XN=1 - | (1U << MPU_RASR_S_Pos) // S=1 - | (1U << MPU_RASR_C_Pos) // C=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - // region #3: (not configured) - { MPU_RBAR_VALID_Msk | (MPU_RBAR_REGION_Msk & 2U), 0U }, - - { // region #3: Peripherals: base=0x4000'0000, size=512M=2^(28+1) - 0x40000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 3U), // region #3 - (28U << MPU_RASR_SIZE_Pos) // 2^(28+1) region - | (0x3U << MPU_RASR_AP_Pos) // PA:rw/UA:rw - | (1U << MPU_RASR_XN_Pos) // XN=1 - | (1U << MPU_RASR_S_Pos) // S=1 - | (1U << MPU_RASR_B_Pos) // B=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - { // region #4: Priv. Periph: base=0xE000'0000, size=512M=2^(28+1) - 0xE0000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 4U), // region #4 - (28U << MPU_RASR_SIZE_Pos) // 2^(28+1) region - | (0x3U << MPU_RASR_AP_Pos) // PA:rw/UA:rw - | (1U << MPU_RASR_XN_Pos) // XN=1 - | (1U << MPU_RASR_S_Pos) // S=1 - | (1U << MPU_RASR_B_Pos) // B=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - { // region #5: Ext RAM: base=0x6000'0000, size=1G=2^(29+1) - 0x60000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 5U), // region #5 - (29U << MPU_RASR_SIZE_Pos) // 2^(28+1) region - | (0x3U << MPU_RASR_AP_Pos) // PA:rw/UA:rw - | (1U << MPU_RASR_XN_Pos) // XN=1 - | (1U << MPU_RASR_S_Pos) // S=1 - | (1U << MPU_RASR_B_Pos) // B=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - { // region #6: Ext Dev: base=0xA000'0000, size=1G=2^(29+1) - 0xA0000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 6U), // region #6 - (29U << MPU_RASR_SIZE_Pos) // 2^(28+1) region - | (0x3U << MPU_RASR_AP_Pos) // PA:rw/UA:rw - | (1U << MPU_RASR_XN_Pos) // XN=1 - | (1U << MPU_RASR_S_Pos) // S=1 - | (1U << MPU_RASR_B_Pos) // B=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - { // region #7: NULL-pointer: base=0x000'0000, size=128M=2^(26+1) - // NOTE: this region extends to 0x080'0000, which is where - // the ROM is re-mapped by STM32 - - 0x00000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 7U), // region #7 - (26U << MPU_RASR_SIZE_Pos) // 2^(26+1)=128M region - | (0x0U << MPU_RASR_AP_Pos) // PA:na/UA:na - | (1U << MPU_RASR_XN_Pos) // XN=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - }; - - __DSB(); - MPU->CTRL = 0U; // disable the MPU - for (uint_fast8_t n = 0U; n < Q_DIM(mpu_setup); ++n) { - MPU->RBAR = mpu_setup[n].rbar; - MPU->RASR = mpu_setup[n].rasr; - } - MPU->CTRL = MPU_CTRL_PRIVDEFENA_Msk // enable background region - | MPU_CTRL_ENABLE_Msk; // enable the MPU - __ISB(); - __DSB(); -} -//............................................................................ -void BSP::init(void) { - // setup the MPU... - STM32L053R8_MPU_setup(); - - // NOTE: SystemInit() already called from the startup code - // but SystemCoreClock needs to be updated - // - SystemCoreClockUpdate(); - - // enable GPIOA clock port for the LED LD2 - RCC->IOPENR |= (1U << 0); - - // configure LED (PA.5) pin as push-pull output, no pull-up, pull-down - GPIOA->MODER &= ~((3U << 2*5)); - GPIOA->MODER |= ((1U << 2*5)); - GPIOA->OTYPER &= ~((1U << 5)); - GPIOA->OSPEEDR &= ~((3U << 2*5)); - GPIOA->OSPEEDR |= ((1U << 2*5)); - GPIOA->PUPDR &= ~((3U << 2*5)); - - // enable GPIOC clock port for the Button B1 - RCC->IOPENR |= (1U << 2); - - // configure Button (PC.13) pins as input, no pull-up, pull-down - GPIOC->MODER &= ~(3U << 2*13); - GPIOC->OSPEEDR &= ~(3U << 2*13); - GPIOC->OSPEEDR |= (1U << 2*13); - GPIOC->PUPDR &= ~(3U << 2*13); - - // initialize the QS software tracing... - if (!QS_INIT(nullptr)) { // initialize the QS software tracing - Q_ERROR(); - } - - // dictionaries... - QS_OBJ_DICTIONARY(&l_SysTick_Handler); - QS_OBJ_DICTIONARY(&l_test_ISR); - - QS_USR_DICTIONARY(CONTEXT_SW); - QS_USR_DICTIONARY(TRACE_MSG); -} -//............................................................................ -void BSP::terminate(int16_t result) { - Q_UNUSED_PAR(result); -} -//............................................................................ -void BSP::ledOn(void) { - GPIOA->BSRR = (LED_LD2); // turn LED2 on -} -//............................................................................ -void BSP::ledOff(void) { - GPIOA->BSRR = (LED_LD2 << 16); // turn LED2 off -} -//............................................................................ -void BSP::trigISR(void) { - NVIC_SetPendingIRQ(EXTI0_1_IRQn); -} -//............................................................................ -void BSP::trace(QP::QActive const *thr, char const *msg) { - QS_BEGIN_ID(TRACE_MSG, 0U) - QS_OBJ(thr); - QS_STR(msg); - QS_END() -} -//............................................................................ -uint32_t BSP::romRead(int32_t offset, uint32_t fromEnd) { - int32_t const rom_base = (fromEnd == 0U) - ? 0x08000000 - : 0x08010000 - 4; - return *(uint32_t volatile *)(rom_base + offset); -} -//............................................................................ -void BSP::romWrite(int32_t offset, uint32_t fromEnd, uint32_t value) { - int32_t const rom_base = (fromEnd == 0U) - ? 0x08000000 - : 0x08010000 - 4; - *(uint32_t volatile *)(rom_base + offset) = value; -} - -//............................................................................ -uint32_t BSP::ramRead(int32_t offset, uint32_t fromEnd) { - int32_t const ram_base = (fromEnd == 0U) - ? 0x20000000 - : 0x20002000 - 4; - return *(uint32_t volatile *)(ram_base + offset); -} -//............................................................................ -void BSP::ramWrite(int32_t offset, uint32_t fromEnd, uint32_t value) { - int32_t const ram_base = (fromEnd == 0U) - ? 0x20000000 - : 0x20002000 - 4; - *(uint32_t volatile *)(ram_base + offset) = value; -} - -// namespace QP ============================================================== -namespace QP { - -// QF callbacks -------------------------------------------------------------- -void QF::onStartup(void) { - // assign all priority bits for preemption-prio. and none to sub-prio. - // NOTE: this might have been changed by STM32Cube. - NVIC_SetPriorityGrouping(0U); - - // set priorities of ALL ISRs used in the system - NVIC_SetPriority(USART2_IRQn, 0U); - NVIC_SetPriority(SysTick_IRQn, QF_AWARE_ISR_CMSIS_PRI + 0U); - NVIC_SetPriority(EXTI0_1_IRQn, QF_AWARE_ISR_CMSIS_PRI + 1U); - // ... - - // enable IRQs... - NVIC_EnableIRQ(EXTI0_1_IRQn); -} -//............................................................................ -void QF::onCleanup(void) { -} -//............................................................................ -void QK::onIdle(void) { -#ifdef Q_SPY - QS::rxParse(); // parse all the received bytes - QS::doOutput(); -#elif defined NDEBUG - // Put the CPU and peripherals to the low-power mode. - // you might need to customize the clock management for your application, - // see the datasheet for your particular Cortex-M3 MCU. - // - __WFI(); // Wait-For-Interrupt -#endif -} - -// QS callbacks ============================================================== -//............................................................................ -void QTimeEvt::tick1_( - uint_fast8_t const tickRate, - void const * const sender) -{ - QF_INT_DISABLE(); - // TODO pend the SysTick - *Q_UINT2PTR_CAST(uint32_t, 0xE000ED04U) = (1U << 26U); - QF_INT_ENABLE(); -} - -//---------------------------------------------------------------------------- - -} // namespace QP - -extern "C" { -//............................................................................ -#ifdef QF_ON_CONTEXT_SW -// NOTE: the context-switch callback is called with interrupts DISABLED -void QF_onContextSw(QP::QActive *prev, QP::QActive *next) { - QS_BEGIN_INCRIT(CONTEXT_SW, 0U) // no critical section! - QS_OBJ(prev); - QS_OBJ(next); - QS_END_INCRIT() -} -#endif // QF_ON_CONTEXT_SW - -} // extern "C" - -//============================================================================ -// NOTE0: -// The MPU protection against NULL-pointer dereferencing sets up a no-access -// MPU region #7 around the NULL address (0x0). The size of this region is set -// to 2^(26+1)==0x0800'0000, because that is the address of Flash in STM32. -// -// REMARK: STM32 MCUs automatically relocate the Flash memory and the Vector -// Table in it to address 0x0800'0000 at startup. However, even though the -// region 0..0x0800'0000 is un-mapped after the relocation, the read access -// is still allowed and causes no CPU exception. Therefore setting up the MPU -// to protect that region is necessary. -// diff --git a/test/qk/test_sched/bsp_nucleo-u545re.cpp b/test/qk/test_sched/bsp_nucleo-u545re.cpp deleted file mode 100644 index c6b0f34b8..000000000 --- a/test/qk/test_sched/bsp_nucleo-u545re.cpp +++ /dev/null @@ -1,315 +0,0 @@ -//============================================================================ -// Product: BSP for system-testing of QK kernel, NUCLEO-U545RE-Q board -// Last updated for version 7.4.0 -// Last updated on 2024-06-24 -// -// Q u a n t u m L e a P s -// ------------------------ -// Modern Embedded Software -// -// Copyright (C) 2005 Quantum Leaps, LLC. -// -// 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: -// -// -//============================================================================ -#include "qpcpp.hpp" -#include "bsp.hpp" - -#include "stm32u545xx.h" // CMSIS-compliant header file for the MCU used -// add other drivers if necessary... - -namespace { - -Q_DEFINE_THIS_FILE - -// Local-scope defines ----------------------------------------------------- -// LED pins available on the board (just one user LED LD2--Green on PA.5) -#define LD2_PIN 5U - -// Button pins available on the board (just one user Button B1 on PC.13) -#define B1_PIN 13U - -// macros from STM32Cube LL: -#define SET_BIT(REG, BIT) ((REG) |= (BIT)) -#define CLEAR_BIT(REG, BIT) ((REG) &= ~(BIT)) -#define READ_BIT(REG, BIT) ((REG) & (BIT)) -#define CLEAR_REG(REG) ((REG) = (0x0)) -#define WRITE_REG(REG, VAL) ((REG) = (VAL)) -#define READ_REG(REG) ((REG)) -#define MODIFY_REG(REG, CLEARMASK, SETMASK) \ - WRITE_REG((REG), ((READ_REG(REG) & (~(CLEARMASK))) | (SETMASK))) - -#ifdef Q_SPY -// QSpy source IDs -static QP::QSpyId const l_SysTick_Handler = { 100U }; -static QP::QSpyId const l_test_ISR = { 101U }; - -enum AppRecords { // application-specific trace records - CONTEXT_SW = QP::QS_USER1, - TRACE_MSG -}; - -#endif - -} // unnamed namespace - -// ISRs used in this project ================================================= -extern "C" { - -//............................................................................ -void SysTick_Handler(void); // prototype -void SysTick_Handler(void) { - QK_ISR_ENTRY(); // inform QK kernel about entering an ISR - - QP::QTimeEvt::TICK_X(0U, &l_SysTick_Handler); - - QK_ISR_EXIT(); // inform QK kernel about exiting an ISR -} -//............................................................................ -void EXTI0_IRQHandler(void); // prototype -void EXTI0_IRQHandler(void) { // for testing, NOTE03 - QK_ISR_ENTRY(); // inform QXK kernel about entering an ISR - - // for testing... - static QP::QEvt const t1(TEST1_SIG); - QP::QF::PUBLISH(&t1, &l_test_ISR); - - QK_ISR_EXIT(); // inform QK kernel about exiting an ISR -} - -} // extern "C" - -// BSP functions ============================================================= - -static void STM32U545RE_MPU_setup(void) { - MPU->CTRL = 0U; // disable the MPU - - MPU->RNR = 0U; // region 0 (for ROM) - MPU->RBAR = (0x08000000U & MPU_RBAR_BASE_Msk) | (0x3U << MPU_RBAR_AP_Pos); - MPU->RLAR = (0x08080000U & MPU_RLAR_LIMIT_Msk) | MPU_RLAR_EN_Msk; - - MPU->RNR = 7U; // region 7 (for NULL pointer protection) - MPU->RBAR = (0x00000000U & MPU_RBAR_BASE_Msk) | MPU_RBAR_XN_Msk; - MPU->RLAR = (0x00080000U & MPU_RLAR_LIMIT_Msk) | MPU_RLAR_EN_Msk; - __DMB(); - - MPU->CTRL = MPU_CTRL_ENABLE_Msk | MPU_CTRL_PRIVDEFENA_Msk; - - SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; - - __DSB(); - __ISB(); -} -//............................................................................ -void BSP::init(void) { - // setup the MPU... - STM32U545RE_MPU_setup(); - - // initialize I-CACHE - MODIFY_REG(ICACHE->CR, ICACHE_CR_WAYSEL, 0U); // 1-way - SET_BIT(ICACHE->CR, ICACHE_CR_EN); // enable - - // flash prefetch buffer enable - SET_BIT(FLASH->ACR, FLASH_ACR_PRFTEN); - - // enable PWR clock interface - SET_BIT(RCC->AHB3ENR, RCC_AHB3ENR_PWREN); - - // NOTE: SystemInit() has been already called from the startup code - // but SystemCoreClock needs to be updated - SystemCoreClockUpdate(); - - // enable GPIOA clock port for the LED LD4 - RCC->AHB2ENR1 |= RCC_AHB2ENR1_GPIOAEN; - - // set all used GPIOA pins as push-pull output, no pull-up, pull-down - MODIFY_REG(GPIOA->OSPEEDR, - GPIO_OSPEEDR_OSPEED0 << (LD2_PIN * GPIO_OSPEEDR_OSPEED1_Pos), - 1U << (LD2_PIN * GPIO_OSPEEDR_OSPEED1_Pos)); // speed==1 - MODIFY_REG(GPIOA->OTYPER, - 1U << LD2_PIN, - 0U << LD2_PIN); // output - MODIFY_REG(GPIOA->PUPDR, - GPIO_PUPDR_PUPD0 << (LD2_PIN * GPIO_PUPDR_PUPD1_Pos), - 0U << (LD2_PIN * GPIO_PUPDR_PUPD1_Pos)); // PUSHPULL - MODIFY_REG(GPIOA->MODER, - GPIO_MODER_MODE0 << (LD2_PIN * GPIO_MODER_MODE1_Pos), - 1U << (LD2_PIN * GPIO_MODER_MODE1_Pos)); // MODE_1 - - // enable GPIOC clock port for the Button B1 - RCC->AHB2ENR1 |= RCC_AHB2ENR1_GPIOCEN; - - // configure Button B1 pin on GPIOC as input, no pull-up, pull-down - MODIFY_REG(GPIOC->PUPDR, - GPIO_PUPDR_PUPD0 << (B1_PIN * GPIO_PUPDR_PUPD1_Pos), - 0U << (B1_PIN * GPIO_PUPDR_PUPD1_Pos)); // NO PULL - MODIFY_REG(GPIOC->MODER, - GPIO_MODER_MODE0 << (B1_PIN * GPIO_MODER_MODE1_Pos), - 0U << (B1_PIN * GPIO_MODER_MODE1_Pos)); // MODE_0 - - // initialize the QS software tracing... - if (!QS_INIT(nullptr)) { // initialize the QS software tracing - Q_ERROR(); - } - - // dictionaries... - QS_OBJ_DICTIONARY(&l_SysTick_Handler); - QS_OBJ_DICTIONARY(&l_test_ISR); - - QS_USR_DICTIONARY(CONTEXT_SW); - QS_USR_DICTIONARY(TRACE_MSG); -} -//............................................................................ -void BSP::terminate(int16_t result) { - Q_UNUSED_PAR(result); -} -//............................................................................ -void BSP::ledOn(void) { - GPIOA->BSRR = (1U << LD2_PIN); // turn LED on -} -//............................................................................ -void BSP::ledOff(void) { - GPIOA->BRR = (1U << LD2_PIN); // turn LED off -} -//............................................................................ -void BSP::trigISR(void) { - NVIC_SetPendingIRQ(EXTI0_IRQn); -} -//............................................................................ -void BSP::trace(QP::QActive const *thr, char const *msg) { - QS_BEGIN_ID(TRACE_MSG, 0U) - QS_OBJ(thr); - QS_STR(msg); - QS_END() -} -//............................................................................ -uint32_t BSP::romRead(int32_t offset, uint32_t fromEnd) { - int32_t const rom_base = (fromEnd == 0U) - ? 0x08000000 - : 0x08080000 - 4; - return *(uint32_t volatile *)(rom_base + offset); -} -//............................................................................ -void BSP::romWrite(int32_t offset, uint32_t fromEnd, uint32_t value) { - int32_t const rom_base = (fromEnd == 0U) - ? 0x08000000 - : 0x08080000 - 4; - *(uint32_t volatile *)(rom_base + offset) = value; -} - -//............................................................................ -uint32_t BSP::ramRead(int32_t offset, uint32_t fromEnd) { - int32_t const ram_base = (fromEnd == 0U) - ? 0x20000000 - : 0x20040000 - 4; - return *(uint32_t volatile *)(ram_base + offset); -} -//............................................................................ -void BSP::ramWrite(int32_t offset, uint32_t fromEnd, uint32_t value) { - int32_t const ram_base = (fromEnd == 0U) - ? 0x20000000 - : 0x20040000 - 4; - *(uint32_t volatile *)(ram_base + offset) = value; -} - -// namespace QP ============================================================== -namespace QP { - -// QF callbacks -------------------------------------------------------------- -void QF::onStartup(void) { - // NOTE: SystemInit() has been already called from the startup code - // but SystemCoreClock needs to be updated - SystemCoreClockUpdate(); - - //NOTE: don't start ticking for these tests - //SysTick_Config(SystemCoreClock / BSP_TICKS_PER_SEC); - - // assign all priority bits for preemption-prio. and none to sub-prio. - // NOTE: this might have been changed by STM32Cube. - NVIC_SetPriorityGrouping(0U); - - // set priorities of ALL ISRs used in the system - NVIC_SetPriority(SysTick_IRQn, QF_AWARE_ISR_CMSIS_PRI + 0U); - NVIC_SetPriority(EXTI0_IRQn, QF_AWARE_ISR_CMSIS_PRI + 1U); - // NOTE: priority of UART IRQ used for QS-RX is set in qutest_port.c - // ... - - // enable IRQs... - NVIC_EnableIRQ(EXTI0_IRQn); -} -//............................................................................ -void QF::onCleanup(void) { -} -//............................................................................ -void QK::onIdle(void) { -#ifdef Q_SPY - QS::rxParse(); // parse all the received bytes - QS::doOutput(); -#elif defined NDEBUG - // Put the CPU and peripherals to the low-power mode. - // you might need to customize the clock management for your application, - // see the datasheet for your particular Cortex-M3 MCU. - // - __WFI(); // Wait-For-Interrupt -#endif -} - -// QS callbacks ============================================================== -//............................................................................ -void QTimeEvt::tick1_( - uint_fast8_t const tickRate, - void const * const sender) -{ - QF_INT_DISABLE(); - // TODO pend the SysTick - *Q_UINT2PTR_CAST(uint32_t, 0xE000ED04U) = (1U << 26U); - QF_INT_ENABLE(); -} - -//---------------------------------------------------------------------------- - -} // namespace QP - -extern "C" { -//............................................................................ -#ifdef QF_ON_CONTEXT_SW -// NOTE: the context-switch callback is called with interrupts DISABLED -void QF_onContextSw(QP::QActive *prev, QP::QActive *next) { - QS_BEGIN_INCRIT(CONTEXT_SW, 0U) // no critical section! - QS_OBJ(prev); - QS_OBJ(next); - QS_END_INCRIT() -} -#endif // QF_ON_CONTEXT_SW - -} // extern "C" - -//============================================================================ -// NOTE0: -// The MPU protection against NULL-pointer dereferencing sets up a no-access -// MPU region #7 around the NULL address (0x0). The size of this region is set -// to 2^(26+1)==0x0800'0000, because that is the address of Flash in STM32. -// -// REMARK: STM32 MCUs automatically relocate the Flash memory and the Vector -// Table in it to address 0x0800'0000 at startup. However, even though the -// region 0..0x0800'0000 is un-mapped after the relocation, the read access -// is still allowed and causes no CPU exception. Therefore setting up the MPU -// to protect that region is necessary. -// diff --git a/test/qk/test_sched/efm32pg1b.mak b/test/qk/test_sched/efm32pg1b.mak deleted file mode 100644 index a0d8264d7..000000000 --- a/test/qk/test_sched/efm32pg1b.mak +++ /dev/null @@ -1,333 +0,0 @@ -############################################################################## -# Product: Makefile for SYSTEM-Level tests of QP/C++ on EMF32, GNU-ARM -# Last Updated for Version: 7.3.0 -# Date of the Last Update: 2023-09-06 -# -# Q u a n t u m L e a P s -# ------------------------ -# Modern Embedded Software -# -# Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -# -# This program is open source software: you can redistribute it and/or -# modify it under the terms of the GNU General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Alternatively, this program may be distributed and modified under the -# terms of Quantum Leaps commercial licenses, which expressly supersede -# the GNU General Public License and are specifically designed for -# licensees interested in retaining the proprietary status of their code. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Contact information: -# -# -############################################################################## -# -# examples of invoking this Makefile: -# make -f efm32pg1b.mak # make and run the tests in the current directory -# make -f efm32pg1b.mak TESTS=thr*.py # make and run the selected tests -# make -f efm32pg1b.mak HOST=localhost:7705 # connect to host:port -# make -f efm32pg1b.mak norun # only make but not run the tests -# make -f efm32pg1b.mak clean # cleanup the build -# make -f efm32pg1b.mak debug # only run tests in DEBUG mode -# -# NOTE: -# To use this Makefile on Windows, you will need the GNU make utility, which -# is included in the QTools collection for Windows, see: -# https://github.com/QuantumLeaps/qtools -# - -# location of the QP/C++ framework (if not provided in an env. variable) -ifeq ($(QPCPP),) -QPCPP := ../../.. -endif - -#----------------------------------------------------------------------------- -# project name, target name, target directory: -# -PROJECT := test_sched -TARGET := efm32 -TARGET_DIR := $(QPCPP)/3rd_party/efm32pg1b/qutest - -#----------------------------------------------------------------------------- -# project directories: -# - -# QP port used in this project -QP_PORT_DIR := $(QPCPP)/ports/arm-cm/qk/gnu - -# make sure that QTOOLS env. variable is defined... -ifeq ("$(wildcard $(QTOOLS))","") -$(error QTOOLS not found. Please install QTools and define QTOOLS env. variable) -endif - - -# list of all source directories used by this project -VPATH := . \ - $(QPCPP)/src/qf \ - $(QPCPP)/src/qk \ - $(QPCPP)/src/qs \ - $(QP_PORT_DIR) \ - $(TARGET_DIR) \ - $(QPCPP)/3rd_party/efm32pg1b \ - $(QPCPP)/3rd_party/efm32pg1b/gnu - -# list of all include directories needed by this project -INCLUDES = -I. \ - -I$(QPCPP)/include \ - -I$(QP_PORT_DIR) \ - -I$(TARGET_DIR) \ - -I$(QPCPP)/3rd_party/CMSIS/Include \ - -I$(QPCPP)/3rd_party/efm32pg1b - -#----------------------------------------------------------------------------- -# project files: -# - -# assembler source files -ASM_SRCS := - -# C source files -C_SRCS := \ - startup_efm32pg1b.c \ - system_efm32pg1b.c \ - em_cmu.c \ - em_emu.c \ - em_gpio.c \ - em_usart.c - -# C++ source files -CPP_SRCS := \ - test_sched.cpp \ - bsp_efm32pg1b.cpp - -OUTPUT := $(PROJECT) -LD_SCRIPT := $(TARGET_DIR)/qutest.ld - -QP_SRCS := \ - qep_hsm.cpp \ - qep_msm.cpp \ - qf_act.cpp \ - qf_actq.cpp \ - qf_defer.cpp \ - qf_dyn.cpp \ - qf_mem.cpp \ - qf_ps.cpp \ - qf_qact.cpp \ - qf_qeq.cpp \ - qf_qmact.cpp \ - qf_time.cpp \ - qk.cpp \ - qk_port.cpp \ - qs.cpp \ - qs_64bit.cpp \ - qs_rx.cpp \ - qs_fp.cpp \ - qutest.cpp \ - qutest_cpp.cpp - -QP_ASMS := - -LIB_DIRS := -LIBS := - -# defines -DEFINES := -DEFM32PG1B200F256GM48=1 \ - -DQF_ON_CONTEXT_SW - -# ARM CPU, ARCH, FPU, and Float-ABI types... -# ARM_CPU: [cortex-m0 | cortex-m0plus | cortex-m1 | cortex-m3 | cortex-m4] -# ARM_FPU: [ | vfp] -# FLOAT_ABI: [ | soft | softfp | hard] -# -ARM_CPU := -mcpu=cortex-m4 -ARM_FPU := -mfpu=vfp -FLOAT_ABI := -mfloat-abi=softfp - -#----------------------------------------------------------------------------- -# GNU-ARM toolset (NOTE: You need to adjust to your machine) -# see https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads -# -ifeq ($(GNU_ARM),) -GNU_ARM := $(QTOOLS)/gnu_arm-none-eabi -endif - -# make sure that the GNU-ARM toolset exists... -ifeq ("$(wildcard $(GNU_ARM))","") -$(error GNU_ARM toolset not found. Please adjust the Makefile) -endif - -CC := $(GNU_ARM)/bin/arm-none-eabi-gcc -CPP := $(GNU_ARM)/bin/arm-none-eabi-g++ -AS := $(GNU_ARM)/bin/arm-none-eabi-as -LINK := $(GNU_ARM)/bin/arm-none-eabi-g++ -BIN := $(GNU_ARM)/bin/arm-none-eabi-objcopy - -#----------------------------------------------------------------------------- -# FLASH tool (NOTE: Requires the JLINK utility) -# NOTE: substitution of '/' to '\' is necessary to run the batch file - -FLASH := $(subst /,\,$(TARGET_DIR)/flash.bat) - -############################################################################## -# Typically you should not need to change anything below this line - -# basic utilities (included in QTools for Windows), see: -# https://www.state-machine.com/qtools - -MKDIR := mkdir -RM := rm - -#----------------------------------------------------------------------------- -# QUTest test script utilities (requires QTOOLS): -# -ifeq ("$(wildcard $(QUTEST))","") -QUTEST := python3 $(QTOOLS)/qutest/qutest.py -endif - -#----------------------------------------------------------------------------- -# build options -# - -# combine all the sources... -CPP_SRCS += $(QP_SRCS) -ASM_SRCS += $(QP_ASMS) - -BIN_DIR := build_$(TARGET) - -ASFLAGS = -g $(ARM_CPU) $(ARM_FPU) $(ASM_CPU) $(ASM_FPU) - - -# NOTE: -# Setting -DQ_UTEST=0 means that QUTest should be built WITHOUT -# the QP-stub for testing QP itself -# -CFLAGS = -c -g $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb -Wall \ - -ffunction-sections -fdata-sections \ - -O $(INCLUDES) $(DEFINES) -DQ_SPY -DQ_UTEST=0 - -CPPFLAGS = -c -g $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb -Wall \ - -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions \ - -O $(INCLUDES) $(DEFINES) -DQ_SPY -DQ_UTEST=0 - - -LINKFLAGS = -T$(LD_SCRIPT) $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb \ - -specs=nosys.specs -specs=nano.specs \ - -Wl,-Map,$(BIN_DIR)/$(OUTPUT).map,--cref,--gc-sections $(LIB_DIRS) - -ASM_OBJS := $(patsubst %.s,%.o, $(notdir $(ASM_SRCS))) -C_OBJS := $(patsubst %.c,%.o, $(notdir $(C_SRCS))) -CPP_OBJS := $(patsubst %.cpp,%.o,$(notdir $(CPP_SRCS))) - -TARGET_BIN := $(BIN_DIR)/$(OUTPUT).bin -TARGET_ELF := $(BIN_DIR)/$(OUTPUT).elf -ASM_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(ASM_OBJS)) -C_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(C_OBJS)) -C_DEPS_EXT := $(patsubst %.o, %.d, $(C_OBJS_EXT)) -CPP_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(CPP_OBJS)) -CPP_DEPS_EXT := $(patsubst %.o, %.d, $(CPP_OBJS_EXT)) - -# create $(BIN_DIR) if it does not exist -ifeq ("$(wildcard $(BIN_DIR))","") -$(shell $(MKDIR) $(BIN_DIR)) -endif - -#----------------------------------------------------------------------------- -# rules -# - -.PHONY : run norun debug flash - -ifeq ($(MAKECMDGOALS),norun) -all : $(TARGET_BIN) -norun : all -else -all : $(TARGET_BIN) run -endif - -$(TARGET_BIN) : $(TARGET_ELF) - $(BIN) -O binary $< $@ - $(FLASH) $@ - -$(TARGET_ELF) : $(ASM_OBJS_EXT) $(C_OBJS_EXT) $(CPP_OBJS_EXT) - $(CPP) $(CPPFLAGS) $(QPCPP)/src/qs/qstamp.cpp -o $(BIN_DIR)/qstamp.o - $(LINK) $(LINKFLAGS) -o $@ $^ $(BIN_DIR)/qstamp.o $(LIBS) - -flash : - $(FLASH) $(TARGET_BIN) - -run : $(TARGET_BIN) - $(QUTEST) -q$(QSPY) -l$(LOG) -o$(OPT) -- $(TESTS) - -$(BIN_DIR)/%.d : %.c - $(CC) -MM -MT $(@:.d=.o) $(CFLAGS) $< > $@ - -$(BIN_DIR)/%.d : %.cpp - $(CPP) -MM -MT $(@:.d=.o) $(CPPFLAGS) $< > $@ - -$(BIN_DIR)/%.o : %.s - $(AS) $(ASFLAGS) $< -o $@ - -$(BIN_DIR)/%.o : %.c - $(CC) $(CFLAGS) $< -o $@ - -$(BIN_DIR)/%.o : %.cpp - $(CPP) $(CPPFLAGS) $< -o $@ - -# create BIN_DIR and include dependencies only if needed -ifneq ($(MAKECMDGOALS),clean) - ifneq ($(MAKECMDGOALS),show) - ifneq ($(MAKECMDGOALS),debug) -ifeq ("$(wildcard $(BIN_DIR))","") -$(shell $(MKDIR) $(BIN_DIR)) -endif --include $(C_DEPS_EXT) $(CPP_DEPS_EXT) - endif - endif -endif - -debug : - $(QUTEST) -edebug -q$(QSPY) -l$(LOG) -o$(OPT) -- $(TESTS) - -.PHONY : clean show - -clean : - -$(RM) $(BIN_DIR)/*.o \ - $(BIN_DIR)/*.d \ - $(BIN_DIR)/*.bin \ - $(BIN_DIR)/*.elf \ - $(BIN_DIR)/*.map - -show : - @echo PROJECT = $(PROJECT) - @echo MAKECMDGOALS = $(MAKECMDGOALS) - @echo TESTS = $(TESTS) - @echo TARGET_ELF = $(TARGET_ELF) - @echo CONF = $(CONF) - @echo VPATH = $(VPATH) - @echo C_SRCS = $(C_SRCS) - @echo CPP_SRCS = $(CPP_SRCS) - @echo ASM_SRCS = $(ASM_SRCS) - @echo C_DEPS_EXT = $(C_DEPS_EXT) - @echo C_OBJS_EXT = $(C_OBJS_EXT) - @echo CPP_DEPS_EXT = $(CPP_DEPS_EXT) - @echo CPP_OBJS_EXT = $(CPP_OBJS_EXT) - @echo ASM_OBJS_EXT = $(ASM_OBJS_EXT) - @echo LIB_DIRS = $(LIB_DIRS) - @echo LIBS = $(LIBS) - @echo DEFINES = $(DEFINES) - @echo QTOOLS = $(QTOOLS) - @echo HOST = $(HOST) - @echo QUTEST = $(QUTEST) - @echo FLASH = $(FLASH) - @echo TESTS = $(TESTS) - diff --git a/test/qk/test_sched/nucleo-c031c6.mak b/test/qk/test_sched/nucleo-c031c6.mak deleted file mode 100644 index a4d3cba8f..000000000 --- a/test/qk/test_sched/nucleo-c031c6.mak +++ /dev/null @@ -1,336 +0,0 @@ -############################################################################## -# Product: Makefile for SYSTEM-Level tests of QP/C on NUCLEO-C031c6, GNU-ARM -# Last Updated for Version: 7.3.0 -# Date of the Last Update: 2023-09-06 -# -# Q u a n t u m L e a P s -# ------------------------ -# Modern Embedded Software -# -# Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -# -# This program is open source software: you can redistribute it and/or -# modify it under the terms of the GNU General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Alternatively, this program may be distributed and modified under the -# terms of Quantum Leaps commercial licenses, which expressly supersede -# the GNU General Public License and are specifically designed for -# licensees interested in retaining the proprietary status of their code. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Contact information: -# -# -############################################################################## -# -# examples of invoking this Makefile: -# make -f nucleo-c031c6.mak USB=g: # make, upload to USB drive, run the tests -# make -f nucleo-c031c6.mak USB=g: TESTS=philo*.py # make and run the selected tests -# make -f nucleo-c031c6.mak HOST=localhost:7705 # connect to host:port -# make -f nucleo-c031c6.mak norun # only make but not run the tests -# make -f nucleo-c031c6.mak clean # cleanup the build -# make -f nucleo-c031c6.mak debug # only run tests in DEBUG mode -# -# NOTE: -# To use this Makefile on Windows, you will need the GNU make utility, which -# is included in the QTools collection for Windows, see: -# https://github.com/QuantumLeaps/qtools -# - -# location of the QP/C++ framework (if not provided in an env. variable) -ifeq ($(QPCPP),) -QPCPP := ../../.. -endif - -#----------------------------------------------------------------------------- -# project name, target name, target directory: -# -PROJECT := test_sched -TARGET := nucleo-c031c6 -TARGET_DIR := $(QPCPP)/3rd_party/nucleo-c031c6/qutest - -#----------------------------------------------------------------------------- -# project directories: -# - -# QP port used in this project -QP_PORT_DIR := $(QPCPP)/ports/arm-cm/qk/gnu - -# make sure that QTOOLS env. variable is defined... -ifeq ("$(wildcard $(QTOOLS))","") -$(error QTOOLS not found. Please install QTools and define QTOOLS env. variable) -endif - - -# list of all source directories used by this project -VPATH := . \ - $(QPCPP)/src/qf \ - $(QPCPP)/src/qk \ - $(QPCPP)/src/qs \ - $(QP_PORT_DIR) \ - $(TARGET_DIR) \ - $(QPCPP)/3rd_party/nucleo-c031c6 \ - $(QPCPP)/3rd_party/nucleo-c031c6/gnu - -# list of all include directories needed by this project -INCLUDES = -I. \ - -I$(QPCPP)/include \ - -I$(QP_PORT_DIR) \ - -I$(TARGET_DIR) \ - -I$(QPCPP)/3rd_party/CMSIS/Include \ - -I$(QPCPP)/3rd_party/nucleo-c031c6 - -#----------------------------------------------------------------------------- -# project files: -# - -# assembler source files -ASM_SRCS := - -# C source files -C_SRCS := \ - system_stm32c0xx.c \ - startup_stm32c031xx.c - -# C++ source files -CPP_SRCS := \ - test_sched.cpp \ - bsp_nucleo-c031c6.cpp - -OUTPUT := $(PROJECT) -LD_SCRIPT := $(TARGET_DIR)/qutest.ld - -QP_SRCS := \ - qep_hsm.cpp \ - qep_msm.cpp \ - qf_act.cpp \ - qf_actq.cpp \ - qf_defer.cpp \ - qf_dyn.cpp \ - qf_mem.cpp \ - qf_ps.cpp \ - qf_qact.cpp \ - qf_qeq.cpp \ - qf_qmact.cpp \ - qf_time.cpp \ - qk.cpp \ - qk_port.cpp \ - qs.cpp \ - qs_64bit.cpp \ - qs_rx.cpp \ - qs_fp.cpp \ - qutest.cpp \ - qutest_cpp.cpp - -QP_ASMS := - -LIB_DIRS := -LIBS := - -# defines -DEFINES := -DSTM32C031xx \ - -DQP_API_VERSION=9999 \ - -DQK_USE_IRQ_HANDLER=Reserved1_IRQHandler \ - -DQK_USE_IRQ_NUM=1 \ - -DQF_ON_CONTEXT_SW - -# ARM CPU, ARCH, FPU, and Float-ABI types... -# ARM_CPU: [cortex-m0 | cortex-m0plus | cortex-m1 | cortex-m3 | cortex-m4] -# ARM_FPU: [ | vfp] -# FLOAT_ABI: [ | soft | softfp | hard] -# -ARM_CPU := -mcpu=cortex-m0plus -ARM_FPU := -FLOAT_ABI := - -#----------------------------------------------------------------------------- -# GNU-ARM toolset (NOTE: You need to adjust to your machine) -# see https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads -# -ifeq ($(GNU_ARM),) -GNU_ARM := $(QTOOLS)/gnu_arm-none-eabi -endif - -# make sure that the GNU-ARM toolset exists... -ifeq ("$(wildcard $(GNU_ARM))","") -$(error GNU_ARM toolset not found. Please adjust the Makefile) -endif - -CC := $(GNU_ARM)/bin/arm-none-eabi-gcc -CPP := $(GNU_ARM)/bin/arm-none-eabi-g++ -AS := $(GNU_ARM)/bin/arm-none-eabi-as -LINK := $(GNU_ARM)/bin/arm-none-eabi-g++ -BIN := $(GNU_ARM)/bin/arm-none-eabi-objcopy - -#----------------------------------------------------------------------------- -# NOTE: The symbol USB must be provided for the NUCLEO board -# has enumerated as USB drive f: -# -ifeq ($(USB),) -$(error USB drive not provided for the NUCLEO board.) -endif - -############################################################################## -# Typically you should not need to change anything below this line - -# basic utilities (included in QTools for Windows), see: -# https://www.state-machine.com/qtools - -MKDIR := mkdir -RM := rm -CP := cp -SLEEP := sleep - -#----------------------------------------------------------------------------- -# QUTest test script utilities (requires QTOOLS): -# -ifeq ("$(wildcard $(QUTEST))","") -QUTEST := python3 $(QTOOLS)/qutest/qutest.py -endif - -#----------------------------------------------------------------------------- -# build options -# - -# combine all the sources... -CPP_SRCS += $(QP_SRCS) -ASM_SRCS += $(QP_ASMS) - -BIN_DIR := build_$(TARGET) - -ASFLAGS = -g $(ARM_CPU) $(ARM_FPU) $(ASM_CPU) $(ASM_FPU) - - -# NOTE: -# Setting -DQ_UTEST=0 means that QUTest should be built WITHOUT -# the QP-stub for testing QP itself -# -CFLAGS = -c -g $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb -Wall \ - -ffunction-sections -fdata-sections \ - -O $(INCLUDES) $(DEFINES) -DQ_SPY -DQ_UTEST=0 - -CPPFLAGS = -c -g $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb -Wall \ - -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions \ - -O $(INCLUDES) $(DEFINES) -DQ_SPY -DQ_UTEST=0 - - -LINKFLAGS = -T$(LD_SCRIPT) $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb \ - -specs=nosys.specs -specs=nano.specs \ - -Wl,-Map,$(BIN_DIR)/$(OUTPUT).map,--cref,--gc-sections $(LIB_DIRS) - -ASM_OBJS := $(patsubst %.s,%.o, $(notdir $(ASM_SRCS))) -C_OBJS := $(patsubst %.c,%.o, $(notdir $(C_SRCS))) -CPP_OBJS := $(patsubst %.cpp,%.o,$(notdir $(CPP_SRCS))) - -TARGET_BIN := $(BIN_DIR)/$(OUTPUT).bin -TARGET_ELF := $(BIN_DIR)/$(OUTPUT).elf -ASM_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(ASM_OBJS)) -C_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(C_OBJS)) -C_DEPS_EXT := $(patsubst %.o, %.d, $(C_OBJS_EXT)) -CPP_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(CPP_OBJS)) -CPP_DEPS_EXT := $(patsubst %.o, %.d, $(CPP_OBJS_EXT)) - -# create $(BIN_DIR) if it does not exist -ifeq ("$(wildcard $(BIN_DIR))","") -$(shell $(MKDIR) $(BIN_DIR)) -endif - -#----------------------------------------------------------------------------- -# rules -# - -.PHONY : run norun debug flash - -ifeq ($(MAKECMDGOALS),norun) -all : $(TARGET_BIN) -norun : all -else -all : $(TARGET_BIN) run -endif - -$(TARGET_BIN) : $(TARGET_ELF) - $(BIN) -O binary $< $@ - $(CP) $@ $(USB) - $(SLEEP) 2 - -$(TARGET_ELF) : $(ASM_OBJS_EXT) $(C_OBJS_EXT) $(CPP_OBJS_EXT) - $(CPP) $(CPPFLAGS) $(QPCPP)/src/qs/qstamp.cpp -o $(BIN_DIR)/qstamp.o - $(LINK) $(LINKFLAGS) -o $@ $^ $(BIN_DIR)/qstamp.o $(LIBS) - -flash : - $(CP) $(TARGET_BIN) $(USB) - -run : $(TARGET_BIN) - $(QUTEST) -q$(QSPY) -l$(LOG) -o$(OPT) -- $(TESTS) - -$(BIN_DIR)/%.d : %.c - $(CC) -MM -MT $(@:.d=.o) $(CFLAGS) $< > $@ - -$(BIN_DIR)/%.d : %.cpp - $(CPP) -MM -MT $(@:.d=.o) $(CPPFLAGS) $< > $@ - -$(BIN_DIR)/%.o : %.s - $(AS) $(ASFLAGS) $< -o $@ - -$(BIN_DIR)/%.o : %.c - $(CC) $(CFLAGS) $< -o $@ - -$(BIN_DIR)/%.o : %.cpp - $(CPP) $(CPPFLAGS) $< -o $@ - -# create BIN_DIR and include dependencies only if needed -ifneq ($(MAKECMDGOALS),clean) - ifneq ($(MAKECMDGOALS),show) - ifneq ($(MAKECMDGOALS),debug) -ifeq ("$(wildcard $(BIN_DIR))","") -$(shell $(MKDIR) $(BIN_DIR)) -endif --include $(C_DEPS_EXT) $(CPP_DEPS_EXT) - endif - endif -endif - -debug : - $(QUTEST) -edebug -q$(QSPY) -l$(LOG) -o$(OPT) -- $(TESTS) - -.PHONY : clean show - -clean : - -$(RM) $(BIN_DIR)/*.o \ - $(BIN_DIR)/*.d \ - $(BIN_DIR)/*.bin \ - $(BIN_DIR)/*.elf \ - $(BIN_DIR)/*.map - -show : - @echo PROJECT = $(PROJECT) - @echo MAKECMDGOALS = $(MAKECMDGOALS) - @echo TESTS = $(TESTS) - @echo TARGET_ELF = $(TARGET_ELF) - @echo CONF = $(CONF) - @echo VPATH = $(VPATH) - @echo C_SRCS = $(C_SRCS) - @echo CPP_SRCS = $(CPP_SRCS) - @echo ASM_SRCS = $(ASM_SRCS) - @echo C_DEPS_EXT = $(C_DEPS_EXT) - @echo C_OBJS_EXT = $(C_OBJS_EXT) - @echo CPP_DEPS_EXT = $(CPP_DEPS_EXT) - @echo CPP_OBJS_EXT = $(CPP_OBJS_EXT) - @echo ASM_OBJS_EXT = $(ASM_OBJS_EXT) - @echo LIB_DIRS = $(LIB_DIRS) - @echo LIBS = $(LIBS) - @echo DEFINES = $(DEFINES) - @echo QTOOLS = $(QTOOLS) - @echo HOST = $(HOST) - @echo QUTEST = $(QUTEST) - @echo TESTS = $(TESTS) - diff --git a/test/qk/test_sched/nucleo-h743zi.mak b/test/qk/test_sched/nucleo-h743zi.mak deleted file mode 100644 index 182f1d3fa..000000000 --- a/test/qk/test_sched/nucleo-h743zi.mak +++ /dev/null @@ -1,347 +0,0 @@ -############################################################################## -# Product: Makefile for QP/C on NUCLEO-H743ZI board, QUTEST, GNU-ARM -# Last Updated for Version: 7.3.0 -# Date of the Last Update: 2023-09-06 -# -# Q u a n t u m L e a P s -# ------------------------ -# Modern Embedded Software -# -# Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -# -# This program is open source software: you can redistribute it and/or -# modify it under the terms of the GNU General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Alternatively, this program may be distributed and modified under the -# terms of Quantum Leaps commercial licenses, which expressly supersede -# the GNU General Public License and are specifically designed for -# licensees interested in retaining the proprietary status of their code. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Contact information: -# -# -############################################################################## -# -# examples of invoking this Makefile: -# make -f nucleo-h743zi.mak USB=g: # make, upload to USB drive, run the tests -# make -f nucleo-h743zi.mak USB=g: TESTS=philo*.py # make and run the selected tests -# make -f nucleo-h743zi.mak USB=g: HOST=localhost:7705 # connect to host:port -# make -f nucleo-h743zi.mak USB=g: norun # only make but not run the tests -# make -f nucleo-h743zi.mak USB=g: clean # cleanup the build -# make -f nucleo-h743zi.mak USB=g: debug # only run tests in DEBUG mode -# -# NOTE: -# To use this Makefile on Windows, you will need the GNU make utility, which -# is included in the QTools collection for Windows, see: -# https://github.com/QuantumLeaps/qtools -# - -# location of the QP/C++ framework (if not provided in an env. variable) -ifeq ($(QPCPP),) -QPCPP := ../../.. -endif - -#----------------------------------------------------------------------------- -# project name, target name, target directory: -# -PROJECT := test_sched -TARGET := nucleo-h743zi -TARGET_DIR := $(QPCPP)/3rd_party/STM32CubeH7/qutest - -#----------------------------------------------------------------------------- -# project directories: -# - -# QP port used in this project -QP_PORT_DIR := $(QPCPP)/ports/arm-cm/qk/gnu - -# make sure that QTOOLS env. variable is defined... -ifeq ("$(wildcard $(QTOOLS))","") -$(error QTOOLS not found. Please install QTools and define QTOOLS env. variable) -endif - - -# list of all source directories used by this project -VPATH := . \ - $(QPCPP)/src/qf \ - $(QPCPP)/src/qk \ - $(QPCPP)/src/qs \ - $(QP_PORT_DIR) \ - $(TARGET_DIR) \ - $(QPCPP)/3rd_party/STM32CubeH7/nucleo-h743zi/gnu \ - $(QPCPP)/3rd_party/STM32CubeH7/Drivers/BSP\STM32H7xx_Nucleo_144 \ - $(QPCPP)/3rd_party/STM32CubeH7/Drivers/STM32H7xx_HAL_Driver/Src \ - $(QPCPP)/3rd_party/STM32CubeH7/Drivers/CMSIS/Device/ST/STM32H7xx/Source/Templates - -# list of all include directories needed by this project -INCLUDES = -I. \ - -I$(QPCPP)/include \ - -I$(QP_PORT_DIR) \ - -I$(TARGET_DIR) \ - -I$(QPCPP)/3rd_party/CMSIS/Include \ - -I$(QPCPP)/3rd_party/STM32CubeH7/Drivers/CMSIS/Device/ST/STM32H7xx/Include \ - -I$(QPCPP)/3rd_party/STM32CubeH7/Drivers/BSP/STM32H7xx_Nucleo_144 \ - -I$(QPCPP)/3rd_party/STM32CubeH7/Drivers/STM32H7xx_HAL_Driver/Inc - -#----------------------------------------------------------------------------- -# project files: -# - -# assembler source files -ASM_SRCS := - -# C source files -C_SRCS := \ - startup_stm32h743xx.c \ - system_stm32h7xx.c \ - stm32h7xx_nucleo_144.c \ - stm32h7xx_hal.c \ - stm32h7xx_hal_cortex.c \ - stm32h7xx_hal_gpio.c \ - stm32h7xx_hal_pwr_ex.c \ - stm32h7xx_hal_rcc.c \ - stm32h7xx_hal_rcc_ex.c \ - stm32h7xx_hal_msp.c \ - stm32h7xx_hal_uart.c - -# C++ source files -CPP_SRCS := \ - test_sched.cpp \ - bsp_nucleo-h743zi.cpp - -OUTPUT := $(PROJECT) -LD_SCRIPT := $(TARGET_DIR)/qutest.ld - -QP_SRCS := \ - qep_hsm.cpp \ - qep_msm.cpp \ - qf_act.cpp \ - qf_actq.cpp \ - qf_defer.cpp \ - qf_dyn.cpp \ - qf_mem.cpp \ - qf_ps.cpp \ - qf_qact.cpp \ - qf_qeq.cpp \ - qf_qmact.cpp \ - qf_time.cpp \ - qk.cpp \ - qk_port.cpp \ - qs.cpp \ - qs_64bit.cpp \ - qs_rx.cpp \ - qs_fp.cpp \ - qutest.cpp \ - qutest_cpp.cpp - -QP_ASMS := - -LIB_DIRS := -LIBS := - -# defines -DEFINES := -DQP_API_VERSION=9999 \ - -DSTM32H743xx -DUSE_HAL_DRIVER -DUSE_STM32H7XX_NUCLEO_144 \ - -DQF_ON_CONTEXT_SW - -# ARM CPU, ARCH, FPU, and Float-ABI types... -# ARM_CPU: [cortex-m0 | cortex-m0plus | cortex-m1 | cortex-m3 | cortex-m4] -# ARM_FPU: [ | vfp] -# FLOAT_ABI: [ | soft | softfp | hard] -# -ARM_CPU := -mcpu=cortex-m7 -ARM_FPU := -mfpu=fpv5-d16 -FLOAT_ABI := -mfloat-abi=softfp - -#----------------------------------------------------------------------------- -# GNU-ARM toolset (NOTE: You need to adjust to your machine) -# see https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads -# -ifeq ($(GNU_ARM),) -GNU_ARM := $(QTOOLS)/gnu_arm-none-eabi -endif - -# make sure that the GNU-ARM toolset exists... -ifeq ("$(wildcard $(GNU_ARM))","") -$(error GNU_ARM toolset not found. Please adjust the Makefile) -endif - -CC := $(GNU_ARM)/bin/arm-none-eabi-gcc -CPP := $(GNU_ARM)/bin/arm-none-eabi-g++ -AS := $(GNU_ARM)/bin/arm-none-eabi-as -LINK := $(GNU_ARM)/bin/arm-none-eabi-g++ -BIN := $(GNU_ARM)/bin/arm-none-eabi-objcopy - -#----------------------------------------------------------------------------- -# NOTE: The symbol USB must be provided for the NUCLEO board -# has enumerated as USB drive f: -# -ifeq ($(USB),) -$(error USB drive not provided for the NUCLEO board.) -endif - -############################################################################## -# Typically you should not need to change anything below this line - -# basic utilities (included in QTools for Windows), see: -# https://www.state-machine.com/qtools - -MKDIR := mkdir -RM := rm -CP := cp -SLEEP := sleep - -#----------------------------------------------------------------------------- -# QUTest test script utilities (requires QTOOLS): -# -ifeq ("$(wildcard $(QUTEST))","") -QUTEST := python3 $(QTOOLS)/qutest/qutest.py -endif - -#----------------------------------------------------------------------------- -# build options -# - -# combine all the sources... -CPP_SRCS += $(QP_SRCS) -ASM_SRCS += $(QP_ASMS) - -BIN_DIR := build_$(TARGET) - -ASFLAGS = -g $(ARM_CPU) $(ARM_FPU) $(ASM_CPU) $(ASM_FPU) - - -# NOTE: -# Setting -DQ_UTEST=0 means that QUTest should be built WITHOUT -# the QP-stub for testing QP itself -# -CFLAGS = -c -g $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb -Wall \ - -ffunction-sections -fdata-sections \ - -O $(INCLUDES) $(DEFINES) -DQ_SPY -DQ_UTEST=0 - -CPPFLAGS = -c -g $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb -Wall \ - -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions \ - -O $(INCLUDES) $(DEFINES) -DQ_SPY -DQ_UTEST=0 - - -LINKFLAGS = -T$(LD_SCRIPT) $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb \ - -specs=nosys.specs -specs=nano.specs \ - -Wl,-Map,$(BIN_DIR)/$(OUTPUT).map,--cref,--gc-sections $(LIB_DIRS) - -ASM_OBJS := $(patsubst %.s,%.o, $(notdir $(ASM_SRCS))) -C_OBJS := $(patsubst %.c,%.o, $(notdir $(C_SRCS))) -CPP_OBJS := $(patsubst %.cpp,%.o,$(notdir $(CPP_SRCS))) - -TARGET_BIN := $(BIN_DIR)/$(OUTPUT).bin -TARGET_ELF := $(BIN_DIR)/$(OUTPUT).elf -ASM_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(ASM_OBJS)) -C_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(C_OBJS)) -C_DEPS_EXT := $(patsubst %.o, %.d, $(C_OBJS_EXT)) -CPP_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(CPP_OBJS)) -CPP_DEPS_EXT := $(patsubst %.o, %.d, $(CPP_OBJS_EXT)) - -# create $(BIN_DIR) if it does not exist -ifeq ("$(wildcard $(BIN_DIR))","") -$(shell $(MKDIR) $(BIN_DIR)) -endif - -#----------------------------------------------------------------------------- -# rules -# - -.PHONY : run norun debug flash - -ifeq ($(MAKECMDGOALS),norun) -all : $(TARGET_BIN) -norun : all -else -all : $(TARGET_BIN) run -endif - -$(TARGET_BIN) : $(TARGET_ELF) - $(BIN) -O binary $< $@ - $(CP) $@ $(USB) - $(SLEEP) 2 - -$(TARGET_ELF) : $(ASM_OBJS_EXT) $(C_OBJS_EXT) $(CPP_OBJS_EXT) - $(CPP) $(CPPFLAGS) $(QPCPP)/src/qs/qstamp.cpp -o $(BIN_DIR)/qstamp.o - $(LINK) $(LINKFLAGS) -o $@ $^ $(BIN_DIR)/qstamp.o $(LIBS) - -flash : - $(CP) $(TARGET_BIN) $(USB) - -run : $(TARGET_BIN) - $(QUTEST) -q$(QSPY) -l$(LOG) -o$(OPT) -- $(TESTS) - -$(BIN_DIR)/%.d : %.c - $(CC) -MM -MT $(@:.d=.o) $(CFLAGS) $< > $@ - -$(BIN_DIR)/%.d : %.cpp - $(CPP) -MM -MT $(@:.d=.o) $(CPPFLAGS) $< > $@ - -$(BIN_DIR)/%.o : %.s - $(AS) $(ASFLAGS) $< -o $@ - -$(BIN_DIR)/%.o : %.c - $(CC) $(CFLAGS) $< -o $@ - -$(BIN_DIR)/%.o : %.cpp - $(CPP) $(CPPFLAGS) $< -o $@ - -# create BIN_DIR and include dependencies only if needed -ifneq ($(MAKECMDGOALS),clean) - ifneq ($(MAKECMDGOALS),show) - ifneq ($(MAKECMDGOALS),debug) -ifeq ("$(wildcard $(BIN_DIR))","") -$(shell $(MKDIR) $(BIN_DIR)) -endif --include $(C_DEPS_EXT) $(CPP_DEPS_EXT) - endif - endif -endif - -debug : - $(QUTEST) -edebug -q$(QSPY) -l$(LOG) -o$(OPT) -- $(TESTS) - -.PHONY : clean show - -clean : - -$(RM) $(BIN_DIR)/*.o \ - $(BIN_DIR)/*.d \ - $(BIN_DIR)/*.bin \ - $(BIN_DIR)/*.elf \ - $(BIN_DIR)/*.map - -show : - @echo PROJECT = $(PROJECT) - @echo MAKECMDGOALS = $(MAKECMDGOALS) - @echo TESTS = $(TESTS) - @echo TARGET_ELF = $(TARGET_ELF) - @echo CONF = $(CONF) - @echo VPATH = $(VPATH) - @echo C_SRCS = $(C_SRCS) - @echo CPP_SRCS = $(CPP_SRCS) - @echo ASM_SRCS = $(ASM_SRCS) - @echo C_DEPS_EXT = $(C_DEPS_EXT) - @echo C_OBJS_EXT = $(C_OBJS_EXT) - @echo CPP_DEPS_EXT = $(CPP_DEPS_EXT) - @echo CPP_OBJS_EXT = $(CPP_OBJS_EXT) - @echo ASM_OBJS_EXT = $(ASM_OBJS_EXT) - @echo LIB_DIRS = $(LIB_DIRS) - @echo LIBS = $(LIBS) - @echo DEFINES = $(DEFINES) - @echo QTOOLS = $(QTOOLS) - @echo HOST = $(HOST) - @echo QUTEST = $(QUTEST) - @echo TESTS = $(TESTS) - diff --git a/test/qk/test_sched/nucleo-l053r8.mak b/test/qk/test_sched/nucleo-l053r8.mak deleted file mode 100644 index a2d55eb24..000000000 --- a/test/qk/test_sched/nucleo-l053r8.mak +++ /dev/null @@ -1,333 +0,0 @@ -############################################################################## -# Product: Makefile for SYSTEM-Level tests of QP/C on NUCLEO-L053R8, GNU-ARM -# Last Updated for Version: 7.3.1 -# Date of the Last Update: 2023-11-13 -# -# Q u a n t u m L e a P s -# ------------------------ -# Modern Embedded Software -# -# Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -# -# This program is open source software: you can redistribute it and/or -# modify it under the terms of the GNU General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Alternatively, this program may be distributed and modified under the -# terms of Quantum Leaps commercial licenses, which expressly supersede -# the GNU General Public License and are specifically designed for -# licensees interested in retaining the proprietary status of their code. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Contact information: -# -# -############################################################################## -# -# examples of invoking this Makefile: -# make -f nucleo-l053r8.mak USB=g: # make, upload to USB drive, run the tests -# make -f nucleo-l053r8.mak USB=g: TESTS=philo*.py # make and run the selected tests -# make -f nucleo-l053r8.mak HOST=localhost:7705 # connect to host:port -# make -f nucleo-l053r8.mak norun # only make but not run the tests -# make -f nucleo-l053r8.mak clean # cleanup the build -# make -f nucleo-l053r8.mak debug # only run tests in DEBUG mode -# -# NOTE: -# To use this Makefile on Windows, you will need the GNU make utility, which -# is included in the QTools collection for Windows, see: -# https://github.com/QuantumLeaps/qtools -# - -# location of the QP/C++ framework (if not provided in an env. variable) -ifeq ($(QPCPP),) -QPCPP := ../../.. -endif - -#----------------------------------------------------------------------------- -# project name, target name, target directory: -# -PROJECT := test_sched -TARGET := nucleo-l053r8 -TARGET_DIR := $(QPCPP)/3rd_party/nucleo-l053r8/qutest - -#----------------------------------------------------------------------------- -# project directories: -# - -# QP port used in this project -QP_PORT_DIR := $(QPCPP)/ports/arm-cm/qk/gnu - -# make sure that QTOOLS env. variable is defined... -ifeq ("$(wildcard $(QTOOLS))","") -$(error QTOOLS not found. Please install QTools and define QTOOLS env. variable) -endif - - -# list of all source directories used by this project -VPATH := . \ - $(QPCPP)/src/qf \ - $(QPCPP)/src/qk \ - $(QPCPP)/src/qs \ - $(QP_PORT_DIR) \ - $(TARGET_DIR) \ - $(QPCPP)/3rd_party/nucleo-l053r8 \ - $(QPCPP)/3rd_party/nucleo-l053r8/gnu - -# list of all include directories needed by this project -INCLUDES = -I. \ - -I$(QPCPP)/include \ - -I$(QP_PORT_DIR) \ - -I$(TARGET_DIR) \ - -I$(QPCPP)/3rd_party/CMSIS/Include \ - -I$(QPCPP)/3rd_party/nucleo-l053r8 - -#----------------------------------------------------------------------------- -# project files: -# - -# assembler source files -ASM_SRCS := - -# C source files -C_SRCS := \ - system_stm32l0xx.c \ - startup_stm32l053xx.c - -# C++ source files -CPP_SRCS := \ - test_sched.cpp \ - bsp_nucleo-l053r8.cpp - -OUTPUT := $(PROJECT) -LD_SCRIPT := $(TARGET_DIR)/qutest.ld - -QP_SRCS := \ - qep_hsm.cpp \ - qep_msm.cpp \ - qf_act.cpp \ - qf_actq.cpp \ - qf_defer.cpp \ - qf_dyn.cpp \ - qf_mem.cpp \ - qf_ps.cpp \ - qf_qact.cpp \ - qf_qeq.cpp \ - qf_qmact.cpp \ - qf_time.cpp \ - qk.cpp \ - qk_port.cpp \ - qs.cpp \ - qs_64bit.cpp \ - qs_rx.cpp \ - qs_fp.cpp \ - qutest.cpp \ - qutest_cpp.cpp - -QP_ASMS := - -LIB_DIRS := -LIBS := - -# defines -DEFINES := -DSTM32L053xx \ - -DQF_ON_CONTEXT_SW - -# ARM CPU, ARCH, FPU, and Float-ABI types... -# ARM_CPU: [cortex-m0 | cortex-m0plus | cortex-m1 | cortex-m3 | cortex-m4] -# ARM_FPU: [ | vfp] -# FLOAT_ABI: [ | soft | softfp | hard] -# -ARM_CPU := -mcpu=cortex-m0plus -ARM_FPU := -FLOAT_ABI := - -#----------------------------------------------------------------------------- -# GNU-ARM toolset (NOTE: You need to adjust to your machine) -# see https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads -# -ifeq ($(GNU_ARM),) -GNU_ARM := $(QTOOLS)/gnu_arm-none-eabi -endif - -# make sure that the GNU-ARM toolset exists... -ifeq ("$(wildcard $(GNU_ARM))","") -$(error GNU_ARM toolset not found. Please adjust the Makefile) -endif - -CC := $(GNU_ARM)/bin/arm-none-eabi-gcc -CPP := $(GNU_ARM)/bin/arm-none-eabi-g++ -AS := $(GNU_ARM)/bin/arm-none-eabi-as -LINK := $(GNU_ARM)/bin/arm-none-eabi-g++ -BIN := $(GNU_ARM)/bin/arm-none-eabi-objcopy - -#----------------------------------------------------------------------------- -# NOTE: The symbol USB must be provided for the NUCLEO board -# has enumerated as USB drive f: -# -ifeq ($(USB),) -$(error USB drive not provided for the NUCLEO board.) -endif - -############################################################################## -# Typically you should not need to change anything below this line - -# basic utilities (included in QTools for Windows), see: -# https://www.state-machine.com/qtools - -MKDIR := mkdir -RM := rm -CP := cp -SLEEP := sleep - -#----------------------------------------------------------------------------- -# QUTest test script utilities (requires QTOOLS): -# -ifeq ("$(wildcard $(QUTEST))","") -QUTEST := python3 $(QTOOLS)/qutest/qutest.py -endif - -#----------------------------------------------------------------------------- -# build options -# - -# combine all the sources... -CPP_SRCS += $(QP_SRCS) -ASM_SRCS += $(QP_ASMS) - -BIN_DIR := build_$(TARGET) - -ASFLAGS = -g $(ARM_CPU) $(ARM_FPU) $(ASM_CPU) $(ASM_FPU) - - -# NOTE: -# Setting -DQ_UTEST=0 means that QUTest should be built WITHOUT -# the QP-stub for testing QP itself -# -CFLAGS = -c -g $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb -Wall \ - -ffunction-sections -fdata-sections \ - -O $(INCLUDES) $(DEFINES) -DQ_SPY -DQ_UTEST=0 - -CPPFLAGS = -c -g $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb -Wall \ - -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions \ - -O $(INCLUDES) $(DEFINES) -DQ_SPY -DQ_UTEST=0 - - -LINKFLAGS = -T$(LD_SCRIPT) $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb \ - -specs=nosys.specs -specs=nano.specs \ - -Wl,-Map,$(BIN_DIR)/$(OUTPUT).map,--cref,--gc-sections $(LIB_DIRS) - -ASM_OBJS := $(patsubst %.s,%.o, $(notdir $(ASM_SRCS))) -C_OBJS := $(patsubst %.c,%.o, $(notdir $(C_SRCS))) -CPP_OBJS := $(patsubst %.cpp,%.o,$(notdir $(CPP_SRCS))) - -TARGET_BIN := $(BIN_DIR)/$(OUTPUT).bin -TARGET_ELF := $(BIN_DIR)/$(OUTPUT).elf -ASM_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(ASM_OBJS)) -C_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(C_OBJS)) -C_DEPS_EXT := $(patsubst %.o, %.d, $(C_OBJS_EXT)) -CPP_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(CPP_OBJS)) -CPP_DEPS_EXT := $(patsubst %.o, %.d, $(CPP_OBJS_EXT)) - -# create $(BIN_DIR) if it does not exist -ifeq ("$(wildcard $(BIN_DIR))","") -$(shell $(MKDIR) $(BIN_DIR)) -endif - -#----------------------------------------------------------------------------- -# rules -# - -.PHONY : run norun debug flash - -ifeq ($(MAKECMDGOALS),norun) -all : $(TARGET_BIN) -norun : all -else -all : $(TARGET_BIN) run -endif - -$(TARGET_BIN) : $(TARGET_ELF) - $(BIN) -O binary $< $@ - $(CP) $@ $(USB) - $(SLEEP) 2 - -$(TARGET_ELF) : $(ASM_OBJS_EXT) $(C_OBJS_EXT) $(CPP_OBJS_EXT) - $(CPP) $(CPPFLAGS) $(QPCPP)/src/qs/qstamp.cpp -o $(BIN_DIR)/qstamp.o - $(LINK) $(LINKFLAGS) -o $@ $^ $(BIN_DIR)/qstamp.o $(LIBS) - -flash : - $(CP) $(TARGET_BIN) $(USB) - -run : $(TARGET_BIN) - $(QUTEST) -q$(QSPY) -l$(LOG) -o$(OPT) -- $(TESTS) - -$(BIN_DIR)/%.d : %.c - $(CC) -MM -MT $(@:.d=.o) $(CFLAGS) $< > $@ - -$(BIN_DIR)/%.d : %.cpp - $(CPP) -MM -MT $(@:.d=.o) $(CPPFLAGS) $< > $@ - -$(BIN_DIR)/%.o : %.s - $(AS) $(ASFLAGS) $< -o $@ - -$(BIN_DIR)/%.o : %.c - $(CC) $(CFLAGS) $< -o $@ - -$(BIN_DIR)/%.o : %.cpp - $(CPP) $(CPPFLAGS) $< -o $@ - -# create BIN_DIR and include dependencies only if needed -ifneq ($(MAKECMDGOALS),clean) - ifneq ($(MAKECMDGOALS),show) - ifneq ($(MAKECMDGOALS),debug) -ifeq ("$(wildcard $(BIN_DIR))","") -$(shell $(MKDIR) $(BIN_DIR)) -endif --include $(C_DEPS_EXT) $(CPP_DEPS_EXT) - endif - endif -endif - -debug : - $(QUTEST) -edebug -q$(QSPY) -l$(LOG) -o$(OPT) -- $(TESTS) - -.PHONY : clean show - -clean : - -$(RM) $(BIN_DIR)/*.o \ - $(BIN_DIR)/*.d \ - $(BIN_DIR)/*.bin \ - $(BIN_DIR)/*.elf \ - $(BIN_DIR)/*.map - -show : - @echo PROJECT = $(PROJECT) - @echo MAKECMDGOALS = $(MAKECMDGOALS) - @echo TESTS = $(TESTS) - @echo TARGET_ELF = $(TARGET_ELF) - @echo CONF = $(CONF) - @echo VPATH = $(VPATH) - @echo C_SRCS = $(C_SRCS) - @echo CPP_SRCS = $(CPP_SRCS) - @echo ASM_SRCS = $(ASM_SRCS) - @echo C_DEPS_EXT = $(C_DEPS_EXT) - @echo C_OBJS_EXT = $(C_OBJS_EXT) - @echo CPP_DEPS_EXT = $(CPP_DEPS_EXT) - @echo CPP_OBJS_EXT = $(CPP_OBJS_EXT) - @echo ASM_OBJS_EXT = $(ASM_OBJS_EXT) - @echo LIB_DIRS = $(LIB_DIRS) - @echo LIBS = $(LIBS) - @echo DEFINES = $(DEFINES) - @echo QTOOLS = $(QTOOLS) - @echo HOST = $(HOST) - @echo QUTEST = $(QUTEST) - @echo TESTS = $(TESTS) - diff --git a/test/qk/test_sched/nucleo-u545re.mak b/test/qk/test_sched/nucleo-u545re.mak deleted file mode 100644 index c21d0d6a0..000000000 --- a/test/qk/test_sched/nucleo-u545re.mak +++ /dev/null @@ -1,334 +0,0 @@ -############################################################################## -# Product: Makefile for SYSTEM-Level tests of QP/C++ on NUCLEO-U545RE-Q, GNU-ARM -# Last Updated for Version: 7.4.0 -# Date of the Last Update: 2024-06-23 -# -# Q u a n t u m L e a P s -# ------------------------ -# Modern Embedded Software -# -# Copyright (C) 2005 Quantum Leaps, LLC. -# -# This program is open source software: you can redistribute it and/or -# modify it under the terms of the GNU General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Alternatively, this program may be distributed and modified under the -# terms of Quantum Leaps commercial licenses, which expressly supersede -# the GNU General Public License and are specifically designed for -# licensees interested in retaining the proprietary status of their code. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Contact information: -# -# -############################################################################## -# -# examples of invoking this Makefile: -# make -f nucleo-u545re.mak USB=g: # make, upload to USB drive, run the tests -# make -f nucleo-u545re.mak USB=g: TESTS=philo*.py # make and run the selected tests -# make -f nucleo-u545re.mak HOST=localhost:7705 # connect to host:port -# make -f nucleo-u545re.mak norun # only make but not run the tests -# make -f nucleo-u545re.mak clean # cleanup the build -# make -f nucleo-u545re.mak debug # only run tests in DEBUG mode -# -# NOTE: -# To use this Makefile on Windows, you will need the GNU make utility, which -# is included in the QTools collection for Windows, see: -# https://github.com/QuantumLeaps/qtools -# - -# location of the QP/C++ framework (if not provided in an env. variable) -ifeq ($(QPCPP),) -QPCPP := ../../.. -endif - -#----------------------------------------------------------------------------- -# project name, target name, target directory: -# -PROJECT := test_sched -TARGET := nucleo-u545re -TARGET_DIR := $(QPCPP)/3rd_party/nucleo-u545re/qutest - -#----------------------------------------------------------------------------- -# project directories: -# - -# QP port used in this project -QP_PORT_DIR := $(QPCPP)/ports/arm-cm/qk/gnu - -# make sure that QTOOLS env. variable is defined... -ifeq ("$(wildcard $(QTOOLS))","") -$(error QTOOLS not found. Please install QTools and define QTOOLS env. variable) -endif - - -# list of all source directories used by this project -VPATH := . \ - $(QPCPP)/src/qf \ - $(QPCPP)/src/qk \ - $(QPCPP)/src/qs \ - $(QP_PORT_DIR) \ - $(TARGET_DIR) \ - $(QPCPP)/3rd_party/nucleo-u545re \ - $(QPCPP)/3rd_party/nucleo-u545re/gnu - -# list of all include directories needed by this project -INCLUDES = -I. \ - -I$(QPCPP)/include \ - -I$(QP_PORT_DIR) \ - -I$(TARGET_DIR) \ - -I$(QPCPP)/3rd_party/CMSIS/Include \ - -I$(QPCPP)/3rd_party/nucleo-u545re - -#----------------------------------------------------------------------------- -# project files: -# - -# assembler source files -ASM_SRCS := - -# C source files -C_SRCS := \ - system_stm32u5xx.c \ - startup_stm32u545retxq.c - -# C++ source files -CPP_SRCS := \ - test_sched.cpp \ - bsp_nucleo-u545re.cpp - -OUTPUT := $(PROJECT) -LD_SCRIPT := $(TARGET_DIR)/qutest.ld - -QP_SRCS := \ - qep_hsm.cpp \ - qep_msm.cpp \ - qf_act.cpp \ - qf_actq.cpp \ - qf_defer.cpp \ - qf_dyn.cpp \ - qf_mem.cpp \ - qf_ps.cpp \ - qf_qact.cpp \ - qf_qeq.cpp \ - qf_qmact.cpp \ - qf_time.cpp \ - qk.cpp \ - qk_port.cpp \ - qs.cpp \ - qs_64bit.cpp \ - qs_rx.cpp \ - qs_fp.cpp \ - qutest.cpp \ - qutest_cpp.cpp - -QP_ASMS := - -LIB_DIRS := -LIBS := - -# defines -DEFINES := -DSTM32U545xx \ - -DQP_API_VERSION=9999 \ - -DQF_ON_CONTEXT_SW - -# ARM CPU, ARCH, FPU, and Float-ABI types... -# ARM_CPU: [cortex-m0 | cortex-m0plus | cortex-m1 | cortex-m3 | cortex-m4] -# ARM_FPU: [ | vfp] -# FLOAT_ABI: [ | soft | softfp | hard] -# -ARM_CPU := -mcpu=cortex-m33 -ARM_FPU := -mfpu=fpv5-sp-d16 -FLOAT_ABI := -mfloat-abi=hard -mthumb - -#----------------------------------------------------------------------------- -# GNU-ARM toolset (NOTE: You need to adjust to your machine) -# see https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads -# -ifeq ($(GNU_ARM),) -GNU_ARM := $(QTOOLS)/gnu_arm-none-eabi -endif - -# make sure that the GNU-ARM toolset exists... -ifeq ("$(wildcard $(GNU_ARM))","") -$(error GNU_ARM toolset not found. Please adjust the Makefile) -endif - -CC := $(GNU_ARM)/bin/arm-none-eabi-gcc -CPP := $(GNU_ARM)/bin/arm-none-eabi-g++ -AS := $(GNU_ARM)/bin/arm-none-eabi-as -LINK := $(GNU_ARM)/bin/arm-none-eabi-g++ -BIN := $(GNU_ARM)/bin/arm-none-eabi-objcopy - -#----------------------------------------------------------------------------- -# NOTE: The symbol USB must be provided for the NUCLEO board -# has enumerated as USB drive f: -# -ifeq ($(USB),) -$(error USB drive not provided for the NUCLEO board.) -endif - -############################################################################## -# Typically you should not need to change anything below this line - -# basic utilities (included in QTools for Windows), see: -# https://www.state-machine.com/qtools - -MKDIR := mkdir -RM := rm -CP := cp -SLEEP := sleep - -#----------------------------------------------------------------------------- -# QUTest test script utilities (requires QTOOLS): -# -ifeq ("$(wildcard $(QUTEST))","") -QUTEST := python3 $(QTOOLS)/qutest/qutest.py -endif - -#----------------------------------------------------------------------------- -# build options -# - -# combine all the sources... -CPP_SRCS += $(QP_SRCS) -ASM_SRCS += $(QP_ASMS) - -BIN_DIR := build_$(TARGET) - -ASFLAGS = -g $(ARM_CPU) $(ARM_FPU) $(ASM_CPU) $(ASM_FPU) - - -# NOTE: -# Setting -DQ_UTEST=0 means that QUTest should be built WITHOUT -# the QP-stub for testing QP itself -# -CFLAGS = -c -g $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb -Wall \ - -ffunction-sections -fdata-sections \ - -O $(INCLUDES) $(DEFINES) -DQ_SPY -DQ_UTEST=0 - -CPPFLAGS = -c -g $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb -Wall \ - -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions \ - -O $(INCLUDES) $(DEFINES) -DQ_SPY -DQ_UTEST=0 - - -LINKFLAGS = -T$(LD_SCRIPT) $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb \ - -specs=nosys.specs -specs=nano.specs \ - -Wl,-Map,$(BIN_DIR)/$(OUTPUT).map,--cref,--gc-sections $(LIB_DIRS) - -ASM_OBJS := $(patsubst %.s,%.o, $(notdir $(ASM_SRCS))) -C_OBJS := $(patsubst %.c,%.o, $(notdir $(C_SRCS))) -CPP_OBJS := $(patsubst %.cpp,%.o,$(notdir $(CPP_SRCS))) - -TARGET_BIN := $(BIN_DIR)/$(OUTPUT).bin -TARGET_ELF := $(BIN_DIR)/$(OUTPUT).elf -ASM_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(ASM_OBJS)) -C_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(C_OBJS)) -C_DEPS_EXT := $(patsubst %.o, %.d, $(C_OBJS_EXT)) -CPP_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(CPP_OBJS)) -CPP_DEPS_EXT := $(patsubst %.o, %.d, $(CPP_OBJS_EXT)) - -# create $(BIN_DIR) if it does not exist -ifeq ("$(wildcard $(BIN_DIR))","") -$(shell $(MKDIR) $(BIN_DIR)) -endif - -#----------------------------------------------------------------------------- -# rules -# - -.PHONY : run norun debug flash - -ifeq ($(MAKECMDGOALS),norun) -all : $(TARGET_BIN) -norun : all -else -all : $(TARGET_BIN) run -endif - -$(TARGET_BIN) : $(TARGET_ELF) - $(BIN) -O binary $< $@ - $(CP) $@ $(USB) - $(SLEEP) 2 - -$(TARGET_ELF) : $(ASM_OBJS_EXT) $(C_OBJS_EXT) $(CPP_OBJS_EXT) - $(CPP) $(CPPFLAGS) $(QPCPP)/src/qs/qstamp.cpp -o $(BIN_DIR)/qstamp.o - $(LINK) $(LINKFLAGS) -o $@ $^ $(BIN_DIR)/qstamp.o $(LIBS) - -flash : - $(CP) $(TARGET_BIN) $(USB) - -run : $(TARGET_BIN) - $(QUTEST) -q$(QSPY) -l$(LOG) -o$(OPT) -- $(TESTS) - -$(BIN_DIR)/%.d : %.c - $(CC) -MM -MT $(@:.d=.o) $(CFLAGS) $< > $@ - -$(BIN_DIR)/%.d : %.cpp - $(CPP) -MM -MT $(@:.d=.o) $(CPPFLAGS) $< > $@ - -$(BIN_DIR)/%.o : %.s - $(AS) $(ASFLAGS) $< -o $@ - -$(BIN_DIR)/%.o : %.c - $(CC) $(CFLAGS) $< -o $@ - -$(BIN_DIR)/%.o : %.cpp - $(CPP) $(CPPFLAGS) $< -o $@ - -# create BIN_DIR and include dependencies only if needed -ifneq ($(MAKECMDGOALS),clean) - ifneq ($(MAKECMDGOALS),show) - ifneq ($(MAKECMDGOALS),debug) -ifeq ("$(wildcard $(BIN_DIR))","") -$(shell $(MKDIR) $(BIN_DIR)) -endif --include $(C_DEPS_EXT) $(CPP_DEPS_EXT) - endif - endif -endif - -debug : - $(QUTEST) -edebug -q$(QSPY) -l$(LOG) -o$(OPT) -- $(TESTS) - -.PHONY : clean show - -clean : - -$(RM) $(BIN_DIR)/*.o \ - $(BIN_DIR)/*.d \ - $(BIN_DIR)/*.bin \ - $(BIN_DIR)/*.elf \ - $(BIN_DIR)/*.map - -show : - @echo PROJECT = $(PROJECT) - @echo MAKECMDGOALS = $(MAKECMDGOALS) - @echo TESTS = $(TESTS) - @echo TARGET_ELF = $(TARGET_ELF) - @echo CONF = $(CONF) - @echo VPATH = $(VPATH) - @echo C_SRCS = $(C_SRCS) - @echo CPP_SRCS = $(CPP_SRCS) - @echo ASM_SRCS = $(ASM_SRCS) - @echo C_DEPS_EXT = $(C_DEPS_EXT) - @echo C_OBJS_EXT = $(C_OBJS_EXT) - @echo CPP_DEPS_EXT = $(CPP_DEPS_EXT) - @echo CPP_OBJS_EXT = $(CPP_OBJS_EXT) - @echo ASM_OBJS_EXT = $(ASM_OBJS_EXT) - @echo LIB_DIRS = $(LIB_DIRS) - @echo LIBS = $(LIBS) - @echo DEFINES = $(DEFINES) - @echo QTOOLS = $(QTOOLS) - @echo HOST = $(HOST) - @echo QUTEST = $(QUTEST) - @echo TESTS = $(TESTS) - diff --git a/test/qk/test_sched/test_mpu.py b/test/qk/test_sched/test_mpu.py deleted file mode 100644 index 37401c0ba..000000000 --- a/test/qk/test_sched/test_mpu.py +++ /dev/null @@ -1,100 +0,0 @@ -# test-script for QUTest unit testing harness -# see https://www.state-machine.com/qtools/qutest.html/qutest.html - -note(''' -This test group verifies the MPU setup, specifically -the protection of various memory regions. -All tests run during the QS_TEST_PAUSE() in -the test_sched.c fixture. -''') - -# preamble -def on_reset(): - expect_pause() - # don't call continue_test() - -def on_setup(): - glb_filter(GRP_SC, GRP_UA) - -MEM_START = 0 -MEM_END = 1 - -# NULL-pointer dereferencing... -test("NULL-read -> ASSERT") -command("MEM_READ", 0x0, 0x80) # value = *(uint32_t volatile *)(param1 + param2); -expect("@timestamp =ASSERT= Mod=*") - -test("NULL-write -> ASSERT") -command("MEM_WRITE", 0x0, 0xA0, 123) # *(uint32_t volatile *)(param1 + param2) = param3; -expect("@timestamp =ASSERT= Mod=*") - -# ROM_READ... -test("Below-Start Flash-read -> ASSERT") -command("ROM_READ", (-4 & 0xFFFFFFFF), MEM_START) # value = BSP_romRead(param1, param2); -expect("@timestamp =ASSERT= Mod=*") - -test("Start-of Flash-read") -command("ROM_READ", 0x0, MEM_START) # value = BSP_romRead(param1, param2); -expect("@timestamp USER+000 ROM_READ *") -expect("@timestamp Trg-Done QS_RX_COMMAND") - -test("Middle-of Flash-read", NORESET) -command("ROM_READ", 0x400, MEM_START) # value = BSP_romRead(param1, param2); -expect("@timestamp USER+000 ROM_READ *") -expect("@timestamp Trg-Done QS_RX_COMMAND") - -test("End-of Flash-read", NORESET) -command("ROM_READ", 0x0, MEM_END) # value = BSP_romRead(param1, param2); -expect("@timestamp USER+000 ROM_READ *") -expect("@timestamp Trg-Done QS_RX_COMMAND") - -skip(1) -test("After-End Flash-read-> ASSERT", NORESET) -command("ROM_READ", 0x4, MEM_END) # value = BSP_romRead(param1, param2); -expect("@timestamp =ASSERT= Mod=*") - -# ROM_WRITE... -test("Middle-of Flash-write -> ASSERT") -command("ROM_WRITE", 0x400, MEM_START, 123) # BSP_romWrite(param1, param2, param3); -expect("@timestamp =ASSERT= Mod=*") - -# RAM_READ... -test("Below-Start SRAM-read -> ASSERT") -command("RAM_READ", (-0x4 & 0xFFFFFFFF), MEM_START) # value = BSP_ramRead(param1, param2); -expect("@timestamp =ASSERT= Mod=*") - -test("Start-of SRAM-read") -command("RAM_READ", 0x0, MEM_START) # value = BSP_ramRead(param1, param2); -expect("@timestamp USER+000 RAM_READ *") -expect("@timestamp Trg-Done QS_RX_COMMAND") - -test("Middle-of SRAM-read, NORESET") -command("RAM_READ", 0x300, MEM_START) # value = BSP_ramRead(param1, param2); -expect("@timestamp USER+000 RAM_READ *") -expect("@timestamp Trg-Done QS_RX_COMMAND") - -test("End-of SRAM-read, NORESET") -command("RAM_READ", 0x0, MEM_END) # value = BSP_ramRead(param1, param2); -expect("@timestamp USER+000 RAM_READ *") -expect("@timestamp Trg-Done QS_RX_COMMAND") - -# RAM_WRITE... -test("Below-Start SRAM-write -> ASSERT", NORESET) -command("RAM_WRITE", (-0x4 & 0xFFFFFFFF), MEM_START, 123) # BSP_ramWrite(param1, param2, param3); -expect("@timestamp =ASSERT= Mod=*") - -test("Middle-of SRAM-write") -command("RAM_WRITE", 0x300, MEM_START, 123) # BSP_ramWrite(param1, param2, param3); -expect("@timestamp USER+000 RAM_WRITE *") -expect("@timestamp Trg-Done QS_RX_COMMAND") - -# the following test must be "RESET-test", because the previous test -# might have corrupted the RAM, so the target is not to be trusted -test("End-of SRAM-write") -command("RAM_WRITE", 0x0, MEM_END, 123) # BSP_ramWrite(param1, param2, param3); -expect("@timestamp USER+000 RAM_WRITE *") -expect("@timestamp Trg-Done QS_RX_COMMAND") - -test("After-End SRAM-write -> ASSERT", NORESET) -command("RAM_WRITE", 0x4, MEM_END, 123) # BSP_ramWrite(param1, param2, param3); -expect("@timestamp =ASSERT= Mod=*") diff --git a/test/qk/test_sched/test_sched.cpp b/test/qk/test_sched/test_sched.cpp deleted file mode 100644 index c6b23ea97..000000000 --- a/test/qk/test_sched/test_sched.cpp +++ /dev/null @@ -1,258 +0,0 @@ -//============================================================================ -// Product: System test fixture for QK on the EFM32 target -// Last updated for version 7.2.0 -// Last updated on 2022-12-14 -// -// Q u a n t u m L e a P s -// ------------------------ -// Modern Embedded Software -// -// Copyright (C) 2005 Quantum Leaps. All rights reserved. -// -// This program is open source software: you can redistribute it and/or -// modify it under the terms of the GNU General Public License as published -// by the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Alternatively, this program may be distributed and modified under the -// terms of Quantum Leaps commercial licenses, which expressly supersede -// the GNU General Public License and are specifically designed for -// licensees interested in retaining the proprietary status of their code. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -// Contact information: -// -// -//============================================================================ -#include "qpcpp.hpp" -#include "bsp.hpp" - -namespace { - -Q_DEFINE_THIS_FILE - -//============================================================================ -// AO ObjB -enum { NUM_B = 3 }; - -//............................................................................ -// AO ObjB -class ObjB : public QP::QActive { -public: - static ObjB inst[NUM_B]; - -public: - ObjB() : QActive(&initial) {} - -protected: - Q_STATE_DECL(initial); - Q_STATE_DECL(active); -}; // class ObjB - -Q_STATE_DEF(ObjB, initial) { - static bool registered = false; // starts off with 0, per C-standard - if (!registered) { - registered = true; - QS_FUN_DICTIONARY(&ObjB::initial); - QS_FUN_DICTIONARY(&ObjB::active); - } - subscribe(TEST1_SIG); - subscribe(TEST2_SIG); - return tran(&active); -} - -Q_STATE_DEF(ObjB, active) { - QP::QState status_; - switch (e->sig) { - case TEST0_SIG: { - BSP::trace(this, "TEST0 1of2"); - BSP::trigISR(); - BSP::trace(this, "TEST0 2of2"); - status_ = Q_RET_HANDLED; - break; - } - case TEST1_SIG: { - static QP::QEvt const t2(TEST2_SIG); - BSP::trace(this, "TEST1 1of2"); - QActive::PUBLISH(&t2, this); - BSP::trace(this, "TEST1 2of2"); - status_ = Q_RET_HANDLED; - break; - } - case TEST2_SIG: { - BSP::trace(this, "TEST2 1of1"); - status_ = Q_RET_HANDLED; - break; - } - default: { - status_ = super(&top); - break; - } - } - return status_; -} - -//============================================================================ -enum UserCommands { - MEM_READ, MEM_WRITE, - ROM_READ, ROM_WRITE, - RAM_READ, RAM_WRITE, -}; - -ObjB ObjB::inst[NUM_B]; - -} // unnamed namespace - -//============================================================================ -int main() { - - QP::QF::init(); // initialize the framework and the underlying QXK kernel - BSP::init(); // initialize the Board Support Package - - // initialize publish-subscribe... - static QP::QSubscrList subscrSto[MAX_PUB_SIG]; - QP::QActive::psInit(subscrSto, Q_DIM(subscrSto)); - - // initialize event pools... - static QF_MPOOL_EL(QP::QEvt) smlPoolSto[10]; // small pool - QP::QF::poolInit(smlPoolSto, sizeof(smlPoolSto), sizeof(smlPoolSto[0])); - - // dictionaries - QS_SIG_DICTIONARY(TEST0_SIG, nullptr); - QS_SIG_DICTIONARY(TEST1_SIG, nullptr); - QS_SIG_DICTIONARY(TEST2_SIG, nullptr); - QS_SIG_DICTIONARY(TEST3_SIG, nullptr); - - QS_ENUM_DICTIONARY(MEM_READ, QS_CMD); - QS_ENUM_DICTIONARY(MEM_WRITE, QS_CMD); - QS_ENUM_DICTIONARY(ROM_READ, QS_CMD); - QS_ENUM_DICTIONARY(ROM_WRITE, QS_CMD); - QS_ENUM_DICTIONARY(RAM_READ, QS_CMD); - QS_ENUM_DICTIONARY(RAM_WRITE, QS_CMD); - - for (std::uint8_t n = 0U; n < NUM_B; ++n) { - QS_OBJ_ARR_DICTIONARY(&ObjB::inst[n], n); - } - - // priority specifications for ObjBs... - static QP::QPrioSpec pspecB[NUM_B]; - QS_OBJ_DICTIONARY(pspecB); - - // pause execution of the test and wait for the test script to continue - // NOTE: - // this pause gives the test-script a chance to poke pspecB and pspecX - // variables to start the threads with the desired prio-specifications. - QS_TEST_PAUSE(); - - static QP::QEvt const *aoB_queueSto[NUM_B][10]; - for (std::uint8_t n = 0U; n < NUM_B; ++n) { - if (pspecB[n] != 0U) { - ObjB::inst[n].start(pspecB[n], // QF-prio/p-thre. - aoB_queueSto[n], // event queue storage - Q_DIM(aoB_queueSto[n]), // event length [events] - nullptr, // no stack storage - 0U); // zero stack size [bytes] - } - } - - return QP::QF::run(); // run the QF application -} - -//============================================================================ -namespace QP { - -void QS::onTestSetup(void) { -} -//............................................................................ -void QS::onTestTeardown(void) { -} -//............................................................................ -//! callback function to execute user commands -void QS::onCommand(uint8_t cmdId, - uint32_t param1, uint32_t param2, uint32_t param3) -{ - uint32_t volatile value; - - switch (cmdId) { - case MEM_READ: { // read MEM (can trip the MPU) - value = *(uint32_t volatile *)(param1 + param2); - QS_BEGIN_ID(QS_USER, 0U) - QS_ENUM(QS_CMD, cmdId); - QS_U32(0, value); - QS_END() - break; - } - case MEM_WRITE: { // write MEM (can trip the MPU) - *(uint32_t volatile *)(param1 + param2) = param3; - QS_BEGIN_ID(QS_USER, 0U) - QS_ENUM(QS_CMD, cmdId); - QS_U32(QS_HEX_FMT , param1); - QS_U32(QS_HEX_FMT , param2); - QS_U32(0 , param3); - QS_END() - break; - } - case ROM_READ: { // read ROM (can trip the MPU) - value = BSP::romRead((int32_t)param1, param2); - QS_BEGIN_ID(QS_USER, 0U) - QS_ENUM(QS_CMD, cmdId); - QS_U32(0, value); - QS_END() - break; - } - case ROM_WRITE: { // write ROM (can trip the MPU) - BSP::romWrite(param1, param2, param3); - QS_BEGIN_ID(QS_USER, 0U) - QS_ENUM(QS_CMD, cmdId); - QS_U32(QS_HEX_FMT , param1); - QS_U32(QS_HEX_FMT , param2); - QS_U32(0 , param3); - QS_END() - break; - } - case RAM_READ: { // read RAM (can trip the MPU) - value = BSP::ramRead(param1, param2); - QS_BEGIN_ID(QS_USER, 0U) - QS_ENUM(QS_CMD, cmdId); - QS_U32(0, value); - QS_END() - break; - } - case RAM_WRITE: { // write RAM (can trip the MPU) - BSP::ramWrite(param1, param2, param3); - QS_BEGIN_ID(QS_USER, 0U) - QS_ENUM(QS_CMD, cmdId); - QS_U32(QS_HEX_FMT , param1); - QS_U32(QS_HEX_FMT , param2); - QS_U32(0, param3); - QS_END() - break; - } - default: { - break; - } - } -} - -//============================================================================ -//! Host callback function to "massage" the event, if necessary -void QS::onTestEvt(QEvt *e) { - Q_UNUSED_PAR(e); -} -//............................................................................ -//! callback function to output the posted QP events (not used here) -void QS::onTestPost(void const *sender, QActive *recipient, - QEvt const *e, bool status) -{ - Q_UNUSED_PAR(sender); - Q_UNUSED_PAR(status); -} - -} // namespace QP diff --git a/test/qk/test_sched/test_sched.py b/test/qk/test_sched/test_sched.py deleted file mode 100644 index 4e1fc52d6..000000000 --- a/test/qk/test_sched/test_sched.py +++ /dev/null @@ -1,188 +0,0 @@ -# test-script for QUTest unit testing harness -# see https://www.state-machine.com/qtools/qutest.html/qutest.html - -note(''' -This test group verifies the preemption tests -in the QK preemptive kernel -''') - -# preamble -def on_reset(): - expect_pause() - # don't call continue_test() yet - # this will be done by the individual tests - # after they poke the priorities of threads - -# helper function to repliacte the Q_PRIO() macro -def Q_PRIO(prio, pthre): - return prio | (pthre << 8) - -test("ao->ao->ao (NO PTS)") -# given... -current_obj(OBJ_AP, "pspecB") -poke(0, 2, pack("2") -expect("@timestamp CONTEXT_SW NULL ObjB::inst[1]") -expect("@timestamp TRACE_MSG ObjB::inst[1] TEST0 1of2") -expect("@timestamp Sch-Next Pri=2->3") -expect("@timestamp CONTEXT_SW ObjB::inst[1] ObjB::inst[2]") -expect("@timestamp TRACE_MSG ObjB::inst[2] TEST1 1of2") -expect("@timestamp Sch-Lock Ceil=0->3") -expect("@timestamp Sch-Unlk Ceil=3->0") -expect("@timestamp TRACE_MSG ObjB::inst[2] TEST1 2of2") -expect("@timestamp TRACE_MSG ObjB::inst[2] TEST2 1of1") -expect("@timestamp Sch-Next Pri=3->2") -expect("@timestamp CONTEXT_SW ObjB::inst[2] ObjB::inst[1]") -expect("@timestamp TRACE_MSG ObjB::inst[1] TEST0 2of2") -expect("@timestamp TRACE_MSG ObjB::inst[1] TEST1 1of2") -expect("@timestamp Sch-Lock Ceil=0->3") -expect("@timestamp Sch-Unlk Ceil=3->0") -expect("@timestamp Sch-Next Pri=2->3") -expect("@timestamp CONTEXT_SW ObjB::inst[1] ObjB::inst[2]") -expect("@timestamp TRACE_MSG ObjB::inst[2] TEST2 1of1") -expect("@timestamp Sch-Next Pri=3->2") -expect("@timestamp CONTEXT_SW ObjB::inst[2] ObjB::inst[1]") -expect("@timestamp TRACE_MSG ObjB::inst[1] TEST1 2of2") -expect("@timestamp TRACE_MSG ObjB::inst[1] TEST2 1of1") -expect("@timestamp TRACE_MSG ObjB::inst[1] TEST2 1of1") -expect("@timestamp Sch-Next Pri=2->1") -expect("@timestamp CONTEXT_SW ObjB::inst[1] ObjB::inst[0]") -expect("@timestamp TRACE_MSG ObjB::inst[0] TEST1 1of2") -expect("@timestamp Sch-Lock Ceil=0->3") -expect("@timestamp Sch-Unlk Ceil=3->0") -expect("@timestamp Sch-Next Pri=1->3") -expect("@timestamp CONTEXT_SW ObjB::inst[0] ObjB::inst[2]") -expect("@timestamp TRACE_MSG ObjB::inst[2] TEST2 1of1") -expect("@timestamp Sch-Next Pri=3->2") -expect("@timestamp CONTEXT_SW ObjB::inst[2] ObjB::inst[1]") -expect("@timestamp TRACE_MSG ObjB::inst[1] TEST2 1of1") -expect("@timestamp Sch-Next Pri=2->1") -expect("@timestamp CONTEXT_SW ObjB::inst[1] ObjB::inst[0]") -expect("@timestamp TRACE_MSG ObjB::inst[0] TEST1 2of2") -expect("@timestamp TRACE_MSG ObjB::inst[0] TEST2 1of1") -expect("@timestamp TRACE_MSG ObjB::inst[0] TEST2 1of1") -expect("@timestamp TRACE_MSG ObjB::inst[0] TEST2 1of1") -expect("@timestamp Sch-Idle Pri=1->0") -expect("@timestamp CONTEXT_SW ObjB::inst[0] NULL") -expect("@timestamp Trg-Done QS_RX_EVENT") - - -test("ao->ao->ao (PTS1)") -# given... -current_obj(OBJ_AP, "pspecB") -poke(0, 2, pack("2") -expect("@timestamp CONTEXT_SW NULL ObjB::inst[1]") -expect("@timestamp TRACE_MSG ObjB::inst[1] TEST0 1of2") -expect("@timestamp TRACE_MSG ObjB::inst[1] TEST0 2of2") -expect("@timestamp Sch-Next Pri=2->3") -expect("@timestamp CONTEXT_SW ObjB::inst[1] ObjB::inst[2]") -expect("@timestamp TRACE_MSG ObjB::inst[2] TEST1 1of2") -expect("@timestamp Sch-Lock Ceil=0->3") -expect("@timestamp Sch-Unlk Ceil=3->0") -expect("@timestamp TRACE_MSG ObjB::inst[2] TEST1 2of2") -expect("@timestamp TRACE_MSG ObjB::inst[2] TEST2 1of1") -expect("@timestamp Sch-Next Pri=3->2") -expect("@timestamp CONTEXT_SW ObjB::inst[2] ObjB::inst[1]") -expect("@timestamp TRACE_MSG ObjB::inst[1] TEST1 1of2") -expect("@timestamp Sch-Lock Ceil=0->3") -expect("@timestamp Sch-Unlk Ceil=3->0") -expect("@timestamp TRACE_MSG ObjB::inst[1] TEST1 2of2") -expect("@timestamp Sch-Next Pri=2->3") -expect("@timestamp CONTEXT_SW ObjB::inst[1] ObjB::inst[2]") -expect("@timestamp TRACE_MSG ObjB::inst[2] TEST2 1of1") -expect("@timestamp Sch-Next Pri=3->2") -expect("@timestamp CONTEXT_SW ObjB::inst[2] ObjB::inst[1]") -expect("@timestamp TRACE_MSG ObjB::inst[1] TEST2 1of1") -expect("@timestamp TRACE_MSG ObjB::inst[1] TEST2 1of1") -expect("@timestamp Sch-Next Pri=2->1") -expect("@timestamp CONTEXT_SW ObjB::inst[1] ObjB::inst[0]") -expect("@timestamp TRACE_MSG ObjB::inst[0] TEST1 1of2") -expect("@timestamp Sch-Lock Ceil=0->3") -expect("@timestamp Sch-Unlk Ceil=3->0") -expect("@timestamp TRACE_MSG ObjB::inst[0] TEST1 2of2") -expect("@timestamp Sch-Next Pri=1->3") -expect("@timestamp CONTEXT_SW ObjB::inst[0] ObjB::inst[2]") -expect("@timestamp TRACE_MSG ObjB::inst[2] TEST2 1of1") -expect("@timestamp Sch-Next Pri=3->2") -expect("@timestamp CONTEXT_SW ObjB::inst[2] ObjB::inst[1]") -expect("@timestamp TRACE_MSG ObjB::inst[1] TEST2 1of1") -expect("@timestamp Sch-Next Pri=2->1") -expect("@timestamp CONTEXT_SW ObjB::inst[1] ObjB::inst[0]") -expect("@timestamp TRACE_MSG ObjB::inst[0] TEST2 1of1") -expect("@timestamp TRACE_MSG ObjB::inst[0] TEST2 1of1") -expect("@timestamp TRACE_MSG ObjB::inst[0] TEST2 1of1") -expect("@timestamp Sch-Idle Pri=1->0") -expect("@timestamp CONTEXT_SW ObjB::inst[0] NULL") -expect("@timestamp Trg-Done QS_RX_EVENT") - - -test("ao->ao->ao (PTS2)") -# given... -current_obj(OBJ_AP, "pspecB") -poke(0, 2, pack("2") -expect("@timestamp CONTEXT_SW NULL ObjB::inst[1]") -expect("@timestamp TRACE_MSG ObjB::inst[1] TEST0 1of2") -expect("@timestamp TRACE_MSG ObjB::inst[1] TEST0 2of2") -expect("@timestamp Sch-Next Pri=2->3") -expect("@timestamp CONTEXT_SW ObjB::inst[1] ObjB::inst[2]") -expect("@timestamp TRACE_MSG ObjB::inst[2] TEST1 1of2") -expect("@timestamp Sch-Lock Ceil=0->3") -expect("@timestamp Sch-Unlk Ceil=3->0") -expect("@timestamp TRACE_MSG ObjB::inst[2] TEST1 2of2") -expect("@timestamp TRACE_MSG ObjB::inst[2] TEST2 1of1") -expect("@timestamp Sch-Next Pri=3->2") -expect("@timestamp CONTEXT_SW ObjB::inst[2] ObjB::inst[1]") -expect("@timestamp TRACE_MSG ObjB::inst[1] TEST1 1of2") -expect("@timestamp Sch-Lock Ceil=0->3") -expect("@timestamp Sch-Unlk Ceil=3->0") -expect("@timestamp TRACE_MSG ObjB::inst[1] TEST1 2of2") -expect("@timestamp Sch-Next Pri=2->3") -expect("@timestamp CONTEXT_SW ObjB::inst[1] ObjB::inst[2]") -expect("@timestamp TRACE_MSG ObjB::inst[2] TEST2 1of1") -expect("@timestamp Sch-Next Pri=3->2") -expect("@timestamp CONTEXT_SW ObjB::inst[2] ObjB::inst[1]") -expect("@timestamp TRACE_MSG ObjB::inst[1] TEST2 1of1") -expect("@timestamp TRACE_MSG ObjB::inst[1] TEST2 1of1") -expect("@timestamp Sch-Next Pri=2->1") -expect("@timestamp CONTEXT_SW ObjB::inst[1] ObjB::inst[0]") -expect("@timestamp TRACE_MSG ObjB::inst[0] TEST1 1of2") -expect("@timestamp Sch-Lock Ceil=0->3") -expect("@timestamp Sch-Unlk Ceil=3->0") -expect("@timestamp Sch-Next Pri=1->3") -expect("@timestamp CONTEXT_SW ObjB::inst[0] ObjB::inst[2]") -expect("@timestamp TRACE_MSG ObjB::inst[2] TEST2 1of1") -expect("@timestamp Sch-Next Pri=3->2") -expect("@timestamp CONTEXT_SW ObjB::inst[2] ObjB::inst[1]") -expect("@timestamp TRACE_MSG ObjB::inst[1] TEST2 1of1") -expect("@timestamp Sch-Next Pri=2->1") -expect("@timestamp CONTEXT_SW ObjB::inst[1] ObjB::inst[0]") -expect("@timestamp TRACE_MSG ObjB::inst[0] TEST1 2of2") -expect("@timestamp TRACE_MSG ObjB::inst[0] TEST2 1of1") -expect("@timestamp TRACE_MSG ObjB::inst[0] TEST2 1of1") -expect("@timestamp TRACE_MSG ObjB::inst[0] TEST2 1of1") -expect("@timestamp Sch-Idle Pri=1->0") -expect("@timestamp CONTEXT_SW ObjB::inst[0] NULL") -expect("@timestamp Trg-Done QS_RX_EVENT") diff --git a/test/qk/test_sched/uvision_efm32.uvoptx b/test/qk/test_sched/uvision_efm32.uvoptx deleted file mode 100644 index 45af40fe7..000000000 --- a/test/qk/test_sched/uvision_efm32.uvoptx +++ /dev/null @@ -1,730 +0,0 @@ - - - - 1.0 - -
### uVision Project, (C) Keil Software
- - - *.c - *.s*; *.src; *.a* - *.obj; *.o - *.lib - *.txt; *.h; *.inc; *.md - *.plm - *.cpp - 0 - - - - 0 - 0 - - - - qutest - 0x4 - ARM-ADS - - 12000000 - - 1 - 1 - 1 - 0 - 0 - - - 1 - 65535 - 0 - 0 - 0 - - - 79 - 66 - 8 - .\uvision_emf32\ - - - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 1 - 0 - 1 - - 3 - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 4 - - - - - - - - - - - Segger\JL2CM3.dll - - - - 0 - DLGUARM - - - - 0 - JL2CM3 - -U440060969 -O206 -S2 -ZTIFSpeedSel5000 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(0) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO7 -FD20000000 -FC8000 -FN1 -FF0GECKOP2.FLM -FS00 -FL020000 -FP0($$Device:EFM32PG1B200F256GM48$Flash\GECKOP2.FLM) - - - 0 - ARMRTXEVENTFLAGS - -L70 -Z18 -C0 -M0 -T1 - - - 0 - UL2CM3 - UL2CM3(-O207 -S0 -C0 -FO7 -FN1 -FC8000 -FD20000000 -FF0GECKOP2 -FL020000 -FS00 -FP0($$Device:EFM32PG1B200F256GM48$Flash\GECKOP2.FLM) - - - 0 - DLGTARM - (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)(1012=-1,-1,-1,-1,0) - - - 0 - ARMDBGFLAGS - - - - 0 - lmidk-agdi - -U0E2006F4 -O4622 -S4 -FO61 - - - - - 0 - 0 - 112 - 1 -
25212
- 0 - 0 - 0 - 0 - 0 - 1 - ..\..\..\src\qs\qutest.c - - \\test\../../../src/qs/qutest.c\112 -
- - 1 - 0 - 142 - 1 -
136
- 0 - 0 - 0 - 0 - 0 - 1 - ..\..\..\src\qs\qs.c - - \\test\../../../src/qs/qs.c\142 -
- - 2 - 0 - 180 - 1 -
27402
- 0 - 0 - 0 - 0 - 0 - 1 - .\test_pts.c - - \\test\test_pts.c\180 -
-
- - - 0 - 1 - QF_readySet_ - - - 1 - 1 - QK_attr_ - - - 2 - 1 - QActive_registry_ - - - 3 - 1 - QS_rxPriv_ - - - 4 - 1 - pspec - - - - - 1 - 2 - 0x20000200 - 0 - - - - - 2 - 0 - 0x400 - 0 - - - - 0 - - - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - - - - - - - - -
-
- - - Applicatioin - 1 - 0 - 0 - 0 - - 1 - 1 - 5 - 0 - 0 - 0 - .\bsp.h - bsp.h - 0 - 0 - - - 1 - 2 - 1 - 0 - 0 - 0 - .\bsp_efm32.c - bsp_efm32.c - 0 - 0 - - - 1 - 3 - 1 - 0 - 0 - 0 - .\test_pts.c - test_pts.c - 0 - 0 - - - - - efm32pg1b - 1 - 0 - 0 - 0 - - 2 - 4 - 2 - 0 - 0 - 0 - ..\..\..\..\3rd_party\efm32pg1b\arm\startup_efm32pg1b.s - startup_efm32pg1b.s - 0 - 0 - - - 2 - 5 - 1 - 0 - 0 - 0 - ..\..\..\..\3rd_party\efm32pg1b\em_cmu.c - em_cmu.c - 0 - 0 - - - 2 - 6 - 1 - 0 - 0 - 0 - ..\..\..\..\3rd_party\efm32pg1b\em_emu.c - em_emu.c - 0 - 0 - - - 2 - 7 - 1 - 0 - 0 - 0 - ..\..\..\..\3rd_party\efm32pg1b\em_gpio.c - em_gpio.c - 0 - 0 - - - 2 - 8 - 1 - 0 - 0 - 0 - ..\..\..\..\3rd_party\efm32pg1b\system_efm32pg1b.c - system_efm32pg1b.c - 0 - 0 - - - 2 - 9 - 1 - 0 - 0 - 0 - ..\..\..\..\3rd_party\efm32pg1b\em_system.c - em_system.c - 0 - 0 - - - 2 - 10 - 1 - 0 - 0 - 0 - ..\..\..\..\3rd_party\efm32pg1b\em_usart.c - em_usart.c - 0 - 0 - - - - - QP - 1 - 0 - 0 - 0 - - 3 - 11 - 1 - 0 - 0 - 0 - ..\..\..\src\qf\qep_hsm.c - qep_hsm.c - 0 - 0 - - - 3 - 12 - 1 - 0 - 0 - 0 - ..\..\..\src\qf\qep_msm.c - qep_msm.c - 0 - 0 - - - 3 - 13 - 1 - 0 - 0 - 0 - ..\..\..\src\qf\qf_act.c - qf_act.c - 0 - 0 - - - 3 - 14 - 1 - 0 - 0 - 0 - ..\..\..\src\qf\qf_actq.c - qf_actq.c - 0 - 0 - - - 3 - 15 - 1 - 0 - 0 - 0 - ..\..\..\src\qf\qf_defer.c - qf_defer.c - 0 - 0 - - - 3 - 16 - 1 - 0 - 0 - 0 - ..\..\..\src\qf\qf_dyn.c - qf_dyn.c - 0 - 0 - - - 3 - 17 - 1 - 0 - 0 - 0 - ..\..\..\src\qf\qf_mem.c - qf_mem.c - 0 - 0 - - - 3 - 18 - 1 - 0 - 0 - 0 - ..\..\..\src\qf\qf_ps.c - qf_ps.c - 0 - 0 - - - 3 - 19 - 1 - 0 - 0 - 0 - ..\..\..\src\qf\qf_qact.c - qf_qact.c - 0 - 0 - - - 3 - 20 - 1 - 0 - 0 - 0 - ..\..\..\src\qf\qf_qeq.c - qf_qeq.c - 0 - 0 - - - 3 - 21 - 1 - 0 - 0 - 0 - ..\..\..\src\qf\qf_qmact.c - qf_qmact.c - 0 - 0 - - - 3 - 22 - 1 - 0 - 0 - 0 - ..\..\..\src\qf\qf_time.c - qf_time.c - 0 - 0 - - - 3 - 23 - 1 - 0 - 0 - 0 - ..\..\..\include\qstamp.c - qstamp.c - 0 - 0 - - - 3 - 24 - 1 - 0 - 0 - 0 - ..\..\..\src\qk\qk.c - qk.c - 0 - 0 - - - - - QP_port - 1 - 0 - 0 - 0 - - 4 - 26 - 5 - 0 - 0 - 0 - ..\..\..\ports\arm-cm\qxk\armclang\qp_port.h - qp_port.h - 0 - 0 - - - 4 - 28 - 1 - 0 - 0 - 0 - ..\..\..\ports\arm-cm\qk\armclang\qk_port.c - qk_port.c - 0 - 0 - - - 4 - 29 - 5 - 0 - 0 - 0 - ..\..\..\ports\arm-cm\qxk\armclang\qs_port.h - qs_port.h - 0 - 0 - - - 4 - 30 - 1 - 0 - 0 - 0 - ..\..\..\3rd_party\efm32pg1b\qutest\qutest_port.c - qutest_port.c - 0 - 0 - - - - - QS - 1 - 0 - 0 - 0 - - 5 - 31 - 1 - 0 - 0 - 0 - ..\..\..\src\qs\qs.c - qs.c - 0 - 0 - - - 5 - 32 - 1 - 0 - 0 - 0 - ..\..\..\src\qs\qs_64bit.c - qs_64bit.c - 0 - 0 - - - 5 - 33 - 1 - 0 - 0 - 0 - ..\..\..\src\qs\qs_fp.c - qs_fp.c - 0 - 0 - - - 5 - 34 - 1 - 0 - 0 - 0 - ..\..\..\src\qs\qs_rx.c - qs_rx.c - 0 - 0 - - - 5 - 35 - 1 - 0 - 0 - 0 - ..\..\..\src\qs\qutest.c - qutest.c - 0 - 0 - - - -
diff --git a/test/qk/test_sched/uvision_efm32.uvprojx b/test/qk/test_sched/uvision_efm32.uvprojx deleted file mode 100644 index a4c6d98d8..000000000 --- a/test/qk/test_sched/uvision_efm32.uvprojx +++ /dev/null @@ -1,587 +0,0 @@ - - - - 2.1 - -
### uVision Project, (C) Keil Software
- - - - qutest - 0x4 - ARM-ADS - 6160000::V6.16::ARMCLANG - 1 - - - EFM32PG1B200F256GM48 - Silicon Labs - SiliconLabs.GeckoPlatform_EFM32PG1B_DFP.4.0.0 - https://www.silabs.com/documents/public/cmsis-packs/ - IRAM(0x20000000,0x00008000) IROM(0x00000000,0x00020000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE - - - UL2CM3(-S0 -C0 -P0 -FD20000000 -FC8000 -FN1 -FF0GECKOP2 -FS00 -FL020000 -FP0($$Device:EFM32PG1B200F256GM48$Flash\GECKOP2.FLM)) - 0 - $$Device:EFM32PG1B200F256GM48$Device\EFM32PG1B\Include\em_device.h - - - - - - - - - - $$Device:EFM32PG1B200F256GM48$SVD\EFM32PG1B\EFM32PG1B200F256GM48.svd - 0 - 0 - - - - - - - 0 - 0 - 0 - 0 - 1 - - .\uvision_emf32\ - test - 1 - 0 - 0 - 1 - 1 - .\uvision_emf32\ - 1 - 0 - 0 - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 1 - 0 - cmd /c "del .\uvision_em32\qstamp.o" - - 0 - 0 - 0 - 0 - - - 1 - 0 - fromelf --bin --output .\uvision_em32\test.bin .\uvision_em32\test.axf - - 0 - 0 - 0 - 0 - - 1 - - - - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 3 - - - 1 - - - SARMCM3.DLL - -MPU - DCM.DLL - -pCM4 - SARMCM3.DLL - -MPU - TCM.DLL - -pCM4 - - - - 1 - 0 - 0 - 0 - 16 - - - - - 1 - 0 - 0 - 1 - 1 - 4096 - - 1 - BIN\UL2CM3.DLL - "" () - - - - - 0 - - - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 0 - 0 - 0 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - "Cortex-M4" - - 0 - 0 - 0 - 1 - 1 - 0 - 0 - 2 - 0 - 0 - 0 - 0 - 8 - 0 - 0 - 0 - 0 - 3 - 3 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x20000000 - 0x8000 - - - 1 - 0x0 - 0x20000 - - - 0 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x20000 - - - 1 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x20000000 - 0x8000 - - - 0 - 0x0 - 0x0 - - - - - - 0 - 1 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 3 - 0 - 1 - 1 - 0 - 0 - 3 - 3 - 0 - 0 - 0 - 0 - 0 - - - Q_SPY, Q_UTEST=0 - - .;..\..\..\include;..\..\..\ports\arm-cm\qk\armclang;..\..\..\..\3rd_party\CMSIS\Include;..\..\..\..\3rd_party\efm32pg1b - - - - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 4 - - - Stack_Size=2048 Heap_Size=16 - - - - - - 1 - 0 - 0 - 0 - 1 - 0 - 0x00000000 - 0x20000000 - - - - - --entry Reset_Handler - - - - - - - - Applicatioin - - - bsp.h - 5 - .\bsp.h - - - bsp_efm32.c - 1 - .\bsp_efm32.c - - - test_pts.c - 1 - .\test_pts.c - - - - - efm32pg1b - - - startup_efm32pg1b.s - 2 - ..\..\..\..\3rd_party\efm32pg1b\arm\startup_efm32pg1b.s - - - em_cmu.c - 1 - ..\..\..\..\3rd_party\efm32pg1b\em_cmu.c - - - em_emu.c - 1 - ..\..\..\..\3rd_party\efm32pg1b\em_emu.c - - - em_gpio.c - 1 - ..\..\..\..\3rd_party\efm32pg1b\em_gpio.c - - - system_efm32pg1b.c - 1 - ..\..\..\..\3rd_party\efm32pg1b\system_efm32pg1b.c - - - em_system.c - 1 - ..\..\..\..\3rd_party\efm32pg1b\em_system.c - - - em_usart.c - 1 - ..\..\..\..\3rd_party\efm32pg1b\em_usart.c - - - - - QP - - - qep_hsm.c - 1 - ..\..\..\src\qf\qep_hsm.c - - - qep_msm.c - 1 - ..\..\..\src\qf\qep_msm.c - - - qf_act.c - 1 - ..\..\..\src\qf\qf_act.c - - - qf_actq.c - 1 - ..\..\..\src\qf\qf_actq.c - - - qf_defer.c - 1 - ..\..\..\src\qf\qf_defer.c - - - qf_dyn.c - 1 - ..\..\..\src\qf\qf_dyn.c - - - qf_mem.c - 1 - ..\..\..\src\qf\qf_mem.c - - - qf_ps.c - 1 - ..\..\..\src\qf\qf_ps.c - - - qf_qact.c - 1 - ..\..\..\src\qf\qf_qact.c - - - qf_qeq.c - 1 - ..\..\..\src\qf\qf_qeq.c - - - qf_qmact.c - 1 - ..\..\..\src\qf\qf_qmact.c - - - qf_time.c - 1 - ..\..\..\src\qf\qf_time.c - - - qstamp.c - 1 - ..\..\..\include\qstamp.c - - - qk.c - 1 - ..\..\..\src\qk\qk.c - - - - - QP_port - - - qk_port.c - 1 - ..\..\..\ports\arm-cm\qk\armclang\qk_port.c - - - qp_port.h - 5 - ..\..\..\ports\arm-cm\qxk\armclang\qp_port.h - - - qutest_port.c - 1 - ..\..\..\3rd_party\efm32pg1b\qutest\qutest_port.c - - - - - QS - - - qs.c - 1 - ..\..\..\src\qs\qs.c - - - qs_64bit.c - 1 - ..\..\..\src\qs\qs_64bit.c - - - qs_fp.c - 1 - ..\..\..\src\qs\qs_fp.c - - - qs_rx.c - 1 - ..\..\..\src\qs\qs_rx.c - - - qutest.c - 1 - ..\..\..\src\qs\qutest.c - - - - - - - - - - - - - - - - - test - 1 - - - - -
diff --git a/test/qs/qs_rx/Makefile b/test/qs/qs_rx/Makefile deleted file mode 100644 index c47089437..000000000 --- a/test/qs/qs_rx/Makefile +++ /dev/null @@ -1,222 +0,0 @@ -############################################################################## -# Product: Makefile for ET embedded test for QP/C++ on the *HOST* -# Last Updated for Version: 7.3.0 -# Date of the Last Update: 2023-06-30 -# -# Q u a n t u m L e a P s -# ------------------------ -# Modern Embedded Software -# -# Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -# -# This program is open source software: you can redistribute it and/or -# modify it under the terms of the GNU General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Alternatively, this program may be distributed and modified under the -# terms of Quantum Leaps commercial licenses, which expressly supersede -# the GNU General Public License and are specifically designed for -# licensees interested in retaining the proprietary status of their code. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Contact information: -# -# -############################################################################## -# -# examples of invoking this Makefile: -# make # make and run the Python tests in the current directory -# make TESTS=test*.py # make and run the selected tests in the curr. dir. -# make HOST=localhost:7705 # connect to host:port -# make norun # only make but not run the tests -# make clean # cleanup the build -# make debug # only run tests in DEBUG mode -# -# NOTE: -# To use this Makefile on Windows, you will need the GNU make utility, which -# is included in the QTools collection for Windows, see: -# https://github.com/QuantumLeaps/qtools -# - -#----------------------------------------------------------------------------- -# project name: -PROJECT := test - -#----------------------------------------------------------------------------- -# project directories: -# -QPCPP := ../../.. -ET := ../../et - -# list of all source directories used by this project -VPATH := . \ - $(QPCPP)/src/qf \ - $(QPCPP)/src/qs \ - $(ET) - -# list of all include directories needed by this project -INCLUDES := -I. \ - -I$(QPCPP)/include \ - -I$(ET) - -#----------------------------------------------------------------------------- -# project files: -# - -# C source files... -C_SRCS := \ - et.c \ - et_host.c - -# C++ source files... -CPP_SRCS := \ - test.cpp \ - qep_hsm.cpp \ - qf_act.cpp \ - qf_actq.cpp \ - qf_qact.cpp \ - qf_qeq.cpp \ - qs.cpp \ - qs_rx.cpp - -LIB_DIRS := -LIBS := - -# defines... -DEFINES := -DQ_SPY - -#============================================================================ -# Typically you should not need to change anything below this line - -#----------------------------------------------------------------------------- -# GNU toolset: -# -# NOTE: -# GNU toolset (MinGW) is included in the QTools collection for Windows, see: -# https://www.state-machine.com/qtools -# It is assumed that %QTOOLS%\bin directory is added to the PATH -# -CC := gcc -CPP := g++ -#LINK := gcc # for C programs -LINK := g++ # for C++ programs - -#----------------------------------------------------------------------------- -# basic utilities (depends on the OS this Makefile runs on): -# -ifeq ($(OS),Windows_NT) - MKDIR := mkdir - RM := rm - TARGET_EXT := .exe -else ifeq ($(OSTYPE),cygwin) - MKDIR := mkdir -p - RM := rm -f - TARGET_EXT := .exe -else - MKDIR := mkdir -p - RM := rm -f - TARGET_EXT := -endif - -#----------------------------------------------------------------------------- -# build options... - -BIN_DIR := build - -CFLAGS := -c -g -O -fno-pie -std=c11 -pedantic -Wall -Wextra -W \ - $(INCLUDES) $(DEFINES) -DQ_HOST - -CPPFLAGS := -c -g -O -fno-pie -std=c++11 -pedantic -Wall -Wextra \ - -fno-rtti -fno-exceptions \ - $(INCLUDES) $(DEFINES) -DQ_HOST - -ifndef GCC_OLD - LINKFLAGS := -no-pie -endif - -ifdef GCOV - CFLAGS += -fprofile-arcs -ftest-coverage - CPPFLAGS += -fprofile-arcs -ftest-coverage - LINKFLAGS += -lgcov --coverage -endif - -#----------------------------------------------------------------------------- -C_OBJS := $(patsubst %.c,%.o, $(C_SRCS)) -CPP_OBJS := $(patsubst %.cpp,%.o, $(CPP_SRCS)) - -TARGET_EXE := $(BIN_DIR)/$(PROJECT)$(TARGET_EXT) -C_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(C_OBJS)) -C_DEPS_EXT := $(patsubst %.o,%.d, $(C_OBJS_EXT)) -CPP_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(CPP_OBJS)) -CPP_DEPS_EXT := $(patsubst %.o,%.d, $(CPP_OBJS_EXT)) - -#----------------------------------------------------------------------------- -# rules -# - -.PHONY : norun clean show - -ifeq ($(MAKECMDGOALS),norun) -all : $(TARGET_EXE) -norun : all -else -all : $(TARGET_EXE) run -endif - -$(TARGET_EXE) : $(C_OBJS_EXT) $(CPP_OBJS_EXT) - $(CPP) $(CPPFLAGS) $(QPCPP)/src/qs/qstamp.cpp -o $(BIN_DIR)/qstamp.o - $(LINK) $(LINKFLAGS) $(LIB_DIRS) -o $@ $^ $(BIN_DIR)/qstamp.o $(LIBS) - -run : $(TARGET_EXE) - $(TARGET_EXE) - -$(BIN_DIR)/%.d : %.cpp - $(CPP) -MM -MT $(@:.d=.o) $(CPPFLAGS) $< > $@ - -$(BIN_DIR)/%.d : %.c - $(CC) -MM -MT $(@:.d=.o) $(CFLAGS) $< > $@ - -$(BIN_DIR)/%.o : %.c - $(CC) $(CFLAGS) $< -o $@ - -$(BIN_DIR)/%.o : %.cpp - $(CPP) $(CPPFLAGS) $< -o $@ - -# create BIN_DIR and include dependencies only if needed -ifneq ($(MAKECMDGOALS),clean) - ifneq ($(MAKECMDGOALS),show) - ifneq ($(MAKECMDGOALS),debug) -ifeq ("$(wildcard $(BIN_DIR))","") -$(shell $(MKDIR) $(BIN_DIR)) -endif --include $(C_DEPS_EXT) $(CPP_DEPS_EXT) - endif - endif -endif - -clean : - -$(RM) $(BIN_DIR)/*.* - -show : - @echo PROJECT = $(PROJECT) - @echo TARGET_EXE = $(TARGET_EXE) - @echo VPATH = $(VPATH) - @echo C_SRCS = $(C_SRCS) - @echo CPP_SRCS = $(CPP_SRCS) - @echo C_DEPS_EXT = $(C_DEPS_EXT) - @echo C_OBJS_EXT = $(C_OBJS_EXT) - @echo C_DEPS_EXT = $(C_DEPS_EXT) - @echo CPP_DEPS_EXT = $(CPP_DEPS_EXT) - @echo CPP_OBJS_EXT = $(CPP_OBJS_EXT) - @echo LIB_DIRS = $(LIB_DIRS) - @echo LIBS = $(LIBS) - @echo DEFINES = $(DEFINES) - diff --git a/test/qs/qs_rx/qp_port.hpp b/test/qs/qs_rx/qp_port.hpp deleted file mode 100644 index 28dfbb496..000000000 --- a/test/qs/qs_rx/qp_port.hpp +++ /dev/null @@ -1,103 +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-29 -//! @version Last updated for: @ref qpcpp_7_3_0 -//! -//! @file -//! @brief QP/C++ port for QUIT unit internal test, Win32 with GNU/VisualC++ - -#ifndef QP_PORT_HPP_ -#define QP_PORT_HPP_ - -#include // Exact-width types. C++11 Standard - -#ifdef __GNUC__ - - // no-return function specifier (GCC-ARM compiler) - #define Q_NORETURN __attribute__ ((noreturn)) void - -#elif (defined _MSC_VER) && (defined __cplusplus) - - // no-return function specifier (Microsoft Visual Studio compiler) - #define Q_NORETURN [[ noreturn ]] void - -#endif - -// QActive event queue type -#define QACTIVE_EQUEUE_TYPE QEQueue - -// The maximum number of active objects in the application -#define QF_MAX_ACTIVE 64U - -// The number of system clock tick rates -#define QF_MAX_TICK_RATE 2U - -// Activate the QF QActive::stop() API -#define QACTIVE_CAN_STOP 1 - -// QF interrupt disable/enable -#define QF_INT_DISABLE() (static_cast(0)) -#define QF_INT_ENABLE() (static_cast(0)) - -// QUIT critical section -#define QF_CRIT_STAT -#define QF_CRIT_ENTRY() QF_INT_DISABLE() -#define QF_CRIT_EXIT() QF_INT_ENABLE() - -// QF_LOG2 not defined -- use the internal LOG2() implementation - -// include files ------------------------------------------------------------- -#include "qequeue.hpp" // Win32-QV needs the native event-queue -#include "qmpool.hpp" // Win32-QV needs the native memory-pool -#include "qp.hpp" // QP platform-independent public interface - -//============================================================================ -// interface used only inside QF implementation, but not in applications - -#ifdef QP_IMPL - - // ET scheduler locking, not used - #define QF_SCHED_STAT_ - #define QF_SCHED_LOCK_(dummy) (static_cast(0)) - #define QF_SCHED_UNLOCK_() (static_cast(0)) - - // native event queue operations... - #define QACTIVE_EQUEUE_WAIT_(me_) \ - Q_ASSERT((me_)->m_eQueue.m_frontEvt != nullptr) - #define QACTIVE_EQUEUE_SIGNAL_(me_) (static_cast(0)) - - // native QF event pool operations - #define QF_EPOOL_TYPE_ QMPool - #define QF_EPOOL_INIT_(p_, poolSto_, poolSize_, evtSize_) \ - (p_).init((poolSto_), (poolSize_), (evtSize_)) - #define QF_EPOOL_EVENT_SIZE_(p_) ((p_).getBlockSize()) - #define QF_EPOOL_GET_(p_, e_, m_, qsId_) \ - ((e_) = static_cast((p_).get((m_), (qsId_)))) - #define QF_EPOOL_PUT_(p_, e_, qsId_) ((p_).put((e_), (qsId_))) - -#endif // QP_IMPL - -#endif // QP_PORT_HPP_ - diff --git a/test/qs/qs_rx/qs_port.hpp b/test/qs/qs_rx/qs_port.hpp deleted file mode 100644 index 8b749a1d0..000000000 --- a/test/qs/qs_rx/qs_port.hpp +++ /dev/null @@ -1,61 +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-18 -//! @version Last updated for: @ref qpcpp_7_3_0 -//! -//! @file -//! @brief QS/C++ port for testing on Windows/Linux/macOS, GNU or Visual C++ - -#ifndef QS_PORT_HPP_ -#define QS_PORT_HPP_ - -#define QS_CTR_SIZE 4U -#define QS_TIME_SIZE 4U - -#if defined(_WIN64) || defined(__LP64__) || defined(_LP64) // 64-bit OS? - #define QS_OBJ_PTR_SIZE 8U - #define QS_FUN_PTR_SIZE 8U -#else // 32-bit OS - #define QS_OBJ_PTR_SIZE 4U - #define QS_FUN_PTR_SIZE 4U -#endif - -// flush the QS output buffer after each QS record -#define QS_REC_DONE() QP::QS::onFlush() - -//============================================================================ -// 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.hpp" *before* "qs.hpp". -// -#ifndef QP_PORT_HPP_ -#include "qp_port.hpp" // use QS with QP -#endif - -#include "qs.hpp" // QS platform-independent public interface - -#endif // QS_PORT_HPP_ - diff --git a/test/qs/qs_rx/test.cpp b/test/qs/qs_rx/test.cpp deleted file mode 100644 index 87ae16cb2..000000000 --- a/test/qs/qs_rx/test.cpp +++ /dev/null @@ -1,144 +0,0 @@ -#include "et.h" // ET: embedded test - -// includes for the CUT... -#include "qp_port.hpp" // QP/C++ port from the port directory -#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem -#ifdef Q_SPY /* software tracing enabled? */ -#include "qs_port.hpp" // QS port from the port directory -#else -#include "qs_dummy.hpp" // QS dummy (inactive) interface -#endif - -extern "C" { - -enum { RX_SIZE = 8 }; - -static std::uint8_t qsBuf[100]; // buffer for QS-TX channel -static std::uint8_t qsRxBuf[RX_SIZE]; // buffer for QS-RX channel - -//............................................................................ -void setup(void) { -} -//............................................................................ -void teardown(void) { -} -//............................................................................ -TEST_GROUP("QS/RX") { - -QP::QS::initBuf(qsBuf, sizeof(qsBuf)); - -TEST("QS-RX initialization") { - QP::QS::rxInitBuf(qsRxBuf, RX_SIZE); - VERIFY(RX_SIZE - 1 == QP::QS::rxGetNfree()); -} - -TEST("QS-RX putting 3") { - VERIFY(QP::QS::rxPut(0x1U)); - VERIFY(QP::QS::rxPut(0x2U)); - VERIFY(QP::QS::rxPut(0x3U)); - VERIFY(RX_SIZE - 1 - 3 == QP::QS::rxGetNfree()); -} - -TEST("QS-RX QS::rxParse") { - QP::QS::rxParse(); - VERIFY(RX_SIZE - 1 == QP::QS::rxGetNfree()); -} - -TEST("QS-RX putting 6") { - VERIFY(QP::QS::rxPut(0x1U)); - VERIFY(QP::QS::rxPut(0x2U)); - VERIFY(QP::QS::rxPut(0x3U)); - VERIFY(QP::QS::rxPut(0x4U)); - VERIFY(QP::QS::rxPut(0x5U)); - VERIFY(QP::QS::rxPut(0x6U)); - VERIFY(RX_SIZE - 1 - 6 == QP::QS::rxGetNfree()); -} - -TEST("QS-RX putting 3 more") { - VERIFY(QP::QS::rxPut(0x7U)); - VERIFY(false == QP::QS::rxPut(0x8U)); - VERIFY(false == QP::QS::rxPut(0x9U)); - VERIFY(0 == QP::QS::rxGetNfree()); -} - -} // TEST_GROUP() - -} // extern "C" - -//============================================================================ -// dependencies for the CUT ... - -//............................................................................ -extern "C" Q_NORETURN Q_onError(char const * const module, int_t const loc) { - Q_UNUSED_PAR(module); - Q_UNUSED_PAR(loc); - ET_onExit(-1); - for (;;) { // make explicitly noreturn - } -} - -namespace QP { - -//............................................................................ -std::uint_fast16_t QF::poolGetMaxBlockSize(void) noexcept { - return 0U; -} -//............................................................................ -void QTimeEvt::tick( - std::uint_fast8_t const tickRate, - void const * const sender) noexcept -{ - Q_UNUSED_PAR(tickRate); - Q_UNUSED_PAR(sender); -} -//............................................................................ -void QActive::publish_( - QEvt const * const e, - void const * const sender, - std::uint_fast8_t const qs_id) noexcept -{ - Q_UNUSED_PAR(e); - Q_UNUSED_PAR(sender); - Q_UNUSED_PAR(qs_id); -} -//............................................................................ -QEvt *QF::newX_(std::uint_fast16_t const evtSize, - std::uint_fast16_t const margin, enum_t const sig) noexcept -{ - Q_UNUSED_PAR(evtSize); - Q_UNUSED_PAR(margin); - Q_UNUSED_PAR(sig); - return nullptr; -} -//............................................................................ -void QF::gc(QEvt const * const e) noexcept { - Q_UNUSED_PAR(e); -} - -/*--------------------------------------------------------------------------*/ -#ifdef Q_SPY - -void QS::onCleanup(void) { -} -//............................................................................ -void QS::onReset(void) { -} -//............................................................................ -void QS::onFlush(void) { -} -//............................................................................ -QSTimeCtr QS::onGetTime(void) { - return (QSTimeCtr)0U; -} -//............................................................................ -void QS::onCommand(uint8_t cmdId, uint32_t param1, - uint32_t param2, uint32_t param3) -{ - (void)cmdId; - (void)param1; - (void)param2; - (void)param3; -} -#endif // Q_SPY - -} // namespace QP diff --git a/test/qs/qs_rx/test.sln b/test/qs/qs_rx/test.sln deleted file mode 100644 index b0e726532..000000000 --- a/test/qs/qs_rx/test.sln +++ /dev/null @@ -1,21 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.30804.86 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test", "test.vcxproj", "{8CC465F7-872E-4D03-B93C-1B64858B4E11}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {8CC465F7-872E-4D03-B93C-1B64858B4E11}.Debug|Win32.ActiveCfg = Debug|Win32 - {8CC465F7-872E-4D03-B93C-1B64858B4E11}.Debug|Win32.Build.0 = Debug|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {5927F686-5967-4B02-A7EA-25F81A1236DB} - EndGlobalSection -EndGlobal diff --git a/test/qs/qs_rx/test.vcxproj b/test/qs/qs_rx/test.vcxproj deleted file mode 100644 index 696d098fe..000000000 --- a/test/qs/qs_rx/test.vcxproj +++ /dev/null @@ -1,75 +0,0 @@ - - - - - Debug - Win32 - - - - - - - - - - - - - - - {8CC465F7-872E-4D03-B93C-1B64858B4E11} - test - Win32Proj - 10.0 - - - - Application - NotSet - v142 - - - - - - - - - - <_ProjectFileVersion>10.0.40219.1 - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - true - - - - Disabled - .;../../include;/GitHub/ET;%(AdditionalIncludeDirectories) - Q_SPY;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - false - - - Default - MultiThreaded - NotUsing - Level4 - ProgramDatabase - 4127 - Default - - - %(AdditionalDependencies) - ../../../ports/win32-qv/$(Configuration);%(AdditionalLibraryDirectories) - true - Console - MachineX86 - - - cmd /c "del $(OutDir)qstamp.obj" - - - - - - \ No newline at end of file diff --git a/test/qs/qs_rx/test.vcxproj.filters b/test/qs/qs_rx/test.vcxproj.filters deleted file mode 100644 index 38e0a851f..000000000 --- a/test/qs/qs_rx/test.vcxproj.filters +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - {ca98b393-b6d6-4f0f-8d96-ee6821a59d87} - - - {6e759350-7436-4cde-b0b3-c2eb2a7f276b} - - - - - - \ No newline at end of file diff --git a/test/qxk/README.txt b/test/qxk/README.txt deleted file mode 100644 index 4b3125c3d..000000000 --- a/test/qxk/README.txt +++ /dev/null @@ -1,13 +0,0 @@ -This directory contains tests of the QXK kernel. -These are SYSTEM tests, where QP is not stubbed-out, but -rather the actual QP code is used instead. - -NOTE: -The tests run only on embedded targets and do NOT -run on the host computer. - -NOTE: -To avoid stubbing-out the QP framework, the tests -define Q_UTEST=0 - - diff --git a/test/qxk/test_sched/bsp.hpp b/test/qxk/test_sched/bsp.hpp deleted file mode 100644 index bf7b2d407..000000000 --- a/test/qxk/test_sched/bsp.hpp +++ /dev/null @@ -1,66 +0,0 @@ -//============================================================================ -// Product: BSP for system-testing QXK -// Last updated for version 7.3.0 -// Last updated on 2023-09-06 -// -// 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: -// -// -//============================================================================ -#ifndef BSP_HPP_ -#define BSP_HPP_ - -namespace BSP { - -void init(void); -void terminate(int16_t const result); - -// for testing... -void trace(QP::QActive const *thr, char const *msg); -void wait4PB1(void); -void ledOn(void); -void ledOff(void); -void trigISR(void); - -uint32_t romRead(int32_t offset, uint32_t fromEnd); -void romWrite(int32_t offset, uint32_t fromEnd, uint32_t value); - -uint32_t ramRead(int32_t offset, uint32_t fromEnd); -void ramWrite(int32_t offset, uint32_t fromEnd, uint32_t value); - -} // namespace BSP - -enum TestSignals { - TEST0_SIG = QP::Q_USER_SIG, - TEST1_SIG, - TEST2_SIG, - TEST3_SIG, - MAX_PUB_SIG, // the last published signal - - MAX_SIG // the last signal -}; - -#endif // BSP_HPP_ - diff --git a/test/qxk/test_sched/bsp_efm32pg1b.cpp b/test/qxk/test_sched/bsp_efm32pg1b.cpp deleted file mode 100644 index af883f766..000000000 --- a/test/qxk/test_sched/bsp_efm32pg1b.cpp +++ /dev/null @@ -1,375 +0,0 @@ -//============================================================================ -// Product: BSP for system-testing of QXK kernel, EFM32-SLSTK3401A board -// Last updated for version 7.2.0 -// Last updated on 2022-12-13 -// -// Q u a n t u m L e a P s -// ------------------------ -// Modern Embedded Software -// -// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -// -// This program is open source software: you can redistribute it and/or -// modify it under the terms of the GNU General Public License as published -// by the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Alternatively, this program may be distributed and modified under the -// terms of Quantum Leaps commercial licenses, which expressly supersede -// the GNU General Public License and are specifically designed for -// licensees interested in retaining the proprietary status of their code. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -// Contact information: -// -// -//============================================================================ -#include "qpcpp.hpp" -#include "bsp.hpp" - -#include "em_device.h" // the device specific header (SiLabs) -#include "em_cmu.h" // Clock Management Unit (SiLabs) -#include "em_gpio.h" // GPIO (SiLabs) -#include "em_usart.h" // USART (SiLabs) -// add other drivers if necessary... - -namespace { - -Q_DEFINE_THIS_FILE - -// Local-scope objects ------------------------------------------------------- -#define LED_PORT gpioPortF -#define LED0_PIN 4 -#define LED1_PIN 5 - -#define PB_PORT gpioPortF -#define PB0_PIN 6 -#define PB1_PIN 7 - -#ifdef Q_SPY - - // QSpy source IDs - static QP::QSpyId const l_SysTick_Handler = { 100U }; - static QP::QSpyId const l_test_ISR = { 101U }; - - enum AppRecords { // application-specific trace records - CONTEXT_SW = QP::QS_USER1, - TRACE_MSG - }; - -#endif - -} // unnamed namespace - -// ISRs used in this project ================================================= -extern "C" { - -//............................................................................ -void SysTick_Handler(void); // prototype -void SysTick_Handler(void) { - QXK_ISR_ENTRY(); // inform QXK about entering an ISR - - QP::QTimeEvt::TICK_X(0U, &l_SysTick_Handler); - //the_Ticker0->TRIG(&l_SysTick_Handler); - - QXK_ISR_EXIT(); // inform QXK about exiting an ISR -} -//............................................................................ -void GPIO_EVEN_IRQHandler(void); // prototype -void GPIO_EVEN_IRQHandler(void) { - QXK_ISR_ENTRY(); // inform QXK about entering an ISR - - // for testing... - static QP::QEvt const t1(TEST1_SIG); - QP::QF::PUBLISH(&t1, &l_test_ISR); - - QXK_ISR_EXIT(); // inform QXK about exiting an ISR -} - -} // extern "C" - -// BSP functions ============================================================= - -// MPU setup for EFM32PG1B200F256GM48 MCU -static void EFM32PG182_MPU_setup(void) { - // The following MPU configuration contains the general EFM32PG1 memory - // map described in the EFM32PG1 Data Sheet Figure 3.2. EFM32PG1 Memory Map - // - // Please note that the actual STM32 MCUs provide much less Flash and SRAM - // than the maximums configured here. This means that actual MCUs have - // unmapped memory regions (e.g., beyond the actual SRAM). Attempts to - // access these regions causes the HardFault exception, which is the - // desired behavior. - // - static struct { - uint32_t rbar; - uint32_t rasr; - } const mpu_setup[] = { - - { // region #0: Flash: base=0x0000'0000, size=512M=2^(28+1) - 0x00000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 0U), // region #0 - (28U << MPU_RASR_SIZE_Pos) // 2^(18+1) region - | (0x6U << MPU_RASR_AP_Pos) // PA:ro/UA:ro - | (1U << MPU_RASR_C_Pos) // C=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - { // region #1: SRAM: base=0x2000'0000, size=512M=2^(28+1) - 0x20000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 1U), // region #1 - (28U << MPU_RASR_SIZE_Pos) // 2^(28+1) region - | (0x3U << MPU_RASR_AP_Pos) // PA:rw/UA:rw - | (1U << MPU_RASR_XN_Pos) // XN=1 - | (1U << MPU_RASR_S_Pos) // S=1 - | (1U << MPU_RASR_C_Pos) // C=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - // region #3: (not configured) - { MPU_RBAR_VALID_Msk | (MPU_RBAR_REGION_Msk & 2U), 0U }, - - { // region #3: Peripherals: base=0x4000'0000, size=512M=2^(28+1) - 0x40000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 3U), // region #3 - (28U << MPU_RASR_SIZE_Pos) // 2^(28+1) region - | (0x3U << MPU_RASR_AP_Pos) // PA:rw/UA:rw - | (1U << MPU_RASR_XN_Pos) // XN=1 - | (1U << MPU_RASR_S_Pos) // S=1 - | (1U << MPU_RASR_B_Pos) // B=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - { // region #4: Priv. Periph: base=0xE000'0000, size=512M=2^(28+1) - 0xE0000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 4U), // region #4 - (28U << MPU_RASR_SIZE_Pos) // 2^(28+1) region - | (0x3U << MPU_RASR_AP_Pos) // PA:rw/UA:rw - | (1U << MPU_RASR_XN_Pos) // XN=1 - | (1U << MPU_RASR_S_Pos) // S=1 - | (1U << MPU_RASR_B_Pos) // B=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - { // region #5: Ext RAM: base=0x6000'0000, size=1G=2^(29+1) - 0x60000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 5U), // region #5 - (29U << MPU_RASR_SIZE_Pos) // 2^(28+1) region - | (0x3U << MPU_RASR_AP_Pos) // PA:rw/UA:rw - | (1U << MPU_RASR_XN_Pos) // XN=1 - | (1U << MPU_RASR_S_Pos) // S=1 - | (1U << MPU_RASR_B_Pos) // B=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - { // region #6: Ext Dev: base=0xA000'0000, size=1G=2^(29+1) - 0xA0000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 6U), // region #6 - (29U << MPU_RASR_SIZE_Pos) // 2^(28+1) region - | (0x3U << MPU_RASR_AP_Pos) // PA:rw/UA:rw - | (1U << MPU_RASR_XN_Pos) // XN=1 - | (1U << MPU_RASR_S_Pos) // S=1 - | (1U << MPU_RASR_B_Pos) // B=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - { // region #7: NULL-pointer: base=0x000'0000, size=256B, NOTE0 - 0x00000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 7U), // region #7 - (7U << MPU_RASR_SIZE_Pos) // 2^(7+1)=256B region - | (0x0U << MPU_RASR_AP_Pos) // PA:na/UA:na - | (1U << MPU_RASR_XN_Pos) // XN=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - }; - - // enable the MemManage_Handler for MPU exception - SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; - - __DSB(); - MPU->CTRL = 0U; // disable the MPU - for (uint_fast8_t n = 0U; n < Q_DIM(mpu_setup); ++n) { - MPU->RBAR = mpu_setup[n].rbar; - MPU->RASR = mpu_setup[n].rasr; - } - MPU->CTRL = MPU_CTRL_ENABLE_Msk; // enable the MPU - __ISB(); - __DSB(); -} -//............................................................................ -void BSP::init(void) { - // setup the MPU... - EFM32PG182_MPU_setup(); - - // NOTE: SystemInit() already called from the startup code - // but SystemCoreClock needs to be updated - // - SystemCoreClockUpdate(); - - // NOTE: The VFP (hardware Floating Point) unit is configured by QXK - - // enable clock for to the peripherals used by this application... - CMU_ClockEnable(cmuClock_HFPER, true); - CMU_ClockEnable(cmuClock_GPIO, true); - CMU_ClockEnable(cmuClock_HFPER, true); - CMU_ClockEnable(cmuClock_GPIO, true); - - // configure the LEDs - GPIO_PinModeSet(LED_PORT, LED0_PIN, gpioModePushPull, 0); - GPIO_PinModeSet(LED_PORT, LED1_PIN, gpioModePushPull, 0); - GPIO_PinOutClear(LED_PORT, LED0_PIN); - GPIO_PinOutClear(LED_PORT, LED1_PIN); - - // configure the Buttons - GPIO_PinModeSet(PB_PORT, PB0_PIN, gpioModeInputPull, 1); - GPIO_PinModeSet(PB_PORT, PB1_PIN, gpioModeInputPull, 1); - - // initialize the QS software tracing... - if (!QS_INIT(nullptr)) { // initialize the QS software tracing - Q_ERROR(); - } - QS_OBJ_DICTIONARY(&l_SysTick_Handler); - QS_OBJ_DICTIONARY(&l_test_ISR); - - QS_USR_DICTIONARY(CONTEXT_SW); - QS_USR_DICTIONARY(TRACE_MSG); -} -//............................................................................ -void BSP::terminate(int16_t result) { - Q_UNUSED_PAR(result); -} -//............................................................................ -void BSP::ledOn(void) { - GPIO->P[LED_PORT].DOUT = GPIO->P[LED_PORT].DOUT | (1U << LED1_PIN); -} -//............................................................................ -void BSP::ledOff(void) { - GPIO->P[LED_PORT].DOUT = GPIO->P[LED_PORT].DOUT & ~(1U << LED1_PIN); -} -//............................................................................ -void BSP::trigISR(void) { - NVIC_SetPendingIRQ(GPIO_EVEN_IRQn); -} -//............................................................................ -void BSP::trace(QP::QActive const *thr, char const *msg) { - QS_BEGIN_ID(TRACE_MSG, 0U) - QS_OBJ(thr); - QS_STR(msg); - QS_END() -} -//............................................................................ -uint32_t BSP::romRead(int32_t offset, uint32_t fromEnd) { - int32_t const rom_base = (fromEnd == 0U) - ? 0x100 // don't include the NULL-ptr region - : 0x40000 - 4; - return *(uint32_t volatile *)(rom_base + offset); -} -//............................................................................ -void BSP::romWrite(int32_t offset, uint32_t fromEnd, uint32_t value) { - int32_t const rom_base = (fromEnd == 0U) - ? 0x100 // don't include the NULL-ptr region - : 0x40000 - 4; - *(uint32_t volatile *)(rom_base + offset) = value; -} - -//............................................................................ -uint32_t BSP::ramRead(int32_t offset, uint32_t fromEnd) { - int32_t const ram_base = (fromEnd == 0U) - ? 0x20000000 - : 0x20008000 - 4; - return *(uint32_t volatile *)(ram_base + offset); -} -//............................................................................ -void BSP::ramWrite(int32_t offset, uint32_t fromEnd, uint32_t value) { - int32_t const ram_base = (fromEnd == 0U) - ? 0x20000000 - : 0x20008000 - 4; - *(uint32_t volatile *)(ram_base + offset) = value; -} - -// namespace QP ============================================================== -namespace QP { - -// QF callbacks -------------------------------------------------------------- -void QF::onStartup(void) { - // assign all priority bits for preemption-prio. and none to sub-prio. - NVIC_SetPriorityGrouping(0U); - - // set priorities of ALL ISRs used in the system - NVIC_SetPriority(USART0_RX_IRQn, 0U); // kernel UNAWARE interrupt - NVIC_SetPriority(GPIO_EVEN_IRQn, QF_AWARE_ISR_CMSIS_PRI + 0U); - NVIC_SetPriority(SysTick_IRQn, QF_AWARE_ISR_CMSIS_PRI + 1U); - // ... - - // enable IRQs... - NVIC_EnableIRQ(GPIO_EVEN_IRQn); -} -//............................................................................ -void QF::onCleanup(void) { -} -//............................................................................ -void QXK::onIdle(void) { -#ifdef Q_SPY - QS::rxParse(); // parse all the received bytes - QS::doOutput(); -#elif defined NDEBUG - // Put the CPU and peripherals to the low-power mode. - // you might need to customize the clock management for your application, - // see the datasheet for your particular Cortex-M3 MCU. - // - __WFI(); // Wait-For-Interrupt -#endif -} - -// QS callbacks ============================================================== -//............................................................................ -void QTimeEvt::tick1_( - uint_fast8_t const tickRate, - void const * const sender) -{ - QF_INT_DISABLE(); - // TODO pend the SysTick - *Q_UINT2PTR_CAST(uint32_t, 0xE000ED04U) = (1U << 26U); - QF_INT_ENABLE(); -} - -//---------------------------------------------------------------------------- - -} // namespace QP - -extern "C" { -//............................................................................ -#ifdef QF_ON_CONTEXT_SW -// NOTE: the context-switch callback is called with interrupts DISABLED -void QF_onContextSw(QP::QActive *prev, QP::QActive *next) { - QS_BEGIN_INCRIT(CONTEXT_SW, 0U) // no critical section! - QS_OBJ(prev); - QS_OBJ(next); - QS_END_INCRIT() -} -#endif // QF_ON_CONTEXT_SW - -} // extern "C" - -//============================================================================ -// NOTE0: -// The MPU protection against NULL-pointer dereferencing sets up a no-access -// MPU region #7 around the NULL address (0x0). This works even though the -// Vector Table also resides at address 0x0. However, the *size* of the -// no-access region should not exceed the size of the Vector Table. In this -// case, the size is set to 2^(7+1)==256 bytes, which does not contain any -// data that the CPU would legitimately read with the LDR instruction. diff --git a/test/qxk/test_sched/bsp_nucleo-c031c6.cpp b/test/qxk/test_sched/bsp_nucleo-c031c6.cpp deleted file mode 100644 index 478a86732..000000000 --- a/test/qxk/test_sched/bsp_nucleo-c031c6.cpp +++ /dev/null @@ -1,362 +0,0 @@ -//============================================================================ -// Product: BSP for system-testing of QXK kernel, NUCLEO-C031C6 board -// Last updated for version 7.3.0 -// Last updated on 2023-07-18 -// -// Q u a n t u m L e a P s -// ------------------------ -// Modern Embedded Software -// -// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -// -// This program is open source software: you can redistribute it and/or -// modify it under the terms of the GNU General Public License as published -// by the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Alternatively, this program may be distributed and modified under the -// terms of Quantum Leaps commercial licenses, which expressly supersede -// the GNU General Public License and are specifically designed for -// licensees interested in retaining the proprietary status of their code. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -// Contact information: -// -// -//============================================================================ -#include "qpcpp.hpp" -#include "bsp.hpp" - -#include "stm32c0xx.h" // CMSIS-compliant header file for the MCU used -// add other drivers if necessary... - -namespace { - -Q_DEFINE_THIS_FILE - -// Local-scope objects ----------------------------------------------------- -// LED pins available on the board (just one user LED LD4--Green on PA.5) -#define LD4_PIN 5U - -// Button pins available on the board (just one user Button B1 on PC.13) -#define B1_PIN 13U - -#ifdef Q_SPY - - // QSpy source IDs - static QP::QSpyId const l_SysTick_Handler = { 100U }; - static QP::QSpyId const l_test_ISR = { 101U }; - - enum AppRecords { // application-specific trace records - CONTEXT_SW = QP::QS_USER1, - TRACE_MSG - }; - -#endif - -} // unnamed namespace - -// ISRs used in this project ================================================= -extern "C" { - -//............................................................................ -void SysTick_Handler(void); // prototype -void SysTick_Handler(void) { - QXK_ISR_ENTRY(); // inform QXK about entering an ISR - - QP::QTimeEvt::TICK_X(0U, &l_SysTick_Handler); - //the_Ticker0->TRIG(&l_SysTick_Handler); - - QXK_ISR_EXIT(); // inform QXK about exiting an ISR -} -//............................................................................ -void EXTI0_1_IRQHandler(void); // prototype -void EXTI0_1_IRQHandler(void) { - QXK_ISR_ENTRY(); // inform QXK about entering an ISR - - // for testing... - static QP::QEvt const t1(TEST1_SIG); - QP::QF::PUBLISH(&t1, &l_test_ISR); - - QXK_ISR_EXIT(); // inform QXK about exiting an ISR -} - -} // extern "C" - -// BSP functions ============================================================= - -static void STM32C031C6_MPU_setup(void) { - // The following MPU configuration contains the general STM32 memory model - // as described in the ST AppNote AN4838 "Managing memory protection unit - // in STM32 MCUs", Figure 2. Cortex-M0+/M3/M4/M7 processor memory map. - // - // Please note that the actual STM32 MCUs provide much less Flash and SRAM - // than the maximums configured here. This means that actual MCUs have - // unmapped memory regions (e.g., beyond the actual SRAM). Attempts to - // access these regions causes the HardFault exception, which is the - // desired behavior. - // - static struct { - uint32_t rbar; - uint32_t rasr; - } const mpu_setup[] = { - - { // region #0: Flash: base=0x0000'0000, size=512M=2^(28+1) - 0x00000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 0U), // region #0 - (28U << MPU_RASR_SIZE_Pos) // 2^(18+1) region - | (0x6U << MPU_RASR_AP_Pos) // PA:ro/UA:ro - | (1U << MPU_RASR_C_Pos) // C=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - { // region #1: SRAM: base=0x2000'0000, size=512M=2^(28+1) - 0x20000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 1U), // region #1 - (28U << MPU_RASR_SIZE_Pos) // 2^(28+1) region - | (0x3U << MPU_RASR_AP_Pos) // PA:rw/UA:rw - | (1U << MPU_RASR_XN_Pos) // XN=1 - | (1U << MPU_RASR_S_Pos) // S=1 - | (1U << MPU_RASR_C_Pos) // C=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - // region #3: (not configured) - { MPU_RBAR_VALID_Msk | (MPU_RBAR_REGION_Msk & 2U), 0U }, - - { // region #3: Peripherals: base=0x4000'0000, size=512M=2^(28+1) - 0x40000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 3U), // region #3 - (28U << MPU_RASR_SIZE_Pos) // 2^(28+1) region - | (0x3U << MPU_RASR_AP_Pos) // PA:rw/UA:rw - | (1U << MPU_RASR_XN_Pos) // XN=1 - | (1U << MPU_RASR_S_Pos) // S=1 - | (1U << MPU_RASR_B_Pos) // B=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - { // region #4: Priv. Periph: base=0xE000'0000, size=512M=2^(28+1) - 0xE0000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 4U), // region #4 - (28U << MPU_RASR_SIZE_Pos) // 2^(28+1) region - | (0x3U << MPU_RASR_AP_Pos) // PA:rw/UA:rw - | (1U << MPU_RASR_XN_Pos) // XN=1 - | (1U << MPU_RASR_S_Pos) // S=1 - | (1U << MPU_RASR_B_Pos) // B=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - { // region #5: Ext RAM: base=0x6000'0000, size=1G=2^(29+1) - 0x60000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 5U), // region #5 - (29U << MPU_RASR_SIZE_Pos) // 2^(28+1) region - | (0x3U << MPU_RASR_AP_Pos) // PA:rw/UA:rw - | (1U << MPU_RASR_XN_Pos) // XN=1 - | (1U << MPU_RASR_S_Pos) // S=1 - | (1U << MPU_RASR_B_Pos) // B=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - { // region #6: Ext Dev: base=0xA000'0000, size=1G=2^(29+1) - 0xA0000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 6U), // region #6 - (29U << MPU_RASR_SIZE_Pos) // 2^(28+1) region - | (0x3U << MPU_RASR_AP_Pos) // PA:rw/UA:rw - | (1U << MPU_RASR_XN_Pos) // XN=1 - | (1U << MPU_RASR_S_Pos) // S=1 - | (1U << MPU_RASR_B_Pos) // B=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - { // region #7: NULL-pointer: base=0x000'0000, size=128M=2^(26+1) - // NOTE: this region extends to 0x080'0000, which is where - // the ROM is re-mapped by STM32 - 0x00000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 7U), // region #7 - (26U << MPU_RASR_SIZE_Pos) // 2^(26+1)=128M region - | (0x0U << MPU_RASR_AP_Pos) // PA:na/UA:na - | (1U << MPU_RASR_XN_Pos) // XN=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - }; - - MPU->CTRL = 0U; // disable the MPU - for (uint_fast8_t n = 0U; n < Q_DIM(mpu_setup); ++n) { - MPU->RBAR = mpu_setup[n].rbar; - MPU->RASR = mpu_setup[n].rasr; - } - MPU->CTRL = MPU_CTRL_PRIVDEFENA_Msk // enable background region - | MPU_CTRL_ENABLE_Msk; // enable the MPU - __ISB(); - __DSB(); -} -//............................................................................ -void BSP::init(void) { - // setup the MPU... - STM32C031C6_MPU_setup(); - - // initialize the QS software tracing... - if (!QS_INIT(nullptr)) { // initialize the QS software tracing - Q_ERROR(); - } - - // dictionaries... - QS_OBJ_DICTIONARY(&l_SysTick_Handler); - QS_OBJ_DICTIONARY(&l_test_ISR); - - QS_USR_DICTIONARY(CONTEXT_SW); - QS_USR_DICTIONARY(TRACE_MSG); -} -//............................................................................ -void BSP::terminate(int16_t result) { - Q_UNUSED_PAR(result); -} -//............................................................................ -void BSP::ledOn(void) { - GPIOA->BSRR = (1U << LD4_PIN); // turn LD4 on -} -//............................................................................ -void BSP::ledOff(void) { - GPIOA->BSRR = (1U << (LD4_PIN + 16U)); // turn LD4 off -} -//............................................................................ -void BSP::trigISR(void) { - NVIC_SetPendingIRQ(EXTI0_1_IRQn); -} -//............................................................................ -void BSP::trace(QP::QActive const *thr, char const *msg) { - QS_BEGIN_ID(TRACE_MSG, 0U) - QS_OBJ(thr); - QS_STR(msg); - QS_END() -} -//............................................................................ -uint32_t BSP::romRead(int32_t offset, uint32_t fromEnd) { - int32_t const rom_base = (fromEnd == 0U) - ? 0x08000000 - : 0x08008000 - 4; - return *(uint32_t volatile *)(rom_base + offset); -} -//............................................................................ -void BSP::romWrite(int32_t offset, uint32_t fromEnd, uint32_t value) { - int32_t const rom_base = (fromEnd == 0U) - ? 0x08000000 - : 0x08008000 - 4; - *(uint32_t volatile *)(rom_base + offset) = value; -} - -//............................................................................ -uint32_t BSP::ramRead(int32_t offset, uint32_t fromEnd) { - int32_t const ram_base = (fromEnd == 0U) - ? 0x20000000 - : 0x20003000 - 4; - return *(uint32_t volatile *)(ram_base + offset); -} -//............................................................................ -void BSP::ramWrite(int32_t offset, uint32_t fromEnd, uint32_t value) { - int32_t const ram_base = (fromEnd == 0U) - ? 0x20000000 - : 0x20003000 - 4; - *(uint32_t volatile *)(ram_base + offset) = value; -} - -// namespace QP ============================================================== -namespace QP { - -// QF callbacks -------------------------------------------------------------- -void QF::onStartup(void) { - // NOTE: SystemInit() has been already called from the startup code - // but SystemCoreClock needs to be updated - // - SystemCoreClockUpdate(); - - //NOTE: don't start ticking for these tests - //SysTick_Config(SystemCoreClock / BSP_TICKS_PER_SEC); - - // assign all priority bits for preemption-prio. and none to sub-prio. - // NOTE: this might have been changed by STM32Cube. - NVIC_SetPriorityGrouping(0U); - - // set priorities of ALL ISRs used in the system - NVIC_SetPriority(SysTick_IRQn, QF_AWARE_ISR_CMSIS_PRI + 0U); - NVIC_SetPriority(EXTI0_1_IRQn, QF_AWARE_ISR_CMSIS_PRI + 1U); - // NOTE: priority of UART IRQ used for QS-RX is set in qutest_port.c - // ... - - // enable IRQs... - NVIC_EnableIRQ(EXTI0_1_IRQn); -} -//............................................................................ -void QF::onCleanup(void) { -} -//............................................................................ -void QXK::onIdle(void) { -#ifdef Q_SPY - QS::rxParse(); // parse all the received bytes - QS::doOutput(); -#elif defined NDEBUG - // Put the CPU and peripherals to the low-power mode. - // you might need to customize the clock management for your application, - // see the datasheet for your particular Cortex-M3 MCU. - // - __WFI(); // Wait-For-Interrupt -#endif -} - -// QS callbacks ============================================================== -//............................................................................ -void QTimeEvt::tick1_( - uint_fast8_t const tickRate, - void const * const sender) -{ - QF_INT_DISABLE(); - // TODO pend the SysTick - *Q_UINT2PTR_CAST(uint32_t, 0xE000ED04U) = (1U << 26U); - QF_INT_ENABLE(); -} - -//---------------------------------------------------------------------------- - -} // namespace QP - -extern "C" { -//............................................................................ -#ifdef QF_ON_CONTEXT_SW -// NOTE: the context-switch callback is called with interrupts DISABLED -void QF_onContextSw(QP::QActive *prev, QP::QActive *next) { - QS_BEGIN_INCRIT(CONTEXT_SW, 0U) // no critical section! - QS_OBJ(prev); - QS_OBJ(next); - QS_END_INCRIT() -} -#endif // QF_ON_CONTEXT_SW - -} // extern "C" - -//============================================================================ -// NOTE0: -// The MPU protection against NULL-pointer dereferencing sets up a no-access -// MPU region #7 around the NULL address (0x0). The size of this region is set -// to 2^(26+1)==0x0800'0000, because that is the address of Flash in STM32. -// -// REMARK: STM32 MCUs automatically relocate the Flash memory and the Vector -// Table in it to address 0x0800'0000 at startup. However, even though the -// region 0..0x0800'0000 is un-mapped after the relocation, the read access -// is still allowed and causes no CPU exception. Therefore setting up the MPU -// to protect that region is necessary. -// diff --git a/test/qxk/test_sched/bsp_nucleo-h743zi.cpp b/test/qxk/test_sched/bsp_nucleo-h743zi.cpp deleted file mode 100644 index 9426907eb..000000000 --- a/test/qxk/test_sched/bsp_nucleo-h743zi.cpp +++ /dev/null @@ -1,307 +0,0 @@ -//============================================================================ -// Product: BSP for system-testing of QXK kernel, NUCLEO-H743ZI board -// Last updated for version 7.2.0 -// Last updated on 2022-12-25 -// -// Q u a n t u m L e a P s -// ------------------------ -// Modern Embedded Software -// -// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -// -// This program is open source software: you can redistribute it and/or -// modify it under the terms of the GNU General Public License as published -// by the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Alternatively, this program may be distributed and modified under the -// terms of Quantum Leaps commercial licenses, which expressly supersede -// the GNU General Public License and are specifically designed for -// licensees interested in retaining the proprietary status of their code. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -// Contact information: -// -// -//============================================================================ -#include "qpcpp.hpp" -#include "bsp.hpp" - -// STM32CubeH7 include files -#include "stm32h7xx_hal.h" -#include "stm32h7xx_nucleo_144.h" -// add other drivers if necessary... - -namespace { - -Q_DEFINE_THIS_FILE - -#ifdef Q_SPY - - // QSpy source IDs - static QP::QSpyId const l_SysTick_Handler = { 100U }; - static QP::QSpyId const l_test_ISR = { 101U }; - - enum AppRecords { // application-specific trace records - CONTEXT_SW = QP::QS_USER1, - TRACE_MSG - }; - -#endif - -} // unnamed namespace - -// ISRs used in this project ================================================= -extern "C" { - -//............................................................................ -void SysTick_Handler(void); // prototype -void SysTick_Handler(void) { - QXK_ISR_ENTRY(); // inform QXK about entering an ISR - - QP::QTimeEvt::TICK_X(0U, &l_SysTick_Handler); - //the_Ticker0->TRIG(&l_SysTick_Handler); - - QXK_ISR_EXIT(); // inform QXK about exiting an ISR -} -//............................................................................ -void EXTI0_IRQHandler(void); // prototype -void EXTI0_IRQHandler(void) { // for testing, NOTE03 - QXK_ISR_ENTRY(); // inform QXK about entering an ISR - - // for testing... - static QP::QEvt const t1(TEST1_SIG); - QP::QF::PUBLISH(&t1, &l_test_ISR); - - QXK_ISR_EXIT(); // inform QXK about exiting an ISR -} - -} // extern "C" - -// BSP functions ============================================================= -// MPU setup for STM32H743ZI MCU -static void STM32H743ZI_MPU_setup(void) { - // The following MPU configuration contains just a generic ROM - // region (with read-only access) and NULL-pointer protection region. - // Otherwise, the MPU will fall back on the background region (PRIVDEFENA). - // - static struct { - std::uint32_t rbar; - std::uint32_t rasr; - } const mpu_setup[] = { - - { // region #0: Flash: base=0x0000'0000, size=512M=2^(28+1) - 0x00000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 0U), // region #0 - (28U << MPU_RASR_SIZE_Pos) // 2^(18+1) region - | (0x6U << MPU_RASR_AP_Pos) // PA:ro/UA:ro - | (1U << MPU_RASR_C_Pos) // C=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - { // region #7: NULL-pointer: base=0x000'0000, size=128M=2^(26+1) - // NOTE: this region extends to 0x080'0000, which is where - // the ROM is re-mapped by STM32 - // - 0x00000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 7U), // region #7 - (26U << MPU_RASR_SIZE_Pos) // 2^(26+1)=128M region - | (0x0U << MPU_RASR_AP_Pos) // PA:na/UA:na - | (1U << MPU_RASR_XN_Pos) // XN=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - }; - - // enable the MemManage_Handler for MPU exception - SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; - - __DSB(); - MPU->CTRL = 0U; // disable the MPU */ - for (std::uint_fast8_t n = 0U; n < Q_DIM(mpu_setup); ++n) { - MPU->RBAR = mpu_setup[n].rbar; - MPU->RASR = mpu_setup[n].rasr; - } - MPU->CTRL = MPU_CTRL_ENABLE_Msk // enable the MPU */ - | MPU_CTRL_PRIVDEFENA_Msk; // enable background region */ - __ISB(); - __DSB(); -} -//............................................................................ -void BSP::init(void) { - // setup the MPU... - STM32H743ZI_MPU_setup(); - - // NOTE: SystemInit() already called from the startup code - // but SystemCoreClock needs to be updated - // - SystemCoreClockUpdate(); - - SCB_EnableICache(); // Enable I-Cache - SCB_EnableDCache(); // Enable D-Cache - - // Configure Flash prefetch and Instr. cache through ART accelerator -#if (ART_ACCLERATOR_ENABLE != 0) - __HAL_FLASH_ART_ENABLE(); -#endif // ART_ACCLERATOR_ENABLE - - // Configure the LEDs - BSP_LED_Init(LED1); - BSP_LED_Init(LED2); - BSP_LED_Init(LED3); - - // Configure the User Button in GPIO Mode - BSP_PB_Init(BUTTON_USER, BUTTON_MODE_GPIO); - - // initialize the QS software tracing... - if (!QS_INIT(nullptr)) { // initialize the QS software tracing - Q_ERROR(); - } - - // dictionaries... - QS_OBJ_DICTIONARY(&l_SysTick_Handler); - QS_OBJ_DICTIONARY(&l_test_ISR); - - QS_USR_DICTIONARY(CONTEXT_SW); - QS_USR_DICTIONARY(TRACE_MSG); -} -//............................................................................ -void BSP::terminate(int16_t result) { - Q_UNUSED_PAR(result); -} -//............................................................................ -void BSP::ledOn(void) { - BSP_LED_On(LED1); -} -//............................................................................ -void BSP::ledOff(void) { - BSP_LED_Off(LED1); -} -//............................................................................ -void BSP::trigISR(void) { - NVIC_SetPendingIRQ(EXTI0_IRQn); -} -//............................................................................ -void BSP::trace(QP::QActive const *thr, char const *msg) { - QS_BEGIN_ID(TRACE_MSG, 0U) - QS_OBJ(thr); - QS_STR(msg); - QS_END() -} -//............................................................................ -uint32_t BSP::romRead(int32_t offset, uint32_t fromEnd) { - int32_t const rom_base = (fromEnd == 0U) - ? 0x08000000 - : 0x08200000 - 4; - return *(uint32_t volatile *)(rom_base + offset); -} -//............................................................................ -void BSP::romWrite(int32_t offset, uint32_t fromEnd, uint32_t value) { - int32_t const rom_base = (fromEnd == 0U) - ? 0x08000000 - : 0x08200000 - 4; - *(uint32_t volatile *)(rom_base + offset) = value; -} - -//............................................................................ -uint32_t BSP::ramRead(int32_t offset, uint32_t fromEnd) { - int32_t const ram_base = (fromEnd == 0U) - ? 0x20000000 - : 0x20020000 - 4; - return *(uint32_t volatile *)(ram_base + offset); -} -//............................................................................ -void BSP::ramWrite(int32_t offset, uint32_t fromEnd, uint32_t value) { - int32_t const ram_base = (fromEnd == 0U) - ? 0x20000000 - : 0x20020000 - 4; - *(uint32_t volatile *)(ram_base + offset) = value; -} - -// namespace QP ============================================================== -namespace QP { - -// QF callbacks -------------------------------------------------------------- -void QF::onStartup(void) { - //NOTE: don't start ticking for these tests - //SysTick_Config(SystemCoreClock / BSP_TICKS_PER_SEC); - - // assign all priority bits for preemption-prio. and none to sub-prio. - NVIC_SetPriorityGrouping(0U); - - // set priorities of ALL ISRs used in the system - NVIC_SetPriority(USART2_IRQn, 0U); - NVIC_SetPriority(SysTick_IRQn, QF_AWARE_ISR_CMSIS_PRI + 0U); - NVIC_SetPriority(EXTI0_IRQn, QF_AWARE_ISR_CMSIS_PRI + 1U); - // ... - - // enable IRQs... - NVIC_EnableIRQ(EXTI0_IRQn); -} -//............................................................................ -void QF::onCleanup(void) { -} -//............................................................................ -void QXK::onIdle(void) { -#ifdef Q_SPY - QS::rxParse(); // parse all the received bytes - QS::doOutput(); -#elif defined NDEBUG - // Put the CPU and peripherals to the low-power mode. - // you might need to customize the clock management for your application, - // see the datasheet for your particular Cortex-M3 MCU. - // - __WFI(); // Wait-For-Interrupt -#endif -} - -// QS callbacks ============================================================== -//............................................................................ -void QTimeEvt::tick1_( - uint_fast8_t const tickRate, - void const * const sender) -{ - QF_INT_DISABLE(); - // TODO pend the SysTick - *Q_UINT2PTR_CAST(uint32_t, 0xE000ED04U) = (1U << 26U); - QF_INT_ENABLE(); -} - -//---------------------------------------------------------------------------- - -} // namespace QP - -extern "C" { -//............................................................................ -#ifdef QF_ON_CONTEXT_SW -// NOTE: the context-switch callback is called with interrupts DISABLED -void QF_onContextSw(QP::QActive *prev, QP::QActive *next) { - QS_BEGIN_INCRIT(CONTEXT_SW, 0U) // no critical section! - QS_OBJ(prev); - QS_OBJ(next); - QS_END_INCRIT() -} -#endif // QF_ON_CONTEXT_SW - -} // extern "C" - -//============================================================================ -// NOTE0: -// The MPU protection against NULL-pointer dereferencing sets up a no-access -// MPU region #7 around the NULL address (0x0). The size of this region is set -// to 2^(26+1)==0x0800'0000, because that is the address of Flash in STM32. -// -// REMARK: STM32 MCUs automatically relocate the Flash memory and the Vector -// Table in it to address 0x0800'0000 at startup. However, even though the -// region 0..0x0800'0000 is un-mapped after the relocation, the read access -// is still allowed and causes no CPU exception. Therefore setting up the MPU -// to protect that region is necessary. -// diff --git a/test/qxk/test_sched/bsp_nucleo-l053r8.cpp b/test/qxk/test_sched/bsp_nucleo-l053r8.cpp deleted file mode 100644 index 1449b32e1..000000000 --- a/test/qxk/test_sched/bsp_nucleo-l053r8.cpp +++ /dev/null @@ -1,382 +0,0 @@ -//============================================================================ -// Product: BSP for system-testing of QXK kernel, NUCLEO-L053R8 board -// Last updated for version 7.2.1 -// Last updated on 2023-01-26 -// -// Q u a n t u m L e a P s -// ------------------------ -// Modern Embedded Software -// -// Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -// -// This program is open source software: you can redistribute it and/or -// modify it under the terms of the GNU General Public License as published -// by the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Alternatively, this program may be distributed and modified under the -// terms of Quantum Leaps commercial licenses, which expressly supersede -// the GNU General Public License and are specifically designed for -// licensees interested in retaining the proprietary status of their code. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -// Contact information: -// -// -//============================================================================ -#include "qpcpp.hpp" -#include "bsp.hpp" - -#include "stm32l0xx.h" // CMSIS-compliant header file for the MCU used -// add other drivers if necessary... - -namespace { - -Q_DEFINE_THIS_FILE - -// Local-scope objects ------------------------------------------------------- -// LED pins available on the board (just one user LED LD2--Green on PA.5) -#define LED_LD2 (1U << 5) - -// Button pins available on the board (just one user Button B1 on PC.13) -#define BTN_B1 (1U << 13) - -#ifdef Q_SPY - - // QSpy source IDs - static QP::QSpyId const l_SysTick_Handler = { 100U }; - static QP::QSpyId const l_test_ISR = { 101U }; - - enum AppRecords { // application-specific trace records - CONTEXT_SW = QP::QS_USER1, - TRACE_MSG - }; - -#endif - -} // unnamed namespace - -// ISRs used in this project ================================================= -extern "C" { - -//............................................................................ -void SysTick_Handler(void); // prototype -void SysTick_Handler(void) { - QXK_ISR_ENTRY(); // inform QXK about entering an ISR - - QP::QTimeEvt::TICK_X(0U, &l_SysTick_Handler); - //the_Ticker0->TRIG(&l_SysTick_Handler); - - QXK_ISR_EXIT(); // inform QXK about exiting an ISR -} -//............................................................................ -void EXTI0_1_IRQHandler(void); // prototype -void EXTI0_1_IRQHandler(void) { - QXK_ISR_ENTRY(); // inform QXK about entering an ISR - - // for testing... - static QP::QEvt const t1(TEST1_SIG); - QP::QF::PUBLISH(&t1, &l_test_ISR); - - QXK_ISR_EXIT(); // inform QXK about exiting an ISR -} - -} // extern "C" - -// BSP functions ============================================================= - -// MPU setup for STM32L053R8 MCU -static void STM32L053R8_MPU_setup(void) { - // The following MPU configuration contains the general STM32 memory model - // as described in the ST AppNote AN4838 "Managing memory protection unit - // in STM32 MCUs", Figure 2. Cortex-M0+/M3/M4/M7 processor memory map. - // - // Please note that the actual STM32 MCUs provide much less Flash and SRAM - // than the maximums configured here. This means that actual MCUs have - // unmapped memory regions (e.g., beyond the actual SRAM). Attempts to - // access these regions causes the HardFault exception, which is the - // desired behavior. - // - static struct { - uint32_t rbar; - uint32_t rasr; - } const mpu_setup[] = { - - { // region #0: Flash: base=0x0000'0000, size=512M=2^(28+1) - 0x00000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 0U), // region #0 - (28U << MPU_RASR_SIZE_Pos) // 2^(18+1) region - | (0x6U << MPU_RASR_AP_Pos) // PA:ro/UA:ro - | (1U << MPU_RASR_C_Pos) // C=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - { // region #1: SRAM: base=0x2000'0000, size=512M=2^(28+1) - 0x20000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 1U), // region #1 - (28U << MPU_RASR_SIZE_Pos) // 2^(28+1) region - | (0x3U << MPU_RASR_AP_Pos) // PA:rw/UA:rw - | (1U << MPU_RASR_XN_Pos) // XN=1 - | (1U << MPU_RASR_S_Pos) // S=1 - | (1U << MPU_RASR_C_Pos) // C=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - // region #3: (not configured) - { MPU_RBAR_VALID_Msk | (MPU_RBAR_REGION_Msk & 2U), 0U }, - - { // region #3: Peripherals: base=0x4000'0000, size=512M=2^(28+1) - 0x40000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 3U), // region #3 - (28U << MPU_RASR_SIZE_Pos) // 2^(28+1) region - | (0x3U << MPU_RASR_AP_Pos) // PA:rw/UA:rw - | (1U << MPU_RASR_XN_Pos) // XN=1 - | (1U << MPU_RASR_S_Pos) // S=1 - | (1U << MPU_RASR_B_Pos) // B=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - { // region #4: Priv. Periph: base=0xE000'0000, size=512M=2^(28+1) - 0xE0000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 4U), // region #4 - (28U << MPU_RASR_SIZE_Pos) // 2^(28+1) region - | (0x3U << MPU_RASR_AP_Pos) // PA:rw/UA:rw - | (1U << MPU_RASR_XN_Pos) // XN=1 - | (1U << MPU_RASR_S_Pos) // S=1 - | (1U << MPU_RASR_B_Pos) // B=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - { // region #5: Ext RAM: base=0x6000'0000, size=1G=2^(29+1) - 0x60000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 5U), // region #5 - (29U << MPU_RASR_SIZE_Pos) // 2^(28+1) region - | (0x3U << MPU_RASR_AP_Pos) // PA:rw/UA:rw - | (1U << MPU_RASR_XN_Pos) // XN=1 - | (1U << MPU_RASR_S_Pos) // S=1 - | (1U << MPU_RASR_B_Pos) // B=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - { // region #6: Ext Dev: base=0xA000'0000, size=1G=2^(29+1) - 0xA0000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 6U), // region #6 - (29U << MPU_RASR_SIZE_Pos) // 2^(28+1) region - | (0x3U << MPU_RASR_AP_Pos) // PA:rw/UA:rw - | (1U << MPU_RASR_XN_Pos) // XN=1 - | (1U << MPU_RASR_S_Pos) // S=1 - | (1U << MPU_RASR_B_Pos) // B=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - { // region #7: NULL-pointer: base=0x000'0000, size=128M=2^(26+1) - // NOTE: this region extends to 0x080'0000, which is where - // the ROM is re-mapped by STM32 - - 0x00000000U // base address - | MPU_RBAR_VALID_Msk // valid region - | (MPU_RBAR_REGION_Msk & 7U), // region #7 - (26U << MPU_RASR_SIZE_Pos) // 2^(26+1)=128M region - | (0x0U << MPU_RASR_AP_Pos) // PA:na/UA:na - | (1U << MPU_RASR_XN_Pos) // XN=1 - | MPU_RASR_ENABLE_Msk // region enable - }, - - }; - - __DSB(); - MPU->CTRL = 0U; // disable the MPU - for (uint_fast8_t n = 0U; n < Q_DIM(mpu_setup); ++n) { - MPU->RBAR = mpu_setup[n].rbar; - MPU->RASR = mpu_setup[n].rasr; - } - MPU->CTRL = MPU_CTRL_PRIVDEFENA_Msk // enable background region - | MPU_CTRL_ENABLE_Msk; // enable the MPU - __ISB(); - __DSB(); -} -//............................................................................ -void BSP::init(void) { - // setup the MPU... - STM32L053R8_MPU_setup(); - - // NOTE: SystemInit() already called from the startup code - // but SystemCoreClock needs to be updated - // - SystemCoreClockUpdate(); - - // enable GPIOA clock port for the LED LD2 - RCC->IOPENR |= (1U << 0); - - // configure LED (PA.5) pin as push-pull output, no pull-up, pull-down - GPIOA->MODER &= ~((3U << 2*5)); - GPIOA->MODER |= ((1U << 2*5)); - GPIOA->OTYPER &= ~((1U << 5)); - GPIOA->OSPEEDR &= ~((3U << 2*5)); - GPIOA->OSPEEDR |= ((1U << 2*5)); - GPIOA->PUPDR &= ~((3U << 2*5)); - - // enable GPIOC clock port for the Button B1 - RCC->IOPENR |= (1U << 2); - - // configure Button (PC.13) pins as input, no pull-up, pull-down - GPIOC->MODER &= ~(3U << 2*13); - GPIOC->OSPEEDR &= ~(3U << 2*13); - GPIOC->OSPEEDR |= (1U << 2*13); - GPIOC->PUPDR &= ~(3U << 2*13); - - // initialize the QS software tracing... - if (!QS_INIT(nullptr)) { // initialize the QS software tracing - Q_ERROR(); - } - QS_OBJ_DICTIONARY(&l_SysTick_Handler); - QS_OBJ_DICTIONARY(&l_test_ISR); - - QS_USR_DICTIONARY(CONTEXT_SW); - QS_USR_DICTIONARY(TRACE_MSG); -} -//............................................................................ -void BSP::terminate(int16_t result) { - Q_UNUSED_PAR(result); -} -//............................................................................ -void BSP::ledOn(void) { - GPIOA->BSRR = (LED_LD2); // turn LED2 on -} -//............................................................................ -void BSP::ledOff(void) { - GPIOA->BSRR = (LED_LD2 << 16); // turn LED2 off -} -//............................................................................ -void BSP::trigISR(void) { - NVIC_SetPendingIRQ(EXTI0_1_IRQn); -} -//............................................................................ -void BSP::trace(QP::QActive const *thr, char const *msg) { - QS_BEGIN_ID(TRACE_MSG, 0U) - QS_OBJ(thr); - QS_STR(msg); - QS_END() -} -//............................................................................ -uint32_t BSP::romRead(int32_t offset, uint32_t fromEnd) { - int32_t const rom_base = (fromEnd == 0U) - ? 0x08000000 - : 0x08010000 - 4; - return *(uint32_t volatile *)(rom_base + offset); -} -//............................................................................ -void BSP::romWrite(int32_t offset, uint32_t fromEnd, uint32_t value) { - int32_t const rom_base = (fromEnd == 0U) - ? 0x08000000 - : 0x08010000 - 4; - *(uint32_t volatile *)(rom_base + offset) = value; -} - -//............................................................................ -uint32_t BSP::ramRead(int32_t offset, uint32_t fromEnd) { - int32_t const ram_base = (fromEnd == 0U) - ? 0x20000000 - : 0x20002000 - 4; - return *(uint32_t volatile *)(ram_base + offset); -} -//............................................................................ -void BSP::ramWrite(int32_t offset, uint32_t fromEnd, uint32_t value) { - int32_t const ram_base = (fromEnd == 0U) - ? 0x20000000 - : 0x20002000 - 4; - *(uint32_t volatile *)(ram_base + offset) = value; -} - -// namespace QP ============================================================== -namespace QP { - -// QF callbacks -------------------------------------------------------------- -void QF::onStartup(void) { - //NOTE: don't start ticking for these tests - //SysTick_Config(SystemCoreClock / BSP_TICKS_PER_SEC); - - // assign all priority bits for preemption-prio. and none to sub-prio. - NVIC_SetPriorityGrouping(0U); - - // set priorities of ALL ISRs used in the system - NVIC_SetPriority(USART2_IRQn, 0U); - NVIC_SetPriority(SysTick_IRQn, QF_AWARE_ISR_CMSIS_PRI + 0U); - NVIC_SetPriority(EXTI0_1_IRQn, QF_AWARE_ISR_CMSIS_PRI + 1U); - // ... - - // enable IRQs... - NVIC_EnableIRQ(EXTI0_1_IRQn); -} -//............................................................................ -void QF::onCleanup(void) { -} -//............................................................................ -void QXK::onIdle(void) { -#ifdef Q_SPY - QS::rxParse(); // parse all the received bytes - QS::doOutput(); -#elif defined NDEBUG - // Put the CPU and peripherals to the low-power mode. - // you might need to customize the clock management for your application, - // see the datasheet for your particular Cortex-M3 MCU. - // - __WFI(); // Wait-For-Interrupt -#endif -} - -// QS callbacks ============================================================== -//............................................................................ -void QTimeEvt::tick1_( - uint_fast8_t const tickRate, - void const * const sender) -{ - QF_INT_DISABLE(); - // TODO pend the SysTick - *Q_UINT2PTR_CAST(uint32_t, 0xE000ED04U) = (1U << 26U); - QF_INT_ENABLE(); -} - -//---------------------------------------------------------------------------- - -} // namespace QP - -extern "C" { -//............................................................................ -#ifdef QF_ON_CONTEXT_SW -// NOTE: the context-switch callback is called with interrupts DISABLED -void QF_onContextSw(QP::QActive *prev, QP::QActive *next) { - QS_BEGIN_INCRIT(CONTEXT_SW, 0U) // no critical section! - QS_OBJ(prev); - QS_OBJ(next); - QS_END_INCRIT() -} -#endif // QF_ON_CONTEXT_SW - -} // extern "C" - -//============================================================================ -// NOTE0: -// The MPU protection against NULL-pointer dereferencing sets up a no-access -// MPU region #7 around the NULL address (0x0). The size of this region is set -// to 2^(26+1)==0x0800'0000, because that is the address of Flash in STM32. -// -// REMARK: STM32 MCUs automatically relocate the Flash memory and the Vector -// Table in it to address 0x0800'0000 at startup. However, even though the -// region 0..0x0800'0000 is un-mapped after the relocation, the read access -// is still allowed and causes no CPU exception. Therefore setting up the MPU -// to protect that region is necessary. -// diff --git a/test/qxk/test_sched/efm32pg1b.mak b/test/qxk/test_sched/efm32pg1b.mak deleted file mode 100644 index 01342a131..000000000 --- a/test/qxk/test_sched/efm32pg1b.mak +++ /dev/null @@ -1,336 +0,0 @@ -############################################################################## -# Product: Makefile for SYSTEM-Level tests of QP/C++ on EMF32, GNU-ARM -# Last Updated for Version: 7.3.0 -# Date of the Last Update: 2023-09-06 -# -# Q u a n t u m L e a P s -# ------------------------ -# Modern Embedded Software -# -# Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -# -# This program is open source software: you can redistribute it and/or -# modify it under the terms of the GNU General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Alternatively, this program may be distributed and modified under the -# terms of Quantum Leaps commercial licenses, which expressly supersede -# the GNU General Public License and are specifically designed for -# licensees interested in retaining the proprietary status of their code. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Contact information: -# -# -############################################################################## -# -# examples of invoking this Makefile: -# make -f efm32pg1b.mak # make and run the tests in the current directory -# make -f efm32pg1b.mak TESTS=thr*.py # make and run the selected tests -# make -f efm32pg1b.mak HOST=localhost:7705 # connect to host:port -# make -f efm32pg1b.mak norun # only make but not run the tests -# make -f efm32pg1b.mak clean # cleanup the build -# make -f efm32pg1b.mak debug # only run tests in DEBUG mode -# -# NOTE: -# To use this Makefile on Windows, you will need the GNU make utility, which -# is included in the QTools collection for Windows, see: -# https://github.com/QuantumLeaps/qtools -# - -# location of the QP/C++ framework (if not provided in an env. variable) -ifeq ($(QPCPP),) -QPCPP := ../../.. -endif - -#----------------------------------------------------------------------------- -# project name, target name, target directory: -# -PROJECT := test_sched -TARGET := efm32 -TARGET_DIR := $(QPCPP)/3rd_party/efm32pg1b/qutest - -#----------------------------------------------------------------------------- -# project directories: -# - -# QP port used in this project -QP_PORT_DIR := $(QPCPP)/ports/arm-cm/qxk/gnu - -# make sure that QTOOLS env. variable is defined... -ifeq ("$(wildcard $(QTOOLS))","") -$(error QTOOLS not found. Please install QTools and define QTOOLS env. variable) -endif - - -# list of all source directories used by this project -VPATH := . \ - $(QPCPP)/src/qf \ - $(QPCPP)/src/qxk \ - $(QPCPP)/src/qs \ - $(QP_PORT_DIR) \ - $(TARGET_DIR) \ - $(QPCPP)/3rd_party/efm32pg1b \ - $(QPCPP)/3rd_party/efm32pg1b/gnu - -# list of all include directories needed by this project -INCLUDES = -I. \ - -I$(QPCPP)/include \ - -I$(QP_PORT_DIR) \ - -I$(TARGET_DIR) \ - -I$(QPCPP)/3rd_party/CMSIS/Include \ - -I$(QPCPP)/3rd_party/efm32pg1b - -#----------------------------------------------------------------------------- -# project files: -# - -# assembler source files -ASM_SRCS := - -# C source files -C_SRCS := \ - startup_efm32pg1b.c \ - system_efm32pg1b.c \ - em_cmu.c \ - em_emu.c \ - em_gpio.c \ - em_usart.c - -# C++ source files -CPP_SRCS := \ - test_sched.cpp \ - bsp_efm32pg1b.cpp - -OUTPUT := $(PROJECT) -LD_SCRIPT := $(TARGET_DIR)/qutest.ld - -QP_SRCS := \ - qep_hsm.cpp \ - qep_msm.cpp \ - qf_act.cpp \ - qf_actq.cpp \ - qf_defer.cpp \ - qf_dyn.cpp \ - qf_mem.cpp \ - qf_ps.cpp \ - qf_qact.cpp \ - qf_qeq.cpp \ - qf_qmact.cpp \ - qf_time.cpp \ - qxk.cpp \ - qxk_xthr.cpp \ - qxk_sema.cpp \ - qxk_mutex.cpp \ - qxk_port.cpp \ - qs.cpp \ - qs_64bit.cpp \ - qs_rx.cpp \ - qs_fp.cpp \ - qutest.cpp \ - qutest_cpp.cpp - -QP_ASMS := - -LIB_DIRS := -LIBS := - -# defines -DEFINES := -DEFM32PG1B200F256GM48=1 \ - -DQF_ON_CONTEXT_SW - -# ARM CPU, ARCH, FPU, and Float-ABI types... -# ARM_CPU: [cortex-m0 | cortex-m0plus | cortex-m1 | cortex-m3 | cortex-m4] -# ARM_FPU: [ | vfp] -# FLOAT_ABI: [ | soft | softfp | hard] -# -ARM_CPU := -mcpu=cortex-m4 -ARM_FPU := -mfpu=vfp -FLOAT_ABI := -mfloat-abi=softfp - -#----------------------------------------------------------------------------- -# GNU-ARM toolset (NOTE: You need to adjust to your machine) -# see https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads -# -ifeq ($(GNU_ARM),) -GNU_ARM := $(QTOOLS)/gnu_arm-none-eabi -endif - -# make sure that the GNU-ARM toolset exists... -ifeq ("$(wildcard $(GNU_ARM))","") -$(error GNU_ARM toolset not found. Please adjust the Makefile) -endif - -CC := $(GNU_ARM)/bin/arm-none-eabi-gcc -CPP := $(GNU_ARM)/bin/arm-none-eabi-g++ -AS := $(GNU_ARM)/bin/arm-none-eabi-as -LINK := $(GNU_ARM)/bin/arm-none-eabi-g++ -BIN := $(GNU_ARM)/bin/arm-none-eabi-objcopy - -#----------------------------------------------------------------------------- -# FLASH tool (NOTE: Requires the JLINK utility) -# NOTE: substitution of '/' to '\' is necessary to run the batch file - -FLASH := $(subst /,\,$(TARGET_DIR)/flash.bat) - -############################################################################## -# Typically you should not need to change anything below this line - -# basic utilities (included in QTools for Windows), see: -# https://www.state-machine.com/qtools - -MKDIR := mkdir -RM := rm - -#----------------------------------------------------------------------------- -# QUTest test script utilities (requires QTOOLS): -# -ifeq ("$(wildcard $(QUTEST))","") -QUTEST := python3 $(QTOOLS)/qutest/qutest.py -endif - -#----------------------------------------------------------------------------- -# build options -# - -# combine all the sources... -CPP_SRCS += $(QP_SRCS) -ASM_SRCS += $(QP_ASMS) - -BIN_DIR := build_$(TARGET) - -ASFLAGS = -g $(ARM_CPU) $(ARM_FPU) $(ASM_CPU) $(ASM_FPU) - - -# NOTE: -# Setting -DQ_UTEST=0 means that QUTest should be built WITHOUT -# the QP-stub for testing QP itself -# -CFLAGS = -c -g $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb -Wall \ - -ffunction-sections -fdata-sections \ - -O $(INCLUDES) $(DEFINES) -DQ_SPY -DQ_UTEST=0 - -CPPFLAGS = -c -g $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb -Wall \ - -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions \ - -O $(INCLUDES) $(DEFINES) -DQ_SPY -DQ_UTEST=0 - - -LINKFLAGS = -T$(LD_SCRIPT) $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb \ - -specs=nosys.specs -specs=nano.specs \ - -Wl,-Map,$(BIN_DIR)/$(OUTPUT).map,--cref,--gc-sections $(LIB_DIRS) - -ASM_OBJS := $(patsubst %.s,%.o, $(notdir $(ASM_SRCS))) -C_OBJS := $(patsubst %.c,%.o, $(notdir $(C_SRCS))) -CPP_OBJS := $(patsubst %.cpp,%.o,$(notdir $(CPP_SRCS))) - -TARGET_BIN := $(BIN_DIR)/$(OUTPUT).bin -TARGET_ELF := $(BIN_DIR)/$(OUTPUT).elf -ASM_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(ASM_OBJS)) -C_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(C_OBJS)) -C_DEPS_EXT := $(patsubst %.o, %.d, $(C_OBJS_EXT)) -CPP_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(CPP_OBJS)) -CPP_DEPS_EXT := $(patsubst %.o, %.d, $(CPP_OBJS_EXT)) - -# create $(BIN_DIR) if it does not exist -ifeq ("$(wildcard $(BIN_DIR))","") -$(shell $(MKDIR) $(BIN_DIR)) -endif - -#----------------------------------------------------------------------------- -# rules -# - -.PHONY : run norun debug flash - -ifeq ($(MAKECMDGOALS),norun) -all : $(TARGET_BIN) -norun : all -else -all : $(TARGET_BIN) run -endif - -$(TARGET_BIN) : $(TARGET_ELF) - $(BIN) -O binary $< $@ - $(FLASH) $@ - -$(TARGET_ELF) : $(ASM_OBJS_EXT) $(C_OBJS_EXT) $(CPP_OBJS_EXT) - $(CPP) $(CPPFLAGS) $(QPCPP)/src/qs/qstamp.cpp -o $(BIN_DIR)/qstamp.o - $(LINK) $(LINKFLAGS) -o $@ $^ $(BIN_DIR)/qstamp.o $(LIBS) - -flash : - $(FLASH) $(TARGET_BIN) - -run : $(TARGET_BIN) - $(QUTEST) -q$(QSPY) -l$(LOG) -o$(OPT) -- $(TESTS) - -$(BIN_DIR)/%.d : %.c - $(CC) -MM -MT $(@:.d=.o) $(CFLAGS) $< > $@ - -$(BIN_DIR)/%.d : %.cpp - $(CPP) -MM -MT $(@:.d=.o) $(CPPFLAGS) $< > $@ - -$(BIN_DIR)/%.o : %.s - $(AS) $(ASFLAGS) $< -o $@ - -$(BIN_DIR)/%.o : %.c - $(CC) $(CFLAGS) $< -o $@ - -$(BIN_DIR)/%.o : %.cpp - $(CPP) $(CPPFLAGS) $< -o $@ - -# create BIN_DIR and include dependencies only if needed -ifneq ($(MAKECMDGOALS),clean) - ifneq ($(MAKECMDGOALS),show) - ifneq ($(MAKECMDGOALS),debug) -ifeq ("$(wildcard $(BIN_DIR))","") -$(shell $(MKDIR) $(BIN_DIR)) -endif --include $(C_DEPS_EXT) $(CPP_DEPS_EXT) - endif - endif -endif - -debug : - $(QUTEST) $(TESTS) DEBUG $(HOST) - -.PHONY : clean show - -clean : - -$(RM) $(BIN_DIR)/*.o \ - $(BIN_DIR)/*.d \ - $(BIN_DIR)/*.bin \ - $(BIN_DIR)/*.elf \ - $(BIN_DIR)/*.map - -show : - @echo PROJECT = $(PROJECT) - @echo MAKECMDGOALS = $(MAKECMDGOALS) - @echo TESTS = $(TESTS) - @echo TARGET_ELF = $(TARGET_ELF) - @echo CONF = $(CONF) - @echo VPATH = $(VPATH) - @echo C_SRCS = $(C_SRCS) - @echo CPP_SRCS = $(CPP_SRCS) - @echo ASM_SRCS = $(ASM_SRCS) - @echo C_DEPS_EXT = $(C_DEPS_EXT) - @echo C_OBJS_EXT = $(C_OBJS_EXT) - @echo CPP_DEPS_EXT = $(CPP_DEPS_EXT) - @echo CPP_OBJS_EXT = $(CPP_OBJS_EXT) - @echo ASM_OBJS_EXT = $(ASM_OBJS_EXT) - @echo LIB_DIRS = $(LIB_DIRS) - @echo LIBS = $(LIBS) - @echo DEFINES = $(DEFINES) - @echo QTOOLS = $(QTOOLS) - @echo HOST = $(HOST) - @echo QUTEST = $(QUTEST) - @echo FLASH = $(FLASH) - @echo TESTS = $(TESTS) - diff --git a/test/qxk/test_sched/nucleo-c031c6.mak b/test/qxk/test_sched/nucleo-c031c6.mak deleted file mode 100644 index 0fb96900e..000000000 --- a/test/qxk/test_sched/nucleo-c031c6.mak +++ /dev/null @@ -1,339 +0,0 @@ -############################################################################## -# Product: Makefile for SYSTEM-Level tests of QP/C on NUCLEO-C031c6, GNU-ARM -# Last Updated for Version: 7.3.0 -# Date of the Last Update: 2023-09-06 -# -# Q u a n t u m L e a P s -# ------------------------ -# Modern Embedded Software -# -# Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -# -# This program is open source software: you can redistribute it and/or -# modify it under the terms of the GNU General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Alternatively, this program may be distributed and modified under the -# terms of Quantum Leaps commercial licenses, which expressly supersede -# the GNU General Public License and are specifically designed for -# licensees interested in retaining the proprietary status of their code. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Contact information: -# -# -############################################################################## -# -# examples of invoking this Makefile: -# make -f nucleo-c031c6.mak USB=g: # make, upload to USB drive, run the tests -# make -f nucleo-c031c6.mak USB=g: TESTS=philo*.py # make and run the selected tests -# make -f nucleo-c031c6.mak HOST=localhost:7705 # connect to host:port -# make -f nucleo-c031c6.mak norun # only make but not run the tests -# make -f nucleo-c031c6.mak clean # cleanup the build -# make -f nucleo-c031c6.mak debug # only run tests in DEBUG mode -# -# NOTE: -# To use this Makefile on Windows, you will need the GNU make utility, which -# is included in the QTools collection for Windows, see: -# https://github.com/QuantumLeaps/qtools -# - -# location of the QP/C++ framework (if not provided in an env. variable) -ifeq ($(QPCPP),) -QPCPP := ../../.. -endif - -#----------------------------------------------------------------------------- -# project name, target name, target directory: -# -PROJECT := test_sched -TARGET := nucleo-c031c6 -TARGET_DIR := $(QPCPP)/3rd_party/nucleo-c031c6/qutest - -#----------------------------------------------------------------------------- -# project directories: -# - -# QP port used in this project -QP_PORT_DIR := $(QPCPP)/ports/arm-cm/qxk/gnu - -# make sure that QTOOLS env. variable is defined... -ifeq ("$(wildcard $(QTOOLS))","") -$(error QTOOLS not found. Please install QTools and define QTOOLS env. variable) -endif - - -# list of all source directories used by this project -VPATH := . \ - $(QPCPP)/src/qf \ - $(QPCPP)/src/qxk \ - $(QPCPP)/src/qs \ - $(QP_PORT_DIR) \ - $(TARGET_DIR) \ - $(QPCPP)/3rd_party/nucleo-c031c6 \ - $(QPCPP)/3rd_party/nucleo-c031c6/gnu - -# list of all include directories needed by this project -INCLUDES = -I. \ - -I$(QPCPP)/include \ - -I$(QP_PORT_DIR) \ - -I$(TARGET_DIR) \ - -I$(QPCPP)/3rd_party/CMSIS/Include \ - -I$(QPCPP)/3rd_party/nucleo-c031c6 - -#----------------------------------------------------------------------------- -# project files: -# - -# assembler source files -ASM_SRCS := - -# C source files -C_SRCS := \ - system_stm32c0xx.c \ - startup_stm32c031xx.c - -# C++ source files -CPP_SRCS := \ - test_sched.cpp \ - bsp_nucleo-c031c6.cpp - -OUTPUT := $(PROJECT) -LD_SCRIPT := $(TARGET_DIR)/qutest.ld - -QP_SRCS := \ - qep_hsm.cpp \ - qep_msm.cpp \ - qf_act.cpp \ - qf_actq.cpp \ - qf_defer.cpp \ - qf_dyn.cpp \ - qf_mem.cpp \ - qf_ps.cpp \ - qf_qact.cpp \ - qf_qeq.cpp \ - qf_qmact.cpp \ - qf_time.cpp \ - qxk.cpp \ - qxk_xthr.cpp \ - qxk_sema.cpp \ - qxk_mutex.cpp \ - qxk_port.cpp \ - qs.cpp \ - qs_64bit.cpp \ - qs_rx.cpp \ - qs_fp.cpp \ - qutest.cpp \ - qutest_cpp.cpp - -QP_ASMS := - -LIB_DIRS := -LIBS := - -# defines -DEFINES := -DSTM32C031xx \ - -DQP_API_VERSION=9999 \ - -DQXK_USE_IRQ_HANDLER=Reserved1_IRQHandler \ - -DQXK_USE_IRQ_NUM=1 \ - -DQF_ON_CONTEXT_SW - -# ARM CPU, ARCH, FPU, and Float-ABI types... -# ARM_CPU: [cortex-m0 | cortex-m0plus | cortex-m1 | cortex-m3 | cortex-m4] -# ARM_FPU: [ | vfp] -# FLOAT_ABI: [ | soft | softfp | hard] -# -ARM_CPU := -mcpu=cortex-m0plus -ARM_FPU := -FLOAT_ABI := - -#----------------------------------------------------------------------------- -# GNU-ARM toolset (NOTE: You need to adjust to your machine) -# see https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads -# -ifeq ($(GNU_ARM),) -GNU_ARM := $(QTOOLS)/gnu_arm-none-eabi -endif - -# make sure that the GNU-ARM toolset exists... -ifeq ("$(wildcard $(GNU_ARM))","") -$(error GNU_ARM toolset not found. Please adjust the Makefile) -endif - -CC := $(GNU_ARM)/bin/arm-none-eabi-gcc -CPP := $(GNU_ARM)/bin/arm-none-eabi-g++ -AS := $(GNU_ARM)/bin/arm-none-eabi-as -LINK := $(GNU_ARM)/bin/arm-none-eabi-g++ -BIN := $(GNU_ARM)/bin/arm-none-eabi-objcopy - -#----------------------------------------------------------------------------- -# NOTE: The symbol USB must be provided for the NUCLEO board -# has enumerated as USB drive f: -# -ifeq ($(USB),) -$(error USB drive not provided for the NUCLEO board.) -endif - -############################################################################## -# Typically you should not need to change anything below this line - -# basic utilities (included in QTools for Windows), see: -# https://www.state-machine.com/qtools - -MKDIR := mkdir -RM := rm -CP := cp -SLEEP := sleep - -#----------------------------------------------------------------------------- -# QUTest test script utilities (requires QTOOLS): -# -ifeq ("$(wildcard $(QUTEST))","") -QUTEST := python3 $(QTOOLS)/qutest/qutest.py -endif - -#----------------------------------------------------------------------------- -# build options -# - -# combine all the sources... -CPP_SRCS += $(QP_SRCS) -ASM_SRCS += $(QP_ASMS) - -BIN_DIR := build_$(TARGET) - -ASFLAGS = -g $(ARM_CPU) $(ARM_FPU) $(ASM_CPU) $(ASM_FPU) - - -# NOTE: -# Setting -DQ_UTEST=0 means that QUTest should be built WITHOUT -# the QP-stub for testing QP itself -# -CFLAGS = -c -g $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb -Wall \ - -ffunction-sections -fdata-sections \ - -O $(INCLUDES) $(DEFINES) -DQ_SPY -DQ_UTEST=0 - -CPPFLAGS = -c -g $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb -Wall \ - -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions \ - -O $(INCLUDES) $(DEFINES) -DQ_SPY -DQ_UTEST=0 - - -LINKFLAGS = -T$(LD_SCRIPT) $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb \ - -specs=nosys.specs -specs=nano.specs \ - -Wl,-Map,$(BIN_DIR)/$(OUTPUT).map,--cref,--gc-sections $(LIB_DIRS) - -ASM_OBJS := $(patsubst %.s,%.o, $(notdir $(ASM_SRCS))) -C_OBJS := $(patsubst %.c,%.o, $(notdir $(C_SRCS))) -CPP_OBJS := $(patsubst %.cpp,%.o,$(notdir $(CPP_SRCS))) - -TARGET_BIN := $(BIN_DIR)/$(OUTPUT).bin -TARGET_ELF := $(BIN_DIR)/$(OUTPUT).elf -ASM_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(ASM_OBJS)) -C_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(C_OBJS)) -C_DEPS_EXT := $(patsubst %.o, %.d, $(C_OBJS_EXT)) -CPP_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(CPP_OBJS)) -CPP_DEPS_EXT := $(patsubst %.o, %.d, $(CPP_OBJS_EXT)) - -# create $(BIN_DIR) if it does not exist -ifeq ("$(wildcard $(BIN_DIR))","") -$(shell $(MKDIR) $(BIN_DIR)) -endif - -#----------------------------------------------------------------------------- -# rules -# - -.PHONY : run norun debug flash - -ifeq ($(MAKECMDGOALS),norun) -all : $(TARGET_BIN) -norun : all -else -all : $(TARGET_BIN) run -endif - -$(TARGET_BIN) : $(TARGET_ELF) - $(BIN) -O binary $< $@ - $(CP) $@ $(USB) - $(SLEEP) 2 - -$(TARGET_ELF) : $(ASM_OBJS_EXT) $(C_OBJS_EXT) $(CPP_OBJS_EXT) - $(CPP) $(CPPFLAGS) $(QPCPP)/src/qs/qstamp.cpp -o $(BIN_DIR)/qstamp.o - $(LINK) $(LINKFLAGS) -o $@ $^ $(BIN_DIR)/qstamp.o $(LIBS) - -flash : - $(CP) $(TARGET_BIN) $(USB) - -run : $(TARGET_BIN) - $(QUTEST) -q$(QSPY) -l$(LOG) -o$(OPT) -- $(TESTS) - -$(BIN_DIR)/%.d : %.c - $(CC) -MM -MT $(@:.d=.o) $(CFLAGS) $< > $@ - -$(BIN_DIR)/%.d : %.cpp - $(CPP) -MM -MT $(@:.d=.o) $(CPPFLAGS) $< > $@ - -$(BIN_DIR)/%.o : %.s - $(AS) $(ASFLAGS) $< -o $@ - -$(BIN_DIR)/%.o : %.c - $(CC) $(CFLAGS) $< -o $@ - -$(BIN_DIR)/%.o : %.cpp - $(CPP) $(CPPFLAGS) $< -o $@ - -# create BIN_DIR and include dependencies only if needed -ifneq ($(MAKECMDGOALS),clean) - ifneq ($(MAKECMDGOALS),show) - ifneq ($(MAKECMDGOALS),debug) -ifeq ("$(wildcard $(BIN_DIR))","") -$(shell $(MKDIR) $(BIN_DIR)) -endif --include $(C_DEPS_EXT) $(CPP_DEPS_EXT) - endif - endif -endif - -debug : - $(QUTEST) -edebug -q$(QSPY) -l$(LOG) -o$(OPT) -- $(TESTS) - -.PHONY : clean show - -clean : - -$(RM) $(BIN_DIR)/*.o \ - $(BIN_DIR)/*.d \ - $(BIN_DIR)/*.bin \ - $(BIN_DIR)/*.elf \ - $(BIN_DIR)/*.map - -show : - @echo PROJECT = $(PROJECT) - @echo MAKECMDGOALS = $(MAKECMDGOALS) - @echo TESTS = $(TESTS) - @echo TARGET_ELF = $(TARGET_ELF) - @echo CONF = $(CONF) - @echo VPATH = $(VPATH) - @echo C_SRCS = $(C_SRCS) - @echo CPP_SRCS = $(CPP_SRCS) - @echo ASM_SRCS = $(ASM_SRCS) - @echo C_DEPS_EXT = $(C_DEPS_EXT) - @echo C_OBJS_EXT = $(C_OBJS_EXT) - @echo CPP_DEPS_EXT = $(CPP_DEPS_EXT) - @echo CPP_OBJS_EXT = $(CPP_OBJS_EXT) - @echo ASM_OBJS_EXT = $(ASM_OBJS_EXT) - @echo LIB_DIRS = $(LIB_DIRS) - @echo LIBS = $(LIBS) - @echo DEFINES = $(DEFINES) - @echo QTOOLS = $(QTOOLS) - @echo HOST = $(HOST) - @echo QUTEST = $(QUTEST) - @echo TESTS = $(TESTS) - diff --git a/test/qxk/test_sched/nucleo-h743zi.mak b/test/qxk/test_sched/nucleo-h743zi.mak deleted file mode 100644 index 5f730969f..000000000 --- a/test/qxk/test_sched/nucleo-h743zi.mak +++ /dev/null @@ -1,350 +0,0 @@ -############################################################################## -# Product: Makefile for QP/C on NUCLEO-H743ZI board, QUTEST, GNU-ARM -# Last Updated for Version: 7.3.0 -# Date of the Last Update: 2023-09-06 -# -# Q u a n t u m L e a P s -# ------------------------ -# Modern Embedded Software -# -# Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -# -# This program is open source software: you can redistribute it and/or -# modify it under the terms of the GNU General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Alternatively, this program may be distributed and modified under the -# terms of Quantum Leaps commercial licenses, which expressly supersede -# the GNU General Public License and are specifically designed for -# licensees interested in retaining the proprietary status of their code. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Contact information: -# -# -############################################################################## -# -# examples of invoking this Makefile: -# make -f nucleo-h743zi.mak USB=g: # make, upload to USB drive, run the tests -# make -f nucleo-h743zi.mak USB=g: TESTS=philo*.py # make and run the selected tests -# make -f nucleo-h743zi.mak USB=g: HOST=localhost:7705 # connect to host:port -# make -f nucleo-h743zi.mak USB=g: norun # only make but not run the tests -# make -f nucleo-h743zi.mak USB=g: clean # cleanup the build -# make -f nucleo-h743zi.mak USB=g: debug # only run tests in DEBUG mode -# -# NOTE: -# To use this Makefile on Windows, you will need the GNU make utility, which -# is included in the QTools collection for Windows, see: -# https://github.com/QuantumLeaps/qtools -# - -# location of the QP/C++ framework (if not provided in an env. variable) -ifeq ($(QPCPP),) -QPCPP := ../../.. -endif - -#----------------------------------------------------------------------------- -# project name, target name, target directory: -# -PROJECT := test_sched -TARGET := nucleo-h743zi -TARGET_DIR := $(QPCPP)/3rd_party/STM32CubeH7/qutest - -#----------------------------------------------------------------------------- -# project directories: -# - -# QP port used in this project -QP_PORT_DIR := $(QPCPP)/ports/arm-cm/qxk/gnu - -# make sure that QTOOLS env. variable is defined... -ifeq ("$(wildcard $(QTOOLS))","") -$(error QTOOLS not found. Please install QTools and define QTOOLS env. variable) -endif - - -# list of all source directories used by this project -VPATH := . \ - $(QPCPP)/src/qf \ - $(QPCPP)/src/qxk \ - $(QPCPP)/src/qs \ - $(QP_PORT_DIR) \ - $(TARGET_DIR) \ - $(QPCPP)/3rd_party/STM32CubeH7/nucleo-h743zi/gnu \ - $(QPCPP)/3rd_party/STM32CubeH7/Drivers/BSP\STM32H7xx_Nucleo_144 \ - $(QPCPP)/3rd_party/STM32CubeH7/Drivers/STM32H7xx_HAL_Driver/Src \ - $(QPCPP)/3rd_party/STM32CubeH7/Drivers/CMSIS/Device/ST/STM32H7xx/Source/Templates - -# list of all include directories needed by this project -INCLUDES = -I. \ - -I$(QPCPP)/include \ - -I$(QP_PORT_DIR) \ - -I$(TARGET_DIR) \ - -I$(QPCPP)/3rd_party/CMSIS/Include \ - -I$(QPCPP)/3rd_party/STM32CubeH7/Drivers/CMSIS/Device/ST/STM32H7xx/Include \ - -I$(QPCPP)/3rd_party/STM32CubeH7/Drivers/BSP/STM32H7xx_Nucleo_144 \ - -I$(QPCPP)/3rd_party/STM32CubeH7/Drivers/STM32H7xx_HAL_Driver/Inc - -#----------------------------------------------------------------------------- -# project files: -# - -# assembler source files -ASM_SRCS := - -# C source files -C_SRCS := \ - startup_stm32h743xx.c \ - system_stm32h7xx.c \ - stm32h7xx_nucleo_144.c \ - stm32h7xx_hal.c \ - stm32h7xx_hal_cortex.c \ - stm32h7xx_hal_gpio.c \ - stm32h7xx_hal_pwr_ex.c \ - stm32h7xx_hal_rcc.c \ - stm32h7xx_hal_rcc_ex.c \ - stm32h7xx_hal_msp.c \ - stm32h7xx_hal_uart.c - -# C++ source files -CPP_SRCS := \ - test_sched.cpp \ - bsp_nucleo-h743zi.cpp - -OUTPUT := $(PROJECT) -LD_SCRIPT := $(TARGET_DIR)/qutest.ld - -QP_SRCS := \ - qep_hsm.cpp \ - qep_msm.cpp \ - qf_act.cpp \ - qf_actq.cpp \ - qf_defer.cpp \ - qf_dyn.cpp \ - qf_mem.cpp \ - qf_ps.cpp \ - qf_qact.cpp \ - qf_qeq.cpp \ - qf_qmact.cpp \ - qf_time.cpp \ - qxk.cpp \ - qxk_xthr.cpp \ - qxk_sema.cpp \ - qxk_mutex.cpp \ - qxk_port.cpp \ - qs.cpp \ - qs_64bit.cpp \ - qs_rx.cpp \ - qs_fp.cpp \ - qutest.cpp \ - qutest_cpp.cpp - -QP_ASMS := - -LIB_DIRS := -LIBS := - -# defines -DEFINES := -DQP_API_VERSION=9999 \ - -DSTM32H743xx -DUSE_HAL_DRIVER -DUSE_STM32H7XX_NUCLEO_144 \ - -DQF_ON_CONTEXT_SW - -# ARM CPU, ARCH, FPU, and Float-ABI types... -# ARM_CPU: [cortex-m0 | cortex-m0plus | cortex-m1 | cortex-m3 | cortex-m4] -# ARM_FPU: [ | vfp] -# FLOAT_ABI: [ | soft | softfp | hard] -# -ARM_CPU := -mcpu=cortex-m7 -ARM_FPU := -mfpu=fpv5-d16 -FLOAT_ABI := -mfloat-abi=softfp - -#----------------------------------------------------------------------------- -# GNU-ARM toolset (NOTE: You need to adjust to your machine) -# see https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads -# -ifeq ($(GNU_ARM),) -GNU_ARM := $(QTOOLS)/gnu_arm-none-eabi -endif - -# make sure that the GNU-ARM toolset exists... -ifeq ("$(wildcard $(GNU_ARM))","") -$(error GNU_ARM toolset not found. Please adjust the Makefile) -endif - -CC := $(GNU_ARM)/bin/arm-none-eabi-gcc -CPP := $(GNU_ARM)/bin/arm-none-eabi-g++ -AS := $(GNU_ARM)/bin/arm-none-eabi-as -LINK := $(GNU_ARM)/bin/arm-none-eabi-g++ -BIN := $(GNU_ARM)/bin/arm-none-eabi-objcopy - -#----------------------------------------------------------------------------- -# NOTE: The symbol USB must be provided for the NUCLEO board -# has enumerated as USB drive f: -# -ifeq ($(USB),) -$(error USB drive not provided for the NUCLEO board.) -endif - -############################################################################## -# Typically you should not need to change anything below this line - -# basic utilities (included in QTools for Windows), see: -# https://www.state-machine.com/qtools - -MKDIR := mkdir -RM := rm -CP := cp -SLEEP := sleep - -#----------------------------------------------------------------------------- -# QUTest test script utilities (requires QTOOLS): -# -ifeq ("$(wildcard $(QUTEST))","") -QUTEST := python3 $(QTOOLS)/qutest/qutest.py -endif - -#----------------------------------------------------------------------------- -# build options -# - -# combine all the sources... -CPP_SRCS += $(QP_SRCS) -ASM_SRCS += $(QP_ASMS) - -BIN_DIR := build_$(TARGET) - -ASFLAGS = -g $(ARM_CPU) $(ARM_FPU) $(ASM_CPU) $(ASM_FPU) - - -# NOTE: -# Setting -DQ_UTEST=0 means that QUTest should be built WITHOUT -# the QP-stub for testing QP itself -# -CFLAGS = -c -g $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb -Wall \ - -ffunction-sections -fdata-sections \ - -O $(INCLUDES) $(DEFINES) -DQ_SPY -DQ_UTEST=0 - -CPPFLAGS = -c -g $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb -Wall \ - -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions \ - -O $(INCLUDES) $(DEFINES) -DQ_SPY -DQ_UTEST=0 - - -LINKFLAGS = -T$(LD_SCRIPT) $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb \ - -specs=nosys.specs -specs=nano.specs \ - -Wl,-Map,$(BIN_DIR)/$(OUTPUT).map,--cref,--gc-sections $(LIB_DIRS) - -ASM_OBJS := $(patsubst %.s,%.o, $(notdir $(ASM_SRCS))) -C_OBJS := $(patsubst %.c,%.o, $(notdir $(C_SRCS))) -CPP_OBJS := $(patsubst %.cpp,%.o,$(notdir $(CPP_SRCS))) - -TARGET_BIN := $(BIN_DIR)/$(OUTPUT).bin -TARGET_ELF := $(BIN_DIR)/$(OUTPUT).elf -ASM_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(ASM_OBJS)) -C_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(C_OBJS)) -C_DEPS_EXT := $(patsubst %.o, %.d, $(C_OBJS_EXT)) -CPP_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(CPP_OBJS)) -CPP_DEPS_EXT := $(patsubst %.o, %.d, $(CPP_OBJS_EXT)) - -# create $(BIN_DIR) if it does not exist -ifeq ("$(wildcard $(BIN_DIR))","") -$(shell $(MKDIR) $(BIN_DIR)) -endif - -#----------------------------------------------------------------------------- -# rules -# - -.PHONY : run norun debug flash - -ifeq ($(MAKECMDGOALS),norun) -all : $(TARGET_BIN) -norun : all -else -all : $(TARGET_BIN) run -endif - -$(TARGET_BIN) : $(TARGET_ELF) - $(BIN) -O binary $< $@ - $(CP) $@ $(USB) - $(SLEEP) 2 - -$(TARGET_ELF) : $(ASM_OBJS_EXT) $(C_OBJS_EXT) $(CPP_OBJS_EXT) - $(CPP) $(CPPFLAGS) $(QPCPP)/src/qs/qstamp.cpp -o $(BIN_DIR)/qstamp.o - $(LINK) $(LINKFLAGS) -o $@ $^ $(BIN_DIR)/qstamp.o $(LIBS) - -flash : - $(CP) $(TARGET_BIN) $(USB) - -run : $(TARGET_BIN) - $(QUTEST) -q$(QSPY) -l$(LOG) -o$(OPT) -- $(TESTS) - -$(BIN_DIR)/%.d : %.c - $(CC) -MM -MT $(@:.d=.o) $(CFLAGS) $< > $@ - -$(BIN_DIR)/%.d : %.cpp - $(CPP) -MM -MT $(@:.d=.o) $(CPPFLAGS) $< > $@ - -$(BIN_DIR)/%.o : %.s - $(AS) $(ASFLAGS) $< -o $@ - -$(BIN_DIR)/%.o : %.c - $(CC) $(CFLAGS) $< -o $@ - -$(BIN_DIR)/%.o : %.cpp - $(CPP) $(CPPFLAGS) $< -o $@ - -# create BIN_DIR and include dependencies only if needed -ifneq ($(MAKECMDGOALS),clean) - ifneq ($(MAKECMDGOALS),show) - ifneq ($(MAKECMDGOALS),debug) -ifeq ("$(wildcard $(BIN_DIR))","") -$(shell $(MKDIR) $(BIN_DIR)) -endif --include $(C_DEPS_EXT) $(CPP_DEPS_EXT) - endif - endif -endif - -debug : - $(QUTEST) $(TESTS) DEBUG $(HOST) - -.PHONY : clean show - -clean : - -$(RM) $(BIN_DIR)/*.o \ - $(BIN_DIR)/*.d \ - $(BIN_DIR)/*.bin \ - $(BIN_DIR)/*.elf \ - $(BIN_DIR)/*.map - -show : - @echo PROJECT = $(PROJECT) - @echo MAKECMDGOALS = $(MAKECMDGOALS) - @echo TESTS = $(TESTS) - @echo TARGET_ELF = $(TARGET_ELF) - @echo CONF = $(CONF) - @echo VPATH = $(VPATH) - @echo C_SRCS = $(C_SRCS) - @echo CPP_SRCS = $(CPP_SRCS) - @echo ASM_SRCS = $(ASM_SRCS) - @echo C_DEPS_EXT = $(C_DEPS_EXT) - @echo C_OBJS_EXT = $(C_OBJS_EXT) - @echo CPP_DEPS_EXT = $(CPP_DEPS_EXT) - @echo CPP_OBJS_EXT = $(CPP_OBJS_EXT) - @echo ASM_OBJS_EXT = $(ASM_OBJS_EXT) - @echo LIB_DIRS = $(LIB_DIRS) - @echo LIBS = $(LIBS) - @echo DEFINES = $(DEFINES) - @echo QTOOLS = $(QTOOLS) - @echo HOST = $(HOST) - @echo QUTEST = $(QUTEST) - @echo TESTS = $(TESTS) - diff --git a/test/qxk/test_sched/nucleo-l053r8.mak b/test/qxk/test_sched/nucleo-l053r8.mak deleted file mode 100644 index 936a059e5..000000000 --- a/test/qxk/test_sched/nucleo-l053r8.mak +++ /dev/null @@ -1,336 +0,0 @@ -############################################################################## -# Product: Makefile for SYSTEM-Level tests of QP/C on NUCLEO-L053R8, GNU-ARM -# Last Updated for Version: 7.3.1 -# Date of the Last Update: 2023-11-13 -# -# Q u a n t u m L e a P s -# ------------------------ -# Modern Embedded Software -# -# Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved. -# -# This program is open source software: you can redistribute it and/or -# modify it under the terms of the GNU General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Alternatively, this program may be distributed and modified under the -# terms of Quantum Leaps commercial licenses, which expressly supersede -# the GNU General Public License and are specifically designed for -# licensees interested in retaining the proprietary status of their code. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Contact information: -# -# -############################################################################## -# -# examples of invoking this Makefile: -# make -f nucleo-l053r8.mak USB=g: # make, upload to USB drive, run the tests -# make -f nucleo-l053r8.mak USB=g: TESTS=philo*.py # make and run the selected tests -# make -f nucleo-l053r8.mak HOST=localhost:7705 # connect to host:port -# make -f nucleo-l053r8.mak norun # only make but not run the tests -# make -f nucleo-l053r8.mak clean # cleanup the build -# make -f nucleo-l053r8.mak debug # only run tests in DEBUG mode -# -# NOTE: -# To use this Makefile on Windows, you will need the GNU make utility, which -# is included in the QTools collection for Windows, see: -# https://github.com/QuantumLeaps/qtools -# - -# location of the QP/C++ framework (if not provided in an env. variable) -ifeq ($(QPCPP),) -QPCPP := ../../.. -endif - -#----------------------------------------------------------------------------- -# project name, target name, target directory: -# -PROJECT := test_sched -TARGET := nucleo-l053r8 -TARGET_DIR := $(QPCPP)/3rd_party/nucleo-l053r8/qutest - -#----------------------------------------------------------------------------- -# project directories: -# - -# QP port used in this project -QP_PORT_DIR := $(QPCPP)/ports/arm-cm/qxk/gnu - -# make sure that QTOOLS env. variable is defined... -ifeq ("$(wildcard $(QTOOLS))","") -$(error QTOOLS not found. Please install QTools and define QTOOLS env. variable) -endif - - -# list of all source directories used by this project -VPATH := . \ - $(QPCPP)/src/qf \ - $(QPCPP)/src/qxk \ - $(QPCPP)/src/qs \ - $(QP_PORT_DIR) \ - $(TARGET_DIR) \ - $(QPCPP)/3rd_party/nucleo-l053r8 \ - $(QPCPP)/3rd_party/nucleo-l053r8/gnu - -# list of all include directories needed by this project -INCLUDES = -I. \ - -I$(QPCPP)/include \ - -I$(QP_PORT_DIR) \ - -I$(TARGET_DIR) \ - -I$(QPCPP)/3rd_party/CMSIS/Include \ - -I$(QPCPP)/3rd_party/nucleo-l053r8 - -#----------------------------------------------------------------------------- -# project files: -# - -# assembler source files -ASM_SRCS := - -# C source files -C_SRCS := \ - system_stm32l0xx.c \ - startup_stm32l053xx.c - -# C++ source files -CPP_SRCS := \ - test_sched.cpp \ - bsp_nucleo-l053r8.cpp - -OUTPUT := $(PROJECT) -LD_SCRIPT := $(TARGET_DIR)/qutest.ld - -QP_SRCS := \ - qep_hsm.cpp \ - qep_msm.cpp \ - qf_act.cpp \ - qf_actq.cpp \ - qf_defer.cpp \ - qf_dyn.cpp \ - qf_mem.cpp \ - qf_ps.cpp \ - qf_qact.cpp \ - qf_qeq.cpp \ - qf_qmact.cpp \ - qf_time.cpp \ - qxk.cpp \ - qxk_xthr.cpp \ - qxk_sema.cpp \ - qxk_mutex.cpp \ - qxk_port.cpp \ - qs.cpp \ - qs_64bit.cpp \ - qs_rx.cpp \ - qs_fp.cpp \ - qutest.cpp \ - qutest_cpp.cpp - -QP_ASMS := - -LIB_DIRS := -LIBS := - -# defines -DEFINES := -DSTM32L053xx \ - -DQF_ON_CONTEXT_SW - -# ARM CPU, ARCH, FPU, and Float-ABI types... -# ARM_CPU: [cortex-m0 | cortex-m0plus | cortex-m1 | cortex-m3 | cortex-m4] -# ARM_FPU: [ | vfp] -# FLOAT_ABI: [ | soft | softfp | hard] -# -ARM_CPU := -mcpu=cortex-m0plus -ARM_FPU := -FLOAT_ABI := - -#----------------------------------------------------------------------------- -# GNU-ARM toolset (NOTE: You need to adjust to your machine) -# see https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads -# -ifeq ($(GNU_ARM),) -GNU_ARM := $(QTOOLS)/gnu_arm-none-eabi -endif - -# make sure that the GNU-ARM toolset exists... -ifeq ("$(wildcard $(GNU_ARM))","") -$(error GNU_ARM toolset not found. Please adjust the Makefile) -endif - -CC := $(GNU_ARM)/bin/arm-none-eabi-gcc -CPP := $(GNU_ARM)/bin/arm-none-eabi-g++ -AS := $(GNU_ARM)/bin/arm-none-eabi-as -LINK := $(GNU_ARM)/bin/arm-none-eabi-g++ -BIN := $(GNU_ARM)/bin/arm-none-eabi-objcopy - -#----------------------------------------------------------------------------- -# NOTE: The symbol USB must be provided for the NUCLEO board -# has enumerated as USB drive f: -# -ifeq ($(USB),) -$(error USB drive not provided for the NUCLEO board.) -endif - -############################################################################## -# Typically you should not need to change anything below this line - -# basic utilities (included in QTools for Windows), see: -# https://www.state-machine.com/qtools - -MKDIR := mkdir -RM := rm -CP := cp -SLEEP := sleep - -#----------------------------------------------------------------------------- -# QUTest test script utilities (requires QTOOLS): -# -ifeq ("$(wildcard $(QUTEST))","") -QUTEST := python3 $(QTOOLS)/qutest/qutest.py -endif - -#----------------------------------------------------------------------------- -# build options -# - -# combine all the sources... -CPP_SRCS += $(QP_SRCS) -ASM_SRCS += $(QP_ASMS) - -BIN_DIR := build_$(TARGET) - -ASFLAGS = -g $(ARM_CPU) $(ARM_FPU) $(ASM_CPU) $(ASM_FPU) - - -# NOTE: -# Setting -DQ_UTEST=0 means that QUTest should be built WITHOUT -# the QP-stub for testing QP itself -# -CFLAGS = -c -g $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb -Wall \ - -ffunction-sections -fdata-sections \ - -O $(INCLUDES) $(DEFINES) -DQ_SPY -DQ_UTEST=0 - -CPPFLAGS = -c -g $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb -Wall \ - -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions \ - -O $(INCLUDES) $(DEFINES) -DQ_SPY -DQ_UTEST=0 - - -LINKFLAGS = -T$(LD_SCRIPT) $(ARM_CPU) $(ARM_FPU) $(FLOAT_ABI) -mthumb \ - -specs=nosys.specs -specs=nano.specs \ - -Wl,-Map,$(BIN_DIR)/$(OUTPUT).map,--cref,--gc-sections $(LIB_DIRS) - -ASM_OBJS := $(patsubst %.s,%.o, $(notdir $(ASM_SRCS))) -C_OBJS := $(patsubst %.c,%.o, $(notdir $(C_SRCS))) -CPP_OBJS := $(patsubst %.cpp,%.o,$(notdir $(CPP_SRCS))) - -TARGET_BIN := $(BIN_DIR)/$(OUTPUT).bin -TARGET_ELF := $(BIN_DIR)/$(OUTPUT).elf -ASM_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(ASM_OBJS)) -C_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(C_OBJS)) -C_DEPS_EXT := $(patsubst %.o, %.d, $(C_OBJS_EXT)) -CPP_OBJS_EXT := $(addprefix $(BIN_DIR)/, $(CPP_OBJS)) -CPP_DEPS_EXT := $(patsubst %.o, %.d, $(CPP_OBJS_EXT)) - -# create $(BIN_DIR) if it does not exist -ifeq ("$(wildcard $(BIN_DIR))","") -$(shell $(MKDIR) $(BIN_DIR)) -endif - -#----------------------------------------------------------------------------- -# rules -# - -.PHONY : run norun debug flash - -ifeq ($(MAKECMDGOALS),norun) -all : $(TARGET_BIN) -norun : all -else -all : $(TARGET_BIN) run -endif - -$(TARGET_BIN) : $(TARGET_ELF) - $(BIN) -O binary $< $@ - $(CP) $@ $(USB) - $(SLEEP) 2 - -$(TARGET_ELF) : $(ASM_OBJS_EXT) $(C_OBJS_EXT) $(CPP_OBJS_EXT) - $(CPP) $(CPPFLAGS) $(QPCPP)/src/qs/qstamp.cpp -o $(BIN_DIR)/qstamp.o - $(LINK) $(LINKFLAGS) -o $@ $^ $(BIN_DIR)/qstamp.o $(LIBS) - -flash : - $(CP) $(TARGET_BIN) $(USB) - -run : $(TARGET_BIN) - $(QUTEST) -q$(QSPY) -l$(LOG) -o$(OPT) -- $(TESTS) - -$(BIN_DIR)/%.d : %.c - $(CC) -MM -MT $(@:.d=.o) $(CFLAGS) $< > $@ - -$(BIN_DIR)/%.d : %.cpp - $(CPP) -MM -MT $(@:.d=.o) $(CPPFLAGS) $< > $@ - -$(BIN_DIR)/%.o : %.s - $(AS) $(ASFLAGS) $< -o $@ - -$(BIN_DIR)/%.o : %.c - $(CC) $(CFLAGS) $< -o $@ - -$(BIN_DIR)/%.o : %.cpp - $(CPP) $(CPPFLAGS) $< -o $@ - -# create BIN_DIR and include dependencies only if needed -ifneq ($(MAKECMDGOALS),clean) - ifneq ($(MAKECMDGOALS),show) - ifneq ($(MAKECMDGOALS),debug) -ifeq ("$(wildcard $(BIN_DIR))","") -$(shell $(MKDIR) $(BIN_DIR)) -endif --include $(C_DEPS_EXT) $(CPP_DEPS_EXT) - endif - endif -endif - -debug : - $(QUTEST) $(TESTS) DEBUG $(HOST) - -.PHONY : clean show - -clean : - -$(RM) $(BIN_DIR)/*.o \ - $(BIN_DIR)/*.d \ - $(BIN_DIR)/*.bin \ - $(BIN_DIR)/*.elf \ - $(BIN_DIR)/*.map - -show : - @echo PROJECT = $(PROJECT) - @echo MAKECMDGOALS = $(MAKECMDGOALS) - @echo TESTS = $(TESTS) - @echo TARGET_ELF = $(TARGET_ELF) - @echo CONF = $(CONF) - @echo VPATH = $(VPATH) - @echo C_SRCS = $(C_SRCS) - @echo CPP_SRCS = $(CPP_SRCS) - @echo ASM_SRCS = $(ASM_SRCS) - @echo C_DEPS_EXT = $(C_DEPS_EXT) - @echo C_OBJS_EXT = $(C_OBJS_EXT) - @echo CPP_DEPS_EXT = $(CPP_DEPS_EXT) - @echo CPP_OBJS_EXT = $(CPP_OBJS_EXT) - @echo ASM_OBJS_EXT = $(ASM_OBJS_EXT) - @echo LIB_DIRS = $(LIB_DIRS) - @echo LIBS = $(LIBS) - @echo DEFINES = $(DEFINES) - @echo QTOOLS = $(QTOOLS) - @echo HOST = $(HOST) - @echo QUTEST = $(QUTEST) - @echo TESTS = $(TESTS) - diff --git a/test/qxk/test_sched/test_mpu.py b/test/qxk/test_sched/test_mpu.py deleted file mode 100644 index c1b8908d6..000000000 --- a/test/qxk/test_sched/test_mpu.py +++ /dev/null @@ -1,99 +0,0 @@ -# test-script for QUTest unit testing harness -# see https://www.state-machine.com/qtools/qutest.html/qutest.html - -note(''' -@uid{TQP701} -This test group verifies the memory access protection, -specifically the protection of various memory regions. -All tests run during the QS_TEST_PAUSE() in -the test_sched.c fixture. -''') - -# preamble -def on_reset(): - expect_pause() - # don't call continue_test() - -def on_setup(): - glb_filter(GRP_SC, GRP_UA) - -MEM_START = 0 -MEM_END = 1 - -# NULL-pointer dereferencing... -test(''' -NULL-read -> ASSERT -''') -command("MEM_READ", 0x0, 0x80) # value = *(uint32_t volatile *)(param1 + param2); -expect("@timestamp =ASSERT= Mod=*") - -test("NULL-write -> ASSERT") -command("MEM_WRITE", 0x0, 0xA0, 123) # *(uint32_t volatile *)(param1 + param2) = param3; -expect("@timestamp =ASSERT= Mod=*") - -# ROM_READ... -test("Below-Start Flash-read -> ASSERT") -command("ROM_READ", (-4 & 0xFFFFFFFF), MEM_START) # value = BSP_romRead(param1, param2); -expect("@timestamp =ASSERT= Mod=*") - -test("Start-of Flash-read") -command("ROM_READ", 0x0, MEM_START) # value = BSP_romRead(param1, param2); -expect("@timestamp USER+000 ROM_READ *") -expect("@timestamp Trg-Done QS_RX_COMMAND") - -test("Middle-of Flash-read", NORESET) -command("ROM_READ", 0x400, MEM_START) # value = BSP_romRead(param1, param2); -expect("@timestamp USER+000 ROM_READ *") -expect("@timestamp Trg-Done QS_RX_COMMAND") - -test("End-of Flash-read", NORESET) -command("ROM_READ", 0x0, MEM_END) # value = BSP_romRead(param1, param2); -expect("@timestamp USER+000 ROM_READ *") -expect("@timestamp Trg-Done QS_RX_COMMAND") - -skip(1) -test("After-End Flash-read-> ASSERT", NORESET) -command("ROM_READ", 0x4, MEM_END) # value = BSP_romRead(param1, param2); -expect("@timestamp =ASSERT= Mod=*") - -# ROM_WRITE... -test("Middle-of Flash-write -> ASSERT") -command("ROM_WRITE", 0x400, MEM_START, 123) # BSP_romWrite(param1, param2, param3); -expect("@timestamp =ASSERT= Mod=*") - -# RAM_READ... -test("Below-Start SRAM-read -> ASSERT") -command("RAM_READ", (-0x4 & 0xFFFFFFFF), MEM_START) # value = BSP_ramRead(param1, param2); -expect("@timestamp =ASSERT= Mod=*") - -test("Start-of SRAM-read") -command("RAM_READ", 0x0, MEM_START) # value = BSP_ramRead(param1, param2); -expect("@timestamp USER+000 RAM_READ *") -expect("@timestamp Trg-Done QS_RX_COMMAND") - -test("Middle-of SRAM-read", NORESET) -command("RAM_READ", 0x300, MEM_START) # value = BSP_ramRead(param1, param2); -expect("@timestamp USER+000 RAM_READ *") -expect("@timestamp Trg-Done QS_RX_COMMAND") - -test("End-of SRAM-read", NORESET) -command("RAM_READ", 0x0, MEM_END) # value = BSP_ramRead(param1, param2); -expect("@timestamp USER+000 RAM_READ *") -expect("@timestamp Trg-Done QS_RX_COMMAND") - -# RAM_WRITE... -test("Below-Start SRAM-write -> ASSERT", NORESET) -command("RAM_WRITE", (-0x4 & 0xFFFFFFFF), MEM_START, 123) # BSP_ramWrite(param1, param2, param3); -expect("@timestamp =ASSERT= Mod=*") - -# wrtiting to RAM does not need to be tested because the fact -# that the test fixture runs at all means that RAM works. -skip(1) -test("Middle-of SRAM-write") -command("RAM_WRITE", 0x300, MEM_START, 123) # BSP_ramWrite(param1, param2, param3); -expect("@timestamp USER+000 RAM_WRITE *") -expect("@timestamp Trg-Done QS_RX_COMMAND") - -test("After-End SRAM-write -> ASSERT") -command("RAM_WRITE", 0x4, MEM_END, 123) # BSP_ramWrite(param1, param2, param3); -expect("@timestamp =ASSERT= Mod=*") diff --git a/test/qxk/test_sched/test_sched.cpp b/test/qxk/test_sched/test_sched.cpp deleted file mode 100644 index b62eb5ac6..000000000 --- a/test/qxk/test_sched/test_sched.cpp +++ /dev/null @@ -1,317 +0,0 @@ -//============================================================================ -// Product: System test fixture for QXK on the EFM32 target -// Last updated for version 7.4.0 -// Last updated on 2024-06-21 -// -// Q u a n t u m L e a P s -// ------------------------ -// Modern Embedded Software -// -// Copyright (C) 2005 Quantum Leaps. All rights reserved. -// -// This program is open source software: you can redistribute it and/or -// modify it under the terms of the GNU General Public License as published -// by the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Alternatively, this program may be distributed and modified under the -// terms of Quantum Leaps commercial licenses, which expressly supersede -// the GNU General Public License and are specifically designed for -// licensees interested in retaining the proprietary status of their code. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -// Contact information: -// -// -//============================================================================ -#include "qpcpp.hpp" -#include "bsp.hpp" - -namespace { - -Q_DEFINE_THIS_FILE - -//============================================================================ -// AO ObjB -enum { NUM_B = 3 }; - -//............................................................................ -// AO ObjB -class ObjB : public QP::QActive { -public: - static ObjB inst[NUM_B]; - -public: - ObjB() : QActive(&initial) {} - -protected: - Q_STATE_DECL(initial); - Q_STATE_DECL(active); -}; // class ObjB - -Q_STATE_DEF(ObjB, initial) { - static bool registered = false; // starts off with 0, per C-standard - if (!registered) { - registered = true; - QS_FUN_DICTIONARY(&ObjB::initial); - QS_FUN_DICTIONARY(&ObjB::active); - } - subscribe(TEST1_SIG); - subscribe(TEST2_SIG); - return tran(&active); -} - -Q_STATE_DEF(ObjB, active) { - QP::QState status_; - switch (e->sig) { - case TEST0_SIG: { - BSP::trace(this, "TEST0 1of2"); - BSP::trigISR(); - BSP::trace(this, "TEST0 2of2"); - status_ = Q_RET_HANDLED; - break; - } - case TEST1_SIG: { - BSP::trace(this, "TEST1 1of1"); - status_ = Q_RET_HANDLED; - break; - } - case TEST2_SIG: { - BSP::trace(this, "TEST2 1of1"); - status_ = Q_RET_HANDLED; - break; - } - default: { - status_ = super(&top); - break; - } - } - return status_; -} -//.......................................................................... -ObjB ObjB::inst[NUM_B]; - -//============================================================================ -enum { NUM_X = 3 }; - -enum UserCommands { - MEM_READ, MEM_WRITE, - ROM_READ, ROM_WRITE, - RAM_READ, RAM_WRITE, -}; - -static void ThrX_run(QP::QXThread * const me) { - me->subscribe(TEST1_SIG); - me->subscribe(TEST2_SIG); - - for (;;) { - QP::QEvt const *e = me->queueGet(QP::QXTHREAD_NO_TIMEOUT); - switch (e->sig) { - case TEST0_SIG: { - BSP::trace(me, "TEST0 1of2"); - BSP::trigISR(); - BSP::trace(me, "TEST0 2of2"); - break; - } - case TEST1_SIG: { - static QP::QEvt const t2(TEST2_SIG); - BSP::trace(me, "TEST1 1of2"); - QP::QActive::PUBLISH(&t2, me); - BSP::trace(me, "TEST1 2of2"); - break; - } - case TEST2_SIG: { - BSP::trace(me, "TEST2 1of1"); - break; - } - default: { - break; - } - } - } -} - -class ThrX : public QP::QXThread { -public: - static ThrX inst[NUM_X]; - -public: - ThrX() : QXThread(&ThrX_run) {} -}; - -ThrX ThrX::inst[NUM_X]; - -} // unnamed namespace - -//============================================================================ -int main() { - - QP::QF::init(); // initialize the framework and the underlying QXK kernel - BSP::init(); // initialize the Board Support Package - - // initialize publish-subscribe... - static QP::QSubscrList subscrSto[MAX_PUB_SIG]; - QP::QActive::psInit(subscrSto, Q_DIM(subscrSto)); - - // initialize event pools... - static QF_MPOOL_EL(QP::QEvt) smlPoolSto[10]; // small pool - QP::QF::poolInit(smlPoolSto, sizeof(smlPoolSto), sizeof(smlPoolSto[0])); - - // dictionaries - QS_SIG_DICTIONARY(TEST0_SIG, nullptr); - QS_SIG_DICTIONARY(TEST1_SIG, nullptr); - QS_SIG_DICTIONARY(TEST2_SIG, nullptr); - QS_SIG_DICTIONARY(TEST3_SIG, nullptr); - - QS_ENUM_DICTIONARY(MEM_READ, QS_CMD); - QS_ENUM_DICTIONARY(MEM_WRITE, QS_CMD); - QS_ENUM_DICTIONARY(ROM_READ, QS_CMD); - QS_ENUM_DICTIONARY(ROM_WRITE, QS_CMD); - QS_ENUM_DICTIONARY(RAM_READ, QS_CMD); - QS_ENUM_DICTIONARY(RAM_WRITE, QS_CMD); - - // priority specifications for ObjBs... - static QP::QPrioSpec pspecB[NUM_B]; - QS_OBJ_DICTIONARY(pspecB); - - // priority specifications for ThrXs... - static QP::QPrioSpec pspecX[NUM_X]; - QS_OBJ_DICTIONARY(pspecX); - - for (std::uint8_t n = 0U; n < NUM_B; ++n) { - QS_OBJ_ARR_DICTIONARY(&ObjB::inst[n], n); - } - for (std::uint8_t n = 0U; n < NUM_X; ++n) { - QS_OBJ_ARR_DICTIONARY(&ThrX::inst[n], n); - } - - // pause execution of the test and wait for the test script to continue - // NOTE: - // this pause gives the test-script a chance to poke pspecB and pspecX - // variables to start the threads with the desired prio-specifications. - QS_TEST_PAUSE(); - - static QP::QEvt const *aoB_queueSto[NUM_B][10]; - for (std::uint8_t n = 0U; n < NUM_B; ++n) { - if (pspecB[n] != 0U) { - ObjB::inst[n].start(pspecB[n], // QF-prio/p-thre. - aoB_queueSto[n], // event queue storage - Q_DIM(aoB_queueSto[n]), // event length [events] - nullptr, // no stack storage - 0U); // zero stack size [bytes] - } - } - - static QP::QEvt const *thrX_queueSto[NUM_X][5]; - static std::uint64_t thrXStackSto[NUM_X][32]; - for (std::uint8_t n = 0U; n < NUM_X; ++n) { - if (pspecX[n] != 0U) { - ThrX::inst[n].start(pspecX[n], // QF-prio/p-thre. - thrX_queueSto[n], // event queue storage - Q_DIM(thrX_queueSto[n]), // event length [events] - thrXStackSto[n], // stack storage - sizeof(thrXStackSto[n]));// stack size [bytes] - } - } - - return QP::QF::run(); // run the QF application -} - -//========================================================================== -namespace QP { - -void QS::onTestSetup(void) { -} -//............................................................................ -void QS::onTestTeardown(void) { -} -//............................................................................ -//! callback function to execute user commands -void QS::onCommand(uint8_t cmdId, - uint32_t param1, uint32_t param2, uint32_t param3) -{ - uint32_t volatile value; - - switch (cmdId) { - case MEM_READ: { // read MEM (can trip the MPU) - value = *(uint32_t volatile *)(param1 + param2); - QS_BEGIN_ID(QS_USER, 0U) - QS_ENUM(QS_CMD, cmdId); - QS_U32(0, value); - QS_END() - break; - } - case MEM_WRITE: { // write MEM (can trip the MPU) - *(uint32_t volatile *)(param1 + param2) = param3; - QS_BEGIN_ID(QS_USER, 0U) - QS_ENUM(QS_CMD, cmdId); - QS_U32(QS_HEX_FMT , param1); - QS_U32(QS_HEX_FMT , param2); - QS_U32(0 , param3); - QS_END() - break; - } - case ROM_READ: { // read ROM (can trip the MPU) - value = BSP::romRead((int32_t)param1, param2); - QS_BEGIN_ID(QS_USER, 0U) - QS_ENUM(QS_CMD, cmdId); - QS_U32(0, value); - QS_END() - break; - } - case ROM_WRITE: { // write ROM (can trip the MPU) - BSP::romWrite(param1, param2, param3); - QS_BEGIN_ID(QS_USER, 0U) - QS_ENUM(QS_CMD, cmdId); - QS_U32(QS_HEX_FMT , param1); - QS_U32(QS_HEX_FMT , param2); - QS_U32(0 , param3); - QS_END() - break; - } - case RAM_READ: { // read RAM (can trip the MPU) - value = BSP::ramRead(param1, param2); - QS_BEGIN_ID(QS_USER, 0U) - QS_ENUM(QS_CMD, cmdId); - QS_U32(0, value); - QS_END() - break; - } - case RAM_WRITE: { // write RAM (can trip the MPU) - BSP::ramWrite(param1, param2, param3); - QS_BEGIN_ID(QS_USER, 0U) - QS_ENUM(QS_CMD, cmdId); - QS_U32(QS_HEX_FMT , param1); - QS_U32(QS_HEX_FMT , param2); - QS_U32(0, param3); - QS_END() - break; - } - default: { - break; - } - } -} - -//============================================================================ -//! Host callback function to "massage" the event, if necessary -void QS::onTestEvt(QEvt *e) { - Q_UNUSED_PAR(e); -} -//............................................................................ -//! callback function to output the posted QP events (not used here) -void QS::onTestPost(void const *sender, QActive *recipient, - QEvt const *e, bool status) -{ - Q_UNUSED_PAR(sender); - Q_UNUSED_PAR(status); -} - -} // namespace QP diff --git a/test/qxk/test_sched/test_sched.py b/test/qxk/test_sched/test_sched.py deleted file mode 100644 index 989572a6e..000000000 --- a/test/qxk/test_sched/test_sched.py +++ /dev/null @@ -1,148 +0,0 @@ -# test-script for QUTest unit testing harness -# see https://www.state-machine.com/qtools/qutest.html/qutest.html - -# preamble -def on_reset(): - expect_pause() - -scenario("extened->basic") -# given... -current_obj(OBJ_AP, "pspecB") -poke(0, 2, pack("1") -expect("@timestamp CONTEXT_SW NULL ThrX::inst[0]") -expect("@timestamp TRACE_MSG ThrX::inst[0] TEST0 1of2") -expect("@timestamp Sch-Next Pri=1->4") -expect("@timestamp CONTEXT_SW ThrX::inst[0] ObjB::inst[0]") -expect("@timestamp TRACE_MSG ObjB::inst[0] TEST1 1of1") -expect("@timestamp Sch-Next Pri=4->1") -expect("@timestamp CONTEXT_SW ObjB::inst[0] ThrX::inst[0]") -expect("@timestamp TRACE_MSG ThrX::inst[0] TEST0 2of2") -expect("@timestamp TRACE_MSG ThrX::inst[0] TEST1 1of2") -expect("@timestamp Sch-Lock Ceil=0->4") -expect("@timestamp Sch-Unlk Ceil=4->0") -expect("@timestamp Sch-Next Pri=1->4") -expect("@timestamp CONTEXT_SW ThrX::inst[0] ObjB::inst[0]") -expect("@timestamp TRACE_MSG ObjB::inst[0] TEST2 1of1") -expect("@timestamp Sch-Next Pri=4->1") -expect("@timestamp CONTEXT_SW ObjB::inst[0] ThrX::inst[0]") -expect("@timestamp TRACE_MSG ThrX::inst[0] TEST1 2of2") -expect("@timestamp TRACE_MSG ThrX::inst[0] TEST2 1of1") -expect("@timestamp Sch-Idle Pri=1->0") -expect("@timestamp CONTEXT_SW ThrX::inst[0] NULL") -expect("@timestamp Trg-Done QS_RX_EVENT") - - -scenario("extended->extened->basic") -# given... -current_obj(OBJ_AP, "pspecB") -poke(0, 2, pack("4") -expect("@timestamp CONTEXT_SW NULL ThrX::inst[0]") -expect("@timestamp TRACE_MSG ThrX::inst[0] TEST0 1of2") -expect("@timestamp Sch-Next Pri=4->5") -expect("@timestamp CONTEXT_SW ThrX::inst[0] ThrX::inst[1]") -expect("@timestamp TRACE_MSG ThrX::inst[1] TEST1 1of2") -expect("@timestamp Sch-Lock Ceil=0->5") -expect("@timestamp Sch-Unlk Ceil=5->0") -expect("@timestamp TRACE_MSG ThrX::inst[1] TEST1 2of2") -expect("@timestamp TRACE_MSG ThrX::inst[1] TEST2 1of1") -expect("@timestamp Sch-Next Pri=5->4") -expect("@timestamp CONTEXT_SW ThrX::inst[1] ThrX::inst[0]") -expect("@timestamp TRACE_MSG ThrX::inst[0] TEST0 2of2") -expect("@timestamp TRACE_MSG ThrX::inst[0] TEST1 1of2") -expect("@timestamp Sch-Lock Ceil=0->5") -expect("@timestamp Sch-Unlk Ceil=5->0") -expect("@timestamp Sch-Next Pri=4->5") -expect("@timestamp CONTEXT_SW ThrX::inst[0] ThrX::inst[1]") -expect("@timestamp TRACE_MSG ThrX::inst[1] TEST2 1of1") -expect("@timestamp Sch-Next Pri=5->4") -expect("@timestamp CONTEXT_SW ThrX::inst[1] ThrX::inst[0]") -expect("@timestamp TRACE_MSG ThrX::inst[0] TEST1 2of2") -expect("@timestamp TRACE_MSG ThrX::inst[0] TEST2 1of1") -expect("@timestamp TRACE_MSG ThrX::inst[0] TEST2 1of1") -expect("@timestamp Sch-Next Pri=4->3") -expect("@timestamp CONTEXT_SW ThrX::inst[0] ObjB::inst[2]") -expect("@timestamp TRACE_MSG ObjB::inst[2] TEST1 1of1") -expect("@timestamp TRACE_MSG ObjB::inst[2] TEST2 1of1") -expect("@timestamp TRACE_MSG ObjB::inst[2] TEST2 1of1") -expect("@timestamp Sch-Next Pri=3->2") -expect("@timestamp CONTEXT_SW ObjB::inst[2] ObjB::inst[1]") -expect("@timestamp TRACE_MSG ObjB::inst[1] TEST1 1of1") -expect("@timestamp TRACE_MSG ObjB::inst[1] TEST2 1of1") -expect("@timestamp TRACE_MSG ObjB::inst[1] TEST2 1of1") -expect("@timestamp Sch-Next Pri=2->1") -expect("@timestamp CONTEXT_SW ObjB::inst[1] ObjB::inst[0]") -expect("@timestamp TRACE_MSG ObjB::inst[0] TEST1 1of1") -expect("@timestamp TRACE_MSG ObjB::inst[0] TEST2 1of1") -expect("@timestamp TRACE_MSG ObjB::inst[0] TEST2 1of1") -expect("@timestamp Sch-Idle Pri=1->0") -expect("@timestamp CONTEXT_SW ObjB::inst[0] NULL") -expect("@timestamp Trg-Done QS_RX_EVENT") - - -scenario("extened->basic->extended") -# given... -current_obj(OBJ_AP, "pspecB") -poke(0, 2, pack("1") -expect("@timestamp CONTEXT_SW NULL ThrX::inst[0]") -expect("@timestamp TRACE_MSG ThrX::inst[0] TEST0 1of2") -expect("@timestamp Sch-Next Pri=1->5") -expect("@timestamp CONTEXT_SW ThrX::inst[0] ThrX::inst[1]") -expect("@timestamp TRACE_MSG ThrX::inst[1] TEST1 1of2") -expect("@timestamp Sch-Lock Ceil=0->5") -expect("@timestamp Sch-Unlk Ceil=5->0") -expect("@timestamp TRACE_MSG ThrX::inst[1] TEST1 2of2") -expect("@timestamp TRACE_MSG ThrX::inst[1] TEST2 1of1") -expect("@timestamp Sch-Next Pri=5->4") -expect("@timestamp CONTEXT_SW ThrX::inst[1] ObjB::inst[0]") -expect("@timestamp TRACE_MSG ObjB::inst[0] TEST1 1of1") -expect("@timestamp TRACE_MSG ObjB::inst[0] TEST2 1of1") -expect("@timestamp Sch-Next Pri=4->1") -expect("@timestamp CONTEXT_SW ObjB::inst[0] ThrX::inst[0]") -expect("@timestamp TRACE_MSG ThrX::inst[0] TEST0 2of2") -expect("@timestamp TRACE_MSG ThrX::inst[0] TEST1 1of2") -expect("@timestamp Sch-Lock Ceil=0->5") -expect("@timestamp Sch-Unlk Ceil=5->0") -expect("@timestamp Sch-Next Pri=1->5") -expect("@timestamp CONTEXT_SW ThrX::inst[0] ThrX::inst[1]") -expect("@timestamp TRACE_MSG ThrX::inst[1] TEST2 1of1") -expect("@timestamp Sch-Next Pri=5->4") -expect("@timestamp CONTEXT_SW ThrX::inst[1] ObjB::inst[0]") -expect("@timestamp TRACE_MSG ObjB::inst[0] TEST2 1of1") -expect("@timestamp Sch-Next Pri=4->1") -expect("@timestamp CONTEXT_SW ObjB::inst[0] ThrX::inst[0]") -expect("@timestamp TRACE_MSG ThrX::inst[0] TEST1 2of2") -expect("@timestamp TRACE_MSG ThrX::inst[0] TEST2 1of1") -expect("@timestamp TRACE_MSG ThrX::inst[0] TEST2 1of1") -expect("@timestamp Sch-Idle Pri=1->0") -expect("@timestamp CONTEXT_SW ThrX::inst[0] NULL") -expect("@timestamp Trg-Done QS_RX_EVENT") diff --git a/test/qxk/test_sched/uvision_efm32.uvoptx b/test/qxk/test_sched/uvision_efm32.uvoptx deleted file mode 100644 index f89706298..000000000 --- a/test/qxk/test_sched/uvision_efm32.uvoptx +++ /dev/null @@ -1,777 +0,0 @@ - - - - 1.0 - -
### uVision Project, (C) Keil Software
- - - *.c - *.s*; *.src; *.a* - *.obj; *.o - *.lib - *.txt; *.h; *.inc; *.md - *.plm - *.cpp - 0 - - - - 0 - 0 - - - - qutest - 0x4 - ARM-ADS - - 12000000 - - 1 - 1 - 1 - 0 - 0 - - - 1 - 65535 - 0 - 0 - 0 - - - 79 - 66 - 8 - .\uvision_emf32\ - - - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 1 - 0 - 1 - - 3 - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 4 - - - - - - - - - - - Segger\JL2CM3.dll - - - - 0 - DLGUARM - - - - 0 - JL2CM3 - -U440060969 -O206 -S2 -ZTIFSpeedSel5000 -A0 -C0 -JU1 -JI127.0.0.1 -JP0 -RST0 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(0) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -TB1 -TFE0 -FO7 -FD20000000 -FC8000 -FN1 -FF0GECKOP2.FLM -FS00 -FL020000 -FP0($$Device:EFM32PG1B200F256GM48$Flash\GECKOP2.FLM) - - - 0 - ARMRTXEVENTFLAGS - -L70 -Z18 -C0 -M0 -T1 - - - 0 - UL2CM3 - UL2CM3(-O207 -S0 -C0 -FO7 -FN1 -FC8000 -FD20000000 -FF0GECKOP2 -FL020000 -FS00 -FP0($$Device:EFM32PG1B200F256GM48$Flash\GECKOP2.FLM) - - - 0 - DLGTARM - (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)(1012=-1,-1,-1,-1,0) - - - 0 - ARMDBGFLAGS - - - - 0 - lmidk-agdi - -U0E2006F4 -O4622 -S4 -FO61 - - - - - 0 - 0 - 142 - 1 -
136
- 0 - 0 - 0 - 0 - 0 - 1 - ..\..\..\src\qs\qs.c - - \\test\../../../src/qs/qs.c\142 -
- - 1 - 0 - 113 - 1 -
29538
- 0 - 0 - 0 - 0 - 0 - 1 - ..\..\..\src\qs\qutest.c - - \\test\../../../src/qs/qutest.c\113 -
- - 2 - 0 - 259 - 1 -
26664
- 0 - 0 - 0 - 0 - 0 - 1 - ..\..\..\src\qxk\qxk.c - - \\test\../../../src/qxk/qxk.c\259 -
- - 3 - 0 - 103 - 1 -
29984
- 0 - 0 - 0 - 0 - 0 - 1 - .\test_sched.c - - \\test\test_sched.c\103 -
-
- - - 0 - 1 - QF_readySet_ - - - 1 - 1 - QXK_attr_ - - - 2 - 1 - QActive_registry_ - - - 3 - 1 - QS_rxPriv_ - - - - - 1 - 2 - 0x20000200 - 0 - - - - - 2 - 0 - 0x400 - 0 - - - - 0 - - - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - - - - - - - - -
-
- - - Applicatioin - 1 - 0 - 0 - 0 - - 1 - 1 - 5 - 0 - 0 - 0 - .\bsp.h - bsp.h - 0 - 0 - - - 1 - 2 - 1 - 0 - 0 - 0 - .\bsp_efm32.c - bsp_efm32.c - 0 - 0 - - - 1 - 3 - 1 - 0 - 0 - 0 - .\test_sched.c - test_sched.c - 0 - 0 - - - - - efm32pg1b - 1 - 0 - 0 - 0 - - 2 - 4 - 2 - 0 - 0 - 0 - ..\..\..\..\3rd_party\efm32pg1b\arm\startup_efm32pg1b.s - startup_efm32pg1b.s - 0 - 0 - - - 2 - 5 - 1 - 0 - 0 - 0 - ..\..\..\..\3rd_party\efm32pg1b\em_cmu.c - em_cmu.c - 0 - 0 - - - 2 - 6 - 1 - 0 - 0 - 0 - ..\..\..\..\3rd_party\efm32pg1b\em_emu.c - em_emu.c - 0 - 0 - - - 2 - 7 - 1 - 0 - 0 - 0 - ..\..\..\..\3rd_party\efm32pg1b\em_gpio.c - em_gpio.c - 0 - 0 - - - 2 - 8 - 1 - 0 - 0 - 0 - ..\..\..\..\3rd_party\efm32pg1b\system_efm32pg1b.c - system_efm32pg1b.c - 0 - 0 - - - 2 - 9 - 1 - 0 - 0 - 0 - ..\..\..\..\3rd_party\efm32pg1b\em_system.c - em_system.c - 0 - 0 - - - 2 - 10 - 1 - 0 - 0 - 0 - ..\..\..\..\3rd_party\efm32pg1b\em_usart.c - em_usart.c - 0 - 0 - - - - - QP - 1 - 0 - 0 - 0 - - 3 - 11 - 1 - 0 - 0 - 0 - ..\..\..\src\qf\qep_hsm.c - qep_hsm.c - 0 - 0 - - - 3 - 12 - 1 - 0 - 0 - 0 - ..\..\..\src\qf\qep_msm.c - qep_msm.c - 0 - 0 - - - 3 - 13 - 1 - 0 - 0 - 0 - ..\..\..\src\qf\qf_act.c - qf_act.c - 0 - 0 - - - 3 - 14 - 1 - 0 - 0 - 0 - ..\..\..\src\qf\qf_actq.c - qf_actq.c - 0 - 0 - - - 3 - 15 - 1 - 0 - 0 - 0 - ..\..\..\src\qf\qf_defer.c - qf_defer.c - 0 - 0 - - - 3 - 16 - 1 - 0 - 0 - 0 - ..\..\..\src\qf\qf_dyn.c - qf_dyn.c - 0 - 0 - - - 3 - 17 - 1 - 0 - 0 - 0 - ..\..\..\src\qf\qf_mem.c - qf_mem.c - 0 - 0 - - - 3 - 18 - 1 - 0 - 0 - 0 - ..\..\..\src\qf\qf_ps.c - qf_ps.c - 0 - 0 - - - 3 - 19 - 1 - 0 - 0 - 0 - ..\..\..\src\qf\qf_qact.c - qf_qact.c - 0 - 0 - - - 3 - 20 - 1 - 0 - 0 - 0 - ..\..\..\src\qf\qf_qeq.c - qf_qeq.c - 0 - 0 - - - 3 - 21 - 1 - 0 - 0 - 0 - ..\..\..\src\qf\qf_qmact.c - qf_qmact.c - 0 - 0 - - - 3 - 22 - 1 - 0 - 0 - 0 - ..\..\..\src\qf\qf_time.c - qf_time.c - 0 - 0 - - - 3 - 23 - 1 - 0 - 0 - 0 - ..\..\..\src\qxk\qxk.c - qxk.c - 0 - 0 - - - 3 - 24 - 1 - 0 - 0 - 0 - ..\..\..\src\qxk\qxk_mutex.c - qxk_mutex.c - 0 - 0 - - - 3 - 25 - 1 - 0 - 0 - 0 - ..\..\..\src\qxk\qxk_sema.c - qxk_sema.c - 0 - 0 - - - 3 - 26 - 1 - 0 - 0 - 0 - ..\..\..\src\qxk\qxk_xthr.c - qxk_xthr.c - 0 - 0 - - - 3 - 27 - 1 - 0 - 0 - 0 - ..\..\..\include\qstamp.c - qstamp.c - 0 - 0 - - - - - QP_port - 1 - 0 - 0 - 0 - - 4 - 29 - 5 - 0 - 0 - 0 - ..\..\..\ports\arm-cm\qxk\armclang\qp_port.h - qp_port.h - 0 - 0 - - - 4 - 30 - 5 - 0 - 0 - 0 - ..\..\..\ports\arm-cm\qxk\armclang\qs_port.h - qs_port.h - 0 - 0 - - - 4 - 31 - 1 - 0 - 0 - 0 - ..\..\..\ports\arm-cm\qxk\armclang\qxk_port.c - qxk_port.c - 0 - 0 - - - 4 - 33 - 1 - 0 - 0 - 0 - ..\..\..\3rd_party\efm32pg1b\qutest\qutest_port.c - qutest_port.c - 0 - 0 - - - - - QS - 1 - 0 - 0 - 0 - - 5 - 34 - 1 - 0 - 0 - 0 - ..\..\..\src\qs\qs.c - qs.c - 0 - 0 - - - 5 - 35 - 1 - 0 - 0 - 0 - ..\..\..\src\qs\qs_64bit.c - qs_64bit.c - 0 - 0 - - - 5 - 36 - 1 - 0 - 0 - 0 - ..\..\..\src\qs\qs_fp.c - qs_fp.c - 0 - 0 - - - 5 - 37 - 1 - 0 - 0 - 0 - ..\..\..\src\qs\qs_rx.c - qs_rx.c - 0 - 0 - - - 5 - 38 - 1 - 0 - 0 - 0 - ..\..\..\src\qs\qutest.c - qutest.c - 0 - 0 - - - -
diff --git a/test/qxk/test_sched/uvision_efm32.uvprojx b/test/qxk/test_sched/uvision_efm32.uvprojx deleted file mode 100644 index 6cc9e13bb..000000000 --- a/test/qxk/test_sched/uvision_efm32.uvprojx +++ /dev/null @@ -1,607 +0,0 @@ - - - - 2.1 - -
### uVision Project, (C) Keil Software
- - - - qutest - 0x4 - ARM-ADS - 6160000::V6.16::ARMCLANG - 1 - - - EFM32PG1B200F256GM48 - Silicon Labs - SiliconLabs.GeckoPlatform_EFM32PG1B_DFP.4.0.0 - https://www.silabs.com/documents/public/cmsis-packs/ - IRAM(0x20000000,0x00008000) IROM(0x00000000,0x00020000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE - - - UL2CM3(-S0 -C0 -P0 -FD20000000 -FC8000 -FN1 -FF0GECKOP2 -FS00 -FL020000 -FP0($$Device:EFM32PG1B200F256GM48$Flash\GECKOP2.FLM)) - 0 - $$Device:EFM32PG1B200F256GM48$Device\EFM32PG1B\Include\em_device.h - - - - - - - - - - $$Device:EFM32PG1B200F256GM48$SVD\EFM32PG1B\EFM32PG1B200F256GM48.svd - 0 - 0 - - - - - - - 0 - 0 - 0 - 0 - 1 - - .\uvision_emf32\ - test - 1 - 0 - 0 - 1 - 1 - .\uvision_emf32\ - 1 - 0 - 0 - - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 1 - 0 - cmd /c "del .\uvision_em32\qstamp.o" - - 0 - 0 - 0 - 0 - - - 0 - 0 - - - 0 - 0 - 0 - 0 - - 1 - - - - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 3 - - - 1 - - - SARMCM3.DLL - -MPU - DCM.DLL - -pCM4 - SARMCM3.DLL - -MPU - TCM.DLL - -pCM4 - - - - 1 - 0 - 0 - 0 - 16 - - - - - 1 - 0 - 0 - 1 - 1 - 4096 - - 1 - BIN\UL2CM3.DLL - "" () - - - - - 0 - - - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 0 - 0 - 0 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - "Cortex-M4" - - 0 - 0 - 0 - 1 - 1 - 0 - 0 - 2 - 0 - 0 - 0 - 0 - 8 - 0 - 0 - 0 - 0 - 3 - 3 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x20000000 - 0x8000 - - - 1 - 0x0 - 0x20000 - - - 0 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x0 - - - 1 - 0x0 - 0x20000 - - - 1 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x0 - 0x0 - - - 0 - 0x20000000 - 0x8000 - - - 0 - 0x0 - 0x0 - - - - - - 0 - 1 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 3 - 0 - 1 - 1 - 0 - 0 - 3 - 3 - 0 - 0 - 0 - 0 - 0 - - - Q_SPY, Q_UTEST=0, QF_ON_CONTEXT_SW - - .;..\..\..\include;..\..\..\ports\arm-cm\qxk\armclang;..\..\..\..\3rd_party\CMSIS\Include;..\..\..\..\3rd_party\efm32pg1b - - - - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 4 - - - Stack_Size=2048 Heap_Size=16 - - - - - - 1 - 0 - 0 - 0 - 1 - 0 - 0x00000000 - 0x20000000 - - - - - --entry Reset_Handler - - - - - - - - Applicatioin - - - bsp.h - 5 - .\bsp.h - - - bsp_efm32.c - 1 - .\bsp_efm32.c - - - test_sched.c - 1 - .\test_sched.c - - - - - efm32pg1b - - - startup_efm32pg1b.s - 2 - ..\..\..\..\3rd_party\efm32pg1b\arm\startup_efm32pg1b.s - - - em_cmu.c - 1 - ..\..\..\..\3rd_party\efm32pg1b\em_cmu.c - - - em_emu.c - 1 - ..\..\..\..\3rd_party\efm32pg1b\em_emu.c - - - em_gpio.c - 1 - ..\..\..\..\3rd_party\efm32pg1b\em_gpio.c - - - system_efm32pg1b.c - 1 - ..\..\..\..\3rd_party\efm32pg1b\system_efm32pg1b.c - - - em_system.c - 1 - ..\..\..\..\3rd_party\efm32pg1b\em_system.c - - - em_usart.c - 1 - ..\..\..\..\3rd_party\efm32pg1b\em_usart.c - - - - - QP - - - qep_hsm.c - 1 - ..\..\..\src\qf\qep_hsm.c - - - qep_msm.c - 1 - ..\..\..\src\qf\qep_msm.c - - - qf_act.c - 1 - ..\..\..\src\qf\qf_act.c - - - qf_actq.c - 1 - ..\..\..\src\qf\qf_actq.c - - - qf_defer.c - 1 - ..\..\..\src\qf\qf_defer.c - - - qf_dyn.c - 1 - ..\..\..\src\qf\qf_dyn.c - - - qf_mem.c - 1 - ..\..\..\src\qf\qf_mem.c - - - qf_ps.c - 1 - ..\..\..\src\qf\qf_ps.c - - - qf_qact.c - 1 - ..\..\..\src\qf\qf_qact.c - - - qf_qeq.c - 1 - ..\..\..\src\qf\qf_qeq.c - - - qf_qmact.c - 1 - ..\..\..\src\qf\qf_qmact.c - - - qf_time.c - 1 - ..\..\..\src\qf\qf_time.c - - - qxk.c - 1 - ..\..\..\src\qxk\qxk.c - - - qxk_mutex.c - 1 - ..\..\..\src\qxk\qxk_mutex.c - - - qxk_sema.c - 1 - ..\..\..\src\qxk\qxk_sema.c - - - qxk_xthr.c - 1 - ..\..\..\src\qxk\qxk_xthr.c - - - qstamp.c - 1 - ..\..\..\include\qstamp.c - - - - - QP_port - - - qp_port.h - 5 - ..\..\..\ports\arm-cm\qxk\armclang\qp_port.h - - - qs_port.h - 5 - ..\..\..\ports\arm-cm\qxk\armclang\qs_port.h - - - qxk_port.c - 1 - ..\..\..\ports\arm-cm\qxk\armclang\qxk_port.c - - - qutest_port.c - 1 - ..\..\..\3rd_party\efm32pg1b\qutest\qutest_port.c - - - - - QS - - - qs.c - 1 - ..\..\..\src\qs\qs.c - - - qs_64bit.c - 1 - ..\..\..\src\qs\qs_64bit.c - - - qs_fp.c - 1 - ..\..\..\src\qs\qs_fp.c - - - qs_rx.c - 1 - ..\..\..\src\qs\qs_rx.c - - - qutest.c - 1 - ..\..\..\src\qs\qutest.c - - - - - - - - - - - - - - - - - test - 1 - - - - -
diff --git a/zephyr/qf_port.cpp b/zephyr/qf_port.cpp index 68e9d0d08..d88ca83e6 100644 --- a/zephyr/qf_port.cpp +++ b/zephyr/qf_port.cpp @@ -1,29 +1,32 @@ //============================================================================ -// 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. +// Q u a n t u m L e a P s +// ------------------------ +// Modern Embedded Software // -// The terms of the open source GNU General Public License version 3 -// can be found at: +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial // -// The terms of the closed source Quantum Leaps commercial licenses -// can be found at: +// 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. // -// Contact information: -// +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: +// // //============================================================================ -//! @date Last updated on: 2024-06-11 -//! @version Last updated for: @ref qpc_7_4_0 +//! @date Last updated on: 2024-09-26 +//! @version Last updated for: @ref qpc_8_0_0 //! //! @file //! @brief QF/C++ port to Zephyr RTOS kernel, all supported compilers @@ -79,8 +82,8 @@ int_t run() { // produce the QS_QF_RUN trace record QS_CRIT_STAT QS_CRIT_ENTRY(); - QS_BEGIN_PRE_(QS_QF_RUN, 0U) - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_RUN, 0U) + QS_END_PRE() QS_CRIT_EXIT(); // perform QS work... @@ -128,7 +131,7 @@ void QActive::setAttr(std::uint32_t attr1, void const *attr2) { } //............................................................................ void QActive::start(QPrioSpec const prioSpec, - QEvt const * * const qSto, std::uint_fast16_t const qLen, + QEvtPtr * const qSto, std::uint_fast16_t const qLen, void * const stkSto, std::uint_fast16_t const stkSize, void const * const par) { @@ -138,7 +141,7 @@ void QActive::start(QPrioSpec const prioSpec, // initialize the Zephyr message queue k_msgq_init(&m_eQueue, reinterpret_cast(qSto), - sizeof(QEvt *), static_cast(qLen)); + sizeof(QEvtPtr), static_cast(qLen)); // top-most initial tran. (virtual call) init(par, m_prio); @@ -199,6 +202,13 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin, { QF_CRIT_STAT QF_CRIT_ENTRY(); + + Q_REQUIRE_INCRIT(200, e != nullptr); +#ifndef Q_UNSAFE + Q_INVARIANT_INCRIT(201, e->verify_()); +#endif // ndef Q_UNSAFE + + // NOTE: k_msgq_num_free_get() can be safely called from crit-section std::uint_fast16_t nFree = static_cast(k_msgq_num_free_get(&m_eQueue)); @@ -209,7 +219,7 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin, } else { status = false; // cannot post - Q_ERROR_INCRIT(510); // must be able to post the event + Q_ERROR_INCRIT(210); // must be able to post the event } } else if (nFree > static_cast(margin)) { @@ -221,38 +231,41 @@ bool QActive::post_(QEvt const * const e, std::uint_fast16_t const margin, if (status) { // can post the event? - QS_BEGIN_PRE_(QS_QF_ACTIVE_POST, m_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_(this); // this active object (recipient) - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_);// pool-Id & ref-Count - QS_EQC_PRE_(nFree); // # free entries available - QS_EQC_PRE_(0U); // min # free entries (unknown) - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_ACTIVE_POST, m_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(this); // this active object (recipient) + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_);// pool-Id & ref-Count + QS_EQC_PRE(nFree); // # free entries available + QS_EQC_PRE(0U); // min # free entries (unknown) + QS_END_PRE() if (e->getPoolNum_() != 0U) { // is it a pool event? QEvt_refCtr_inc_(e); // increment the reference counter } - QF_CRIT_EXIT(); + QF_CRIT_EXIT(); // exit crit.sect. before calling Zephyr API int err = k_msgq_put(&m_eQueue, static_cast(&e), K_NO_WAIT); + QF_CRIT_ENTRY(); // re-enter crit.sect. after calling Zephyr API // posting to the Zephyr message queue must succeed, see NOTE1 - QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(520, err == 0); + Q_ASSERT_INCRIT(220, err == 0); +#ifdef Q_UNSAFE + Q_UNUSED_PAR(err); +#endif } else { - QS_BEGIN_PRE_(QS_QF_ACTIVE_POST_ATTEMPT, m_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_(this); // this active object (recipient) - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_);// pool-Id & ref-Count - QS_EQC_PRE_(nFree); // # free entries available - QS_EQC_PRE_(0U); // min # free entries (unknown) - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_ACTIVE_POST_ATTEMPT, m_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(this); // this active object (recipient) + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_EQC_PRE(nFree); // # free entries available + QS_EQC_PRE(0U); // min # free entries (unknown) + QS_END_PRE() } QF_CRIT_EXIT(); @@ -263,48 +276,59 @@ void QActive::postLIFO(QEvt const * const e) noexcept { QF_CRIT_STAT QF_CRIT_ENTRY(); - QS_BEGIN_PRE_(QS_QF_ACTIVE_POST_LIFO, m_prio) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of this event - QS_OBJ_PRE_(this); // this active object - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // pool-Id & ref-Count - QS_EQC_PRE_(k_msgq_num_free_get(&m_eQueue)); // # free entries - QS_EQC_PRE_(0U); // min # free entries (unknown) - QS_END_PRE_() + Q_REQUIRE_INCRIT(300, e != nullptr); +#ifndef Q_UNSAFE + Q_INVARIANT_INCRIT(301, e->verify_()); +#endif // ndef Q_UNSAFE + + QS_BEGIN_PRE(QS_QF_ACTIVE_POST_LIFO, m_prio) + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(e->sig); // the signal of this event + QS_OBJ_PRE(this); // this active object + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); + QS_EQC_PRE(k_msgq_num_free_get(&m_eQueue)); // # free entries + QS_EQC_PRE(0U); // min # free entries (unknown) + QS_END_PRE() if (e->getPoolNum_() != 0U) { // is it a pool event? QEvt_refCtr_inc_(e); // increment the reference counter } - QF_CRIT_EXIT(); // NOTE: Zephyr message queue does not currently support LIFO posting // so normal FIFO posting is used instead. + QF_CRIT_EXIT(); // exit crit.sect. before calling Zephyr API int err = k_msgq_put(&m_eQueue, static_cast(&e), K_NO_WAIT); + QF_CRIT_ENTRY(); // re-enter crit.sect. after calling Zephyr API + + Q_ASSERT_INCRIT(310, err == 0); +#ifdef Q_UNSAFE + Q_UNUSED_PAR(err); +#endif - QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(710, err == 0); QF_CRIT_EXIT(); } //............................................................................ QEvt const *QActive::get_(void) noexcept { // wait for an event (forever) - QEvt const *e; + QEvtPtr e; int err = k_msgq_get(&m_eQueue, static_cast(&e), K_FOREVER); - // queue-get must succeed QF_CRIT_STAT QF_CRIT_ENTRY(); - Q_ASSERT_INCRIT(810, err == 0); + Q_ASSERT_INCRIT(410, err == 0); // queue-get must succeed +#ifdef Q_UNSAFE + Q_UNUSED_PAR(err); +#endif - QS_BEGIN_PRE_(QS_QF_ACTIVE_GET, m_prio) - QS_TIME_PRE_(); // timestamp - QS_SIG_PRE_(e->sig); // the signal of this event - QS_OBJ_PRE_(this); // this active object - QS_2U8_PRE_(e->getPoolNum_(), e->refCtr_); // pool-Id & ref-Count - QS_EQC_PRE_(k_msgq_num_free_get(&m_eQueue)); // # free entries - QS_END_PRE_() + QS_BEGIN_PRE(QS_QF_ACTIVE_GET, m_prio) + QS_TIME_PRE(); // timestamp + QS_SIG_PRE(e->sig); // the signal of this event + QS_OBJ_PRE(this); // this active object + QS_2U8_PRE(e->getPoolNum_(), e->refCtr_); // pool-Id & ref-Count + QS_EQC_PRE(k_msgq_num_free_get(&m_eQueue)); // # free entries + QS_END_PRE() QF_CRIT_EXIT(); diff --git a/zephyr/qp_port.hpp b/zephyr/qp_port.hpp index 5ef17bda2..f29a20cc3 100644 --- a/zephyr/qp_port.hpp +++ b/zephyr/qp_port.hpp @@ -1,29 +1,27 @@ //============================================================================ -// 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 -// ------------------------ -// Modern Embedded Software -// -// Copyright (C) 2005 Quantum Leaps, LLC . +// 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 // -// 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: +// 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. // -// Contact information: +// NOTE: +// The GPL (see ) does NOT permit the +// incorporation of the QP/C software into proprietary programs. Please +// contact Quantum Leaps for commercial licensing options, which expressly +// supersede the GPL and are designed explicitly for licensees interested +// in using QP/C in closed-source proprietary applications. +// +// Quantum Leaps contact information: // // //============================================================================ @@ -38,7 +36,7 @@ #include // Exact-width types. C++11 Standard #include // Zephyr kernel API -#include "qp_config.hpp" // external QP configuration +#include "qp_config.hpp" // QP configuration from the application // no-return function specifier (C++11 Standard) #define Q_NORETURN [[ noreturn ]] void @@ -65,7 +63,6 @@ #include "qmpool.hpp" // this QP port uses the native QF memory pool #include "qp.hpp" // QP platform-independent public interface - namespace QP { namespace QF { @@ -75,7 +72,6 @@ extern struct k_spinlock spinlock; } // namespace QF } // namespace QP - //============================================================================ // interface used only inside QF implementation, but not in applications #ifdef QP_IMPL diff --git a/zephyr/qutest_port.cpp b/zephyr/qutest_port.cpp index 37e072957..1d8bd4ae9 100644 --- a/zephyr/qutest_port.cpp +++ b/zephyr/qutest_port.cpp @@ -1,6 +1,6 @@ //============================================================================ // Product: QUTEST port for Zephyr RTOS -// Last updated for version 7.4.0 +// Last updated for version 8.0.0 // Last updated on 2024-06-11 // // Q u a n t u m L e a P s