This commit is contained in:
MMS 2024-10-15 13:15:28 -04:00
parent bea51e87ba
commit 33aa75cfa9
224 changed files with 5459 additions and 42585 deletions

24
.gitignore vendored
View File

@ -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/

@ -1 +1 @@
Subproject commit aca09a2e3571adf97e5ce6cb5b1d645ba2418c1d
Subproject commit 43a99789efed81bd200558e742623745822c779a

View File

@ -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.

View File

@ -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 <state-machine.com>.
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 <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

View File

@ -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)
<p align="center">
<img src="https://www.state-machine.com/img/github-star.jpg"/><br>
</p>
[RTEF]: <https://www.state-machine.com/rtef>
[QP]: <https://www.state-machine.com/products/qp>
[QP/C]: <https://github.com/QuantumLeaps/qpc>
[QP/C++]: <https://github.com/QuantumLeaps/qpcpp>
[QS/C++]: <https://www.state-machine.com/qpcpp/srs-qp_qs.html>
[QV]: <https://www.state-machine.com/qpcpp/srs-qp_qv.html>
[QK]: <https://www.state-machine.com/qpcpp/srs-qp_qk.html>
[QXK]: <https://www.state-machine.com/qpcpp/srs-qp_qxk.html>
[QM]: <https://github.com/QuantumLeaps/qm>
[QTools]: <https://github.com/QuantumLeaps/qtools>
[QP-Rel]: <https://github.com/QuantumLeaps/qpcpp/releases>
@ -153,6 +172,7 @@ If you like this project, please give it a star (in the upper-right corner of yo
[HSM]: <https://www.state-machine.com/qpcpp/srs-qp_sm.html>
[Lic]: <https://www.state-machine.com/licensing>
[Cust]: <https://www.state-machine.com/customers>
[Sup]: <mailto:support@state-machine.com>
[AN]: <https://www.state-machine.com/doc/AN_Getting_Started_with_QP.pdf>
[Tutorial]: <https://www.state-machine.com/qpcpp/gs_tut.html>
[Video]: <https://youtu.be/O7ER6_VqIH0>

View File

@ -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(<target>> 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=<preset> .` from your project directory. The build then can be started with `cmake --build --preset=<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

@ -1 +1 @@
Subproject commit 3ba405ac6fdc2d31b451ebf3b9dd329ca025311c
Subproject commit c3b9ebe040f79020b8e8c69724075b81f972adfd

45
include/README.md Normal file
View File

@ -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]: <https://www.state-machine.com/licensing>
[Cust]: <https://www.state-machine.com/customers>
[Sup]: <mailto:support@state-machine.com>

View File

@ -3,17 +3,10 @@
// Model: qpcpp.qm
// File: ${include::qequeue.hpp}
//
// This code has been generated by QM 6.2.0 <www.state-machine.com/qm>.
// This code has been generated by QM 7.0.0 <www.state-machine.com/qm>.
// 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 <state-machine.com>.
// 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: <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>
//
@ -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 @@ public:
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)
{}
void init(
@ -108,7 +120,11 @@ public:
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;

View File

@ -3,17 +3,10 @@
// Model: qpcpp.qm
// File: ${include::qk.hpp}
//
// This code has been generated by QM 6.2.0 <www.state-machine.com/qm>.
// This code has been generated by QM 7.0.0 <www.state-machine.com/qm>.
// 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 <state-machine.com>.
// 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: <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>
//
@ -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<void>(0))
//${QK-impl::QACTIVE_EQUEUE_SIGNAL_} .........................................
#ifndef Q_UNSAFE

View File

