mirror of
https://github.com/QuantumLeaps/qpcpp.git
synced 2025-01-14 05:42:57 +08:00
8.0.0
This commit is contained in:
parent
bea51e87ba
commit
33aa75cfa9
24
.gitignore
vendored
24
.gitignore
vendored
@ -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
|
@ -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.
|
||||
|
||||
|
@ -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
|
32
README.md
32
README.md
@ -34,15 +34,15 @@ provides instructions on how to download, install, and get started with QP.
|
||||
- [AppNote: "Getting Started with QP Real-Time Embedded Frameworks"][AN]
|
||||
contains also a tutorial, in which you build a simple "Blinky" application.
|
||||
|
||||
## Licensing
|
||||
The QP frameworks (QP/C and QP/C++) are licensed under the
|
||||
# Licensing
|
||||
The QP/C++ real-time embedded framework is licensed under the
|
||||
[dual licensing model](https://www.state-machine.com/licensing), with
|
||||
the following licensing options:
|
||||
|
||||
1. [Open-source licensing](https://www.state-machine.com/licensing#Open) under the
|
||||
[GNU General Public License (GPLv3)](https://www.gnu.org/licenses/gpl-3.0.en.html).
|
||||
|
||||
> NOTE: GPL requires that all modifications to the original code
|
||||
> NOTE: The GPL requires that all modifications to the original code
|
||||
as well as your application code (Derivative Works as defined in the
|
||||
Copyright Law) must also be released under the terms of the GPL
|
||||
open source license.
|
||||
@ -56,13 +56,26 @@ proprietary status of their code.
|
||||
all QP frameworks can be licensed commercially, in which case you don't use
|
||||
any open source license and you do not violate your policy.
|
||||
|
||||
## Files Removed from the QP/C++ Open Source GPL Distribution
|
||||
Due to the widespread non-compliance with the GPL, as well as infringement on the
|
||||
[dual-licensing model of QP frameworks][Lic], the following QP/C++ components
|
||||
have been **removed from the open-source GPL distribution**:
|
||||
- QS target-resident software tracing component
|
||||
- QXK dual-mode kernel
|
||||
|
||||
> NOTE: These components are available to the [commercial licensees][Cust] with
|
||||
the active Support Term. Please contact [Quantum Leaps technical support][Sup]
|
||||
to get the complete QP/C++ framework distribution.
|
||||
|
||||
> NOTE: To request **evaluation** of the complete QP/C++ framework, please contact
|
||||
Quantum Leaps at: https://www.state-machine.com/contact
|
||||
|
||||
# About QP/C++
|
||||
QP/C++ (Quantum Platform in C++) is a lightweight, open source
|
||||
[Real-Time Embedded Framework (RTEF)][RTEF] for building modern embedded
|
||||
software as systems of asynchronous, event-driven [Active Objects][Active]
|
||||
(actors). The [QP/C++] framework is a member of a [QP] family consisting of
|
||||
[QP/C] and [QP/C++] frameworks, which are strictly quality controlled,
|
||||
[QP/C++] and [QP/C] frameworks, which are strictly quality controlled,
|
||||
thoroughly documented, and [commercially licensable][Lic].
|
||||
|
||||
## Safer Model of Concurrency
|
||||
@ -103,7 +116,7 @@ without any traditional RTOS. The framework contains a selection of
|
||||
the [preemptive non-blocking QK kernel][QK], and the preemptive,
|
||||
[dual-mode QXK kernel][QXK] that provides all the features you might expect
|
||||
from a traditional RTOS. Native QP ports and ready-to-use examples are provided
|
||||
for major CPUs, such as ARM Cortex-M (M0/M0+/M3/M4/M7/M23/M33/M85).
|
||||
for major CPUs, such as ARM Cortex-M (M0/M0+/M3/M4/M7/M23/M33/...).
|
||||
|
||||
## Traditional RTOS/OS
|
||||
QP/C++ can also work with a traditional RTOS, such as ThreadX, embOS, FreeRTOS,
|
||||
@ -138,12 +151,18 @@ in your web browser.
|
||||
# How to Help this Project?
|
||||
If you like this project, please give it a star (in the upper-right corner of your browser window):
|
||||
|
||||
![GitHub star](https://www.state-machine.com/img/github-star.jpg)
|
||||
<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>
|
||||
|
@ -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
|
||||
|
2
examples
2
examples
@ -1 +1 @@
|
||||
Subproject commit 3ba405ac6fdc2d31b451ebf3b9dd329ca025311c
|
||||
Subproject commit c3b9ebe040f79020b8e8c69724075b81f972adfd
|
45
include/README.md
Normal file
45
include/README.md
Normal 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>
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
138
include/qp.hpp
138
include/qp.hpp
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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_
|
||||
|
1058
include/qs.hpp
1058
include/qs.hpp
File diff suppressed because it is too large
Load Diff
@ -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_
|
||||
|
@ -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_
|
@ -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>
|
||||
//
|
||||
|
@ -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
|
||||
|
342
include/qxk.hpp
342
include/qxk.hpp
@ -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_
|
@ -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
63
ports/README.md
Normal 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>
|
@ -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...
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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...
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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_
|
||||
|
@ -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_
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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...
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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...
|
||||
|
@ -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(); \
|
||||
|
@ -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
|
||||
|
@ -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];
|
||||
}
|
||||
|
||||
|
@ -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_
|
||||
|
@ -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_
|
@ -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"
|
||||
|
@ -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_
|
@ -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_
|
||||
|
@ -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_
|
@ -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"
|
||||
|
@ -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_
|
||||
|
@ -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_
|
@ -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"
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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_
|
@ -1,3 +0,0 @@
|
||||
// Size Options for 32bit CPU (e.g., ARM Cortex-M)
|
||||
-si4 -sl4 -sll8 -ss2 -sw4 -sp4 -sf4 -sd8 -sld8
|
||||
|
@ -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
|
@ -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
@ -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
|
@ -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])
|
@ -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_
|
@ -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
|
@ -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_)
|
||||
|
@ -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_
|
||||
|
@ -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)
|
||||
|
@ -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_
|
||||
|
@ -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_
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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_
|
@ -1,3 +0,0 @@
|
||||
// Size Options for 32bit CPU (e.g., ARM Cortex-M)
|
||||
-si4 -sl4 -sll8 -ss2 -sw4 -sp4 -sf4 -sd8 -sld8
|
||||
|
@ -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
|
@ -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
Loading…
x
Reference in New Issue
Block a user