mirror of
https://github.com/QuantumLeaps/qpc.git
synced 2025-01-14 06:43:19 +08:00
8.0.0
This commit is contained in:
parent
d3f94c7783
commit
efec63749b
24
.gitignore
vendored
24
.gitignore
vendored
@ -37,17 +37,29 @@
|
||||
version-*
|
||||
JLink*.*
|
||||
|
||||
cert/
|
||||
include/qs.h
|
||||
include/qs_pkg.h
|
||||
include/qxk.h
|
||||
src/qs/qs.c
|
||||
src/qs/qs_64bit.c
|
||||
src/qs/qs_fp.c
|
||||
src/qs/qs_rx.c
|
||||
src/qs/qutest.c
|
||||
src/qxk/qxk.c
|
||||
src/qxk/qxk_mutex.c
|
||||
src/qxk/qxk_sema.c
|
||||
src/qxk/qxk_xthr.c
|
||||
|
||||
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
|
||||
qpc
|
||||
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>
|
||||
#BC89496843DE5343CECA990E1370BDD6F9ACDC56
|
||||
#2BACD81DCE8ED122C193E4F48A14170D660DFF1E
|
30
README.md
30
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,6 +56,19 @@ 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
|
||||
@ -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/qpc/srs-qp_qs.html>
|
||||
[QV]: <https://www.state-machine.com/qpc/srs-qp_qv.html>
|
||||
[QK]: <https://www.state-machine.com/qpc/srs-qp_qk.html>
|
||||
[QXK]: <https://www.state-machine.com/qpc/srs-qp_qxk.html>
|
||||
[QM]: <https://github.com/QuantumLeaps/qm>
|
||||
[QTools]: <https://github.com/QuantumLeaps/qtools>
|
||||
[QP-Rel]: <https://github.com/QuantumLeaps/qpc/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/qpc/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/qpc/gs_tut.html>
|
||||
[Video]: <https://youtu.be/O7ER6_VqIH0>
|
||||
|
@ -38,6 +38,10 @@ set(QPC_PROJECT qpcPrj)
|
||||
set(QPC_CFG_KERNEL QV)
|
||||
set(QPC_CFG_GUI TRUE)
|
||||
set(QPC_CFG_PORT win32)
|
||||
# QP/C 8.0.0: to include a local 'qp_config.h' add the related include path
|
||||
# to the qpc build settings. Replace "${CMAKE_CURRENT_LIST_DIR}/include" by
|
||||
# your project specific path!
|
||||
set(QPC_CFG_QPCONFIG_H_INCLUDE_PATH ${CMAKE_CURRENT_LIST_DIR}/include)
|
||||
qpc_sdk_init()
|
||||
|
||||
target_link_libraries(qpcApp PRIVATE qpc)
|
||||
@ -78,6 +82,8 @@ This file is situated in the root directory of qpc. It performs a pre-initializa
|
||||
* `QPC-CFG-GUI` - BOOL: set this boolean variable to ON/TRUE, if GUI support (win32) shall be compiled in. Default: OFF
|
||||
* `QPC_CFG_UNIT_TEST` - BOOL: set this to ON/TRUE to support qutest, if build configuration `Spy` is active. Default: OFF
|
||||
* `QPC_CFG_VERBOSE` - BOOL: set this to enable more verbosity in message output. Default: OFF
|
||||
* `QPC_CFG_QPCONFIG_H_INCLUDE_PATH`: - STRING (PATH): (`QP/C 8.0.0`) set this to have the build of QP/C use your project specific `qp_config.h`.
|
||||
Default: `${QPC_SDK_PATH}/ports/config`
|
||||
|
||||
### General usage hints
|
||||
1. Set `QPC_SDK_PATH` or `QPC_FETCH_FROM_GIT` either in your `CMakeLists.txt` file or as an environment variable.
|
||||
@ -111,43 +117,13 @@ Many `qpc` examples provide 3 build configurations:
|
||||
These configurations are also supported by qpc 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
|
||||
`qpc` 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.
|
||||
With the release of QP/C V8.0.0 the inclusion of `qp_config.h` is mandatory.
|
||||
The `cmake` build system of qpc addresses this by providing the configuration variable `QPC_CFG_QPCONFIG_H_INCLUDE_PATH`. Set this to the path of your local project's `qp_config.h` and this will automatically be found by the build system. Do this in your main `CMakeLists.txt` file __before__ calling `qpc_sdk_init()`.
|
||||
|
||||
As `qp_config.h` is a project related file, which - in most cases - resides outside the `qpc` 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 `qpc` itself.
|
||||
You do not need to set this variable, should the qpc default settings be sufficient for your project. In this case the build system uses the `qp_config.h` file, as it can be found in the directory `${QPC_SDK_PATH}/src/ports/config`.
|
||||
|
||||
An example can be found in the [cmake dpp example](https://github.com/QuantumLeaps/qpc-examples/tree/main/posix-win32-cmake/dpp). Have a look into
|
||||
the example's [CMakeLists.txt](https://github.com/QuantumLeaps/qpc-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 qpc library
|
||||
target_link_libraries(dpp
|
||||
PRIVATE
|
||||
qpc
|
||||
)
|
||||
# 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(qpc # add -DQP_CONFIG to the qpc build
|
||||
PUBLIC
|
||||
QP_CONFIG
|
||||
)
|
||||
target_include_directories(qpc # add the path to 'qp_config.h' to the list of include paths for qpc
|
||||
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()
|
||||
```
|
||||
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).
|
||||
|
||||
### 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`.
|
||||
|
2
examples
2
examples
@ -1 +1 @@
|
||||
Subproject commit 16ea07cc4dbcbde83431a9962cf4ec157b951dcf
|
||||
Subproject commit f505eec147a61e8a10f725bf343f914b5cedb57c
|
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**:
|
||||
|
||||
```
|
||||
qpc
|
||||
|
|
||||
+---include
|
||||
| qs.h
|
||||
| qs_pkg.h
|
||||
| qxk.h
|
||||
|
|
||||
\---src
|
||||
|
|
||||
+---qs
|
||||
| qs.c
|
||||
| qs_64bit.c
|
||||
| qs_fp.c
|
||||
| qs_rx.c
|
||||
| qutest.c
|
||||
|
|
||||
\---qxk
|
||||
qxk.c
|
||||
qxk_mutex.c
|
||||
qxk_sema.c
|
||||
qxk_xthr.c
|
||||
```
|
||||
|
||||
> 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: qpc.qm
|
||||
// File: ${include::qequeue.h}
|
||||
//
|
||||
// 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) : qpc
|
||||
// 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>
|
||||
//
|
||||
@ -51,13 +43,11 @@
|
||||
typedef uint8_t QEQueueCtr;
|
||||
#elif (QF_EQUEUE_CTR_SIZE == 2U)
|
||||
typedef uint16_t QEQueueCtr;
|
||||
#elif (QF_EQUEUE_CTR_SIZE == 4U)
|
||||
typedef uint32_t QEQueueCtr;
|
||||
#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
|
||||
|
||||
struct QEvt; // forward declaration
|
||||
struct QEvt; // forward declartion
|
||||
|
||||
//$declare${QF::QEQueue} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
|
||||
@ -70,7 +60,7 @@ typedef struct QEQueue {
|
||||
struct QEvt const * volatile frontEvt;
|
||||
|
||||
//! @private @memberof QEQueue
|
||||
struct QEvt const ** ring;
|
||||
struct QEvt const * * ring;
|
||||
|
||||
//! @private @memberof QEQueue
|
||||
QEQueueCtr end;
|
||||
@ -84,18 +74,42 @@ typedef struct QEQueue {
|
||||
//! @private @memberof QEQueue
|
||||
QEQueueCtr volatile nFree;
|
||||
|
||||
#ifndef Q_UNSAFE
|
||||
//! @private @memberof QEQueue
|
||||
uintptr_t frontEvt_dis;
|
||||
#endif // ndef Q_UNSAFE
|
||||
|
||||
#ifndef Q_UNSAFE
|
||||
//! @private @memberof QEQueue
|
||||
QEQueueCtr head_dis;
|
||||
#endif // ndef Q_UNSAFE
|
||||
|
||||
#ifndef Q_UNSAFE
|
||||
//! @private @memberof QEQueue
|
||||
QEQueueCtr tail_dis;
|
||||
#endif // ndef Q_UNSAFE
|
||||
|
||||
#ifndef Q_UNSAFE
|
||||
//! @private @memberof QEQueue
|
||||
QEQueueCtr nFree_dis;
|
||||
#endif // ndef Q_UNSAFE
|
||||
|
||||
#ifndef Q_UNSAFE
|
||||
//! @private @memberof QEQueue
|
||||
QEQueueCtr nMin;
|
||||
#endif // ndef Q_UNSAFE
|
||||
|
||||
// public:
|
||||
// type:
|
||||
} QEQueue;
|
||||
extern QEQueue QEQueue_dummy;
|
||||
|
||||
// dummy static member to force generating 'struct QEQueue {...}'
|
||||
extern QEQueue * QEQueue_dummy;
|
||||
|
||||
// public:
|
||||
|
||||
//! @public @memberof QEQueue
|
||||
void QEQueue_init(QEQueue * const me,
|
||||
struct QEvt const ** const qSto,
|
||||
struct QEvt const * * const qSto,
|
||||
uint_fast16_t const qLen);
|
||||
|
||||
//! @public @memberof QEQueue
|
||||
@ -120,7 +134,11 @@ static inline QEQueueCtr QEQueue_getNFree(QEQueue const * const me) {
|
||||
|
||||
//! @public @memberof QEQueue
|
||||
static inline QEQueueCtr QEQueue_getNMin(QEQueue const * const me) {
|
||||
#ifndef Q_UNSAFE
|
||||
return me->nMin;
|
||||
#else
|
||||
return 0U;
|
||||
#endif
|
||||
}
|
||||
|
||||
//! @public @memberof QEQueue
|
||||
|
35
include/qk.h
35
include/qk.h
@ -3,17 +3,10 @@
|
||||
// Model: qpc.qm
|
||||
// File: ${include::qk.h}
|
||||
//
|
||||
// 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) : qpc
|
||||
// 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>
|
||||
//
|
||||
@ -162,8 +154,7 @@ void QK_activate_(void);
|
||||
} while (false)
|
||||
|
||||
//${QK-impl::QACTIVE_EQUEUE_WAIT_} ...........................................
|
||||
#define QACTIVE_EQUEUE_WAIT_(me_) \
|
||||
Q_ASSERT_INCRIT(320, (me_)->eQueue.frontEvt != (QEvt *)0)
|
||||
#define QACTIVE_EQUEUE_WAIT_(me_) ((void)0)
|
||||
|
||||
//${QK-impl::QACTIVE_EQUEUE_SIGNAL_} .........................................
|
||||
#ifndef Q_UNSAFE
|
||||
|
@ -3,17 +3,10 @@
|
||||
// Model: qpc.qm
|
||||
// File: ${include::qmpool.h}
|
||||
//
|
||||
// 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) : qpc
|
||||
// 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>
|
||||
//
|
||||
@ -71,8 +63,8 @@
|
||||
#endif
|
||||
|
||||
#define QF_MPOOL_EL(evType_) struct { \
|
||||
QFreeBlock sto_[((sizeof(evType_) - 1U) \
|
||||
/ sizeof(QFreeBlock)) + 1U]; }
|
||||
QFreeBlock sto_[((sizeof(evType_) - 1U) / (2U * sizeof(void *))) + 1U]; \
|
||||
}
|
||||
|
||||
//$declare${QF::QFreeBlock} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
|
||||
@ -116,8 +108,20 @@ typedef struct {
|
||||
//! @private @memberof QMPool
|
||||
QMPoolCtr volatile nFree;
|
||||
|
||||
#ifndef Q_UNSAFE
|
||||
//! @private @memberof QMPool
|
||||
QMPoolCtr nMin;
|
||||
#endif // ndef Q_UNSAFE
|
||||
|
||||
#ifndef Q_UNSAFE
|
||||
//! @private @memberof QMPool
|
||||
uintptr_t free_head_dis;
|
||||
#endif // ndef Q_UNSAFE
|
||||
|
||||
#ifndef Q_UNSAFE
|
||||
//! @private @memberof QMPool
|
||||
QMPoolCtr nFree_dis;
|
||||
#endif // ndef Q_UNSAFE
|
||||
} QMPool;
|
||||
|
||||
// public:
|
||||
|
150
include/qp.h
150
include/qp.h
@ -3,17 +3,10 @@
|
||||
// Model: qpc.qm
|
||||
// File: ${include::qp.h}
|
||||
//
|
||||
// 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) : qpc
|
||||
// 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,9 +36,9 @@
|
||||
#define QP_H_
|
||||
|
||||
//============================================================================
|
||||
#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
|
||||
@ -134,12 +126,6 @@ typedef uint16_t QSignal;
|
||||
typedef uint32_t QSignal;
|
||||
#endif // (Q_SIGNAL_SIZE == 4U)
|
||||
|
||||
//${QEP::QEVT_MARKER} ........................................................
|
||||
#define QEVT_MARKER 0xE0U
|
||||
|
||||
//${QEP::QEVT_DYNAMIC} .......................................................
|
||||
#define QEVT_DYNAMIC 0U
|
||||
|
||||
//${QEP::QEvt} ...............................................................
|
||||
//! @class QEvt
|
||||
typedef struct QEvt {
|
||||
@ -151,10 +137,10 @@ typedef struct QEvt {
|
||||
// private:
|
||||
|
||||
//! @private @memberof QEvt
|
||||
uint8_t volatile refCtr_;
|
||||
uint8_t evtTag_;
|
||||
|
||||
//! @private @memberof QEvt
|
||||
uint8_t evtTag_;
|
||||
uint8_t volatile refCtr_;
|
||||
} QEvt;
|
||||
|
||||
extern QEvt const QEvt_reserved_[4];
|
||||
@ -166,8 +152,8 @@ static inline void QEvt_ctor(QEvt * const me,
|
||||
enum_t const sig)
|
||||
{
|
||||
me->sig = (QSignal)sig;
|
||||
me->evtTag_ = 0x0FU;
|
||||
me->refCtr_ = 0U;
|
||||
me->evtTag_ = QEVT_MARKER;
|
||||
}
|
||||
|
||||
//! @public @memberof QEvt
|
||||
@ -180,15 +166,18 @@ static inline QEvt * QEvt_init(QEvt * const me,
|
||||
|
||||
// private:
|
||||
|
||||
#ifndef Q_UNSAFE
|
||||
//! @private @memberof QEvt
|
||||
static inline bool QEvt_verify_(QEvt const * const me) {
|
||||
return (me != (QEvt const *)0)
|
||||
&& ((me->evtTag_ & 0xF0U) == QEVT_MARKER);
|
||||
uint8_t rc = me->refCtr_;
|
||||
return (rc <= 2U*QF_MAX_ACTIVE)
|
||||
&& (((me->evtTag_ ^ rc) & 0x0FU) == 0x0FU);
|
||||
}
|
||||
#endif // ndef Q_UNSAFE
|
||||
|
||||
//! @private @memberof QEvt
|
||||
static inline uint_fast8_t QEvt_getPoolNum_(QEvt const * const me) {
|
||||
return (uint_fast8_t)me->evtTag_ & 0x0FU;
|
||||
return (uint_fast8_t)(me->evtTag_ >> 4U);
|
||||
}
|
||||
|
||||
//${QEP::QStateRet} ..........................................................
|
||||
@ -198,7 +187,6 @@ static inline uint_fast8_t QEvt_getPoolNum_(QEvt const * const me) {
|
||||
enum QStateRet {
|
||||
// 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 guard
|
||||
|
||||
// handled and do not need to "bubble up"
|
||||
@ -214,12 +202,10 @@ enum QStateRet {
|
||||
|
||||
// transitions need to execute transition-action table in ::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 me->state
|
||||
Q_RET_TRAN_HIST, //!< transition to history of a given state
|
||||
Q_RET_TRAN_XP //!< exit-point transition out of a submachine
|
||||
};
|
||||
|
||||
//${QEP::QState} .............................................................
|
||||
@ -253,16 +239,6 @@ typedef struct QMTranActTable {
|
||||
QActionHandler const act[1]; //!< @private @memberof QMTranActTable
|
||||
} QMTranActTable;
|
||||
|
||||
//${QEP::QReservedSig} .......................................................
|
||||
//! Reserved signals by the QHsm-style state machine implementation
|
||||
enum QReservedSig {
|
||||
Q_EMPTY_SIG, //!< signal to execute the default case
|
||||
Q_ENTRY_SIG, //!< signal for coding entry actions
|
||||
Q_EXIT_SIG, //!< signal for coding exit actions
|
||||
Q_INIT_SIG, //!< signal for coding initial transitions
|
||||
Q_USER_SIG //!< offset for the user signals (QP Application)
|
||||
};
|
||||
|
||||
//${QEP::QAsmAttr} ...........................................................
|
||||
union QAsmAttr {
|
||||
QStateHandler fun; //!< @private @memberof QAsmAttr
|
||||
@ -451,7 +427,10 @@ QState QMsm_enterHistory_(
|
||||
//$declare${QEP-macros} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
|
||||
//${QEP-macros::QEVT_INITIALIZER} ............................................
|
||||
#define QEVT_INITIALIZER(sig_) { (QSignal)(sig_), 0U, QEVT_MARKER }
|
||||
#define QEVT_INITIALIZER(sig_) { (QSignal)(sig_), 0x01U, 0x0EU }
|
||||
|
||||
//${QEP-macros::QEVT_DYNAMIC} ................................................
|
||||
#define QEVT_DYNAMIC ((uint8_t)0)
|
||||
|
||||
//${QEP-macros::QASM_INIT} ...................................................
|
||||
#ifdef Q_SPY
|
||||
@ -494,6 +473,21 @@ QState QMsm_enterHistory_(
|
||||
//${QEP-macros::Q_MSM_UPCAST} ................................................
|
||||
#define Q_MSM_UPCAST(ptr_) ((QMsm *)(ptr_))
|
||||
|
||||
//${QEP-macros::Q_EMPTY_SIG} .................................................
|
||||
#define Q_EMPTY_SIG ((QSignal)0)
|
||||
|
||||
//${QEP-macros::Q_ENTRY_SIG} .................................................
|
||||
#define Q_ENTRY_SIG ((QSignal)1)
|
||||
|
||||
//${QEP-macros::Q_EXIT_SIG} ..................................................
|
||||
#define Q_EXIT_SIG ((QSignal)2)
|
||||
|
||||
//${QEP-macros::Q_INIT_SIG} ..................................................
|
||||
#define Q_INIT_SIG ((QSignal)3)
|
||||
|
||||
//${QEP-macros::Q_USER_SIG} ..................................................
|
||||
#define Q_USER_SIG ((enum_t)4)
|
||||
|
||||
//${QEP-macros::Q_TRAN} ......................................................
|
||||
#define Q_TRAN(target_) \
|
||||
((Q_ASM_UPCAST(me))->temp.fun = Q_STATE_CAST(target_), \
|
||||
@ -582,18 +576,6 @@ QState QMsm_enterHistory_(
|
||||
(struct QMTranActTable const *)(tatbl_))), \
|
||||
(QState)Q_RET_TRAN_HIST)
|
||||
|
||||
//${QEP-macros::QM_TRAN_EP} ..................................................
|
||||
#define QM_TRAN_EP(tatbl_) ((Q_ASM_UPCAST(me))->temp.tatbl \
|
||||
= (struct QMTranActTable const *)(tatbl_), \
|
||||
(QState)Q_RET_TRAN_EP)
|
||||
|
||||
//${QEP-macros::QM_TRAN_XP} ..................................................
|
||||
#define QM_TRAN_XP(xp_, tatbl_) \
|
||||
((((Q_ASM_UPCAST(me))->state.act = (xp_)), \
|
||||
((Q_ASM_UPCAST(me))->temp.tatbl = \
|
||||
(struct QMTranActTable const *)(tatbl_))), \
|
||||
(QState)Q_RET_TRAN_XP)
|
||||
|
||||
//${QEP-macros::QM_HANDLED} ..................................................
|
||||
#define QM_HANDLED() ((QState)Q_RET_HANDLED)
|
||||
|
||||
@ -603,11 +585,6 @@ QState QMsm_enterHistory_(
|
||||
//${QEP-macros::QM_SUPER} ....................................................
|
||||
#define QM_SUPER() ((QState)Q_RET_SUPER)
|
||||
|
||||
//${QEP-macros::QM_SUPER_SUB} ................................................
|
||||
#define QM_SUPER_SUB(host_) \
|
||||
((Q_ASM_UPCAST(me))->temp.obj = (host_), \
|
||||
(QState)Q_RET_SUPER_SUB)
|
||||
|
||||
//${QEP-macros::QM_STATE_NULL} ...............................................
|
||||
#define QM_STATE_NULL ((QMState *)0)
|
||||
//$enddecl${QEP-macros} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -774,7 +751,7 @@ static inline bool QPSet_verify_(QPSet const * const me,
|
||||
#endif // ndef Q_UNSAFE
|
||||
|
||||
//${QF::types::QSubscrList} ..................................................
|
||||
// @struct QSubscrList
|
||||
//! @struct QSubscrList
|
||||
typedef struct {
|
||||
// private:
|
||||
|
||||
@ -787,6 +764,9 @@ typedef struct {
|
||||
#endif // ndef Q_UNSAFE
|
||||
} QSubscrList;
|
||||
|
||||
//${QF::types::QEvtPtr} ......................................................
|
||||
typedef QEvt const * QEvtPtr;
|
||||
|
||||
//${QF::types::QEQueue} ......................................................
|
||||
struct QEQueue;
|
||||
//$enddecl${QF::types} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -859,7 +839,7 @@ void QActive_setAttr(QActive * const me,
|
||||
//! @public @memberof QActive
|
||||
void QActive_start(QActive * const me,
|
||||
QPrioSpec const prioSpec,
|
||||
QEvt const * * const qSto,
|
||||
QEvtPtr * const qSto,
|
||||
uint_fast16_t const qLen,
|
||||
void * const stkSto,
|
||||
uint_fast16_t const stkSize,
|
||||
@ -972,19 +952,40 @@ typedef struct QTimeEvt {
|
||||
//! @private @memberof QTimeEvt
|
||||
struct QTimeEvt * volatile next;
|
||||
|
||||
#ifndef Q_UNSAFE
|
||||
//! @private @memberof QTimeEvt
|
||||
void * volatile act;
|
||||
uintptr_t next_dis;
|
||||
#endif // ndef Q_UNSAFE
|
||||
|
||||
//! @private @memberof QTimeEvt
|
||||
void * act;
|
||||
|
||||
//! @private @memberof QTimeEvt
|
||||
QTimeEvtCtr volatile ctr;
|
||||
|
||||
#ifndef Q_UNSAFE
|
||||
//! @private @memberof QTimeEvt
|
||||
QTimeEvtCtr ctr_dis;
|
||||
#endif // ndef Q_UNSAFE
|
||||
|
||||
//! @private @memberof QTimeEvt
|
||||
QTimeEvtCtr interval;
|
||||
|
||||
//! @private @memberof QTimeEvt
|
||||
uint8_t tickRate;
|
||||
|
||||
//! @private @memberof QTimeEvt
|
||||
uint8_t flags;
|
||||
} QTimeEvt;
|
||||
|
||||
//! @static @private @memberof QTimeEvt
|
||||
extern QTimeEvt QTimeEvt_timeEvtHead_[QF_MAX_TICK_RATE];
|
||||
|
||||
#ifndef Q_UNSAFE
|
||||
//! @static @private @memberof QTimeEvt
|
||||
extern uintptr_t QTimeEvt_timeEvtHead_dis_[QF_MAX_TICK_RATE];
|
||||
#endif // ndef Q_UNSAFE
|
||||
|
||||
// public:
|
||||
|
||||
//! @public @memberof QTimeEvt
|
||||
@ -995,15 +996,15 @@ void QTimeEvt_ctorX(QTimeEvt * const me,
|
||||
|
||||
//! @public @memberof QTimeEvt
|
||||
void QTimeEvt_armX(QTimeEvt * const me,
|
||||
QTimeEvtCtr const nTicks,
|
||||
QTimeEvtCtr const interval);
|
||||
uint32_t const nTicks,
|
||||
uint32_t const interval);
|
||||
|
||||
//! @public @memberof QTimeEvt
|
||||
bool QTimeEvt_disarm(QTimeEvt * const me);
|
||||
|
||||
//! @public @memberof QTimeEvt
|
||||
bool QTimeEvt_rearm(QTimeEvt * const me,
|
||||
QTimeEvtCtr const nTicks);
|
||||
uint32_t const nTicks);
|
||||
|
||||
//! @public @memberof QTimeEvt
|
||||
bool QTimeEvt_wasDisarmed(QTimeEvt * const me);
|
||||
@ -1011,6 +1012,9 @@ bool QTimeEvt_wasDisarmed(QTimeEvt * const me);
|
||||
//! @public @memberof QTimeEvt
|
||||
QTimeEvtCtr QTimeEvt_currCtr(QTimeEvt const * const me);
|
||||
|
||||
//! @static @private @memberof QTimeEvt
|
||||
void QTimeEvt_init(void);
|
||||
|
||||
//! @static @private @memberof QTimeEvt
|
||||
void QTimeEvt_tick_(
|
||||
uint_fast8_t const tickRate,
|
||||
|
@ -3,17 +3,10 @@
|
||||
// Model: qpc.qm
|
||||
// File: ${include::qp_pkg.h}
|
||||
//
|
||||
// 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) : qpc
|
||||
// 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>
|
||||
//
|
||||
@ -77,23 +69,29 @@ void QF_bzero_(
|
||||
uint_fast16_t const len);
|
||||
//$enddecl${QF::QF-pkg} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
// Bitmasks are for the QTimeEvt::refCtr_ attribute (inherited from ::QEvt).
|
||||
// In ::QTimeEvt this attribute is NOT used for reference counting.
|
||||
#define QTE_IS_LINKED (1U << 7U)
|
||||
#define QTE_WAS_DISARMED (1U << 6U)
|
||||
#define QTE_TICK_RATE 0x0FU
|
||||
// Bitmasks are for the QTimeEvt::flags attribute
|
||||
#define QTE_FLAG_IS_LINKED (1U << 7U)
|
||||
#define QTE_FLAG_WAS_DISARMED (1U << 6U)
|
||||
|
||||
//! @private @memberof QEvt
|
||||
static inline void QEvt_refCtr_inc_(QEvt const *me) {
|
||||
++((QEvt *)me)->refCtr_;
|
||||
uint8_t rc = me->refCtr_ + 1U;
|
||||
((QEvt *)me)->refCtr_ = rc; // cast away 'const'
|
||||
#ifndef Q_UNSAFE
|
||||
((QEvt *)me)->evtTag_ = (me->evtTag_ & 0xF0U) | ((~rc) & 0x0FU);
|
||||
#endif // ndef Q_UNSAFE
|
||||
}
|
||||
|
||||
//! @private @memberof QEvt
|
||||
static inline void QEvt_refCtr_dec_(QEvt const *me) {
|
||||
--((QEvt *)me)->refCtr_;
|
||||
uint8_t rc = me->refCtr_ - 1U;
|
||||
((QEvt *)me)->refCtr_ = rc; // cast away 'const'
|
||||
#ifndef Q_UNSAFE
|
||||
((QEvt *)me)->evtTag_ = (me->evtTag_ & 0xF0U) | ((~rc) & 0x0FU);
|
||||
#endif // ndef Q_UNSAFE
|
||||
}
|
||||
|
||||
#define QACTIVE_CAST_(ptr_) ((QActive *)(ptr_))
|
||||
#define Q_UINTPTR_CAST_(ptr_) ((uintptr_t)(ptr_))
|
||||
#define QACTIVE_CAST_(ptr_) ((QActive *)(ptr_))
|
||||
#define Q_PTR2UINT_CAST_(ptr_) ((uintptr_t)(ptr_))
|
||||
|
||||
#endif // QP_PKG_H_
|
||||
|
127
include/qpc.h
127
include/qpc.h
@ -3,17 +3,10 @@
|
||||
// Model: qpc.qm
|
||||
// File: ${include::qpc.h}
|
||||
//
|
||||
// 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) : qpc
|
||||
// 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>
|
||||
//
|
||||
@ -43,26 +35,25 @@
|
||||
#ifndef QPC_H_
|
||||
#define QPC_H_
|
||||
|
||||
//============================================================================
|
||||
#include "qp_port.h" // QP port from the port directory
|
||||
#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
|
||||
#ifdef Q_SPY // software tracing enabled?
|
||||
#include "qs_port.h" // QS/C port from the port directory
|
||||
#else
|
||||
#include "qs_dummy.h" // QS/C dummy (inactive) interface
|
||||
#include "qs_dummy.h" // QS/C dummy interface (inactive)
|
||||
#endif
|
||||
|
||||
//============================================================================
|
||||
#ifndef QP_API_VERSION
|
||||
|
||||
#define QP_API_VERSION 0
|
||||
|
||||
#define QP_API_VERSION 0
|
||||
#endif // #ifndef QP_API_VERSION
|
||||
|
||||
//============================================================================
|
||||
// QP API compatibility layer...
|
||||
//============================================================================
|
||||
#if (QP_API_VERSION < 800)
|
||||
|
||||
#if (QP_API_VERSION < 740)
|
||||
#define QM_SUPER_SUB(host_) 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"
|
||||
|
||||
#ifdef QEVT_DYN_CTOR
|
||||
//! @deprecated #QEVT_DYN_CTOR, please use #QEVT_PAR_INIT
|
||||
@ -98,6 +89,12 @@ typedef char char_t;
|
||||
//! number that **always** evaluates the `expr_` expression.
|
||||
#define Q_ALLEGE_ID(id_, expr_) ((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_) ((void)(expr_))
|
||||
|
||||
#else // QP FuSa Subsystem enabled
|
||||
|
||||
//! @deprecated general purpose assertion with user-specified ID
|
||||
@ -144,78 +141,6 @@ static inline void QF_psInit(
|
||||
//! @deprecated instead use: QASM_IS_IN()
|
||||
#define QHsm_isIn(me_, state_) QASM_IS_IN((QAsm *)(me_), (state_))
|
||||
|
||||
//============================================================================
|
||||
#if (QP_API_VERSION < 691)
|
||||
|
||||
//! @deprecated enable the QS global filter
|
||||
#define QS_FILTER_ON(rec_) QS_GLB_FILTER((rec_))
|
||||
|
||||
//! @deprecated disable the QS global filter
|
||||
#define QS_FILTER_OFF(rec_) QS_GLB_FILTER(-(rec_))
|
||||
|
||||
//! @deprecated enable the QS local filter for SM (state machine) object
|
||||
#define QS_FILTER_SM_OBJ(obj_) ((void)0)
|
||||
|
||||
//! @deprecated enable the QS local filter for AO (active objects)
|
||||
#define QS_FILTER_AO_OBJ(obj_) ((void)0)
|
||||
|
||||
//! @deprecated enable the QS local filter for MP (memory pool) object
|
||||
#define QS_FILTER_MP_OBJ(obj_) ((void)0)
|
||||
|
||||
//! @deprecated enable the QS local filter for EQ (event queue) object
|
||||
#define QS_FILTER_EQ_OBJ(obj_) ((void)0)
|
||||
|
||||
//! @deprecated enable the QS local filter for TE (time event) object
|
||||
#define QS_FILTER_TE_OBJ(obj_) ((void)0)
|
||||
|
||||
#ifdef Q_SPY
|
||||
|
||||
//! @deprecated local Filter for a generic application object `obj_`.
|
||||
#define QS_FILTER_AP_OBJ(obj_) (QS_filt_.loc_AP = (obj_))
|
||||
|
||||
//! @deprecated begin of a user QS record, instead use QS_BEGIN_ID()
|
||||
#define QS_BEGIN(rec_, obj_) \
|
||||
if (((QS_filt_.glb[(uint_fast8_t)(rec_) >> 3U] \
|
||||
& (1U << ((uint_fast8_t)(rec_) & 7U))) != 0U) \
|
||||
&& ((QS_priv_.locFilter_AP == (void *)0) \
|
||||
|| (QS_priv_.locFilter_AP == (obj_)))) \
|
||||
{ \
|
||||
QS_CRIT_STAT \
|
||||
QS_CRIT_ENTRY(); \
|
||||
QS_beginRec_((uint_fast8_t)(rec_)); \
|
||||
QS_TIME_PRE_(); {
|
||||
|
||||
//! @deprecated Output formatted uint32_t to the QS record
|
||||
#define QS_U32_HEX(width_, data_) \
|
||||
(QS_u32_fmt_((uint8_t)(((width_) << 4)) | QS_HEX_FMT, (data_)))
|
||||
|
||||
#else
|
||||
|
||||
#define QS_FILTER_AP_OBJ(obj_) ((void)0)
|
||||
#define QS_BEGIN(rec_, obj_) if (false) {
|
||||
#define QS_U32_HEX(width_, data_) ((void)0)
|
||||
|
||||
#endif
|
||||
|
||||
//============================================================================
|
||||
#if (QP_API_VERSION < 660)
|
||||
|
||||
//! @deprecated casting to QXThreadHandler
|
||||
//! instead use: the new signature of QXThreadHandler and don't cast
|
||||
#define Q_XTHREAD_CAST(handler_) ((QXThreadHandler)(handler_))
|
||||
|
||||
//============================================================================
|
||||
#if (QP_API_VERSION < 580)
|
||||
|
||||
//! @deprecated instead use: QASM_INIT()
|
||||
#define QMSM_INIT(me_, par_, qsId_) QASM_INIT((me_), (par_), (qsId_))
|
||||
|
||||
//! @deprecated instead use: QASM_DISPATCH()
|
||||
#define QMSM_DISPATCH(me_, e_, qsId_) QASM_DISPATCH((me_), (e_), (qsId_))
|
||||
|
||||
#endif // QP_API_VERSION < 580
|
||||
#endif // QP_API_VERSION < 660
|
||||
#endif // QP_API_VERSION < 691
|
||||
#endif // QP_API_VERSION < 700
|
||||
#endif // QP_API_VERSION < 800
|
||||
|
||||
#endif // QPC_H_
|
||||
|
1033
include/qs.h
1033
include/qs.h
File diff suppressed because it is too large
Load Diff
@ -1,45 +1,32 @@
|
||||
//$file${include::qs_dummy.h} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
//============================================================================
|
||||
// QP/C-Spy software tracing target-resident component
|
||||
//
|
||||
// Model: qpc.qm
|
||||
// File: ${include::qs_dummy.h}
|
||||
//
|
||||
// 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) : qpc
|
||||
// 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.h} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
//============================================================================
|
||||
#ifndef QS_DUMMY_H_
|
||||
#define QS_DUMMY_H_
|
||||
|
||||
@ -55,14 +42,11 @@
|
||||
#define QS_EXIT() ((void)0)
|
||||
#define QS_DUMP() ((void)0)
|
||||
#define QS_GLB_FILTER(rec_) ((void)0)
|
||||
#define QS_LOC_FILTER(qsId_) ((void)0)
|
||||
#define QS_LOC_FILTER(qsId_) ((void)0)
|
||||
|
||||
#define QS_GET_BYTE(pByte_) ((uint16_t)0xFFFFU)
|
||||
#define QS_GET_BLOCK(pSize_) ((uint8_t *)0)
|
||||
|
||||
#define QS_BEGIN_ID(rec_, qsId_) if (false) {
|
||||
#define QS_BEGIN_ID(rec_, qsId_) if (false) {
|
||||
#define QS_END() }
|
||||
#define QS_BEGIN_INCRIT(rec_, qsId_) if (false) {
|
||||
#define QS_BEGIN_INCRIT(rec_, qsId_) if (false) {
|
||||
#define QS_END_INCRIT() }
|
||||
|
||||
#define QS_I8(width_, data_) ((void)0)
|
||||
@ -98,37 +82,87 @@
|
||||
|
||||
#define QS_OUTPUT() ((void)0)
|
||||
#define QS_RX_INPUT() ((void)0)
|
||||
#define QS_RX_PUT(b_) ((void)0)
|
||||
#define QS_ONLY(code_) ((void)0)
|
||||
|
||||
//============================================================================
|
||||
// QS API used inside applications
|
||||
#ifndef QS_TIME_SIZE
|
||||
typedef uint32_t QSTimeCtr;
|
||||
#elif (QS_TIME_SIZE == 2U)
|
||||
typedef uint16_t QSTimeCtr;
|
||||
#else
|
||||
typedef uint32_t QSTimeCtr;
|
||||
#endif
|
||||
|
||||
void QS_initBuf(uint8_t * const sto, uint_fast32_t const stoSize);
|
||||
uint16_t QS_getByte(void);
|
||||
uint8_t const *QS_getBlock(uint16_t* const pNbytes);
|
||||
void QS_doOutput(void);
|
||||
uint8_t QS_onStartup(void const* arg);
|
||||
void QS_onCleanup(void);
|
||||
void QS_onFlush(void);
|
||||
QSTimeCtr QS_onGetTime(void);
|
||||
|
||||
void QS_rxInitBuf(uint8_t * const sto, uint16_t const stoSize);
|
||||
void QS_rxParse(void);
|
||||
|
||||
//============================================================================
|
||||
// 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_U8_PRE_(data_) ((void)0)
|
||||
#define QS_2U8_PRE_(data1_, data2_) ((void)0)
|
||||
#define QS_U16_PRE_(data_) ((void)0)
|
||||
#define QS_U32_PRE_(data_) ((void)0)
|
||||
#define QS_TIME_PRE_() ((void)0)
|
||||
#define QS_SIG_PRE_(sig_) ((void)0)
|
||||
#define QS_EVS_PRE_(size_) ((void)0)
|
||||
#define QS_OBJ_PRE_(obj_) ((void)0)
|
||||
#define QS_FUN_PRE_(fun_) ((void)0)
|
||||
#define QS_EQC_PRE_(ctr_) ((void)0)
|
||||
#define QS_MPC_PRE_(ctr_) ((void)0)
|
||||
#define QS_MPS_PRE_(size_) ((void)0)
|
||||
#define QS_TEC_PRE_(ctr_) ((void)0)
|
||||
#define QS_BEGIN_PRE(rec_, qsId_) if (false) {
|
||||
#define QS_END_PRE() }
|
||||
#define QS_U8_PRE(data_) ((void)0)
|
||||
#define QS_2U8_PRE(data1_, data2_) ((void)0)
|
||||
#define QS_U16_PRE(data_) ((void)0)
|
||||
#define QS_U32_PRE(data_) ((void)0)
|
||||
#define QS_TIME_PRE() ((void)0)
|
||||
#define QS_SIG_PRE(sig_) ((void)0)
|
||||
#define QS_EVS_PRE(size_) ((void)0)
|
||||
#define QS_OBJ_PRE(obj_) ((void)0)
|
||||
#define QS_FUN_PRE(fun_) ((void)0)
|
||||
#define QS_EQC_PRE(ctr_) ((void)0)
|
||||
#define QS_MPC_PRE(ctr_) ((void)0)
|
||||
#define QS_MPS_PRE(size_) ((void)0)
|
||||
#define QS_TEC_PRE(ctr_) ((void)0)
|
||||
|
||||
#define QS_CRIT_STAT
|
||||
#define QS_CRIT_ENTRY() ((void)0)
|
||||
#define QS_CRIT_EXIT() ((void)0)
|
||||
#define QS_CRIT_ENTRY() ((void)0)
|
||||
#define QS_CRIT_EXIT() ((void)0)
|
||||
|
||||
#define QS_MEM_SYS() ((void)0)
|
||||
#define QS_MEM_APP() ((void)0)
|
||||
#define QS_MEM_SYS() ((void)0)
|
||||
#define QS_MEM_APP() ((void)0)
|
||||
|
||||
#define QS_TR_CRIT_ENTRY() ((void)0)
|
||||
#define QS_TR_CRIT_EXIT() ((void)0)
|
||||
#define QS_TR_CRIT_ENTRY() ((void)0)
|
||||
#define QS_TR_CRIT_EXIT() ((void)0)
|
||||
#define QS_TR_ISR_ENTRY(isrnest_, prio_) ((void)0)
|
||||
#define QS_TR_ISR_EXIT(isrnest_, prio_) ((void)0)
|
||||
#endif // QP_IMPL
|
||||
|
176
include/qs_pkg.h
176
include/qs_pkg.h
@ -1,176 +0,0 @@
|
||||
//$file${include::qs_pkg.h} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
//
|
||||
// Model: qpc.qm
|
||||
// File: ${include::qs_pkg.h}
|
||||
//
|
||||
// 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) : qpc
|
||||
// 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.h} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
#ifndef QS_PKG_H_
|
||||
#define QS_PKG_H_
|
||||
|
||||
//============================================================================
|
||||
//! @cond INTERNAL
|
||||
|
||||
//! QS received record types (RX channel)
|
||||
enum QSpyRxRecords {
|
||||
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
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
#define QS_FRAME 0x7EU
|
||||
#define QS_ESC 0x7DU
|
||||
#define QS_ESC_XOR 0x20U
|
||||
#define QS_GOOD_CHKSUM 0xFFU
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
#define QS_BEGIN_PRE_(rec_, qsId_) \
|
||||
if (QS_GLB_CHECK_(rec_) && QS_LOC_CHECK_(qsId_)) { \
|
||||
QS_beginRec_((uint_fast8_t)(rec_));
|
||||
#define QS_END_PRE_() QS_endRec_(); }
|
||||
|
||||
#define QS_U8_PRE_(data_) (QS_u8_raw_((uint8_t)(data_)))
|
||||
#define QS_2U8_PRE_(data1_, data2_) \
|
||||
(QS_2u8_raw_((uint8_t)(data1_), (uint8_t)(data2_)))
|
||||
#define QS_U16_PRE_(data_) (QS_u16_raw_((uint16_t)(data_)))
|
||||
#define QS_U32_PRE_(data_) (QS_u32_raw_((uint32_t)(data_)))
|
||||
#define QS_STR_PRE_(msg_) (QS_str_raw_((msg_)))
|
||||
#define QS_OBJ_PRE_(obj_) (QS_obj_raw_(obj_))
|
||||
|
||||
#if (!defined Q_SIGNAL_SIZE || (Q_SIGNAL_SIZE == 1U))
|
||||
#define QS_SIG_PRE_(sig_) (QS_u8_raw_((uint8_t)sig_))
|
||||
#elif (Q_SIGNAL_SIZE == 2U)
|
||||
#define QS_SIG_PRE_(sig_) (QS_u16_raw_((uint16_t)sig_))
|
||||
#elif (Q_SIGNAL_SIZE == 4U)
|
||||
#define QS_SIG_PRE_(sig_) (QS_u32_raw_((uint32_t)sig_))
|
||||
#endif
|
||||
|
||||
#if (!defined QS_FUN_PTR_SIZE || (QS_FUN_PTR_SIZE == 2U))
|
||||
#define QS_FUN_PRE_(fun_) (QS_u16_raw_((uint16_t)(fun_)))
|
||||
#elif (QS_FUN_PTR_SIZE == 4U)
|
||||
#define QS_FUN_PRE_(fun_) (QS_u32_raw_((uint32_t)(fun_)))
|
||||
#elif (QS_FUN_PTR_SIZE == 8U)
|
||||
#define QS_FUN_PRE_(fun_) (QS_u64_raw_((uint64_t)(fun_)))
|
||||
#else
|
||||
#define QS_FUN_PRE_(fun_) (QS_u32_raw_((uint32_t)(fun_)))
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
#if (!defined QF_EQUEUE_CTR_SIZE || (QF_EQUEUE_CTR_SIZE == 1U))
|
||||
#define QS_EQC_PRE_(ctr_) QS_u8_raw_((uint8_t)(ctr_))
|
||||
#elif (QF_EQUEUE_CTR_SIZE == 2U)
|
||||
#define QS_EQC_PRE_(ctr_) QS_u16_raw_((uint16_t)(ctr_))
|
||||
#elif (QF_EQUEUE_CTR_SIZE == 4U)
|
||||
#define QS_EQC_PRE_(ctr_) QS_u32_raw_((uint32_t)(ctr_))
|
||||
#endif
|
||||
|
||||
#if (!defined QF_EVENT_SIZ_SIZE || (QF_EVENT_SIZ_SIZE == 1U))
|
||||
#define QS_EVS_PRE_(size_) QS_u8_raw_((uint8_t)(size_))
|
||||
#elif (QF_EVENT_SIZ_SIZE == 2U)
|
||||
#define QS_EVS_PRE_(size_) QS_u16_raw_((uint16_t)(size_))
|
||||
#elif (QF_EVENT_SIZ_SIZE == 4U)
|
||||
#define QS_EVS_PRE_(size_) QS_u32_raw_((uint32_t)(size_))
|
||||
#endif
|
||||
|
||||
#if (!defined QF_MPOOL_SIZ_SIZE || (QF_MPOOL_SIZ_SIZE == 1U))
|
||||
#define QS_MPS_PRE_(size_) QS_u8_raw_((uint8_t)(size_))
|
||||
#elif (QF_MPOOL_SIZ_SIZE == 2U)
|
||||
#define QS_MPS_PRE_(size_) QS_u16_raw_((uint16_t)(size_))
|
||||
#elif (QF_MPOOL_SIZ_SIZE == 4U)
|
||||
#define QS_MPS_PRE_(size_) QS_u32_raw_((uint32_t)(size_))
|
||||
#endif
|
||||
|
||||
#if (!defined QF_MPOOL_CTR_SIZE || (QF_MPOOL_CTR_SIZE == 1U))
|
||||
#define QS_MPC_PRE_(ctr_) QS_u8_raw_((uint8_t)(ctr_))
|
||||
#elif (QF_MPOOL_CTR_SIZE == 2U)
|
||||
#define QS_MPC_PRE_(ctr_) QS_u16_raw_((uint16_t)(ctr_))
|
||||
#elif (QF_MPOOL_CTR_SIZE == 4U)
|
||||
#define QS_MPC_PRE_(ctr_) QS_u32_raw_((uint16_t)(ctr_))
|
||||
#endif
|
||||
|
||||
#if (!defined QF_TIMEEVT_CTR_SIZE || (QF_TIMEEVT_CTR_SIZE == 1U))
|
||||
#define QS_TEC_PRE_(ctr_) QS_u8_raw_((uint8_t)(ctr_))
|
||||
#elif (QF_TIMEEVT_CTR_SIZE == 2U)
|
||||
#define QS_TEC_PRE_(ctr_) QS_u16_raw_((uint16_t)(ctr_))
|
||||
#elif (QF_TIMEEVT_CTR_SIZE == 4U)
|
||||
#define QS_TEC_PRE_(ctr_) QS_u32_raw_((uint32_t)(ctr_))
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
#define QS_INSERT_BYTE_(b_) \
|
||||
buf[head] = (b_); \
|
||||
++head; \
|
||||
if (head == end) { \
|
||||
head = 0U; \
|
||||
}
|
||||
|
||||
#define QS_INSERT_ESC_BYTE_(b_) \
|
||||
chksum = (uint8_t)(chksum + (b_)); \
|
||||
if (((b_) != QS_FRAME) && ((b_) != QS_ESC)) { \
|
||||
QS_INSERT_BYTE_(b_) \
|
||||
} \
|
||||
else { \
|
||||
QS_INSERT_BYTE_(QS_ESC) \
|
||||
QS_INSERT_BYTE_((uint8_t)((b_) ^ QS_ESC_XOR))\
|
||||
++QS_priv_.used; \
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
#if (defined Q_UTEST) && (Q_UTEST != 0)
|
||||
void QS_processTestEvts_(void);
|
||||
#endif // Q_UTEST != 0
|
||||
|
||||
//! @endcond
|
||||
//============================================================================
|
||||
|
||||
#endif // QS_PKG_H_
|
@ -3,17 +3,10 @@
|
||||
// Model: qpc.qm
|
||||
// File: ${include::qsafe.h}
|
||||
//
|
||||
// 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) : qpc
|
||||
// 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: qpc.qm
|
||||
// File: ${include::qstamp.h}
|
||||
//
|
||||
// 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) : qpc
|
||||
// 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>
|
||||
//
|
||||
|
35
include/qv.h
35
include/qv.h
@ -3,17 +3,10 @@
|
||||
// Model: qpc.qm
|
||||
// File: ${include::qv.h}
|
||||
//
|
||||
// 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) : qpc
|
||||
// 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>
|
||||
//
|
||||
@ -111,8 +103,7 @@ void QV_onIdle(void);
|
||||
#define QF_SCHED_UNLOCK_() ((void)0)
|
||||
|
||||
//${QV-impl::QACTIVE_EQUEUE_WAIT_} ...........................................
|
||||
#define QACTIVE_EQUEUE_WAIT_(me_) \
|
||||
Q_ASSERT_INCRIT(310, (me_)->eQueue.frontEvt != (QEvt *)0)
|
||||
#define QACTIVE_EQUEUE_WAIT_(me_) ((void)0)
|
||||
|
||||
//${QV-impl::QACTIVE_EQUEUE_SIGNAL_} .........................................
|
||||
#ifndef Q_UNSAFE
|
||||
|
405
include/qxk.h
405
include/qxk.h
@ -1,405 +0,0 @@
|
||||
//$file${include::qxk.h} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
//
|
||||
// Model: qpc.qm
|
||||
// File: ${include::qxk.h}
|
||||
//
|
||||
// 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) : qpc
|
||||
// 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.h} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
#ifndef QXK_H_
|
||||
#define QXK_H_
|
||||
|
||||
//$declare${QXK::QXK} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
|
||||
//${QXK::QXK} ................................................................
|
||||
//! @class QXK
|
||||
typedef struct QXK {
|
||||
//! @cond INTERNAL
|
||||
uint8_t dummy;
|
||||
//! @endcond
|
||||
} QXK;
|
||||
//$enddecl${QXK::QXK} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
//$declare${QXK::QSchedStatus} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
|
||||
//${QXK::QSchedStatus} .......................................................
|
||||
typedef uint_fast16_t QSchedStatus;
|
||||
//$enddecl${QXK::QSchedStatus} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
//$declare${QXK::QXTHREAD_NO_TIMEOUT} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
|
||||
//${QXK::QXTHREAD_NO_TIMEOUT} ................................................
|
||||
#define QXTHREAD_NO_TIMEOUT ((QTimeEvtCtr)0)
|
||||
//$enddecl${QXK::QXTHREAD_NO_TIMEOUT} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
//$declare${QXK::QXK-base} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
|
||||
//${QXK::QXK-base::Attr} .....................................................
|
||||
//! @class QXK_Attr
|
||||
typedef struct {
|
||||
// private:
|
||||
|
||||
//! @memberof QXK_Attr
|
||||
struct QActive * volatile curr;
|
||||
|
||||
//! @memberof QXK_Attr
|
||||
struct QActive * volatile next;
|
||||
|
||||
//! @memberof QXK_Attr
|
||||
struct QActive * volatile prev;
|
||||
|
||||
//! @memberof QXK_Attr
|
||||
uint_fast8_t volatile actPrio;
|
||||
|
||||
//! @memberof QXK_Attr
|
||||
uint_fast8_t volatile lockCeil;
|
||||
|
||||
//! @memberof QXK_Attr
|
||||
uint_fast8_t volatile lockHolder;
|
||||
|
||||
//! @memberof QXK_Attr
|
||||
QPSet readySet;
|
||||
|
||||
#ifndef Q_UNSAFE
|
||||
//! @memberof QXK_Attr
|
||||
QPSet readySet_dis;
|
||||
#endif // ndef Q_UNSAFE
|
||||
} QXK_Attr;
|
||||
|
||||
//${QXK::QXK-base::priv_} ....................................................
|
||||
//! @static @private @memberof QXK
|
||||
extern QXK_Attr QXK_priv_;
|
||||
|
||||
//${QXK::QXK-base::onIdle} ...................................................
|
||||
//! @static @public @memberof QXK
|
||||
void QXK_onIdle(void);
|
||||
|
||||
//${QXK::QXK-base::schedLock} ................................................
|
||||
//! @static @public @memberof QXK
|
||||
QSchedStatus QXK_schedLock(uint_fast8_t const ceiling);
|
||||
|
||||
//${QXK::QXK-base::schedUnlock} ..............................................
|
||||
//! @static @public @memberof QXK
|
||||
void QXK_schedUnlock(QSchedStatus const stat);
|
||||
|
||||
//${QXK::QXK-base::current} ..................................................
|
||||
//! @static @public @memberof QXK
|
||||
QActive * QXK_current(void);
|
||||
|
||||
//${QXK::QXK-base::sched_} ...................................................
|
||||
//! @static @private @memberof QXK
|
||||
uint_fast8_t QXK_sched_(void);
|
||||
|
||||
//${QXK::QXK-base::activate_} ................................................
|
||||
//! @static @private @memberof QXK
|
||||
void QXK_activate_(void);
|
||||
|
||||
//${QXK::QXK-base::contextSw_} ...............................................
|
||||
//! @static @public @memberof QXK
|
||||
void QXK_contextSw_(QActive * const next);
|
||||
|
||||
//${QXK::QXK-base::threadExit_} ..............................................
|
||||
//! @static @private @memberof QXK
|
||||
void QXK_threadExit_(void);
|
||||
//$enddecl${QXK::QXK-base} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
//$declare${QXK::QXThread} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
|
||||
//${QXK::QXThread} ...........................................................
|
||||
//! @class QXThread
|
||||
//! @extends QActive
|
||||
typedef struct QXThread {
|
||||
// protected:
|
||||
QActive super;
|
||||
|
||||
// private:
|
||||
|
||||
//! @private @memberof QXThread
|
||||
QTimeEvt timeEvt;
|
||||
} QXThread;
|
||||
|
||||
//! @static @private @memberof QXThread
|
||||
//! dummy static member to force QM to generate 'struct QXThread'
|
||||
extern QXThread const * QXThread_dummy;
|
||||
|
||||
// public:
|
||||
|
||||
//! @public @memberof QXThread
|
||||
void QXThread_ctor(QXThread * const me,
|
||||
QXThreadHandler const handler,
|
||||
uint_fast8_t const tickRate);
|
||||
|
||||
//! @public @memberof QXThread
|
||||
static inline void QXThread_start(QXThread * const me,
|
||||
QPrioSpec const prioSpec,
|
||||
QEvt const * * const qSto,
|
||||
uint_fast16_t const qLen,
|
||||
void * const stkSto,
|
||||
uint_fast16_t const stkSize,
|
||||
void const * const par)
|
||||
{
|
||||
QActive_start(&me->super, prioSpec, qSto, qLen, stkSto, stkSize, par);
|
||||
}
|
||||
|
||||
//! @public @memberof QXThread
|
||||
bool QXThread_delay(QTimeEvtCtr const nTicks);
|
||||
|
||||
//! @public @memberof QXThread
|
||||
bool QXThread_delayCancel(QXThread * const me);
|
||||
|
||||
//! @static @public @memberof QXThread
|
||||
QEvt const * QXThread_queueGet(QTimeEvtCtr const nTicks);
|
||||
|
||||
// private:
|
||||
|
||||
//! @private @memberof QXThread
|
||||
void QXThread_block_(QXThread const * const me);
|
||||
|
||||
//! @private @memberof QXThread
|
||||
void QXThread_unblock_(QXThread const * const me);
|
||||
|
||||
//! @private @memberof QXThread
|
||||
void QXThread_timeout_(QActive * const act);
|
||||
|
||||
//! @private @memberof QXThread
|
||||
void QXThread_teArm_(QXThread * const me,
|
||||
enum_t const sig,
|
||||
QTimeEvtCtr const nTicks);
|
||||
|
||||
//! @private @memberof QXThread
|
||||
bool QXThread_teDisarm_(QXThread * const me);
|
||||
|
||||
// public:
|
||||
|
||||
//! @private @memberof QXThread
|
||||
void QXThread_stackInit_(
|
||||
QActive * const me,
|
||||
QXThreadHandler const handler,
|
||||
void * const stkSto,
|
||||
uint_fast16_t const stkSize);
|
||||
//$enddecl${QXK::QXThread} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
//$declare${QXK::QXSemaphore} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
|
||||
//${QXK::QXSemaphore} ........................................................
|
||||
//! @class QXSemaphore
|
||||
typedef struct {
|
||||
// private:
|
||||
|
||||
//! @private @memberof QXSemaphore
|
||||
QPSet waitSet;
|
||||
|
||||
//! @private @memberof QXSemaphore
|
||||
uint8_t volatile count;
|
||||
|
||||
//! @private @memberof QXSemaphore
|
||||
uint8_t max_count;
|
||||
} QXSemaphore;
|
||||
|
||||
// public:
|
||||
|
||||
//! @public @memberof QXSemaphore
|
||||
void QXSemaphore_init(QXSemaphore * const me,
|
||||
uint_fast8_t const count,
|
||||
uint_fast8_t const max_count);
|
||||
|
||||
//! @public @memberof QXSemaphore
|
||||
bool QXSemaphore_wait(QXSemaphore * const me,
|
||||
QTimeEvtCtr const nTicks);
|
||||
|
||||
//! @public @memberof QXSemaphore
|
||||
bool QXSemaphore_tryWait(QXSemaphore * const me);
|
||||
|
||||
//! @public @memberof QXSemaphore
|
||||
bool QXSemaphore_signal(QXSemaphore * const me);
|
||||
//$enddecl${QXK::QXSemaphore} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
//$declare${QXK::QXMutex} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
|
||||
//${QXK::QXMutex} ............................................................
|
||||
//! @class QXMutex
|
||||
typedef struct {
|
||||
// private:
|
||||
|
||||
//! @private @memberof QXMutex
|
||||
QActive ao;
|
||||
|
||||
//! @private @memberof QXMutex
|
||||
QPSet waitSet;
|
||||
} QXMutex;
|
||||
|
||||
// public:
|
||||
|
||||
//! @public @memberof QXMutex
|
||||
void QXMutex_init(QXMutex * const me,
|
||||
QPrioSpec const prioSpec);
|
||||
|
||||
//! @public @memberof QXMutex
|
||||
bool QXMutex_lock(QXMutex * const me,
|
||||
QTimeEvtCtr const nTicks);
|
||||
|
||||
//! @public @memberof QXMutex
|
||||
bool QXMutex_tryLock(QXMutex * const me);
|
||||
|
||||
//! @public @memberof QXMutex
|
||||
void QXMutex_unlock(QXMutex * const me);
|
||||
//$enddecl${QXK::QXMutex} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
//$declare${QXK-macros} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
||||
|
||||
//${QXK-macros::QXTHREAD_POST_X} .............................................
|
||||
#define QXTHREAD_POST_X(me_, e_, margin_, sender_) \
|
||||
QACTIVE_POST_X(&(me_)->super, (e_), (margin_), (sender_))
|
||||
//$enddecl${QXK-macros} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
//============================================================================
|
||||
// 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_} ..........................................
|
||||
#define QACTIVE_EQUEUE_WAIT_(me_) \
|
||||
Q_ASSERT_INCRIT(310, (me_)->eQueue.frontEvt != (QEvt *)0)
|
||||
|
||||
//${QXK-impl::QACTIVE_EQUEUE_SIGNAL_} ........................................
|
||||
#ifndef Q_UNSAFE
|
||||
#define QACTIVE_EQUEUE_SIGNAL_(me_) do { \
|
||||
QPSet_insert(&QXK_priv_.readySet, (uint_fast8_t)(me_)->prio); \
|
||||
QPSet_update_(&QXK_priv_.readySet, &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
|
||||
#define QACTIVE_EQUEUE_SIGNAL_(me_) do { \
|
||||
QPSet_insert(&QXK_priv_.readySet, (uint_fast8_t)(me_)->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->super.temp.obj == QXK_PTR_CAST_(QMState*, &me->eQueue)) { \
|
||||
(void)QXThread_teDisarm_(QXTHREAD_CAST_(me)); \
|
||||
QPSet_insert(&QXK_priv_.readySet, (uint_fast8_t)me->prio); \
|
||||
QPSet_update_(&QXK_priv_.readySet, &QXK_priv_.readySet_dis); \
|
||||
if (!QXK_ISR_CONTEXT_()) { \
|
||||
(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->super.temp.obj == QXK_PTR_CAST_(QMState*, &me->eQueue)) { \
|
||||
(void)QXThread_teDisarm_(QXTHREAD_CAST_(me)); \
|
||||
QPSet_insert(&QXK_priv_.readySet, (uint_fast8_t)me->prio); \
|
||||
if (!QXK_ISR_CONTEXT_()) { \
|
||||
(void)QXK_sched_(); \
|
||||
} \
|
||||
} \
|
||||
} while (false)
|
||||
#endif // def Q_UNSAFE
|
||||
|
||||
//${QXK-impl::QXK_PTR_CAST_} .................................................
|
||||
#define QXK_PTR_CAST_(type_, ptr_) ((type_)(ptr_))
|
||||
|
||||
//${QXK-impl::QXTHREAD_CAST_} ................................................
|
||||
#define QXTHREAD_CAST_(ptr_) ((QXThread *)(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_) \
|
||||
(QMPool_init(&(p_), (poolSto_), (poolSize_), (evtSize_)))
|
||||
|
||||
//${QF_EPOOL-impl::QF_EPOOL_EVENT_SIZE_} .....................................
|
||||
#define QF_EPOOL_EVENT_SIZE_(p_) ((uint_fast16_t)(p_).blockSize)
|
||||
|
||||
//${QF_EPOOL-impl::QF_EPOOL_GET_} ............................................
|
||||
#define QF_EPOOL_GET_(p_, e_, m_, qsId_) \
|
||||
((e_) = (QEvt *)QMPool_get(&(p_), (m_), (qsId_)))
|
||||
|
||||
//${QF_EPOOL-impl::QF_EPOOL_PUT_} ............................................
|
||||
#define QF_EPOOL_PUT_(p_, e_, qsId_) \
|
||||
(QMPool_put(&(p_), (e_), (qsId_)))
|
||||
//$enddecl${QF_EPOOL-impl} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
enum QXK_TimeoutSigs {
|
||||
QXK_DELAY_SIG = 1,
|
||||
QXK_TIMEOUT_SIG
|
||||
};
|
||||
|
||||
#endif // QP_IMPL
|
||||
|
||||
#endif // QXK_H_
|
@ -14,3 +14,7 @@ else()
|
||||
endif()
|
||||
|
||||
add_subdirectory(${PORT_DIR})
|
||||
if(NOT QPC_CFG_QPCONFIG_H_INCLUDE_PATH)
|
||||
set(QPC_CFG_QPCONFIG_H_INCLUDE_PATH config)
|
||||
endif()
|
||||
target_include_directories(qpc PUBLIC ${QPC_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**:
|
||||
|
||||
```
|
||||
qpc
|
||||
|
|
||||
\---ports
|
||||
+---arm-cm
|
||||
| +---qxk
|
||||
| | +---armclang
|
||||
| | | qxk_port.c
|
||||
| | | qp_port.h
|
||||
| | | qs_port.h
|
||||
| | |
|
||||
| | +---config
|
||||
| | | qp_config.h
|
||||
| | |
|
||||
| | +---gnu
|
||||
| | | qxk_port.c
|
||||
| | | qp_port.h
|
||||
| | | qs_port.h
|
||||
| | |
|
||||
| | \---iar
|
||||
| | qxk_port.c
|
||||
| | qp_port.h
|
||||
| | qs_port.h
|
||||
| |
|
||||
| \---qutest
|
||||
| qp_port.h
|
||||
| qs_port.h
|
||||
|
|
||||
+---posix-qutest
|
||||
| qp_port.h
|
||||
| qs_port.h
|
||||
| qutest_port.c
|
||||
| safe_std.h
|
||||
|
|
||||
\---win32-qutest
|
||||
qp_port.h
|
||||
qs_port.h
|
||||
qutest_port.c
|
||||
safe_std.h
|
||||
```
|
||||
|
||||
> 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 qpc_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
|
||||
@ -76,14 +75,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
|
||||
@ -105,13 +107,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
|
||||
@ -136,6 +141,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
|
||||
@ -143,11 +149,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
|
||||
@ -169,6 +174,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
|
||||
@ -176,11 +182,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
|
||||
@ -217,8 +222,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...
|
||||
@ -240,7 +245,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
|
||||
|
||||
@ -253,17 +262,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
|
||||
@ -324,84 +330,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,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-02
|
||||
//! @version Last updated for: @ref qpc_7_3_1
|
||||
//! @date Last updated on: 2024-09-30
|
||||
//! @version Last updated for: @ref qpc_8_0_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QP/C port to ARM Cortex-M, preemptive QK kernel, ARM-CLANG
|
||||
@ -36,12 +35,9 @@
|
||||
#ifndef QP_PORT_H_
|
||||
#define QP_PORT_H_
|
||||
|
||||
#include <stdint.h> // Exact-width types. WG14/N843 C99 Standard
|
||||
#include <stdbool.h> // Boolean type. WG14/N843 C99 Standard
|
||||
|
||||
#ifdef QP_CONFIG
|
||||
#include "qp_config.h" // external QP configuration
|
||||
#endif
|
||||
#include <stdint.h> // Exact-width types. WG14/N843 C99 Standard
|
||||
#include <stdbool.h> // Boolean type. WG14/N843 C99 Standard
|
||||
#include "qp_config.h" // QP configuration from the application
|
||||
|
||||
// no-return function specifier (C11 Standard)
|
||||
#define Q_NORETURN _Noreturn void
|
||||
@ -157,7 +153,7 @@ static inline uint32_t QK_get_IPSR(void) {
|
||||
#endif // ARMv6-M
|
||||
|
||||
// initialization of the QK kernel
|
||||
#define QK_INIT() QK_init()
|
||||
#define QK_INIT() QK_init()
|
||||
void QK_init(void);
|
||||
void QK_thread_ret(void);
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
// <info@state-machine.com>
|
||||
//============================================================================
|
||||
//! @date Last updated on: 2024-06-06
|
||||
//! @version Last updated for: @ref qpc_7_4_0
|
||||
//! @version Last updated for: @ref qpc_8_0_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QS/C port to a 32-bit CPU and a generic C99 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_H_
|
||||
@ -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
|
||||
@ -158,7 +149,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
|
||||
@ -244,8 +234,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 qpc_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
|
||||
@ -76,14 +75,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
|
||||
@ -105,13 +107,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
|
||||
@ -136,6 +141,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
|
||||
@ -143,11 +149,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
|
||||
@ -169,6 +174,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
|
||||
@ -176,11 +182,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
|
||||
@ -217,8 +222,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...
|
||||
@ -240,7 +245,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
|
||||
|
||||
@ -253,17 +262,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
|
||||
@ -281,7 +287,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"
|
||||
@ -329,84 +335,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,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 qpc_7_3_1
|
||||
//! @date Last updated on: 2024-09-30
|
||||
//! @version Last updated for: @ref qpc_8_0_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QP/C port to ARM Cortex-M, preemptive QK kernel, GNU-ARM
|
||||
@ -36,12 +35,9 @@
|
||||
#ifndef QP_PORT_H_
|
||||
#define QP_PORT_H_
|
||||
|
||||
#include <stdint.h> // Exact-width types. WG14/N843 C99 Standard
|
||||
#include <stdbool.h> // Boolean type. WG14/N843 C99 Standard
|
||||
|
||||
#ifdef QP_CONFIG
|
||||
#include "qp_config.h" // external QP configuration
|
||||
#endif
|
||||
#include <stdint.h> // Exact-width types. WG14/N843 C99 Standard
|
||||
#include <stdbool.h> // Boolean type. WG14/N843 C99 Standard
|
||||
#include "qp_config.h" // QP configuration from the application
|
||||
|
||||
// no-return function specifier (C11 Standard)
|
||||
#define Q_NORETURN _Noreturn void
|
||||
@ -222,8 +218,6 @@ extern int32_t volatile QF_int_lock_nest_;
|
||||
// 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_H_
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
// <info@state-machine.com>
|
||||
//============================================================================
|
||||
//! @date Last updated on: 2024-06-06
|
||||
//! @version Last updated for: @ref qpc_7_4_0
|
||||
//! @version Last updated for: @ref qpc_8_0_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QS/C port to a 32-bit CPU and a generic C99 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 qpc_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
|
||||
@ -80,13 +79,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?
|
||||
@ -109,12 +111,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?
|
||||
@ -140,6 +145,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
|
||||
@ -147,10 +153,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?
|
||||
@ -173,6 +178,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
|
||||
@ -180,10 +186,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?
|
||||
@ -221,8 +226,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...
|
||||
@ -244,7 +249,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
|
||||
|
||||
@ -257,17 +266,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
|
||||
@ -328,88 +334,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,
|
||||
@ -418,7 +473,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"
|
||||
@ -438,7 +493,7 @@ __asm volatile (
|
||||
" ADDS %[n],%[n],#4 \n"
|
||||
" MOVS r0,r2 \n"
|
||||
"QF_qlog2_3:" : [n]"=r"(n)
|
||||
);
|
||||
);
|
||||
return n + log2LUT[x];
|
||||
}
|
||||
|
||||
|
@ -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 qpc_7_3_1
|
||||
//! @date Last updated on: 2024-09-30
|
||||
//! @version Last updated for: @ref qpc_8_0_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QP/C port to ARM Cortex-M, preemptive QK kernel, IAR-ARM
|
||||
@ -36,13 +35,10 @@
|
||||
#ifndef QP_PORT_H_
|
||||
#define QP_PORT_H_
|
||||
|
||||
#include <stdint.h> // Exact-width types. WG14/N843 C99 Standard
|
||||
#include <stdbool.h> // Boolean type. WG14/N843 C99 Standard
|
||||
#include <stdint.h> // Exact-width types. WG14/N843 C99 Standard
|
||||
#include <stdbool.h> // Boolean type. WG14/N843 C99 Standard
|
||||
#include <intrinsics.h> // IAR intrinsic functions
|
||||
|
||||
#ifdef QP_CONFIG
|
||||
#include "qp_config.h" // external QP configuration
|
||||
#endif
|
||||
#include "qp_config.h" // QP configuration from the application
|
||||
|
||||
// no-return function specifier (C11 Standard)
|
||||
#define Q_NORETURN _Noreturn void
|
||||
@ -216,8 +212,6 @@ extern int32_t volatile QF_int_lock_nest_;
|
||||
// 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_H_
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
// <info@state-machine.com>
|
||||
//============================================================================
|
||||
//! @date Last updated on: 2024-06-06
|
||||
//! @version Last updated for: @ref qpc_7_4_0
|
||||
//! @version Last updated for: @ref qpc_8_0_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QS/C port to a 32-bit CPU and a generic C99 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 qpc_7_3_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QP/C "port" for QUTEST unit test harness, generic C99
|
||||
|
||||
#ifndef QP_PORT_H_
|
||||
#define QP_PORT_H_
|
||||
|
||||
#include <stdint.h> // Exact-width types. WG14/N843 C99 Standard
|
||||
#include <stdbool.h> // Boolean type. WG14/N843 C99 Standard
|
||||
|
||||
#ifdef QP_CONFIG
|
||||
#include "qp_config.h" // external QP configuration
|
||||
#endif
|
||||
|
||||
// no-return function specifier (C11 Standard)
|
||||
#define Q_NORETURN _Noreturn void
|
||||
|
||||
// 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() (++QS_tstPriv_.intLock)
|
||||
#define QF_INT_ENABLE() (--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.h" // QUTest port uses QEQueue event-queue
|
||||
#include "qmpool.h" // QUTest port uses QMPool memory-pool
|
||||
#include "qp.h" // 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) ((void)0)
|
||||
#define QF_SCHED_UNLOCK_() ((void)0)
|
||||
|
||||
// native event queue operations
|
||||
#define QACTIVE_EQUEUE_WAIT_(me_) \
|
||||
Q_ASSERT_INCRIT(310, (me_)->eQueue.frontEvt != (QEvt *)0)
|
||||
|
||||
#ifndef Q_UNSAFE
|
||||
#define QACTIVE_EQUEUE_SIGNAL_(me_) \
|
||||
QPSet_insert(&QS_tstPriv_.readySet, (uint_fast8_t)(me_)->prio); \
|
||||
QPSet_update_(&QS_tstPriv_.readySet, &QS_tstPriv_.readySet_dis)
|
||||
#else
|
||||
#define QACTIVE_EQUEUE_SIGNAL_(me_) \
|
||||
QPSet_insert(&QF_readySet_, (uint_fast8_t)(me_)->prio)
|
||||
#endif
|
||||
|
||||
// native QF event pool operations
|
||||
#define QF_EPOOL_TYPE_ QMPool
|
||||
#define QF_EPOOL_INIT_(p_, poolSto_, poolSize_, evtSize_) \
|
||||
(QMPool_init(&(p_), (poolSto_), (poolSize_), (evtSize_)))
|
||||
#define QF_EPOOL_EVENT_SIZE_(p_) ((uint_fast16_t)(p_).blockSize)
|
||||
#define QF_EPOOL_GET_(p_, e_, m_, qsId_) \
|
||||
((e_) = (QEvt *)QMPool_get(&(p_), (m_), (qsId_)))
|
||||
#define QF_EPOOL_PUT_(p_, e_, qsId_) \
|
||||
(QMPool_put(&(p_), (e_), (qsId_)))
|
||||
|
||||
#endif // QP_IMPL
|
||||
|
||||
#endif // QP_PORT_H_
|
||||
|
@ -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 qpc_7_4_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QS/C port to a 32-bit CPU and a generic C99 compiler.
|
||||
|
||||
#ifndef QS_PORT_H_
|
||||
#define QS_PORT_H_
|
||||
|
||||
// object pointer size in bytes
|
||||
#define QS_OBJ_PTR_SIZE 4U
|
||||
|
||||
// function pointer size in bytes
|
||||
#define QS_FUN_PTR_SIZE 4U
|
||||
|
||||
//============================================================================
|
||||
// NOTE: QS might be used with or without other QP components, in which
|
||||
// case the separate definitions of the macros QF_CRIT_STAT, QF_CRIT_ENTRY(),
|
||||
// and QF_CRIT_EXIT() are needed. In this port QS is configured to be used
|
||||
// with the other QP component, by simply including "qp_port.h"
|
||||
// *before* "qs.h".
|
||||
#ifndef QP_PORT_H_
|
||||
#include "qp_port.h" // use QS with QP
|
||||
#endif
|
||||
|
||||
#include "qs.h" // QS platform-independent public interface
|
||||
|
||||
#endif // QS_PORT_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: 2023-12-03
|
||||
//! @version Last updated for: @ref qpc_7_3_1
|
||||
//! @date Last updated on: 2024-09-30
|
||||
//! @version Last updated for: @ref qpc_8_0_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QP/C port to ARM Cortex-M, cooperative QV kernel, ARM-CLANG
|
||||
@ -36,12 +35,9 @@
|
||||
#ifndef QP_PORT_H_
|
||||
#define QP_PORT_H_
|
||||
|
||||
#include <stdint.h> // Exact-width types. WG14/N843 C99 Standard
|
||||
#include <stdbool.h> // Boolean type. WG14/N843 C99 Standard
|
||||
|
||||
#ifdef QP_CONFIG
|
||||
#include "qp_config.h" // external QP configuration
|
||||
#endif
|
||||
#include <stdint.h> // Exact-width types. WG14/N843 C99 Standard
|
||||
#include <stdbool.h> // Boolean type. WG14/N843 C99 Standard
|
||||
#include "qp_config.h" // QP configuration from the application
|
||||
|
||||
// no-return function specifier (C11 Standard)
|
||||
#define Q_NORETURN _Noreturn void
|
||||
@ -114,10 +110,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 +120,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)
|
||||
|
||||
@ -206,8 +200,6 @@ extern int32_t volatile QF_int_lock_nest_;
|
||||
// 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_H_
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
// <info@state-machine.com>
|
||||
//============================================================================
|
||||
//! @date Last updated on: 2024-06-06
|
||||
//! @version Last updated for: @ref qpc_7_4_0
|
||||
//! @version Last updated for: @ref qpc_8_0_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QS/C port to a 32-bit CPU and a generic C99 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 qpc_7_3_1
|
||||
//! @date Last updated on: 2024-09-30
|
||||
//! @version Last updated for: @ref qpc_8_0_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QV/C port to ARM Cortex-M, ARM-CLANG
|
||||
@ -58,20 +57,24 @@
|
||||
// For best performance, these functions are implemented in assembly,
|
||||
// but they can be implemented in C as well.
|
||||
|
||||
|
||||
//int32_t volatile QF_int_lock_nest_; // not used
|
||||
extern char const QF_port_module_[];
|
||||
char const QF_port_module_[] = "qv_port";
|
||||
|
||||
//............................................................................
|
||||
// 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
|
||||
@ -93,13 +96,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
|
||||
@ -124,6 +130,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
|
||||
@ -131,11 +138,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
|
||||
@ -157,6 +163,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
|
||||
@ -164,11 +171,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
|
||||
@ -205,8 +211,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_H_
|
||||
@ -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
|
||||
@ -158,7 +149,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,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-02
|
||||
//! @version Last updated for: @ref qpc_7_3_1
|
||||
//! @date Last updated on: 2024-09-30
|
||||
//! @version Last updated for: @ref qpc_8_0_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QP/C port to ARM Cortex-M, cooperative QV kernel, GNU-ARM
|
||||
@ -36,12 +35,9 @@
|
||||
#ifndef QP_PORT_H_
|
||||
#define QP_PORT_H_
|
||||
|
||||
#include <stdint.h> // Exact-width types. WG14/N843 C99 Standard
|
||||
#include <stdbool.h> // Boolean type. WG14/N843 C99 Standard
|
||||
|
||||
#ifdef QP_CONFIG
|
||||
#include "qp_config.h" // external QP configuration
|
||||
#endif
|
||||
#include <stdint.h> // Exact-width types. WG14/N843 C99 Standard
|
||||
#include <stdbool.h> // Boolean type. WG14/N843 C99 Standard
|
||||
#include "qp_config.h" // QP configuration from the application
|
||||
|
||||
// no-return function specifier (C11 Standard)
|
||||
#define Q_NORETURN _Noreturn void
|
||||
@ -114,10 +110,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 +120,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)
|
||||
|
||||
@ -206,8 +200,6 @@ extern int32_t volatile QF_int_lock_nest_;
|
||||
// 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_H_
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
// <info@state-machine.com>
|
||||
//============================================================================
|
||||
//! @date Last updated on: 2024-06-06
|
||||
//! @version Last updated for: @ref qpc_7_4_0
|
||||
//! @version Last updated for: @ref qpc_8_0_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QS/C port to a 32-bit CPU and a generic C99 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 qpc_7_3_1
|
||||
//! @date Last updated on: 2024-09-30
|
||||
//! @version Last updated for: @ref qpc_8_0_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QV/C port to ARM Cortex-M, GNU-ARM
|
||||
@ -58,20 +57,24 @@
|
||||
// For best performance, these functions are implemented in assembly,
|
||||
// but they can be implemented in C as well.
|
||||
|
||||
|
||||
//int32_t volatile QF_int_lock_nest_; // not used
|
||||
extern char const QF_port_module_[];
|
||||
char const QF_port_module_[] = "qv_port";
|
||||
|
||||
//............................................................................
|
||||
// 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
|
||||
@ -93,13 +96,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
|
||||
@ -124,6 +130,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
|
||||
@ -131,11 +138,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
|
||||
@ -157,6 +163,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
|
||||
@ -164,11 +171,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
|
||||
@ -205,8 +211,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,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-02
|
||||
//! @version Last updated for: @ref qpc_7_3_1
|
||||
//! @date Last updated on: 2024-09-30
|
||||
//! @version Last updated for: @ref qpc_8_0_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QP/C port to ARM Cortex-M, cooperative QV kernel, IAR-ARM
|
||||
@ -36,13 +35,10 @@
|
||||
#ifndef QP_PORT_H_
|
||||
#define QP_PORT_H_
|
||||
|
||||
#include <stdint.h> // Exact-width types. WG14/N843 C99 Standard
|
||||
#include <stdbool.h> // Boolean type. WG14/N843 C99 Standard
|
||||
#include <stdint.h> // Exact-width types. WG14/N843 C99 Standard
|
||||
#include <stdbool.h> // Boolean type. WG14/N843 C99 Standard
|
||||
#include <intrinsics.h> // IAR intrinsic functions
|
||||
|
||||
#ifdef QP_CONFIG
|
||||
#include "qp_config.h" // external QP configuration
|
||||
#endif
|
||||
#include "qp_config.h" // QP configuration from the application
|
||||
|
||||
// no-return function specifier (C11 Standard)
|
||||
#define Q_NORETURN _Noreturn void
|
||||
@ -116,9 +112,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 +123,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(); \
|
||||
@ -207,8 +201,6 @@ extern int32_t volatile QF_int_lock_nest_;
|
||||
// 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_H_
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
// <info@state-machine.com>
|
||||
//============================================================================
|
||||
//! @date Last updated on: 2024-06-06
|
||||
//! @version Last updated for: @ref qpc_7_4_0
|
||||
//! @version Last updated for: @ref qpc_8_0_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QS/C port to a 32-bit CPU and a generic C99 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 qpc_7_3_1
|
||||
//! @date Last updated on: 2024-09-30
|
||||
//! @version Last updated for: @ref qpc_8_0_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QV/C port to ARM Cortex-M, IAR-ARM
|
||||
@ -69,13 +68,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?
|
||||
@ -98,12 +100,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?
|
||||
@ -129,6 +134,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
|
||||
@ -136,10 +142,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?
|
||||
@ -162,6 +167,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
|
||||
@ -169,10 +175,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?
|
||||
@ -210,8 +215,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...
|
||||
@ -240,6 +245,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,
|
||||
@ -248,7 +254,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"
|
||||
@ -268,7 +274,7 @@ __asm volatile (
|
||||
" ADDS %[n],%[n],#4 \n"
|
||||
" MOVS r0,r2 \n"
|
||||
"QF_qlog2_3:" : [n]"=r"(n)
|
||||
);
|
||||
);
|
||||
return n + log2LUT[x];
|
||||
}
|
||||
|
||||
|
@ -1,234 +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_H_
|
||||
#define QP_PORT_H_
|
||||
|
||||
#include <stdint.h> // Exact-width types. WG14/N843 C99 Standard
|
||||
#include <stdbool.h> // Boolean type. WG14/N843 C99 Standard
|
||||
|
||||
#ifdef QP_CONFIG
|
||||
#include "qp_config.h" // external QP configuration
|
||||
#endif
|
||||
|
||||
// no-return function specifier (C11 Standard)
|
||||
#define Q_NORETURN _Noreturn void
|
||||
|
||||
// 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((uint32_t)(n_))
|
||||
|
||||
#else // ARMv7-M or higher
|
||||
|
||||
// BASEPRI threshold for "QF-aware" interrupts, see NOTE3
|
||||
#define QF_BASEPRI 0x3F
|
||||
|
||||
// CMSIS threshold for "QF-aware" interrupts, see NOTE4
|
||||
#define QF_AWARE_ISR_CMSIS_PRI (QF_BASEPRI >> (8 - __NVIC_PRIO_BITS))
|
||||
|
||||
// ARMv7-M or higher provide the CLZ instruction for fast LOG2
|
||||
#define QF_LOG2(n_) ((uint_fast8_t)(32 - __builtin_clz((unsigned)(n_))))
|
||||
|
||||
#endif
|
||||
|
||||
// interrupt disabling policy, see NOTE2 and NOTE3
|
||||
#define QF_INT_DISABLE() (QF_int_disable_())
|
||||
#define QF_INT_ENABLE() (QF_int_enable_())
|
||||
|
||||
// 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
|
||||
uint_fast8_t QF_qlog2(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)
|
||||
void QF_onMemSys(void);
|
||||
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()
|
||||
void QXK_init(void);
|
||||
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.h" // QXK kernel uses the native QP event queue
|
||||
#include "qmpool.h" // QXK kernel uses the native QP memory pool
|
||||
#include "qp.h" // QP framework
|
||||
#include "qxk.h" // QXK kernel
|
||||
|
||||
// prototypes
|
||||
void QF_int_disable_(void);
|
||||
void QF_int_enable_(void);
|
||||
void QF_crit_entry_(void);
|
||||
void QF_crit_exit_(void);
|
||||
|
||||
extern int32_t volatile QF_int_lock_nest_;
|
||||
|
||||
//============================================================================
|
||||
// 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_H_
|
||||
|
@ -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 qpc_7_4_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QS/C port to a 32-bit CPU and a generic C99 compiler.
|
||||
|
||||
#ifndef QS_PORT_H_
|
||||
#define QS_PORT_H_
|
||||
|
||||
// object pointer size in bytes
|
||||
#define QS_OBJ_PTR_SIZE 4U
|
||||
|
||||
// function pointer size in bytes
|
||||
#define QS_FUN_PTR_SIZE 4U
|
||||
|
||||
//============================================================================
|
||||
// NOTE: QS might be used with or without other QP components, in which
|
||||
// case the separate definitions of the macros QF_CRIT_STAT, QF_CRIT_ENTRY(),
|
||||
// and QF_CRIT_EXIT() are needed. In this port QS is configured to be used
|
||||
// with the other QP component, by simply including "qp_port.h"
|
||||
// *before* "qs.h".
|
||||
#ifndef QP_PORT_H_
|
||||
#include "qp_port.h" // use QS with QP
|
||||
#endif
|
||||
|
||||
#include "qs.h" // QS platform-independent public interface
|
||||
|
||||
#endif // QS_PORT_H_
|
@ -1,798 +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 qpc_7_4_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QXK/C port to ARM Cortex-M, ARM-CLANG
|
||||
|
||||
#define QP_IMPL 1U
|
||||
#include "qp_port.h"
|
||||
#include "qp_pkg.h"
|
||||
#include "qsafe.h" // QP Functional Safety (FuSa) System
|
||||
|
||||
#include <stddef.h> // for offsetof()
|
||||
|
||||
//============================================================================
|
||||
// NOTE: keep in synch with struct QXK_Attr in "qxk.h" !!!
|
||||
#define QXK_CURR 0
|
||||
#define QXK_NEXT 4
|
||||
#define QXK_ACT_PRIO 12
|
||||
|
||||
// make sure that the offsets match the QXK declaration in "qxk.h"
|
||||
_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.h" !!!
|
||||
#define QACTIVE_PRIO 12
|
||||
#define QACTIVE_OSOBJ 20
|
||||
|
||||
// make sure that the offsets match the QActvie declaration in "qp.h"
|
||||
_Static_assert(QACTIVE_OSOBJ == offsetof(QActive, osObject),
|
||||
"QActive.osObject at unexpected offset");
|
||||
_Static_assert(QACTIVE_PRIO == offsetof(QActive, prio),
|
||||
"QActive.prio at unexpected offset");
|
||||
|
||||
//============================================================================
|
||||
// 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_(QActive *me, QXThreadHandler const handler,
|
||||
void * const stkSto, uint_fast16_t const stkSize)
|
||||
{
|
||||
// round down the stack top to the 8-byte boundary
|
||||
// NOTE: ARM Cortex-M stack grows down from hi -> low memory
|
||||
uint32_t *sp =
|
||||
(uint32_t *)((((uint32_t)stkSto + stkSize) >> 3U) << 3U);
|
||||
uint32_t *sp_limit;
|
||||
|
||||
// synthesize the ARM Cortex-M exception stack frame...
|
||||
*(--sp) = (1U << 24); // xPSR (just the THUMB bit)
|
||||
*(--sp) = (uint32_t)handler; // PC (the thread handler)
|
||||
*(--sp) = (uint32_t)&QXK_threadExit_; // LR (exit from thread)
|
||||
*(--sp) = 0x0000000CU; // R12
|
||||
*(--sp) = 0x00000003U; // R3
|
||||
*(--sp) = 0x00000002U; // R2
|
||||
*(--sp) = 0x00000001U; // R1
|
||||
*(--sp) = (uint32_t)me; // 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
|
||||
me->osObject = sp;
|
||||
|
||||
// pre-fill the unused part of the stack with 0xDEADBEEF
|
||||
sp_limit = (uint32_t *)(((((uint32_t)stkSto - 1U) >> 3U) + 1U) << 3U);
|
||||
for (; sp >= sp_limit; --sp) {
|
||||
*sp = 0xDEADBEEFU;
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
|
||||
|
||||
//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))
|
||||
uint_fast8_t QF_qlog2(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
|
||||
|
@ -1,255 +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_H_
|
||||
#define QP_CONFIG_H_
|
||||
|
||||
//-------- <<< 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
|
||||
// </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_H_
|
@ -1,235 +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, GNU-ARM
|
||||
|
||||
#ifndef QP_PORT_H_
|
||||
#define QP_PORT_H_
|
||||
|
||||
#include <stdint.h> // Exact-width types. WG14/N843 C99 Standard
|
||||
#include <stdbool.h> // Boolean type. WG14/N843 C99 Standard
|
||||
|
||||
#ifdef QP_CONFIG
|
||||
#include "qp_config.h" // external QP configuration
|
||||
#endif
|
||||
|
||||
// no-return function specifier (C11 Standard)
|
||||
#define Q_NORETURN _Noreturn void
|
||||
|
||||
// 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((uint32_t)(n_))
|
||||
|
||||
#else // ARMv7-M or higher
|
||||
|
||||
// BASEPRI threshold for "QF-aware" interrupts, see NOTE3
|
||||
#define QF_BASEPRI 0x3F
|
||||
|
||||
// CMSIS threshold for "QF-aware" interrupts, see NOTE4
|
||||
#define QF_AWARE_ISR_CMSIS_PRI (QF_BASEPRI >> (8 - __NVIC_PRIO_BITS))
|
||||
|
||||
// ARMv7-M or higher provide the CLZ instruction for fast LOG2
|
||||
#define QF_LOG2(n_) ((uint_fast8_t)(32 - __builtin_clz((unsigned)(n_))))
|
||||
|
||||
#endif
|
||||
|
||||
// interrupt disabling policy, see NOTE2 and NOTE3
|
||||
#define QF_INT_DISABLE() (QF_int_disable_())
|
||||
#define QF_INT_ENABLE() (QF_int_enable_())
|
||||
|
||||
// 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
|
||||
uint_fast8_t QF_qlog2(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)
|
||||
void QF_onMemSys(void);
|
||||
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()
|
||||
void QXK_init(void);
|
||||
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.h" // QXK kernel uses the native QP event queue
|
||||
#include "qmpool.h" // QXK kernel uses the native QP memory pool
|
||||
#include "qp.h" // QP framework
|
||||
#include "qxk.h" // QXK kernel
|
||||
|
||||
// prototypes
|
||||
void QF_int_disable_(void);
|
||||
void QF_int_enable_(void);
|
||||
void QF_crit_entry_(void);
|
||||
void QF_crit_exit_(void);
|
||||
|
||||
extern int32_t volatile QF_int_lock_nest_;
|
||||
|
||||
//============================================================================
|
||||
// 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_H_
|
||||
|
@ -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 qpc_7_4_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QS/C port to a 32-bit CPU and a generic C99 compiler.
|
||||
|
||||
#ifndef QS_PORT_H_
|
||||
#define QS_PORT_H_
|
||||
|
||||
// object pointer size in bytes
|
||||
#define QS_OBJ_PTR_SIZE 4U
|
||||
|
||||
// function pointer size in bytes
|
||||
#define QS_FUN_PTR_SIZE 4U
|
||||
|
||||
//============================================================================
|
||||
// NOTE: QS might be used with or without other QP components, in which
|
||||
// case the separate definitions of the macros QF_CRIT_STAT, QF_CRIT_ENTRY(),
|
||||
// and QF_CRIT_EXIT() are needed. In this port QS is configured to be used
|
||||
// with the other QP component, by simply including "qp_port.h"
|
||||
// *before* "qs.h".
|
||||
#ifndef QP_PORT_H_
|
||||
#include "qp_port.h" // use QS with QP
|
||||
#endif
|
||||
|
||||
#include "qs.h" // QS platform-independent public interface
|
||||
|
||||
#endif // QS_PORT_H_
|
@ -1,808 +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 qpc_7_4_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QXK/C port to ARM Cortex-M, GNU-ARM
|
||||
|
||||
#define QP_IMPL 1U
|
||||
#include "qp_port.h"
|
||||
#include "qp_pkg.h"
|
||||
#include "qsafe.h" // QP Functional Safety (FuSa) System
|
||||
|
||||
#include <stddef.h> // for offsetof()
|
||||
|
||||
//============================================================================
|
||||
// NOTE: keep in synch with struct QXK_Attr in "qxk.h" !!!
|
||||
#define QXK_CURR 0
|
||||
#define QXK_NEXT 4
|
||||
#define QXK_ACT_PRIO 12
|
||||
|
||||
// make sure that the offsets match the QXK declaration in "qxk.h"
|
||||
_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.h" !!!
|
||||
#define QACTIVE_PRIO 12
|
||||
#define QACTIVE_OSOBJ 20
|
||||
|
||||
// make sure that the offsets match the QActvie declaration in "qp.h"
|
||||
_Static_assert(QACTIVE_OSOBJ == offsetof(QActive, osObject),
|
||||
"QActive.osObject at unexpected offset");
|
||||
_Static_assert(QACTIVE_PRIO == offsetof(QActive, prio),
|
||||
"QActive.prio at unexpected offset");
|
||||
|
||||
//============================================================================
|
||||
// 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_(QActive *me, QXThreadHandler const handler,
|
||||
void * const stkSto, uint_fast16_t const stkSize)
|
||||
{
|
||||
// round down the stack top to the 8-byte boundary
|
||||
// NOTE: ARM Cortex-M stack grows down from hi -> low memory
|
||||
uint32_t *sp =
|
||||
(uint32_t *)((((uint32_t)stkSto + stkSize) >> 3U) << 3U);
|
||||
uint32_t *sp_limit;
|
||||
|
||||
// synthesize the ARM Cortex-M exception stack frame...
|
||||
*(--sp) = (1U << 24); // xPSR (just the THUMB bit)
|
||||
*(--sp) = (uint32_t)handler; // PC (the thread handler)
|
||||
*(--sp) = (uint32_t)&QXK_threadExit_; // LR (exit from thread)
|
||||
*(--sp) = 0x0000000CU; // R12
|
||||
*(--sp) = 0x00000003U; // R3
|
||||
*(--sp) = 0x00000002U; // R2
|
||||
*(--sp) = 0x00000001U; // R1
|
||||
*(--sp) = (uint32_t)me; // 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
|
||||
me->osObject = sp;
|
||||
|
||||
// pre-fill the unused part of the stack with 0xDEADBEEF
|
||||
sp_limit = (uint32_t *)(((((uint32_t)stkSto - 1U) >> 3U) + 1U) << 3U);
|
||||
for (; sp >= sp_limit; --sp) {
|
||||
*sp = 0xDEADBEEFU;
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
|
||||
|
||||
//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
|
||||
|
@ -1,228 +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, IAR-ARM
|
||||
|
||||
#ifndef QP_PORT_H_
|
||||
#define QP_PORT_H_
|
||||
|
||||
#include <stdint.h> // Exact-width types. WG14/N843 C99 Standard
|
||||
#include <stdbool.h> // Boolean type. WG14/N843 C99 Standard
|
||||
#include <intrinsics.h> // IAR intrinsic functions
|
||||
|
||||
#ifdef QP_CONFIG
|
||||
#include "qp_config.h" // external QP configuration
|
||||
#endif
|
||||
|
||||
// no-return function specifier (C11 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((uint32_t)(n_))
|
||||
|
||||
#else // ARMv7-M or higher
|
||||
|
||||
// BASEPRI threshold for "QF-aware" interrupts, see NOTE3
|
||||
#define QF_BASEPRI 0x3F
|
||||
|
||||
// CMSIS threshold for "QF-aware" interrupts, see NOTE4
|
||||
#define QF_AWARE_ISR_CMSIS_PRI (QF_BASEPRI >> (8 - __NVIC_PRIO_BITS))
|
||||
|
||||
// ARMv7-M or higher provide the CLZ instruction for fast LOG2
|
||||
#define QF_LOG2(n_) ((uint_fast8_t)(32U - __CLZ((unsigned long)(n_))))
|
||||
|
||||
#endif
|
||||
|
||||
// interrupt disabling policy, see NOTE2 and NOTE3
|
||||
#define QF_INT_DISABLE() (QF_int_disable_())
|
||||
#define QF_INT_ENABLE() (QF_int_enable_())
|
||||
|
||||
// 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
|
||||
uint_fast8_t QF_qlog2(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)
|
||||
void QF_onMemSys(void);
|
||||
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()
|
||||
void QXK_init(void);
|
||||
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.h" // QXK kernel uses the native QP event queue
|
||||
#include "qmpool.h" // QXK kernel uses the native QP memory pool
|
||||
#include "qp.h" // QP framework
|
||||
#include "qxk.h" // QXK kernel
|
||||
|
||||
// prototypes
|
||||
void QF_int_disable_(void);
|
||||
void QF_int_enable_(void);
|
||||
void QF_crit_entry_(void);
|
||||
void QF_crit_exit_(void);
|
||||
|
||||
extern int32_t volatile QF_int_lock_nest_;
|
||||
|
||||
//============================================================================
|
||||
// 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_H_
|
||||
|
@ -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 qpc_7_4_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QS/C port to a 32-bit CPU and a generic C99 compiler.
|
||||
|
||||
#ifndef QS_PORT_H_
|
||||
#define QS_PORT_H_
|
||||
|
||||
// object pointer size in bytes
|
||||
#define QS_OBJ_PTR_SIZE 4U
|
||||
|
||||
// function pointer size in bytes
|
||||
#define QS_FUN_PTR_SIZE 4U
|
||||
|
||||
//============================================================================
|
||||
// NOTE: QS might be used with or without other QP components, in which
|
||||
// case the separate definitions of the macros QF_CRIT_STAT, QF_CRIT_ENTRY(),
|
||||
// and QF_CRIT_EXIT() are needed. In this port QS is configured to be used
|
||||
// with the other QP component, by simply including "qp_port.h"
|
||||
// *before* "qs.h".
|
||||
#ifndef QP_PORT_H_
|
||||
#include "qp_port.h" // use QS with QP
|
||||
#endif
|
||||
|
||||
#include "qs.h" // QS platform-independent public interface
|
||||
|
||||
#endif // QS_PORT_H_
|
@ -1,801 +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 qpc_7_4_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QXK/C port to ARM Cortex-M, IAR-ARM
|
||||
|
||||
#define QP_IMPL 1U
|
||||
#include "qp_port.h"
|
||||
#include "qp_pkg.h"
|
||||
#include "qsafe.h" // QP Functional Safety (FuSa) System
|
||||
|
||||
#include <stddef.h> // for offsetof()
|
||||
|
||||
//============================================================================
|
||||
// NOTE: keep in synch with struct QXK_Attr in "qxk.h" !!!
|
||||
#define QXK_CURR 0
|
||||
#define QXK_NEXT 4
|
||||
#define QXK_ACT_PRIO 12
|
||||
|
||||
// make sure that the offsets match the QXK declaration in "qxk.h"
|
||||
_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.h" !!!
|
||||
#define QACTIVE_PRIO 12
|
||||
#define QACTIVE_OSOBJ 20
|
||||
|
||||
// make sure that the offsets match the QActvie declaration in "qp.h"
|
||||
_Static_assert(QACTIVE_OSOBJ == offsetof(QActive, osObject),
|
||||
"QActive.osObject at unexpected offset");
|
||||
_Static_assert(QACTIVE_PRIO == offsetof(QActive, prio),
|
||||
"QActive.prio at unexpected offset");
|
||||
|
||||
//============================================================================
|
||||
// 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_(QActive *me, QXThreadHandler const handler,
|
||||
void * const stkSto, uint_fast16_t const stkSize)
|
||||
{
|
||||
// round down the stack top to the 8-byte boundary
|
||||
// NOTE: ARM Cortex-M stack grows down from hi -> low memory
|
||||
uint32_t *sp =
|
||||
(uint32_t *)((((uint32_t)stkSto + stkSize) >> 3U) << 3U);
|
||||
uint32_t *sp_limit;
|
||||
|
||||
// synthesize the ARM Cortex-M exception stack frame...
|
||||
*(--sp) = (1U << 24); // xPSR (just the THUMB bit)
|
||||
*(--sp) = (uint32_t)handler; // PC (the thread handler)
|
||||
*(--sp) = (uint32_t)&QXK_threadExit_; // LR (exit from thread)
|
||||
*(--sp) = 0x0000000CU; // R12
|
||||
*(--sp) = 0x00000003U; // R3
|
||||
*(--sp) = 0x00000002U; // R2
|
||||
*(--sp) = 0x00000001U; // R1
|
||||
*(--sp) = (uint32_t)me; // 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
|
||||
me->osObject = sp;
|
||||
|
||||
// pre-fill the unused part of the stack with 0xDEADBEEF
|
||||
sp_limit = (uint32_t *)(((((uint32_t)stkSto - 1U) >> 3U) + 1U) << 3U);
|
||||
for (; sp >= sp_limit; --sp) {
|
||||
*sp = 0xDEADBEEFU;
|
||||
}
|
||||
}
|
||||
|
||||
// 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_
|
||||
|
||||
//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)
|
||||
uint_fast8_t QF_qlog2(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
|
||||
|
@ -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_H_
|
||||
@ -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
|
||||
@ -158,7 +149,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 qpc_7_3_0
|
||||
//! @date Last updated on: 2023-09-30
|
||||
//! @version Last updated for: @ref qpc_8_0_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QP/C port to ARM Cortex-R, preemptive QK kernel, GNU-ARM
|
||||
@ -36,12 +36,9 @@
|
||||
#ifndef QP_PORT_H_
|
||||
#define QP_PORT_H_
|
||||
|
||||
#include <stdint.h> // Exact-width types. WG14/N843 C99 Standard
|
||||
#include <stdbool.h> // Boolean type. WG14/N843 C99 Standard
|
||||
|
||||
#ifdef QP_CONFIG
|
||||
#include "qp_config.h" // external QP configuration
|
||||
#endif
|
||||
#include <stdint.h> // Exact-width types. WG14/N843 C99 Standard
|
||||
#include <stdbool.h> // Boolean type. WG14/N843 C99 Standard
|
||||
#include "qp_config.h" // QP configuration from the application
|
||||
|
||||
// no-return function specifier (C11 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 qpc_7_4_0
|
||||
//! @version Last updated for: @ref qpc_8_0_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QS/C port to a 32-bit CPU and a generic C99 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 qpc_7_3_0
|
||||
//! @date Last updated on: 2023-09-30
|
||||
//! @version Last updated for: @ref qpc_8_0_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QP/C port to ARM Cortex-R, preemptive QK kernel, IAR-ARM
|
||||
@ -36,13 +36,10 @@
|
||||
#ifndef QP_PORT_H_
|
||||
#define QP_PORT_H_
|
||||
|
||||
#include <stdint.h> // Exact-width types. WG14/N843 C99 Standard
|
||||
#include <stdbool.h> // Boolean type. WG14/N843 C99 Standard
|
||||
#include <stdint.h> // Exact-width types. WG14/N843 C99 Standard
|
||||
#include <stdbool.h> // Boolean type. WG14/N843 C99 Standard
|
||||
#include <intrinsics.h> // IAR intrinsic functions
|
||||
|
||||
#ifdef QP_CONFIG
|
||||
#include "qp_config.h" // external QP configuration
|
||||
#endif
|
||||
#include "qp_config.h" // QP configuration from the application
|
||||
|
||||
// no-return function specifier (C11 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 qpc_7_4_0
|
||||
//! @version Last updated for: @ref qpc_8_0_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QS/C port to a 32-bit CPU and a generic C99 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 qpc_7_3_0
|
||||
//! @date Last updated on: 2023-09-30
|
||||
//! @version Last updated for: @ref qpc_8_0_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QP/C port to ARM Cortex-R, preemptive QK kernel, TI-ARM
|
||||
@ -36,12 +36,9 @@
|
||||
#ifndef QP_PORT_H_
|
||||
#define QP_PORT_H_
|
||||
|
||||
#include <stdint.h> // Exact-width types. WG14/N843 C99 Standard
|
||||
#include <stdbool.h> // Boolean type. WG14/N843 C99 Standard
|
||||
|
||||
#ifdef QP_CONFIG
|
||||
#include "qp_config.h" // external QP configuration
|
||||
#endif
|
||||
#include <stdint.h> // Exact-width types. WG14/N843 C99 Standard
|
||||
#include <stdbool.h> // Boolean type. WG14/N843 C99 Standard
|
||||
#include "qp_config.h" // QP configuration from the application
|
||||
|
||||
// no-return function specifier (C11 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 qpc_7_4_0
|
||||
//! @version Last updated for: @ref qpc_8_0_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QS/C port to a 32-bit CPU and a generic C99 compiler.
|
||||
|
@ -1,32 +1,30 @@
|
||||
//============================================================================
|
||||
// QP configuration file (QV 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_H_
|
||||
@ -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
|
||||
@ -158,7 +149,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
|
||||
@ -233,6 +223,7 @@
|
||||
|
||||
// </h>
|
||||
|
||||
|
||||
//------------- <<< end of configuration section >>> -----------------------
|
||||
|
||||
#endif // QP_CONFIG_H_
|
||||
|
@ -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 qpc_7_3_0
|
||||
//! @date Last updated on: 2023-09-30
|
||||
//! @version Last updated for: @ref qpc_8_0_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QP/C port to ARM Cortex-R, cooperative QV kernel, GNU-ARM
|
||||
@ -36,15 +36,12 @@
|
||||
#ifndef QP_PORT_H_
|
||||
#define QP_PORT_H_
|
||||
|
||||
#include <stdint.h> // Exact-width types. WG14/N843 C99 Standard
|
||||
#include <stdbool.h> // Boolean type. WG14/N843 C99 Standard
|
||||
#include <stdint.h> // Exact-width types. WG14/N843 C99 Standard
|
||||
#include <stdbool.h> // Boolean type. WG14/N843 C99 Standard
|
||||
#include "qp_config.h" // QP configuration from the application
|
||||
|
||||
#ifdef QP_CONFIG
|
||||
#include "qp_config.h" // external QP configuration
|
||||
#endif
|
||||
|
||||
// no-return function specifier (GNU-ARM compiler)
|
||||
#define Q_NORETURN __attribute__ ((noreturn)) void
|
||||
// no-return function specifier (C11 Standard)
|
||||
#define Q_NORETURN _Noreturn void
|
||||
|
||||
// QF configuration for QV -- data members of the QActive class...
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
// <info@state-machine.com>
|
||||
//============================================================================
|
||||
//! @date Last updated on: 2024-06-06
|
||||
//! @version Last updated for: @ref qpc_7_4_0
|
||||
//! @version Last updated for: @ref qpc_8_0_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QS/C port to a 32-bit CPU and a generic C99 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 qpc_7_3_0
|
||||
//! @date Last updated on: 2023-09-30
|
||||
//! @version Last updated for: @ref qpc_8_0_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QP/C port to Cortex-R, cooperative QV kernel, IAR-ARM
|
||||
@ -36,16 +36,13 @@
|
||||
#ifndef QP_PORT_H_
|
||||
#define QP_PORT_H_
|
||||
|
||||
#include <stdint.h> // Exact-width types. WG14/N843 C99 Standard
|
||||
#include <stdbool.h> // Boolean type. WG14/N843 C99 Standard
|
||||
#include <stdint.h> // Exact-width types. WG14/N843 C99 Standard
|
||||
#include <stdbool.h> // Boolean type. WG14/N843 C99 Standard
|
||||
#include <intrinsics.h> // IAR intrinsic functions
|
||||
#include "qp_config.h" // QP configuration from the application
|
||||
|
||||
#ifdef QP_CONFIG
|
||||
#include "qp_config.h" // external QP configuration
|
||||
#endif
|
||||
|
||||
// no-return function specifier (IAR-ARM compiler)
|
||||
#define Q_NORETURN __noreturn void
|
||||
// no-return function specifier (C11 Standard)
|
||||
#define Q_NORETURN _Noreturn void
|
||||
|
||||
// QF configuration for QV -- data members of the QActive class...
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
// <info@state-machine.com>
|
||||
//============================================================================
|
||||
//! @date Last updated on: 2024-06-06
|
||||
//! @version Last updated for: @ref qpc_7_4_0
|
||||
//! @version Last updated for: @ref qpc_8_0_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QS/C port to a 32-bit CPU and a generic C99 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 qpc_7_3_0
|
||||
//! @date Last updated on: 2023-09-30
|
||||
//! @version Last updated for: @ref qpc_8_0_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QP/C port to ARM Cortex-R, cooperative QV kernel, TI-ARM
|
||||
@ -36,12 +36,9 @@
|
||||
#ifndef QP_PORT_H_
|
||||
#define QP_PORT_H_
|
||||
|
||||
#include <stdint.h> // Exact-width types. WG14/N843 C99 Standard
|
||||
#include <stdbool.h> // Boolean type. WG14/N843 C99 Standard
|
||||
|
||||
#ifdef QP_CONFIG
|
||||
#include "qp_config.h" // external QP configuration
|
||||
#endif
|
||||
#include <stdint.h> // Exact-width types. WG14/N843 C99 Standard
|
||||
#include <stdbool.h> // Boolean type. WG14/N843 C99 Standard
|
||||
#include "qp_config.h" // QP configuration from the application
|
||||
|
||||
// no-return function specifier (C11 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 qpc_7_4_0
|
||||
//! @version Last updated for: @ref qpc_8_0_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QS/C port to a 32-bit CPU and a generic C99 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_H_
|
||||
@ -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
|
||||
@ -158,7 +149,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,40 +1,43 @@
|
||||
//============================================================================
|
||||
// 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 qpc_7_4_0
|
||||
//! @date Last updated on: 2024-09-26
|
||||
//! @version Last updated for: @ref qpc_8_0_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QF/C port to embOS RTOS kernel, generic C11 compiler
|
||||
//!
|
||||
#define QP_IMPL // this is QP implementation
|
||||
#include "qp_port.h" // QP port
|
||||
#include "qp_pkg.h" // QP package-level interface
|
||||
#include "qsafe.h" // QP Functional Safety (FuSa) subsystem
|
||||
#include "qp_pkg.h" // QP package-scope interface
|
||||
#include "qsafe.h" // QP Functional Safety (FuSa) Subsystem
|
||||
#ifdef Q_SPY // QS software tracing enabled?
|
||||
#include "qs_port.h" // QS port
|
||||
#include "qs_pkg.h" // QS package-scope internal interface
|
||||
#include "qs_pkg.h" // QS facilities for pre-defined trace records
|
||||
#else
|
||||
#include "qs_dummy.h" // disable the QS software tracing
|
||||
#endif // Q_SPY
|
||||
@ -77,8 +80,11 @@ static void thread_function(void *pVoid) { // embOS signature
|
||||
}
|
||||
//............................................................................
|
||||
void QF_init(void) {
|
||||
OS_InitKern(); // initialize embOS
|
||||
OS_InitHW(); // initialize the hardware used by embOS
|
||||
QF_bzero_(&QF_priv_, sizeof(QF_priv_));
|
||||
QF_bzero_(&QActive_registry_[0], sizeof(QActive_registry_));
|
||||
QTimeEvt_init(); // initialize QTimeEvts
|
||||
OS_InitKern(); // initialize embOS
|
||||
OS_InitHW(); // initialize the hardware used by embOS
|
||||
}
|
||||
//............................................................................
|
||||
int QF_run(void) {
|
||||
@ -87,29 +93,29 @@ int QF_run(void) {
|
||||
// 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
|
||||
|
||||
return 0; // dummy return to make the compiler happy
|
||||
return 0; // this unreachable return keeps the compiler happy
|
||||
}
|
||||
//............................................................................
|
||||
void QF_stop(void) {
|
||||
QF_onCleanup(); // cleanup callback
|
||||
QF_onCleanup(); // cleanup callback
|
||||
}
|
||||
|
||||
//............................................................................
|
||||
void QActive_start(QActive * const me,
|
||||
QPrioSpec const prioSpec,
|
||||
QEvt const * * const qSto, uint_fast16_t const qLen,
|
||||
QEvtPtr * const qSto, uint_fast16_t const qLen,
|
||||
void * const stkSto, uint_fast16_t const stkSize,
|
||||
void const * const par)
|
||||
{
|
||||
// create the embOS message box for the AO
|
||||
OS_MAILBOX_Create(&me->eQueue,
|
||||
(OS_U16)sizeof(QEvt *),
|
||||
(OS_U16)sizeof(QEvtPtr), // item size
|
||||
(OS_UINT)qLen,
|
||||
(void *)&qSto[0]);
|
||||
|
||||
@ -183,9 +189,20 @@ void QActive_setAttr(QActive *const me, uint32_t attr1, void const *attr2) {
|
||||
bool QActive_post_(QActive * const me, QEvt const * const e,
|
||||
uint_fast16_t const margin, void const * const sender)
|
||||
{
|
||||
#ifndef Q_SPY
|
||||
Q_UNUSED_PAR(sender);
|
||||
#endif
|
||||
|
||||
QF_CRIT_STAT
|
||||
QF_CRIT_ENTRY();
|
||||
uint_fast16_t nFree =
|
||||
|
||||
Q_REQUIRE_INCRIT(200, e != (QEvt *)0);
|
||||
#ifndef Q_UNSAFE
|
||||
Q_INVARIANT_INCRIT(201, QEvt_verify_(e));
|
||||
#endif // ndef Q_UNSAFE
|
||||
|
||||
// the number of free slots available in the queue
|
||||
uint_fast16_t const nFree =
|
||||
(uint_fast16_t)(me->eQueue.maxMsg - me->eQueue.nofMsg);
|
||||
|
||||
bool status;
|
||||
@ -195,7 +212,7 @@ bool QActive_post_(QActive * const me, QEvt const * const e,
|
||||
}
|
||||
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 > (QEQueueCtr)margin) {
|
||||
@ -207,15 +224,15 @@ bool QActive_post_(QActive * const me, QEvt const * const e,
|
||||
|
||||
if (status) { // can post the event?
|
||||
|
||||
QS_BEGIN_PRE_(QS_QF_ACTIVE_POST, me->prio)
|
||||
QS_TIME_PRE_(); // timestamp
|
||||
QS_OBJ_PRE_(sender); // the sender object
|
||||
QS_SIG_PRE_(e->sig); // the signal of the event
|
||||
QS_OBJ_PRE_(me); // this active object (recipient)
|
||||
QS_2U8_PRE_(QEvt_getPoolNum_(e), e->refCtr_); // pool-Id&ref-Count
|
||||
QS_EQC_PRE_(nFree); // # free entries
|
||||
QS_EQC_PRE_(0U); // min # free entries (unknown)
|
||||
QS_END_PRE_()
|
||||
QS_BEGIN_PRE(QS_QF_ACTIVE_POST, me->prio)
|
||||
QS_TIME_PRE(); // timestamp
|
||||
QS_OBJ_PRE(sender); // the sender object
|
||||
QS_SIG_PRE(e->sig); // the signal of the event
|
||||
QS_OBJ_PRE(me); // this active object (recipient)
|
||||
QS_2U8_PRE(QEvt_getPoolNum_(e), e->refCtr_);
|
||||
QS_EQC_PRE((QEQueueCtr)nFree); // # free entries
|
||||
QS_EQC_PRE(0U); // min # free entries (unknown)
|
||||
QS_END_PRE()
|
||||
|
||||
if (QEvt_getPoolNum_(e) != 0U) { // is it a pool event?
|
||||
QEvt_refCtr_inc_(e); // increment the reference counter
|
||||
@ -226,20 +243,19 @@ bool QActive_post_(QActive * const me, QEvt const * const 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, me->prio)
|
||||
QS_TIME_PRE_(); // timestamp
|
||||
QS_OBJ_PRE_(sender); // the sender object
|
||||
QS_SIG_PRE_(e->sig); // the signal of the event
|
||||
QS_OBJ_PRE_(me); // this active object (recipient)
|
||||
QS_2U8_PRE_(QEvt_getPoolNum_(e), e->refCtr_); // pool-Id&ref-Count
|
||||
QS_EQC_PRE_(nFree); // # free entries
|
||||
QS_EQC_PRE_(margin); // margin requested
|
||||
QS_END_PRE_()
|
||||
else { // cannot post the event
|
||||
|
||||
QS_BEGIN_PRE(QS_QF_ACTIVE_POST_ATTEMPT, me->prio)
|
||||
QS_TIME_PRE(); // timestamp
|
||||
QS_OBJ_PRE(sender); // the sender object
|
||||
QS_SIG_PRE(e->sig); // the signal of the event
|
||||
QS_OBJ_PRE(me); // this active object (recipient)
|
||||
QS_2U8_PRE(QEvt_getPoolNum_(e), e->refCtr_); // pool-Id&ref-Count
|
||||
QS_EQC_PRE(nFree); // # free entries
|
||||
QS_EQC_PRE(margin); // margin requested
|
||||
QS_END_PRE()
|
||||
}
|
||||
QF_CRIT_EXIT();
|
||||
|
||||
@ -250,14 +266,19 @@ void QActive_postLIFO_(QActive * const me, QEvt const * const e) {
|
||||
QF_CRIT_STAT
|
||||
QF_CRIT_ENTRY();
|
||||
|
||||
QS_BEGIN_PRE_(QS_QF_ACTIVE_POST_LIFO, me->prio)
|
||||
QS_TIME_PRE_(); // timestamp
|
||||
QS_SIG_PRE_(e->sig); // the signal of this event
|
||||
QS_OBJ_PRE_(me); // this active object
|
||||
QS_2U8_PRE_(QEvt_getPoolNum_(e), e->refCtr_); // pool-Id&ref-Count
|
||||
QS_EQC_PRE_(me->eQueue.maxMsg - me->eQueue.nofMsg); // # free
|
||||
QS_EQC_PRE_(0U); // min # free entries (unknown)
|
||||
QS_END_PRE_()
|
||||
Q_REQUIRE_INCRIT(300, e != (QEvt *)0);
|
||||
#ifndef Q_UNSAFE
|
||||
Q_INVARIANT_INCRIT(301, QEvt_verify_(e));
|
||||
#endif // ndef Q_UNSAFE
|
||||
|
||||
QS_BEGIN_PRE(QS_QF_ACTIVE_POST_LIFO, me->prio)
|
||||
QS_TIME_PRE(); // timestamp
|
||||
QS_SIG_PRE(e->sig); // the signal of this event
|
||||
QS_OBJ_PRE(me); // this active object
|
||||
QS_2U8_PRE(QEvt_getPoolNum_(e), e->refCtr_);
|
||||
QS_EQC_PRE(me->eQueue.maxMsg - me->eQueue.nofMsg); // # free
|
||||
QS_EQC_PRE(0U); // min # free entries (unknown)
|
||||
QS_END_PRE()
|
||||
|
||||
if (QEvt_getPoolNum_(e) != 0U) { // is it a pool event?
|
||||
QEvt_refCtr_inc_(e); // increment the reference counter
|
||||
@ -268,24 +289,26 @@ void QActive_postLIFO_(QActive * const me, QEvt const * const 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_(QActive * const me) {
|
||||
QEvt const *e;
|
||||
QEvtPtr e;
|
||||
OS_MAILBOX_GetBlocked(&me->eQueue, (void *)&e);
|
||||
|
||||
QS_CRIT_STAT
|
||||
QS_CRIT_ENTRY();
|
||||
QS_BEGIN_PRE_(QS_QF_ACTIVE_GET, me->prio)
|
||||
QS_TIME_PRE_(); // timestamp
|
||||
QS_SIG_PRE_(e->sig); // the signal of this event
|
||||
QS_OBJ_PRE_(me); // this active object
|
||||
QS_2U8_PRE_(QEvt_getPoolNum_(e), e->refCtr_); // pool-Id&ref-Count
|
||||
QS_EQC_PRE_(me->eQueue.maxMsg - me->eQueue.nofMsg);// # free
|
||||
QS_END_PRE_()
|
||||
QS_CRIT_EXIT();
|
||||
QF_CRIT_STAT
|
||||
QF_CRIT_ENTRY();
|
||||
|
||||
QS_BEGIN_PRE(QS_QF_ACTIVE_GET, me->prio)
|
||||
QS_TIME_PRE(); // timestamp
|
||||
QS_SIG_PRE(e->sig); // the signal of this event
|
||||
QS_OBJ_PRE(me); // this active object
|
||||
QS_2U8_PRE(QEvt_getPoolNum_(e), e->refCtr_);
|
||||
QS_EQC_PRE((QEQueueCtr)(me->eQueue.maxMsg - me->eQueue.nofMsg));
|
||||
QS_END_PRE()
|
||||
|
||||
QF_CRIT_EXIT();
|
||||
|
||||
return e;
|
||||
}
|
||||
@ -298,8 +321,8 @@ QEvt const *QActive_get_(QActive * const me) {
|
||||
// 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 qpc_7_3_0
|
||||
//! @date Last updated on: 2023-09-30
|
||||
//! @version Last updated for: @ref qpc_8_0_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QP/C port to embOS RTOS (v5), generic C11 compiler
|
||||
@ -36,12 +36,9 @@
|
||||
#ifndef QP_PORT_H_
|
||||
#define QP_PORT_H_
|
||||
|
||||
#include <stdint.h> // Exact-width types. WG14/N843 C99 Standard
|
||||
#include <stdbool.h> // Boolean type. WG14/N843 C99 Standard
|
||||
|
||||
#ifdef QP_CONFIG
|
||||
#include "qp_config.h" // external QP configuration
|
||||
#endif
|
||||
#include <stdint.h> // Exact-width types. WG14/N843 C99 Standard
|
||||
#include <stdbool.h> // Boolean type. WG14/N843 C99 Standard
|
||||
#include "qp_config.h" // QP configuration from the application
|
||||
|
||||
// no-return function specifier (C11 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 qpc_7_4_0
|
||||
//! @version Last updated for: @ref qpc_8_0_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QS/C port to a 32-bit CPU and a generic C99 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 qpc_7_3_0
|
||||
//! @date Last updated on: 2023-09-30
|
||||
//! @version Last updated for: @ref qpc_8_0_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QP/C port to FreeRTOS 10.x, generic C11 compiler
|
||||
@ -36,12 +36,9 @@
|
||||
#ifndef QP_PORT_H_
|
||||
#define QP_PORT_H_
|
||||
|
||||
#include <stdint.h> // Exact-width types. WG14/N843 C99 Standard
|
||||
#include <stdbool.h> // Boolean type. WG14/N843 C99 Standard
|
||||
|
||||
#ifdef QP_CONFIG
|
||||
#include "qp_config.h" // external QP configuration
|
||||
#endif
|
||||
#include <stdint.h> // Exact-width types. WG14/N843 C99 Standard
|
||||
#include <stdbool.h> // Boolean type. WG14/N843 C99 Standard
|
||||
#include "qp_config.h" // QP configuration from the application
|
||||
|
||||
// no-return function specifier (C11 Standard)
|
||||
#define Q_NORETURN _Noreturn void
|
||||
@ -206,7 +203,7 @@ enum FreeRTOS_TaskAttrs {
|
||||
#define QF_EPOOL_PUT_(p_, e_, qsId_) \
|
||||
(QMPool_put(&(p_), (e_), (qsId_)))
|
||||
|
||||
#endif // 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 qpc_7_4_0
|
||||
//! @version Last updated for: @ref qpc_8_0_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QS/C port to a 32-bit CPU and a generic C99 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,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 qpc_7_4_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QS/C port to a 16-bit CPU and a generic C99 compiler.
|
||||
|
||||
#ifndef QS_PORT_H_
|
||||
#define QS_PORT_H_
|
||||
|
||||
// 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.h"
|
||||
// *before* "qs.h".
|
||||
#ifndef QP_PORT_H_
|
||||
#include "qp_port.h" // use QS with QP
|
||||
#endif
|
||||
|
||||
#include "qs.h" // QS platform-independent public interface
|
||||
|
||||
#endif // QS_PORT_H_
|
@ -1,47 +0,0 @@
|
||||
//! @file
|
||||
//! @brief Selected exact-width and fast minimum-width integer types
|
||||
//! for 16-bit CPU architecture (e.g., MSP430).
|
||||
//!
|
||||
//! @description
|
||||
//! This header is part of the ANSI C99 standard library to define the
|
||||
//! standard exact-width integer types (see C99 Section 7.18.1.1).
|
||||
//! If the compiler does not provide the stdint.h header file, you can
|
||||
//! either create one in the QP port directory, or you can typedef the
|
||||
//! 8 exact-width integer types directly in the qep_port.h header file.
|
||||
//!
|
||||
//! @note The version included in the QP documentation contains only the 8
|
||||
//! exact-width types and 6 fast minimum-width types actually used in QP.
|
||||
//! The actual definition of the integer types is platform dependent.
|
||||
#ifndef STDINT_H_
|
||||
#define STDINT_H_
|
||||
|
||||
//lint -save
|
||||
//lint -e9093 M3:R21.2(R) name matches a pattern reserved to the compiler
|
||||
//lint -e586 B18:R5.2(b) keyword 'short'/'long' is deprecated
|
||||
|
||||
// Exact-width types. WG14/N843 C99 Standard, Section 7.18.1.1
|
||||
typedef signed char int8_t; //!< exact-width 8-bit signed int
|
||||
typedef signed int int16_t; //!< exact-width 16-bit signed int
|
||||
typedef signed long int int32_t; //!< exact-width 32-bit signed int
|
||||
typedef signed long long int64_t; //!< exact-width 64-bit signed int
|
||||
|
||||
typedef unsigned char uint8_t; //!< exact-width 8-bit unsigned int
|
||||
typedef unsigned int uint16_t; //!< exact-width 16-bit unsigned int
|
||||
typedef unsigned long int uint32_t; //!< exact-width 32-bit unsigned int
|
||||
typedef unsigned long long uint64_t; //!< exact-width 64-bit unsigned int
|
||||
|
||||
// Fastest minimum-width types. WG14/N843 C99 Standard, Section 7.18.1.3
|
||||
typedef signed int int_fast8_t; //!< fast at-least 8-bit signed int
|
||||
typedef unsigned int uint_fast8_t; //!< fast at-least 8-bit unsigned int
|
||||
typedef signed int int_fast16_t; //!< fast at-least 16-bit signed int
|
||||
typedef unsigned int uint_fast16_t; //!< fast at-least 16-bit unsigned int
|
||||
typedef signed long int_fast32_t; //!< fast at-least 32-bit signed int
|
||||
typedef unsigned long uint_fast32_t; //!< fast at-least 32-bit unsigned int
|
||||
|
||||
// unsigned integer type capable of holding a pointer to void.
|
||||
typedef unsigned uintptr_t; //!< unsigned int capable of holding void*
|
||||
|
||||
//lint -restore
|
||||
|
||||
#endif // STDINT_H_
|
||||
|
@ -1,3 +0,0 @@
|
||||
// Size Options for 32bit CPU (e.g., ARM Cortex-M)
|
||||
-si4 -sl4 -sll8 -ss2 -sw4 -sp4 -sf4 -sd8 -sld8
|
||||
|
@ -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 qpc_7_4_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QS/C port to a 32-bit CPU and a generic C99 compiler.
|
||||
|
||||
#ifndef QS_PORT_H_
|
||||
#define QS_PORT_H_
|
||||
|
||||
// object pointer size in bytes
|
||||
#define QS_OBJ_PTR_SIZE 4U
|
||||
|
||||
// function pointer size in bytes
|
||||
#define QS_FUN_PTR_SIZE 4U
|
||||
|
||||
//============================================================================
|
||||
// NOTE: QS might be used with or without other QP components, in which
|
||||
// case the separate definitions of the macros QF_CRIT_STAT, QF_CRIT_ENTRY(),
|
||||
// and QF_CRIT_EXIT() are needed. In this port QS is configured to be used
|
||||
// with the other QP component, by simply including "qp_port.h"
|
||||
// *before* "qs.h".
|
||||
#ifndef QP_PORT_H_
|
||||
#include "qp_port.h" // use QS with QP
|
||||
#endif
|
||||
|
||||
#include "qs.h" // QS platform-independent public interface
|
||||
|
||||
#endif // QS_PORT_H_
|
@ -1,47 +0,0 @@
|
||||
//! @file
|
||||
//! @brief Selected exact-width and fast minimum-width integer types
|
||||
//! for 32-bit CPU architecture (e.g., ARM Cortex-M).
|
||||
//!
|
||||
//! @description
|
||||
//! This header is part of the ANSI C99 standard library to define the
|
||||
//! standard exact-width integer types (see C99 Section 7.18.1.1).
|
||||
//! If the compiler does not provide the stdint.h header file, you can
|
||||
//! either create one in the QP port directory, or you can typedef the
|
||||
//! 8 exact-width integer types directly in the qep_port.h header file.
|
||||
//!
|
||||
//! @note The version included in the QP documentation contains only the 8
|
||||
//! exact-width types and 6 fast minimum-width types actually used in QP.
|
||||
//! The actual definition of the integer types is platform dependent.
|
||||
#ifndef STDINT_H_
|
||||
#define STDINT_H_
|
||||
|
||||
//lint -save
|
||||
//lint -e9093 M3:R21.2(R) name matches a pattern reserved to the compiler
|
||||
//lint -e586 B18:R5.2(b) keyword 'short'/'long' is deprecated
|
||||
|
||||
// Exact-width types. WG14/N843 C99 Standard, Section 7.18.1.1
|
||||
typedef signed char int8_t; //!< exact-width 8-bit signed int
|
||||
typedef signed short int16_t; //!< exact-width 16-bit signed int
|
||||
typedef signed int int32_t; //!< exact-width 32-bit signed int
|
||||
typedef signed long long int64_t; //!< exact-width 64-bit signed int
|
||||
|
||||
typedef unsigned char uint8_t; //!< exact-width 8-bit unsigned int
|
||||
typedef unsigned short uint16_t; //!< exact-width 16-bit unsigned int
|
||||
typedef unsigned int uint32_t; //!< exact-width 32-bit unsigned int
|
||||
typedef unsigned long long uint64_t; //!< exact-width 64-bit unsigned int
|
||||
|
||||
// Fastest minimum-width types. WG14/N843 C99 Standard, Section 7.18.1.3
|
||||
typedef signed int int_fast8_t; //!< fast at-least 8-bit signed int
|
||||
typedef unsigned int uint_fast8_t; //!< fast at-least 8-bit unsigned int
|
||||
typedef signed int int_fast16_t; //!< fast at-least 16-bit signed int
|
||||
typedef unsigned int uint_fast16_t; //!< fast at-least 16-bit unsigned int
|
||||
typedef signed long int_fast32_t; //!< fast at-least 32-bit signed int
|
||||
typedef unsigned long uint_fast32_t; //!< fast at-least 32-bit unsigned int
|
||||
|
||||
// unsigned integer type capable of holding a pointer to void.
|
||||
typedef unsigned uintptr_t; //!< unsigned int capable of holding void*
|
||||
|
||||
//lint -restore
|
||||
|
||||
#endif // STDINT_H_
|
||||
|
@ -1,696 +0,0 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
// Copyright Vector Informatik GmbH 2019. All rights reserved.
|
||||
//
|
||||
// This file is provided by Vector Informatik GmbH (https://www.vector.com) for
|
||||
// use with PC-lint Plus. Redistribution is permitted but any redistribution
|
||||
// must preserve this notice and, if the redistributed file has been modified,
|
||||
// provide notice that the file has been modified from the original.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// au-barr.lnt -- Author options - BARR-C:2018
|
||||
//
|
||||
// This options file contains options to help enforce the
|
||||
// checks advocated by the Embedded C Coding Standard BARR-C:2018.
|
||||
// https://barrgroup.com/Embedded-Systems/Books/Embedded-C-Coding-Standard
|
||||
|
||||
//========== GENERAL RULES ==========
|
||||
|
||||
// 1.1 Which C?
|
||||
|
||||
/* Enable C99 mode */
|
||||
-std=c99
|
||||
|
||||
/* 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 */
|
||||
+e818
|
||||
-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 */
|
||||
+e952
|
||||
-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 '.c' */
|
||||
-hook(module_open, -cond(!('%[file_name]' ~ '[.]c$'),
|
||||
+message(8517, "module '%[file_name]' should have '.c' extension")))
|
||||
+e8517
|
||||
-append(8517,[BARR-C:2018 Rule 4.1b])
|
||||
|
||||
/* 8518 - header does not end with '.h' */
|
||||
-hook(header_open, -cond(!('%[file_name]' ~ '[.]h$'),
|
||||
+message(8517, "header '%[file_name]' should have '.h' extension")))
|
||||
+e8518
|
||||
-append(8518,[BARR-C:2018 Rule 4.1b])
|
||||
|
||||
/* 8519 - 'main' function defined in file that does not contain the word 'main' */
|
||||
-astquery(FunctionDecl : {
|
||||
getQualifiedNameAsString() == "main"
|
||||
isThisDeclarationADefinition()
|
||||
not "main" in getLocation().getBufferName()
|
||||
message(8519 "main function defined in file '" getLocation().getBufferName() "' 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 */
|
||||
-astquery(TypedefDecl : {
|
||||
$name = getNameAsString()
|
||||
$name ~~ "[^[:lower:]_]"
|
||||
message(8526 "typedef name '" $name "' should consist of lowercase letters and underscores")
|
||||
})
|
||||
+e8526
|
||||
-append(8526,[BARR-C:2018 Rule 5.1a])
|
||||
|
||||
/* 8527 - typedef name should end with '_t' suffix */
|
||||
-astquery(TypedefDecl : {
|
||||
$name = getNameAsString()
|
||||
not $name ~~ "_t$"
|
||||
message(8527 "typedef name '" $name " ' should end with '_t' suffix")
|
||||
})
|
||||
+e8527
|
||||
-append(8527,[BARR-C:2018 Rule 5.1a])
|
||||
|
||||
/* 8528 - non-anonymous struct/union/enum declared outside of typedef */
|
||||
-astquery(RecordDecl : {
|
||||
isFreeStanding() && not isAnonymousStructOrUnion()
|
||||
message(8528 "non-anonymous struct/union declared outside of a typedef")
|
||||
})
|
||||
-astquery(EnumDecl : {
|
||||
isFreeStanding() && hasName()
|
||||
message(8528 "non-anonymous enum declared outside of a typedef")
|
||||
})
|
||||
+e8528
|
||||
-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 */
|
||||
+e9209
|
||||
-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 */
|
||||
-astquery(BinaryOperator : {
|
||||
getLHS().getType().isIntegerType() && getRHS().getType().isIntegerType()
|
||||
$lhs_type = getLHS().ignoreParenImpCasts().getType()
|
||||
$rhs_type = getRHS().ignoreParenImpCasts().getType()
|
||||
! $lhs_type.isEnumeralType() && ! $lhs_type.isBooleanType()
|
||||
! $rhs_type.isEnumeralType() && ! $rhs_type.isBooleanType()
|
||||
$lhs_type.isUnsignedIntegerOrEnumerationType() != $rhs_type.isUnsignedIntegerOrEnumerationType()
|
||||
message(8524 "combining signed and unsigned types with operator '" getOpcodeStr "'")
|
||||
})
|
||||
+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 */
|
||||
-astquery(CStyleCastExpr() : {
|
||||
getType().isBooleanType()
|
||||
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++ */
|
||||
-astquery(FunctionDecl() : {
|
||||
("|" + getNameAsString() + "|") in "|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 '" currentnode "'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 */
|
||||
-astquery(FunctionDecl() : {
|
||||
("|" + getNameAsString() + "|") in "|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 '" currentnode "' 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 */
|
||||
-astquery(FunctionDecl : {
|
||||
getNameAsString().startsWith("_")
|
||||
message(8503 "function '" currentnode "' begins with an underscore")
|
||||
})
|
||||
+e8503
|
||||
-append(8503,[BARR-C:2018 Rule 6.1c])
|
||||
|
||||
/* 8504 - function name is longer than 31 characters */
|
||||
-astquery(FunctionDecl : {
|
||||
getNameAsString().length() > 31
|
||||
message(8504 "function '" currentnode "' is longer than 31 characters")
|
||||
})
|
||||
+e8504
|
||||
-append(8504,[BARR-C:2018 Rule 6.1d])
|
||||
|
||||
/* 8505 - function name contains upper case letter(s) */
|
||||
-astquery(FunctionDecl : {
|
||||
getNameAsString() ~~ "[[:upper:]]"
|
||||
message(8505 "function '" currentnode "' contains uppercase letters")
|
||||
})
|
||||
+e8505
|
||||
-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++ */
|
||||
-astquery(VarDecl : {
|
||||
("|" + getNameAsString() + "|") in "|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 '" currentnode "' 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 */
|
||||
-astquery(VarDecl : {
|
||||
("|" + getNameAsString() + "|") in "|errno|stderr|stdin|stdout|"
|
||||
message(8525 "variable '" currentnode "' 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 */
|
||||
-astquery(VarDecl : {
|
||||
getNameAsString().startsWith("_")
|
||||
message(8508 "variable '" currentnode "' begins with an underscore")
|
||||
})
|
||||
+e8508
|
||||
-append(8508,[BARR-C:2018 Rule 7.1c])
|
||||
|
||||
/* 8509 - variable name is longer than 31 characters */
|
||||
-astquery(VarDecl : {
|
||||
getNameAsString().length() > 31
|
||||
message(8509 "variable '" currentnode "' is longer than 31 characters")
|
||||
})
|
||||
+e8509
|
||||
-append(8509,[BARR-C:2018 Rule 7.1d])
|
||||
|
||||
/* 8510 - variable name contains less than 3 characters */
|
||||
-astquery(VarDecl : {
|
||||
getNameAsString().length() < 3
|
||||
message(8510 "variable '" currentnode "' contains less than 3 characters")
|
||||
})
|
||||
+e8510
|
||||
-append(8510,[BARR-C:2018 Rule 7.1e])
|
||||
|
||||
/* 8511 - variable name contains upper case letter(s) */
|
||||
-astquery(VarDecl : {
|
||||
getNameAsString() ~~ "[[:upper:]]"
|
||||
message(8511 "variable '" currentnode "' contains uppercase letters")
|
||||
})
|
||||
+e8511
|
||||
-append(8511,[BARR-C:2018 Rule 7.1f])
|
||||
|
||||
/* 8512 - global variable must start with 'g' */
|
||||
-astquery(VarDecl() : {
|
||||
hasExternalFormalLinkage()
|
||||
not getNameAsString().startsWith("g")
|
||||
message(8512 "global variable '" currentnode "' should have 'g' prefix")
|
||||
})
|
||||
+e8512
|
||||
-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 */
|
||||
-astquery(VarDecl() : {
|
||||
getType().isPointerType()
|
||||
if (getType().getPointeeType().isPointerType) {
|
||||
not getNameAsString().startsWith("pp")
|
||||
message(8514 "variable '" currentnode "' of type '" getType() "' should have 'pp' prefix")
|
||||
} else {
|
||||
not getNameAsString().startsWith("p")
|
||||
message(8513 "variable '" currentnode "' of type '" getType() "' should have 'p' prefix")
|
||||
}
|
||||
})
|
||||
+e8513
|
||||
+e8514
|
||||
-append(8513,[BARR-C:2018 Rule 7.1k])
|
||||
-append(8514,[BARR-C:2018 Rule 7.1l])
|
||||
|
||||
/* 8515 - boolean variable should have 'b' prefix */
|
||||
-astquery(VarDecl: {
|
||||
getType.isBooleanType()
|
||||
not getNameAsString().startsWith("b")
|
||||
message(8515 "boolean variable '" currentnode "' should have 'b' prefix")
|
||||
})
|
||||
+e8515
|
||||
-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 */
|
||||
-astquery(BinaryOperator() : {
|
||||
getOpcodeStr() == "=="
|
||||
$decl_ref = getLHS().ignoreParenCasts().DeclRefExpr()
|
||||
$decl_ref && getRHS().isConstantExpr()
|
||||
message(8522 "variable '" $decl_ref.getDecl() "' should appear on RHS of '==' operator")
|
||||
})
|
||||
+e8522
|
||||
-append(8522,[BARR-C:2018 Rule 8.6a])
|
@ -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
|
File diff suppressed because it is too large
Load Diff
@ -1,633 +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-c99.lnt -- Author options - QL-C99: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 C99 mode */
|
||||
-std=c99
|
||||
|
||||
/* 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 '.c' */
|
||||
-hook(module_open, -cond(!('%[file_name]' ~ '[.]c$'),
|
||||
+message(8517, "module '%[file_name]' should have '.c' extension")))
|
||||
+e8517
|
||||
-append(8517,[BARR-C:2018 Rule 4.1b])
|
||||
|
||||
/* 8518 - header does not end with '.h' */
|
||||
-hook(header_open, -cond(!('%[file_name]' ~ '[.]h$'),
|
||||
+message(8517, "header '%[file_name]' should have '.h' 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 */
|
||||
-hook(record_decl, -cond(%[is_freestanding] && !%[is_anonymous],
|
||||
+message(8528, "non-anonymous struct/union declared outside of a typedef")))
|
||||
-hook(enum_decl, -cond(%[is_freestanding] && '%[name]' != '',
|
||||
+message(8528, "non-anonymous enum declared outside of a typedef")))
|
||||
+e8528
|
||||
-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 */
|
||||
-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,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] [-u...] files
|
||||
@echo examples:
|
||||
@echo make -uQ_SPY -uQ_UTEST : use 32bit CPU (default) and undefine Q_SPY/Q_UTEST
|
||||
@echo make 16bit -uQ_SPY : use 16bit CPU includes and undefine Q_SPY
|
||||
@echo.
|
||||
|
||||
:: NOTE: adjust to for your installation directory of PC-Lint-Plus
|
||||
@set PCLP=C:\tools\lint-plus2\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 QPC=..\..
|
||||
|
||||
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\*.c
|
||||
|
||||
%PCLP% -os(lint_qv.log) std.lnt %LINTFLAGS% -iqv ..\..\src\qv\*.c
|
||||
|
||||
%PCLP% -os(lint_qk.log) std.lnt %LINTFLAGS% -iqk ..\..\src\qk\*.c
|
||||
|
||||
%PCLP% -os(lint_qxk.log) std.lnt %LINTFLAGS% -iqxk ..\..\src\qxk\*.c
|
||||
|
||||
%PCLP% -os(lint_qs.log) std.lnt %LINTFLAGS% -iqv ..\..\src\qs\*.c
|
||||
|
||||
:end
|
||||
@endlocal
|
@ -1,363 +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-14
|
||||
//! @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%QPC%/include // QP/C public includes
|
||||
|
||||
// standards
|
||||
// language standard...
|
||||
au-misra4.lnt // MISRA-C:2023 (MC4) compliance
|
||||
|
||||
// customized BARR-C:2018 style guidelines
|
||||
au-barr.lnt // BARR-C:2018 style guidelines
|
||||
-e8505 // suppress [Rule 6.1e] function contains uppercase letters
|
||||
-e8511 // suppress [Rule 7.1f] variable contains uppercase letters
|
||||
-e8512 // suppress [Rule 7.1j] global variable should have 'g' prefix
|
||||
-e8510 // suppress [Rule 7.1e] variable contains less than 3 characters
|
||||
-e8513 // suppress [Rule 7.1k] variable should have 'pp' prefix
|
||||
-e8514 // suppress [Rule 7.1l] variable should have 'p' prefix
|
||||
-e8515 // suppress [Rule 7.1m] boolean variable should have 'b' prefix
|
||||
-e8526 // suppress [Rule 5.1a] typedef name should consist of lowercase letters
|
||||
-e8527 // suppress [Rule 5.1a] typedef name should end with '_t' suffix
|
||||
-e9209 // suppress [Rule 5.2c] plain char data used with prohibited operator &
|
||||
-e8522 // suppress [Rule 8.6a] variable should appear on RHS of '==' operator
|
||||
|
||||
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 QP/C Applications
|
||||
qpc.lnt // QP/C options
|
||||
|
||||
//============================================================================
|
||||
// additional suppression rules for building QP/C source code...
|
||||
|
||||
// QEP -----------------------------------------------------------------------
|
||||
|
||||
//! M4-D4.9(A) function-like macro
|
||||
//! @tr{DVP-QP-MC4-D04_09A}
|
||||
-esym(9026,
|
||||
QACTIVE_CAST_)
|
||||
|
||||
//! M4-D4.9(A) function-like macro
|
||||
//! @tr{DVP-QP-MC4-D04_09B}
|
||||
-esym(9026,
|
||||
QHSM_RESERVED_EVT_,
|
||||
QS_STATE_ENTRY_,
|
||||
QS_STATE_EXIT_)
|
||||
|
||||
//! M4-R11.5(A) conversion from pointer to void to other pointer
|
||||
//! @tr{DVR-QP-MC4-R11_05}
|
||||
-emacro(9079,
|
||||
Q_EVT_CAST)
|
||||
|
||||
//! M4-R8.13(A) parameter of function could be pointer to const
|
||||
//! @tr{DVR-QP-MC4-R08_13}
|
||||
-efunc(818,
|
||||
QMsm_isIn_)
|
||||
|
||||
// QF ------------------------------------------------------------------------
|
||||
|
||||
//! M4-D4.8(A) complete definition is unnecessary in this translation unit
|
||||
//! @tr{DVP-QP-MC4-D04_08}
|
||||
-efile(9045,
|
||||
-qp_pkg.h)
|
||||
|
||||
//! M4-D4.9(A) function-like macro
|
||||
//! @tr{DVP-QP-MC4-D04_09A}
|
||||
-esym(9026,
|
||||
QF_CRIT_ENTRY,
|
||||
QF_CRIT_EXIT,
|
||||
Q_ASSERT_INCRIT,
|
||||
Q_REQUIRE_INCRIT,
|
||||
Q_ENSURE_INCRIT,
|
||||
Q_INVARIANT_INCRIT,
|
||||
Q_ERROR_INCRIT,
|
||||
QF_SCHED_LOCK_,
|
||||
QF_SCHED_UNLOCK_,
|
||||
QF_ISR_CONTEXT_,
|
||||
QF_MPOOL_EL,
|
||||
Q_UINTPTR_CAST_)
|
||||
|
||||
//! M4-R8.13(A) parameter of function could be pointer to const
|
||||
//! @tr{DVR-QP-MC4-R08_13}
|
||||
-efunc(818,
|
||||
QActive_start_)
|
||||
|
||||
//! M4-R11.3(R) cast from pointer to object type
|
||||
//! @tr{DVP-QP-MC4-R11_03B}
|
||||
-emacro(9087,
|
||||
QACTIVE_CAST_)
|
||||
|
||||
//! M4-R11.3(R) cast from pointer to object type
|
||||
//! @tr{DVP-QP-MC4-R11_03B}
|
||||
-efunc(9087,
|
||||
QActive_ctor,
|
||||
QMActive_ctor)
|
||||
|
||||
//! M4-R11.4(A) conversion between object pointer type and integer type
|
||||
//! @tr{DVR-QP-MC4-R11_04}
|
||||
-emacro(9078,
|
||||
Q_UINTPTR_CAST_)
|
||||
|
||||
//! M4-R11.5(A) conversion from pointer to void to other pointer type
|
||||
//! @tr{DVR-QP-MC4-R11_05}
|
||||
-emacro(9079,
|
||||
QACTIVE_CAST_,
|
||||
QF_EPOOL_GET_)
|
||||
-efunc(9079,
|
||||
QF_bzero_,
|
||||
QF_deleteRef_,
|
||||
QMPool_get,
|
||||
QMPool_put,
|
||||
QMPool_init,
|
||||
QTimeEvt_tick_,
|
||||
QTimeEvt_armX,
|
||||
QTimeEvt_rearm)
|
||||
|
||||
//! M4-R11.8(R) cast drops const qualifier
|
||||
//! @tr{DVR-QP-MC4-R11_08}
|
||||
-emacro(9005,
|
||||
QACTIVE_CAST_)
|
||||
-efunc(9005,
|
||||
QEvt_refCtr_inc_,
|
||||
QEvt_refCtr_dec_,
|
||||
QF_gc)
|
||||
|
||||
//! M4-R15.5(A) return statement before end of function
|
||||
//! @tr{DVP-QS-MC4-R15_05}
|
||||
-efunc(904,
|
||||
QActive_post_,
|
||||
QActive_postLIFO_)
|
||||
|
||||
//! M4-R18.3(R) relational operator <= applied to pointers
|
||||
//! @tr{DVR-QP-MC4-R18_03}
|
||||
-efunc(946,
|
||||
QMPool_get,
|
||||
QMPool_put)
|
||||
|
||||
//! definition of macro ends in semicolon
|
||||
//! @tr{DVR-QP-PCLP-823}
|
||||
-esym(823,
|
||||
QF_CRIT_STAT,
|
||||
QF_SCHED_STAT_)
|
||||
|
||||
//! suspicious pointer-to-pointer conversion (area too small)
|
||||
//! @tr{DVP-QP-PCLP-826}
|
||||
-emacro(826,
|
||||
QACTIVE_CAST_)
|
||||
|
||||
|
||||
// QV ------------------------------------------------------------------------
|
||||
|
||||
// QK ------------------------------------------------------------------------
|
||||
|
||||
//! M4-D4.9(A) function-like macro
|
||||
//! @tr{DVP-QP-MC4-D04_09A}
|
||||
-esym(9026,
|
||||
QK_ISR_CONTEXT_,
|
||||
QK_ISR_ENTRY,
|
||||
QK_ISR_EXIT)
|
||||
|
||||
// QXK -----------------------------------------------------------------------
|
||||
|
||||
//! M4-D4.9(A) function-like macro
|
||||
//! @tr{DVP-QP-MC4-D04_09A}
|
||||
-esym(9026,
|
||||
QXK_ISR_CONTEXT_,
|
||||
QXK_CONTEXT_SWITCH_,
|
||||
QXK_PTR_CAST_,
|
||||
QXTHREAD_CAST_,
|
||||
QXTHREAD_EQUEUE_SIGNAL_)
|
||||
|
||||
//! M4-R11.3(R) cast from pointer to object type
|
||||
//! @tr{DVP-QP-MC4-R11_03B}
|
||||
-emacro(9087,
|
||||
QXTHREAD_CAST_)
|
||||
|
||||
//! M4-R11.3(R) cast from pointer to object type
|
||||
//! @tr{DVR-QP-MC4-R11_03C}
|
||||
-emacro(9087,
|
||||
QXK_PTR_CAST_)
|
||||
|
||||
//! M4-R11.5(A) conversion from pointer to void to other pointer type
|
||||
//! @tr{DVR-QP-MC4-R11_05}
|
||||
-emacro(9079,
|
||||
QXK_PTR_CAST_)
|
||||
|
||||
//! MC3-R8.13(A) could be pointer to const
|
||||
//! @tr{DVR-QP-MC4-R08_13}
|
||||
-efunc(818,
|
||||
QXThread_init_,
|
||||
QXThread_dispatch_,
|
||||
QXThread_postLIFO_)
|
||||
|
||||
//! @tr{DVP-QP-PCLP-826}
|
||||
-emacro(826,
|
||||
QXK_PTR_CAST_,
|
||||
QXTHREAD_CAST_)
|
||||
|
||||
//! cast increases required alignment from 2 to 4
|
||||
//! @tr{DVR-QP-PCLP-2445}
|
||||
-emacro(2445,
|
||||
QXK_PTR_CAST_)
|
||||
|
||||
// QS ------------------------------------------------------------------------
|
||||
// the following options are needed only when Q_SPY is defined...
|
||||
|
||||
//! M4-D4.9(A) function-like macro
|
||||
//! @tr{DVP-QS-MC4-D04_09A}
|
||||
-esym(9026,
|
||||
QS_INSERT_BYTE_,
|
||||
QS_INSERT_ESC_BYTE_,
|
||||
QS_RX_TRAN_,
|
||||
QS_CRIT_ENTRY,
|
||||
QS_CRIT_EXIT)
|
||||
|
||||
//! M4-R8.13(A) parameter ... of function could be pointer to const
|
||||
//! @tr{DVR-QS-MC4-R08_13}
|
||||
-efunc(818,
|
||||
QHsmDummy_init_,
|
||||
QHsmDummy_dispatch_,
|
||||
QActiveDummy_start_,
|
||||
QActiveDummy_init_,
|
||||
QActiveDummy_dispatch_)
|
||||
|
||||
//! M4-R11.1(R) conversion between pointer to function and differing type
|
||||
//! @tr{DVP-QS-MC4-R11_01}
|
||||
-emacro(9074,
|
||||
QS_FUN_PRE_)
|
||||
-efunc(9074,
|
||||
QS_getTestProbe_)
|
||||
|
||||
//! M4-R11.3(R) cast from pointer to object type
|
||||
//! @tr{DVR-QS-MC4-R11_03C}
|
||||
-efile(9087,
|
||||
-qs_rx.c,
|
||||
-qutest.c)
|
||||
|
||||
//! M4-R11.4(A) conversion between object pointer type and integer type
|
||||
//! @tr{DVR-QS-MC4-R11_04}
|
||||
-emacro(9078,
|
||||
QS_OBJ_PRE_,
|
||||
QS_FUN_PRE_)
|
||||
-efunc(9078,
|
||||
QS_rxHandleGoodFrame_,
|
||||
QS_getTestProbe_)
|
||||
|
||||
//! M4-R11.5(A) conversion from pointer to void to other pointer type
|
||||
//! @tr{DVR-QS-MC4-R11_05}
|
||||
-efile(9079,
|
||||
-qs_rx.c,
|
||||
-qutest.c)
|
||||
|
||||
//! M4-R11.6(R) explicit cast from integer to 'void *'
|
||||
//! @tr{DVR-QS-MC4-R11_06}
|
||||
-emacro(923,
|
||||
QS_OBJ_PRE_,
|
||||
QS_FUN_PRE_)
|
||||
-efunc(923,
|
||||
QS_rxHandleGoodFrame_,
|
||||
QS_getTestProbe_)
|
||||
|
||||
//! M4-R14.3(R) boolean condition for 'if' always evaluates to 'false'
|
||||
//! @tr{DVR-QS-MC4-R14_03}
|
||||
-emacro(774,
|
||||
QS_BEGIN_PRE_)
|
||||
|
||||
//! M4-R19.2(A) union declared
|
||||
//! @tr{DVR-QS-MC4-R19_02}
|
||||
-efunc(9018,
|
||||
QS_target_info_pre_,
|
||||
QS_f32_fmt_,
|
||||
QS_f64_fmt_)
|
||||
|
||||
//! constant value used in Boolean context (left operand to || operator)
|
||||
//! @tr{DVR-QS-PCLP-506}
|
||||
-emacro(506,
|
||||
QS_BEGIN_PRE_)
|
||||
|
||||
//! excessive shift value (precision 0 shifted right by ...)
|
||||
//! @tr{DVR-QS-PCLP-572}
|
||||
-emacro(572,
|
||||
QS_BEGIN_PRE_)
|
||||
|
||||
//! union initialization
|
||||
//! @tr{DVR-QS-PCLP-708}
|
||||
-efunc(708,
|
||||
QS_f64_fmt_)
|
||||
|
||||
//! union member not referenced
|
||||
//! @tr{DVR-QS-PCLP-754}
|
||||
-esym(754,
|
||||
Variant::aFlt,
|
||||
AFltVar::prio,
|
||||
*U32Rep::u32)
|
||||
|
||||
//! Constant expression evaluates to 0 in 'binary' operation '>>'
|
||||
//! @tr{DVR-QS-PCLP-778}
|
||||
-emacro(778,
|
||||
QS_BEGIN_PRE_)
|
||||
|
||||
//! suspicious pointer-to-pointer conversion (area too small)
|
||||
//! @tr{DVR-QS-PCLP-818}
|
||||
-efile(826,
|
||||
-qs_rx.c,
|
||||
-qutest.c)
|
||||
|
||||
//! definition of macro ends in semicolon
|
||||
//! @tr{DVR-QS-PCLP-823}
|
||||
-esym(823,
|
||||
QS_CRIT_STAT,
|
||||
QS_BEGIN_PRE_)
|
||||
|
||||
//! the right operand to << always evaluates to 0
|
||||
//! @tr{DVR-QS-PCLP-845}
|
||||
-emacro(845,
|
||||
QS_BEGIN_PRE_)
|
||||
|
||||
//! cast increases required alignment
|
||||
//! @tr{DVP-QS-PCLP-2445}
|
||||
-efunc(2445,
|
||||
QS_rxHandleGoodFrame_,
|
||||
QS_rxPoke_)
|
||||
|
@ -1,94 +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 qpc_7_3_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QP/C "port" to PC-Lint-Plus, QK kernel, generic C99
|
||||
|
||||
#ifndef QP_PORT_H_
|
||||
#define QP_PORT_H_
|
||||
|
||||
#include <stdint.h> // Exact-width types. WG14/N843 C99 Standard
|
||||
#include <stdbool.h> // Boolean type. WG14/N843 C99 Standard
|
||||
|
||||
#ifdef QP_CONFIG
|
||||
#include "qp_config.h" // external QP configuration
|
||||
#endif
|
||||
|
||||
// no-return function specifier (C11 Standard)
|
||||
#define Q_NORETURN _Noreturn void
|
||||
|
||||
// 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 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() ((void)0)
|
||||
|
||||
// Define the ISR exit sequence
|
||||
#define QK_ISR_EXIT() do { \
|
||||
QF_INT_DISABLE(); \
|
||||
if (QK_sched_() != 0U) { \
|
||||
*Q_UINT2PTR_CAST(uint32_t, 0xE000ED04U) = (1U << 28U);\
|
||||
} \
|
||||
QF_INT_ENABLE(); \
|
||||
} while (false)
|
||||
|
||||
void intDisable(void);
|
||||
void intEnable(void);
|
||||
uint32_t critEntry(void);
|
||||
void critExit(uint32_t stat);
|
||||
uint32_t QK_get_IPSR(void);
|
||||
|
||||
// include files -------------------------------------------------------------
|
||||
#include "qequeue.h" // QK kernel uses the native QP event queue
|
||||
#include "qmpool.h" // QK kernel uses the native QP memory pool
|
||||
#include "qp.h" // QP framework
|
||||
#include "qk.h" // QK kernel
|
||||
|
||||
#endif // QP_PORT_H_
|
||||
|
@ -1,562 +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.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Adapted by Quantum Leaps from au-barr.lnt
|
||||
//
|
||||
// ql-style.lnt.lnt -- Author options - Quantum-Leaps:2018
|
||||
//
|
||||
// This options file contains options to help enforce the
|
||||
// checks advocated by the Quantum Leaps Coding Standard
|
||||
// https://barrgroup.com/Embedded-Systems/Books/Embedded-C-Coding-Standard
|
||||
|
||||
//========== GENERAL RULES ==========
|
||||
|
||||
// 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 */
|
||||
+e818
|
||||
-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 */
|
||||
+e952
|
||||
-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
|
||||
|
||||
/* 8517 - module does not end with '.c' */
|
||||
-hook(module_open, -cond(!('%[file_name]' ~ '[.]c$'),
|
||||
+message(8517, "module '%[file_name]' should have '.c' extension")))
|
||||
+e8517
|
||||
-append(8517,[BARR-C:2018 Rule 4.1b])
|
||||
|
||||
/* 8518 - header does not end with '.h' */
|
||||
-hook(header_open, -cond(!('%[file_name]' ~ '[.]h$'),
|
||||
+message(8517, "header '%[file_name]' should have '.h' 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 ==========
|
||||
|
||||
/* 8528 - non-anonymous struct/union/enum declared outside of typedef */
|
||||
-hook(record_decl, -cond(%[is_freestanding] && !%[is_anonymous],
|
||||
+message(8528, "non-anonymous struct/union declared outside of a typedef")))
|
||||
-hook(enum_decl, -cond(%[is_freestanding] && '%[name]' != '',
|
||||
+message(8528, "non-anonymous enum declared outside of a typedef")))
|
||||
+e8528
|
||||
-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])
|
||||
|
||||
// 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 */
|
||||
-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])
|
||||
|
||||
/* 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])
|
||||
|
||||
|
||||
// 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 */
|
||||
-hook(binary_expr, -cond('%[opcode]' == '==' &&
|
||||
'%[walk_lhs_expr.walk_past_paren_cast.set_msg_loc.is_decl_ref_expr]' == 'true' &&
|
||||
'%[walk_rhs_expr.is_constant_expr]' == 'true',
|
||||
+message(8522, "variable '%[walk_lhs_expr.walk_past_paren_cast.walk_decl.qual_name]' should appear on RHS of '==' operator")))
|
||||
+e8522
|
||||
-append(8522,[BARR-C:2018 Rule 8.6a])
|
@ -1,426 +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-06-11
|
||||
//! @version Last updated for version: 7.4.0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief PC-Lint-Plus option file for analysing both **QP/C**
|
||||
//! and **QP/C Applications**
|
||||
|
||||
// C Language Standard
|
||||
-std=c99 // apply the C99 Language Standard
|
||||
|
||||
//! M4-D4.8(A) complete definition is unnecessary in this translation unit
|
||||
//! @tr{DVP-QP-MC4-D04_08}
|
||||
-efile(9045,
|
||||
-qp.h,
|
||||
-qequeue.h,
|
||||
-qmpool.h,
|
||||
-qv.h,
|
||||
-qk.h,
|
||||
-qxk.h,
|
||||
-qs.h)
|
||||
|
||||
// Functional Safety (FuSa) System --------------------------------------------
|
||||
|
||||
// "no return" semantics for error/failure callbacks
|
||||
-sem(Q_onError, r_no)
|
||||
-sem(assert_failed, r_no)
|
||||
|
||||
//! M4-D4.9(A) function-like macro
|
||||
//! @tr{DVP-QP-MC4-D04_09A} (false-positive)
|
||||
-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)
|
||||
|
||||
//! PCLP definition of macro ends in semicolon
|
||||
//! @tr{DVP-QP-PCLP-823}
|
||||
-esym(823,
|
||||
Q_DEFINE_THIS_MODULE)
|
||||
|
||||
//! BARR-C(R1.8b) parameter of function could be const
|
||||
-efunc(952,
|
||||
Q_onError
|
||||
)
|
||||
|
||||
// QEP -----------------------------------------------------------------------
|
||||
//! M4-D4.9(A) function-like macro
|
||||
//! @tr{DVP-QP-MC4-D04_09A} (false-positive)
|
||||
-esym(9026,
|
||||
Q_UNUSED_PAR,
|
||||
Q_TRAN,
|
||||
Q_TRAN_HIST,
|
||||
Q_SUPER,
|
||||
Q_HANDLED,
|
||||
Q_UNHANDLED,
|
||||
Q_IGNORED,
|
||||
Q_ASM_UPCAST,
|
||||
Q_HSM_UPCAST,
|
||||
Q_MSM_UPCAST,
|
||||
Q_EVT_CAST,
|
||||
QEVT_INITIALIZER,
|
||||
Q_UINT2PTR_CAST,
|
||||
Q_STATE_CAST,
|
||||
Q_ACTION_CAST,
|
||||
QASM_INIT,
|
||||
QASM_DISPATCH,
|
||||
QASM_IS_IN)
|
||||
|
||||
//! M4-D4.9(A) function-like macro
|
||||
//! @tr{DVP-QP-MC4-D04_09B} (correct identification)
|
||||
-esym(9026,
|
||||
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,
|
||||
QMSM_INIT,
|
||||
QMSM_DISPATCH)
|
||||
|
||||
//! M4-R11.1(R) conversion between pointer to function type
|
||||
//! @tr{DVP-QP-MC4-R11_01}
|
||||
-emacro(9074,
|
||||
Q_STATE_CAST,
|
||||
Q_ACTION_CAST,
|
||||
Q_TRAN,
|
||||
Q_TRAN_HIST,
|
||||
Q_SUPER,
|
||||
QM_ENTRY,
|
||||
QM_EXIT,
|
||||
QM_SM_EXIT,
|
||||
QM_TRAN,
|
||||
QM_TRAN_INIT,
|
||||
QM_TRAN_HIST,
|
||||
QM_TRAN_EP,
|
||||
QM_TRAN_XP)
|
||||
|
||||
//! M4-R11.3(R) cast from pointer to pointer (upcast)
|
||||
//! @tr{DVP-QP-MC4-R11_03A}
|
||||
-emacro(9087,
|
||||
Q_ASM_UPCAST,
|
||||
Q_HSM_UPCAST,
|
||||
Q_MSM_UPCAST,
|
||||
QM_TRAN,
|
||||
QM_TRAN_EP,
|
||||
QM_TRAN_INIT)
|
||||
|
||||
//! M4-R11.3(R) cast from pointer to pointer (downcast)
|
||||
//! @tr{DVP-QP-MC4-R11_03B}
|
||||
-emacro(9087,
|
||||
Q_EVT_CAST)
|
||||
|
||||
//! M4-R12.3(A) comma operator used
|
||||
//! @tr{DVP-QP-MC4-R12_03}
|
||||
-emacro(9008,
|
||||
Q_SUPER,
|
||||
Q_TRAN,
|
||||
Q_TRAN_HIST,
|
||||
QM_ENTRY,
|
||||
QM_EXIT,
|
||||
QM_SUPER_SUB,
|
||||
QM_TRAN,
|
||||
QM_TRAN_INIT,
|
||||
QM_TRAN_EP,
|
||||
QM_TRAN_XP,
|
||||
QM_SM_EXIT,
|
||||
QM_SUPER_SUB)
|
||||
|
||||
//! M4-R13.4(A) result of assignment used in left operand to ',' operator
|
||||
//! @tr{DVP-QP-MC4-R13_04}
|
||||
-emacro(9084,
|
||||
Q_SUPER,
|
||||
Q_TRAN,
|
||||
QM_ENTRY,
|
||||
QM_EXIT,
|
||||
QM_TRAN,
|
||||
QM_TRAN_INIT,
|
||||
QM_TRAN_HIST,
|
||||
QM_TRAN_EP,
|
||||
QM_TRAN_XP,
|
||||
QM_SM_EXIT,
|
||||
QM_SUPER_SUB)
|
||||
|
||||
//! M4-R19.2(A) union declared
|
||||
//! @tr{DVP-QP-MC4-R19_02}
|
||||
-esym(9018,
|
||||
QAsmAttr)
|
||||
|
||||
//! '<symbol>' not referenced in QM-style state machines
|
||||
//! @tr{DVP-QP-PCLP-754}
|
||||
-esym(754,
|
||||
*(anonymous struct)::act,
|
||||
*(anonymous struct)::target)
|
||||
|
||||
//! suspicious pointer-to-pointer conversion (area too small)
|
||||
//! @tr{DVP-QP-PCLP-826}
|
||||
-emacro(826,
|
||||
Q_EVT_CAST)
|
||||
|
||||
// deprecated QEP facilities...
|
||||
-deprecate( type, QFsm, QP/C API pre 5.4.x)
|
||||
-deprecate( function, QFsm_ctor, QP/C API pre 5.4.x)
|
||||
-deprecate( function, QF_onIdle, QP/C API pre 5.4.x)
|
||||
-deprecate( macro, Q_IGNORED, QP/C API pre 5.4.x)
|
||||
-deprecate( macro, QMSM_INIT, QP/C API pre 5.8.x)
|
||||
-deprecate( macro, QMSM_DISPATCH, QP/C API pre 5.8.x)
|
||||
|
||||
// QF ------------------------------------------------------------------------
|
||||
|
||||
//! M4-D4.9(A) function-like macro
|
||||
//! @tr{DVP-QP-MC4-D04_09B}
|
||||
-esym(9026,
|
||||
QF_INT_DISABLE,
|
||||
QF_INT_ENABLE,
|
||||
Q_PRIO,
|
||||
QF_LOG2,
|
||||
Q_NEW,
|
||||
Q_NEW_X,
|
||||
Q_NEW_REF,
|
||||
Q_DELETE_REF,
|
||||
QF_PUBLISH,
|
||||
QF_CRIT_ENTRY,
|
||||
QF_CRIT_EXIT,
|
||||
QF_CRIT_EXIT_NOP,
|
||||
QF_MEM_SYS,
|
||||
QF_MEM_APP,
|
||||
QF_MPOOL_EL,
|
||||
QF_LOG2,
|
||||
QF_EPOOL_INIT_,
|
||||
QF_EPOOL_EVENT_SIZE_,
|
||||
QF_EPOOL_GET_,
|
||||
QF_EPOOL_PUT_,
|
||||
QF_PTR_INC_,
|
||||
QACTIVE_START,
|
||||
QACTIVE_POST,
|
||||
QACTIVE_POST_X,
|
||||
QACTIVE_POST_LIFO,
|
||||
QACTIVE_PUBLISH,
|
||||
QACTIVE_EQUEUE_WAIT_,
|
||||
QACTIVE_EQUEUE_SIGNAL_,
|
||||
QACTIVE_EQUEUE_ONEMPTY_,
|
||||
QTIMEEVT_TICK,
|
||||
QTIMEEVT_TICK_X,
|
||||
QTICKER_TRIG,
|
||||
QF_TICK,
|
||||
QF_TICK_X)
|
||||
|
||||
//! M4-R11.3(R) cast to pointer to different object type (upcast)
|
||||
//! @tr{DVP-QP-MC4-R11_03A}
|
||||
-emacro(9087,
|
||||
QACTIVE_POST,
|
||||
QACTIVE_POST_LIFO)
|
||||
|
||||
//! M4-R11.3(R) cast to pointer to different object type (downcast)
|
||||
//! @tr{DVP-QP-MC4-R11_03B}
|
||||
-emacro(9087,
|
||||
Q_NEW,
|
||||
Q_NEW_X)
|
||||
|
||||
//! suspicious pointer-to-pointer conversion (area too small)
|
||||
//! @tr{DVP-QP-PCLP-826}
|
||||
-emacro(826,
|
||||
QACTIVE_POST,
|
||||
QACTIVE_POST_X,
|
||||
QACTIVE_POST_LIFO,
|
||||
Q_NEW,
|
||||
Q_NEW_X)
|
||||
|
||||
// deprecated QF facilities...
|
||||
-deprecate( macro,QTimeEvt_ctor, QP/C API pre 5.8.x)
|
||||
-deprecate( macro,QTimeEvt_postIn, QP/C API pre 5.8.x)
|
||||
-deprecate( macro,QTimeEvt_postEvery, QP/C API pre 5.8.x)
|
||||
|
||||
// QV ------------------------------------------------------------------------
|
||||
//! M4-D4.9(A) function-like macro
|
||||
//! @tr{DVP-QP-MC4-D04_09A}
|
||||
-esym(9026,
|
||||
QV_CPU_SLEEP)
|
||||
|
||||
// QK ------------------------------------------------------------------------
|
||||
// M4-D4.9(A) function-like macro
|
||||
//! @tr{DVP-QP-MC4-D04_09A}
|
||||
-esym(9026,
|
||||
QK_ISR_ENTRY,
|
||||
QK_ISR_EXIT,
|
||||
QK_ISR_CONTEXT_)
|
||||
|
||||
// QXK -----------------------------------------------------------------------
|
||||
//! M4-D4.9(A) function-like macro
|
||||
//! @tr{DVP-QP-MC4-D04_09A}
|
||||
-esym(9026,
|
||||
QXK_ISR_ENTRY,
|
||||
QXK_ISR_EXIT,
|
||||
QXK_TLS,
|
||||
QXTHREAD_START,
|
||||
QXTHREAD_POST_X)
|
||||
|
||||
// deprecated QXK facilities...
|
||||
-deprecate( macro, Q_XTHREAD_CAST, QP/C API pre 6.7.x)
|
||||
|
||||
// QS ------------------------------------------------------------------------
|
||||
|
||||
//! M4-D4.9(A) function-like macro
|
||||
//! @tr{DVP-QS-MC4-D04_09A}
|
||||
-esym(9026,
|
||||
QS_INIT,
|
||||
QS_EXIT,
|
||||
QS_DUMP,
|
||||
QS_RESET,
|
||||
QS_GLB_FILTER,
|
||||
QS_LOC_FILTER,
|
||||
QS_FILTER_ON,
|
||||
QS_FILTER_OFF,
|
||||
QS_FILTER_SM_OBJ,
|
||||
QS_FILTER_AO_OBJ,
|
||||
QS_FILTER_MP_OBJ,
|
||||
QS_FILTER_EQ_OBJ,
|
||||
QS_FILTER_TE_OBJ,
|
||||
QS_FILTER_AP_OBJ,
|
||||
QS_GET_BYTE,
|
||||
QS_GET_BLOCK,
|
||||
QS_BEGIN,
|
||||
QS_BEGIN_ID,
|
||||
QS_END,
|
||||
QS_BEGIN_INCRIT,
|
||||
QS_END_INCRIT,
|
||||
QS_TR_CRIT_ENTRY,
|
||||
QS_TR_CRIT_EXIT,
|
||||
QS_TR_ISR_ENTRY,
|
||||
QS_TR_ISR_EXIT,
|
||||
QS_ONLY,
|
||||
QS_REC_DONE,
|
||||
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_SIG,
|
||||
QS_ENUM,
|
||||
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)
|
||||
|
||||
//! M4-D4.9(A) function-like macro
|
||||
//! @tr{DVP-QS-MC4-D04_09A}
|
||||
-esym(9026,
|
||||
QS_CRIT_ENTRY,
|
||||
QS_CRIT_EXIT,
|
||||
QS_MEM_SYS,
|
||||
QS_MEM_APP,
|
||||
QS_GLB_CHECK_,
|
||||
QS_LOC_CHECK_,
|
||||
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_)
|
||||
|
||||
//! M4-R11.1(R) conversion between pointer to function type
|
||||
//! @tr{DVP-QS-MC4-R11_01}
|
||||
-emacro(9074,
|
||||
QS_FUN_DICTIONARY,
|
||||
QS_TEST_PROBE_DEF)
|
||||
|
||||
// M4-R15.5(A) return statement before end of function
|
||||
//! @tr{DVP-QS-MC4-R15_05}
|
||||
-emacro(904,
|
||||
QS_TEST_PROBE)
|
||||
|
||||
//! M4-R19.2(A) union declared
|
||||
//! @tr{DVR-QS-MC4-R19_02}
|
||||
-esym(9018,
|
||||
Variant)
|
||||
|
||||
//! M4-R20.10(A) stringize operator
|
||||
//! @tr{DVP-QS-MC4-R20_10}
|
||||
-esym(9024,
|
||||
QS_OBJ_DICTIONARY,
|
||||
QS_OBJ_ARR_DICTIONARY,
|
||||
QS_FUN_DICTIONARY,
|
||||
QS_SIG_DICTIONARY,
|
||||
QS_USR_DICTIONARY,
|
||||
QS_ENUM_DICTIONARY)
|
||||
|
||||
//! implicit conversion of enum to integral type 'int'
|
||||
//! @tr{DVP-QS-PCLP-641}
|
||||
-emacro(641,
|
||||
QS_SIG_DICTIONARY)
|
||||
|
||||
//! definition of macro ends in semicolon
|
||||
//! @tr{DVP-QS-PCLP-823}
|
||||
-esym(823,
|
||||
QS_TEST_PROBE_DEF)
|
@ -1,86 +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 qpc_7_3_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QP/C "port" to PC-Lint-Plus, QV kernel, generic C99
|
||||
|
||||
#ifndef QP_PORT_H_
|
||||
#define QP_PORT_H_
|
||||
|
||||
#include <stdint.h> // Exact-width types. WG14/N843 C99 Standard
|
||||
#include <stdbool.h> // Boolean type. WG14/N843 C99 Standard
|
||||
|
||||
#ifdef QP_CONFIG
|
||||
#include "qp_config.h" // external QP configuration
|
||||
#endif
|
||||
|
||||
// no-return function specifier (C11 Standard)
|
||||
#define Q_NORETURN _Noreturn void
|
||||
|
||||
// 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 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)
|
||||
|
||||
void intDisable(void);
|
||||
void intEnable(void);
|
||||
uint32_t critEntry(void);
|
||||
void critExit(uint32_t stat);
|
||||
|
||||
// include files -------------------------------------------------------------
|
||||
#include "qequeue.h" // QV kernel uses the native QP event queue
|
||||
#include "qmpool.h" // QV kernel uses the native QP memory pool
|
||||
#include "qp.h" // QP framework
|
||||
#include "qv.h" // QV kernel
|
||||
|
||||
#endif // QP_PORT_H_
|
||||
|
@ -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 qpc_7_3_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QP/C "port" to PC-Lint-Plus, QXK kernel, generic C99
|
||||
|
||||
#ifndef QP_PORT_H_
|
||||
#define QP_PORT_H_
|
||||
|
||||
#include <stdint.h> // Exact-width types. WG14/N843 C99 Standard
|
||||
#include <stdbool.h> // Boolean type. WG14/N843 C99 Standard
|
||||
|
||||
#ifdef QP_CONFIG
|
||||
#include "qp_config.h" // external QP configuration
|
||||
#endif
|
||||
|
||||
// no-return function specifier (C11 Standard)
|
||||
#define Q_NORETURN _Noreturn void
|
||||
|
||||
// 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 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() ((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())
|
||||
|
||||
void intDisable(void);
|
||||
void intEnable(void);
|
||||
uint32_t critEntry(void);
|
||||
void critExit(uint32_t stat);
|
||||
uint32_t QXK_get_IPSR(void);
|
||||
void QXK_trigPendSV(void);
|
||||
|
||||
// include files -------------------------------------------------------------
|
||||
#include "qequeue.h" // QXK kernel uses the native QP event queue
|
||||
#include "qmpool.h" // QXK kernel uses the native QP memory pool
|
||||
#include "qp.h" // QP framework
|
||||
#include "qxk.h" // QXK kernel
|
||||
|
||||
#endif // QP_PORT_H_
|
||||
|
@ -1,44 +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-06-06
|
||||
//! @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
|
||||
-width(120,4) // break lines after 99 characters with 4 characters indent
|
||||
+flm // make sure no foreign includes change the format
|
||||
|
||||
-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() // output a summary of all produced messages
|
||||
|
||||
// globally suppress the following warnings:
|
||||
-e546 // explicitly taking address of function
|
||||
-e717 // monocarpic do-while used to group statements
|
@ -1,30 +0,0 @@
|
||||
//! @file
|
||||
//! @brief Boolean type and constansts. WG14/N843 C99 Standard, Section 7.16
|
||||
//!
|
||||
//! @description
|
||||
//! This header is part of the ANSI C99 standard library to define the
|
||||
//! standard Boolean type as well as the 'true' and 'false' constansts.
|
||||
#ifndef STDBOOL_H_
|
||||
#define STDBOOL_H_
|
||||
|
||||
//lint -save
|
||||
//lint -e9071 M3-R21.1(r), defined macro is reserved to the compiler
|
||||
//lint -e9093 the name is reserved to the compiler
|
||||
//lint -emacro(8523, false, true) cast to boolean
|
||||
|
||||
#ifndef __cplusplus
|
||||
|
||||
typedef _Bool bool; //!< standard Boolean data type
|
||||
|
||||
//! standard 'false' constant
|
||||
#define false ((bool)0)
|
||||
|
||||
//! standard 'true' constant
|
||||
#define true ((bool)1)
|
||||
|
||||
#endif // !__cplusplus
|
||||
|
||||
//lint -restore
|
||||
|
||||
#endif // STDBOOL_H_
|
||||
|
@ -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,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 qpc_7_4_0
|
||||
//!
|
||||
//! @file
|
||||
//! @brief QS/C port to a 16-bit CPU and a generic C99 compiler.
|
||||
|
||||
#ifndef QS_PORT_H_
|
||||
#define QS_PORT_H_
|
||||
|
||||
// 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.h"
|
||||
// *before* "qs.h".
|
||||
#ifndef QP_PORT_H_
|
||||
#include "qp_port.h" // use QS with QP
|
||||
#endif
|
||||
|
||||
#include "qs.h" // QS platform-independent public interface
|
||||
|
||||
#endif // QS_PORT_H_
|
@ -1,47 +0,0 @@
|
||||
//! @file
|
||||
//! @brief Selected exact-width and fast minimum-width integer types
|
||||
//! for 16-bit CPU architecture (e.g., MSP430).
|
||||
//!
|
||||
//! @description
|
||||
//! This header is part of the ANSI C99 standard library to define the
|
||||
//! standard exact-width integer types (see C99 Section 7.18.1.1).
|
||||
//! If the compiler does not provide the stdint.h header file, you can
|
||||
//! either create one in the QP port directory, or you can typedef the
|
||||
//! 8 exact-width integer types directly in the qep_port.h header file.
|
||||
//!
|
||||
//! @note The version included in the QP documentation contains only the 8
|
||||
//! exact-width types and 6 fast minimum-width types actually used in QP.
|
||||
//! The actual definition of the integer types is platform dependent.
|
||||
#ifndef STDINT_H_
|
||||
#define STDINT_H_
|
||||
|
||||
//lint -save
|
||||
//lint -e9093 M3:R21.2(R) name matches a pattern reserved to the compiler
|
||||
//lint -e586 B18:R5.2(b) keyword 'short'/'long' is deprecated
|
||||
|
||||
// Exact-width types. WG14/N843 C99 Standard, Section 7.18.1.1
|
||||
typedef signed char int8_t; //!< exact-width 8-bit signed int
|
||||
typedef signed int int16_t; //!< exact-width 16-bit signed int
|
||||
typedef signed long int int32_t; //!< exact-width 32-bit signed int
|
||||
typedef signed long long int64_t; //!< exact-width 64-bit signed int
|
||||
|
||||
typedef unsigned char uint8_t; //!< exact-width 8-bit unsigned int
|
||||
typedef unsigned int uint16_t; //!< exact-width 16-bit unsigned int
|
||||
typedef unsigned long int uint32_t; //!< exact-width 32-bit unsigned int
|
||||
typedef unsigned long long uint64_t; //!< exact-width 64-bit unsigned int
|
||||
|
||||
// Fastest minimum-width types. WG14/N843 C99 Standard, Section 7.18.1.3
|
||||
typedef signed int int_fast8_t; //!< fast at-least 8-bit signed int
|
||||
typedef unsigned int uint_fast8_t; //!< fast at-least 8-bit unsigned int
|
||||
typedef signed int int_fast16_t; //!< fast at-least 16-bit signed int
|
||||
typedef unsigned int uint_fast16_t; //!< fast at-least 16-bit unsigned int
|
||||
typedef signed long int_fast32_t; //!< fast at-least 32-bit signed int
|
||||
typedef unsigned long uint_fast32_t; //!< fast at-least 32-bit unsigned int
|
||||
|
||||
// unsigned integer type capable of holding a pointer to void.
|
||||
typedef unsigned uintptr_t; //!< unsigned int capable of holding void*
|
||||
|
||||
//lint -restore
|
||||
|
||||
#endif // STDINT_H_
|
||||
|
@ -1,3 +0,0 @@
|
||||
// Size Options for 32bit CPU (e.g., ARM Cortex-M)
|
||||
-si4 -sl4 -sll8 -ss2 -sw4 -sp4 -sf4 -sd8 -sld8
|
||||
|
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