@ -3,17 +3,10 @@
// Model: qpcpp.qm
// File: ${include::qmpool.hpp}
//
// This code has been generated by QM 6.2.0 <www.state-machine.com/qm>.
// This code has been generated by QM 7.0.0 <www.state-machine.com/qm>.
// 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 <state-machine.com>.
// 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: <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>
//
@ -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 @@ private:
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 @@ public:
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
{}
void init(
void * const poolSto,
@ -130,7 +138,11 @@ public:
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;

View File

@ -3,17 +3,10 @@
// Model: qpcpp.qm
// File: ${include::qp.hpp}
//
// This code has been generated by QM 6.2.0 <www.state-machine.com/qm>.
// This code has been generated by QM 7.0.0 <www.state-machine.com/qm>.
// 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 <state-machine.com>.
// 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: <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>
//
@ -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 @@ public:
static_cast<void>(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<std::uint8_t>(evtTag_) & 0x0FU;
return static_cast<std::uint8_t>(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 @@ public:
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 @@ public:
// 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 @@ protected:
m_temp.tatbl = static_cast<QP::QMTranActTable const *>(tatbl);
return Q_RET_TRAN_HIST;
}
QState qm_tran_ep(void const * const tatbl) noexcept {
m_temp.tatbl = static_cast<QP::QMTranActTable const *>(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<QP::QMTranActTable const *>(tatbl);
return Q_RET_TRAN_XP;
}
#ifdef Q_SPY
QState qm_entry(QMState const * const s) noexcept {
@ -376,14 +355,6 @@ protected:
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 @@ public:
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 @@ private:
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 @@ public:
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 @@ public:
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 @@ public:
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;

View File

@ -3,17 +3,10 @@
// Model: qpcpp.qm
// File: ${include::qp_pkg.hpp}
//
// This code has been generated by QM 6.2.0 <www.state-machine.com/qm>.
// This code has been generated by QM 7.0.0 <www.state-machine.com/qm>.
// 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 <state-machine.com>.
// 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: <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>
//
@ -76,25 +68,30 @@ void bzero_(
} // namespace QP
//$enddecl${QF::QF-pkg} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#define QF_CONST_CAST_(type_, ptr_) const_cast<type_>(ptr_)
#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_)))
#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
// 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

View File

@ -3,17 +3,10 @@
// Model: qpcpp.qm
// File: ${include::qpcpp.hpp}
//
// This code has been generated by QM 6.2.0 <www.state-machine.com/qm>.
// This code has been generated by QM 7.0.0 <www.state-machine.com/qm>.
// 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 <state-machine.com>.
// 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: <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>
//
@ -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<void>(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<void>(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<std::uint_fast8_t>(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_

File diff suppressed because it is too large Load Diff

View File

@ -1,64 +1,52 @@
//$file${include::qs_dummy.hpp} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
//============================================================================
// QP/C++ Spy software tracing target-resident component
//
// Model: qpcpp.qm
// File: ${include::qs_dummy.hpp}
//
// This code has been generated by QM 6.2.0 <www.state-machine.com/qm>.
// 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 <state-machine.com>.
// 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: <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>
//
//$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<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_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_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<void>(0)
@ -96,27 +84,83 @@
#define QS_RX_INPUT() static_cast<void>(0)
#define QS_ONLY(code_) static_cast<void>(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<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_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)
@ -128,7 +172,7 @@
#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)
#define QS_TR_ISR_EXIT(isrnest_, prio_) static_cast<void>(0)
#endif // QP_IMPL
#endif // QS_DUMMY_HPP_

View File

@ -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 <www.state-machine.com/qm>.
// 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 <state-machine.com>.
//
// 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: <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>
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//
//$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<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_

View File

@ -3,17 +3,10 @@
// Model: qpcpp.qm
// File: ${include::qstamp.hpp}
//
// This code has been generated by QM 6.2.0 <www.state-machine.com/qm>.
// This code has been generated by QM 7.0.0 <www.state-machine.com/qm>.
// 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 <state-machine.com>.
// 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: <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>
//

View File

@ -3,17 +3,10 @@
// Model: qpcpp.qm
// File: ${include::qv.hpp}
//
// This code has been generated by QM 6.2.0 <www.state-machine.com/qm>.
// This code has been generated by QM 7.0.0 <www.state-machine.com/qm>.
// 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 <state-machine.com>.
// 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: <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>
//
@ -94,8 +86,7 @@ void onIdle();
#define QF_SCHED_UNLOCK_() (static_cast<void>(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<void>(0))
//${QV-impl::QACTIVE_EQUEUE_SIGNAL_} .........................................
#ifndef Q_UNSAFE

View File

@ -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 <www.state-machine.com/qm>.
// 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 <state-machine.com>.
//
// 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: <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>
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//
//$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<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)
#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<std::uint_fast8_t>((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<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)
#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<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)
#endif // def Q_UNSAFE
//${QXK-impl::QXTHREAD_CAST_} ................................................
#define QXTHREAD_CAST_(ptr_) (static_cast<QP::QXThread *>(ptr_))
//${QXK-impl::QXK_PTR_CAST_} .................................................
#define QXK_PTR_CAST_(type_, ptr_) (reinterpret_cast<type_>(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<QEvt *>((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_

View File

@ -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})

63
ports/README.md Normal file
View File

@ -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]: <https://www.state-machine.com/customers>
[sup]: <mailto:support@state-machine.com>

View File

@ -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 <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:
// <www.state-machine.com>
// 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>
//============================================================================
//! @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
// 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).
#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
#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
#ifndef QK_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)
#else //--------- use the selected IRQ
#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
// 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
#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*.
// NOTE! interrupts are still disabled when NMI is used
" B . \n" // wait for preemption by NMI/IRQ
#endif //--------- use the NMI
#endif //--------- ARMv7-M and higher
// 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
// ...continue here from either NMI_Handler() or IRQ_Handler()
__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)
// 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...

View File

@ -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 <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:
// <www.state-machine.com>
// 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>
//============================================================================
//! @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 <cstdint> // Exact-width types. C++11 Standard
#ifdef QP_CONFIG
#include "qp_config.hpp" // external QP configuration
#endif
#include <cstdint> // 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

View File

@ -28,7 +28,7 @@
// <info@state-machine.com>
//============================================================================
//! @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

View File

@ -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: <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:
// <www.state-machine.com>
// NOTE:
// The GPL (see <www.gnu.org/licenses/gpl-3.0>) does NOT permit the
// incorporation of the QP/C software into proprietary programs. Please
// contact Quantum Leaps for commercial licensing options, which expressly
// supersede the GPL and are designed explicitly for licensees interested
// in using QP/C in closed-source proprietary applications.
//
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
#ifndef QP_CONFIG_HPP_
@ -34,17 +32,10 @@
//-------- <<< Use Configuration Wizard in Context Menu >>> -----------------
// <n>NOTE: Requires command-line macro: QP_CONFIG
// <i>This qp_config.h header file is activated only when the macro
// <i>QP_CONFIG is defined on the command-line to the compiler
// <n>-------------------------------------------
// <o>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)
// <i>QP API backwards compatibility with the QP/C API version.
// <i>Lower QP_API_VERSION values enable backwards compatibility
@ -132,6 +123,7 @@
// <c1>Event parameter initialization (QEVT_PAR_INIT)
// <i>Resource Acquisition Is Initialization (RAII) for dynamic events
//#define QEVT_PAR_INIT
// </c>
// <c1>Provide destructors for QP classes
// <i>Destructors for classes
@ -162,7 +154,6 @@
// <o>Event queue counter size (QF_EQUEUE_CTR_SIZE)
// <1U=>1 (default)
// <2U=>2
// <4U=>4
// <i>Size of event queue counter [bytes]
// <i>Default: 1 (255 events maximum in a queue)
#define QF_EQUEUE_CTR_SIZE 1U
@ -215,7 +206,7 @@
//..........................................................................
// <h>QK Preemptive Non-Blocking Kernel
// <i>Preemptive non-blocking RTOS kernel.
// <i>Preemptive non-blocking/blocking RTOS kernel.
// <h>Context switch callback (QF_ON_CONTEXT_SW)
@ -248,8 +239,8 @@
// <i>If enabled, provide the otherwise unused IRQ number (QK_USE_IRQ_NUM)
// <i>and the corresponding IRQ handler name (QK_USE_IRQ_HANDLER)
// <i>in the "Text Editor" mode.
//#define QK_USE_IRQ_NUM 31
//#define QK_USE_IRQ_HANDLER Reserved31_IRQHandler
//#define QK_USE_IRQ_NUM <adjust to your MCU>
//#define QK_USE_IRQ_HANDLER <adjust to your MCU>
// </c>
// </h>

View File

@ -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 <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:
// <www.state-machine.com>
// 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>
//============================================================================
//! @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
// 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).
#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
#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
#ifndef QK_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)
#else //--------- use the selected IRQ
#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
// 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
#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*.
// NOTE! interrupts are still disabled when NMI is used
" B . \n" // wait for preemption by NMI/IRQ
#endif //--------- use the NMI
#endif //--------- ARMv7-M and higher
// 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
// 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
// ...continue here from either NMI_Handler() or IRQ_Handler()
__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)
// 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...

View File

@ -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 <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:
// <www.state-machine.com>
// 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>
//============================================================================
//! @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 <cstdint> // Exact-width types. C++11 Standard
#ifdef QP_CONFIG
#include "qp_config.hpp" // external QP configuration
#endif
#include <cstdint> // 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

View File

@ -28,7 +28,7 @@
// <info@state-machine.com>
//============================================================================
//! @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

View File

@ -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 <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:
// <www.state-machine.com>
// 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>
//============================================================================
//! @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
// 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).
#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
#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
#ifndef QK_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)
#else //--------- use the selected IRQ
#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
// 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
#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*.
// NOTE! interrupts are still disabled when NMI is used
" B . \n" // wait for preemption by NMI/IRQ
#endif //--------- use the NMI
#endif //--------- ARMv7-M and higher
// 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
// 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
__stackless
void QK_USE_IRQ_HANDLER(void) {
#endif //--------- use IRQ
// ...continue here from either NMI_Handler() or IRQ_Handler()
__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)
// 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,

View File

@ -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 <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:
// <www.state-machine.com>
// 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>
//============================================================================
//! @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 <cstdint> // Exact-width types. C++11 Standard
#include <intrinsics.h> // IAR intrinsic functions
#ifdef QP_CONFIG
#include "qp_config.hpp" // external QP configuration
#endif
#include <cstdint> // Exact-width types. C++11 Standard
#include <intrinsics.h> // IAR intrinsic functions
#include "qp_config.hpp" // QP configuration from the application
// no-return function specifier (C++11 Standard)
#define Q_NORETURN [[ noreturn ]] void

View File

@ -28,7 +28,7 @@
// <info@state-machine.com>
//============================================================================
//! @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

View File

@ -1,100 +0,0 @@
//============================================================================
// QP/C++ Real-Time Embedded Framework (RTEF)
// 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>
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
//! @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 <cstdint> // 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<void>(0))
#define QF_SCHED_UNLOCK_() (static_cast<void>(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<QEvt *>((p_).get((m_), (qsId_))))
#define QF_EPOOL_PUT_(p_, e_, qsId_) ((p_).put((e_), (qsId_)))
#endif // QP_IMPL
#endif // QP_PORT_HPP_

View File

@ -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: <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>
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// <info@state-machine.com>
//============================================================================
//! @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_

View File

@ -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 <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:
// <www.state-machine.com>
// 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>
//============================================================================
//! @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 <cstdint> // Exact-width types. C++11 Standard
#ifdef QP_CONFIG
#include "qp_config.hpp" // external QP configuration
#endif
#include <cstdint> // 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)

View File

@ -28,7 +28,7 @@
// <info@state-machine.com>
//============================================================================
//! @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

View File

@ -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 <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:
// <www.state-machine.com>
// 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>
//============================================================================
//! @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...

View File

@ -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: <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:
// <www.state-machine.com>
// NOTE:
// The GPL (see <www.gnu.org/licenses/gpl-3.0>) does NOT permit the
// incorporation of the QP/C software into proprietary programs. Please
// contact Quantum Leaps for commercial licensing options, which expressly
// supersede the GPL and are designed explicitly for licensees interested
// in using QP/C in closed-source proprietary applications.
//
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
#ifndef QP_CONFIG_HPP_
@ -34,17 +32,10 @@
//-------- <<< Use Configuration Wizard in Context Menu >>> -----------------
// <n>NOTE: Requires command-line macro: QP_CONFIG
// <i>This qp_config.h header file is activated only when the macro
// <i>QP_CONFIG is defined on the command-line to the compiler
// <n>-------------------------------------------
// <o>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)
// <i>QP API backwards compatibility with the QP/C API version.
// <i>Lower QP_API_VERSION values enable backwards compatibility
@ -132,6 +123,7 @@
// <c1>Event parameter initialization (QEVT_PAR_INIT)
// <i>Resource Acquisition Is Initialization (RAII) for dynamic events
//#define QEVT_PAR_INIT
// </c>
// <c1>Provide destructors for QP classes
// <i>Destructors for classes
@ -162,7 +154,6 @@
// <o>Event queue counter size (QF_EQUEUE_CTR_SIZE)
// <1U=>1 (default)
// <2U=>2
// <4U=>4
// <i>Size of event queue counter [bytes]
// <i>Default: 1 (255 events maximum in a queue)
#define QF_EQUEUE_CTR_SIZE 1U

View File

@ -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 <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:
// <www.state-machine.com>
// 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>
//============================================================================
//! @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 <cstdint> // Exact-width types. C++11 Standard
#ifdef QP_CONFIG
#include "qp_config.hpp" // external QP configuration
#endif
#include <cstdint> // 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)

View File

@ -28,7 +28,7 @@
// <info@state-machine.com>
//============================================================================
//! @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

View File

@ -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: <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:
// <www.state-machine.com>
// 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>
//============================================================================
//! @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...

View File

@ -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 <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:
// <www.state-machine.com>
// 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>
//============================================================================
//! @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 <cstdint> // Exact-width types. C++11 Standard
#include <intrinsics.h> // IAR intrinsic functions
#ifdef QP_CONFIG
#include "qp_config.hpp" // external QP configuration
#endif
#include <cstdint> // Exact-width types. C++11 Standard
#include <intrinsics.h> // 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(); \

View File

@ -28,7 +28,7 @@
// <info@state-machine.com>
//============================================================================
//! @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

View File

@ -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 <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:
// <www.state-machine.com>
// 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>
//============================================================================
//! @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];
}

View File

@ -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 <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>
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// <info@state-machine.com>
//============================================================================
//! @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 <cstdint> // 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<std::uint32_t>(n_))
#else // ARMv7-M or higher
// BASEPRI threshold for "QF-aware" interrupts, see NOTE3
#define QF_BASEPRI 0x3F
// CMSIS threshold for "QF-aware" interrupts, see NOTE4
#define QF_AWARE_ISR_CMSIS_PRI (QF_BASEPRI >> (8 - __NVIC_PRIO_BITS))
// ARMv7-M or higher provide the CLZ instruction for fast LOG2
#define QF_LOG2(n_) \
(static_cast<std::uint32_t>(32 - __builtin_clz((n_))))
#endif
// interrupt disabling policy, see NOTE2 and NOTE3
#define QF_INT_DISABLE() (QF_int_disable_())
#define QF_INT_ENABLE() (QF_int_enable_())
// 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_

View File

@ -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: <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>
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// <info@state-machine.com>
//============================================================================
//! @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_

View File

@ -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 <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>
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// <info@state-machine.com>
//============================================================================
//! @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 <cstddef> // 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"

View File

@ -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: <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>
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// <info@state-machine.com>
//============================================================================
#ifndef QP_CONFIG_HPP_
#define QP_CONFIG_HPP_
//-------- <<< Use Configuration Wizard in Context Menu >>> -----------------
// <n>NOTE: Requires command-line macro: QP_CONFIG
// <i>This qp_config.h header file is activated only when the macro
// <i>QP_CONFIG is defined on the command-line to the compiler
// <n>-------------------------------------------
// <o>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)
// <i>QP API backwards compatibility with the QP/C API version.
// <i>Lower QP_API_VERSION values enable backwards compatibility
// <i>with lower (older) QP API versions.
// <i>For example, QP_API_VERSION==691 will enable the compatibility
// <i>layer with QP version 6.9.1 and newer, but not older than 6.9.1.
// <i>QP_API_VERSION==0 enables the maximum currently supported
// <i>backwards compatibility. Conversely, QP_API_VERSION==9999 means
// <i>that no backwards compatibility layer should be enabled.
// <i>Default: 0 (All supported)
#define QP_API_VERSION 0
//..........................................................................
// <h>QP Functional Safety (FuSa) Subsystem (Q_UNSAFE)
// <i>The QP FuSa Subsystem consists of the following facilities:
// <i>- Software assertions as a recommended technique
// <i> (called Failure Assertion Programming (FAP) in IEC 61508)
// <i>- Software Self-Monitoring (SSM), which encompasses such techniques:
// <i> * Duplicate Inverse Storage for critical variables
// <i> * Memory Markers for critical objects (e.g., events)
// <i> * Hard-limits for all loops
// <i> * Memory Isolation by means of Memory Protection Unit (MPU)
// <c3>Disable QP FuSa in development
// <i>Disable assertions and other self monitoring features
// <i>in development build configurations (NDEBUG undefined).
// <i>VIOLATES functional safety standards. NOT recommended !!!
//#ifndef NDEBUG
//#define Q_UNSAFE
//#endif
// </c>
// <c3>Disable QP FuSa in production release
// <i>Disable assertions and other self monitoring features
// <i>in the release build configurations (NDEBUG defined).
// <i>VIOLATES functional safety standards. NOT recommended !!!
//#ifdef NDEBUG
//#define Q_UNSAFE
//#endif
// </c>
// </h>
//..........................................................................
// <h>QEP Event Processor
// <i>Events and state machines.
// <o>Event signal size (Q_SIGNAL_SIZE)
// <1U=>1
// <2U=>2 (default)
// <4U=>4
// <i>Size of the QEvt signal for QEP/QF [bytes]
// <i>Default: 2
#define Q_SIGNAL_SIZE 2U
// </h>
//..........................................................................
// <h>QF Framework
// <i>Active Object framework
// <o>Maximum # Active Objects (QF_MAX_ACTIVE) <1-64>
// <i>Maximum # Active Objects in the system <1..64>
// <i>Default: 32
#define QF_MAX_ACTIVE 32U
// <o>Maximum # event pools (QF_MAX_EPOOL)
// <0=>0 no event pools
// <1=>1 <2=>2 <3=>3 (default) <4=>4 <5=>5
// <6=>6 <7=>7 <8=>8 <9=>9 <10=>10 <11=>11
// <12=>12 <13=>13 <14=>14 <15=>15
// <i>Maximum # Event Pools <1..15>
// <i>Default: 3
#define QF_MAX_EPOOL 3U
// <o>Maximum # clock tick rates (QF_MAX_TICK_RATE)
// <0=>0 no time events
// <1=>1 (default) <2=>2 <3=>3 <4=>4 <5=>5
// <6=>6 <7=>7 <8=>8 <9=>9 <10=>10 <11=>11
// <12=>12 <13=>13 <14=>14 <15=>15
// <i>Maximum # clock tick rates for time events <1..15>
// <i>Default: 1
#define QF_MAX_TICK_RATE 1U
// <c1>Event parameter initialization (QEVT_PAR_INIT)
// <i>Resource Acquisition Is Initialization (RAII) for dynamic events
//#define QEVT_PAR_INIT
// <c1>Provide destructors for QP classes
// <i>Destructors for classes
//#define Q_XTOR
// </c>
// <c1>Active Object stop API (QACTIVE_CAN_STOP)
// <i>Enable Active Object stop API (Not recommended)
//#define QACTIVE_CAN_STOP
// </c>
// <o>Event size (QF_EVENT_SIZ_SIZE)
// <1U=>1
// <2U=>2 (default)
// <4U=>4
// <i>Size of the dynamic events for QF [bytes]
// <i>Default: 2 (64K bytes maximum event size)
#define QF_EVENT_SIZ_SIZE 2U
// <o>Time event counter size (QF_TIMEEVT_CTR_SIZE)
// <1U=>1
// <2U=>2
// <4U=>4 (default)
// <i>Size of the QTimeEvt counter [bytes]
// <i>Default: 4 (2^32 dynamic range)
#define QF_TIMEEVT_CTR_SIZE 4U
// <o>Event queue counter size (QF_EQUEUE_CTR_SIZE)
// <1U=>1 (default)
// <2U=>2
// <4U=>4
// <i>Size of event queue counter [bytes]
// <i>Default: 1 (255 events maximum in a queue)
#define QF_EQUEUE_CTR_SIZE 1U
// <o>Memory pool counter size (QF_MPOOL_CTR_SIZE)
// <1U=>1
// <2U=>2 (default)
// <4U=>4
// <i>Size of memory pool counter [bytes]
// <i>Default: 2 (64K blocks maximum in a pool)
#define QF_MPOOL_CTR_SIZE 2U
// <o>Memory block size (QF_MPOOL_SIZ_SIZE)
// <1U=>1
// <2U=>2 (default)
// <4U=>4
// <i>Size of memory pool block [bytes]
// <i>Default: 2 (64K bytes maximum block size)
#define QF_MPOOL_SIZ_SIZE 2U
// </h>
//..........................................................................
// <h>QS Software Tracing
// <i>Target-resident component of QP/Spy software tracing system
// <i>(tracing instrumentation and command-input).
// <n>NOTE: Requires command-line macro: Q_SPY
// <i>The QS software tracing instrumentation is activated only when
// <i>the macro Q_SPY is defined on the command-line to the compiler.
// <i>Typically, Q_SPY is defined only in the "spy" build configuration.
// <o>QS timestamp size (QS_TIME_SIZE)
// <1U=>1
// <2U=>2
// <4U=>4 (default)
// <i>Size of the timestamp in QS [bytes]
// <i>Default: 4 (2^32 dynamic range)
#define QS_TIME_SIZE 4U
// <o>QS buffer counter size (QS_CTR_SIZE)
// <1U=>1
// <2U=>2 (default)
// <4U=>4
// <i>Size of the counter in the internal QS buffer [bytes]
// <i>Default: 2 (64K bytes in QS buffer)
#define QS_CTR_SIZE 2U
// </h>
//..........................................................................
// <h>QXK Preemptive Dual-Mode Kernel
// <i>Preemptive non-blocking/blocking RTOS kernel.
// <h>Context switch callback (QF_ON_CONTEXT_SW)
// <c2>Context switch callback WITHOUT QS
// <i>Enable context switch callback QF_onContextSw()
// <i>When Q_SPY is undefined.
//#ifndef Q_SPY
//#define QF_ON_CONTEXT_SW
//#endif
// </c>
// <c2>Context switch callback WITH QS
// <i>Enable context switch callback QF_onContextSw()
// <i>When Q_SPY is defined.
//#ifdef Q_SPY
//#define QF_ON_CONTEXT_SW
//#endif
// </c>
// </h>
// <c2>MPU memory isolation (QF_MEM_ISOLATE)
// <i>Enable memory isolation (requires MPU)
// <i>NOTE: implies QF_ON_CONTEXT_SW.
//#define QF_MEM_ISOLATE
// </c>
// <c4>Use IRQ handler for QXK return-from-preemption
// <i>Enable this option only if the NMI handler is used in the project.
// <i>If enabled, provide the otherwise unused IRQ number (QXK_USE_IRQ_NUM)
// <i>and the corresponding IRQ handler name (QXK_USE_IRQ_HANDLER)
// <i>in the "Text Editor" mode.
//#define QXK_USE_IRQ_NUM 31
//#define QXK_USE_IRQ_HANDLER Reserved31_IRQHandler
// </c>
// </h>
//------------- <<< end of configuration section >>> -----------------------
#endif // QP_CONFIG_HPP_

View File

@ -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 <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>
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// <info@state-machine.com>
//============================================================================
//! @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 <cstdint> // 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<std::uint32_t>(n_))
#else // ARMv7-M or higher
// BASEPRI threshold for "QF-aware" interrupts, see NOTE3
#define QF_BASEPRI 0x3F
// CMSIS threshold for "QF-aware" interrupts, see 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<std::uint32_t>(32 - __builtin_clz((n_))))
#endif
// interrupt disabling policy, see NOTE2 and NOTE3
#define QF_INT_DISABLE() (QF_int_disable_())
#define QF_INT_ENABLE() (QF_int_enable_())
// 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_

View File

@ -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: <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>
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// <info@state-machine.com>
//============================================================================
//! @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_

View File

@ -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 <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>
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// <info@state-machine.com>
//============================================================================
//! @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 <cstddef> // 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"

View File

@ -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 <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>
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// <info@state-machine.com>
//============================================================================
//! @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 <cstdint> // Exact-width types. C++11 Standard
#include <intrinsics.h> // 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<std::uint32_t>(n_))
#else // ARMv7-M or higher
// BASEPRI threshold for "QF-aware" interrupts, see NOTE3
#define QF_BASEPRI 0x3F
// CMSIS threshold for "QF-aware" interrupts, see NOTE4
#define QF_AWARE_ISR_CMSIS_PRI (QF_BASEPRI >> (8 - __NVIC_PRIO_BITS))
// ARMv7-M or higher provide the CLZ instruction for fast LOG2
#define QF_LOG2(n_) \
(static_cast<std::uint32_t>(32U - __CLZ((n_))))
#endif
// interrupt disabling policy, see NOTE2 and NOTE3
#define QF_INT_DISABLE() (QF_int_disable_())
#define QF_INT_ENABLE() (QF_int_enable_())
// 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_

View File

@ -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: <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>
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// <info@state-machine.com>
//============================================================================
//! @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_

View File

@ -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 <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>
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// <info@state-machine.com>
//============================================================================
//! @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 <cstddef> // 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"

View File

@ -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

View File

@ -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: <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:
// <www.state-machine.com>
// NOTE:
// The GPL (see <www.gnu.org/licenses/gpl-3.0>) does NOT permit the
// incorporation of the QP/C software into proprietary programs. Please
// contact Quantum Leaps for commercial licensing options, which expressly
// supersede the GPL and are designed explicitly for licensees interested
// in using QP/C in closed-source proprietary applications.
//
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
#ifndef QP_CONFIG_HPP_
@ -34,17 +32,10 @@
//-------- <<< Use Configuration Wizard in Context Menu >>> -----------------
// <n>NOTE: Requires command-line macro: QP_CONFIG
// <i>This qp_config.h header file is activated only when the macro
// <i>QP_CONFIG is defined on the command-line to the compiler
// <n>-------------------------------------------
// <o>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)
// <i>QP API backwards compatibility with the QP/C API version.
// <i>Lower QP_API_VERSION values enable backwards compatibility
@ -132,6 +123,7 @@
// <c1>Event parameter initialization (QEVT_PAR_INIT)
// <i>Resource Acquisition Is Initialization (RAII) for dynamic events
//#define QEVT_PAR_INIT
// </c>
// <c1>Provide destructors for QP classes
// <i>Destructors for classes
@ -162,7 +154,6 @@
// <o>Event queue counter size (QF_EQUEUE_CTR_SIZE)
// <1U=>1 (default)
// <2U=>2
// <4U=>4
// <i>Size of event queue counter [bytes]
// <i>Default: 1 (255 events maximum in a queue)
#define QF_EQUEUE_CTR_SIZE 1U

View File

@ -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: <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:
// <www.state-machine.com>
// 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>
//============================================================================
//! @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 <cstdint> // Exact-width types. C++11 Standard
#ifdef QP_CONFIG
#include "qp_config.hpp" // external QP configuration
#endif
#include <cstdint> // 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

View File

@ -28,7 +28,7 @@
// <info@state-machine.com>
//============================================================================
//! @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

View File

@ -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: <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:
// <www.state-machine.com>
// 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>
//============================================================================
//! @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 <cstdint> // Exact-width types. C++11 Standard
#include <intrinsics.h> // IAR intrinsic functions
#ifdef QP_CONFIG
#include "qp_config.hpp" // external QP configuration
#endif
#include <cstdint> // Exact-width types. C++11 Standard
#include <intrinsics.h> // IAR intrinsic functions
#include "qp_config.hpp" // QP configuration from the application
// no-return function specifier (C++11 Standard)
#define Q_NORETURN [[ noreturn ]] void

View File

@ -28,7 +28,7 @@
// <info@state-machine.com>
//============================================================================
//! @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

View File

@ -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: <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:
// <www.state-machine.com>
// 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>
//============================================================================
//! @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 <cstdint> // Exact-width types. C++11 Standard
#ifdef QP_CONFIG
#include "qp_config.hpp" // external QP configuration
#endif
#include <cstdint> // 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

View File

@ -28,7 +28,7 @@
// <info@state-machine.com>
//============================================================================
//! @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

View File

@ -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: <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:
// <www.state-machine.com>
// NOTE:
// The GPL (see <www.gnu.org/licenses/gpl-3.0>) does NOT permit the
// incorporation of the QP/C software into proprietary programs. Please
// contact Quantum Leaps for commercial licensing options, which expressly
// supersede the GPL and are designed explicitly for licensees interested
// in using QP/C in closed-source proprietary applications.
//
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
#ifndef QP_CONFIG_HPP_
@ -34,17 +32,10 @@
//-------- <<< Use Configuration Wizard in Context Menu >>> -----------------
// <n>NOTE: Requires command-line macro: QP_CONFIG
// <i>This qp_config.h header file is activated only when the macro
// <i>QP_CONFIG is defined on the command-line to the compiler
// <n>-------------------------------------------
// <o>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)
// <i>QP API backwards compatibility with the QP/C API version.
// <i>Lower QP_API_VERSION values enable backwards compatibility
@ -132,6 +123,7 @@
// <c1>Event parameter initialization (QEVT_PAR_INIT)
// <i>Resource Acquisition Is Initialization (RAII) for dynamic events
//#define QEVT_PAR_INIT
// </c>
// <c1>Provide destructors for QP classes
// <i>Destructors for classes
@ -162,7 +154,6 @@
// <o>Event queue counter size (QF_EQUEUE_CTR_SIZE)
// <1U=>1 (default)
// <2U=>2
// <4U=>4
// <i>Size of event queue counter [bytes]
// <i>Default: 1 (255 events maximum in a queue)
#define QF_EQUEUE_CTR_SIZE 1U

View File

@ -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: <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:
// <www.state-machine.com>
// 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>
//============================================================================
//! @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 <cstdint> // Exact-width types. C++11 Standard
#ifdef QP_CONFIG
#include "qp_config.hpp" // external QP configuration
#endif
#include <cstdint> // 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

View File

@ -28,7 +28,7 @@
// <info@state-machine.com>
//============================================================================
//! @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

View File

@ -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: <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:
// <www.state-machine.com>
// 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>
//============================================================================
//! @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 <cstdint> // Exact-width types. C++11 Standard
#include <intrinsics.h> // IAR intrinsic functions
#ifdef QP_CONFIG
#include "qp_config.hpp" // external QP configuration
#endif
#include <cstdint> // Exact-width types. C++11 Standard
#include <intrinsics.h> // IAR intrinsic functions
#include "qp_config.hpp" // QP configuration from the application
// no-return function specifier (C++11 Standard)
#define Q_NORETURN [[ noreturn ]] void

View File

@ -28,7 +28,7 @@
// <info@state-machine.com>
//============================================================================
//! @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

View File

@ -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: <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:
// <www.state-machine.com>
// 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>
//============================================================================
//! @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 <cstdint> // Exact-width types. C++11 Standard
#ifdef QP_CONFIG
#include "qp_config.hpp" // external QP configuration
#endif
#include <cstdint> // 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

View File

@ -28,7 +28,7 @@
// <info@state-machine.com>
//============================================================================
//! @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

View File

@ -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: <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:
// <www.state-machine.com>
// NOTE:
// The GPL (see <www.gnu.org/licenses/gpl-3.0>) does NOT permit the
// incorporation of the QP/C software into proprietary programs. Please
// contact Quantum Leaps for commercial licensing options, which expressly
// supersede the GPL and are designed explicitly for licensees interested
// in using QP/C in closed-source proprietary applications.
//
// Quantum Leaps contact information:
// <www.state-machine.com/licensing>
// <info@state-machine.com>
//============================================================================
#ifndef QP_CONFIG_HPP_
@ -34,17 +32,10 @@
//-------- <<< Use Configuration Wizard in Context Menu >>> -----------------
// <n>NOTE: Requires command-line macro: QP_CONFIG
// <i>This qp_config.h header file is activated only when the macro
// <i>QP_CONFIG is defined on the command-line to the compiler
// <n>-------------------------------------------
// <o>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)
// <i>QP API backwards compatibility with the QP/C API version.
// <i>Lower QP_API_VERSION values enable backwards compatibility
@ -132,6 +123,7 @@
// <c1>Event parameter initialization (QEVT_PAR_INIT)
// <i>Resource Acquisition Is Initialization (RAII) for dynamic events
//#define QEVT_PAR_INIT
// </c>
// <c1>Provide destructors for QP classes
// <i>Destructors for classes
@ -162,7 +154,6 @@
// <o>Event queue counter size (QF_EQUEUE_CTR_SIZE)
// <1U=>1 (default)
// <2U=>2
// <4U=>4
// <i>Size of event queue counter [bytes]
// <i>Default: 1 (255 events maximum in a queue)
#define QF_EQUEUE_CTR_SIZE 1U

View File

@ -1,29 +1,32 @@
//============================================================================
// 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
//
// 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:
// <www.state-machine.com>
// 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>
//============================================================================
//! @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<OS_U16>(sizeof(QEvt *)),
static_cast<OS_U16>(sizeof(QEvtPtr)),
static_cast<OS_UINT>(qLen),
static_cast<void *>(&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<void OS_STACKPTR *>(stkSto),
static_cast<OS_UINT>(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<std::uint_fast16_t>(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<QEQueueCtr>(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<OS_CONST_PTR void *>(&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<OS_CONST_PTR void *>(&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<void *>(&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,

View File

@ -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: <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:
// <www.state-machine.com>
// 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>
//============================================================================
//! @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 <cstdint> // Exact-width types. C++11 Standard
#ifdef QP_CONFIG
#include "qp_config.hpp" // external QP configuration
#endif
#include <cstdint> // 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

View File

@ -28,7 +28,7 @@
// <info@state-machine.com>
//============================================================================
//! @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

File diff suppressed because it is too large Load Diff

View File

@ -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: <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:
// <www.state-machine.com>
// 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>
//============================================================================
//! @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 <cstdint> // Exact-width types. C++11 Standard
#ifdef QP_CONFIG
#include "qp_config.hpp" // external QP configuration
#endif
#include <cstdint> // 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<QEvt *>((p_).get((m_), (qsId_))))
#define QF_EPOOL_PUT_(p_, e_, qsId_) ((p_).put((e_), (qsId_)))
#endif // ifdef QP_IMPL
#endif // def QP_IMPL
//============================================================================
// NOTE2:

View File

@ -28,7 +28,7 @@
// <info@state-machine.com>
//============================================================================
//! @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

View File

@ -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

View File

@ -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

View File

@ -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: <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>
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// <info@state-machine.com>
//============================================================================
//! @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_

View File

@ -1,3 +0,0 @@
// Size Options for 32bit CPU (e.g., ARM Cortex-M)
-si4 -sl4 -sll8 -ss2 -sw4 -sp4 -sf4 -sd8 -sld8

View File

@ -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

View File

@ -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: <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>
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// <info@state-machine.com>
//============================================================================
//! @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_

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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]' ~ '^(?P<keyword>alignas|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]' ~ '^(?P<keyword>alignas|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])

View File

@ -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<class IntType>
constexpr byte& operator<<=(byte& b, IntType shift) noexcept;
template<class IntType>
constexpr byte operator<<(byte b, IntType shift) noexcept;
template<class IntType>
constexpr byte& operator>>=(byte& b, IntType shift) noexcept;
template<class IntType>
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<class IntType>
constexpr IntType to_integer(byte b) noexcept;
}
#define NULL nullptr
//#define offsetof(type, member) ...
//lint -restore
#endif // _CSTDDEF_

View File

@ -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: <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>
::
:: Redistributions in source code must retain this top-level comment block.
:: Plagiarizing this software to sidestep the license obligations is illegal.
::
:: Contact information:
:: <www.state-machine.com>
:: <info@state-machine.com>
:: ===========================================================================
@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

View File

@ -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: <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>
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// <info@state-machine.com>
//============================================================================
//! @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<macro>)
-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_)

View File

@ -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: <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>
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// <info@state-machine.com>
//============================================================================
//! @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 <cstdint> // 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<void>(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_

View File

@ -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: <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>
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// <info@state-machine.com>
//============================================================================
//! @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)

View File

@ -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: <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>
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// <info@state-machine.com>
//============================================================================
//! @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 <cstdint> // 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_

View File

@ -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: <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>
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// <info@state-machine.com>
//============================================================================
//! @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 <cstdint> // 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<void>(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_

View File

@ -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: <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>
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// <info@state-machine.com>
//============================================================================
//! @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<nn> options bleed to other files
-summary() // produce a summary of all produced messages

View File

@ -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

View File

@ -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

View File

@ -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: <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>
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// <info@state-machine.com>
//============================================================================
//! @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_

View File

@ -1,3 +0,0 @@
// Size Options for 32bit CPU (e.g., ARM Cortex-M)
-si4 -sl4 -sll8 -ss2 -sw4 -sp4 -sf4 -sd8 -sld8

View File

@ -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

View File

@ -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: <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>
//
// Redistributions in source code must retain this top-level comment block.
// Plagiarizing this software to sidestep the license obligations is illegal.
//
// Contact information:
// <www.state-machine.com>
// <info@state-machine.com>
//============================================================================
//! @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_

Some files were not shown because too many files have changed in this diff Show More