Compare commits
248 Commits
mueller/sp
...
docker_d3
Author | SHA1 | Date | |
---|---|---|---|
7de56f189b | |||
541f563683 | |||
28ea71a077 | |||
a044d7d724 | |||
687700cee8 | |||
732b615cb3 | |||
394ce2ec3e | |||
dde96ae220 | |||
c3aaab4b93 | |||
edf1d5ae8d | |||
690991b4b5 | |||
1a294e6a13 | |||
8c4e34153b | |||
b60e4bcb90 | |||
b18410aa63 | |||
7f57a8784a | |||
4b33aa8262 | |||
d47a908117 | |||
fce95e04a8 | |||
fc742e4270 | |||
b5183a19fc | |||
ca453a8f16 | |||
b7c0c07141 | |||
0158102f11 | |||
69859fdbc9 | |||
90bccc744e | |||
ab89108c55 | |||
a682bbe400 | |||
e67fc2ab0d | |||
71ce966531 | |||
6b0f4a159f | |||
4a06b558c1 | |||
6d921f03fd | |||
65bc8213fe | |||
a0ee86ace8 | |||
a07a368272 | |||
cb8a4bbbec | |||
17f54006b8 | |||
395cf9cfa7 | |||
a3c0b441ec | |||
b4132800ae | |||
ad53b48fcb | |||
dee40f9079 | |||
92ec24352f | |||
3f9e459f48 | |||
e0c7f8d51d | |||
eb79386c92 | |||
4542f31c40 | |||
689fb378d8 | |||
98b711a872 | |||
800aa131fa | |||
6983980304 | |||
7c0ba59993 | |||
28873fc87b | |||
24e849ed9c | |||
d8985c141e | |||
7602b15256 | |||
d1a82bceed | |||
7292b02907 | |||
347714d53a | |||
f230fa1617 | |||
93615b100c | |||
e18d3d559e | |||
08ff061d07 | |||
cc351c1066 | |||
664a548c53 | |||
e9895559a3 | |||
eda5b8f593 | |||
e03f55604a | |||
51d7df2dba | |||
12046a2db6 | |||
c697d0f8ab | |||
c7cf8e710d | |||
7dddcdfd55 | |||
261eea381e | |||
e59f1f26bf | |||
f7cde80088 | |||
e60a665de4 | |||
34658ef7db | |||
940fd6f465 | |||
f288d5120d | |||
5a425a1c58 | |||
5e62258aa6 | |||
0b53b4873f | |||
8e2597f609 | |||
dac700b80a | |||
d0fc360697 | |||
576414438c | |||
13cda86d23 | |||
e1dd27b9dd | |||
8e9d4b451c | |||
816550b69c | |||
7fee852dbd | |||
1e7032f89c | |||
f0debecbbc | |||
ef9d7aa7d3 | |||
b8fd2db434 | |||
878e32cbe8 | |||
4821706561 | |||
eed6a64597 | |||
5736023ffa | |||
8a12a5097e | |||
87e4a57ef7 | |||
0375ee1881 | |||
c8e034d975 | |||
e98aa005cb | |||
52310f7d32 | |||
e3d1308205 | |||
970f039e85 | |||
99c72fd00b | |||
2708b71d77 | |||
5a4539def4 | |||
13a34cd677 | |||
811287aac8 | |||
23fb06578b | |||
c86e99e6dc | |||
4092de911c | |||
00952e15b0 | |||
6366283ce2 | |||
01ebf0f4d3 | |||
99fe6487c8 | |||
d4a6f987bc | |||
57bac4f262 | |||
cfa6843c8f | |||
b6b3221b22 | |||
8dc640c162 | |||
deee4c43c0 | |||
ad0b6f1ed1 | |||
ec03a674bd | |||
9e3d5b6a0c | |||
994c7299b9 | |||
57a830cb46 | |||
271057ca6b | |||
861335212e | |||
038e47a46e | |||
c215508a12 | |||
ccadbb5942 | |||
171c48495c | |||
a83b86ccd2 | |||
2e4b9bcd7c | |||
3046822e88 | |||
6442dd0c38 | |||
9b6fa646ed | |||
e77bde459b | |||
2d9d83a1c5 | |||
c561271070 | |||
70d4fc1e0a | |||
b8cfb36426 | |||
e5c140e0ae | |||
b99160e850 | |||
c4c340fde1 | |||
9a4c7589cc | |||
d11f898f70 | |||
34e124f2db | |||
e05c72b062 | |||
377c3325d2 | |||
2ca8523215 | |||
25775614de | |||
efb3d982f3 | |||
0410ecd9e3 | |||
dd986fefd3 | |||
b38329aa0e | |||
0fe1b70bae | |||
c5b4499d98 | |||
458aa5c265 | |||
eb0223bc51 | |||
be6a492022 | |||
d8bd08dd8c | |||
18c2847b08 | |||
d983305ea5 | |||
dd9e28fca1 | |||
7b7f5d7e0a | |||
fd112ed597 | |||
5989c88c88 | |||
da8a108cb7 | |||
75132c1e39 | |||
eb494707af | |||
736f8d0238 | |||
f1acf8e18b | |||
15352b539d | |||
4015e85506 | |||
aacaf52fd9 | |||
89f83f4e3d | |||
39b7976056 | |||
8a40878eb5 | |||
220469a2dd | |||
6308427d03 | |||
398d04dc50 | |||
80a5ed3c5b | |||
5d5a355110 | |||
c78b7c432b | |||
637512ad77 | |||
a4bd5a2aaa | |||
a943e4eebb | |||
cb0c80d8dc | |||
2fbf847367 | |||
57e6c46e72 | |||
a3617cad11 | |||
b62c19a364 | |||
8e4ad10627 | |||
496bc665d6 | |||
2c8531ea48 | |||
b94685e045 | |||
572d602b72 | |||
88051c9302 | |||
d62ee6a611 | |||
91ef4ff30b | |||
4032228005 | |||
50ce13d596 | |||
68302e7c5e | |||
18f9958332 | |||
68231db9a1 | |||
85e849ca00 | |||
617d41c7d5 | |||
cccdced74d | |||
750369b0a6 | |||
539e01deee | |||
4079edc80e | |||
a569990ca2 | |||
9c7eba4431 | |||
513ae9dc10 | |||
effecd4662 | |||
b951cb736a | |||
7e1aed6ad9 | |||
07155e2546 | |||
8c6c8ad3c0 | |||
35f257800e | |||
d0b7c22afc | |||
a18bc15cbb | |||
4ed9cc933f | |||
7af1c86f1c | |||
bd0b7aa230 | |||
72e0938f9a | |||
dd1b0a9380 | |||
4dee913d51 | |||
b764194ed0 | |||
2d0e4ba951 | |||
0d549b687d | |||
738f572043 | |||
cab508fd64 | |||
c7daf697a8 | |||
c20be13733 | |||
b42987059a | |||
82fc7f33a8 | |||
bfa77cf810 | |||
23af170229 | |||
b32d1da421 | |||
6f0362b956 |
8
.gitignore
vendored
8
.gitignore
vendored
@ -1,6 +1,14 @@
|
|||||||
|
# PyCharm and CLion
|
||||||
|
/.idea/*
|
||||||
|
!/.idea/runConfigurations
|
||||||
|
!/.idea/cmake.xml
|
||||||
|
!/.idea/codeStyles
|
||||||
|
|
||||||
|
# Eclipse
|
||||||
.cproject
|
.cproject
|
||||||
.project
|
.project
|
||||||
.settings
|
.settings
|
||||||
.metadata
|
.metadata
|
||||||
|
|
||||||
/build*
|
/build*
|
||||||
|
/cmake-build*
|
||||||
|
14
.idea/codeStyles/Project.xml
generated
Normal file
14
.idea/codeStyles/Project.xml
generated
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
|
<code_scheme name="Project" version="173">
|
||||||
|
<clangFormatSettings>
|
||||||
|
<option name="ENABLED" value="true" />
|
||||||
|
</clangFormatSettings>
|
||||||
|
<codeStyleSettings language="CMake">
|
||||||
|
<indentOptions>
|
||||||
|
<option name="INDENT_SIZE" value="2" />
|
||||||
|
<option name="CONTINUATION_INDENT_SIZE" value="0" />
|
||||||
|
<option name="TAB_SIZE" value="2" />
|
||||||
|
</indentOptions>
|
||||||
|
</codeStyleSettings>
|
||||||
|
</code_scheme>
|
||||||
|
</component>
|
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
|
<state>
|
||||||
|
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||||
|
</state>
|
||||||
|
</component>
|
7
.run/fsfw-tests_coverage.run.xml
Normal file
7
.run/fsfw-tests_coverage.run.xml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="fsfw-tests_coverage" type="CMakeRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="fsfw-tests" TARGET_NAME="fsfw-tests_coverage" CONFIG_NAME="Debug Unittest" RUN_TARGET_PROJECT_NAME="fsfw-tests" RUN_TARGET_NAME="fsfw-tests">
|
||||||
|
<method v="2">
|
||||||
|
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
|
||||||
|
</method>
|
||||||
|
</configuration>
|
||||||
|
</component>
|
7
.run/fsfw.run.xml
Normal file
7
.run/fsfw.run.xml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="fsfw" type="CMakeRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="fsfw-tests" TARGET_NAME="fsfw" CONFIG_NAME="Debug Unittest" RUN_TARGET_PROJECT_NAME="fsfw-tests" RUN_TARGET_NAME="fsfw-tests">
|
||||||
|
<method v="2">
|
||||||
|
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
|
||||||
|
</method>
|
||||||
|
</configuration>
|
||||||
|
</component>
|
116
CHANGELOG.md
116
CHANGELOG.md
@ -12,6 +12,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
## Changes
|
## Changes
|
||||||
|
|
||||||
|
- Renamed auto-formatting script to `auto-formatter.sh` and made it more robust.
|
||||||
|
If `cmake-format` is installed, it will also auto-format the `CMakeLists.txt` files now.
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/625
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/626
|
||||||
- Bump C++ required version to C++17. Every project which uses the FSFW and every modern
|
- Bump C++ required version to C++17. Every project which uses the FSFW and every modern
|
||||||
compiler supports it
|
compiler supports it
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/622
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/622
|
||||||
@ -25,18 +29,88 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/572
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/572
|
||||||
- HAL Devicehandlers: Periodic printout is run-time configurable now
|
- HAL Devicehandlers: Periodic printout is run-time configurable now
|
||||||
- `oneShotAction` flag in the `TestTask` class is not static anymore
|
- `oneShotAction` flag in the `TestTask` class is not static anymore
|
||||||
- HAL Linux Uart: Baudrate and bits per word are enums now, avoiding misconfigurations
|
- Major update for version handling, using `git describe` to fetch version information with git.
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/585
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/601
|
||||||
|
- Add helper functions provided by [`cmake-modules`](https://github.com/bilke/cmake-modules)
|
||||||
|
manually now. Those should not change too often and only a small subset is needed
|
||||||
|
- Separate folder for easier update and for distinction
|
||||||
|
- LICENSE file included
|
||||||
|
- use `int` for version numbers to allow unset or uninitialized version
|
||||||
|
- Initialize Version object with numbers set to -1
|
||||||
|
- Instead of hardcoding the git hash, it is now retrieved from git
|
||||||
|
- `Version` now allows specifying additional version information like the git SHA1 hash and the
|
||||||
|
versions since the last tag
|
||||||
|
- Additional information is set to the last part of the git describe output for `FSFW_VERSION` now.
|
||||||
|
- Version still need to be hand-updated if the FSFW is not included as a submodule for now.
|
||||||
- IPC Message Queue Handling: Allow passing an optional `MqArgs` argument into the MessageQueue
|
- IPC Message Queue Handling: Allow passing an optional `MqArgs` argument into the MessageQueue
|
||||||
creation call. It allows passing context information and an arbitrary user argument into
|
creation call. It allows passing context information and an arbitrary user argument into
|
||||||
the message queue. Also streamlined and simplified `MessageQueue` implementation for all OSALs
|
the message queue. Also streamlined and simplified `MessageQueue` implementation for all OSALs
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/583
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/583
|
||||||
- Clock:
|
|
||||||
- `timeval` to `TimeOfDay_t`
|
### Task Module Refactoring
|
||||||
- Added Mutex for gmtime calls: (compare http://www.opengate.at/blog/2020/01/timeless/)
|
|
||||||
- Moved the statics used by Clock in ClockCommon.cpp to this file
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/636
|
||||||
- Better check for leap seconds
|
|
||||||
- Added Unittests for Clock (only getter)
|
**Refactoring general task code**
|
||||||
|
|
||||||
|
- There was a lot of duplicate/boilerplate code inside the individual task IF OSAL implementations.
|
||||||
|
Remove it by introducing base classes `PeriodicTaskBase` and `FixedTimeslotTaskBase`.
|
||||||
|
|
||||||
|
**Refactor PeriodicTaskIF**
|
||||||
|
|
||||||
|
- Convert `virtual ReturnValue_t addComponent(object_id_t object)` to
|
||||||
|
`virtual ReturnValue_t addComponent(object_id_t object, uint8_t opCode = 0)`, allowing to pass
|
||||||
|
the operation code passed to `performOperation`. Updated API taking
|
||||||
|
an `ExecutableObjectIF` accordingly
|
||||||
|
|
||||||
|
**Refactor FixedTimeslotTaskIF**
|
||||||
|
|
||||||
|
- Add additional `addSlot` function which takes an `ExecutableObjectIF` pointer and its Object ID
|
||||||
|
|
||||||
|
**Refactor FixedSequenceSlot**
|
||||||
|
|
||||||
|
- Introduce typedef `CustomCheckFunc` for `ReturnValue_t (*customCheckFunction)(const SlotList&)`.
|
||||||
|
- Convert `ReturnValue_t (*customCheckFunction)(const SlotList&)` to
|
||||||
|
`ReturnValue_t (*customCheckFunction)(const SlotList&, void*)`, allowing arbitrary user arguments
|
||||||
|
for the custom checker
|
||||||
|
|
||||||
|
**Linux Task Module**
|
||||||
|
|
||||||
|
- Use composition instead of inheritance for the `PeriodicPosixTask` and make the `PosixTask` a
|
||||||
|
member of the class
|
||||||
|
|
||||||
|
### HAL
|
||||||
|
|
||||||
|
- HAL Linux Uart: Baudrate and bits per word are enums now, avoiding misconfigurations
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/585
|
||||||
|
- HAL Linux SPI: Set the Clock Default State when setting new SPI speed
|
||||||
|
and mode
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/573
|
||||||
|
- GPIO HAL: `Direction`, `GpioOperation` and `Levels` are enum classes now, which prevents
|
||||||
|
name clashes with Windows defines.
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/572
|
||||||
|
- HAL Linux Uart: Baudrate and bits per word are enums now, avoiding misconfigurations
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/585
|
||||||
|
|
||||||
|
### Time
|
||||||
|
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/584 and
|
||||||
|
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/593
|
||||||
|
|
||||||
|
- `timeval` to `TimeOfDay_t`
|
||||||
|
- Added Mutex for gmtime calls: (compare http://www.opengate.at/blog/2020/01/timeless/)
|
||||||
|
- Moved the statics used by Clock in ClockCommon.cpp to this file
|
||||||
|
- Better check for leap seconds
|
||||||
|
- Added Unittests for Clock (only getter)
|
||||||
|
|
||||||
|
### Power
|
||||||
|
|
||||||
|
- `PowerSwitchIF`: Remove `const` specifier from `sendSwitchCommand` and `sendFuseOnCommand` and
|
||||||
|
also specify a `ReturnValue_t` return type
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/590
|
||||||
|
- Extend `PowerSwitcher` module to optionally check current state when calling `turnOn` or
|
||||||
|
`turnOff`. Tis can be helpful to avoid commanding switches which do not need commanding
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/590
|
||||||
|
|
||||||
## Removed
|
## Removed
|
||||||
|
|
||||||
@ -46,12 +120,38 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
## Additions
|
## Additions
|
||||||
|
|
||||||
|
- Added options for CI/CD builds: `FSFW_CICD_BUILD`. This allows the source code to know
|
||||||
|
whether it is running in CI/CD
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/623
|
||||||
|
- Basic `clion` support: Update `.gitignore` and add some basic run configurations
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/625
|
||||||
|
- LTO support: Allow using LTO/IPO by setting `FSFW_ENABLE_LTO=1`. CMake is able to detect whether
|
||||||
|
the user compiler supports IPO/LPO. LTO is on by default now. Most modern compilers support it,
|
||||||
|
can make good use of it and it usually makes the code faster and/or smaller.
|
||||||
|
After some more research:
|
||||||
|
Enabling LTO will actually cause the compiler to only produce thin LTO by adding
|
||||||
|
`-flto -fno-fat-lto-objects` to the compiler options. I am not sure this is an ideal choice
|
||||||
|
because if an application linking against the FSFW does not use LTO, there can be compile
|
||||||
|
issues (e.g. observed when compiling the FSFW tests without LTO). This is a known issue as
|
||||||
|
can be seen in the multiple CMake issues for it:
|
||||||
|
- https://gitlab.kitware.com/cmake/cmake/-/issues/22913,
|
||||||
|
- https://gitlab.kitware.com/cmake/cmake/-/issues/16808,
|
||||||
|
- https://gitlab.kitware.com/cmake/cmake/-/issues/21696
|
||||||
|
Easiest solution for now: Keep this option OFF by default.
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/616
|
||||||
- Linux HAL: Add wiretapping option for I2C. Enabled with `FSFW_HAL_I2C_WIRETAPPING` defined to 1
|
- Linux HAL: Add wiretapping option for I2C. Enabled with `FSFW_HAL_I2C_WIRETAPPING` defined to 1
|
||||||
- Dedicated Version class and constant `fsfw::FSFW_VERSION` containing version information
|
- Dedicated Version class and constant `fsfw::FSFW_VERSION` containing version information
|
||||||
inside `fsfw/version.h`
|
inside `fsfw/version.h`
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/559
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/559
|
||||||
|
- Added generic PUS TC Scheduler Service 11. It depends on the new added Emebeded Template Library
|
||||||
|
(ETL) dependency.
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/594
|
||||||
- Added ETL dependency and improved library dependency management
|
- Added ETL dependency and improved library dependency management
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/592
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/592
|
||||||
|
- Add a `DummyPowerSwitcher` module which can be useful for test setups when no PCDU is available
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/590
|
||||||
|
- New typedef for switcher type
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/590
|
||||||
- `Subsystem`: New API to add table and sequence entries
|
- `Subsystem`: New API to add table and sequence entries
|
||||||
|
|
||||||
## Fixed
|
## Fixed
|
||||||
|
634
CMakeLists.txt
634
CMakeLists.txt
@ -1,50 +1,114 @@
|
|||||||
cmake_minimum_required(VERSION 3.13)
|
cmake_minimum_required(VERSION 3.13)
|
||||||
|
|
||||||
set(LIB_FSFW_NAME fsfw)
|
set(MSG_PREFIX "fsfw |")
|
||||||
project(${LIB_FSFW_NAME})
|
|
||||||
|
|
||||||
if(NOT CMAKE_CXX_STANDARD)
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
|
||||||
elseif(${CMAKE_CXX_STANDARD} LESS 17)
|
|
||||||
message(FATAL_ERROR "Compiling the FSFW requires a minimum of C++17 support")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(FSFW_VERSION 4)
|
|
||||||
set(FSFW_SUBVERSION 0)
|
|
||||||
set(FSFW_REVISION 0)
|
|
||||||
|
|
||||||
# Add the cmake folder so the FindSphinx module is found
|
# Add the cmake folder so the FindSphinx module is found
|
||||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||||
|
list(APPEND CMAKE_MODULE_PATH
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake-modules/bilke")
|
||||||
|
list(APPEND CMAKE_MODULE_PATH
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake-modules/rpavlik")
|
||||||
|
|
||||||
set(FSFW_ETL_LIB_MAJOR_VERSION 20 CACHE STRING
|
# ##############################################################################
|
||||||
"ETL library major version requirement"
|
# Version file handling #
|
||||||
)
|
# ##############################################################################
|
||||||
set(FSFW_ETL_LIB_VERSION ${FSFW_ETL_LIB_MAJOR_VERSION}.27.3 CACHE STRING
|
|
||||||
"ETL library exact version requirement"
|
|
||||||
)
|
|
||||||
set(FSFW_ETL_LINK_TARGET etl::etl)
|
|
||||||
|
|
||||||
set(FSFW_CATCH2_LIB_MAJOR_VERSION 3 CACHE STRING
|
set(FSFW_VERSION_IF_GIT_FAILS 4)
|
||||||
"Catch2 library major version requirement"
|
set(FSFW_SUBVERSION_IF_GIT_FAILS 0)
|
||||||
)
|
set(FSFW_REVISION_IF_GIT_FAILS 0)
|
||||||
set(FSFW_CATCH2_LIB_VERSION v${FSFW_CATCH2_LIB_MAJOR_VERSION}.0.0-preview5 CACHE STRING
|
|
||||||
"Catch2 library exact version requirement"
|
|
||||||
)
|
|
||||||
|
|
||||||
set(FSFW_ETL_LIB_NAME etl)
|
set(FSFW_GIT_VER_HANDLING_OK FALSE)
|
||||||
|
# Version handling
|
||||||
option(FSFW_GENERATE_SECTIONS
|
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git)
|
||||||
"Generate function and data sections. Required to remove unused code" ON
|
message(STATUS "${MSG_PREFIX} Determining version information with git")
|
||||||
)
|
include(FsfwHelpers)
|
||||||
if(FSFW_GENERATE_SECTIONS)
|
determine_version_with_git("--exclude" "docker_*")
|
||||||
option(FSFW_REMOVE_UNUSED_CODE "Remove unused code" ON)
|
if(GIT_INFO)
|
||||||
|
set(FSFW_GIT_INFO
|
||||||
|
${GIT_INFO}
|
||||||
|
CACHE STRING "Version information retrieved with git describe")
|
||||||
|
list(GET FSFW_GIT_INFO 1 FSFW_VERSION)
|
||||||
|
list(GET FSFW_GIT_INFO 2 FSFW_SUBVERSION)
|
||||||
|
list(GET FSFW_GIT_INFO 3 FSFW_REVISION)
|
||||||
|
list(GET FSFW_GIT_INFO 4 FSFW_VCS_INFO)
|
||||||
|
if(NOT FSFW_VERSION)
|
||||||
|
set(FSFW_VERSION ${FSFW_VERSION_IF_GIT_FAILS})
|
||||||
|
endif()
|
||||||
|
if(NOT FSFW_SUBVERSION)
|
||||||
|
set(FSFW_SUBVERSION ${FSFW_SUBVERSION_IF_GIT_FAILS})
|
||||||
|
endif()
|
||||||
|
if(NOT FSFW_REVISION)
|
||||||
|
set(FSFW_REVISION ${FSFW_REVISION_IF_GIT_FAILS})
|
||||||
|
endif()
|
||||||
|
set(FSFW_GIT_VER_HANDLING_OK TRUE)
|
||||||
|
else()
|
||||||
|
set(FSFW_GIT_VER_HANDLING_OK FALSE)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
if(NOT FSFW_GIT_VER_HANDLING_OK)
|
||||||
|
set(FSFW_VERSION ${FSFW_VERSION_IF_GIT_FAILS})
|
||||||
|
set(FSFW_SUBVERSION ${FSFW_SUBVERSION_IF_GIT_FAILS})
|
||||||
|
set(FSFW_REVISION ${FSFW_REVISION_IF_GIT_FAILS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
option(FSFW_BUILD_UNITTESTS "Build unittest binary in addition to static library" OFF)
|
set(LIB_FSFW_NAME fsfw)
|
||||||
|
project(${LIB_FSFW_NAME}
|
||||||
|
VERSION ${FSFW_VERSION}.${FSFW_SUBVERSION}.${FSFW_REVISION})
|
||||||
|
|
||||||
|
if(NOT CMAKE_CXX_STANDARD)
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||||
|
elseif(${CMAKE_CXX_STANDARD} LESS 17)
|
||||||
|
message(
|
||||||
|
FATAL_ERROR
|
||||||
|
"${MSG_PREFIX} Compiling the FSFW requires a minimum of C++17 support")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(FSFW_SOURCES_DIR "${CMAKE_SOURCE_DIR}/src/fsfw")
|
||||||
|
|
||||||
|
set(FSFW_ETL_LIB_NAME etl)
|
||||||
|
set(FSFW_ETL_LIB_MAJOR_VERSION
|
||||||
|
20
|
||||||
|
CACHE STRING "ETL library major version requirement")
|
||||||
|
set(FSFW_ETL_LIB_VERSION
|
||||||
|
${FSFW_ETL_LIB_MAJOR_VERSION}.28.0
|
||||||
|
CACHE STRING "ETL library exact version requirement")
|
||||||
|
set(FSFW_ETL_LINK_TARGET etl::etl)
|
||||||
|
|
||||||
|
set(FSFW_CATCH2_LIB_MAJOR_VERSION
|
||||||
|
3
|
||||||
|
CACHE STRING "Catch2 library major version requirement")
|
||||||
|
set(FSFW_CATCH2_LIB_VERSION
|
||||||
|
v${FSFW_CATCH2_LIB_MAJOR_VERSION}.0.0-preview5
|
||||||
|
CACHE STRING "Catch2 library exact version requirement")
|
||||||
|
|
||||||
|
# Keep this off by default for now. See PR:
|
||||||
|
# https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/616 for information which
|
||||||
|
# keeping this on by default is problematic
|
||||||
|
option(
|
||||||
|
FSFW_ENABLE_IPO
|
||||||
|
"Enable interprocedural optimization or link-time optimization if available"
|
||||||
|
OFF)
|
||||||
|
if(FSFW_ENABLE_IPO)
|
||||||
|
include(CheckIPOSupported)
|
||||||
|
check_ipo_supported(RESULT IPO_SUPPORTED OUTPUT IPO_ERROR)
|
||||||
|
if(NOT IPO_SUPPORTED)
|
||||||
|
message(STATUS "FSFW | IPO/LTO not supported: ${IPO_ERROR}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
option(FSFW_GENERATE_SECTIONS
|
||||||
|
"Generate function and data sections. Required to remove unused code" ON)
|
||||||
|
if(FSFW_GENERATE_SECTIONS)
|
||||||
|
option(FSFW_REMOVE_UNUSED_CODE "Remove unused code" ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
option(FSFW_BUILD_UNITTESTS
|
||||||
|
"Build unittest binary in addition to static library" OFF)
|
||||||
|
option(FSFW_CICD_BUILD "Build for CI/CD. This can disable problematic test" OFF)
|
||||||
option(FSFW_BUILD_DOCS "Build documentation with Sphinx and Doxygen" OFF)
|
option(FSFW_BUILD_DOCS "Build documentation with Sphinx and Doxygen" OFF)
|
||||||
if(FSFW_BUILD_UNITTESTS)
|
if(FSFW_BUILD_UNITTESTS)
|
||||||
option(FSFW_TESTS_GEN_COV "Generate coverage data for unittests" ON)
|
option(FSFW_TESTS_GEN_COV "Generate coverage data for unittests" ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
option(FSFW_WARNING_SHADOW_LOCAL_GCC "Enable -Wshadow=local warning in GCC" ON)
|
option(FSFW_WARNING_SHADOW_LOCAL_GCC "Enable -Wshadow=local warning in GCC" ON)
|
||||||
@ -65,88 +129,93 @@ option(FSFW_ADD_TMSTORAGE "Compile with tm storage components" OFF)
|
|||||||
# Contrib sources
|
# Contrib sources
|
||||||
option(FSFW_ADD_SGP4_PROPAGATOR "Add SGP4 propagator code" OFF)
|
option(FSFW_ADD_SGP4_PROPAGATOR "Add SGP4 propagator code" OFF)
|
||||||
|
|
||||||
|
|
||||||
set(FSFW_TEST_TGT fsfw-tests)
|
set(FSFW_TEST_TGT fsfw-tests)
|
||||||
set(FSFW_DUMMY_TGT fsfw-dummy)
|
set(FSFW_DUMMY_TGT fsfw-dummy)
|
||||||
|
|
||||||
add_library(${LIB_FSFW_NAME})
|
add_library(${LIB_FSFW_NAME})
|
||||||
|
|
||||||
if(FSFW_BUILD_UNITTESTS)
|
if(IPO_SUPPORTED AND FSFW_ENABLE_IPO)
|
||||||
message(STATUS "Building the FSFW unittests in addition to the static library")
|
set_property(TARGET ${LIB_FSFW_NAME} PROPERTY INTERPROCEDURAL_OPTIMIZATION
|
||||||
# Check whether the user has already installed Catch2 first
|
TRUE)
|
||||||
find_package(Catch2 ${FSFW_CATCH2_LIB_MAJOR_VERSION})
|
|
||||||
# Not installed, so use FetchContent to download and provide Catch2
|
|
||||||
if(NOT Catch2_FOUND)
|
|
||||||
message(STATUS "Catch2 installation not found. Downloading Catch2 library with FetchContent")
|
|
||||||
include(FetchContent)
|
|
||||||
|
|
||||||
FetchContent_Declare(
|
|
||||||
Catch2
|
|
||||||
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
|
|
||||||
GIT_TAG ${FSFW_CATCH2_LIB_VERSION}
|
|
||||||
)
|
|
||||||
|
|
||||||
list(APPEND FSFW_FETCH_CONTENT_TARGETS Catch2)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(FSFW_CONFIG_PATH tests/src/fsfw_tests/unit/testcfg)
|
|
||||||
configure_file(tests/src/fsfw_tests/unit/testcfg/FSFWConfig.h.in FSFWConfig.h)
|
|
||||||
configure_file(tests/src/fsfw_tests/unit/testcfg/TestsConfig.h.in tests/TestsConfig.h)
|
|
||||||
|
|
||||||
project(${FSFW_TEST_TGT} CXX C)
|
|
||||||
add_executable(${FSFW_TEST_TGT})
|
|
||||||
|
|
||||||
if(FSFW_TESTS_GEN_COV)
|
|
||||||
message(STATUS "Generating coverage data for the library")
|
|
||||||
message(STATUS "Targets linking against ${LIB_FSFW_NAME} "
|
|
||||||
"will be compiled with coverage data as well"
|
|
||||||
)
|
|
||||||
include(FetchContent)
|
|
||||||
FetchContent_Declare(
|
|
||||||
cmake-modules
|
|
||||||
GIT_REPOSITORY https://github.com/bilke/cmake-modules.git
|
|
||||||
)
|
|
||||||
FetchContent_MakeAvailable(cmake-modules)
|
|
||||||
set(CMAKE_BUILD_TYPE "Debug")
|
|
||||||
list(APPEND CMAKE_MODULE_PATH ${cmake-modules_SOURCE_DIR})
|
|
||||||
include(CodeCoverage)
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
message(STATUS "Finding and/or providing ETL library")
|
if(FSFW_BUILD_UNITTESTS)
|
||||||
|
message(
|
||||||
|
STATUS
|
||||||
|
"${MSG_PREFIX} Building the FSFW unittests in addition to the static library"
|
||||||
|
)
|
||||||
|
# Check whether the user has already installed Catch2 first
|
||||||
|
find_package(Catch2 ${FSFW_CATCH2_LIB_MAJOR_VERSION})
|
||||||
|
# Not installed, so use FetchContent to download and provide Catch2
|
||||||
|
if(NOT Catch2_FOUND)
|
||||||
|
message(
|
||||||
|
STATUS
|
||||||
|
"${MSG_PREFIX} Catch2 installation not found. Downloading Catch2 library with FetchContent"
|
||||||
|
)
|
||||||
|
include(FetchContent)
|
||||||
|
|
||||||
|
FetchContent_Declare(
|
||||||
|
Catch2
|
||||||
|
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
|
||||||
|
GIT_TAG ${FSFW_CATCH2_LIB_VERSION})
|
||||||
|
|
||||||
|
list(APPEND FSFW_FETCH_CONTENT_TARGETS Catch2)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(FSFW_CONFIG_PATH tests/src/fsfw_tests/unit/testcfg)
|
||||||
|
configure_file(tests/src/fsfw_tests/unit/testcfg/FSFWConfig.h.in FSFWConfig.h)
|
||||||
|
configure_file(tests/src/fsfw_tests/unit/testcfg/TestsConfig.h.in
|
||||||
|
tests/TestsConfig.h)
|
||||||
|
|
||||||
|
project(${FSFW_TEST_TGT} CXX C)
|
||||||
|
add_executable(${FSFW_TEST_TGT})
|
||||||
|
if(IPO_SUPPORTED AND FSFW_ENABLE_IPO)
|
||||||
|
set_property(TARGET ${FSFW_TEST_TGT} PROPERTY INTERPROCEDURAL_OPTIMIZATION
|
||||||
|
TRUE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(FSFW_TESTS_GEN_COV)
|
||||||
|
message(STATUS "${MSG_PREFIX} Generating coverage data for the library")
|
||||||
|
message(STATUS "${MSG_PREFIX} Targets linking against ${LIB_FSFW_NAME} "
|
||||||
|
"will be compiled with coverage data as well")
|
||||||
|
set(CMAKE_BUILD_TYPE "Debug")
|
||||||
|
include(CodeCoverage)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message(STATUS "${MSG_PREFIX} Finding and/or providing ETL library")
|
||||||
|
|
||||||
# Check whether the user has already installed ETL first
|
# Check whether the user has already installed ETL first
|
||||||
find_package(${FSFW_ETL_LIB_NAME} ${FSFW_ETL_LIB_MAJOR_VERSION} QUIET)
|
find_package(${FSFW_ETL_LIB_NAME} ${FSFW_ETL_LIB_MAJOR_VERSION} QUIET)
|
||||||
# Not installed, so use FetchContent to download and provide etl
|
# Not installed, so use FetchContent to download and provide etl
|
||||||
if(NOT ${FSFW_ETL_LIB_NAME}_FOUND)
|
if(NOT ${FSFW_ETL_LIB_NAME}_FOUND)
|
||||||
message(STATUS
|
message(
|
||||||
"No ETL installation was found with find_package. Installing and providing "
|
STATUS
|
||||||
"etl with FindPackage"
|
"No ETL installation was found with find_package. Installing and providing "
|
||||||
)
|
"etl with FindPackage")
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
${FSFW_ETL_LIB_NAME}
|
${FSFW_ETL_LIB_NAME}
|
||||||
GIT_REPOSITORY https://github.com/ETLCPP/etl
|
GIT_REPOSITORY https://github.com/ETLCPP/etl
|
||||||
GIT_TAG ${FSFW_ETL_LIB_VERSION}
|
GIT_TAG ${FSFW_ETL_LIB_VERSION})
|
||||||
)
|
|
||||||
|
|
||||||
list(APPEND FSFW_FETCH_CONTENT_TARGETS ${FSFW_ETL_LIB_NAME})
|
list(APPEND FSFW_FETCH_CONTENT_TARGETS ${FSFW_ETL_LIB_NAME})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# The documentation for FetchContent recommends declaring all the dependencies
|
# The documentation for FetchContent recommends declaring all the dependencies
|
||||||
# before making them available. We make all declared dependency available here
|
# before making them available. We make all declared dependency available here
|
||||||
# after their declaration
|
# after their declaration
|
||||||
if(FSFW_FETCH_CONTENT_TARGETS)
|
if(FSFW_FETCH_CONTENT_TARGETS)
|
||||||
FetchContent_MakeAvailable(${FSFW_FETCH_CONTENT_TARGETS})
|
FetchContent_MakeAvailable(${FSFW_FETCH_CONTENT_TARGETS})
|
||||||
if(TARGET ${FSFW_ETL_LIB_NAME})
|
if(TARGET ${FSFW_ETL_LIB_NAME})
|
||||||
add_library(${FSFW_ETL_LINK_TARGET} ALIAS ${FSFW_ETL_LIB_NAME})
|
add_library(${FSFW_ETL_LINK_TARGET} ALIAS ${FSFW_ETL_LIB_NAME})
|
||||||
endif()
|
endif()
|
||||||
if(TARGET Catch2)
|
if(TARGET Catch2)
|
||||||
# Fixes regression -preview4, to be confirmed in later releases
|
# Fixes regression -preview4, to be confirmed in later releases Related
|
||||||
# Related GitHub issue: https://github.com/catchorg/Catch2/issues/2417
|
# GitHub issue: https://github.com/catchorg/Catch2/issues/2417
|
||||||
set_target_properties(Catch2 PROPERTIES DEBUG_POSTFIX "")
|
set_target_properties(Catch2 PROPERTIES DEBUG_POSTFIX "")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(FSFW_CORE_INC_PATH "inc")
|
set(FSFW_CORE_INC_PATH "inc")
|
||||||
@ -154,269 +223,242 @@ set(FSFW_CORE_INC_PATH "inc")
|
|||||||
set_property(CACHE FSFW_OSAL PROPERTY STRINGS host linux rtems freertos)
|
set_property(CACHE FSFW_OSAL PROPERTY STRINGS host linux rtems freertos)
|
||||||
|
|
||||||
# For configure files
|
# For configure files
|
||||||
target_include_directories(${LIB_FSFW_NAME} PRIVATE
|
target_include_directories(${LIB_FSFW_NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
${CMAKE_CURRENT_BINARY_DIR}
|
target_include_directories(${LIB_FSFW_NAME}
|
||||||
)
|
INTERFACE ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
target_include_directories(${LIB_FSFW_NAME} INTERFACE
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# Backwards comptability
|
# Backwards comptability
|
||||||
if(OS_FSFW AND NOT FSFW_OSAL)
|
if(OS_FSFW AND NOT FSFW_OSAL)
|
||||||
message(WARNING "Please pass the FSFW OSAL as FSFW_OSAL instead of OS_FSFW")
|
message(
|
||||||
set(FSFW_OSAL OS_FSFW)
|
WARNING
|
||||||
|
"${MSG_PREFIX} Please pass the FSFW OSAL as FSFW_OSAL instead of OS_FSFW")
|
||||||
|
set(FSFW_OSAL OS_FSFW)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT FSFW_OSAL)
|
if(NOT FSFW_OSAL)
|
||||||
message(STATUS "No OS for FSFW via FSFW_OSAL set. Assuming host OS")
|
message(STATUS "No OS for FSFW via FSFW_OSAL set. Assuming host OS")
|
||||||
# Assume host OS and autodetermine from OS_FSFW
|
# Assume host OS and autodetermine from OS_FSFW
|
||||||
if(UNIX)
|
if(UNIX)
|
||||||
set(FSFW_OSAL "linux"
|
set(FSFW_OSAL
|
||||||
CACHE STRING
|
"linux"
|
||||||
"OS abstraction layer used in the FSFW"
|
CACHE STRING "OS abstraction layer used in the FSFW")
|
||||||
)
|
elseif(WIN32)
|
||||||
elseif(WIN32)
|
set(FSFW_OSAL
|
||||||
set(FSFW_OSAL "host"
|
"host"
|
||||||
CACHE STRING "OS abstraction layer used in the FSFW"
|
CACHE STRING "OS abstraction layer used in the FSFW")
|
||||||
)
|
endif()
|
||||||
endif()
|
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(FSFW_OSAL_DEFINITION FSFW_OSAL_HOST)
|
set(FSFW_OSAL_DEFINITION FSFW_OSAL_HOST)
|
||||||
|
|
||||||
if(FSFW_OSAL MATCHES host)
|
if(FSFW_OSAL MATCHES host)
|
||||||
set(FSFW_OS_NAME "Host")
|
set(FSFW_OS_NAME "Host")
|
||||||
set(FSFW_OSAL_HOST ON)
|
set(FSFW_OSAL_HOST ON)
|
||||||
elseif(FSFW_OSAL MATCHES linux)
|
elseif(FSFW_OSAL MATCHES linux)
|
||||||
set(FSFW_OS_NAME "Linux")
|
set(FSFW_OS_NAME "Linux")
|
||||||
set(FSFW_OSAL_LINUX ON)
|
set(FSFW_OSAL_LINUX ON)
|
||||||
elseif(FSFW_OSAL MATCHES freertos)
|
elseif(FSFW_OSAL MATCHES freertos)
|
||||||
set(FSFW_OS_NAME "FreeRTOS")
|
set(FSFW_OS_NAME "FreeRTOS")
|
||||||
set(FSFW_OSAL_FREERTOS ON)
|
set(FSFW_OSAL_FREERTOS ON)
|
||||||
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
|
target_link_libraries(${LIB_FSFW_NAME} PRIVATE ${LIB_OS_NAME})
|
||||||
${LIB_OS_NAME}
|
|
||||||
)
|
|
||||||
elseif(FSFW_OSAL STREQUAL rtems)
|
elseif(FSFW_OSAL STREQUAL rtems)
|
||||||
set(FSFW_OS_NAME "RTEMS")
|
set(FSFW_OS_NAME "RTEMS")
|
||||||
set(FSFW_OSAL_RTEMS ON)
|
set(FSFW_OSAL_RTEMS ON)
|
||||||
else()
|
else()
|
||||||
message(WARNING
|
message(
|
||||||
"Invalid operating system for FSFW specified! Setting to host.."
|
WARNING
|
||||||
)
|
"${MSG_PREFIX} Invalid operating system for FSFW specified! Setting to host.."
|
||||||
set(FSFW_OS_NAME "Host")
|
)
|
||||||
set(OS_FSFW "host")
|
set(FSFW_OS_NAME "Host")
|
||||||
|
set(OS_FSFW "host")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
configure_file(src/fsfw/FSFW.h.in fsfw/FSFW.h)
|
configure_file(src/fsfw/FSFW.h.in fsfw/FSFW.h)
|
||||||
configure_file(src/fsfw/FSFWVersion.h.in fsfw/FSFWVersion.h)
|
configure_file(src/fsfw/FSFWVersion.h.in fsfw/FSFWVersion.h)
|
||||||
|
|
||||||
message(STATUS "Compiling FSFW for the ${FSFW_OS_NAME} operating system.")
|
message(
|
||||||
|
STATUS "${MSG_PREFIX} Compiling FSFW for the ${FSFW_OS_NAME} operating system"
|
||||||
|
)
|
||||||
|
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
if(FSFW_ADD_HAL)
|
if(FSFW_ADD_HAL)
|
||||||
add_subdirectory(hal)
|
add_subdirectory(hal)
|
||||||
endif()
|
endif()
|
||||||
add_subdirectory(contrib)
|
add_subdirectory(contrib)
|
||||||
if(FSFW_BUILD_DOCS)
|
if(FSFW_BUILD_DOCS)
|
||||||
add_subdirectory(docs)
|
add_subdirectory(docs)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(FSFW_BUILD_UNITTESTS)
|
if(FSFW_BUILD_UNITTESTS)
|
||||||
if(FSFW_TESTS_GEN_COV)
|
if(FSFW_TESTS_GEN_COV)
|
||||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||||
include(CodeCoverage)
|
include(CodeCoverage)
|
||||||
|
|
||||||
# Remove quotes.
|
# Remove quotes.
|
||||||
separate_arguments(COVERAGE_COMPILER_FLAGS
|
separate_arguments(COVERAGE_COMPILER_FLAGS NATIVE_COMMAND
|
||||||
NATIVE_COMMAND "${COVERAGE_COMPILER_FLAGS}"
|
"${COVERAGE_COMPILER_FLAGS}")
|
||||||
)
|
|
||||||
|
|
||||||
# Add compile options manually, we don't want coverage for Catch2
|
# Add compile options manually, we don't want coverage for Catch2
|
||||||
target_compile_options(${FSFW_TEST_TGT} PRIVATE
|
target_compile_options(${FSFW_TEST_TGT}
|
||||||
"${COVERAGE_COMPILER_FLAGS}"
|
PRIVATE "${COVERAGE_COMPILER_FLAGS}")
|
||||||
)
|
target_compile_options(${LIB_FSFW_NAME}
|
||||||
target_compile_options(${LIB_FSFW_NAME} PRIVATE
|
PRIVATE "${COVERAGE_COMPILER_FLAGS}")
|
||||||
"${COVERAGE_COMPILER_FLAGS}"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Exclude directories here
|
# Exclude directories here
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(GCOVR_ADDITIONAL_ARGS
|
set(GCOVR_ADDITIONAL_ARGS "--exclude-throw-branches"
|
||||||
"--exclude-throw-branches"
|
"--exclude-unreachable-branches")
|
||||||
"--exclude-unreachable-branches"
|
set(COVERAGE_EXCLUDES "/c/msys64/mingw64/*" "*/fsfw_hal/*")
|
||||||
)
|
elseif(UNIX)
|
||||||
set(COVERAGE_EXCLUDES
|
set(COVERAGE_EXCLUDES
|
||||||
"/c/msys64/mingw64/*" "*/fsfw_hal/*"
|
"/usr/include/*"
|
||||||
)
|
"/usr/bin/*"
|
||||||
elseif(UNIX)
|
"Catch2/*"
|
||||||
set(COVERAGE_EXCLUDES
|
"/usr/local/include/*"
|
||||||
"/usr/include/*" "/usr/bin/*" "Catch2/*"
|
"*/fsfw_tests/*"
|
||||||
"/usr/local/include/*" "*/fsfw_tests/*"
|
"*/catch2-src/*"
|
||||||
"*/catch2-src/*" "*/fsfw_hal/*"
|
"*/fsfw_hal/*")
|
||||||
)
|
endif()
|
||||||
endif()
|
|
||||||
|
|
||||||
target_link_options(${FSFW_TEST_TGT} PRIVATE
|
target_link_options(${FSFW_TEST_TGT} PRIVATE -fprofile-arcs
|
||||||
-fprofile-arcs
|
-ftest-coverage)
|
||||||
-ftest-coverage
|
target_link_options(${LIB_FSFW_NAME} PRIVATE -fprofile-arcs
|
||||||
)
|
-ftest-coverage)
|
||||||
target_link_options(${LIB_FSFW_NAME} PRIVATE
|
# Need to specify this as an interface, otherwise there will the compile
|
||||||
-fprofile-arcs
|
# issues
|
||||||
-ftest-coverage
|
target_link_options(${LIB_FSFW_NAME} INTERFACE -fprofile-arcs
|
||||||
)
|
-ftest-coverage)
|
||||||
# Need to specify this as an interface, otherwise there will the compile issues
|
|
||||||
target_link_options(${LIB_FSFW_NAME} INTERFACE
|
|
||||||
-fprofile-arcs
|
|
||||||
-ftest-coverage
|
|
||||||
)
|
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
setup_target_for_coverage_gcovr_html(
|
setup_target_for_coverage_gcovr_html(
|
||||||
NAME ${FSFW_TEST_TGT}_coverage
|
NAME ${FSFW_TEST_TGT}_coverage EXECUTABLE ${FSFW_TEST_TGT}
|
||||||
EXECUTABLE ${FSFW_TEST_TGT}
|
DEPENDENCIES ${FSFW_TEST_TGT})
|
||||||
DEPENDENCIES ${FSFW_TEST_TGT}
|
else()
|
||||||
)
|
setup_target_for_coverage_lcov(
|
||||||
else()
|
NAME ${FSFW_TEST_TGT}_coverage EXECUTABLE ${FSFW_TEST_TGT}
|
||||||
setup_target_for_coverage_lcov(
|
DEPENDENCIES ${FSFW_TEST_TGT})
|
||||||
NAME ${FSFW_TEST_TGT}_coverage
|
endif()
|
||||||
EXECUTABLE ${FSFW_TEST_TGT}
|
|
||||||
DEPENDENCIES ${FSFW_TEST_TGT}
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
target_link_libraries(${FSFW_TEST_TGT} PRIVATE Catch2::Catch2 ${LIB_FSFW_NAME})
|
endif()
|
||||||
|
target_link_libraries(${FSFW_TEST_TGT} PRIVATE Catch2::Catch2
|
||||||
|
${LIB_FSFW_NAME})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# The project CMakeLists file has to set the FSFW_CONFIG_PATH and add it.
|
# The project CMakeLists file has to set the FSFW_CONFIG_PATH and add it. If
|
||||||
# If this is not given, we include the default configuration and emit a warning.
|
# this is not given, we include the default configuration and emit a warning.
|
||||||
if(NOT FSFW_CONFIG_PATH)
|
if(NOT FSFW_CONFIG_PATH)
|
||||||
set(DEF_CONF_PATH misc/defaultcfg/fsfwconfig)
|
set(DEF_CONF_PATH misc/defaultcfg/fsfwconfig)
|
||||||
if(NOT FSFW_BUILD_DOCS)
|
if(NOT FSFW_BUILD_DOCS)
|
||||||
message(WARNING "Flight Software Framework configuration path not set!")
|
message(
|
||||||
message(WARNING "Setting default configuration from ${DEF_CONF_PATH} ..")
|
WARNING
|
||||||
endif()
|
"${MSG_PREFIX} Flight Software Framework configuration path not set")
|
||||||
add_subdirectory(${DEF_CONF_PATH})
|
message(
|
||||||
set(FSFW_CONFIG_PATH ${DEF_CONF_PATH})
|
WARNING
|
||||||
|
"${MSG_PREFIX} Setting default configuration from ${DEF_CONF_PATH} ..")
|
||||||
|
endif()
|
||||||
|
add_subdirectory(${DEF_CONF_PATH})
|
||||||
|
set(FSFW_CONFIG_PATH ${DEF_CONF_PATH})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# FSFW might be part of a possibly complicated folder structure, so we
|
# FSFW might be part of a possibly complicated folder structure, so we extract
|
||||||
# extract the absolute path of the fsfwconfig folder.
|
# the absolute path of the fsfwconfig folder.
|
||||||
if(IS_ABSOLUTE ${FSFW_CONFIG_PATH})
|
if(IS_ABSOLUTE ${FSFW_CONFIG_PATH})
|
||||||
set(FSFW_CONFIG_PATH_ABSOLUTE ${FSFW_CONFIG_PATH})
|
set(FSFW_CONFIG_PATH_ABSOLUTE ${FSFW_CONFIG_PATH})
|
||||||
else()
|
else()
|
||||||
get_filename_component(FSFW_CONFIG_PATH_ABSOLUTE
|
get_filename_component(FSFW_CONFIG_PATH_ABSOLUTE ${FSFW_CONFIG_PATH} REALPATH
|
||||||
${FSFW_CONFIG_PATH} REALPATH BASE_DIR ${CMAKE_SOURCE_DIR}
|
BASE_DIR ${CMAKE_SOURCE_DIR})
|
||||||
)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
foreach(INCLUDE_PATH ${FSFW_ADDITIONAL_INC_PATHS})
|
foreach(INCLUDE_PATH ${FSFW_ADDITIONAL_INC_PATHS})
|
||||||
if(IS_ABSOLUTE ${INCLUDE_PATH})
|
if(IS_ABSOLUTE ${INCLUDE_PATH})
|
||||||
set(CURR_ABS_INC_PATH "${INCLUDE_PATH}")
|
set(CURR_ABS_INC_PATH "${INCLUDE_PATH}")
|
||||||
else()
|
else()
|
||||||
get_filename_component(CURR_ABS_INC_PATH
|
get_filename_component(CURR_ABS_INC_PATH ${INCLUDE_PATH} REALPATH BASE_DIR
|
||||||
${INCLUDE_PATH} REALPATH BASE_DIR ${CMAKE_SOURCE_DIR})
|
${CMAKE_SOURCE_DIR})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CMAKE_VERBOSE)
|
if(CMAKE_VERBOSE)
|
||||||
message(STATUS "FSFW include path: ${CURR_ABS_INC_PATH}")
|
message(STATUS "FSFW include path: ${CURR_ABS_INC_PATH}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
list(APPEND FSFW_ADD_INC_PATHS_ABS ${CURR_ABS_INC_PATH})
|
list(APPEND FSFW_ADD_INC_PATHS_ABS ${CURR_ABS_INC_PATH})
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||||
if(NOT DEFINED FSFW_WARNING_FLAGS)
|
if(NOT DEFINED FSFW_WARNING_FLAGS)
|
||||||
set(FSFW_WARNING_FLAGS
|
set(FSFW_WARNING_FLAGS
|
||||||
-Wall
|
-Wall
|
||||||
-Wextra
|
-Wextra
|
||||||
-Wimplicit-fallthrough=1
|
-Wimplicit-fallthrough=1
|
||||||
-Wno-unused-parameter
|
-Wno-unused-parameter
|
||||||
-Wno-psabi
|
-Wno-psabi
|
||||||
-Wduplicated-cond # check for duplicate conditions
|
-Wduplicated-cond # check for duplicate conditions
|
||||||
-Wduplicated-branches # check for duplicate branches
|
-Wduplicated-branches # check for duplicate branches
|
||||||
-Wlogical-op # Search for bitwise operations instead of logical
|
-Wlogical-op # Search for bitwise operations instead of logical
|
||||||
-Wnull-dereference # Search for NULL dereference
|
-Wnull-dereference # Search for NULL dereference
|
||||||
-Wundef # Warn if undefind marcos are used
|
-Wundef # Warn if undefind marcos are used
|
||||||
-Wformat=2 # Format string problem detection
|
-Wformat=2 # Format string problem detection
|
||||||
-Wformat-overflow=2 # Formatting issues in printf
|
-Wformat-overflow=2 # Formatting issues in printf
|
||||||
-Wformat-truncation=2 # Formatting issues in printf
|
-Wformat-truncation=2 # Formatting issues in printf
|
||||||
-Wformat-security # Search for dangerous printf operations
|
-Wformat-security # Search for dangerous printf operations
|
||||||
-Wstrict-overflow=3 # Warn if integer overflows might happen
|
-Wstrict-overflow=3 # Warn if integer overflows might happen
|
||||||
-Warray-bounds=2 # Some array bounds violations will be found
|
-Warray-bounds=2 # Some array bounds violations will be found
|
||||||
-Wshift-overflow=2 # Search for bit left shift overflows (<c++14)
|
-Wshift-overflow=2 # Search for bit left shift overflows (<c++14)
|
||||||
-Wcast-qual # Warn if the constness is cast away
|
-Wcast-qual # Warn if the constness is cast away
|
||||||
-Wstringop-overflow=4
|
-Wstringop-overflow=4
|
||||||
# -Wstack-protector # Emits a few false positives for low level access
|
# -Wstack-protector # Emits a few false positives for low level access
|
||||||
# -Wconversion # Creates many false positives
|
# -Wconversion # Creates many false positives -Warith-conversion # Use
|
||||||
# -Warith-conversion # Use with Wconversion to find more implicit conversions
|
# with Wconversion to find more implicit conversions -fanalyzer # Should
|
||||||
# -fanalyzer # Should be used to look through problems
|
# be used to look through problems
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(FSFW_GENERATE_SECTIONS)
|
if(FSFW_GENERATE_SECTIONS)
|
||||||
target_compile_options(${LIB_FSFW_NAME} PRIVATE
|
target_compile_options(${LIB_FSFW_NAME} PRIVATE "-ffunction-sections"
|
||||||
"-ffunction-sections"
|
"-fdata-sections")
|
||||||
"-fdata-sections"
|
endif()
|
||||||
)
|
|
||||||
endif()
|
if(FSFW_REMOVE_UNUSED_CODE)
|
||||||
|
target_link_options(${LIB_FSFW_NAME} PRIVATE "Wl,--gc-sections")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(FSFW_WARNING_SHADOW_LOCAL_GCC)
|
||||||
|
list(APPEND WARNING_FLAGS "-Wshadow=local")
|
||||||
|
endif()
|
||||||
|
|
||||||
if(FSFW_REMOVE_UNUSED_CODE)
|
|
||||||
target_link_options(${LIB_FSFW_NAME} PRIVATE
|
|
||||||
"Wl,--gc-sections"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(FSFW_WARNING_SHADOW_LOCAL_GCC)
|
|
||||||
list(APPEND WARNING_FLAGS "-Wshadow=local")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||||
set(COMPILER_FLAGS "/permissive-")
|
set(COMPILER_FLAGS "/permissive-")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Required include paths to compile the FSFW
|
# Required include paths to compile the FSFW
|
||||||
target_include_directories(${LIB_FSFW_NAME} INTERFACE
|
target_include_directories(
|
||||||
${CMAKE_SOURCE_DIR}
|
${LIB_FSFW_NAME} INTERFACE ${CMAKE_SOURCE_DIR} ${FSFW_CONFIG_PATH_ABSOLUTE}
|
||||||
${FSFW_CONFIG_PATH_ABSOLUTE}
|
${FSFW_CORE_INC_PATH} ${FSFW_ADD_INC_PATHS_ABS})
|
||||||
${FSFW_CORE_INC_PATH}
|
|
||||||
${FSFW_ADD_INC_PATHS_ABS}
|
|
||||||
)
|
|
||||||
|
|
||||||
# Includes path required to compile FSFW itself as well
|
# Includes path required to compile FSFW itself as well We assume that the
|
||||||
# We assume that the fsfwconfig folder uses include relative to the project
|
# fsfwconfig folder uses include relative to the project root here!
|
||||||
# root here!
|
target_include_directories(
|
||||||
target_include_directories(${LIB_FSFW_NAME} PRIVATE
|
${LIB_FSFW_NAME} PRIVATE ${CMAKE_SOURCE_DIR} ${FSFW_CONFIG_PATH_ABSOLUTE}
|
||||||
${CMAKE_SOURCE_DIR}
|
${FSFW_CORE_INC_PATH} ${FSFW_ADD_INC_PATHS_ABS})
|
||||||
${FSFW_CONFIG_PATH_ABSOLUTE}
|
|
||||||
${FSFW_CORE_INC_PATH}
|
|
||||||
${FSFW_ADD_INC_PATHS_ABS}
|
|
||||||
)
|
|
||||||
|
|
||||||
target_compile_options(${LIB_FSFW_NAME} PRIVATE
|
target_compile_options(${LIB_FSFW_NAME} PRIVATE ${FSFW_WARNING_FLAGS}
|
||||||
${FSFW_WARNING_FLAGS}
|
${COMPILER_FLAGS})
|
||||||
${COMPILER_FLAGS}
|
|
||||||
)
|
|
||||||
|
|
||||||
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
|
target_link_libraries(${LIB_FSFW_NAME} PRIVATE ${FSFW_ETL_LINK_TARGET}
|
||||||
${FSFW_ETL_LINK_TARGET}
|
${FSFW_ADDITIONAL_LINK_LIBS})
|
||||||
${FSFW_ADDITIONAL_LINK_LIBS}
|
|
||||||
)
|
|
||||||
|
|
||||||
string(CONCAT POST_BUILD_COMMENT
|
string(
|
||||||
|
CONCAT
|
||||||
|
POST_BUILD_COMMENT
|
||||||
"######################################################################\n"
|
"######################################################################\n"
|
||||||
"Built FSFW v${FSFW_VERSION}.${FSFW_SUBVERSION}.${FSFW_REVISION}, "
|
"Built FSFW v${FSFW_VERSION}.${FSFW_SUBVERSION}.${FSFW_REVISION}, "
|
||||||
"Target OSAL: ${FSFW_OS_NAME}\n"
|
"Target OSAL: ${FSFW_OS_NAME}\n"
|
||||||
"######################################################################\n"
|
"######################################################################\n")
|
||||||
)
|
|
||||||
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
TARGET ${LIB_FSFW_NAME}
|
TARGET ${LIB_FSFW_NAME}
|
||||||
POST_BUILD
|
POST_BUILD
|
||||||
COMMENT ${POST_BUILD_COMMENT}
|
COMMENT ${POST_BUILD_COMMENT})
|
||||||
)
|
|
||||||
|
0
FSFWVersion.h.in
Normal file
0
FSFWVersion.h.in
Normal file
@ -99,7 +99,7 @@ add and link against the FSFW library in general.
|
|||||||
|
|
||||||
4. Link against the FSFW library
|
4. Link against the FSFW library
|
||||||
|
|
||||||
```cmake
|
```sh
|
||||||
target_link_libraries(${YourProjectName} PRIVATE fsfw)
|
target_link_libraries(${YourProjectName} PRIVATE fsfw)
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -131,7 +131,7 @@ default. This can be disabled by setting the `FSFW_TESTS_COV_GEN` option to `OFF
|
|||||||
You can use the following commands inside the `fsfw` folder to set up the build system
|
You can use the following commands inside the `fsfw` folder to set up the build system
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
mkdir build-Unittest && cd build-Unittest
|
mkdir build-tests && cd build-tests
|
||||||
cmake -DFSFW_BUILD_UNITTESTS=ON -DFSFW_OSAL=host -DCMAKE_BUILD_TYPE=Debug ..
|
cmake -DFSFW_BUILD_UNITTESTS=ON -DFSFW_OSAL=host -DCMAKE_BUILD_TYPE=Debug ..
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -12,3 +12,9 @@ RUN git clone https://github.com/catchorg/Catch2.git && \
|
|||||||
git checkout v3.0.0-preview5 && \
|
git checkout v3.0.0-preview5 && \
|
||||||
cmake -Bbuild -H. -DBUILD_TESTING=OFF && \
|
cmake -Bbuild -H. -DBUILD_TESTING=OFF && \
|
||||||
cmake --build build/ --target install
|
cmake --build build/ --target install
|
||||||
|
|
||||||
|
RUN git clone https://github.com/ETLCPP/etl.git && \
|
||||||
|
cd etl && \
|
||||||
|
git checkout 20.28.0 && \
|
||||||
|
cmake -B build . && \
|
||||||
|
cmake --install build/
|
||||||
|
2
automation/Jenkinsfile
vendored
2
automation/Jenkinsfile
vendored
@ -14,7 +14,7 @@ pipeline {
|
|||||||
stage('Configure') {
|
stage('Configure') {
|
||||||
steps {
|
steps {
|
||||||
dir(BUILDDIR) {
|
dir(BUILDDIR) {
|
||||||
sh 'cmake -DFSFW_OSAL=host -DFSFW_BUILD_UNITTESTS=ON ..'
|
sh 'cmake -DFSFW_OSAL=host -DFSFW_BUILD_UNITTESTS=ON -DFSFW_CICD_BUILD=ON ..'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
28
cmake/FsfwHelpers.cmake
Normal file
28
cmake/FsfwHelpers.cmake
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# Determines the git version with git describe and returns it by setting
|
||||||
|
# the GIT_INFO list in the parent scope. The list has the following entries
|
||||||
|
# 1. Full version string
|
||||||
|
# 2. Major version
|
||||||
|
# 3. Minor version
|
||||||
|
# 4. Revision
|
||||||
|
# 5. git SHA hash and commits since tag
|
||||||
|
function(determine_version_with_git)
|
||||||
|
include(GetGitRevisionDescription)
|
||||||
|
git_describe(VERSION ${ARGN})
|
||||||
|
string(FIND ${VERSION} "." VALID_VERSION)
|
||||||
|
if(VALID_VERSION EQUAL -1)
|
||||||
|
message(WARNING "Version string ${VERSION} retrieved with git describe is invalid")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
# Parse the version information into pieces.
|
||||||
|
string(REGEX REPLACE "^v([0-9]+)\\..*" "\\1" _VERSION_MAJOR "${VERSION}")
|
||||||
|
string(REGEX REPLACE "^v[0-9]+\\.([0-9]+).*" "\\1" _VERSION_MINOR "${VERSION}")
|
||||||
|
string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" _VERSION_PATCH "${VERSION}")
|
||||||
|
string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.[0-9]+-(.*)" "\\1" VERSION_SHA1 "${VERSION}")
|
||||||
|
set(GIT_INFO ${VERSION})
|
||||||
|
list(APPEND GIT_INFO ${_VERSION_MAJOR})
|
||||||
|
list(APPEND GIT_INFO ${_VERSION_MINOR})
|
||||||
|
list(APPEND GIT_INFO ${_VERSION_PATCH})
|
||||||
|
list(APPEND GIT_INFO ${VERSION_SHA1})
|
||||||
|
set(GIT_INFO ${GIT_INFO} PARENT_SCOPE)
|
||||||
|
message(STATUS "${MSG_PREFIX} Set git version info into GIT_INFO from the git tag ${VERSION}")
|
||||||
|
endfunction()
|
7
cmake/cmake-modules/README.md
Normal file
7
cmake/cmake-modules/README.md
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
The files in the `bilke` folder were manually copy and pasted from the
|
||||||
|
[cmake-modules repository](https://github.com/bilke/cmake-modules). It was decided to do
|
||||||
|
this because only a small subset of its provided functions are needed.
|
||||||
|
|
||||||
|
The files in the `rpavlik` folder were manually copy and pasted from the
|
||||||
|
[cmake-modules repository](https://github.com/rpavlik/cmake-modules). It was decided to do
|
||||||
|
this because only a small subset of its provided functions are needed.
|
719
cmake/cmake-modules/bilke/CodeCoverage.cmake
Normal file
719
cmake/cmake-modules/bilke/CodeCoverage.cmake
Normal file
@ -0,0 +1,719 @@
|
|||||||
|
# Copyright (c) 2012 - 2017, Lars Bilke
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
# are permitted provided that the following conditions are met:
|
||||||
|
#
|
||||||
|
# 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
# list of conditions and the following disclaimer.
|
||||||
|
#
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
|
# and/or other materials provided with the distribution.
|
||||||
|
#
|
||||||
|
# 3. Neither the name of the copyright holder nor the names of its contributors
|
||||||
|
# may be used to endorse or promote products derived from this software without
|
||||||
|
# specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
#
|
||||||
|
# CHANGES:
|
||||||
|
#
|
||||||
|
# 2012-01-31, Lars Bilke
|
||||||
|
# - Enable Code Coverage
|
||||||
|
#
|
||||||
|
# 2013-09-17, Joakim Söderberg
|
||||||
|
# - Added support for Clang.
|
||||||
|
# - Some additional usage instructions.
|
||||||
|
#
|
||||||
|
# 2016-02-03, Lars Bilke
|
||||||
|
# - Refactored functions to use named parameters
|
||||||
|
#
|
||||||
|
# 2017-06-02, Lars Bilke
|
||||||
|
# - Merged with modified version from github.com/ufz/ogs
|
||||||
|
#
|
||||||
|
# 2019-05-06, Anatolii Kurotych
|
||||||
|
# - Remove unnecessary --coverage flag
|
||||||
|
#
|
||||||
|
# 2019-12-13, FeRD (Frank Dana)
|
||||||
|
# - Deprecate COVERAGE_LCOVR_EXCLUDES and COVERAGE_GCOVR_EXCLUDES lists in favor
|
||||||
|
# of tool-agnostic COVERAGE_EXCLUDES variable, or EXCLUDE setup arguments.
|
||||||
|
# - CMake 3.4+: All excludes can be specified relative to BASE_DIRECTORY
|
||||||
|
# - All setup functions: accept BASE_DIRECTORY, EXCLUDE list
|
||||||
|
# - Set lcov basedir with -b argument
|
||||||
|
# - Add automatic --demangle-cpp in lcovr, if 'c++filt' is available (can be
|
||||||
|
# overridden with NO_DEMANGLE option in setup_target_for_coverage_lcovr().)
|
||||||
|
# - Delete output dir, .info file on 'make clean'
|
||||||
|
# - Remove Python detection, since version mismatches will break gcovr
|
||||||
|
# - Minor cleanup (lowercase function names, update examples...)
|
||||||
|
#
|
||||||
|
# 2019-12-19, FeRD (Frank Dana)
|
||||||
|
# - Rename Lcov outputs, make filtered file canonical, fix cleanup for targets
|
||||||
|
#
|
||||||
|
# 2020-01-19, Bob Apthorpe
|
||||||
|
# - Added gfortran support
|
||||||
|
#
|
||||||
|
# 2020-02-17, FeRD (Frank Dana)
|
||||||
|
# - Make all add_custom_target()s VERBATIM to auto-escape wildcard characters
|
||||||
|
# in EXCLUDEs, and remove manual escaping from gcovr targets
|
||||||
|
#
|
||||||
|
# 2021-01-19, Robin Mueller
|
||||||
|
# - Add CODE_COVERAGE_VERBOSE option which will allow to print out commands which are run
|
||||||
|
# - Added the option for users to set the GCOVR_ADDITIONAL_ARGS variable to supply additional
|
||||||
|
# flags to the gcovr command
|
||||||
|
#
|
||||||
|
# 2020-05-04, Mihchael Davis
|
||||||
|
# - Add -fprofile-abs-path to make gcno files contain absolute paths
|
||||||
|
# - Fix BASE_DIRECTORY not working when defined
|
||||||
|
# - Change BYPRODUCT from folder to index.html to stop ninja from complaining about double defines
|
||||||
|
#
|
||||||
|
# 2021-05-10, Martin Stump
|
||||||
|
# - Check if the generator is multi-config before warning about non-Debug builds
|
||||||
|
#
|
||||||
|
# 2022-02-22, Marko Wehle
|
||||||
|
# - Change gcovr output from -o <filename> for --xml <filename> and --html <filename> output respectively.
|
||||||
|
# This will allow for Multiple Output Formats at the same time by making use of GCOVR_ADDITIONAL_ARGS, e.g. GCOVR_ADDITIONAL_ARGS "--txt".
|
||||||
|
#
|
||||||
|
# USAGE:
|
||||||
|
#
|
||||||
|
# 1. Copy this file into your cmake modules path.
|
||||||
|
#
|
||||||
|
# 2. Add the following line to your CMakeLists.txt (best inside an if-condition
|
||||||
|
# using a CMake option() to enable it just optionally):
|
||||||
|
# include(CodeCoverage)
|
||||||
|
#
|
||||||
|
# 3. Append necessary compiler flags for all supported source files:
|
||||||
|
# append_coverage_compiler_flags()
|
||||||
|
# Or for specific target:
|
||||||
|
# append_coverage_compiler_flags_to_target(YOUR_TARGET_NAME)
|
||||||
|
#
|
||||||
|
# 3.a (OPTIONAL) Set appropriate optimization flags, e.g. -O0, -O1 or -Og
|
||||||
|
#
|
||||||
|
# 4. If you need to exclude additional directories from the report, specify them
|
||||||
|
# using full paths in the COVERAGE_EXCLUDES variable before calling
|
||||||
|
# setup_target_for_coverage_*().
|
||||||
|
# Example:
|
||||||
|
# set(COVERAGE_EXCLUDES
|
||||||
|
# '${PROJECT_SOURCE_DIR}/src/dir1/*'
|
||||||
|
# '/path/to/my/src/dir2/*')
|
||||||
|
# Or, use the EXCLUDE argument to setup_target_for_coverage_*().
|
||||||
|
# Example:
|
||||||
|
# setup_target_for_coverage_lcov(
|
||||||
|
# NAME coverage
|
||||||
|
# EXECUTABLE testrunner
|
||||||
|
# EXCLUDE "${PROJECT_SOURCE_DIR}/src/dir1/*" "/path/to/my/src/dir2/*")
|
||||||
|
#
|
||||||
|
# 4.a NOTE: With CMake 3.4+, COVERAGE_EXCLUDES or EXCLUDE can also be set
|
||||||
|
# relative to the BASE_DIRECTORY (default: PROJECT_SOURCE_DIR)
|
||||||
|
# Example:
|
||||||
|
# set(COVERAGE_EXCLUDES "dir1/*")
|
||||||
|
# setup_target_for_coverage_gcovr_html(
|
||||||
|
# NAME coverage
|
||||||
|
# EXECUTABLE testrunner
|
||||||
|
# BASE_DIRECTORY "${PROJECT_SOURCE_DIR}/src"
|
||||||
|
# EXCLUDE "dir2/*")
|
||||||
|
#
|
||||||
|
# 5. Use the functions described below to create a custom make target which
|
||||||
|
# runs your test executable and produces a code coverage report.
|
||||||
|
#
|
||||||
|
# 6. Build a Debug build:
|
||||||
|
# cmake -DCMAKE_BUILD_TYPE=Debug ..
|
||||||
|
# make
|
||||||
|
# make my_coverage_target
|
||||||
|
#
|
||||||
|
|
||||||
|
include(CMakeParseArguments)
|
||||||
|
|
||||||
|
option(CODE_COVERAGE_VERBOSE "Verbose information" FALSE)
|
||||||
|
|
||||||
|
# Check prereqs
|
||||||
|
find_program( GCOV_PATH gcov )
|
||||||
|
find_program( LCOV_PATH NAMES lcov lcov.bat lcov.exe lcov.perl)
|
||||||
|
find_program( FASTCOV_PATH NAMES fastcov fastcov.py )
|
||||||
|
find_program( GENHTML_PATH NAMES genhtml genhtml.perl genhtml.bat )
|
||||||
|
find_program( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/scripts/test)
|
||||||
|
find_program( CPPFILT_PATH NAMES c++filt )
|
||||||
|
|
||||||
|
if(NOT GCOV_PATH)
|
||||||
|
message(FATAL_ERROR "gcov not found! Aborting...")
|
||||||
|
endif() # NOT GCOV_PATH
|
||||||
|
|
||||||
|
get_property(LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
|
||||||
|
list(GET LANGUAGES 0 LANG)
|
||||||
|
|
||||||
|
if("${CMAKE_${LANG}_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
|
||||||
|
if("${CMAKE_${LANG}_COMPILER_VERSION}" VERSION_LESS 3)
|
||||||
|
message(FATAL_ERROR "Clang version must be 3.0.0 or greater! Aborting...")
|
||||||
|
endif()
|
||||||
|
elseif(NOT CMAKE_COMPILER_IS_GNUCXX)
|
||||||
|
if("${CMAKE_Fortran_COMPILER_ID}" MATCHES "[Ff]lang")
|
||||||
|
# Do nothing; exit conditional without error if true
|
||||||
|
elseif("${CMAKE_Fortran_COMPILER_ID}" MATCHES "GNU")
|
||||||
|
# Do nothing; exit conditional without error if true
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "Compiler is not GNU gcc! Aborting...")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(COVERAGE_COMPILER_FLAGS "-g -fprofile-arcs -ftest-coverage"
|
||||||
|
CACHE INTERNAL "")
|
||||||
|
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
|
||||||
|
include(CheckCXXCompilerFlag)
|
||||||
|
check_cxx_compiler_flag(-fprofile-abs-path HAVE_fprofile_abs_path)
|
||||||
|
if(HAVE_fprofile_abs_path)
|
||||||
|
set(COVERAGE_COMPILER_FLAGS "${COVERAGE_COMPILER_FLAGS} -fprofile-abs-path")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(CMAKE_Fortran_FLAGS_COVERAGE
|
||||||
|
${COVERAGE_COMPILER_FLAGS}
|
||||||
|
CACHE STRING "Flags used by the Fortran compiler during coverage builds."
|
||||||
|
FORCE )
|
||||||
|
set(CMAKE_CXX_FLAGS_COVERAGE
|
||||||
|
${COVERAGE_COMPILER_FLAGS}
|
||||||
|
CACHE STRING "Flags used by the C++ compiler during coverage builds."
|
||||||
|
FORCE )
|
||||||
|
set(CMAKE_C_FLAGS_COVERAGE
|
||||||
|
${COVERAGE_COMPILER_FLAGS}
|
||||||
|
CACHE STRING "Flags used by the C compiler during coverage builds."
|
||||||
|
FORCE )
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS_COVERAGE
|
||||||
|
""
|
||||||
|
CACHE STRING "Flags used for linking binaries during coverage builds."
|
||||||
|
FORCE )
|
||||||
|
set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE
|
||||||
|
""
|
||||||
|
CACHE STRING "Flags used by the shared libraries linker during coverage builds."
|
||||||
|
FORCE )
|
||||||
|
mark_as_advanced(
|
||||||
|
CMAKE_Fortran_FLAGS_COVERAGE
|
||||||
|
CMAKE_CXX_FLAGS_COVERAGE
|
||||||
|
CMAKE_C_FLAGS_COVERAGE
|
||||||
|
CMAKE_EXE_LINKER_FLAGS_COVERAGE
|
||||||
|
CMAKE_SHARED_LINKER_FLAGS_COVERAGE )
|
||||||
|
|
||||||
|
get_property(GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||||
|
if(NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG))
|
||||||
|
message(WARNING "Code coverage results with an optimised (non-Debug) build may be misleading")
|
||||||
|
endif() # NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG)
|
||||||
|
|
||||||
|
if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
|
||||||
|
link_libraries(gcov)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Defines a target for running and collection code coverage information
|
||||||
|
# Builds dependencies, runs the given executable and outputs reports.
|
||||||
|
# NOTE! The executable should always have a ZERO as exit code otherwise
|
||||||
|
# the coverage generation will not complete.
|
||||||
|
#
|
||||||
|
# setup_target_for_coverage_lcov(
|
||||||
|
# NAME testrunner_coverage # New target name
|
||||||
|
# EXECUTABLE testrunner -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
|
||||||
|
# DEPENDENCIES testrunner # Dependencies to build first
|
||||||
|
# BASE_DIRECTORY "../" # Base directory for report
|
||||||
|
# # (defaults to PROJECT_SOURCE_DIR)
|
||||||
|
# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative
|
||||||
|
# # to BASE_DIRECTORY, with CMake 3.4+)
|
||||||
|
# NO_DEMANGLE # Don't demangle C++ symbols
|
||||||
|
# # even if c++filt is found
|
||||||
|
# )
|
||||||
|
function(setup_target_for_coverage_lcov)
|
||||||
|
|
||||||
|
set(options NO_DEMANGLE)
|
||||||
|
set(oneValueArgs BASE_DIRECTORY NAME)
|
||||||
|
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES LCOV_ARGS GENHTML_ARGS)
|
||||||
|
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||||
|
|
||||||
|
if(NOT LCOV_PATH)
|
||||||
|
message(FATAL_ERROR "lcov not found! Aborting...")
|
||||||
|
endif() # NOT LCOV_PATH
|
||||||
|
|
||||||
|
if(NOT GENHTML_PATH)
|
||||||
|
message(FATAL_ERROR "genhtml not found! Aborting...")
|
||||||
|
endif() # NOT GENHTML_PATH
|
||||||
|
|
||||||
|
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
|
||||||
|
if(DEFINED Coverage_BASE_DIRECTORY)
|
||||||
|
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
|
||||||
|
else()
|
||||||
|
set(BASEDIR ${PROJECT_SOURCE_DIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Collect excludes (CMake 3.4+: Also compute absolute paths)
|
||||||
|
set(LCOV_EXCLUDES "")
|
||||||
|
foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_LCOV_EXCLUDES})
|
||||||
|
if(CMAKE_VERSION VERSION_GREATER 3.4)
|
||||||
|
get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR})
|
||||||
|
endif()
|
||||||
|
list(APPEND LCOV_EXCLUDES "${EXCLUDE}")
|
||||||
|
endforeach()
|
||||||
|
list(REMOVE_DUPLICATES LCOV_EXCLUDES)
|
||||||
|
|
||||||
|
# Conditional arguments
|
||||||
|
if(CPPFILT_PATH AND NOT ${Coverage_NO_DEMANGLE})
|
||||||
|
set(GENHTML_EXTRA_ARGS "--demangle-cpp")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Setting up commands which will be run to generate coverage data.
|
||||||
|
# Cleanup lcov
|
||||||
|
set(LCOV_CLEAN_CMD
|
||||||
|
${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -directory .
|
||||||
|
-b ${BASEDIR} --zerocounters
|
||||||
|
)
|
||||||
|
# Create baseline to make sure untouched files show up in the report
|
||||||
|
set(LCOV_BASELINE_CMD
|
||||||
|
${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -c -i -d . -b
|
||||||
|
${BASEDIR} -o ${Coverage_NAME}.base
|
||||||
|
)
|
||||||
|
# Run tests
|
||||||
|
set(LCOV_EXEC_TESTS_CMD
|
||||||
|
${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}
|
||||||
|
)
|
||||||
|
# Capturing lcov counters and generating report
|
||||||
|
set(LCOV_CAPTURE_CMD
|
||||||
|
${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --directory . -b
|
||||||
|
${BASEDIR} --capture --output-file ${Coverage_NAME}.capture
|
||||||
|
)
|
||||||
|
# add baseline counters
|
||||||
|
set(LCOV_BASELINE_COUNT_CMD
|
||||||
|
${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -a ${Coverage_NAME}.base
|
||||||
|
-a ${Coverage_NAME}.capture --output-file ${Coverage_NAME}.total
|
||||||
|
)
|
||||||
|
# filter collected data to final coverage report
|
||||||
|
set(LCOV_FILTER_CMD
|
||||||
|
${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --remove
|
||||||
|
${Coverage_NAME}.total ${LCOV_EXCLUDES} --output-file ${Coverage_NAME}.info
|
||||||
|
)
|
||||||
|
# Generate HTML output
|
||||||
|
set(LCOV_GEN_HTML_CMD
|
||||||
|
${GENHTML_PATH} ${GENHTML_EXTRA_ARGS} ${Coverage_GENHTML_ARGS} -o
|
||||||
|
${Coverage_NAME} ${Coverage_NAME}.info
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if(CODE_COVERAGE_VERBOSE)
|
||||||
|
message(STATUS "Executed command report")
|
||||||
|
message(STATUS "Command to clean up lcov: ")
|
||||||
|
string(REPLACE ";" " " LCOV_CLEAN_CMD_SPACED "${LCOV_CLEAN_CMD}")
|
||||||
|
message(STATUS "${LCOV_CLEAN_CMD_SPACED}")
|
||||||
|
|
||||||
|
message(STATUS "Command to create baseline: ")
|
||||||
|
string(REPLACE ";" " " LCOV_BASELINE_CMD_SPACED "${LCOV_BASELINE_CMD}")
|
||||||
|
message(STATUS "${LCOV_BASELINE_CMD_SPACED}")
|
||||||
|
|
||||||
|
message(STATUS "Command to run the tests: ")
|
||||||
|
string(REPLACE ";" " " LCOV_EXEC_TESTS_CMD_SPACED "${LCOV_EXEC_TESTS_CMD}")
|
||||||
|
message(STATUS "${LCOV_EXEC_TESTS_CMD_SPACED}")
|
||||||
|
|
||||||
|
message(STATUS "Command to capture counters and generate report: ")
|
||||||
|
string(REPLACE ";" " " LCOV_CAPTURE_CMD_SPACED "${LCOV_CAPTURE_CMD}")
|
||||||
|
message(STATUS "${LCOV_CAPTURE_CMD_SPACED}")
|
||||||
|
|
||||||
|
message(STATUS "Command to add baseline counters: ")
|
||||||
|
string(REPLACE ";" " " LCOV_BASELINE_COUNT_CMD_SPACED "${LCOV_BASELINE_COUNT_CMD}")
|
||||||
|
message(STATUS "${LCOV_BASELINE_COUNT_CMD_SPACED}")
|
||||||
|
|
||||||
|
message(STATUS "Command to filter collected data: ")
|
||||||
|
string(REPLACE ";" " " LCOV_FILTER_CMD_SPACED "${LCOV_FILTER_CMD}")
|
||||||
|
message(STATUS "${LCOV_FILTER_CMD_SPACED}")
|
||||||
|
|
||||||
|
message(STATUS "Command to generate lcov HTML output: ")
|
||||||
|
string(REPLACE ";" " " LCOV_GEN_HTML_CMD_SPACED "${LCOV_GEN_HTML_CMD}")
|
||||||
|
message(STATUS "${LCOV_GEN_HTML_CMD_SPACED}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Setup target
|
||||||
|
add_custom_target(${Coverage_NAME}
|
||||||
|
COMMAND ${LCOV_CLEAN_CMD}
|
||||||
|
COMMAND ${LCOV_BASELINE_CMD}
|
||||||
|
COMMAND ${LCOV_EXEC_TESTS_CMD}
|
||||||
|
COMMAND ${LCOV_CAPTURE_CMD}
|
||||||
|
COMMAND ${LCOV_BASELINE_COUNT_CMD}
|
||||||
|
COMMAND ${LCOV_FILTER_CMD}
|
||||||
|
COMMAND ${LCOV_GEN_HTML_CMD}
|
||||||
|
|
||||||
|
# Set output files as GENERATED (will be removed on 'make clean')
|
||||||
|
BYPRODUCTS
|
||||||
|
${Coverage_NAME}.base
|
||||||
|
${Coverage_NAME}.capture
|
||||||
|
${Coverage_NAME}.total
|
||||||
|
${Coverage_NAME}.info
|
||||||
|
${Coverage_NAME}/index.html
|
||||||
|
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
||||||
|
DEPENDS ${Coverage_DEPENDENCIES}
|
||||||
|
VERBATIM # Protect arguments to commands
|
||||||
|
COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report."
|
||||||
|
)
|
||||||
|
|
||||||
|
# Show where to find the lcov info report
|
||||||
|
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
|
||||||
|
COMMAND ;
|
||||||
|
COMMENT "Lcov code coverage info report saved in ${Coverage_NAME}.info."
|
||||||
|
)
|
||||||
|
|
||||||
|
# Show info where to find the report
|
||||||
|
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
|
||||||
|
COMMAND ;
|
||||||
|
COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report."
|
||||||
|
)
|
||||||
|
|
||||||
|
endfunction() # setup_target_for_coverage_lcov
|
||||||
|
|
||||||
|
# Defines a target for running and collection code coverage information
|
||||||
|
# Builds dependencies, runs the given executable and outputs reports.
|
||||||
|
# NOTE! The executable should always have a ZERO as exit code otherwise
|
||||||
|
# the coverage generation will not complete.
|
||||||
|
#
|
||||||
|
# setup_target_for_coverage_gcovr_xml(
|
||||||
|
# NAME ctest_coverage # New target name
|
||||||
|
# EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
|
||||||
|
# DEPENDENCIES executable_target # Dependencies to build first
|
||||||
|
# BASE_DIRECTORY "../" # Base directory for report
|
||||||
|
# # (defaults to PROJECT_SOURCE_DIR)
|
||||||
|
# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative
|
||||||
|
# # to BASE_DIRECTORY, with CMake 3.4+)
|
||||||
|
# )
|
||||||
|
# The user can set the variable GCOVR_ADDITIONAL_ARGS to supply additional flags to the
|
||||||
|
# GCVOR command.
|
||||||
|
function(setup_target_for_coverage_gcovr_xml)
|
||||||
|
|
||||||
|
set(options NONE)
|
||||||
|
set(oneValueArgs BASE_DIRECTORY NAME)
|
||||||
|
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
|
||||||
|
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||||
|
|
||||||
|
if(NOT GCOVR_PATH)
|
||||||
|
message(FATAL_ERROR "gcovr not found! Aborting...")
|
||||||
|
endif() # NOT GCOVR_PATH
|
||||||
|
|
||||||
|
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
|
||||||
|
if(DEFINED Coverage_BASE_DIRECTORY)
|
||||||
|
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
|
||||||
|
else()
|
||||||
|
set(BASEDIR ${PROJECT_SOURCE_DIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Collect excludes (CMake 3.4+: Also compute absolute paths)
|
||||||
|
set(GCOVR_EXCLUDES "")
|
||||||
|
foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_GCOVR_EXCLUDES})
|
||||||
|
if(CMAKE_VERSION VERSION_GREATER 3.4)
|
||||||
|
get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR})
|
||||||
|
endif()
|
||||||
|
list(APPEND GCOVR_EXCLUDES "${EXCLUDE}")
|
||||||
|
endforeach()
|
||||||
|
list(REMOVE_DUPLICATES GCOVR_EXCLUDES)
|
||||||
|
|
||||||
|
# Combine excludes to several -e arguments
|
||||||
|
set(GCOVR_EXCLUDE_ARGS "")
|
||||||
|
foreach(EXCLUDE ${GCOVR_EXCLUDES})
|
||||||
|
list(APPEND GCOVR_EXCLUDE_ARGS "-e")
|
||||||
|
list(APPEND GCOVR_EXCLUDE_ARGS "${EXCLUDE}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# Set up commands which will be run to generate coverage data
|
||||||
|
# Run tests
|
||||||
|
set(GCOVR_XML_EXEC_TESTS_CMD
|
||||||
|
${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}
|
||||||
|
)
|
||||||
|
# Running gcovr
|
||||||
|
set(GCOVR_XML_CMD
|
||||||
|
${GCOVR_PATH} --xml ${Coverage_NAME}.xml -r ${BASEDIR} ${GCOVR_ADDITIONAL_ARGS}
|
||||||
|
${GCOVR_EXCLUDE_ARGS} --object-directory=${PROJECT_BINARY_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
if(CODE_COVERAGE_VERBOSE)
|
||||||
|
message(STATUS "Executed command report")
|
||||||
|
|
||||||
|
message(STATUS "Command to run tests: ")
|
||||||
|
string(REPLACE ";" " " GCOVR_XML_EXEC_TESTS_CMD_SPACED "${GCOVR_XML_EXEC_TESTS_CMD}")
|
||||||
|
message(STATUS "${GCOVR_XML_EXEC_TESTS_CMD_SPACED}")
|
||||||
|
|
||||||
|
message(STATUS "Command to generate gcovr XML coverage data: ")
|
||||||
|
string(REPLACE ";" " " GCOVR_XML_CMD_SPACED "${GCOVR_XML_CMD}")
|
||||||
|
message(STATUS "${GCOVR_XML_CMD_SPACED}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_custom_target(${Coverage_NAME}
|
||||||
|
COMMAND ${GCOVR_XML_EXEC_TESTS_CMD}
|
||||||
|
COMMAND ${GCOVR_XML_CMD}
|
||||||
|
|
||||||
|
BYPRODUCTS ${Coverage_NAME}.xml
|
||||||
|
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
||||||
|
DEPENDS ${Coverage_DEPENDENCIES}
|
||||||
|
VERBATIM # Protect arguments to commands
|
||||||
|
COMMENT "Running gcovr to produce Cobertura code coverage report."
|
||||||
|
)
|
||||||
|
|
||||||
|
# Show info where to find the report
|
||||||
|
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
|
||||||
|
COMMAND ;
|
||||||
|
COMMENT "Cobertura code coverage report saved in ${Coverage_NAME}.xml."
|
||||||
|
)
|
||||||
|
endfunction() # setup_target_for_coverage_gcovr_xml
|
||||||
|
|
||||||
|
# Defines a target for running and collection code coverage information
|
||||||
|
# Builds dependencies, runs the given executable and outputs reports.
|
||||||
|
# NOTE! The executable should always have a ZERO as exit code otherwise
|
||||||
|
# the coverage generation will not complete.
|
||||||
|
#
|
||||||
|
# setup_target_for_coverage_gcovr_html(
|
||||||
|
# NAME ctest_coverage # New target name
|
||||||
|
# EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
|
||||||
|
# DEPENDENCIES executable_target # Dependencies to build first
|
||||||
|
# BASE_DIRECTORY "../" # Base directory for report
|
||||||
|
# # (defaults to PROJECT_SOURCE_DIR)
|
||||||
|
# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative
|
||||||
|
# # to BASE_DIRECTORY, with CMake 3.4+)
|
||||||
|
# )
|
||||||
|
# The user can set the variable GCOVR_ADDITIONAL_ARGS to supply additional flags to the
|
||||||
|
# GCVOR command.
|
||||||
|
function(setup_target_for_coverage_gcovr_html)
|
||||||
|
|
||||||
|
set(options NONE)
|
||||||
|
set(oneValueArgs BASE_DIRECTORY NAME)
|
||||||
|
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
|
||||||
|
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||||
|
|
||||||
|
if(NOT GCOVR_PATH)
|
||||||
|
message(FATAL_ERROR "gcovr not found! Aborting...")
|
||||||
|
endif() # NOT GCOVR_PATH
|
||||||
|
|
||||||
|
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
|
||||||
|
if(DEFINED Coverage_BASE_DIRECTORY)
|
||||||
|
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
|
||||||
|
else()
|
||||||
|
set(BASEDIR ${PROJECT_SOURCE_DIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Collect excludes (CMake 3.4+: Also compute absolute paths)
|
||||||
|
set(GCOVR_EXCLUDES "")
|
||||||
|
foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_GCOVR_EXCLUDES})
|
||||||
|
if(CMAKE_VERSION VERSION_GREATER 3.4)
|
||||||
|
get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR})
|
||||||
|
endif()
|
||||||
|
list(APPEND GCOVR_EXCLUDES "${EXCLUDE}")
|
||||||
|
endforeach()
|
||||||
|
list(REMOVE_DUPLICATES GCOVR_EXCLUDES)
|
||||||
|
|
||||||
|
# Combine excludes to several -e arguments
|
||||||
|
set(GCOVR_EXCLUDE_ARGS "")
|
||||||
|
foreach(EXCLUDE ${GCOVR_EXCLUDES})
|
||||||
|
list(APPEND GCOVR_EXCLUDE_ARGS "-e")
|
||||||
|
list(APPEND GCOVR_EXCLUDE_ARGS "${EXCLUDE}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# Set up commands which will be run to generate coverage data
|
||||||
|
# Run tests
|
||||||
|
set(GCOVR_HTML_EXEC_TESTS_CMD
|
||||||
|
${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}
|
||||||
|
)
|
||||||
|
# Create folder
|
||||||
|
set(GCOVR_HTML_FOLDER_CMD
|
||||||
|
${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/${Coverage_NAME}
|
||||||
|
)
|
||||||
|
# Running gcovr
|
||||||
|
set(GCOVR_HTML_CMD
|
||||||
|
${GCOVR_PATH} --html ${Coverage_NAME}/index.html --html-details -r ${BASEDIR} ${GCOVR_ADDITIONAL_ARGS}
|
||||||
|
${GCOVR_EXCLUDE_ARGS} --object-directory=${PROJECT_BINARY_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
if(CODE_COVERAGE_VERBOSE)
|
||||||
|
message(STATUS "Executed command report")
|
||||||
|
|
||||||
|
message(STATUS "Command to run tests: ")
|
||||||
|
string(REPLACE ";" " " GCOVR_HTML_EXEC_TESTS_CMD_SPACED "${GCOVR_HTML_EXEC_TESTS_CMD}")
|
||||||
|
message(STATUS "${GCOVR_HTML_EXEC_TESTS_CMD_SPACED}")
|
||||||
|
|
||||||
|
message(STATUS "Command to create a folder: ")
|
||||||
|
string(REPLACE ";" " " GCOVR_HTML_FOLDER_CMD_SPACED "${GCOVR_HTML_FOLDER_CMD}")
|
||||||
|
message(STATUS "${GCOVR_HTML_FOLDER_CMD_SPACED}")
|
||||||
|
|
||||||
|
message(STATUS "Command to generate gcovr HTML coverage data: ")
|
||||||
|
string(REPLACE ";" " " GCOVR_HTML_CMD_SPACED "${GCOVR_HTML_CMD}")
|
||||||
|
message(STATUS "${GCOVR_HTML_CMD_SPACED}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_custom_target(${Coverage_NAME}
|
||||||
|
COMMAND ${GCOVR_HTML_EXEC_TESTS_CMD}
|
||||||
|
COMMAND ${GCOVR_HTML_FOLDER_CMD}
|
||||||
|
COMMAND ${GCOVR_HTML_CMD}
|
||||||
|
|
||||||
|
BYPRODUCTS ${PROJECT_BINARY_DIR}/${Coverage_NAME}/index.html # report directory
|
||||||
|
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
||||||
|
DEPENDS ${Coverage_DEPENDENCIES}
|
||||||
|
VERBATIM # Protect arguments to commands
|
||||||
|
COMMENT "Running gcovr to produce HTML code coverage report."
|
||||||
|
)
|
||||||
|
|
||||||
|
# Show info where to find the report
|
||||||
|
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
|
||||||
|
COMMAND ;
|
||||||
|
COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report."
|
||||||
|
)
|
||||||
|
|
||||||
|
endfunction() # setup_target_for_coverage_gcovr_html
|
||||||
|
|
||||||
|
# Defines a target for running and collection code coverage information
|
||||||
|
# Builds dependencies, runs the given executable and outputs reports.
|
||||||
|
# NOTE! The executable should always have a ZERO as exit code otherwise
|
||||||
|
# the coverage generation will not complete.
|
||||||
|
#
|
||||||
|
# setup_target_for_coverage_fastcov(
|
||||||
|
# NAME testrunner_coverage # New target name
|
||||||
|
# EXECUTABLE testrunner -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
|
||||||
|
# DEPENDENCIES testrunner # Dependencies to build first
|
||||||
|
# BASE_DIRECTORY "../" # Base directory for report
|
||||||
|
# # (defaults to PROJECT_SOURCE_DIR)
|
||||||
|
# EXCLUDE "src/dir1/" "src/dir2/" # Patterns to exclude.
|
||||||
|
# NO_DEMANGLE # Don't demangle C++ symbols
|
||||||
|
# # even if c++filt is found
|
||||||
|
# SKIP_HTML # Don't create html report
|
||||||
|
# POST_CMD perl -i -pe s!${PROJECT_SOURCE_DIR}/!!g ctest_coverage.json # E.g. for stripping source dir from file paths
|
||||||
|
# )
|
||||||
|
function(setup_target_for_coverage_fastcov)
|
||||||
|
|
||||||
|
set(options NO_DEMANGLE SKIP_HTML)
|
||||||
|
set(oneValueArgs BASE_DIRECTORY NAME)
|
||||||
|
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES FASTCOV_ARGS GENHTML_ARGS POST_CMD)
|
||||||
|
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||||
|
|
||||||
|
if(NOT FASTCOV_PATH)
|
||||||
|
message(FATAL_ERROR "fastcov not found! Aborting...")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT Coverage_SKIP_HTML AND NOT GENHTML_PATH)
|
||||||
|
message(FATAL_ERROR "genhtml not found! Aborting...")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
|
||||||
|
if(Coverage_BASE_DIRECTORY)
|
||||||
|
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
|
||||||
|
else()
|
||||||
|
set(BASEDIR ${PROJECT_SOURCE_DIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Collect excludes (Patterns, not paths, for fastcov)
|
||||||
|
set(FASTCOV_EXCLUDES "")
|
||||||
|
foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_FASTCOV_EXCLUDES})
|
||||||
|
list(APPEND FASTCOV_EXCLUDES "${EXCLUDE}")
|
||||||
|
endforeach()
|
||||||
|
list(REMOVE_DUPLICATES FASTCOV_EXCLUDES)
|
||||||
|
|
||||||
|
# Conditional arguments
|
||||||
|
if(CPPFILT_PATH AND NOT ${Coverage_NO_DEMANGLE})
|
||||||
|
set(GENHTML_EXTRA_ARGS "--demangle-cpp")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Set up commands which will be run to generate coverage data
|
||||||
|
set(FASTCOV_EXEC_TESTS_CMD ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS})
|
||||||
|
|
||||||
|
set(FASTCOV_CAPTURE_CMD ${FASTCOV_PATH} ${Coverage_FASTCOV_ARGS} --gcov ${GCOV_PATH}
|
||||||
|
--search-directory ${BASEDIR}
|
||||||
|
--process-gcno
|
||||||
|
--output ${Coverage_NAME}.json
|
||||||
|
--exclude ${FASTCOV_EXCLUDES}
|
||||||
|
--exclude ${FASTCOV_EXCLUDES}
|
||||||
|
)
|
||||||
|
|
||||||
|
set(FASTCOV_CONVERT_CMD ${FASTCOV_PATH}
|
||||||
|
-C ${Coverage_NAME}.json --lcov --output ${Coverage_NAME}.info
|
||||||
|
)
|
||||||
|
|
||||||
|
if(Coverage_SKIP_HTML)
|
||||||
|
set(FASTCOV_HTML_CMD ";")
|
||||||
|
else()
|
||||||
|
set(FASTCOV_HTML_CMD ${GENHTML_PATH} ${GENHTML_EXTRA_ARGS} ${Coverage_GENHTML_ARGS}
|
||||||
|
-o ${Coverage_NAME} ${Coverage_NAME}.info
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(FASTCOV_POST_CMD ";")
|
||||||
|
if(Coverage_POST_CMD)
|
||||||
|
set(FASTCOV_POST_CMD ${Coverage_POST_CMD})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CODE_COVERAGE_VERBOSE)
|
||||||
|
message(STATUS "Code coverage commands for target ${Coverage_NAME} (fastcov):")
|
||||||
|
|
||||||
|
message(" Running tests:")
|
||||||
|
string(REPLACE ";" " " FASTCOV_EXEC_TESTS_CMD_SPACED "${FASTCOV_EXEC_TESTS_CMD}")
|
||||||
|
message(" ${FASTCOV_EXEC_TESTS_CMD_SPACED}")
|
||||||
|
|
||||||
|
message(" Capturing fastcov counters and generating report:")
|
||||||
|
string(REPLACE ";" " " FASTCOV_CAPTURE_CMD_SPACED "${FASTCOV_CAPTURE_CMD}")
|
||||||
|
message(" ${FASTCOV_CAPTURE_CMD_SPACED}")
|
||||||
|
|
||||||
|
message(" Converting fastcov .json to lcov .info:")
|
||||||
|
string(REPLACE ";" " " FASTCOV_CONVERT_CMD_SPACED "${FASTCOV_CONVERT_CMD}")
|
||||||
|
message(" ${FASTCOV_CONVERT_CMD_SPACED}")
|
||||||
|
|
||||||
|
if(NOT Coverage_SKIP_HTML)
|
||||||
|
message(" Generating HTML report: ")
|
||||||
|
string(REPLACE ";" " " FASTCOV_HTML_CMD_SPACED "${FASTCOV_HTML_CMD}")
|
||||||
|
message(" ${FASTCOV_HTML_CMD_SPACED}")
|
||||||
|
endif()
|
||||||
|
if(Coverage_POST_CMD)
|
||||||
|
message(" Running post command: ")
|
||||||
|
string(REPLACE ";" " " FASTCOV_POST_CMD_SPACED "${FASTCOV_POST_CMD}")
|
||||||
|
message(" ${FASTCOV_POST_CMD_SPACED}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Setup target
|
||||||
|
add_custom_target(${Coverage_NAME}
|
||||||
|
|
||||||
|
# Cleanup fastcov
|
||||||
|
COMMAND ${FASTCOV_PATH} ${Coverage_FASTCOV_ARGS} --gcov ${GCOV_PATH}
|
||||||
|
--search-directory ${BASEDIR}
|
||||||
|
--zerocounters
|
||||||
|
|
||||||
|
COMMAND ${FASTCOV_EXEC_TESTS_CMD}
|
||||||
|
COMMAND ${FASTCOV_CAPTURE_CMD}
|
||||||
|
COMMAND ${FASTCOV_CONVERT_CMD}
|
||||||
|
COMMAND ${FASTCOV_HTML_CMD}
|
||||||
|
COMMAND ${FASTCOV_POST_CMD}
|
||||||
|
|
||||||
|
# Set output files as GENERATED (will be removed on 'make clean')
|
||||||
|
BYPRODUCTS
|
||||||
|
${Coverage_NAME}.info
|
||||||
|
${Coverage_NAME}.json
|
||||||
|
${Coverage_NAME}/index.html # report directory
|
||||||
|
|
||||||
|
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
|
||||||
|
DEPENDS ${Coverage_DEPENDENCIES}
|
||||||
|
VERBATIM # Protect arguments to commands
|
||||||
|
COMMENT "Resetting code coverage counters to zero. Processing code coverage counters and generating report."
|
||||||
|
)
|
||||||
|
|
||||||
|
set(INFO_MSG "fastcov code coverage info report saved in ${Coverage_NAME}.info and ${Coverage_NAME}.json.")
|
||||||
|
if(NOT Coverage_SKIP_HTML)
|
||||||
|
string(APPEND INFO_MSG " Open ${PROJECT_BINARY_DIR}/${Coverage_NAME}/index.html in your browser to view the coverage report.")
|
||||||
|
endif()
|
||||||
|
# Show where to find the fastcov info report
|
||||||
|
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E echo ${INFO_MSG}
|
||||||
|
)
|
||||||
|
|
||||||
|
endfunction() # setup_target_for_coverage_fastcov
|
||||||
|
|
||||||
|
function(append_coverage_compiler_flags)
|
||||||
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
|
||||||
|
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
|
||||||
|
message(STATUS "Appending code coverage compiler flags: ${COVERAGE_COMPILER_FLAGS}")
|
||||||
|
endfunction() # append_coverage_compiler_flags
|
||||||
|
|
||||||
|
# Setup coverage for specific library
|
||||||
|
function(append_coverage_compiler_flags_to_target name)
|
||||||
|
target_compile_options(${name}
|
||||||
|
PRIVATE ${COVERAGE_COMPILER_FLAGS})
|
||||||
|
endfunction()
|
23
cmake/cmake-modules/bilke/LICENSE_1_0.txt
Normal file
23
cmake/cmake-modules/bilke/LICENSE_1_0.txt
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
Boost Software License - Version 1.0 - August 17th, 2003
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person or organization
|
||||||
|
obtaining a copy of the software and accompanying documentation covered by
|
||||||
|
this license (the "Software") to use, reproduce, display, distribute,
|
||||||
|
execute, and transmit the Software, and to prepare derivative works of the
|
||||||
|
Software, and to permit third-parties to whom the Software is furnished to
|
||||||
|
do so, all subject to the following:
|
||||||
|
|
||||||
|
The copyright notices in the Software and this entire statement, including
|
||||||
|
the above license grant, this restriction and the following disclaimer,
|
||||||
|
must be included in all copies of the Software, in whole or in part, and
|
||||||
|
all derivative works of the Software, unless such copies or derivative
|
||||||
|
works are solely in the form of machine-executable object code generated by
|
||||||
|
a source language processor.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||||
|
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||||
|
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||||
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
284
cmake/cmake-modules/rpavlik/GetGitRevisionDescription.cmake
Normal file
284
cmake/cmake-modules/rpavlik/GetGitRevisionDescription.cmake
Normal file
@ -0,0 +1,284 @@
|
|||||||
|
# - Returns a version string from Git
|
||||||
|
#
|
||||||
|
# These functions force a re-configure on each git commit so that you can
|
||||||
|
# trust the values of the variables in your build system.
|
||||||
|
#
|
||||||
|
# get_git_head_revision(<refspecvar> <hashvar> [ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR])
|
||||||
|
#
|
||||||
|
# Returns the refspec and sha hash of the current head revision
|
||||||
|
#
|
||||||
|
# git_describe(<var> [<additional arguments to git describe> ...])
|
||||||
|
#
|
||||||
|
# Returns the results of git describe on the source tree, and adjusting
|
||||||
|
# the output so that it tests false if an error occurs.
|
||||||
|
#
|
||||||
|
# git_describe_working_tree(<var> [<additional arguments to git describe> ...])
|
||||||
|
#
|
||||||
|
# Returns the results of git describe on the working tree (--dirty option),
|
||||||
|
# and adjusting the output so that it tests false if an error occurs.
|
||||||
|
#
|
||||||
|
# git_get_exact_tag(<var> [<additional arguments to git describe> ...])
|
||||||
|
#
|
||||||
|
# Returns the results of git describe --exact-match on the source tree,
|
||||||
|
# and adjusting the output so that it tests false if there was no exact
|
||||||
|
# matching tag.
|
||||||
|
#
|
||||||
|
# git_local_changes(<var>)
|
||||||
|
#
|
||||||
|
# Returns either "CLEAN" or "DIRTY" with respect to uncommitted changes.
|
||||||
|
# Uses the return code of "git diff-index --quiet HEAD --".
|
||||||
|
# Does not regard untracked files.
|
||||||
|
#
|
||||||
|
# Requires CMake 2.6 or newer (uses the 'function' command)
|
||||||
|
#
|
||||||
|
# Original Author:
|
||||||
|
# 2009-2020 Ryan Pavlik <ryan.pavlik@gmail.com> <abiryan@ryand.net>
|
||||||
|
# http://academic.cleardefinition.com
|
||||||
|
#
|
||||||
|
# Copyright 2009-2013, Iowa State University.
|
||||||
|
# Copyright 2013-2020, Ryan Pavlik
|
||||||
|
# Copyright 2013-2020, Contributors
|
||||||
|
# SPDX-License-Identifier: BSL-1.0
|
||||||
|
# Distributed under the Boost Software License, Version 1.0.
|
||||||
|
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
# http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
|
||||||
|
if(__get_git_revision_description)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
set(__get_git_revision_description YES)
|
||||||
|
|
||||||
|
# We must run the following at "include" time, not at function call time,
|
||||||
|
# to find the path to this module rather than the path to a calling list file
|
||||||
|
get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
|
||||||
|
|
||||||
|
# Function _git_find_closest_git_dir finds the next closest .git directory
|
||||||
|
# that is part of any directory in the path defined by _start_dir.
|
||||||
|
# The result is returned in the parent scope variable whose name is passed
|
||||||
|
# as variable _git_dir_var. If no .git directory can be found, the
|
||||||
|
# function returns an empty string via _git_dir_var.
|
||||||
|
#
|
||||||
|
# Example: Given a path C:/bla/foo/bar and assuming C:/bla/.git exists and
|
||||||
|
# neither foo nor bar contain a file/directory .git. This wil return
|
||||||
|
# C:/bla/.git
|
||||||
|
#
|
||||||
|
function(_git_find_closest_git_dir _start_dir _git_dir_var)
|
||||||
|
set(cur_dir "${_start_dir}")
|
||||||
|
set(git_dir "${_start_dir}/.git")
|
||||||
|
while(NOT EXISTS "${git_dir}")
|
||||||
|
# .git dir not found, search parent directories
|
||||||
|
set(git_previous_parent "${cur_dir}")
|
||||||
|
get_filename_component(cur_dir "${cur_dir}" DIRECTORY)
|
||||||
|
if(cur_dir STREQUAL git_previous_parent)
|
||||||
|
# We have reached the root directory, we are not in git
|
||||||
|
set(${_git_dir_var}
|
||||||
|
""
|
||||||
|
PARENT_SCOPE)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
set(git_dir "${cur_dir}/.git")
|
||||||
|
endwhile()
|
||||||
|
set(${_git_dir_var}
|
||||||
|
"${git_dir}"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(get_git_head_revision _refspecvar _hashvar)
|
||||||
|
_git_find_closest_git_dir("${CMAKE_CURRENT_SOURCE_DIR}" GIT_DIR)
|
||||||
|
|
||||||
|
if("${ARGN}" STREQUAL "ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR")
|
||||||
|
set(ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR TRUE)
|
||||||
|
else()
|
||||||
|
set(ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR FALSE)
|
||||||
|
endif()
|
||||||
|
if(NOT "${GIT_DIR}" STREQUAL "")
|
||||||
|
file(RELATIVE_PATH _relative_to_source_dir "${CMAKE_SOURCE_DIR}"
|
||||||
|
"${GIT_DIR}")
|
||||||
|
if("${_relative_to_source_dir}" MATCHES "[.][.]" AND NOT ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR)
|
||||||
|
# We've gone above the CMake root dir.
|
||||||
|
set(GIT_DIR "")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
if("${GIT_DIR}" STREQUAL "")
|
||||||
|
set(${_refspecvar}
|
||||||
|
"GITDIR-NOTFOUND"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
set(${_hashvar}
|
||||||
|
"GITDIR-NOTFOUND"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Check if the current source dir is a git submodule or a worktree.
|
||||||
|
# In both cases .git is a file instead of a directory.
|
||||||
|
#
|
||||||
|
if(NOT IS_DIRECTORY ${GIT_DIR})
|
||||||
|
# The following git command will return a non empty string that
|
||||||
|
# points to the super project working tree if the current
|
||||||
|
# source dir is inside a git submodule.
|
||||||
|
# Otherwise the command will return an empty string.
|
||||||
|
#
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${GIT_EXECUTABLE}" rev-parse
|
||||||
|
--show-superproject-working-tree
|
||||||
|
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||||
|
OUTPUT_VARIABLE out
|
||||||
|
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
if(NOT "${out}" STREQUAL "")
|
||||||
|
# If out is empty, GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a submodule
|
||||||
|
file(READ ${GIT_DIR} submodule)
|
||||||
|
string(REGEX REPLACE "gitdir: (.*)$" "\\1" GIT_DIR_RELATIVE
|
||||||
|
${submodule})
|
||||||
|
string(STRIP ${GIT_DIR_RELATIVE} GIT_DIR_RELATIVE)
|
||||||
|
get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH)
|
||||||
|
get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE}
|
||||||
|
ABSOLUTE)
|
||||||
|
set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD")
|
||||||
|
else()
|
||||||
|
# GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a worktree
|
||||||
|
file(READ ${GIT_DIR} worktree_ref)
|
||||||
|
# The .git directory contains a path to the worktree information directory
|
||||||
|
# inside the parent git repo of the worktree.
|
||||||
|
#
|
||||||
|
string(REGEX REPLACE "gitdir: (.*)$" "\\1" git_worktree_dir
|
||||||
|
${worktree_ref})
|
||||||
|
string(STRIP ${git_worktree_dir} git_worktree_dir)
|
||||||
|
_git_find_closest_git_dir("${git_worktree_dir}" GIT_DIR)
|
||||||
|
set(HEAD_SOURCE_FILE "${git_worktree_dir}/HEAD")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD")
|
||||||
|
endif()
|
||||||
|
set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data")
|
||||||
|
if(NOT EXISTS "${GIT_DATA}")
|
||||||
|
file(MAKE_DIRECTORY "${GIT_DATA}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT EXISTS "${HEAD_SOURCE_FILE}")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
set(HEAD_FILE "${GIT_DATA}/HEAD")
|
||||||
|
configure_file("${HEAD_SOURCE_FILE}" "${HEAD_FILE}" COPYONLY)
|
||||||
|
|
||||||
|
configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in"
|
||||||
|
"${GIT_DATA}/grabRef.cmake" @ONLY)
|
||||||
|
include("${GIT_DATA}/grabRef.cmake")
|
||||||
|
|
||||||
|
set(${_refspecvar}
|
||||||
|
"${HEAD_REF}"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
set(${_hashvar}
|
||||||
|
"${HEAD_HASH}"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(git_describe _var)
|
||||||
|
if(NOT GIT_FOUND)
|
||||||
|
find_package(Git QUIET)
|
||||||
|
endif()
|
||||||
|
get_git_head_revision(refspec hash)
|
||||||
|
if(NOT GIT_FOUND)
|
||||||
|
set(${_var}
|
||||||
|
"GIT-NOTFOUND"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
if(NOT hash)
|
||||||
|
set(${_var}
|
||||||
|
"HEAD-HASH-NOTFOUND"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# TODO sanitize
|
||||||
|
#if((${ARGN}" MATCHES "&&") OR
|
||||||
|
# (ARGN MATCHES "||") OR
|
||||||
|
# (ARGN MATCHES "\\;"))
|
||||||
|
# message("Please report the following error to the project!")
|
||||||
|
# message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}")
|
||||||
|
#endif()
|
||||||
|
|
||||||
|
#message(STATUS "Arguments to execute_process: ${ARGN}")
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${GIT_EXECUTABLE}" describe --tags --always ${hash} ${ARGN}
|
||||||
|
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||||
|
RESULT_VARIABLE res
|
||||||
|
OUTPUT_VARIABLE out
|
||||||
|
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
if(NOT res EQUAL 0)
|
||||||
|
set(out "${out}-${res}-NOTFOUND")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(${_var}
|
||||||
|
"${out}"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(git_describe_working_tree _var)
|
||||||
|
if(NOT GIT_FOUND)
|
||||||
|
find_package(Git QUIET)
|
||||||
|
endif()
|
||||||
|
if(NOT GIT_FOUND)
|
||||||
|
set(${_var}
|
||||||
|
"GIT-NOTFOUND"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${GIT_EXECUTABLE}" describe --dirty ${ARGN}
|
||||||
|
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||||
|
RESULT_VARIABLE res
|
||||||
|
OUTPUT_VARIABLE out
|
||||||
|
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
if(NOT res EQUAL 0)
|
||||||
|
set(out "${out}-${res}-NOTFOUND")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(${_var}
|
||||||
|
"${out}"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(git_get_exact_tag _var)
|
||||||
|
git_describe(out --exact-match ${ARGN})
|
||||||
|
set(${_var}
|
||||||
|
"${out}"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(git_local_changes _var)
|
||||||
|
if(NOT GIT_FOUND)
|
||||||
|
find_package(Git QUIET)
|
||||||
|
endif()
|
||||||
|
get_git_head_revision(refspec hash)
|
||||||
|
if(NOT GIT_FOUND)
|
||||||
|
set(${_var}
|
||||||
|
"GIT-NOTFOUND"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
if(NOT hash)
|
||||||
|
set(${_var}
|
||||||
|
"HEAD-HASH-NOTFOUND"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${GIT_EXECUTABLE}" diff-index --quiet HEAD --
|
||||||
|
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||||
|
RESULT_VARIABLE res
|
||||||
|
OUTPUT_VARIABLE out
|
||||||
|
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
if(res EQUAL 0)
|
||||||
|
set(${_var}
|
||||||
|
"CLEAN"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
else()
|
||||||
|
set(${_var}
|
||||||
|
"DIRTY"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
endif()
|
||||||
|
endfunction()
|
@ -0,0 +1,43 @@
|
|||||||
|
#
|
||||||
|
# Internal file for GetGitRevisionDescription.cmake
|
||||||
|
#
|
||||||
|
# Requires CMake 2.6 or newer (uses the 'function' command)
|
||||||
|
#
|
||||||
|
# Original Author:
|
||||||
|
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
|
||||||
|
# http://academic.cleardefinition.com
|
||||||
|
# Iowa State University HCI Graduate Program/VRAC
|
||||||
|
#
|
||||||
|
# Copyright 2009-2012, Iowa State University
|
||||||
|
# Copyright 2011-2015, Contributors
|
||||||
|
# Distributed under the Boost Software License, Version 1.0.
|
||||||
|
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||||
|
# http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
# SPDX-License-Identifier: BSL-1.0
|
||||||
|
|
||||||
|
set(HEAD_HASH)
|
||||||
|
|
||||||
|
file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024)
|
||||||
|
|
||||||
|
string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS)
|
||||||
|
if(HEAD_CONTENTS MATCHES "ref")
|
||||||
|
# named branch
|
||||||
|
string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}")
|
||||||
|
if(EXISTS "@GIT_DIR@/${HEAD_REF}")
|
||||||
|
configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
|
||||||
|
else()
|
||||||
|
configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY)
|
||||||
|
file(READ "@GIT_DATA@/packed-refs" PACKED_REFS)
|
||||||
|
if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}")
|
||||||
|
set(HEAD_HASH "${CMAKE_MATCH_1}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
# detached HEAD
|
||||||
|
configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT HEAD_HASH)
|
||||||
|
file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024)
|
||||||
|
string(STRIP "${HEAD_HASH}" HEAD_HASH)
|
||||||
|
endif()
|
26
cmake/cmake-modules/rpavlik/LICENSES/BSD-3-Clause.txt
Normal file
26
cmake/cmake-modules/rpavlik/LICENSES/BSD-3-Clause.txt
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
Copyright (c) <year> <owner>. All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the copyright holder nor the names of its contributors
|
||||||
|
may be used to endorse or promote products derived from this software without
|
||||||
|
specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
23
cmake/cmake-modules/rpavlik/LICENSES/BSL-1.0.txt
Normal file
23
cmake/cmake-modules/rpavlik/LICENSES/BSL-1.0.txt
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
Boost Software License - Version 1.0 - August 17th, 2003
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person or organization
|
||||||
|
obtaining a copy of the software and accompanying documentation covered by
|
||||||
|
this license (the "Software") to use, reproduce, display, distribute, execute,
|
||||||
|
and transmit the Software, and to prepare derivative works of the Software,
|
||||||
|
and to permit third-parties to whom the Software is furnished to do so, all
|
||||||
|
subject to the following:
|
||||||
|
|
||||||
|
The copyright notices in the Software and this entire statement, including
|
||||||
|
the above license grant, this restriction and the following disclaimer, must
|
||||||
|
be included in all copies of the Software, in whole or in part, and all derivative
|
||||||
|
works of the Software, unless such copies or derivative works are solely in
|
||||||
|
the form of machine-executable object code generated by a source language
|
||||||
|
processor.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES
|
||||||
|
OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
23
cmake/cmake-modules/rpavlik/LICENSE_1_0.txt
Normal file
23
cmake/cmake-modules/rpavlik/LICENSE_1_0.txt
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
Boost Software License - Version 1.0 - August 17th, 2003
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person or organization
|
||||||
|
obtaining a copy of the software and accompanying documentation covered by
|
||||||
|
this license (the "Software") to use, reproduce, display, distribute,
|
||||||
|
execute, and transmit the Software, and to prepare derivative works of the
|
||||||
|
Software, and to permit third-parties to whom the Software is furnished to
|
||||||
|
do so, all subject to the following:
|
||||||
|
|
||||||
|
The copyright notices in the Software and this entire statement, including
|
||||||
|
the above license grant, this restriction and the following disclaimer,
|
||||||
|
must be included in all copies of the Software, in whole or in part, and
|
||||||
|
all derivative works of the Software, unless such copies or derivative
|
||||||
|
works are solely in the form of machine-executable object code generated by
|
||||||
|
a source language processor.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||||
|
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||||
|
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||||
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
@ -20,7 +20,9 @@ LinuxLibgpioIF::~LinuxLibgpioIF() {
|
|||||||
ReturnValue_t LinuxLibgpioIF::addGpios(GpioCookie* gpioCookie) {
|
ReturnValue_t LinuxLibgpioIF::addGpios(GpioCookie* gpioCookie) {
|
||||||
ReturnValue_t result;
|
ReturnValue_t result;
|
||||||
if (gpioCookie == nullptr) {
|
if (gpioCookie == nullptr) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "LinuxLibgpioIF::addGpios: Invalid cookie" << std::endl;
|
sif::error << "LinuxLibgpioIF::addGpios: Invalid cookie" << std::endl;
|
||||||
|
#endif
|
||||||
return RETURN_FAILED;
|
return RETURN_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,8 +98,10 @@ ReturnValue_t LinuxLibgpioIF::configureGpioByLabel(gpioId_t gpioId,
|
|||||||
std::string& label = gpioByLabel.label;
|
std::string& label = gpioByLabel.label;
|
||||||
struct gpiod_chip* chip = gpiod_chip_open_by_label(label.c_str());
|
struct gpiod_chip* chip = gpiod_chip_open_by_label(label.c_str());
|
||||||
if (chip == nullptr) {
|
if (chip == nullptr) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "LinuxLibgpioIF::configureGpioByLabel: Failed to open gpio from gpio "
|
sif::warning << "LinuxLibgpioIF::configureGpioByLabel: Failed to open gpio from gpio "
|
||||||
<< "group with label " << label << ". Gpio ID: " << gpioId << std::endl;
|
<< "group with label " << label << ". Gpio ID: " << gpioId << std::endl;
|
||||||
|
#endif
|
||||||
return RETURN_FAILED;
|
return RETURN_FAILED;
|
||||||
}
|
}
|
||||||
std::string failOutput = "label: " + label;
|
std::string failOutput = "label: " + label;
|
||||||
@ -108,8 +112,10 @@ ReturnValue_t LinuxLibgpioIF::configureGpioByChip(gpioId_t gpioId, GpiodRegularB
|
|||||||
std::string& chipname = gpioByChip.chipname;
|
std::string& chipname = gpioByChip.chipname;
|
||||||
struct gpiod_chip* chip = gpiod_chip_open_by_name(chipname.c_str());
|
struct gpiod_chip* chip = gpiod_chip_open_by_name(chipname.c_str());
|
||||||
if (chip == nullptr) {
|
if (chip == nullptr) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "LinuxLibgpioIF::configureGpioByChip: Failed to open chip " << chipname
|
sif::warning << "LinuxLibgpioIF::configureGpioByChip: Failed to open chip " << chipname
|
||||||
<< ". Gpio ID: " << gpioId << std::endl;
|
<< ". Gpio ID: " << gpioId << std::endl;
|
||||||
|
#endif
|
||||||
return RETURN_FAILED;
|
return RETURN_FAILED;
|
||||||
}
|
}
|
||||||
std::string failOutput = "chipname: " + chipname;
|
std::string failOutput = "chipname: " + chipname;
|
||||||
@ -133,8 +139,10 @@ ReturnValue_t LinuxLibgpioIF::configureGpioByLineName(gpioId_t gpioId,
|
|||||||
|
|
||||||
struct gpiod_chip* chip = gpiod_chip_open_by_name(chipname);
|
struct gpiod_chip* chip = gpiod_chip_open_by_name(chipname);
|
||||||
if (chip == nullptr) {
|
if (chip == nullptr) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "LinuxLibgpioIF::configureGpioByLineName: Failed to open chip " << chipname
|
sif::warning << "LinuxLibgpioIF::configureGpioByLineName: Failed to open chip " << chipname
|
||||||
<< ". <Gpio ID: " << gpioId << std::endl;
|
<< ". <Gpio ID: " << gpioId << std::endl;
|
||||||
|
#endif
|
||||||
return RETURN_FAILED;
|
return RETURN_FAILED;
|
||||||
}
|
}
|
||||||
std::string failOutput = "line name: " + lineName;
|
std::string failOutput = "line name: " + lineName;
|
||||||
@ -153,10 +161,12 @@ ReturnValue_t LinuxLibgpioIF::configureRegularGpio(gpioId_t gpioId, struct gpiod
|
|||||||
lineNum = regularGpio.lineNum;
|
lineNum = regularGpio.lineNum;
|
||||||
lineHandle = gpiod_chip_get_line(chip, lineNum);
|
lineHandle = gpiod_chip_get_line(chip, lineNum);
|
||||||
if (!lineHandle) {
|
if (!lineHandle) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "LinuxLibgpioIF::configureRegularGpio: Failed to open line " << std::endl;
|
sif::warning << "LinuxLibgpioIF::configureRegularGpio: Failed to open line " << std::endl;
|
||||||
sif::warning << "GPIO ID: " << gpioId << ", line number: " << lineNum << ", " << failOutput
|
sif::warning << "GPIO ID: " << gpioId << ", line number: " << lineNum << ", " << failOutput
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
sif::warning << "Check if Linux GPIO configuration has changed. " << std::endl;
|
sif::warning << "Check if Linux GPIO configuration has changed. " << std::endl;
|
||||||
|
#endif
|
||||||
gpiod_chip_close(chip);
|
gpiod_chip_close(chip);
|
||||||
return RETURN_FAILED;
|
return RETURN_FAILED;
|
||||||
}
|
}
|
||||||
@ -175,7 +185,9 @@ ReturnValue_t LinuxLibgpioIF::configureRegularGpio(gpioId_t gpioId, struct gpiod
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "LinuxLibgpioIF::configureGpios: Invalid direction specified" << std::endl;
|
sif::error << "LinuxLibgpioIF::configureGpios: Invalid direction specified" << std::endl;
|
||||||
|
#endif
|
||||||
return GPIO_INVALID_INSTANCE;
|
return GPIO_INVALID_INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,7 +216,9 @@ ReturnValue_t LinuxLibgpioIF::configureRegularGpio(gpioId_t gpioId, struct gpiod
|
|||||||
ReturnValue_t LinuxLibgpioIF::pullHigh(gpioId_t gpioId) {
|
ReturnValue_t LinuxLibgpioIF::pullHigh(gpioId_t gpioId) {
|
||||||
gpioMapIter = gpioMap.find(gpioId);
|
gpioMapIter = gpioMap.find(gpioId);
|
||||||
if (gpioMapIter == gpioMap.end()) {
|
if (gpioMapIter == gpioMap.end()) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "LinuxLibgpioIF::pullHigh: Unknown GPIO ID " << gpioId << std::endl;
|
sif::warning << "LinuxLibgpioIF::pullHigh: Unknown GPIO ID " << gpioId << std::endl;
|
||||||
|
#endif
|
||||||
return UNKNOWN_GPIO_ID;
|
return UNKNOWN_GPIO_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,7 +210,7 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const
|
|||||||
#endif
|
#endif
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
ReturnValue_t result = gpioComIF->pullLow(gpioId);
|
result = gpioComIF->pullLow(gpioId);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
#if FSFW_VERBOSE_LEVEL >= 1
|
#if FSFW_VERBOSE_LEVEL >= 1
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
@ -314,7 +314,7 @@ void UartComIF::configureBaudrate(struct termios* options, UartCookie* uartCooki
|
|||||||
cfsetispeed(options, B4000000);
|
cfsetispeed(options, B4000000);
|
||||||
cfsetospeed(options, B4000000);
|
cfsetospeed(options, B4000000);
|
||||||
break;
|
break;
|
||||||
#endif // ! __APPLE__
|
#endif // ! __APPLE__
|
||||||
default:
|
default:
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "UartComIF::configureBaudrate: Baudrate not supported" << std::endl;
|
sif::warning << "UartComIF::configureBaudrate: Baudrate not supported" << std::endl;
|
||||||
|
@ -10,6 +10,10 @@
|
|||||||
#include "stm32h7xx_hal.h"
|
#include "stm32h7xx_hal.h"
|
||||||
#include "stm32h7xx_hal_spi.h"
|
#include "stm32h7xx_hal_spi.h"
|
||||||
|
|
||||||
|
#ifndef STM_USE_PERIPHERAL_TX_BUFFER_MPU_PROTECTION
|
||||||
|
#define STM_USE_PERIPHERAL_TX_BUFFER_MPU_PROTECTION 1
|
||||||
|
#endif
|
||||||
|
|
||||||
enum class TransferStates { IDLE, WAIT, SUCCESS, FAILURE };
|
enum class TransferStates { IDLE, WAIT, SUCCESS, FAILURE };
|
||||||
|
|
||||||
class GyroL3GD20H {
|
class GyroL3GD20H {
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
if [[ ! -f README.md ]]; then
|
|
||||||
cd ..
|
|
||||||
fi
|
|
||||||
|
|
||||||
find ./src -iname *.h -o -iname *.cpp -o -iname *.c | xargs clang-format --style=file -i
|
|
||||||
find ./hal -iname *.h -o -iname *.cpp -o -iname *.c | xargs clang-format --style=file -i
|
|
||||||
find ./tests -iname *.h -o -iname *.cpp -o -iname *.c | xargs clang-format --style=file -i
|
|
23
scripts/auto-formatter.sh
Executable file
23
scripts/auto-formatter.sh
Executable file
@ -0,0 +1,23 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
if [[ ! -f README.md ]]; then
|
||||||
|
cd ..
|
||||||
|
fi
|
||||||
|
|
||||||
|
cmake_fmt="cmake-format"
|
||||||
|
file_selectors="-iname CMakeLists.txt"
|
||||||
|
if command -v ${cmake_fmt} &> /dev/null; then
|
||||||
|
${cmake_fmt} -i CMakeLists.txt
|
||||||
|
find ./src ${file_selectors} | xargs ${cmake_fmt} -i
|
||||||
|
else
|
||||||
|
echo "No ${cmake_fmt} tool found, not formatting CMake files"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cpp_format="clang-format"
|
||||||
|
file_selectors="-iname *.h -o -iname *.cpp -o -iname *.c -o -iname *.tpp"
|
||||||
|
if command -v ${cpp_format} &> /dev/null; then
|
||||||
|
find ./src ${file_selectors} | xargs ${cpp_format} --style=file -i
|
||||||
|
find ./hal ${file_selectors} | xargs ${cpp_format} --style=file -i
|
||||||
|
find ./tests ${file_selectors} | xargs ${cpp_format} --style=file -i
|
||||||
|
else
|
||||||
|
echo "No ${cpp_format} tool found, not formatting C++/C files"
|
||||||
|
fi
|
@ -1,9 +1,6 @@
|
|||||||
target_include_directories(${LIB_FSFW_NAME} PRIVATE
|
target_include_directories(${LIB_FSFW_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}
|
|
||||||
)
|
|
||||||
|
|
||||||
target_include_directories(${LIB_FSFW_NAME} INTERFACE
|
target_include_directories(${LIB_FSFW_NAME}
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}
|
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
)
|
|
||||||
|
|
||||||
add_subdirectory(fsfw)
|
add_subdirectory(fsfw)
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
target_sources(${LIB_FSFW_NAME} PRIVATE version.cpp)
|
||||||
version.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
# Core
|
# Core
|
||||||
|
|
||||||
@ -37,22 +35,22 @@ add_subdirectory(tmtcservices)
|
|||||||
# Optional
|
# Optional
|
||||||
|
|
||||||
if(FSFW_ADD_MONITORING)
|
if(FSFW_ADD_MONITORING)
|
||||||
add_subdirectory(monitoring)
|
add_subdirectory(monitoring)
|
||||||
endif()
|
endif()
|
||||||
if(FSFW_ADD_PUS)
|
if(FSFW_ADD_PUS)
|
||||||
add_subdirectory(pus)
|
add_subdirectory(pus)
|
||||||
endif()
|
endif()
|
||||||
if(FSFW_ADD_TMSTORAGE)
|
if(FSFW_ADD_TMSTORAGE)
|
||||||
add_subdirectory(tmstorage)
|
add_subdirectory(tmstorage)
|
||||||
endif()
|
endif()
|
||||||
if(FSFW_ADD_COORDINATES)
|
if(FSFW_ADD_COORDINATES)
|
||||||
add_subdirectory(coordinates)
|
add_subdirectory(coordinates)
|
||||||
endif()
|
endif()
|
||||||
if(FSFW_ADD_RMAP)
|
if(FSFW_ADD_RMAP)
|
||||||
add_subdirectory(rmap)
|
add_subdirectory(rmap)
|
||||||
endif()
|
endif()
|
||||||
if(FSFW_ADD_DATALINKLAYER)
|
if(FSFW_ADD_DATALINKLAYER)
|
||||||
add_subdirectory(datalinklayer)
|
add_subdirectory(datalinklayer)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# OSAL
|
# OSAL
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
#ifndef FSFW_VERSION_H_
|
#ifndef FSFW_VERSION_H_
|
||||||
#define FSFW_VERSION_H_
|
#define FSFW_VERSION_H_
|
||||||
|
|
||||||
// Versioning is kept in project CMakeLists.txt file
|
// Versioning is managed in project CMakeLists.txt file
|
||||||
#define FSFW_VERSION_MAJOR @FSFW_VERSION@
|
static constexpr int FSFW_VERSION_MAJOR = @FSFW_VERSION@;
|
||||||
#define FSFW_VERSION_MINOR @FSFW_SUBVERSION@
|
static constexpr int FSFW_VERSION_MINOR = @FSFW_SUBVERSION@;
|
||||||
#define FSFW_VERSION_REVISION @FSFW_REVISION@
|
static constexpr int FSFW_VERSION_REVISION = @FSFW_REVISION@;
|
||||||
|
// Also contains CST (Commits since tag) information
|
||||||
|
static const char FSFW_VCS_INFO[] = "@FSFW_VCS_INFO@";
|
||||||
|
|
||||||
#endif /* FSFW_VERSION_H_ */
|
#endif /* FSFW_VERSION_H_ */
|
||||||
|
@ -1,7 +1,3 @@
|
|||||||
target_sources(${LIB_FSFW_NAME}
|
target_sources(
|
||||||
PRIVATE
|
${LIB_FSFW_NAME} PRIVATE ActionHelper.cpp ActionMessage.cpp
|
||||||
ActionHelper.cpp
|
CommandActionHelper.cpp SimpleActionHelper.cpp)
|
||||||
ActionMessage.cpp
|
|
||||||
CommandActionHelper.cpp
|
|
||||||
SimpleActionHelper.cpp
|
|
||||||
)
|
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
target_sources(${LIB_FSFW_NAME} PRIVATE CFDPHandler.cpp CFDPMessage.cpp)
|
||||||
CFDPHandler.cpp
|
|
||||||
CFDPMessage.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
add_subdirectory(pdu)
|
add_subdirectory(pdu)
|
||||||
add_subdirectory(tlv)
|
add_subdirectory(tlv)
|
||||||
|
@ -1,32 +1,30 @@
|
|||||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
target_sources(
|
||||||
PduConfig.cpp
|
${LIB_FSFW_NAME}
|
||||||
VarLenField.cpp
|
PRIVATE PduConfig.cpp
|
||||||
HeaderSerializer.cpp
|
VarLenField.cpp
|
||||||
HeaderDeserializer.cpp
|
HeaderSerializer.cpp
|
||||||
FileDirectiveDeserializer.cpp
|
HeaderDeserializer.cpp
|
||||||
FileDirectiveSerializer.cpp
|
FileDirectiveDeserializer.cpp
|
||||||
|
FileDirectiveSerializer.cpp
|
||||||
AckInfo.cpp
|
AckInfo.cpp
|
||||||
AckPduSerializer.cpp
|
AckPduSerializer.cpp
|
||||||
AckPduDeserializer.cpp
|
AckPduDeserializer.cpp
|
||||||
EofInfo.cpp
|
EofInfo.cpp
|
||||||
EofPduSerializer.cpp
|
EofPduSerializer.cpp
|
||||||
EofPduDeserializer.cpp
|
EofPduDeserializer.cpp
|
||||||
NakInfo.cpp
|
NakInfo.cpp
|
||||||
NakPduSerializer.cpp
|
NakPduSerializer.cpp
|
||||||
NakPduDeserializer.cpp
|
NakPduDeserializer.cpp
|
||||||
FinishedInfo.cpp
|
FinishedInfo.cpp
|
||||||
FinishedPduSerializer.cpp
|
FinishedPduSerializer.cpp
|
||||||
FinishedPduDeserializer.cpp
|
FinishedPduDeserializer.cpp
|
||||||
MetadataInfo.cpp
|
MetadataInfo.cpp
|
||||||
MetadataPduSerializer.cpp
|
MetadataPduSerializer.cpp
|
||||||
MetadataPduDeserializer.cpp
|
MetadataPduDeserializer.cpp
|
||||||
KeepAlivePduSerializer.cpp
|
KeepAlivePduSerializer.cpp
|
||||||
KeepAlivePduDeserializer.cpp
|
KeepAlivePduDeserializer.cpp
|
||||||
PromptPduSerializer.cpp
|
PromptPduSerializer.cpp
|
||||||
PromptPduDeserializer.cpp
|
PromptPduDeserializer.cpp
|
||||||
|
FileDataSerializer.cpp
|
||||||
FileDataSerializer.cpp
|
FileDataDeserializer.cpp
|
||||||
FileDataDeserializer.cpp
|
FileDataInfo.cpp)
|
||||||
FileDataInfo.cpp
|
|
||||||
)
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
target_sources(
|
||||||
EntityIdTlv.cpp
|
${LIB_FSFW_NAME}
|
||||||
FilestoreRequestTlv.cpp
|
PRIVATE EntityIdTlv.cpp
|
||||||
FilestoreResponseTlv.cpp
|
FilestoreRequestTlv.cpp
|
||||||
Lv.cpp
|
FilestoreResponseTlv.cpp
|
||||||
Tlv.cpp
|
Lv.cpp
|
||||||
FlowLabelTlv.cpp
|
Tlv.cpp
|
||||||
MessageToUserTlv.cpp
|
FlowLabelTlv.cpp
|
||||||
FaultHandlerOverrideTlv.cpp
|
MessageToUserTlv.cpp
|
||||||
)
|
FaultHandlerOverrideTlv.cpp)
|
||||||
|
@ -1,5 +1,2 @@
|
|||||||
target_sources(${LIB_FSFW_NAME}
|
target_sources(${LIB_FSFW_NAME} PRIVATE SharedRingBuffer.cpp
|
||||||
PRIVATE
|
SimpleRingBuffer.cpp)
|
||||||
SharedRingBuffer.cpp
|
|
||||||
SimpleRingBuffer.cpp
|
|
||||||
)
|
|
||||||
|
@ -5,89 +5,88 @@
|
|||||||
#error Include FIFOBase.h before FIFOBase.tpp!
|
#error Include FIFOBase.h before FIFOBase.tpp!
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline FIFOBase<T>::FIFOBase(T* values, const size_t maxCapacity):
|
inline FIFOBase<T>::FIFOBase(T* values, const size_t maxCapacity)
|
||||||
maxCapacity(maxCapacity), values(values){};
|
: maxCapacity(maxCapacity), values(values){};
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline ReturnValue_t FIFOBase<T>::insert(T value) {
|
inline ReturnValue_t FIFOBase<T>::insert(T value) {
|
||||||
if (full()) {
|
if (full()) {
|
||||||
return FULL;
|
return FULL;
|
||||||
} else {
|
} else {
|
||||||
values[writeIndex] = value;
|
values[writeIndex] = value;
|
||||||
writeIndex = next(writeIndex);
|
writeIndex = next(writeIndex);
|
||||||
++currentSize;
|
++currentSize;
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline ReturnValue_t FIFOBase<T>::retrieve(T* value) {
|
inline ReturnValue_t FIFOBase<T>::retrieve(T* value) {
|
||||||
if (empty()) {
|
if (empty()) {
|
||||||
return EMPTY;
|
return EMPTY;
|
||||||
} else {
|
} else {
|
||||||
if (value == nullptr){
|
if (value == nullptr) {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
|
||||||
*value = values[readIndex];
|
|
||||||
readIndex = next(readIndex);
|
|
||||||
--currentSize;
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
|
||||||
}
|
}
|
||||||
|
*value = values[readIndex];
|
||||||
|
readIndex = next(readIndex);
|
||||||
|
--currentSize;
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline ReturnValue_t FIFOBase<T>::peek(T* value) {
|
inline ReturnValue_t FIFOBase<T>::peek(T* value) {
|
||||||
if(empty()) {
|
if (empty()) {
|
||||||
return EMPTY;
|
return EMPTY;
|
||||||
} else {
|
} else {
|
||||||
if (value == nullptr){
|
if (value == nullptr) {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
|
||||||
*value = values[readIndex];
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
|
||||||
}
|
}
|
||||||
|
*value = values[readIndex];
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline ReturnValue_t FIFOBase<T>::pop() {
|
inline ReturnValue_t FIFOBase<T>::pop() {
|
||||||
T value;
|
T value;
|
||||||
return this->retrieve(&value);
|
return this->retrieve(&value);
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline bool FIFOBase<T>::empty() {
|
inline bool FIFOBase<T>::empty() {
|
||||||
return (currentSize == 0);
|
return (currentSize == 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline bool FIFOBase<T>::full() {
|
inline bool FIFOBase<T>::full() {
|
||||||
return (currentSize == maxCapacity);
|
return (currentSize == maxCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline size_t FIFOBase<T>::size() {
|
inline size_t FIFOBase<T>::size() {
|
||||||
return currentSize;
|
return currentSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline size_t FIFOBase<T>::next(size_t current) {
|
inline size_t FIFOBase<T>::next(size_t current) {
|
||||||
++current;
|
++current;
|
||||||
if (current == maxCapacity) {
|
if (current == maxCapacity) {
|
||||||
current = 0;
|
current = 0;
|
||||||
}
|
}
|
||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline size_t FIFOBase<T>::getMaxCapacity() const {
|
inline size_t FIFOBase<T>::getMaxCapacity() const {
|
||||||
return maxCapacity;
|
return maxCapacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
template<typename T>
|
inline void FIFOBase<T>::setContainer(T* data) {
|
||||||
inline void FIFOBase<T>::setContainer(T *data) {
|
this->values = data;
|
||||||
this->values = data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -12,6 +12,7 @@ template <typename T, size_t MAX_SIZE, typename count_t = uint8_t>
|
|||||||
class FixedArrayList : public ArrayList<T, count_t> {
|
class FixedArrayList : public ArrayList<T, count_t> {
|
||||||
static_assert(MAX_SIZE <= std::numeric_limits<count_t>::max(),
|
static_assert(MAX_SIZE <= std::numeric_limits<count_t>::max(),
|
||||||
"count_t is not large enough to hold MAX_SIZE");
|
"count_t is not large enough to hold MAX_SIZE");
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T data[MAX_SIZE];
|
T data[MAX_SIZE];
|
||||||
|
|
||||||
|
@ -1,109 +1,109 @@
|
|||||||
#ifndef FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_
|
#ifndef FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_
|
||||||
#define FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_
|
#define FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_
|
||||||
|
|
||||||
|
template <typename key_t, typename T, typename KEY_COMPARE>
|
||||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::insert(key_t key, T value,
|
||||||
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::insert(key_t key, T value, Iterator *storedValue) {
|
Iterator *storedValue) {
|
||||||
if (_size == theMap.maxSize()) {
|
if (_size == theMap.maxSize()) {
|
||||||
return MAP_FULL;
|
return MAP_FULL;
|
||||||
}
|
}
|
||||||
size_t position = findNicePlace(key);
|
size_t position = findNicePlace(key);
|
||||||
memmove(static_cast<void*>(&theMap[position + 1]),static_cast<void*>(&theMap[position]),
|
memmove(static_cast<void *>(&theMap[position + 1]), static_cast<void *>(&theMap[position]),
|
||||||
(_size - position) * sizeof(std::pair<key_t,T>));
|
(_size - position) * sizeof(std::pair<key_t, T>));
|
||||||
theMap[position].first = key;
|
theMap[position].first = key;
|
||||||
theMap[position].second = value;
|
theMap[position].second = value;
|
||||||
++_size;
|
++_size;
|
||||||
if (storedValue != nullptr) {
|
if (storedValue != nullptr) {
|
||||||
*storedValue = Iterator(&theMap[position]);
|
*storedValue = Iterator(&theMap[position]);
|
||||||
}
|
}
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
template <typename key_t, typename T, typename KEY_COMPARE>
|
||||||
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::insert(std::pair<key_t, T> pair) {
|
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::insert(std::pair<key_t, T> pair) {
|
||||||
return insert(pair.first, pair.second);
|
return insert(pair.first, pair.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
template <typename key_t, typename T, typename KEY_COMPARE>
|
||||||
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::exists(key_t key) const {
|
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::exists(key_t key) const {
|
||||||
ReturnValue_t result = KEY_DOES_NOT_EXIST;
|
ReturnValue_t result = KEY_DOES_NOT_EXIST;
|
||||||
if (findFirstIndex(key) < _size) {
|
if (findFirstIndex(key) < _size) {
|
||||||
result = HasReturnvaluesIF::RETURN_OK;
|
result = HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
template <typename key_t, typename T, typename KEY_COMPARE>
|
||||||
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::erase(Iterator *iter) {
|
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::erase(Iterator *iter) {
|
||||||
size_t i;
|
size_t i;
|
||||||
if ((i = findFirstIndex((*iter).value->first)) >= _size) {
|
if ((i = findFirstIndex((*iter).value->first)) >= _size) {
|
||||||
return KEY_DOES_NOT_EXIST;
|
return KEY_DOES_NOT_EXIST;
|
||||||
}
|
}
|
||||||
removeFromPosition(i);
|
removeFromPosition(i);
|
||||||
if (*iter != begin()) {
|
if (*iter != begin()) {
|
||||||
(*iter)--;
|
(*iter)--;
|
||||||
} else {
|
} else {
|
||||||
*iter = begin();
|
*iter = begin();
|
||||||
}
|
}
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
template <typename key_t, typename T, typename KEY_COMPARE>
|
||||||
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::erase(key_t key) {
|
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::erase(key_t key) {
|
||||||
size_t i;
|
size_t i;
|
||||||
if ((i = findFirstIndex(key)) >= _size) {
|
if ((i = findFirstIndex(key)) >= _size) {
|
||||||
return KEY_DOES_NOT_EXIST;
|
return KEY_DOES_NOT_EXIST;
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
removeFromPosition(i);
|
removeFromPosition(i);
|
||||||
i = findFirstIndex(key, i);
|
i = findFirstIndex(key, i);
|
||||||
} while (i < _size);
|
} while (i < _size);
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
template <typename key_t, typename T, typename KEY_COMPARE>
|
||||||
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::find(key_t key, T **value) const {
|
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::find(key_t key, T **value) const {
|
||||||
ReturnValue_t result = exists(key);
|
ReturnValue_t result = exists(key);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
*value = &theMap[findFirstIndex(key)].second;
|
*value = &theMap[findFirstIndex(key)].second;
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
template <typename key_t, typename T, typename KEY_COMPARE>
|
||||||
inline size_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::findFirstIndex(key_t key, size_t startAt) const {
|
inline size_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::findFirstIndex(key_t key,
|
||||||
if (startAt >= _size) {
|
size_t startAt) const {
|
||||||
return startAt + 1;
|
if (startAt >= _size) {
|
||||||
|
return startAt + 1;
|
||||||
|
}
|
||||||
|
size_t i = startAt;
|
||||||
|
for (i = startAt; i < _size; ++i) {
|
||||||
|
if (theMap[i].first == key) {
|
||||||
|
return i;
|
||||||
}
|
}
|
||||||
size_t i = startAt;
|
}
|
||||||
for (i = startAt; i < _size; ++i) {
|
return i;
|
||||||
if (theMap[i].first == key) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
template <typename key_t, typename T, typename KEY_COMPARE>
|
||||||
inline size_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::findNicePlace(key_t key) const {
|
inline size_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::findNicePlace(key_t key) const {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
for (i = 0; i < _size; ++i) {
|
for (i = 0; i < _size; ++i) {
|
||||||
if (myComp(key, theMap[i].first)) {
|
if (myComp(key, theMap[i].first)) {
|
||||||
return i;
|
return i;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return i;
|
}
|
||||||
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
template <typename key_t, typename T, typename KEY_COMPARE>
|
||||||
inline void FixedOrderedMultimap<key_t, T, KEY_COMPARE>::removeFromPosition(size_t position) {
|
inline void FixedOrderedMultimap<key_t, T, KEY_COMPARE>::removeFromPosition(size_t position) {
|
||||||
if (_size <= position) {
|
if (_size <= position) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
memmove(static_cast<void*>(&theMap[position]), static_cast<void*>(&theMap[position + 1]),
|
memmove(static_cast<void *>(&theMap[position]), static_cast<void *>(&theMap[position + 1]),
|
||||||
(_size - position - 1) * sizeof(std::pair<key_t,T>));
|
(_size - position - 1) * sizeof(std::pair<key_t, T>));
|
||||||
--_size;
|
--_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif /* FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_ */
|
#endif /* FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_ */
|
||||||
|
@ -1,4 +1,2 @@
|
|||||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
target_sources(${LIB_FSFW_NAME} PRIVATE ControllerBase.cpp
|
||||||
ControllerBase.cpp
|
ExtendedControllerBase.cpp)
|
||||||
ExtendedControllerBase.cpp
|
|
||||||
)
|
|
||||||
|
@ -1,5 +1,2 @@
|
|||||||
target_sources(${LIB_FSFW_NAME}
|
target_sources(${LIB_FSFW_NAME} PRIVATE CoordinateTransformations.cpp
|
||||||
PRIVATE
|
Sgp4Propagator.cpp)
|
||||||
CoordinateTransformations.cpp
|
|
||||||
Sgp4Propagator.cpp
|
|
||||||
)
|
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
target_sources(${LIB_FSFW_NAME}
|
target_sources(
|
||||||
PRIVATE
|
${LIB_FSFW_NAME}
|
||||||
Clcw.cpp
|
PRIVATE Clcw.cpp
|
||||||
DataLinkLayer.cpp
|
DataLinkLayer.cpp
|
||||||
Farm1StateLockout.cpp
|
Farm1StateLockout.cpp
|
||||||
Farm1StateOpen.cpp
|
Farm1StateOpen.cpp
|
||||||
Farm1StateWait.cpp
|
Farm1StateWait.cpp
|
||||||
MapPacketExtraction.cpp
|
MapPacketExtraction.cpp
|
||||||
TcTransferFrame.cpp
|
TcTransferFrame.cpp
|
||||||
TcTransferFrameLocal.cpp
|
TcTransferFrameLocal.cpp
|
||||||
VirtualChannelReception.cpp
|
VirtualChannelReception.cpp)
|
||||||
)
|
|
||||||
|
@ -1,4 +1 @@
|
|||||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
target_sources(${LIB_FSFW_NAME} PRIVATE PoolDataSetBase.cpp PoolEntry.cpp)
|
||||||
PoolDataSetBase.cpp
|
|
||||||
PoolEntry.cpp
|
|
||||||
)
|
|
||||||
|
@ -1,10 +1,6 @@
|
|||||||
target_sources(${LIB_FSFW_NAME}
|
target_sources(
|
||||||
PRIVATE
|
${LIB_FSFW_NAME}
|
||||||
LocalDataPoolManager.cpp
|
PRIVATE LocalDataPoolManager.cpp LocalDataSet.cpp LocalPoolDataSetBase.cpp
|
||||||
LocalDataSet.cpp
|
LocalPoolObjectBase.cpp SharedLocalDataSet.cpp)
|
||||||
LocalPoolDataSetBase.cpp
|
|
||||||
LocalPoolObjectBase.cpp
|
|
||||||
SharedLocalDataSet.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
add_subdirectory(internal)
|
add_subdirectory(internal)
|
||||||
|
@ -696,9 +696,9 @@ void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver& receiver) {
|
|||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
/* Configuration error */
|
/* Configuration error */
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "LocalDataPoolManager::performHkOperation: HK generation failed." << std::endl;
|
sif::warning << "LocalDataPoolManager::performPeriodicHkOperation: HK generation failed." << std::endl;
|
||||||
#else
|
#else
|
||||||
sif::printWarning("LocalDataPoolManager::performHkOperation: HK generation failed.\n");
|
sif::printWarning("LocalDataPoolManager::performPeriodicHkOperation: HK generation failed.\n");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,205 +5,189 @@
|
|||||||
#error Include LocalPoolVariable.h before LocalPoolVariable.tpp!
|
#error Include LocalPoolVariable.h before LocalPoolVariable.tpp!
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline LocalPoolVariable<T>::LocalPoolVariable(HasLocalDataPoolIF* hkOwner,
|
inline LocalPoolVariable<T>::LocalPoolVariable(HasLocalDataPoolIF* hkOwner, lp_id_t poolId,
|
||||||
lp_id_t poolId, DataSetIF* dataSet, pool_rwm_t setReadWriteMode):
|
DataSetIF* dataSet, pool_rwm_t setReadWriteMode)
|
||||||
LocalPoolObjectBase(poolId, hkOwner, dataSet, setReadWriteMode) {}
|
: LocalPoolObjectBase(poolId, hkOwner, dataSet, setReadWriteMode) {}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline LocalPoolVariable<T>::LocalPoolVariable(object_id_t poolOwner,
|
inline LocalPoolVariable<T>::LocalPoolVariable(object_id_t poolOwner, lp_id_t poolId,
|
||||||
lp_id_t poolId, DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
|
DataSetIF* dataSet, pool_rwm_t setReadWriteMode)
|
||||||
LocalPoolObjectBase(poolOwner, poolId, dataSet, setReadWriteMode) {}
|
: LocalPoolObjectBase(poolOwner, poolId, dataSet, setReadWriteMode) {}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline LocalPoolVariable<T>::LocalPoolVariable(gp_id_t globalPoolId, DataSetIF* dataSet,
|
||||||
|
pool_rwm_t setReadWriteMode)
|
||||||
|
: LocalPoolObjectBase(globalPoolId.objectId, globalPoolId.localPoolId, dataSet,
|
||||||
|
setReadWriteMode) {}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline LocalPoolVariable<T>::LocalPoolVariable(gp_id_t globalPoolId,
|
inline ReturnValue_t LocalPoolVariable<T>::read(MutexIF::TimeoutType timeoutType,
|
||||||
DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
|
uint32_t timeoutMs) {
|
||||||
LocalPoolObjectBase(globalPoolId.objectId, globalPoolId.localPoolId,
|
if (hkManager == nullptr) {
|
||||||
dataSet, setReadWriteMode){}
|
return readWithoutLock();
|
||||||
|
}
|
||||||
|
MutexIF* mutex = LocalDpManagerAttorney::getMutexHandle(*hkManager);
|
||||||
template<typename T>
|
ReturnValue_t result = mutex->lockMutex(timeoutType, timeoutMs);
|
||||||
inline ReturnValue_t LocalPoolVariable<T>::read(
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
|
|
||||||
if(hkManager == nullptr) {
|
|
||||||
return readWithoutLock();
|
|
||||||
}
|
|
||||||
MutexIF* mutex = LocalDpManagerAttorney::getMutexHandle(*hkManager);
|
|
||||||
ReturnValue_t result = mutex->lockMutex(timeoutType, timeoutMs);
|
|
||||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result = readWithoutLock();
|
|
||||||
mutex->unlockMutex();
|
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
result = readWithoutLock();
|
||||||
|
mutex->unlockMutex();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline ReturnValue_t LocalPoolVariable<T>::readWithoutLock() {
|
inline ReturnValue_t LocalPoolVariable<T>::readWithoutLock() {
|
||||||
if(readWriteMode == pool_rwm_t::VAR_WRITE) {
|
if (readWriteMode == pool_rwm_t::VAR_WRITE) {
|
||||||
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
||||||
reportReadCommitError("LocalPoolVector",
|
reportReadCommitError("LocalPoolVector", PoolVariableIF::INVALID_READ_WRITE_MODE, true,
|
||||||
PoolVariableIF::INVALID_READ_WRITE_MODE, true, targetObjectId,
|
targetObjectId, localPoolId);
|
||||||
localPoolId);
|
return PoolVariableIF::INVALID_READ_WRITE_MODE;
|
||||||
return PoolVariableIF::INVALID_READ_WRITE_MODE;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
PoolEntry<T>* poolEntry = nullptr;
|
PoolEntry<T>* poolEntry = nullptr;
|
||||||
ReturnValue_t result = LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId,
|
ReturnValue_t result =
|
||||||
&poolEntry);
|
LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId, &poolEntry);
|
||||||
if(result != RETURN_OK) {
|
if (result != RETURN_OK) {
|
||||||
object_id_t ownerObjectId = hkManager->getCreatorObjectId();
|
object_id_t ownerObjectId = hkManager->getCreatorObjectId();
|
||||||
reportReadCommitError("LocalPoolVariable", result,
|
reportReadCommitError("LocalPoolVariable", result, false, ownerObjectId, localPoolId);
|
||||||
false, ownerObjectId, localPoolId);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->value = *(poolEntry->getDataPtr());
|
|
||||||
this->valid = poolEntry->getValid();
|
|
||||||
return RETURN_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline ReturnValue_t LocalPoolVariable<T>::commit(bool setValid,
|
|
||||||
MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
|
|
||||||
this->setValid(setValid);
|
|
||||||
return commit(timeoutType, timeoutMs);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline ReturnValue_t LocalPoolVariable<T>::commit(
|
|
||||||
MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
|
|
||||||
if(hkManager == nullptr) {
|
|
||||||
return commitWithoutLock();
|
|
||||||
}
|
|
||||||
MutexIF* mutex = LocalDpManagerAttorney::getMutexHandle(*hkManager);
|
|
||||||
ReturnValue_t result = mutex->lockMutex(timeoutType, timeoutMs);
|
|
||||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result = commitWithoutLock();
|
|
||||||
mutex->unlockMutex();
|
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->value = *(poolEntry->getDataPtr());
|
||||||
|
this->valid = poolEntry->getValid();
|
||||||
|
return RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
|
inline ReturnValue_t LocalPoolVariable<T>::commit(bool setValid, MutexIF::TimeoutType timeoutType,
|
||||||
|
uint32_t timeoutMs) {
|
||||||
|
this->setValid(setValid);
|
||||||
|
return commit(timeoutType, timeoutMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline ReturnValue_t LocalPoolVariable<T>::commit(MutexIF::TimeoutType timeoutType,
|
||||||
|
uint32_t timeoutMs) {
|
||||||
|
if (hkManager == nullptr) {
|
||||||
|
return commitWithoutLock();
|
||||||
|
}
|
||||||
|
MutexIF* mutex = LocalDpManagerAttorney::getMutexHandle(*hkManager);
|
||||||
|
ReturnValue_t result = mutex->lockMutex(timeoutType, timeoutMs);
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
result = commitWithoutLock();
|
||||||
|
mutex->unlockMutex();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
inline ReturnValue_t LocalPoolVariable<T>::commitWithoutLock() {
|
inline ReturnValue_t LocalPoolVariable<T>::commitWithoutLock() {
|
||||||
if(readWriteMode == pool_rwm_t::VAR_READ) {
|
if (readWriteMode == pool_rwm_t::VAR_READ) {
|
||||||
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
||||||
reportReadCommitError("LocalPoolVector",
|
reportReadCommitError("LocalPoolVector", PoolVariableIF::INVALID_READ_WRITE_MODE, false,
|
||||||
PoolVariableIF::INVALID_READ_WRITE_MODE, false, targetObjectId,
|
targetObjectId, localPoolId);
|
||||||
localPoolId);
|
return PoolVariableIF::INVALID_READ_WRITE_MODE;
|
||||||
return PoolVariableIF::INVALID_READ_WRITE_MODE;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
PoolEntry<T>* poolEntry = nullptr;
|
PoolEntry<T>* poolEntry = nullptr;
|
||||||
ReturnValue_t result = LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId,
|
ReturnValue_t result =
|
||||||
&poolEntry);
|
LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId, &poolEntry);
|
||||||
if(result != RETURN_OK) {
|
if (result != RETURN_OK) {
|
||||||
object_id_t ownerObjectId = hkManager->getCreatorObjectId();
|
object_id_t ownerObjectId = hkManager->getCreatorObjectId();
|
||||||
reportReadCommitError("LocalPoolVariable", result,
|
reportReadCommitError("LocalPoolVariable", result, false, ownerObjectId, localPoolId);
|
||||||
false, ownerObjectId, localPoolId);
|
return result;
|
||||||
return result;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
*(poolEntry->getDataPtr()) = this->value;
|
*(poolEntry->getDataPtr()) = this->value;
|
||||||
poolEntry->setValid(this->valid);
|
poolEntry->setValid(this->valid);
|
||||||
return RETURN_OK;
|
return RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline ReturnValue_t LocalPoolVariable<T>::serialize(uint8_t** buffer,
|
inline ReturnValue_t LocalPoolVariable<T>::serialize(
|
||||||
size_t* size, const size_t max_size,
|
uint8_t** buffer, size_t* size, const size_t max_size,
|
||||||
SerializeIF::Endianness streamEndianness) const {
|
SerializeIF::Endianness streamEndianness) const {
|
||||||
return SerializeAdapter::serialize(&value,
|
return SerializeAdapter::serialize(&value, buffer, size, max_size, streamEndianness);
|
||||||
buffer, size ,max_size, streamEndianness);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline size_t LocalPoolVariable<T>::getSerializedSize() const {
|
inline size_t LocalPoolVariable<T>::getSerializedSize() const {
|
||||||
return SerializeAdapter::getSerializedSize(&value);
|
return SerializeAdapter::getSerializedSize(&value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline ReturnValue_t LocalPoolVariable<T>::deSerialize(const uint8_t** buffer,
|
inline ReturnValue_t LocalPoolVariable<T>::deSerialize(const uint8_t** buffer, size_t* size,
|
||||||
size_t* size, SerializeIF::Endianness streamEndianness) {
|
SerializeIF::Endianness streamEndianness) {
|
||||||
return SerializeAdapter::deSerialize(&value, buffer, size, streamEndianness);
|
return SerializeAdapter::deSerialize(&value, buffer, size, streamEndianness);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline std::ostream& operator<< (std::ostream &out,
|
inline std::ostream& operator<<(std::ostream& out, const LocalPoolVariable<T>& var) {
|
||||||
const LocalPoolVariable<T> &var) {
|
out << var.value;
|
||||||
out << var.value;
|
return out;
|
||||||
return out;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline LocalPoolVariable<T>::operator T() const {
|
inline LocalPoolVariable<T>::operator T() const {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline LocalPoolVariable<T> & LocalPoolVariable<T>::operator=(
|
inline LocalPoolVariable<T>& LocalPoolVariable<T>::operator=(const T& newValue) {
|
||||||
const T& newValue) {
|
value = newValue;
|
||||||
value = newValue;
|
return *this;
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline LocalPoolVariable<T>& LocalPoolVariable<T>::operator =(
|
inline LocalPoolVariable<T>& LocalPoolVariable<T>::operator=(
|
||||||
const LocalPoolVariable<T>& newPoolVariable) {
|
const LocalPoolVariable<T>& newPoolVariable) {
|
||||||
value = newPoolVariable.value;
|
value = newPoolVariable.value;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline bool LocalPoolVariable<T>::operator ==(
|
inline bool LocalPoolVariable<T>::operator==(const LocalPoolVariable<T>& other) const {
|
||||||
const LocalPoolVariable<T> &other) const {
|
return this->value == other.value;
|
||||||
return this->value == other.value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline bool LocalPoolVariable<T>::operator ==(const T &other) const {
|
inline bool LocalPoolVariable<T>::operator==(const T& other) const {
|
||||||
return this->value == other;
|
return this->value == other;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
template<typename T>
|
inline bool LocalPoolVariable<T>::operator!=(const LocalPoolVariable<T>& other) const {
|
||||||
inline bool LocalPoolVariable<T>::operator !=(
|
return not(*this == other);
|
||||||
const LocalPoolVariable<T> &other) const {
|
|
||||||
return not (*this == other);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline bool LocalPoolVariable<T>::operator !=(const T &other) const {
|
inline bool LocalPoolVariable<T>::operator!=(const T& other) const {
|
||||||
return not (*this == other);
|
return not(*this == other);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
template<typename T>
|
inline bool LocalPoolVariable<T>::operator<(const LocalPoolVariable<T>& other) const {
|
||||||
inline bool LocalPoolVariable<T>::operator <(
|
return this->value < other.value;
|
||||||
const LocalPoolVariable<T> &other) const {
|
|
||||||
return this->value < other.value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline bool LocalPoolVariable<T>::operator <(const T &other) const {
|
inline bool LocalPoolVariable<T>::operator<(const T& other) const {
|
||||||
return this->value < other;
|
return this->value < other;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
template<typename T>
|
inline bool LocalPoolVariable<T>::operator>(const LocalPoolVariable<T>& other) const {
|
||||||
inline bool LocalPoolVariable<T>::operator >(
|
return not(*this < other);
|
||||||
const LocalPoolVariable<T> &other) const {
|
|
||||||
return not (*this < other);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline bool LocalPoolVariable<T>::operator >(const T &other) const {
|
inline bool LocalPoolVariable<T>::operator>(const T& other) const {
|
||||||
return not (*this < other);
|
return not(*this < other);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* FSFW_DATAPOOLLOCAL_LOCALPOOLVARIABLE_TPP_ */
|
#endif /* FSFW_DATAPOOLLOCAL_LOCALPOOLVARIABLE_TPP_ */
|
||||||
|
@ -5,174 +5,172 @@
|
|||||||
#error Include LocalPoolVector.h before LocalPoolVector.tpp!
|
#error Include LocalPoolVector.h before LocalPoolVector.tpp!
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template<typename T, uint16_t vectorSize>
|
template <typename T, uint16_t vectorSize>
|
||||||
inline LocalPoolVector<T, vectorSize>::LocalPoolVector(
|
inline LocalPoolVector<T, vectorSize>::LocalPoolVector(HasLocalDataPoolIF* hkOwner, lp_id_t poolId,
|
||||||
HasLocalDataPoolIF* hkOwner, lp_id_t poolId, DataSetIF* dataSet,
|
DataSetIF* dataSet,
|
||||||
pool_rwm_t setReadWriteMode):
|
pool_rwm_t setReadWriteMode)
|
||||||
LocalPoolObjectBase(poolId, hkOwner, dataSet, setReadWriteMode) {}
|
: LocalPoolObjectBase(poolId, hkOwner, dataSet, setReadWriteMode) {}
|
||||||
|
|
||||||
template<typename T, uint16_t vectorSize>
|
template <typename T, uint16_t vectorSize>
|
||||||
inline LocalPoolVector<T, vectorSize>::LocalPoolVector(object_id_t poolOwner,
|
inline LocalPoolVector<T, vectorSize>::LocalPoolVector(object_id_t poolOwner, lp_id_t poolId,
|
||||||
lp_id_t poolId, DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
|
DataSetIF* dataSet,
|
||||||
LocalPoolObjectBase(poolOwner, poolId, dataSet, setReadWriteMode) {}
|
pool_rwm_t setReadWriteMode)
|
||||||
|
: LocalPoolObjectBase(poolOwner, poolId, dataSet, setReadWriteMode) {}
|
||||||
|
|
||||||
template<typename T, uint16_t vectorSize>
|
template <typename T, uint16_t vectorSize>
|
||||||
inline LocalPoolVector<T, vectorSize>::LocalPoolVector(gp_id_t globalPoolId,
|
inline LocalPoolVector<T, vectorSize>::LocalPoolVector(gp_id_t globalPoolId, DataSetIF* dataSet,
|
||||||
DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
|
pool_rwm_t setReadWriteMode)
|
||||||
LocalPoolObjectBase(globalPoolId.objectId, globalPoolId.localPoolId,
|
: LocalPoolObjectBase(globalPoolId.objectId, globalPoolId.localPoolId, dataSet,
|
||||||
dataSet, setReadWriteMode) {}
|
setReadWriteMode) {}
|
||||||
|
|
||||||
template<typename T, uint16_t vectorSize>
|
template <typename T, uint16_t vectorSize>
|
||||||
inline ReturnValue_t LocalPoolVector<T, vectorSize>::read(
|
inline ReturnValue_t LocalPoolVector<T, vectorSize>::read(MutexIF::TimeoutType timeoutType,
|
||||||
MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
|
uint32_t timeoutMs) {
|
||||||
MutexGuard(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs);
|
MutexGuard(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs);
|
||||||
return readWithoutLock();
|
return readWithoutLock();
|
||||||
}
|
}
|
||||||
template<typename T, uint16_t vectorSize>
|
template <typename T, uint16_t vectorSize>
|
||||||
inline ReturnValue_t LocalPoolVector<T, vectorSize>::readWithoutLock() {
|
inline ReturnValue_t LocalPoolVector<T, vectorSize>::readWithoutLock() {
|
||||||
if(readWriteMode == pool_rwm_t::VAR_WRITE) {
|
if (readWriteMode == pool_rwm_t::VAR_WRITE) {
|
||||||
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
||||||
reportReadCommitError("LocalPoolVector",
|
reportReadCommitError("LocalPoolVector", PoolVariableIF::INVALID_READ_WRITE_MODE, true,
|
||||||
PoolVariableIF::INVALID_READ_WRITE_MODE, true, targetObjectId,
|
targetObjectId, localPoolId);
|
||||||
localPoolId);
|
return PoolVariableIF::INVALID_READ_WRITE_MODE;
|
||||||
return PoolVariableIF::INVALID_READ_WRITE_MODE;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
PoolEntry<T>* poolEntry = nullptr;
|
PoolEntry<T>* poolEntry = nullptr;
|
||||||
ReturnValue_t result = LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId,
|
ReturnValue_t result =
|
||||||
&poolEntry);
|
LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId, &poolEntry);
|
||||||
memset(this->value, 0, vectorSize * sizeof(T));
|
memset(this->value, 0, vectorSize * sizeof(T));
|
||||||
|
|
||||||
if(result != RETURN_OK) {
|
if (result != RETURN_OK) {
|
||||||
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
||||||
reportReadCommitError("LocalPoolVector", result, true, targetObjectId,
|
reportReadCommitError("LocalPoolVector", result, true, targetObjectId, localPoolId);
|
||||||
localPoolId);
|
return result;
|
||||||
return result;
|
}
|
||||||
}
|
std::memcpy(this->value, poolEntry->getDataPtr(), poolEntry->getByteSize());
|
||||||
std::memcpy(this->value, poolEntry->getDataPtr(), poolEntry->getByteSize());
|
this->valid = poolEntry->getValid();
|
||||||
this->valid = poolEntry->getValid();
|
return RETURN_OK;
|
||||||
return RETURN_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, uint16_t vectorSize>
|
template <typename T, uint16_t vectorSize>
|
||||||
inline ReturnValue_t LocalPoolVector<T, vectorSize>::commit(bool valid,
|
inline ReturnValue_t LocalPoolVector<T, vectorSize>::commit(bool valid,
|
||||||
MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
|
MutexIF::TimeoutType timeoutType,
|
||||||
this->setValid(valid);
|
uint32_t timeoutMs) {
|
||||||
return commit(timeoutType, timeoutMs);
|
this->setValid(valid);
|
||||||
|
return commit(timeoutType, timeoutMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, uint16_t vectorSize>
|
template <typename T, uint16_t vectorSize>
|
||||||
inline ReturnValue_t LocalPoolVector<T, vectorSize>::commit(
|
inline ReturnValue_t LocalPoolVector<T, vectorSize>::commit(MutexIF::TimeoutType timeoutType,
|
||||||
MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
|
uint32_t timeoutMs) {
|
||||||
MutexGuard(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs);
|
MutexGuard(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs);
|
||||||
return commitWithoutLock();
|
return commitWithoutLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, uint16_t vectorSize>
|
template <typename T, uint16_t vectorSize>
|
||||||
inline ReturnValue_t LocalPoolVector<T, vectorSize>::commitWithoutLock() {
|
inline ReturnValue_t LocalPoolVector<T, vectorSize>::commitWithoutLock() {
|
||||||
if(readWriteMode == pool_rwm_t::VAR_READ) {
|
if (readWriteMode == pool_rwm_t::VAR_READ) {
|
||||||
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
||||||
reportReadCommitError("LocalPoolVector",
|
reportReadCommitError("LocalPoolVector", PoolVariableIF::INVALID_READ_WRITE_MODE, false,
|
||||||
PoolVariableIF::INVALID_READ_WRITE_MODE, false, targetObjectId,
|
targetObjectId, localPoolId);
|
||||||
localPoolId);
|
return PoolVariableIF::INVALID_READ_WRITE_MODE;
|
||||||
return PoolVariableIF::INVALID_READ_WRITE_MODE;
|
}
|
||||||
}
|
PoolEntry<T>* poolEntry = nullptr;
|
||||||
PoolEntry<T>* poolEntry = nullptr;
|
ReturnValue_t result =
|
||||||
ReturnValue_t result = LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId,
|
LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId, &poolEntry);
|
||||||
&poolEntry);
|
if (result != RETURN_OK) {
|
||||||
if(result != RETURN_OK) {
|
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
||||||
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
reportReadCommitError("LocalPoolVector", result, false, targetObjectId, localPoolId);
|
||||||
reportReadCommitError("LocalPoolVector", result, false, targetObjectId,
|
|
||||||
localPoolId);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
std::memcpy(poolEntry->getDataPtr(), this->value, poolEntry->getByteSize());
|
|
||||||
poolEntry->setValid(this->valid);
|
|
||||||
return RETURN_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, uint16_t vectorSize>
|
|
||||||
inline T& LocalPoolVector<T, vectorSize>::operator [](size_t i) {
|
|
||||||
if(i < vectorSize) {
|
|
||||||
return value[i];
|
|
||||||
}
|
|
||||||
// If this happens, I have to set some value. I consider this
|
|
||||||
// a configuration error, but I wont exit here.
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::warning << "LocalPoolVector: Invalid index. Setting or returning"
|
|
||||||
" last value!" << std::endl;
|
|
||||||
#else
|
|
||||||
sif::printWarning("LocalPoolVector: Invalid index. Setting or returning"
|
|
||||||
" last value!\n");
|
|
||||||
#endif
|
|
||||||
return value[vectorSize - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, uint16_t vectorSize>
|
|
||||||
inline const T& LocalPoolVector<T, vectorSize>::operator [](size_t i) const {
|
|
||||||
if(i < vectorSize) {
|
|
||||||
return value[i];
|
|
||||||
}
|
|
||||||
// If this happens, I have to set some value. I consider this
|
|
||||||
// a configuration error, but I wont exit here.
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::warning << "LocalPoolVector: Invalid index. Setting or returning"
|
|
||||||
" last value!" << std::endl;
|
|
||||||
#else
|
|
||||||
sif::printWarning("LocalPoolVector: Invalid index. Setting or returning"
|
|
||||||
" last value!\n");
|
|
||||||
#endif
|
|
||||||
return value[vectorSize - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, uint16_t vectorSize>
|
|
||||||
inline ReturnValue_t LocalPoolVector<T, vectorSize>::serialize(uint8_t** buffer,
|
|
||||||
size_t* size, size_t maxSize,
|
|
||||||
SerializeIF::Endianness streamEndianness) const {
|
|
||||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
|
|
||||||
for (uint16_t i = 0; i < vectorSize; i++) {
|
|
||||||
result = SerializeAdapter::serialize(&(value[i]), buffer, size,
|
|
||||||
maxSize, streamEndianness);
|
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
std::memcpy(poolEntry->getDataPtr(), this->value, poolEntry->getByteSize());
|
||||||
|
poolEntry->setValid(this->valid);
|
||||||
|
return RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, uint16_t vectorSize>
|
template <typename T, uint16_t vectorSize>
|
||||||
|
inline T& LocalPoolVector<T, vectorSize>::operator[](size_t i) {
|
||||||
|
if (i < vectorSize) {
|
||||||
|
return value[i];
|
||||||
|
}
|
||||||
|
// If this happens, I have to set some value. I consider this
|
||||||
|
// a configuration error, but I wont exit here.
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::warning << "LocalPoolVector: Invalid index. Setting or returning"
|
||||||
|
" last value!"
|
||||||
|
<< std::endl;
|
||||||
|
#else
|
||||||
|
sif::printWarning(
|
||||||
|
"LocalPoolVector: Invalid index. Setting or returning"
|
||||||
|
" last value!\n");
|
||||||
|
#endif
|
||||||
|
return value[vectorSize - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, uint16_t vectorSize>
|
||||||
|
inline const T& LocalPoolVector<T, vectorSize>::operator[](size_t i) const {
|
||||||
|
if (i < vectorSize) {
|
||||||
|
return value[i];
|
||||||
|
}
|
||||||
|
// If this happens, I have to set some value. I consider this
|
||||||
|
// a configuration error, but I wont exit here.
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::warning << "LocalPoolVector: Invalid index. Setting or returning"
|
||||||
|
" last value!"
|
||||||
|
<< std::endl;
|
||||||
|
#else
|
||||||
|
sif::printWarning(
|
||||||
|
"LocalPoolVector: Invalid index. Setting or returning"
|
||||||
|
" last value!\n");
|
||||||
|
#endif
|
||||||
|
return value[vectorSize - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, uint16_t vectorSize>
|
||||||
|
inline ReturnValue_t LocalPoolVector<T, vectorSize>::serialize(
|
||||||
|
uint8_t** buffer, size_t* size, size_t maxSize,
|
||||||
|
SerializeIF::Endianness streamEndianness) const {
|
||||||
|
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
for (uint16_t i = 0; i < vectorSize; i++) {
|
||||||
|
result = SerializeAdapter::serialize(&(value[i]), buffer, size, maxSize, streamEndianness);
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, uint16_t vectorSize>
|
||||||
inline size_t LocalPoolVector<T, vectorSize>::getSerializedSize() const {
|
inline size_t LocalPoolVector<T, vectorSize>::getSerializedSize() const {
|
||||||
return vectorSize * SerializeAdapter::getSerializedSize(value);
|
return vectorSize * SerializeAdapter::getSerializedSize(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, uint16_t vectorSize>
|
template <typename T, uint16_t vectorSize>
|
||||||
inline ReturnValue_t LocalPoolVector<T, vectorSize>::deSerialize(
|
inline ReturnValue_t LocalPoolVector<T, vectorSize>::deSerialize(
|
||||||
const uint8_t** buffer, size_t* size,
|
const uint8_t** buffer, size_t* size, SerializeIF::Endianness streamEndianness) {
|
||||||
SerializeIF::Endianness streamEndianness) {
|
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
|
||||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
|
for (uint16_t i = 0; i < vectorSize; i++) {
|
||||||
for (uint16_t i = 0; i < vectorSize; i++) {
|
result = SerializeAdapter::deSerialize(&(value[i]), buffer, size, streamEndianness);
|
||||||
result = SerializeAdapter::deSerialize(&(value[i]), buffer, size,
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
streamEndianness);
|
break;
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result;
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
template<typename T, uint16_t vectorSize>
|
template <typename T, uint16_t vectorSize>
|
||||||
inline std::ostream& operator<< (std::ostream &out,
|
inline std::ostream& operator<<(std::ostream& out, const LocalPoolVector<T, vectorSize>& var) {
|
||||||
const LocalPoolVector<T, vectorSize> &var) {
|
out << "Vector: [";
|
||||||
out << "Vector: [";
|
for (int i = 0; i < vectorSize; i++) {
|
||||||
for(int i = 0;i < vectorSize; i++) {
|
out << var.value[i];
|
||||||
out << var.value[i];
|
if (i < vectorSize - 1) {
|
||||||
if(i < vectorSize - 1) {
|
out << ", ";
|
||||||
out << ", ";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
out << "]";
|
}
|
||||||
return out;
|
out << "]";
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1,5 +1,2 @@
|
|||||||
target_sources(${LIB_FSFW_NAME}
|
target_sources(${LIB_FSFW_NAME} PRIVATE HasLocalDpIFUserAttorney.cpp
|
||||||
PRIVATE
|
HasLocalDpIFManagerAttorney.cpp)
|
||||||
HasLocalDpIFUserAttorney.cpp
|
|
||||||
HasLocalDpIFManagerAttorney.cpp
|
|
||||||
)
|
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
target_sources(${LIB_FSFW_NAME}
|
target_sources(
|
||||||
PRIVATE
|
${LIB_FSFW_NAME}
|
||||||
AssemblyBase.cpp
|
PRIVATE AssemblyBase.cpp
|
||||||
ChildHandlerBase.cpp
|
ChildHandlerBase.cpp
|
||||||
ChildHandlerFDIR.cpp
|
ChildHandlerFDIR.cpp
|
||||||
DeviceHandlerBase.cpp
|
DeviceHandlerBase.cpp
|
||||||
DeviceHandlerFailureIsolation.cpp
|
DeviceHandlerFailureIsolation.cpp
|
||||||
DeviceHandlerMessage.cpp
|
DeviceHandlerMessage.cpp
|
||||||
DeviceTmReportingWrapper.cpp
|
DeviceTmReportingWrapper.cpp
|
||||||
HealthDevice.cpp
|
HealthDevice.cpp)
|
||||||
)
|
|
||||||
|
@ -1062,7 +1062,8 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
/**
|
/**
|
||||||
* Same as triggerEvent, but for forwarding if object is used as proxy.
|
* Same as triggerEvent, but for forwarding if object is used as proxy.
|
||||||
*/
|
*/
|
||||||
virtual void forwardEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0) const override;
|
virtual void forwardEvent(Event event, uint32_t parameter1 = 0,
|
||||||
|
uint32_t parameter2 = 0) const override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if current mode is transitional mode.
|
* Checks if current mode is transitional mode.
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
target_sources(${LIB_FSFW_NAME} PRIVATE EventManager.cpp EventMessage.cpp)
|
||||||
EventManager.cpp
|
|
||||||
EventMessage.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
add_subdirectory(eventmatching)
|
add_subdirectory(eventmatching)
|
||||||
|
@ -1,7 +1,3 @@
|
|||||||
target_sources(${LIB_FSFW_NAME}
|
target_sources(
|
||||||
PRIVATE
|
${LIB_FSFW_NAME} PRIVATE EventIdRangeMatcher.cpp EventMatchTree.cpp
|
||||||
EventIdRangeMatcher.cpp
|
ReporterRangeMatcher.cpp SeverityRangeMatcher.cpp)
|
||||||
EventMatchTree.cpp
|
|
||||||
ReporterRangeMatcher.cpp
|
|
||||||
SeverityRangeMatcher.cpp
|
|
||||||
)
|
|
||||||
|
@ -27,6 +27,7 @@ enum : uint8_t {
|
|||||||
PUS_SERVICE_6 = 86,
|
PUS_SERVICE_6 = 86,
|
||||||
PUS_SERVICE_8 = 88,
|
PUS_SERVICE_8 = 88,
|
||||||
PUS_SERVICE_9 = 89,
|
PUS_SERVICE_9 = 89,
|
||||||
|
PUS_SERVICE_11 = 91,
|
||||||
PUS_SERVICE_17 = 97,
|
PUS_SERVICE_17 = 97,
|
||||||
PUS_SERVICE_23 = 103,
|
PUS_SERVICE_23 = 103,
|
||||||
MGM_LIS3MDL = 106,
|
MGM_LIS3MDL = 106,
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
target_sources(${LIB_FSFW_NAME}
|
target_sources(
|
||||||
PRIVATE
|
${LIB_FSFW_NAME} PRIVATE EventCorrelation.cpp FailureIsolationBase.cpp
|
||||||
EventCorrelation.cpp
|
FaultCounter.cpp)
|
||||||
FailureIsolationBase.cpp
|
|
||||||
FaultCounter.cpp
|
|
||||||
)
|
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
target_sources(${LIB_FSFW_NAME}
|
target_sources(
|
||||||
PRIVATE
|
${LIB_FSFW_NAME}
|
||||||
arrayprinter.cpp
|
PRIVATE arrayprinter.cpp
|
||||||
AsciiConverter.cpp
|
AsciiConverter.cpp
|
||||||
CRC.cpp
|
CRC.cpp
|
||||||
DleEncoder.cpp
|
DleEncoder.cpp
|
||||||
PeriodicOperationDivider.cpp
|
PeriodicOperationDivider.cpp
|
||||||
timevalOperations.cpp
|
timevalOperations.cpp
|
||||||
Type.cpp
|
Type.cpp
|
||||||
bitutility.cpp
|
bitutility.cpp)
|
||||||
)
|
|
||||||
|
|
||||||
add_subdirectory(math)
|
add_subdirectory(math)
|
||||||
|
@ -1,4 +1 @@
|
|||||||
target_sources(${LIB_FSFW_NAME}
|
target_sources(${LIB_FSFW_NAME} PRIVATE QuaternionOperations.cpp)
|
||||||
PRIVATE
|
|
||||||
QuaternionOperations.cpp
|
|
||||||
)
|
|
||||||
|
@ -1,6 +1,2 @@
|
|||||||
target_sources(${LIB_FSFW_NAME}
|
target_sources(${LIB_FSFW_NAME} PRIVATE HealthHelper.cpp HealthMessage.cpp
|
||||||
PRIVATE
|
HealthTable.cpp)
|
||||||
HealthHelper.cpp
|
|
||||||
HealthMessage.cpp
|
|
||||||
HealthTable.cpp
|
|
||||||
)
|
|
||||||
|
@ -1,5 +1,2 @@
|
|||||||
target_sources(${LIB_FSFW_NAME}
|
target_sources(${LIB_FSFW_NAME} PRIVATE HousekeepingMessage.cpp
|
||||||
PRIVATE
|
PeriodicHousekeepingHelper.cpp)
|
||||||
HousekeepingMessage.cpp
|
|
||||||
PeriodicHousekeepingHelper.cpp
|
|
||||||
)
|
|
||||||
|
@ -1,4 +1 @@
|
|||||||
target_sources(${LIB_FSFW_NAME}
|
target_sources(${LIB_FSFW_NAME} PRIVATE InternalErrorReporter.cpp)
|
||||||
PRIVATE
|
|
||||||
InternalErrorReporter.cpp
|
|
||||||
)
|
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
target_sources(
|
||||||
CommandMessage.cpp
|
${LIB_FSFW_NAME} PRIVATE CommandMessage.cpp CommandMessageCleaner.cpp
|
||||||
CommandMessageCleaner.cpp
|
MessageQueueMessage.cpp MessageQueueBase.cpp)
|
||||||
MessageQueueMessage.cpp
|
|
||||||
MessageQueueBase.cpp
|
|
||||||
)
|
|
||||||
|
@ -1,5 +1,2 @@
|
|||||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
target_sources(${LIB_FSFW_NAME} PRIVATE MemoryHelper.cpp MemoryMessage.cpp
|
||||||
MemoryHelper.cpp
|
GenericFileSystemMessage.cpp)
|
||||||
MemoryMessage.cpp
|
|
||||||
GenericFileSystemMessage.cpp
|
|
||||||
)
|
|
||||||
|
@ -1,5 +1 @@
|
|||||||
target_sources(${LIB_FSFW_NAME}
|
target_sources(${LIB_FSFW_NAME} PRIVATE ModeHelper.cpp ModeMessage.cpp)
|
||||||
PRIVATE
|
|
||||||
ModeHelper.cpp
|
|
||||||
ModeMessage.cpp
|
|
||||||
)
|
|
||||||
|
@ -1,5 +1,2 @@
|
|||||||
target_sources(${LIB_FSFW_NAME}
|
target_sources(${LIB_FSFW_NAME} PRIVATE LimitViolationReporter.cpp
|
||||||
PRIVATE
|
MonitoringMessage.cpp)
|
||||||
LimitViolationReporter.cpp
|
|
||||||
MonitoringMessage.cpp
|
|
||||||
)
|
|
||||||
|
@ -1,5 +1 @@
|
|||||||
target_sources(${LIB_FSFW_NAME}
|
target_sources(${LIB_FSFW_NAME} PRIVATE ObjectManager.cpp SystemObject.cpp)
|
||||||
PRIVATE
|
|
||||||
ObjectManager.cpp
|
|
||||||
SystemObject.cpp
|
|
||||||
)
|
|
||||||
|
@ -50,7 +50,8 @@ class SystemObject : public SystemObjectIF {
|
|||||||
virtual ReturnValue_t initialize() override;
|
virtual ReturnValue_t initialize() override;
|
||||||
virtual ReturnValue_t checkObjectConnections() override;
|
virtual ReturnValue_t checkObjectConnections() override;
|
||||||
|
|
||||||
virtual void forwardEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0) const override;
|
virtual void forwardEvent(Event event, uint32_t parameter1 = 0,
|
||||||
|
uint32_t parameter2 = 0) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_OBJECTMANAGER_SYSTEMOBJECT_H_ */
|
#endif /* FSFW_OBJECTMANAGER_SYSTEMOBJECT_H_ */
|
||||||
|
@ -14,6 +14,7 @@ enum framework_objects : object_id_t {
|
|||||||
PUS_SERVICE_5_EVENT_REPORTING = 0x53000005,
|
PUS_SERVICE_5_EVENT_REPORTING = 0x53000005,
|
||||||
PUS_SERVICE_8_FUNCTION_MGMT = 0x53000008,
|
PUS_SERVICE_8_FUNCTION_MGMT = 0x53000008,
|
||||||
PUS_SERVICE_9_TIME_MGMT = 0x53000009,
|
PUS_SERVICE_9_TIME_MGMT = 0x53000009,
|
||||||
|
PUS_SERVICE_11_TC_SCHEDULER = 0x53000011,
|
||||||
PUS_SERVICE_17_TEST = 0x53000017,
|
PUS_SERVICE_17_TEST = 0x53000017,
|
||||||
PUS_SERVICE_20_PARAMETERS = 0x53000020,
|
PUS_SERVICE_20_PARAMETERS = 0x53000020,
|
||||||
PUS_SERVICE_200_MODE_MGMT = 0x53000200,
|
PUS_SERVICE_200_MODE_MGMT = 0x53000200,
|
||||||
|
@ -1,35 +1,33 @@
|
|||||||
# Check the OS_FSFW variable
|
# Check the OS_FSFW variable
|
||||||
if(FSFW_OSAL MATCHES "freertos")
|
if(FSFW_OSAL MATCHES "freertos")
|
||||||
add_subdirectory(freertos)
|
add_subdirectory(freertos)
|
||||||
elseif(FSFW_OSAL MATCHES "rtems")
|
elseif(FSFW_OSAL MATCHES "rtems")
|
||||||
add_subdirectory(rtems)
|
add_subdirectory(rtems)
|
||||||
elseif(FSFW_OSAL MATCHES "linux")
|
elseif(FSFW_OSAL MATCHES "linux")
|
||||||
add_subdirectory(linux)
|
add_subdirectory(linux)
|
||||||
elseif(FSFW_OSAL MATCHES "host")
|
elseif(FSFW_OSAL MATCHES "host")
|
||||||
add_subdirectory(host)
|
add_subdirectory(host)
|
||||||
if (WIN32)
|
if(WIN32)
|
||||||
add_subdirectory(windows)
|
add_subdirectory(windows)
|
||||||
elseif(UNIX)
|
elseif(UNIX)
|
||||||
# We still need to pull in some Linux specific sources
|
# We still need to pull in some Linux specific sources
|
||||||
target_sources(${LIB_FSFW_NAME} PUBLIC
|
target_sources(${LIB_FSFW_NAME} PUBLIC linux/tcpipHelpers.cpp)
|
||||||
linux/tcpipHelpers.cpp
|
endif()
|
||||||
)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
else()
|
else()
|
||||||
|
|
||||||
message(WARNING "The OS_FSFW variable was not set. Assuming host OS..")
|
message(WARNING "The OS_FSFW variable was not set. Assuming host OS..")
|
||||||
# Not set. Assumuing this is a host build, try to determine host OS
|
# Not set. Assumuing this is a host build, try to determine host OS
|
||||||
if (WIN32)
|
if(WIN32)
|
||||||
add_subdirectory(host)
|
add_subdirectory(host)
|
||||||
add_subdirectory(windows)
|
add_subdirectory(windows)
|
||||||
elseif (UNIX)
|
elseif(UNIX)
|
||||||
add_subdirectory(linux)
|
add_subdirectory(linux)
|
||||||
else ()
|
else()
|
||||||
# MacOS or other OSes have not been tested yet / are not supported.
|
# MacOS or other OSes have not been tested yet / are not supported.
|
||||||
message(FATAL_ERROR "The host OS could not be determined! Aborting.")
|
message(FATAL_ERROR "The host OS could not be determined! Aborting.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_subdirectory(common)
|
add_subdirectory(common)
|
||||||
|
@ -1,17 +1,10 @@
|
|||||||
if(DEFINED WIN32 OR DEFINED UNIX)
|
if(DEFINED WIN32 OR DEFINED UNIX)
|
||||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
target_sources(
|
||||||
tcpipCommon.cpp
|
${LIB_FSFW_NAME}
|
||||||
TcpIpBase.cpp
|
PRIVATE tcpipCommon.cpp TcpIpBase.cpp UdpTcPollingTask.cpp
|
||||||
UdpTcPollingTask.cpp
|
UdpTmTcBridge.cpp TcpTmTcServer.cpp TcpTmTcBridge.cpp)
|
||||||
UdpTmTcBridge.cpp
|
|
||||||
TcpTmTcServer.cpp
|
|
||||||
TcpTmTcBridge.cpp
|
|
||||||
)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
|
target_link_libraries(${LIB_FSFW_NAME} PRIVATE wsock32 ws2_32)
|
||||||
wsock32
|
endif()
|
||||||
ws2_32
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
@ -109,8 +109,8 @@ TcpTmTcServer::~TcpTmTcServer() { closeSocket(listenerTcpSocket); }
|
|||||||
using namespace tcpip;
|
using namespace tcpip;
|
||||||
// If a connection is accepted, the corresponding socket will be assigned to the new socket
|
// If a connection is accepted, the corresponding socket will be assigned to the new socket
|
||||||
socket_t connSocket = 0;
|
socket_t connSocket = 0;
|
||||||
// sockaddr clientSockAddr = {};
|
sockaddr clientSockAddr = {};
|
||||||
// socklen_t connectorSockAddrLen = 0;
|
socklen_t connectorSockAddrLen = 0;
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
|
|
||||||
// Listen for connection requests permanently for lifetime of program
|
// Listen for connection requests permanently for lifetime of program
|
||||||
@ -121,8 +121,7 @@ TcpTmTcServer::~TcpTmTcServer() { closeSocket(listenerTcpSocket); }
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// connSocket = accept(listenerTcpSocket, &clientSockAddr, &connectorSockAddrLen);
|
connSocket = accept(listenerTcpSocket, &clientSockAddr, &connectorSockAddrLen);
|
||||||
connSocket = accept(listenerTcpSocket, nullptr, nullptr);
|
|
||||||
|
|
||||||
if (connSocket == INVALID_SOCKET) {
|
if (connSocket == INVALID_SOCKET) {
|
||||||
handleError(Protocol::TCP, ErrorSources::ACCEPT_CALL, 500);
|
handleError(Protocol::TCP, ErrorSources::ACCEPT_CALL, 500);
|
||||||
@ -137,6 +136,7 @@ TcpTmTcServer::~TcpTmTcServer() { closeSocket(listenerTcpSocket); }
|
|||||||
if (retval != 0) {
|
if (retval != 0) {
|
||||||
handleError(Protocol::TCP, ErrorSources::SHUTDOWN_CALL);
|
handleError(Protocol::TCP, ErrorSources::SHUTDOWN_CALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
closeSocket(connSocket);
|
closeSocket(connSocket);
|
||||||
connSocket = 0;
|
connSocket = 0;
|
||||||
}
|
}
|
||||||
@ -161,7 +161,7 @@ void TcpTmTcServer::handleServerOperation(socket_t& connSocket) {
|
|||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
ssize_t retval = recv(connSocket, reinterpret_cast<char*>(receptionBuffer.data()),
|
ssize_t retval = recv(connSocket, reinterpret_cast<char*>(receptionBuffer.data()),
|
||||||
receptionBuffer.capacity(), tcpConfig.tcpFlags);
|
receptionBuffer.capacity(), tcpConfig.tcpFlags);
|
||||||
if (retval == 0) {
|
if (retval == 0) {
|
||||||
size_t availableReadData = ringBuffer.getAvailableReadData();
|
size_t availableReadData = ringBuffer.getAvailableReadData();
|
||||||
if (availableReadData > lastRingBufferSize) {
|
if (availableReadData > lastRingBufferSize) {
|
||||||
@ -285,7 +285,7 @@ ReturnValue_t TcpTmTcServer::handleTmSending(socket_t connSocket, bool& tmSent)
|
|||||||
arrayprinter::print(storeAccessor.data(), storeAccessor.size());
|
arrayprinter::print(storeAccessor.data(), storeAccessor.size());
|
||||||
}
|
}
|
||||||
ssize_t retval = send(connSocket, reinterpret_cast<const char*>(storeAccessor.data()),
|
ssize_t retval = send(connSocket, reinterpret_cast<const char*>(storeAccessor.data()),
|
||||||
storeAccessor.size(), tcpConfig.tcpTmFlags);
|
storeAccessor.size(), tcpConfig.tcpTmFlags);
|
||||||
if (retval == static_cast<int>(storeAccessor.size())) {
|
if (retval == static_cast<int>(storeAccessor.size())) {
|
||||||
// Packet sent, clear FIFO entry
|
// Packet sent, clear FIFO entry
|
||||||
tmtcBridge->tmFifo->pop();
|
tmtcBridge->tmFifo->pop();
|
||||||
@ -340,7 +340,7 @@ ReturnValue_t TcpTmTcServer::handleTcRingBufferData(size_t availableReadData) {
|
|||||||
size_t foundSize = 0;
|
size_t foundSize = 0;
|
||||||
size_t readLen = 0;
|
size_t readLen = 0;
|
||||||
while (readLen < readAmount) {
|
while (readLen < readAmount) {
|
||||||
if(spacePacketParser == nullptr) {
|
if (spacePacketParser == nullptr) {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
result =
|
result =
|
||||||
|
@ -154,7 +154,7 @@ void UdpTcPollingTask::setTimeout(double timeoutSeconds) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#elif defined(PLATFORM_UNIX)
|
#elif defined(PLATFORM_UNIX)
|
||||||
timeval tval {};
|
timeval tval{};
|
||||||
tval = timevalOperations::toTimeval(timeoutSeconds);
|
tval = timevalOperations::toTimeval(timeoutSeconds);
|
||||||
int result = setsockopt(serverSocket, SOL_SOCKET, SO_RCVTIMEO, &tval, sizeof(receptionTimeout));
|
int result = setsockopt(serverSocket, SOL_SOCKET, SO_RCVTIMEO, &tval, sizeof(receptionTimeout));
|
||||||
if (result == -1) {
|
if (result == -1) {
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
const std::string UdpTmTcBridge::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT;
|
const std::string UdpTmTcBridge::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT;
|
||||||
|
|
||||||
UdpTmTcBridge::UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination,
|
UdpTmTcBridge::UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination,
|
||||||
const std::string& udpServerPort_, object_id_t tmStoreId,
|
const std::string &udpServerPort_, object_id_t tmStoreId,
|
||||||
object_id_t tcStoreId)
|
object_id_t tcStoreId)
|
||||||
: TmTcBridge(objectId, tcDestination, tmStoreId, tcStoreId) {
|
: TmTcBridge(objectId, tcDestination, tmStoreId, tcStoreId) {
|
||||||
if (udpServerPort_.empty()) {
|
if (udpServerPort_.empty()) {
|
||||||
@ -118,7 +118,7 @@ ReturnValue_t UdpTmTcBridge::sendTm(const uint8_t *data, size_t dataLen) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
ssize_t bytesSent = sendto(serverSocket, reinterpret_cast<const char *>(data), dataLen, flags,
|
ssize_t bytesSent = sendto(serverSocket, reinterpret_cast<const char *>(data), dataLen, flags,
|
||||||
&clientAddress, clientAddressLen);
|
&clientAddress, clientAddressLen);
|
||||||
if (bytesSent == SOCKET_ERROR) {
|
if (bytesSent == SOCKET_ERROR) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "TmTcUdpBridge::sendTm: Send operation failed." << std::endl;
|
sif::warning << "TmTcUdpBridge::sendTm: Send operation failed." << std::endl;
|
||||||
|
@ -29,8 +29,8 @@ class UdpTmTcBridge : public TmTcBridge, public TcpIpBase {
|
|||||||
/* The ports chosen here should not be used by any other process. */
|
/* The ports chosen here should not be used by any other process. */
|
||||||
static const std::string DEFAULT_SERVER_PORT;
|
static const std::string DEFAULT_SERVER_PORT;
|
||||||
|
|
||||||
UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination, const std::string& udpServerPort = "",
|
UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination,
|
||||||
object_id_t tmStoreId = objects::TM_STORE,
|
const std::string& udpServerPort = "", object_id_t tmStoreId = objects::TM_STORE,
|
||||||
object_id_t tcStoreId = objects::TC_STORE);
|
object_id_t tcStoreId = objects::TC_STORE);
|
||||||
~UdpTmTcBridge() override;
|
~UdpTmTcBridge() override;
|
||||||
|
|
||||||
|
@ -1,32 +1,30 @@
|
|||||||
target_sources(${LIB_FSFW_NAME}
|
target_sources(
|
||||||
PRIVATE
|
${LIB_FSFW_NAME}
|
||||||
Clock.cpp
|
PRIVATE Clock.cpp
|
||||||
FixedTimeslotTask.cpp
|
FixedTimeslotTask.cpp
|
||||||
BinarySemaphore.cpp
|
BinarySemaphore.cpp
|
||||||
BinSemaphUsingTask.cpp
|
BinSemaphUsingTask.cpp
|
||||||
CountingSemaphore.cpp
|
CountingSemaphore.cpp
|
||||||
CountingSemaphUsingTask.cpp
|
CountingSemaphUsingTask.cpp
|
||||||
MessageQueue.cpp
|
MessageQueue.cpp
|
||||||
Mutex.cpp
|
Mutex.cpp
|
||||||
MutexFactory.cpp
|
MutexFactory.cpp
|
||||||
PeriodicTask.cpp
|
PeriodicTask.cpp
|
||||||
QueueFactory.cpp
|
QueueFactory.cpp
|
||||||
SemaphoreFactory.cpp
|
SemaphoreFactory.cpp
|
||||||
TaskFactory.cpp
|
TaskFactory.cpp
|
||||||
Timekeeper.cpp
|
Timekeeper.cpp
|
||||||
TaskManagement.cpp
|
TaskManagement.cpp
|
||||||
QueueMapManager.cpp
|
QueueMapManager.cpp)
|
||||||
)
|
|
||||||
|
|
||||||
# FreeRTOS is required to link the FSFW now. It is recommended to compile
|
# FreeRTOS is required to link the FSFW now. It is recommended to compile
|
||||||
# FreeRTOS as a static library and set LIB_OS_NAME to the target name of the
|
# FreeRTOS as a static library and set LIB_OS_NAME to the target name of the
|
||||||
# library.
|
# library.
|
||||||
if(NOT LIB_OS_NAME)
|
if(NOT LIB_OS_NAME)
|
||||||
message(STATUS
|
message(
|
||||||
"LIB_OS_NAME is empty. Make sure to include the FreeRTOS header path properly."
|
STATUS
|
||||||
)
|
"LIB_OS_NAME is empty. Make sure to include the FreeRTOS header path properly."
|
||||||
|
)
|
||||||
else()
|
else()
|
||||||
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
|
target_link_libraries(${LIB_FSFW_NAME} PRIVATE ${LIB_OS_NAME})
|
||||||
${LIB_OS_NAME}
|
|
||||||
)
|
|
||||||
endif()
|
endif()
|
||||||
|
@ -1,27 +1,23 @@
|
|||||||
#include "fsfw/osal/freertos/FixedTimeslotTask.h"
|
#include "fsfw/osal/freertos/FixedTimeslotTask.h"
|
||||||
|
|
||||||
#include "fsfw/objectmanager/ObjectManager.h"
|
#include "fsfw/serviceinterface.h"
|
||||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
|
||||||
|
|
||||||
uint32_t FixedTimeslotTask::deadlineMissedCount = 0;
|
|
||||||
const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = configMINIMAL_STACK_SIZE;
|
const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = configMINIMAL_STACK_SIZE;
|
||||||
|
|
||||||
FixedTimeslotTask::FixedTimeslotTask(TaskName name, TaskPriority setPriority,
|
FixedTimeslotTask::FixedTimeslotTask(TaskName name, TaskPriority setPriority,
|
||||||
TaskStackSize setStack, TaskPeriod overallPeriod,
|
TaskStackSize setStack, TaskPeriod period,
|
||||||
void (*setDeadlineMissedFunc)())
|
TaskDeadlineMissedFunction dlmFunc_)
|
||||||
: started(false), handle(nullptr), pst(overallPeriod * 1000) {
|
: FixedTimeslotTaskBase(period, dlmFunc_), started(false), handle(nullptr) {
|
||||||
configSTACK_DEPTH_TYPE stackSize = setStack / sizeof(configSTACK_DEPTH_TYPE);
|
configSTACK_DEPTH_TYPE stackSize = setStack / sizeof(configSTACK_DEPTH_TYPE);
|
||||||
xTaskCreate(taskEntryPoint, name, stackSize, this, setPriority, &handle);
|
xTaskCreate(taskEntryPoint, name, stackSize, this, setPriority, &handle);
|
||||||
// All additional attributes are applied to the object.
|
|
||||||
this->deadlineMissedFunc = setDeadlineMissedFunc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FixedTimeslotTask::~FixedTimeslotTask() {}
|
FixedTimeslotTask::~FixedTimeslotTask() = default;
|
||||||
|
|
||||||
void FixedTimeslotTask::taskEntryPoint(void* argument) {
|
void FixedTimeslotTask::taskEntryPoint(void* argument) {
|
||||||
// The argument is re-interpreted as FixedTimeslotTask. The Task object is
|
// The argument is re-interpreted as FixedTimeslotTask. The Task object is
|
||||||
// global, so it is found from any place.
|
// global, so it is found from any place.
|
||||||
FixedTimeslotTask* originalTask(reinterpret_cast<FixedTimeslotTask*>(argument));
|
auto* originalTask(reinterpret_cast<FixedTimeslotTask*>(argument));
|
||||||
/* Task should not start until explicitly requested,
|
/* Task should not start until explicitly requested,
|
||||||
* but in FreeRTOS, tasks start as soon as they are created if the scheduler
|
* but in FreeRTOS, tasks start as soon as they are created if the scheduler
|
||||||
* is running but not if the scheduler is not running.
|
* is running but not if the scheduler is not running.
|
||||||
@ -32,26 +28,18 @@ void FixedTimeslotTask::taskEntryPoint(void* argument) {
|
|||||||
* can continue */
|
* can continue */
|
||||||
|
|
||||||
if (not originalTask->started) {
|
if (not originalTask->started) {
|
||||||
vTaskSuspend(NULL);
|
vTaskSuspend(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
originalTask->taskFunctionality();
|
originalTask->taskFunctionality();
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::debug << "Polling task " << originalTask->handle << " returned from taskFunctionality."
|
sif::debug << "Polling task " << originalTask->handle << " returned from taskFunctionality."
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
#else
|
||||||
|
sif::printDebug("Polling task returned from taskFunctionality\n");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void FixedTimeslotTask::missedDeadlineCounter() {
|
|
||||||
FixedTimeslotTask::deadlineMissedCount++;
|
|
||||||
if (FixedTimeslotTask::deadlineMissedCount % 10 == 0) {
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::error << "PST missed " << FixedTimeslotTask::deadlineMissedCount << " deadlines."
|
|
||||||
<< std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t FixedTimeslotTask::startTask() {
|
ReturnValue_t FixedTimeslotTask::startTask() {
|
||||||
started = true;
|
started = true;
|
||||||
|
|
||||||
@ -63,31 +51,12 @@ ReturnValue_t FixedTimeslotTask::startTask() {
|
|||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, uint32_t slotTimeMs,
|
[[noreturn]] void FixedTimeslotTask::taskFunctionality() {
|
||||||
int8_t executionStep) {
|
|
||||||
ExecutableObjectIF* handler = ObjectManager::instance()->get<ExecutableObjectIF>(componentId);
|
|
||||||
if (handler != nullptr) {
|
|
||||||
pst.addSlot(componentId, slotTimeMs, executionStep, handler, this);
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::error << "Component " << std::hex << componentId << " not found, not adding it to pst"
|
|
||||||
<< std::endl;
|
|
||||||
#endif
|
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t FixedTimeslotTask::getPeriodMs() const { return pst.getLengthMs(); }
|
|
||||||
|
|
||||||
ReturnValue_t FixedTimeslotTask::checkSequence() const { return pst.checkSequence(); }
|
|
||||||
|
|
||||||
void FixedTimeslotTask::taskFunctionality() {
|
|
||||||
// A local iterator for the Polling Sequence Table is created to find the
|
// A local iterator for the Polling Sequence Table is created to find the
|
||||||
// start time for the first entry.
|
// start time for the first entry.
|
||||||
auto slotListIter = pst.current;
|
auto slotListIter = pollingSeqTable.current;
|
||||||
|
|
||||||
pst.intializeSequenceAfterTaskCreation();
|
pollingSeqTable.intializeSequenceAfterTaskCreation();
|
||||||
|
|
||||||
// The start time for the first entry is read.
|
// The start time for the first entry is read.
|
||||||
uint32_t intervalMs = slotListIter->pollingTimeMs;
|
uint32_t intervalMs = slotListIter->pollingTimeMs;
|
||||||
@ -108,10 +77,10 @@ void FixedTimeslotTask::taskFunctionality() {
|
|||||||
/* Enter the loop that defines the task behavior. */
|
/* Enter the loop that defines the task behavior. */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
// The component for this slot is executed and the next one is chosen.
|
// The component for this slot is executed and the next one is chosen.
|
||||||
this->pst.executeAndAdvance();
|
this->pollingSeqTable.executeAndAdvance();
|
||||||
if (not pst.slotFollowsImmediately()) {
|
if (not pollingSeqTable.slotFollowsImmediately()) {
|
||||||
// Get the interval till execution of the next slot.
|
// Get the interval till execution of the next slot.
|
||||||
intervalMs = this->pst.getIntervalToPreviousSlotMs();
|
intervalMs = this->pollingSeqTable.getIntervalToPreviousSlotMs();
|
||||||
interval = pdMS_TO_TICKS(intervalMs);
|
interval = pdMS_TO_TICKS(intervalMs);
|
||||||
|
|
||||||
#if (tskKERNEL_VERSION_MAJOR == 10 && tskKERNEL_VERSION_MINOR >= 4) || tskKERNEL_VERSION_MAJOR > 10
|
#if (tskKERNEL_VERSION_MAJOR == 10 && tskKERNEL_VERSION_MINOR >= 4) || tskKERNEL_VERSION_MAJOR > 10
|
||||||
@ -132,8 +101,8 @@ void FixedTimeslotTask::taskFunctionality() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FixedTimeslotTask::handleMissedDeadline() {
|
void FixedTimeslotTask::handleMissedDeadline() {
|
||||||
if (deadlineMissedFunc != nullptr) {
|
if (dlmFunc != nullptr) {
|
||||||
this->deadlineMissedFunc();
|
dlmFunc();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,11 +4,11 @@
|
|||||||
#include "FreeRTOS.h"
|
#include "FreeRTOS.h"
|
||||||
#include "FreeRTOSTaskIF.h"
|
#include "FreeRTOSTaskIF.h"
|
||||||
#include "fsfw/tasks/FixedSlotSequence.h"
|
#include "fsfw/tasks/FixedSlotSequence.h"
|
||||||
#include "fsfw/tasks/FixedTimeslotTaskIF.h"
|
#include "fsfw/tasks/FixedTimeslotTaskBase.h"
|
||||||
#include "fsfw/tasks/Typedef.h"
|
#include "fsfw/tasks/definitions.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
|
||||||
class FixedTimeslotTask : public FixedTimeslotTaskIF, public FreeRTOSTaskIF {
|
class FixedTimeslotTask : public FixedTimeslotTaskBase, public FreeRTOSTaskIF {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Keep in mind that you need to call before vTaskStartScheduler()!
|
* Keep in mind that you need to call before vTaskStartScheduler()!
|
||||||
@ -23,7 +23,7 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF, public FreeRTOSTaskIF {
|
|||||||
* @return Pointer to the newly created task.
|
* @return Pointer to the newly created task.
|
||||||
*/
|
*/
|
||||||
FixedTimeslotTask(TaskName name, TaskPriority setPriority, TaskStackSize setStack,
|
FixedTimeslotTask(TaskName name, TaskPriority setPriority, TaskStackSize setStack,
|
||||||
TaskPeriod overallPeriod, void (*setDeadlineMissedFunc)());
|
TaskPeriod overallPeriod, TaskDeadlineMissedFunction dlmFunc);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The destructor of the class.
|
* @brief The destructor of the class.
|
||||||
@ -32,26 +32,9 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF, public FreeRTOSTaskIF {
|
|||||||
* initialization for the PST and the device handlers. This is done by
|
* initialization for the PST and the device handlers. This is done by
|
||||||
* calling the PST's destructor.
|
* calling the PST's destructor.
|
||||||
*/
|
*/
|
||||||
virtual ~FixedTimeslotTask(void);
|
~FixedTimeslotTask() override;
|
||||||
|
|
||||||
ReturnValue_t startTask(void);
|
ReturnValue_t startTask() override;
|
||||||
/**
|
|
||||||
* This static function can be used as #deadlineMissedFunc.
|
|
||||||
* It counts missedDeadlines and prints the number of missed deadlines
|
|
||||||
* every 10th time.
|
|
||||||
*/
|
|
||||||
static void missedDeadlineCounter();
|
|
||||||
/**
|
|
||||||
* A helper variable to count missed deadlines.
|
|
||||||
*/
|
|
||||||
static uint32_t deadlineMissedCount;
|
|
||||||
|
|
||||||
ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs,
|
|
||||||
int8_t executionStep) override;
|
|
||||||
|
|
||||||
uint32_t getPeriodMs() const override;
|
|
||||||
|
|
||||||
ReturnValue_t checkSequence() const override;
|
|
||||||
|
|
||||||
ReturnValue_t sleepFor(uint32_t ms) override;
|
ReturnValue_t sleepFor(uint32_t ms) override;
|
||||||
|
|
||||||
@ -61,17 +44,6 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF, public FreeRTOSTaskIF {
|
|||||||
bool started;
|
bool started;
|
||||||
TaskHandle_t handle;
|
TaskHandle_t handle;
|
||||||
|
|
||||||
FixedSlotSequence pst;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This attribute holds a function pointer that is executed when
|
|
||||||
* a deadline was missed.
|
|
||||||
* @details
|
|
||||||
* Another function may be announced to determine the actions to perform
|
|
||||||
* when a deadline was missed. Currently, only one function for missing
|
|
||||||
* any deadline is allowed. If not used, it shall be declared NULL.
|
|
||||||
*/
|
|
||||||
void (*deadlineMissedFunc)(void);
|
|
||||||
/**
|
/**
|
||||||
* @brief This is the entry point for a new task.
|
* @brief This is the entry point for a new task.
|
||||||
* @details
|
* @details
|
||||||
@ -88,7 +60,7 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF, public FreeRTOSTaskIF {
|
|||||||
* It links the functionalities provided by FixedSlotSequence with the
|
* It links the functionalities provided by FixedSlotSequence with the
|
||||||
* OS's System Calls to keep the timing of the periods.
|
* OS's System Calls to keep the timing of the periods.
|
||||||
*/
|
*/
|
||||||
void taskFunctionality(void);
|
[[noreturn]] void taskFunctionality();
|
||||||
|
|
||||||
void handleMissedDeadline();
|
void handleMissedDeadline();
|
||||||
};
|
};
|
||||||
|
@ -6,11 +6,11 @@
|
|||||||
|
|
||||||
class FreeRTOSTaskIF {
|
class FreeRTOSTaskIF {
|
||||||
public:
|
public:
|
||||||
virtual ~FreeRTOSTaskIF() {}
|
virtual ~FreeRTOSTaskIF() = default;
|
||||||
virtual TaskHandle_t getTaskHandle() = 0;
|
virtual TaskHandle_t getTaskHandle() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool checkMissedDeadline(const TickType_t xLastWakeTime, const TickType_t interval) {
|
static bool checkMissedDeadline(const TickType_t xLastWakeTime, const TickType_t interval) {
|
||||||
/* Check whether deadline was missed while also taking overflows
|
/* Check whether deadline was missed while also taking overflows
|
||||||
* into account. Drawing this on paper with a timeline helps to understand
|
* into account. Drawing this on paper with a timeline helps to understand
|
||||||
* it. */
|
* it. */
|
||||||
|
@ -5,27 +5,28 @@
|
|||||||
#include "fsfw/tasks/ExecutableObjectIF.h"
|
#include "fsfw/tasks/ExecutableObjectIF.h"
|
||||||
|
|
||||||
PeriodicTask::PeriodicTask(const char* name, TaskPriority setPriority, TaskStackSize setStack,
|
PeriodicTask::PeriodicTask(const char* name, TaskPriority setPriority, TaskStackSize setStack,
|
||||||
TaskPeriod setPeriod, TaskDeadlineMissedFunction deadlineMissedFunc)
|
TaskPeriod setPeriod, TaskDeadlineMissedFunction dlmFunc_)
|
||||||
: started(false), handle(NULL), period(setPeriod), deadlineMissedFunc(deadlineMissedFunc) {
|
: PeriodicTaskBase(setPeriod, dlmFunc_), started(false), handle(nullptr) {
|
||||||
configSTACK_DEPTH_TYPE stackSize = setStack / sizeof(configSTACK_DEPTH_TYPE);
|
configSTACK_DEPTH_TYPE stackSize = setStack / sizeof(configSTACK_DEPTH_TYPE);
|
||||||
BaseType_t status = xTaskCreate(taskEntryPoint, name, stackSize, this, setPriority, &handle);
|
BaseType_t status = xTaskCreate(taskEntryPoint, name, stackSize, this, setPriority, &handle);
|
||||||
if (status != pdPASS) {
|
if (status != pdPASS) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::debug << "PeriodicTask Insufficient heap memory remaining. "
|
sif::debug << "PeriodicTask::PeriodicTask Insufficient heap memory remaining. Status: "
|
||||||
"Status: "
|
|
||||||
<< status << std::endl;
|
<< status << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printDebug("PeriodicTask::PeriodicTask: Insufficient heap memory remaining. Status: %d\n",
|
||||||
|
status);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PeriodicTask::~PeriodicTask(void) {
|
// Do not delete objects, we were responsible for ptrs only.
|
||||||
// Do not delete objects, we were responsible for ptrs only.
|
PeriodicTask::~PeriodicTask() = default;
|
||||||
}
|
|
||||||
|
|
||||||
void PeriodicTask::taskEntryPoint(void* argument) {
|
void PeriodicTask::taskEntryPoint(void* argument) {
|
||||||
// The argument is re-interpreted as PeriodicTask. The Task object is
|
// The argument is re-interpreted as PeriodicTask. The Task object is
|
||||||
// global, so it is found from any place.
|
// global, so it is found from any place.
|
||||||
PeriodicTask* originalTask(reinterpret_cast<PeriodicTask*>(argument));
|
auto* originalTask(reinterpret_cast<PeriodicTask*>(argument));
|
||||||
/* Task should not start until explicitly requested,
|
/* Task should not start until explicitly requested,
|
||||||
* but in FreeRTOS, tasks start as soon as they are created if the scheduler
|
* but in FreeRTOS, tasks start as soon as they are created if the scheduler
|
||||||
* is running but not if the scheduler is not running.
|
* is running but not if the scheduler is not running.
|
||||||
@ -36,7 +37,7 @@ void PeriodicTask::taskEntryPoint(void* argument) {
|
|||||||
* can continue */
|
* can continue */
|
||||||
|
|
||||||
if (not originalTask->started) {
|
if (not originalTask->started) {
|
||||||
vTaskSuspend(NULL);
|
vTaskSuspend(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
originalTask->taskFunctionality();
|
originalTask->taskFunctionality();
|
||||||
@ -62,13 +63,11 @@ ReturnValue_t PeriodicTask::sleepFor(uint32_t ms) {
|
|||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeriodicTask::taskFunctionality() {
|
[[noreturn]] void PeriodicTask::taskFunctionality() {
|
||||||
TickType_t xLastWakeTime;
|
TickType_t xLastWakeTime;
|
||||||
const TickType_t xPeriod = pdMS_TO_TICKS(this->period * 1000.);
|
const TickType_t xPeriod = pdMS_TO_TICKS(this->period * 1000.);
|
||||||
|
|
||||||
for (auto const& object : objectList) {
|
initObjsAfterTaskCreation();
|
||||||
object->initializeAfterTaskCreation();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The xLastWakeTime variable needs to be initialized with the current tick
|
/* The xLastWakeTime variable needs to be initialized with the current tick
|
||||||
count. Note that this is the only time the variable is written to
|
count. Note that this is the only time the variable is written to
|
||||||
@ -77,8 +76,8 @@ void PeriodicTask::taskFunctionality() {
|
|||||||
xLastWakeTime = xTaskGetTickCount();
|
xLastWakeTime = xTaskGetTickCount();
|
||||||
/* Enter the loop that defines the task behavior. */
|
/* Enter the loop that defines the task behavior. */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
for (auto const& object : objectList) {
|
for (auto const& objectPair : objectList) {
|
||||||
object->performOperation();
|
objectPair.first->performOperation(objectPair.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (tskKERNEL_VERSION_MAJOR == 10 && tskKERNEL_VERSION_MINOR >= 4) || tskKERNEL_VERSION_MAJOR > 10
|
#if (tskKERNEL_VERSION_MAJOR == 10 && tskKERNEL_VERSION_MINOR >= 4) || tskKERNEL_VERSION_MAJOR > 10
|
||||||
@ -95,32 +94,10 @@ void PeriodicTask::taskFunctionality() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t PeriodicTask::addComponent(object_id_t object) {
|
|
||||||
ExecutableObjectIF* newObject = ObjectManager::instance()->get<ExecutableObjectIF>(object);
|
|
||||||
return addComponent(newObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t PeriodicTask::addComponent(ExecutableObjectIF* object) {
|
|
||||||
if (object == nullptr) {
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::error << "PeriodicTask::addComponent: Invalid object. Make sure"
|
|
||||||
"it implement ExecutableObjectIF"
|
|
||||||
<< std::endl;
|
|
||||||
#endif
|
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
|
||||||
}
|
|
||||||
objectList.push_back(object);
|
|
||||||
object->setTaskIF(this);
|
|
||||||
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t PeriodicTask::getPeriodMs() const { return period * 1000; }
|
|
||||||
|
|
||||||
TaskHandle_t PeriodicTask::getTaskHandle() { return handle; }
|
TaskHandle_t PeriodicTask::getTaskHandle() { return handle; }
|
||||||
|
|
||||||
void PeriodicTask::handleMissedDeadline() {
|
void PeriodicTask::handleMissedDeadline() {
|
||||||
if (deadlineMissedFunc != nullptr) {
|
if (dlmFunc != nullptr) {
|
||||||
this->deadlineMissedFunc();
|
dlmFunc();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
#include "FreeRTOS.h"
|
#include "FreeRTOS.h"
|
||||||
#include "FreeRTOSTaskIF.h"
|
#include "FreeRTOSTaskIF.h"
|
||||||
#include "fsfw/objectmanager/ObjectManagerIF.h"
|
#include "fsfw/objectmanager/ObjectManagerIF.h"
|
||||||
#include "fsfw/tasks/PeriodicTaskIF.h"
|
#include "fsfw/tasks/PeriodicTaskBase.h"
|
||||||
#include "fsfw/tasks/Typedef.h"
|
#include "fsfw/tasks/definitions.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
|
||||||
class ExecutableObjectIF;
|
class ExecutableObjectIF;
|
||||||
@ -17,7 +17,7 @@ class ExecutableObjectIF;
|
|||||||
* periodic activities of multiple objects.
|
* periodic activities of multiple objects.
|
||||||
* @ingroup task_handling
|
* @ingroup task_handling
|
||||||
*/
|
*/
|
||||||
class PeriodicTask : public PeriodicTaskIF, public FreeRTOSTaskIF {
|
class PeriodicTask : public PeriodicTaskBase, public FreeRTOSTaskIF {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Keep in Mind that you need to call before this vTaskStartScheduler()!
|
* Keep in Mind that you need to call before this vTaskStartScheduler()!
|
||||||
@ -43,7 +43,7 @@ class PeriodicTask : public PeriodicTaskIF, public FreeRTOSTaskIF {
|
|||||||
* @brief Currently, the executed object's lifetime is not coupled with
|
* @brief Currently, the executed object's lifetime is not coupled with
|
||||||
* the task object's lifetime, so the destructor is empty.
|
* the task object's lifetime, so the destructor is empty.
|
||||||
*/
|
*/
|
||||||
virtual ~PeriodicTask(void);
|
~PeriodicTask() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The method to start the task.
|
* @brief The method to start the task.
|
||||||
@ -53,27 +53,6 @@ class PeriodicTask : public PeriodicTaskIF, public FreeRTOSTaskIF {
|
|||||||
* to the system call.
|
* to the system call.
|
||||||
*/
|
*/
|
||||||
ReturnValue_t startTask() override;
|
ReturnValue_t startTask() override;
|
||||||
/**
|
|
||||||
* Adds an object to the list of objects to be executed.
|
|
||||||
* The objects are executed in the order added.
|
|
||||||
* @param object Id of the object to add.
|
|
||||||
* @return
|
|
||||||
* -@c RETURN_OK on success
|
|
||||||
* -@c RETURN_FAILED if the object could not be added.
|
|
||||||
*/
|
|
||||||
ReturnValue_t addComponent(object_id_t object) override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds an object to the list of objects to be executed.
|
|
||||||
* The objects are executed in the order added.
|
|
||||||
* @param object Id of the object to add.
|
|
||||||
* @return
|
|
||||||
* -@c RETURN_OK on success
|
|
||||||
* -@c RETURN_FAILED if the object could not be added.
|
|
||||||
*/
|
|
||||||
ReturnValue_t addComponent(ExecutableObjectIF* object) override;
|
|
||||||
|
|
||||||
uint32_t getPeriodMs() const override;
|
|
||||||
|
|
||||||
ReturnValue_t sleepFor(uint32_t ms) override;
|
ReturnValue_t sleepFor(uint32_t ms) override;
|
||||||
|
|
||||||
@ -83,28 +62,6 @@ class PeriodicTask : public PeriodicTaskIF, public FreeRTOSTaskIF {
|
|||||||
bool started;
|
bool started;
|
||||||
TaskHandle_t handle;
|
TaskHandle_t handle;
|
||||||
|
|
||||||
//! Typedef for the List of objects.
|
|
||||||
typedef std::vector<ExecutableObjectIF*> ObjectList;
|
|
||||||
/**
|
|
||||||
* @brief This attribute holds a list of objects to be executed.
|
|
||||||
*/
|
|
||||||
ObjectList objectList;
|
|
||||||
/**
|
|
||||||
* @brief The period of the task.
|
|
||||||
* @details
|
|
||||||
* The period determines the frequency of the task's execution.
|
|
||||||
* It is expressed in clock ticks.
|
|
||||||
*/
|
|
||||||
TaskPeriod period;
|
|
||||||
/**
|
|
||||||
* @brief The pointer to the deadline-missed function.
|
|
||||||
* @details
|
|
||||||
* This pointer stores the function that is executed if the task's deadline
|
|
||||||
* is missed so each may react individually on a timing failure.
|
|
||||||
* The pointer may be NULL, then nothing happens on missing the deadline.
|
|
||||||
* The deadline is equal to the next execution of the periodic task.
|
|
||||||
*/
|
|
||||||
void (*deadlineMissedFunc)(void);
|
|
||||||
/**
|
/**
|
||||||
* @brief This is the function executed in the new task's context.
|
* @brief This is the function executed in the new task's context.
|
||||||
* @details
|
* @details
|
||||||
@ -125,7 +82,7 @@ class PeriodicTask : public PeriodicTaskIF, public FreeRTOSTaskIF {
|
|||||||
* the next period.
|
* the next period.
|
||||||
* On missing the deadline, the deadlineMissedFunction is executed.
|
* On missing the deadline, the deadlineMissedFunction is executed.
|
||||||
*/
|
*/
|
||||||
void taskFunctionality(void);
|
[[noreturn]] void taskFunctionality();
|
||||||
|
|
||||||
void handleMissedDeadline();
|
void handleMissedDeadline();
|
||||||
};
|
};
|
||||||
|
@ -1,27 +1,23 @@
|
|||||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
target_sources(
|
||||||
Clock.cpp
|
${LIB_FSFW_NAME}
|
||||||
FixedTimeslotTask.cpp
|
PRIVATE Clock.cpp
|
||||||
MessageQueue.cpp
|
FixedTimeslotTask.cpp
|
||||||
Mutex.cpp
|
MessageQueue.cpp
|
||||||
MutexFactory.cpp
|
Mutex.cpp
|
||||||
PeriodicTask.cpp
|
MutexFactory.cpp
|
||||||
QueueFactory.cpp
|
PeriodicTask.cpp
|
||||||
QueueMapManager.cpp
|
QueueFactory.cpp
|
||||||
SemaphoreFactory.cpp
|
QueueMapManager.cpp
|
||||||
TaskFactory.cpp
|
SemaphoreFactory.cpp
|
||||||
taskHelpers.cpp
|
TaskFactory.cpp
|
||||||
)
|
taskHelpers.cpp)
|
||||||
|
|
||||||
if(UNIX)
|
if(UNIX)
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
|
|
||||||
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
|
target_link_libraries(${LIB_FSFW_NAME} PRIVATE ${CMAKE_THREAD_LIBS_INIT})
|
||||||
${CMAKE_THREAD_LIBS_INIT}
|
|
||||||
)
|
|
||||||
if(NOT APPLE)
|
if(NOT APPLE)
|
||||||
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
|
target_link_libraries(${LIB_FSFW_NAME} PRIVATE rt)
|
||||||
rt
|
|
||||||
)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
@ -3,9 +3,7 @@
|
|||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include "fsfw/ipc/MutexFactory.h"
|
|
||||||
#include "fsfw/objectmanager/ObjectManager.h"
|
#include "fsfw/objectmanager/ObjectManager.h"
|
||||||
#include "fsfw/osal/host/FixedTimeslotTask.h"
|
|
||||||
#include "fsfw/osal/host/Mutex.h"
|
#include "fsfw/osal/host/Mutex.h"
|
||||||
#include "fsfw/osal/host/taskHelpers.h"
|
#include "fsfw/osal/host/taskHelpers.h"
|
||||||
#include "fsfw/platform.h"
|
#include "fsfw/platform.h"
|
||||||
@ -22,12 +20,8 @@
|
|||||||
|
|
||||||
FixedTimeslotTask::FixedTimeslotTask(const char* name, TaskPriority setPriority,
|
FixedTimeslotTask::FixedTimeslotTask(const char* name, TaskPriority setPriority,
|
||||||
TaskStackSize setStack, TaskPeriod setPeriod,
|
TaskStackSize setStack, TaskPeriod setPeriod,
|
||||||
void (*setDeadlineMissedFunc)())
|
TaskDeadlineMissedFunction dlmFunc_)
|
||||||
: started(false),
|
: FixedTimeslotTaskBase(setPeriod, dlmFunc_), started(false), taskName(name) {
|
||||||
pollingSeqTable(setPeriod * 1000),
|
|
||||||
taskName(name),
|
|
||||||
period(setPeriod),
|
|
||||||
deadlineMissedFunc(setDeadlineMissedFunc) {
|
|
||||||
// It is propably possible to set task priorities by using the native
|
// It is propably possible to set task priorities by using the native
|
||||||
// task handles for Windows / Linux
|
// task handles for Windows / Linux
|
||||||
mainThread = std::thread(&FixedTimeslotTask::taskEntryPoint, this, this);
|
mainThread = std::thread(&FixedTimeslotTask::taskEntryPoint, this, this);
|
||||||
@ -39,7 +33,7 @@ FixedTimeslotTask::FixedTimeslotTask(const char* name, TaskPriority setPriority,
|
|||||||
tasks::insertTaskName(mainThread.get_id(), taskName);
|
tasks::insertTaskName(mainThread.get_id(), taskName);
|
||||||
}
|
}
|
||||||
|
|
||||||
FixedTimeslotTask::~FixedTimeslotTask(void) {
|
FixedTimeslotTask::~FixedTimeslotTask() {
|
||||||
// Do not delete objects, we were responsible for ptrs only.
|
// Do not delete objects, we were responsible for ptrs only.
|
||||||
terminateThread = true;
|
terminateThread = true;
|
||||||
if (mainThread.joinable()) {
|
if (mainThread.joinable()) {
|
||||||
@ -48,7 +42,7 @@ FixedTimeslotTask::~FixedTimeslotTask(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FixedTimeslotTask::taskEntryPoint(void* argument) {
|
void FixedTimeslotTask::taskEntryPoint(void* argument) {
|
||||||
FixedTimeslotTask* originalTask(reinterpret_cast<FixedTimeslotTask*>(argument));
|
auto* originalTask(reinterpret_cast<FixedTimeslotTask*>(argument));
|
||||||
|
|
||||||
if (not originalTask->started) {
|
if (not originalTask->started) {
|
||||||
// we have to suspend/block here until the task is started.
|
// we have to suspend/block here until the task is started.
|
||||||
@ -81,7 +75,9 @@ ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FixedTimeslotTask::taskFunctionality() {
|
void FixedTimeslotTask::taskFunctionality() {
|
||||||
pollingSeqTable.intializeSequenceAfterTaskCreation();
|
ReturnValue_t result = pollingSeqTable.intializeSequenceAfterTaskCreation();
|
||||||
|
// Ignore returnvalue for now
|
||||||
|
static_cast<void>(result);
|
||||||
|
|
||||||
// A local iterator for the Polling Sequence Table is created to
|
// A local iterator for the Polling Sequence Table is created to
|
||||||
// find the start time for the first entry.
|
// find the start time for the first entry.
|
||||||
@ -106,37 +102,15 @@ void FixedTimeslotTask::taskFunctionality() {
|
|||||||
// we need to wait before executing the current slot
|
// we need to wait before executing the current slot
|
||||||
// this gives us the time to wait:
|
// this gives us the time to wait:
|
||||||
interval = chron_ms(this->pollingSeqTable.getIntervalToPreviousSlotMs());
|
interval = chron_ms(this->pollingSeqTable.getIntervalToPreviousSlotMs());
|
||||||
delayForInterval(¤tStartTime, interval);
|
if (not delayForInterval(¤tStartTime, interval)) {
|
||||||
// TODO deadline missed check
|
if (dlmFunc != nullptr) {
|
||||||
|
dlmFunc();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, uint32_t slotTimeMs,
|
|
||||||
int8_t executionStep) {
|
|
||||||
ExecutableObjectIF* executableObject =
|
|
||||||
ObjectManager::instance()->get<ExecutableObjectIF>(componentId);
|
|
||||||
if (executableObject != nullptr) {
|
|
||||||
pollingSeqTable.addSlot(componentId, slotTimeMs, executionStep, executableObject, this);
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::error << "Component " << std::hex << "0x" << componentId
|
|
||||||
<< "not found, "
|
|
||||||
"not adding it to PST.."
|
|
||||||
<< std::dec << std::endl;
|
|
||||||
#else
|
|
||||||
sif::printError("Component 0x%08x not found, not adding it to PST..\n",
|
|
||||||
static_cast<unsigned int>(componentId));
|
|
||||||
#endif
|
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t FixedTimeslotTask::checkSequence() const { return pollingSeqTable.checkSequence(); }
|
|
||||||
|
|
||||||
uint32_t FixedTimeslotTask::getPeriodMs() const { return period * 1000; }
|
|
||||||
|
|
||||||
bool FixedTimeslotTask::delayForInterval(chron_ms* previousWakeTimeMs, const chron_ms interval) {
|
bool FixedTimeslotTask::delayForInterval(chron_ms* previousWakeTimeMs, const chron_ms interval) {
|
||||||
bool shouldDelay = false;
|
bool shouldDelay = false;
|
||||||
// Get current wakeup time
|
// Get current wakeup time
|
||||||
|
@ -6,10 +6,10 @@
|
|||||||
#include <thread>
|
#include <thread>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "../../objectmanager/ObjectManagerIF.h"
|
#include "fsfw/objectmanager/ObjectManagerIF.h"
|
||||||
#include "../../tasks/FixedSlotSequence.h"
|
#include "fsfw/tasks/FixedSlotSequence.h"
|
||||||
#include "../../tasks/FixedTimeslotTaskIF.h"
|
#include "fsfw/tasks/FixedTimeslotTaskBase.h"
|
||||||
#include "../../tasks/Typedef.h"
|
#include "fsfw/tasks/definitions.h"
|
||||||
|
|
||||||
class ExecutableObjectIF;
|
class ExecutableObjectIF;
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ class ExecutableObjectIF;
|
|||||||
* @details
|
* @details
|
||||||
* @ingroup task_handling
|
* @ingroup task_handling
|
||||||
*/
|
*/
|
||||||
class FixedTimeslotTask : public FixedTimeslotTaskIF {
|
class FixedTimeslotTask : public FixedTimeslotTaskBase {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Standard constructor of the class.
|
* @brief Standard constructor of the class.
|
||||||
@ -39,7 +39,7 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF {
|
|||||||
* @brief Currently, the executed object's lifetime is not coupled with
|
* @brief Currently, the executed object's lifetime is not coupled with
|
||||||
* the task object's lifetime, so the destructor is empty.
|
* the task object's lifetime, so the destructor is empty.
|
||||||
*/
|
*/
|
||||||
virtual ~FixedTimeslotTask(void);
|
~FixedTimeslotTask() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The method to start the task.
|
* @brief The method to start the task.
|
||||||
@ -48,56 +48,22 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF {
|
|||||||
* The address of the task object is passed as an argument
|
* The address of the task object is passed as an argument
|
||||||
* to the system call.
|
* to the system call.
|
||||||
*/
|
*/
|
||||||
ReturnValue_t startTask(void);
|
ReturnValue_t startTask() override;
|
||||||
|
|
||||||
/**
|
ReturnValue_t sleepFor(uint32_t ms) override;
|
||||||
* Add timeslot to the polling sequence table.
|
|
||||||
* @param componentId
|
|
||||||
* @param slotTimeMs
|
|
||||||
* @param executionStep
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, int8_t executionStep);
|
|
||||||
|
|
||||||
ReturnValue_t checkSequence() const override;
|
|
||||||
|
|
||||||
uint32_t getPeriodMs() const;
|
|
||||||
|
|
||||||
ReturnValue_t sleepFor(uint32_t ms);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
using chron_ms = std::chrono::milliseconds;
|
using chron_ms = std::chrono::milliseconds;
|
||||||
|
|
||||||
bool started;
|
bool started;
|
||||||
//!< Typedef for the List of objects.
|
|
||||||
typedef std::vector<ExecutableObjectIF*> ObjectList;
|
|
||||||
std::thread mainThread;
|
std::thread mainThread;
|
||||||
std::atomic<bool> terminateThread{false};
|
std::atomic<bool> terminateThread{false};
|
||||||
|
|
||||||
//! Polling sequence table which contains the object to execute
|
|
||||||
//! and information like the timeslots and the passed execution step.
|
|
||||||
FixedSlotSequence pollingSeqTable;
|
|
||||||
|
|
||||||
std::condition_variable initCondition;
|
std::condition_variable initCondition;
|
||||||
std::mutex initMutex;
|
std::mutex initMutex;
|
||||||
std::string taskName;
|
std::string taskName;
|
||||||
/**
|
|
||||||
* @brief The period of the task.
|
|
||||||
* @details
|
|
||||||
* The period determines the frequency of the task's execution.
|
|
||||||
* It is expressed in clock ticks.
|
|
||||||
*/
|
|
||||||
TaskPeriod period;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The pointer to the deadline-missed function.
|
|
||||||
* @details
|
|
||||||
* This pointer stores the function that is executed if the task's deadline
|
|
||||||
* is missed. So, each may react individually on a timing failure.
|
|
||||||
* The pointer may be NULL, then nothing happens on missing the deadline.
|
|
||||||
* The deadline is equal to the next execution of the periodic task.
|
|
||||||
*/
|
|
||||||
void (*deadlineMissedFunc)(void);
|
|
||||||
/**
|
/**
|
||||||
* @brief This is the function executed in the new task's context.
|
* @brief This is the function executed in the new task's context.
|
||||||
* @details
|
* @details
|
||||||
@ -117,9 +83,9 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF {
|
|||||||
* the checkAndRestartPeriod system call blocks the task until the next
|
* the checkAndRestartPeriod system call blocks the task until the next
|
||||||
* period. On missing the deadline, the deadlineMissedFunction is executed.
|
* period. On missing the deadline, the deadlineMissedFunction is executed.
|
||||||
*/
|
*/
|
||||||
void taskFunctionality(void);
|
void taskFunctionality();
|
||||||
|
|
||||||
bool delayForInterval(chron_ms* previousWakeTimeMs, const chron_ms interval);
|
static bool delayForInterval(chron_ms* previousWakeTimeMs, chron_ms interval);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FRAMEWORK_OSAL_HOST_FIXEDTIMESLOTTASK_H_ */
|
#endif /* FRAMEWORK_OSAL_HOST_FIXEDTIMESLOTTASK_H_ */
|
||||||
|
@ -3,13 +3,10 @@
|
|||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include "fsfw/ipc/MutexFactory.h"
|
|
||||||
#include "fsfw/objectmanager/ObjectManager.h"
|
|
||||||
#include "fsfw/osal/host/Mutex.h"
|
#include "fsfw/osal/host/Mutex.h"
|
||||||
#include "fsfw/osal/host/taskHelpers.h"
|
#include "fsfw/osal/host/taskHelpers.h"
|
||||||
#include "fsfw/platform.h"
|
#include "fsfw/platform.h"
|
||||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||||
#include "fsfw/tasks/ExecutableObjectIF.h"
|
|
||||||
|
|
||||||
#if defined(PLATFORM_WIN)
|
#if defined(PLATFORM_WIN)
|
||||||
#include <processthreadsapi.h>
|
#include <processthreadsapi.h>
|
||||||
@ -20,8 +17,8 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
PeriodicTask::PeriodicTask(const char* name, TaskPriority setPriority, TaskStackSize setStack,
|
PeriodicTask::PeriodicTask(const char* name, TaskPriority setPriority, TaskStackSize setStack,
|
||||||
TaskPeriod setPeriod, void (*setDeadlineMissedFunc)())
|
TaskPeriod setPeriod, TaskDeadlineMissedFunction dlmFunc_)
|
||||||
: started(false), taskName(name), period(setPeriod), deadlineMissedFunc(setDeadlineMissedFunc) {
|
: PeriodicTaskBase(setPeriod, dlmFunc_), started(false), taskName(name) {
|
||||||
// It is probably possible to set task priorities by using the native
|
// It is probably possible to set task priorities by using the native
|
||||||
// task handles for Windows / Linux
|
// task handles for Windows / Linux
|
||||||
mainThread = std::thread(&PeriodicTask::taskEntryPoint, this, this);
|
mainThread = std::thread(&PeriodicTask::taskEntryPoint, this, this);
|
||||||
@ -33,7 +30,7 @@ PeriodicTask::PeriodicTask(const char* name, TaskPriority setPriority, TaskStack
|
|||||||
tasks::insertTaskName(mainThread.get_id(), taskName);
|
tasks::insertTaskName(mainThread.get_id(), taskName);
|
||||||
}
|
}
|
||||||
|
|
||||||
PeriodicTask::~PeriodicTask(void) {
|
PeriodicTask::~PeriodicTask() {
|
||||||
// Do not delete objects, we were responsible for ptrs only.
|
// Do not delete objects, we were responsible for ptrs only.
|
||||||
terminateThread = true;
|
terminateThread = true;
|
||||||
if (mainThread.joinable()) {
|
if (mainThread.joinable()) {
|
||||||
@ -42,7 +39,7 @@ PeriodicTask::~PeriodicTask(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PeriodicTask::taskEntryPoint(void* argument) {
|
void PeriodicTask::taskEntryPoint(void* argument) {
|
||||||
PeriodicTask* originalTask(reinterpret_cast<PeriodicTask*>(argument));
|
auto* originalTask(reinterpret_cast<PeriodicTask*>(argument));
|
||||||
|
|
||||||
if (not originalTask->started) {
|
if (not originalTask->started) {
|
||||||
// we have to suspend/block here until the task is started.
|
// we have to suspend/block here until the task is started.
|
||||||
@ -75,47 +72,27 @@ ReturnValue_t PeriodicTask::sleepFor(uint32_t ms) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PeriodicTask::taskFunctionality() {
|
void PeriodicTask::taskFunctionality() {
|
||||||
for (const auto& object : objectList) {
|
initObjsAfterTaskCreation();
|
||||||
object->initializeAfterTaskCreation();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::chrono::milliseconds periodChrono(static_cast<uint32_t>(period * 1000));
|
std::chrono::milliseconds periodChrono(static_cast<uint32_t>(period * 1000));
|
||||||
auto currentStartTime{std::chrono::duration_cast<std::chrono::milliseconds>(
|
auto currentStartTime{std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||||
std::chrono::system_clock::now().time_since_epoch())};
|
std::chrono::system_clock::now().time_since_epoch())};
|
||||||
auto nextStartTime{currentStartTime};
|
|
||||||
|
|
||||||
/* Enter the loop that defines the task behavior. */
|
/* Enter the loop that defines the task behavior. */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (terminateThread.load()) {
|
if (terminateThread.load()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
for (const auto& object : objectList) {
|
for (const auto& objectPair : objectList) {
|
||||||
object->performOperation();
|
objectPair.first->performOperation(objectPair.second);
|
||||||
}
|
}
|
||||||
if (not delayForInterval(¤tStartTime, periodChrono)) {
|
if (not delayForInterval(¤tStartTime, periodChrono)) {
|
||||||
if (deadlineMissedFunc != nullptr) {
|
if (dlmFunc != nullptr) {
|
||||||
this->deadlineMissedFunc();
|
this->dlmFunc();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t PeriodicTask::addComponent(object_id_t object) {
|
|
||||||
ExecutableObjectIF* newObject = ObjectManager::instance()->get<ExecutableObjectIF>(object);
|
|
||||||
return addComponent(newObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t PeriodicTask::addComponent(ExecutableObjectIF* object) {
|
|
||||||
if (object == nullptr) {
|
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
|
||||||
}
|
|
||||||
object->setTaskIF(this);
|
|
||||||
objectList.push_back(object);
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t PeriodicTask::getPeriodMs() const { return period * 1000; }
|
|
||||||
|
|
||||||
bool PeriodicTask::delayForInterval(chron_ms* previousWakeTimeMs, const chron_ms interval) {
|
bool PeriodicTask::delayForInterval(chron_ms* previousWakeTimeMs, const chron_ms interval) {
|
||||||
bool shouldDelay = false;
|
bool shouldDelay = false;
|
||||||
// Get current wakeup time
|
// Get current wakeup time
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
#include <thread>
|
#include <thread>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "../../objectmanager/ObjectManagerIF.h"
|
#include "fsfw/objectmanager/ObjectManagerIF.h"
|
||||||
#include "../../tasks/PeriodicTaskIF.h"
|
#include "fsfw/tasks/PeriodicTaskBase.h"
|
||||||
#include "../../tasks/Typedef.h"
|
#include "fsfw/tasks/definitions.h"
|
||||||
|
|
||||||
class ExecutableObjectIF;
|
class ExecutableObjectIF;
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ class ExecutableObjectIF;
|
|||||||
*
|
*
|
||||||
* @ingroup task_handling
|
* @ingroup task_handling
|
||||||
*/
|
*/
|
||||||
class PeriodicTask : public PeriodicTaskIF {
|
class PeriodicTask : public PeriodicTaskBase {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Standard constructor of the class.
|
* @brief Standard constructor of the class.
|
||||||
@ -34,12 +34,12 @@ class PeriodicTask : public PeriodicTaskIF {
|
|||||||
* assigned.
|
* assigned.
|
||||||
*/
|
*/
|
||||||
PeriodicTask(const char* name, TaskPriority setPriority, TaskStackSize setStack,
|
PeriodicTask(const char* name, TaskPriority setPriority, TaskStackSize setStack,
|
||||||
TaskPeriod setPeriod, void (*setDeadlineMissedFunc)());
|
TaskPeriod setPeriod, TaskDeadlineMissedFunction dlmFunc);
|
||||||
/**
|
/**
|
||||||
* @brief Currently, the executed object's lifetime is not coupled with
|
* @brief Currently, the executed object's lifetime is not coupled with
|
||||||
* the task object's lifetime, so the destructor is empty.
|
* the task object's lifetime, so the destructor is empty.
|
||||||
*/
|
*/
|
||||||
virtual ~PeriodicTask(void);
|
~PeriodicTask() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The method to start the task.
|
* @brief The method to start the task.
|
||||||
@ -48,63 +48,20 @@ class PeriodicTask : public PeriodicTaskIF {
|
|||||||
* The address of the task object is passed as an argument
|
* The address of the task object is passed as an argument
|
||||||
* to the system call.
|
* to the system call.
|
||||||
*/
|
*/
|
||||||
ReturnValue_t startTask(void);
|
ReturnValue_t startTask() override;
|
||||||
/**
|
|
||||||
* Adds an object to the list of objects to be executed.
|
|
||||||
* The objects are executed in the order added.
|
|
||||||
* @param object Id of the object to add.
|
|
||||||
* @return
|
|
||||||
* -@c RETURN_OK on success
|
|
||||||
* -@c RETURN_FAILED if the object could not be added.
|
|
||||||
*/
|
|
||||||
ReturnValue_t addComponent(object_id_t object);
|
|
||||||
|
|
||||||
/**
|
ReturnValue_t sleepFor(uint32_t ms) override;
|
||||||
* Adds an object to the list of objects to be executed.
|
|
||||||
* The objects are executed in the order added.
|
|
||||||
* @param object pointer to the object to add.
|
|
||||||
* @return
|
|
||||||
* -@c RETURN_OK on success
|
|
||||||
* -@c RETURN_FAILED if the object could not be added.
|
|
||||||
*/
|
|
||||||
ReturnValue_t addComponent(ExecutableObjectIF* object);
|
|
||||||
|
|
||||||
uint32_t getPeriodMs() const;
|
|
||||||
|
|
||||||
ReturnValue_t sleepFor(uint32_t ms);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
using chron_ms = std::chrono::milliseconds;
|
using chron_ms = std::chrono::milliseconds;
|
||||||
bool started;
|
bool started;
|
||||||
//!< Typedef for the List of objects.
|
|
||||||
typedef std::vector<ExecutableObjectIF*> ObjectList;
|
|
||||||
std::thread mainThread;
|
std::thread mainThread;
|
||||||
std::atomic<bool> terminateThread{false};
|
std::atomic<bool> terminateThread{false};
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This attribute holds a list of objects to be executed.
|
|
||||||
*/
|
|
||||||
ObjectList objectList;
|
|
||||||
|
|
||||||
std::condition_variable initCondition;
|
std::condition_variable initCondition;
|
||||||
std::mutex initMutex;
|
std::mutex initMutex;
|
||||||
std::string taskName;
|
std::string taskName;
|
||||||
/**
|
|
||||||
* @brief The period of the task.
|
|
||||||
* @details
|
|
||||||
* The period determines the frequency of the task's execution.
|
|
||||||
* It is expressed in clock ticks.
|
|
||||||
*/
|
|
||||||
TaskPeriod period;
|
|
||||||
/**
|
|
||||||
* @brief The pointer to the deadline-missed function.
|
|
||||||
* @details
|
|
||||||
* This pointer stores the function that is executed if the task's deadline
|
|
||||||
* is missed. So, each may react individually on a timing failure.
|
|
||||||
* The pointer may be NULL, then nothing happens on missing the deadline.
|
|
||||||
* The deadline is equal to the next execution of the periodic task.
|
|
||||||
*/
|
|
||||||
void (*deadlineMissedFunc)(void);
|
|
||||||
/**
|
/**
|
||||||
* @brief This is the function executed in the new task's context.
|
* @brief This is the function executed in the new task's context.
|
||||||
* @details
|
* @details
|
||||||
@ -124,9 +81,9 @@ class PeriodicTask : public PeriodicTaskIF {
|
|||||||
* the checkAndRestartPeriod system call blocks the task until the next
|
* the checkAndRestartPeriod system call blocks the task until the next
|
||||||
* period. On missing the deadline, the deadlineMissedFunction is executed.
|
* period. On missing the deadline, the deadlineMissedFunction is executed.
|
||||||
*/
|
*/
|
||||||
void taskFunctionality(void);
|
void taskFunctionality();
|
||||||
|
|
||||||
bool delayForInterval(chron_ms* previousWakeTimeMs, const chron_ms interval);
|
static bool delayForInterval(chron_ms* previousWakeTimeMs, chron_ms interval);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* PERIODICTASK_H_ */
|
#endif /* FRAMEWORK_OSAL_HOST_PERIODICTASK_H_ */
|
||||||
|
@ -14,9 +14,9 @@ TaskFactory* TaskFactory::factoryInstance = new TaskFactory();
|
|||||||
// Not used for the host implementation for now because C++ thread abstraction is used
|
// Not used for the host implementation for now because C++ thread abstraction is used
|
||||||
const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = 0;
|
const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = 0;
|
||||||
|
|
||||||
TaskFactory::TaskFactory() {}
|
TaskFactory::TaskFactory() = default;
|
||||||
|
|
||||||
TaskFactory::~TaskFactory() {}
|
TaskFactory::~TaskFactory() = default;
|
||||||
|
|
||||||
TaskFactory* TaskFactory::instance() { return TaskFactory::factoryInstance; }
|
TaskFactory* TaskFactory::instance() { return TaskFactory::factoryInstance; }
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
std::mutex nameMapLock;
|
std::mutex nameMapLock;
|
||||||
std::map<std::thread::id, std::string> taskNameMap;
|
std::map<std::thread::id, std::string> taskNameMap;
|
||||||
|
|
||||||
ReturnValue_t tasks::insertTaskName(std::thread::id threadId, std::string taskName) {
|
ReturnValue_t tasks::insertTaskName(std::thread::id threadId, const std::string& taskName) {
|
||||||
std::lock_guard<std::mutex> lg(nameMapLock);
|
std::lock_guard<std::mutex> lg(nameMapLock);
|
||||||
auto returnPair = taskNameMap.emplace(threadId, taskName);
|
auto returnPair = taskNameMap.emplace(threadId, taskName);
|
||||||
if (not returnPair.second) {
|
if (not returnPair.second) {
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
namespace tasks {
|
namespace tasks {
|
||||||
|
|
||||||
ReturnValue_t insertTaskName(std::thread::id threadId, std::string taskName);
|
ReturnValue_t insertTaskName(std::thread::id threadId, const std::string& taskName);
|
||||||
std::string getTaskName(std::thread::id threadId);
|
std::string getTaskName(std::thread::id threadId);
|
||||||
|
|
||||||
} // namespace tasks
|
} // namespace tasks
|
||||||
|
@ -1,29 +1,25 @@
|
|||||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
target_sources(
|
||||||
Clock.cpp
|
${LIB_FSFW_NAME}
|
||||||
BinarySemaphore.cpp
|
PRIVATE Clock.cpp
|
||||||
CountingSemaphore.cpp
|
BinarySemaphore.cpp
|
||||||
FixedTimeslotTask.cpp
|
CountingSemaphore.cpp
|
||||||
InternalErrorCodes.cpp
|
FixedTimeslotTask.cpp
|
||||||
MessageQueue.cpp
|
InternalErrorCodes.cpp
|
||||||
Mutex.cpp
|
MessageQueue.cpp
|
||||||
MutexFactory.cpp
|
Mutex.cpp
|
||||||
PeriodicPosixTask.cpp
|
MutexFactory.cpp
|
||||||
PosixThread.cpp
|
PeriodicPosixTask.cpp
|
||||||
QueueFactory.cpp
|
PosixThread.cpp
|
||||||
SemaphoreFactory.cpp
|
QueueFactory.cpp
|
||||||
TaskFactory.cpp
|
SemaphoreFactory.cpp
|
||||||
tcpipHelpers.cpp
|
TaskFactory.cpp
|
||||||
unixUtility.cpp
|
tcpipHelpers.cpp
|
||||||
)
|
unixUtility.cpp)
|
||||||
|
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
|
|
||||||
target_link_libraries(${LIB_FSFW_NAME} PUBLIC
|
target_link_libraries(${LIB_FSFW_NAME} PUBLIC ${CMAKE_THREAD_LIBS_INIT})
|
||||||
${CMAKE_THREAD_LIBS_INIT}
|
|
||||||
)
|
|
||||||
|
|
||||||
if(NOT APPLE)
|
if(NOT APPLE)
|
||||||
target_link_libraries(${LIB_FSFW_NAME} PUBLIC
|
target_link_libraries(${LIB_FSFW_NAME} PUBLIC rt)
|
||||||
rt
|
|
||||||
)
|
|
||||||
endif()
|
endif()
|
||||||
|
@ -1,22 +1,20 @@
|
|||||||
#include "fsfw/osal/linux/FixedTimeslotTask.h"
|
#include "fsfw/osal/linux/FixedTimeslotTask.h"
|
||||||
|
|
||||||
#include <limits.h>
|
#include <climits>
|
||||||
|
|
||||||
#include "fsfw/objectmanager/ObjectManager.h"
|
|
||||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||||
|
|
||||||
uint32_t FixedTimeslotTask::deadlineMissedCount = 0;
|
|
||||||
const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = PTHREAD_STACK_MIN;
|
const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = PTHREAD_STACK_MIN;
|
||||||
|
|
||||||
FixedTimeslotTask::FixedTimeslotTask(const char* name_, int priority_, size_t stackSize_,
|
FixedTimeslotTask::FixedTimeslotTask(const char* name_, TaskPriority priority_, size_t stackSize_,
|
||||||
uint32_t periodMs_)
|
TaskPeriod periodSeconds_, TaskDeadlineMissedFunction dlmFunc_)
|
||||||
: PosixThread(name_, priority_, stackSize_), pst(periodMs_), started(false) {}
|
: FixedTimeslotTaskBase(periodSeconds_, dlmFunc_),
|
||||||
|
posixThread(name_, priority_, stackSize_),
|
||||||
FixedTimeslotTask::~FixedTimeslotTask() {}
|
started(false) {}
|
||||||
|
|
||||||
void* FixedTimeslotTask::taskEntryPoint(void* arg) {
|
void* FixedTimeslotTask::taskEntryPoint(void* arg) {
|
||||||
// The argument is re-interpreted as PollingTask.
|
// The argument is re-interpreted as PollingTask.
|
||||||
FixedTimeslotTask* originalTask(reinterpret_cast<FixedTimeslotTask*>(arg));
|
auto* originalTask(reinterpret_cast<FixedTimeslotTask*>(arg));
|
||||||
// The task's functionality is called.
|
// The task's functionality is called.
|
||||||
originalTask->taskFunctionality();
|
originalTask->taskFunctionality();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -24,7 +22,7 @@ void* FixedTimeslotTask::taskEntryPoint(void* arg) {
|
|||||||
|
|
||||||
ReturnValue_t FixedTimeslotTask::startTask() {
|
ReturnValue_t FixedTimeslotTask::startTask() {
|
||||||
started = true;
|
started = true;
|
||||||
createTask(&taskEntryPoint, this);
|
posixThread.createTask(&taskEntryPoint, this);
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,63 +30,36 @@ ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) {
|
|||||||
return PosixThread::sleep((uint64_t)ms * 1000000);
|
return PosixThread::sleep((uint64_t)ms * 1000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t FixedTimeslotTask::getPeriodMs() const { return pst.getLengthMs(); }
|
[[noreturn]] void FixedTimeslotTask::taskFunctionality() {
|
||||||
|
|
||||||
ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, uint32_t slotTimeMs,
|
|
||||||
int8_t executionStep) {
|
|
||||||
ExecutableObjectIF* executableObject =
|
|
||||||
ObjectManager::instance()->get<ExecutableObjectIF>(componentId);
|
|
||||||
if (executableObject != nullptr) {
|
|
||||||
pst.addSlot(componentId, slotTimeMs, executionStep, executableObject, this);
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::error << "Component " << std::hex << componentId << " not found, not adding it to pst"
|
|
||||||
<< std::dec << std::endl;
|
|
||||||
#endif
|
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t FixedTimeslotTask::checkSequence() const { return pst.checkSequence(); }
|
|
||||||
|
|
||||||
void FixedTimeslotTask::taskFunctionality() {
|
|
||||||
// Like FreeRTOS pthreads are running as soon as they are created
|
// Like FreeRTOS pthreads are running as soon as they are created
|
||||||
if (!started) {
|
if (!started) {
|
||||||
suspend();
|
posixThread.suspend();
|
||||||
}
|
}
|
||||||
|
|
||||||
pst.intializeSequenceAfterTaskCreation();
|
// Returnvalue ignored for now
|
||||||
|
static_cast<void>(pollingSeqTable.intializeSequenceAfterTaskCreation());
|
||||||
|
|
||||||
// The start time for the first entry is read.
|
// The start time for the first entry is read.
|
||||||
uint64_t lastWakeTime = getCurrentMonotonicTimeMs();
|
uint64_t lastWakeTime = PosixThread::getCurrentMonotonicTimeMs();
|
||||||
uint64_t interval = pst.getIntervalToNextSlotMs();
|
uint32_t interval = 0;
|
||||||
|
|
||||||
// The task's "infinite" inner loop is entered.
|
// The task's "infinite" inner loop is entered.
|
||||||
while (1) {
|
while (true) {
|
||||||
if (pst.slotFollowsImmediately()) {
|
if (pollingSeqTable.slotFollowsImmediately()) {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
} else {
|
} else {
|
||||||
// The interval for the next polling slot is selected.
|
// The interval for the next polling slot is selected.
|
||||||
interval = this->pst.getIntervalToPreviousSlotMs();
|
interval = pollingSeqTable.getIntervalToPreviousSlotMs();
|
||||||
// The period is checked and restarted with the new interval.
|
// The period is checked and restarted with the new interval.
|
||||||
// If the deadline was missed, the deadlineMissedFunc is called.
|
// If the deadline was missed, the deadlineMissedFunc is called.
|
||||||
if (!PosixThread::delayUntil(&lastWakeTime, interval)) {
|
if (!PosixThread::delayUntil(&lastWakeTime, interval)) {
|
||||||
// No time left on timer -> we missed the deadline
|
// No time left on timer -> we missed the deadline
|
||||||
missedDeadlineCounter();
|
if(dlmFunc != nullptr){
|
||||||
|
dlmFunc();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// The device handler for this slot is executed and the next one is chosen.
|
// The device handler for this slot is executed and the next one is chosen.
|
||||||
this->pst.executeAndAdvance();
|
pollingSeqTable.executeAndAdvance();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FixedTimeslotTask::missedDeadlineCounter() {
|
|
||||||
FixedTimeslotTask::deadlineMissedCount++;
|
|
||||||
if (FixedTimeslotTask::deadlineMissedCount % 10 == 0) {
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::error << "PST missed " << FixedTimeslotTask::deadlineMissedCount << " deadlines."
|
|
||||||
<< std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,11 +3,12 @@
|
|||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
#include "../../tasks/FixedSlotSequence.h"
|
|
||||||
#include "../../tasks/FixedTimeslotTaskIF.h"
|
|
||||||
#include "PosixThread.h"
|
#include "PosixThread.h"
|
||||||
|
#include "fsfw/tasks/FixedSlotSequence.h"
|
||||||
|
#include "fsfw/tasks/FixedTimeslotTaskBase.h"
|
||||||
|
#include "fsfw/tasks/definitions.h"
|
||||||
|
|
||||||
class FixedTimeslotTask : public FixedTimeslotTaskIF, public PosixThread {
|
class FixedTimeslotTask : public FixedTimeslotTaskBase {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Create a generic periodic task.
|
* Create a generic periodic task.
|
||||||
@ -21,29 +22,13 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF, public PosixThread {
|
|||||||
* @param period_
|
* @param period_
|
||||||
* @param deadlineMissedFunc_
|
* @param deadlineMissedFunc_
|
||||||
*/
|
*/
|
||||||
FixedTimeslotTask(const char* name_, int priority_, size_t stackSize_, uint32_t periodMs_);
|
FixedTimeslotTask(const char* name_, TaskPriority priority_, size_t stackSize_,
|
||||||
virtual ~FixedTimeslotTask();
|
TaskPeriod periodSeconds_, TaskDeadlineMissedFunction dlmFunc_);
|
||||||
|
~FixedTimeslotTask() override = default;
|
||||||
|
|
||||||
virtual ReturnValue_t startTask();
|
ReturnValue_t startTask() override;
|
||||||
|
|
||||||
virtual ReturnValue_t sleepFor(uint32_t ms);
|
ReturnValue_t sleepFor(uint32_t ms) override;
|
||||||
|
|
||||||
virtual uint32_t getPeriodMs() const;
|
|
||||||
|
|
||||||
virtual ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, int8_t executionStep);
|
|
||||||
|
|
||||||
virtual ReturnValue_t checkSequence() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This static function can be used as #deadlineMissedFunc.
|
|
||||||
* It counts missedDeadlines and prints the number of missed deadlines every 10th time.
|
|
||||||
*/
|
|
||||||
static void missedDeadlineCounter();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A helper variable to count missed deadlines.
|
|
||||||
*/
|
|
||||||
static uint32_t deadlineMissedCount;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
@ -53,9 +38,12 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF, public PosixThread {
|
|||||||
* It links the functionalities provided by FixedSlotSequence with the
|
* It links the functionalities provided by FixedSlotSequence with the
|
||||||
* OS's System Calls to keep the timing of the periods.
|
* OS's System Calls to keep the timing of the periods.
|
||||||
*/
|
*/
|
||||||
virtual void taskFunctionality();
|
[[noreturn]] virtual void taskFunctionality();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
PosixThread posixThread;
|
||||||
|
bool started;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This is the entry point in a new thread.
|
* @brief This is the entry point in a new thread.
|
||||||
*
|
*
|
||||||
@ -68,9 +56,6 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF, public PosixThread {
|
|||||||
* arbitrary data.
|
* arbitrary data.
|
||||||
*/
|
*/
|
||||||
static void* taskEntryPoint(void* arg);
|
static void* taskEntryPoint(void* arg);
|
||||||
FixedSlotSequence pst;
|
|
||||||
|
|
||||||
bool started;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_OSAL_LINUX_FIXEDTIMESLOTTASK_H_ */
|
#endif /* FSFW_OSAL_LINUX_FIXEDTIMESLOTTASK_H_ */
|
||||||
|
@ -1,86 +1,54 @@
|
|||||||
#include "fsfw/osal/linux/PeriodicPosixTask.h"
|
#include "PeriodicPosixTask.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include "fsfw/serviceinterface.h"
|
||||||
|
|
||||||
#include "fsfw/objectmanager/ObjectManager.h"
|
|
||||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
|
||||||
#include "fsfw/tasks/ExecutableObjectIF.h"
|
#include "fsfw/tasks/ExecutableObjectIF.h"
|
||||||
|
|
||||||
PeriodicPosixTask::PeriodicPosixTask(const char* name_, int priority_, size_t stackSize_,
|
PeriodicPosixTask::PeriodicPosixTask(const char* name_, int priority_, size_t stackSize_,
|
||||||
uint32_t period_, void(deadlineMissedFunc_)())
|
TaskPeriod period_, TaskDeadlineMissedFunction dlmFunc_)
|
||||||
: PosixThread(name_, priority_, stackSize_),
|
: PeriodicTaskBase(period_, dlmFunc_),
|
||||||
objectList(),
|
posixThread(name_, priority_, stackSize_),
|
||||||
started(false),
|
started(false) {}
|
||||||
periodMs(period_),
|
|
||||||
deadlineMissedFunc(deadlineMissedFunc_) {}
|
|
||||||
|
|
||||||
PeriodicPosixTask::~PeriodicPosixTask() {
|
|
||||||
// Not Implemented
|
|
||||||
}
|
|
||||||
|
|
||||||
void* PeriodicPosixTask::taskEntryPoint(void* arg) {
|
void* PeriodicPosixTask::taskEntryPoint(void* arg) {
|
||||||
// The argument is re-interpreted as PollingTask.
|
// The argument is re-interpreted as PollingTask.
|
||||||
PeriodicPosixTask* originalTask(reinterpret_cast<PeriodicPosixTask*>(arg));
|
auto* originalTask(reinterpret_cast<PeriodicPosixTask*>(arg));
|
||||||
// The task's functionality is called.
|
// The task's functionality is called.
|
||||||
originalTask->taskFunctionality();
|
originalTask->taskFunctionality();
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t PeriodicPosixTask::addComponent(object_id_t object) {
|
|
||||||
ExecutableObjectIF* newObject = ObjectManager::instance()->get<ExecutableObjectIF>(object);
|
|
||||||
return addComponent(newObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t PeriodicPosixTask::addComponent(ExecutableObjectIF* object) {
|
|
||||||
if (object == nullptr) {
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::error << "PeriodicTask::addComponent: Invalid object. Make sure"
|
|
||||||
<< " it implements ExecutableObjectIF!" << std::endl;
|
|
||||||
#else
|
|
||||||
sif::printError(
|
|
||||||
"PeriodicTask::addComponent: Invalid object. Make sure it "
|
|
||||||
"implements ExecutableObjectIF!\n");
|
|
||||||
#endif
|
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
|
||||||
}
|
|
||||||
objectList.push_back(object);
|
|
||||||
object->setTaskIF(this);
|
|
||||||
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t PeriodicPosixTask::sleepFor(uint32_t ms) {
|
ReturnValue_t PeriodicPosixTask::sleepFor(uint32_t ms) {
|
||||||
return PosixThread::sleep((uint64_t)ms * 1000000);
|
return PosixThread::sleep(static_cast<uint64_t>(ms) * 1000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t PeriodicPosixTask::startTask(void) {
|
ReturnValue_t PeriodicPosixTask::startTask() {
|
||||||
|
if (isEmpty()) {
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
started = true;
|
started = true;
|
||||||
PosixThread::createTask(&taskEntryPoint, this);
|
posixThread.createTask(&taskEntryPoint, this);
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeriodicPosixTask::taskFunctionality(void) {
|
[[noreturn]] void PeriodicPosixTask::taskFunctionality() {
|
||||||
if (not started) {
|
if (not started) {
|
||||||
suspend();
|
posixThread.suspend();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto const& object : objectList) {
|
initObjsAfterTaskCreation();
|
||||||
object->initializeAfterTaskCreation();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t lastWakeTime = getCurrentMonotonicTimeMs();
|
uint64_t lastWakeTime = PosixThread::getCurrentMonotonicTimeMs();
|
||||||
|
uint64_t periodMs = getPeriodMs();
|
||||||
// The task's "infinite" inner loop is entered.
|
// The task's "infinite" inner loop is entered.
|
||||||
while (1) {
|
while (true) {
|
||||||
for (auto const& object : objectList) {
|
for (auto const& objOpCodePair : objectList) {
|
||||||
object->performOperation();
|
objOpCodePair.first->performOperation(objOpCodePair.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (not PosixThread::delayUntil(&lastWakeTime, periodMs)) {
|
if (not PosixThread::delayUntil(&lastWakeTime, periodMs)) {
|
||||||
if (this->deadlineMissedFunc != nullptr) {
|
if (dlmFunc != nullptr) {
|
||||||
this->deadlineMissedFunc();
|
dlmFunc();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t PeriodicPosixTask::getPeriodMs() const { return periodMs; }
|
|
||||||
|
@ -3,12 +3,13 @@
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "../../objectmanager/ObjectManagerIF.h"
|
|
||||||
#include "../../tasks/ExecutableObjectIF.h"
|
|
||||||
#include "../../tasks/PeriodicTaskIF.h"
|
|
||||||
#include "PosixThread.h"
|
#include "PosixThread.h"
|
||||||
|
#include "fsfw/objectmanager/ObjectManagerIF.h"
|
||||||
|
#include "fsfw/tasks/ExecutableObjectIF.h"
|
||||||
|
#include "fsfw/tasks/PeriodicTaskBase.h"
|
||||||
|
#include "fsfw/tasks/PeriodicTaskIF.h"
|
||||||
|
|
||||||
class PeriodicPosixTask : public PosixThread, public PeriodicTaskIF {
|
class PeriodicPosixTask : public PeriodicTaskBase {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Create a generic periodic task.
|
* Create a generic periodic task.
|
||||||
@ -22,9 +23,9 @@ class PeriodicPosixTask : public PosixThread, public PeriodicTaskIF {
|
|||||||
* @param period_
|
* @param period_
|
||||||
* @param deadlineMissedFunc_
|
* @param deadlineMissedFunc_
|
||||||
*/
|
*/
|
||||||
PeriodicPosixTask(const char* name_, int priority_, size_t stackSize_, uint32_t period_,
|
PeriodicPosixTask(const char* name_, int priority_, size_t stackSize_, TaskPeriod period_,
|
||||||
void (*deadlineMissedFunc_)());
|
TaskDeadlineMissedFunction dlmFunc_);
|
||||||
virtual ~PeriodicPosixTask();
|
~PeriodicPosixTask() override = default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The method to start the task.
|
* @brief The method to start the task.
|
||||||
@ -34,42 +35,17 @@ class PeriodicPosixTask : public PosixThread, public PeriodicTaskIF {
|
|||||||
* to the system call.
|
* to the system call.
|
||||||
*/
|
*/
|
||||||
ReturnValue_t startTask() override;
|
ReturnValue_t startTask() override;
|
||||||
/**
|
|
||||||
* Adds an object to the list of objects to be executed.
|
|
||||||
* The objects are executed in the order added.
|
|
||||||
* @param object Id of the object to add.
|
|
||||||
* @return RETURN_OK on success, RETURN_FAILED if the object could not be added.
|
|
||||||
*/
|
|
||||||
ReturnValue_t addComponent(object_id_t object) override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds an object to the list of objects to be executed.
|
|
||||||
* The objects are executed in the order added.
|
|
||||||
* @param object pointer to the object to add.
|
|
||||||
* @return RETURN_OK on success, RETURN_FAILED if the object could not be added.
|
|
||||||
*/
|
|
||||||
ReturnValue_t addComponent(ExecutableObjectIF* object) override;
|
|
||||||
|
|
||||||
uint32_t getPeriodMs() const override;
|
|
||||||
|
|
||||||
ReturnValue_t sleepFor(uint32_t ms) override;
|
ReturnValue_t sleepFor(uint32_t ms) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::vector<ExecutableObjectIF*> ObjectList; //!< Typedef for the List of objects.
|
PosixThread posixThread;
|
||||||
/**
|
|
||||||
* @brief This attribute holds a list of objects to be executed.
|
|
||||||
*/
|
|
||||||
ObjectList objectList;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Flag to indicate that the task was started and is allowed to run
|
* @brief Flag to indicate that the task was started and is allowed to run
|
||||||
*/
|
*/
|
||||||
bool started;
|
bool started;
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Period of the task in milliseconds
|
|
||||||
*/
|
|
||||||
uint32_t periodMs;
|
|
||||||
/**
|
/**
|
||||||
* @brief The function containing the actual functionality of the task.
|
* @brief The function containing the actual functionality of the task.
|
||||||
* @details The method sets and starts
|
* @details The method sets and starts
|
||||||
@ -78,7 +54,7 @@ class PeriodicPosixTask : public PosixThread, public PeriodicTaskIF {
|
|||||||
* will be blocked until the next period. On missing the deadline, the deadlineMissedFunction is
|
* will be blocked until the next period. On missing the deadline, the deadlineMissedFunction is
|
||||||
* executed.
|
* executed.
|
||||||
*/
|
*/
|
||||||
virtual void taskFunctionality(void);
|
[[noreturn]] virtual void taskFunctionality();
|
||||||
/**
|
/**
|
||||||
* @brief This is the entry point in a new thread.
|
* @brief This is the entry point in a new thread.
|
||||||
*
|
*
|
||||||
@ -86,14 +62,6 @@ class PeriodicPosixTask : public PosixThread, public PeriodicTaskIF {
|
|||||||
* of the child class. Needs a valid pointer to the derived class.
|
* of the child class. Needs a valid pointer to the derived class.
|
||||||
*/
|
*/
|
||||||
static void* taskEntryPoint(void* arg);
|
static void* taskEntryPoint(void* arg);
|
||||||
/**
|
|
||||||
* @brief The pointer to the deadline-missed function.
|
|
||||||
* @details This pointer stores the function that is executed if the task's deadline is missed.
|
|
||||||
* So, each may react individually on a timing failure. The pointer may be
|
|
||||||
* NULL, then nothing happens on missing the deadline. The deadline is equal to the next execution
|
|
||||||
* of the periodic task.
|
|
||||||
*/
|
|
||||||
void (*deadlineMissedFunc)();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FRAMEWORK_OSAL_LINUX_PERIODICPOSIXTASK_H_ */
|
#endif /* FRAMEWORK_OSAL_LINUX_PERIODICPOSIXTASK_H_ */
|
||||||
|
@ -35,6 +35,21 @@ class PosixThread {
|
|||||||
*/
|
*/
|
||||||
void resume();
|
void resume();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Function that has to be called by derived class because the
|
||||||
|
* derived class pointer has to be valid as argument.
|
||||||
|
* @details
|
||||||
|
* This function creates a pthread with the given parameters. As the
|
||||||
|
* function requires a pointer to the derived object it has to be called
|
||||||
|
* after the this pointer of the derived object is valid.
|
||||||
|
* Sets the taskEntryPoint as function to be called by new a thread.
|
||||||
|
* @param fnc_ Function which will be executed by the thread.
|
||||||
|
* @param arg_
|
||||||
|
* argument of the taskEntryPoint function, needs to be this pointer
|
||||||
|
* of derived class
|
||||||
|
*/
|
||||||
|
void createTask(void* (*fnc_)(void*), void* arg_);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delay function similar to FreeRtos delayUntil function
|
* Delay function similar to FreeRtos delayUntil function
|
||||||
*
|
*
|
||||||
@ -55,21 +70,6 @@ class PosixThread {
|
|||||||
protected:
|
protected:
|
||||||
pthread_t thread;
|
pthread_t thread;
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Function that has to be called by derived class because the
|
|
||||||
* derived class pointer has to be valid as argument.
|
|
||||||
* @details
|
|
||||||
* This function creates a pthread with the given parameters. As the
|
|
||||||
* function requires a pointer to the derived object it has to be called
|
|
||||||
* after the this pointer of the derived object is valid.
|
|
||||||
* Sets the taskEntryPoint as function to be called by new a thread.
|
|
||||||
* @param fnc_ Function which will be executed by the thread.
|
|
||||||
* @param arg_
|
|
||||||
* argument of the taskEntryPoint function, needs to be this pointer
|
|
||||||
* of derived class
|
|
||||||
*/
|
|
||||||
void createTask(void* (*fnc_)(void*), void* arg_);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char name[PTHREAD_MAX_NAMELEN];
|
char name[PTHREAD_MAX_NAMELEN];
|
||||||
int priority;
|
int priority;
|
||||||
|
@ -8,21 +8,22 @@
|
|||||||
// TODO: Different variant than the lazy loading in QueueFactory. What's better and why?
|
// TODO: Different variant than the lazy loading in QueueFactory. What's better and why?
|
||||||
TaskFactory* TaskFactory::factoryInstance = new TaskFactory();
|
TaskFactory* TaskFactory::factoryInstance = new TaskFactory();
|
||||||
|
|
||||||
TaskFactory::~TaskFactory() {}
|
TaskFactory::~TaskFactory() = default;
|
||||||
|
|
||||||
TaskFactory* TaskFactory::instance() { return TaskFactory::factoryInstance; }
|
TaskFactory* TaskFactory::instance() { return TaskFactory::factoryInstance; }
|
||||||
|
|
||||||
PeriodicTaskIF* TaskFactory::createPeriodicTask(
|
PeriodicTaskIF* TaskFactory::createPeriodicTask(
|
||||||
TaskName name_, TaskPriority taskPriority_, TaskStackSize stackSize_,
|
TaskName name_, TaskPriority taskPriority_, TaskStackSize stackSize_,
|
||||||
TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_) {
|
TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_) {
|
||||||
return new PeriodicPosixTask(name_, taskPriority_, stackSize_, periodInSeconds_ * 1000,
|
return new PeriodicPosixTask(name_, taskPriority_, stackSize_, periodInSeconds_,
|
||||||
deadLineMissedFunction_);
|
deadLineMissedFunction_);
|
||||||
}
|
}
|
||||||
|
|
||||||
FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask(
|
FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask(
|
||||||
TaskName name_, TaskPriority taskPriority_, TaskStackSize stackSize_,
|
TaskName name_, TaskPriority taskPriority_, TaskStackSize stackSize_,
|
||||||
TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_) {
|
TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_) {
|
||||||
return new FixedTimeslotTask(name_, taskPriority_, stackSize_, periodInSeconds_ * 1000);
|
return new FixedTimeslotTask(name_, taskPriority_, stackSize_, periodInSeconds_,
|
||||||
|
deadLineMissedFunction_);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t TaskFactory::deleteTask(PeriodicTaskIF* task) {
|
ReturnValue_t TaskFactory::deleteTask(PeriodicTaskIF* task) {
|
||||||
|
@ -1,20 +1,17 @@
|
|||||||
target_sources(${LIB_FSFW_NAME}
|
target_sources(
|
||||||
PRIVATE
|
${LIB_FSFW_NAME}
|
||||||
Clock.cpp
|
PRIVATE Clock.cpp
|
||||||
CpuUsage.cpp
|
CpuUsage.cpp
|
||||||
InitTask.cpp
|
InitTask.cpp
|
||||||
InternalErrorCodes.cpp
|
InternalErrorCodes.cpp
|
||||||
MessageQueue.cpp
|
MessageQueue.cpp
|
||||||
PeriodicTask.cpp
|
PeriodicTask.cpp
|
||||||
Mutex.cpp
|
Mutex.cpp
|
||||||
MutexFactory.cpp
|
MutexFactory.cpp
|
||||||
FixedTimeslotTask.cpp
|
FixedTimeslotTask.cpp
|
||||||
QueueFactory.cpp
|
QueueFactory.cpp
|
||||||
RtemsBasic.cpp
|
RtemsBasic.cpp
|
||||||
RTEMSTaskBase.cpp
|
RTEMSTaskBase.cpp
|
||||||
TaskFactory.cpp
|
TaskFactory.cpp
|
||||||
BinarySemaphore.cpp
|
BinarySemaphore.cpp
|
||||||
SemaphoreFactory.cpp
|
SemaphoreFactory.cpp)
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,42 +1,32 @@
|
|||||||
#include "fsfw/osal/rtems/FixedTimeslotTask.h"
|
#include "fsfw/osal/rtems/FixedTimeslotTask.h"
|
||||||
|
|
||||||
#include <rtems/bspIo.h>
|
|
||||||
#include <rtems/io.h>
|
#include <rtems/io.h>
|
||||||
#include <rtems/rtems/ratemon.h>
|
|
||||||
#include <rtems/rtems/status.h>
|
#include <rtems/rtems/status.h>
|
||||||
#include <rtems/rtems/tasks.h>
|
#include <rtems/rtems/tasks.h>
|
||||||
#include <rtems/rtems/types.h>
|
#include <rtems/rtems/types.h>
|
||||||
#include <sys/_stdint.h>
|
|
||||||
|
|
||||||
#include "fsfw/objectmanager/ObjectManager.h"
|
|
||||||
#include "fsfw/objectmanager/SystemObjectIF.h"
|
|
||||||
#include "fsfw/osal/rtems/RtemsBasic.h"
|
#include "fsfw/osal/rtems/RtemsBasic.h"
|
||||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||||
#include "fsfw/tasks/FixedSequenceSlot.h"
|
|
||||||
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <list>
|
|
||||||
|
|
||||||
uint32_t FixedTimeslotTask::deadlineMissedCount = 0;
|
|
||||||
|
|
||||||
FixedTimeslotTask::FixedTimeslotTask(const char *name, rtems_task_priority setPriority,
|
FixedTimeslotTask::FixedTimeslotTask(const char *name, rtems_task_priority setPriority,
|
||||||
size_t setStack, uint32_t setOverallPeriod,
|
size_t setStack, TaskPeriod setOverallPeriod,
|
||||||
void (*setDeadlineMissedFunc)(void))
|
TaskDeadlineMissedFunction dlmFunc_)
|
||||||
: RTEMSTaskBase(setPriority, setStack, name), periodId(0), pst(setOverallPeriod) {
|
: FixedTimeslotTaskBase(setOverallPeriod, dlmFunc_),
|
||||||
// All additional attributes are applied to the object.
|
RTEMSTaskBase(setPriority, setStack, name),
|
||||||
this->deadlineMissedFunc = setDeadlineMissedFunc;
|
periodId(0) {}
|
||||||
}
|
|
||||||
|
|
||||||
FixedTimeslotTask::~FixedTimeslotTask() {}
|
FixedTimeslotTask::~FixedTimeslotTask() = default;
|
||||||
|
|
||||||
rtems_task FixedTimeslotTask::taskEntryPoint(rtems_task_argument argument) {
|
rtems_task FixedTimeslotTask::taskEntryPoint(rtems_task_argument argument) {
|
||||||
/* The argument is re-interpreted as a FixedTimeslotTask */
|
/* The argument is re-interpreted as a FixedTimeslotTask */
|
||||||
FixedTimeslotTask *originalTask(reinterpret_cast<FixedTimeslotTask *>(argument));
|
auto *originalTask(reinterpret_cast<FixedTimeslotTask *>(argument));
|
||||||
/* The task's functionality is called. */
|
/* The task's functionality is called. */
|
||||||
return originalTask->taskFunctionality();
|
return originalTask->taskFunctionality();
|
||||||
/* Should never be reached */
|
/* Should never be reached */
|
||||||
@ -46,16 +36,6 @@ rtems_task FixedTimeslotTask::taskEntryPoint(rtems_task_argument argument) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void FixedTimeslotTask::missedDeadlineCounter() {
|
|
||||||
FixedTimeslotTask::deadlineMissedCount++;
|
|
||||||
if (FixedTimeslotTask::deadlineMissedCount % 10 == 0) {
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::error << "PST missed " << FixedTimeslotTask::deadlineMissedCount << " deadlines."
|
|
||||||
<< std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t FixedTimeslotTask::startTask() {
|
ReturnValue_t FixedTimeslotTask::startTask() {
|
||||||
rtems_status_code status =
|
rtems_status_code status =
|
||||||
rtems_task_start(id, FixedTimeslotTask::taskEntryPoint, rtems_task_argument((void *)this));
|
rtems_task_start(id, FixedTimeslotTask::taskEntryPoint, rtems_task_argument((void *)this));
|
||||||
@ -79,54 +59,35 @@ ReturnValue_t FixedTimeslotTask::startTask() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, uint32_t slotTimeMs,
|
[[noreturn]] void FixedTimeslotTask::taskFunctionality() {
|
||||||
int8_t executionStep) {
|
|
||||||
ExecutableObjectIF *object = ObjectManager::instance()->get<ExecutableObjectIF>(componentId);
|
|
||||||
if (object != nullptr) {
|
|
||||||
pst.addSlot(componentId, slotTimeMs, executionStep, object, this);
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::error << "Component " << std::hex << componentId << " not found, not adding it to pst"
|
|
||||||
<< std::endl;
|
|
||||||
#endif
|
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t FixedTimeslotTask::getPeriodMs() const { return pst.getLengthMs(); }
|
|
||||||
|
|
||||||
ReturnValue_t FixedTimeslotTask::checkSequence() const { return pst.checkSequence(); }
|
|
||||||
|
|
||||||
void FixedTimeslotTask::taskFunctionality() {
|
|
||||||
/* A local iterator for the Polling Sequence Table is created to find the start time for
|
/* A local iterator for the Polling Sequence Table is created to find the start time for
|
||||||
the first entry. */
|
the first entry. */
|
||||||
FixedSlotSequence::SlotListIter it = pst.current;
|
auto it = pollingSeqTable.current;
|
||||||
|
|
||||||
/* Initialize the PST with the correct calling task */
|
/* Initialize the PST with the correct calling task */
|
||||||
pst.intializeSequenceAfterTaskCreation();
|
pollingSeqTable.intializeSequenceAfterTaskCreation();
|
||||||
|
|
||||||
/* The start time for the first entry is read. */
|
/* The start time for the first entry is read. */
|
||||||
rtems_interval interval = RtemsBasic::convertMsToTicks(it->pollingTimeMs);
|
rtems_interval interval = RtemsBasic::convertMsToTicks(it->pollingTimeMs);
|
||||||
RTEMSTaskBase::setAndStartPeriod(interval, &periodId);
|
RTEMSTaskBase::setAndStartPeriod(interval, &periodId);
|
||||||
// The task's "infinite" inner loop is entered.
|
// The task's "infinite" inner loop is entered.
|
||||||
while (1) {
|
while (true) {
|
||||||
if (pst.slotFollowsImmediately()) {
|
if (pollingSeqTable.slotFollowsImmediately()) {
|
||||||
/* Do nothing */
|
/* Do nothing */
|
||||||
} else {
|
} else {
|
||||||
/* The interval for the next polling slot is selected. */
|
/* The interval for the next polling slot is selected. */
|
||||||
interval = RtemsBasic::convertMsToTicks(this->pst.getIntervalToNextSlotMs());
|
interval = RtemsBasic::convertMsToTicks(pollingSeqTable.getIntervalToNextSlotMs());
|
||||||
/* The period is checked and restarted with the new interval.
|
/* The period is checked and restarted with the new interval.
|
||||||
If the deadline was missed, the deadlineMissedFunc is called. */
|
If the deadline was missed, the deadlineMissedFunc is called. */
|
||||||
rtems_status_code status = RTEMSTaskBase::restartPeriod(interval, periodId);
|
rtems_status_code status = RTEMSTaskBase::restartPeriod(interval, periodId);
|
||||||
if (status == RTEMS_TIMEOUT) {
|
if (status == RTEMS_TIMEOUT) {
|
||||||
if (this->deadlineMissedFunc != nullptr) {
|
if (dlmFunc != nullptr) {
|
||||||
this->deadlineMissedFunc();
|
dlmFunc();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* The device handler for this slot is executed and the next one is chosen. */
|
/* The device handler for this slot is executed and the next one is chosen. */
|
||||||
this->pst.executeAndAdvance();
|
this->pollingSeqTable.executeAndAdvance();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
#ifndef FSFW_OSAL_RTEMS_FIXEDTIMESLOTTASK_H_
|
#ifndef FSFW_OSAL_RTEMS_FIXEDTIMESLOTTASK_H_
|
||||||
#define FSFW_OSAL_RTEMS_FIXEDTIMESLOTTASK_H_
|
#define FSFW_OSAL_RTEMS_FIXEDTIMESLOTTASK_H_
|
||||||
|
|
||||||
#include "../../tasks/FixedSlotSequence.h"
|
|
||||||
#include "../../tasks/FixedTimeslotTaskIF.h"
|
|
||||||
#include "RTEMSTaskBase.h"
|
#include "RTEMSTaskBase.h"
|
||||||
|
#include "fsfw/tasks/FixedSlotSequence.h"
|
||||||
|
#include "fsfw/tasks/FixedTimeslotTaskBase.h"
|
||||||
|
|
||||||
class FixedTimeslotTask : public RTEMSTaskBase, public FixedTimeslotTaskIF {
|
class FixedTimeslotTask : public FixedTimeslotTaskBase, public RTEMSTaskBase {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief The standard constructor of the class.
|
* @brief The standard constructor of the class.
|
||||||
@ -17,7 +17,7 @@ class FixedTimeslotTask : public RTEMSTaskBase, public FixedTimeslotTaskIF {
|
|||||||
* @param getPst The object id of the completely initialized polling sequence.
|
* @param getPst The object id of the completely initialized polling sequence.
|
||||||
*/
|
*/
|
||||||
FixedTimeslotTask(const char *name, rtems_task_priority setPriority, size_t setStackSize,
|
FixedTimeslotTask(const char *name, rtems_task_priority setPriority, size_t setStackSize,
|
||||||
uint32_t overallPeriod, void (*setDeadlineMissedFunc)());
|
TaskPeriod overallPeriod, TaskDeadlineMissedFunction dlmFunc);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The destructor of the class.
|
* @brief The destructor of the class.
|
||||||
@ -25,44 +25,17 @@ class FixedTimeslotTask : public RTEMSTaskBase, public FixedTimeslotTaskIF {
|
|||||||
* The destructor frees all heap memory that was allocated on thread initialization
|
* The destructor frees all heap memory that was allocated on thread initialization
|
||||||
* for the PST andthe device handlers. This is done by calling the PST's destructor.
|
* for the PST andthe device handlers. This is done by calling the PST's destructor.
|
||||||
*/
|
*/
|
||||||
virtual ~FixedTimeslotTask(void);
|
~FixedTimeslotTask() override;
|
||||||
|
|
||||||
ReturnValue_t startTask(void);
|
ReturnValue_t startTask(void);
|
||||||
/**
|
|
||||||
* This static function can be used as #deadlineMissedFunc.
|
|
||||||
* It counts missedDeadlines and prints the number of missed deadlines every 10th time.
|
|
||||||
*/
|
|
||||||
static void missedDeadlineCounter();
|
|
||||||
/**
|
|
||||||
* A helper variable to count missed deadlines.
|
|
||||||
*/
|
|
||||||
static uint32_t deadlineMissedCount;
|
|
||||||
|
|
||||||
ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, int8_t executionStep);
|
ReturnValue_t sleepFor(uint32_t ms) override;
|
||||||
|
|
||||||
uint32_t getPeriodMs() const;
|
|
||||||
|
|
||||||
ReturnValue_t checkSequence() const;
|
|
||||||
|
|
||||||
ReturnValue_t sleepFor(uint32_t ms);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* @brief id of the associated OS period
|
* @brief id of the associated OS period
|
||||||
*/
|
*/
|
||||||
rtems_id periodId;
|
rtems_id periodId;
|
||||||
|
|
||||||
FixedSlotSequence pst;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This attribute holds a function pointer that is executed when a deadline was missed.
|
|
||||||
*
|
|
||||||
* @details
|
|
||||||
* Another function may be announced to determine the actions to perform when a deadline
|
|
||||||
* was missed. Currently, only one function for missing any deadline is allowed.
|
|
||||||
* If not used, it shall be declared NULL.
|
|
||||||
*/
|
|
||||||
void (*deadlineMissedFunc)(void) = nullptr;
|
|
||||||
/**
|
/**
|
||||||
* @brief This is the entry point in a new polling thread.
|
* @brief This is the entry point in a new polling thread.
|
||||||
* @details This method is the entry point in the new thread
|
* @details This method is the entry point in the new thread
|
||||||
@ -76,7 +49,7 @@ class FixedTimeslotTask : public RTEMSTaskBase, public FixedTimeslotTaskIF {
|
|||||||
* It links the functionalities provided by FixedSlotSequence with the OS's system calls to
|
* It links the functionalities provided by FixedSlotSequence with the OS's system calls to
|
||||||
* keep the timing of the periods.
|
* keep the timing of the periods.
|
||||||
*/
|
*/
|
||||||
void taskFunctionality(void);
|
[[noreturn]] void taskFunctionality();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_OSAL_RTEMS_FIXEDTIMESLOTTASK_H_ */
|
#endif /* FSFW_OSAL_RTEMS_FIXEDTIMESLOTTASK_H_ */
|
||||||
|
@ -65,7 +65,7 @@ ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, MessageQueu
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t returnCode = convertReturnCode(result);
|
ReturnValue_t returnCode = convertReturnCode(result);
|
||||||
if (result == MessageQueueIF::EMPTY) {
|
if (returnCode == MessageQueueIF::EMPTY) {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,9 +36,9 @@ class MessageQueue : public MessageQueueBase {
|
|||||||
* @param max_message_size With this parameter, the maximum message size can be adjusted.
|
* @param max_message_size With this parameter, the maximum message size can be adjusted.
|
||||||
* This should be left default.
|
* This should be left default.
|
||||||
*/
|
*/
|
||||||
MessageQueue(size_t message_depth = 3,
|
explicit MessageQueue(size_t message_depth = 3,
|
||||||
size_t max_message_size = MessageQueueMessage::MAX_MESSAGE_SIZE,
|
size_t max_message_size = MessageQueueMessage::MAX_MESSAGE_SIZE,
|
||||||
MqArgs* args = nullptr);
|
MqArgs* args = nullptr);
|
||||||
|
|
||||||
/** Copying message queues forbidden */
|
/** Copying message queues forbidden */
|
||||||
MessageQueue(const MessageQueue&) = delete;
|
MessageQueue(const MessageQueue&) = delete;
|
||||||
@ -48,18 +48,19 @@ class MessageQueue : public MessageQueueBase {
|
|||||||
* @brief The destructor deletes the formerly created message queue.
|
* @brief The destructor deletes the formerly created message queue.
|
||||||
* @details This is accomplished by using the delete call provided by the operating system.
|
* @details This is accomplished by using the delete call provided by the operating system.
|
||||||
*/
|
*/
|
||||||
virtual ~MessageQueue();
|
~MessageQueue() override;
|
||||||
|
|
||||||
// Implement non-generic MessageQueueIF functions not handled by MessageQueueBase
|
// Implement non-generic MessageQueueIF functions not handled by MessageQueueBase
|
||||||
ReturnValue_t flush(uint32_t* count) override;
|
ReturnValue_t flush(uint32_t* count) override;
|
||||||
|
|
||||||
|
ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override;
|
||||||
ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
||||||
MessageQueueId_t sentFrom = NO_QUEUE,
|
MessageQueueId_t sentFrom, bool ignoreFault) override;
|
||||||
bool ignoreFault = false) override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* \brief This attribute stores a reference to the internal error reporter for reporting full
|
* @brief This attribute stores a reference to the internal error reporter for reporting full
|
||||||
* queues. \details In the event of a full destination queue, the reporter will be notified. The
|
* queues. @details In the event of a full destination queue, the reporter will be notified. The
|
||||||
* reference is set by lazy loading
|
* reference is set by lazy loading
|
||||||
*/
|
*/
|
||||||
InternalErrorReporterIF* internalErrorReporter;
|
InternalErrorReporterIF* internalErrorReporter;
|
||||||
|
@ -5,12 +5,12 @@
|
|||||||
#include "fsfw/tasks/ExecutableObjectIF.h"
|
#include "fsfw/tasks/ExecutableObjectIF.h"
|
||||||
|
|
||||||
PeriodicTask::PeriodicTask(const char* name, rtems_task_priority setPriority, size_t setStack,
|
PeriodicTask::PeriodicTask(const char* name, rtems_task_priority setPriority, size_t setStack,
|
||||||
rtems_interval setPeriod, void (*setDeadlineMissedFunc)())
|
TaskPeriod setPeriod, TaskDeadlineMissedFunction dlmFunc_)
|
||||||
: RTEMSTaskBase(setPriority, setStack, name),
|
: PeriodicTaskBase(setPeriod, dlmFunc_),
|
||||||
periodTicks(RtemsBasic::convertMsToTicks(setPeriod)),
|
RTEMSTaskBase(setPriority, setStack, name),
|
||||||
deadlineMissedFunc(setDeadlineMissedFunc) {}
|
periodTicks(RtemsBasic::convertMsToTicks(static_cast<uint32_t>(setPeriod * 1000.0))) {}
|
||||||
|
|
||||||
PeriodicTask::~PeriodicTask(void) {
|
PeriodicTask::~PeriodicTask() {
|
||||||
/* Do not delete objects, we were responsible for pointers only. */
|
/* Do not delete objects, we were responsible for pointers only. */
|
||||||
rtems_rate_monotonic_delete(periodId);
|
rtems_rate_monotonic_delete(periodId);
|
||||||
}
|
}
|
||||||
@ -18,7 +18,7 @@ PeriodicTask::~PeriodicTask(void) {
|
|||||||
rtems_task PeriodicTask::taskEntryPoint(rtems_task_argument argument) {
|
rtems_task PeriodicTask::taskEntryPoint(rtems_task_argument argument) {
|
||||||
/* The argument is re-interpreted as MultiObjectTask. The Task object is global,
|
/* The argument is re-interpreted as MultiObjectTask. The Task object is global,
|
||||||
so it is found from any place. */
|
so it is found from any place. */
|
||||||
PeriodicTask* originalTask(reinterpret_cast<PeriodicTask*>(argument));
|
auto* originalTask(reinterpret_cast<PeriodicTask*>(argument));
|
||||||
return originalTask->taskFunctionality();
|
return originalTask->taskFunctionality();
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
@ -28,8 +28,10 @@ ReturnValue_t PeriodicTask::startTask() {
|
|||||||
rtems_task_start(id, PeriodicTask::taskEntryPoint, rtems_task_argument((void*)this));
|
rtems_task_start(id, PeriodicTask::taskEntryPoint, rtems_task_argument((void*)this));
|
||||||
if (status != RTEMS_SUCCESSFUL) {
|
if (status != RTEMS_SUCCESSFUL) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "ObjectTask::startTask for " << std::hex << this->getId() << std::dec
|
sif::error << "PeriodicTask::startTask for " << std::hex << this->getId() << std::dec
|
||||||
<< " failed." << std::endl;
|
<< " failed" << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printError("PeriodicTask::startTask for 0x%08x failed\n", getId());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
switch (status) {
|
switch (status) {
|
||||||
@ -47,38 +49,20 @@ ReturnValue_t PeriodicTask::startTask() {
|
|||||||
|
|
||||||
ReturnValue_t PeriodicTask::sleepFor(uint32_t ms) { return RTEMSTaskBase::sleepFor(ms); }
|
ReturnValue_t PeriodicTask::sleepFor(uint32_t ms) { return RTEMSTaskBase::sleepFor(ms); }
|
||||||
|
|
||||||
void PeriodicTask::taskFunctionality() {
|
[[noreturn]] void PeriodicTask::taskFunctionality() {
|
||||||
RTEMSTaskBase::setAndStartPeriod(periodTicks, &periodId);
|
RTEMSTaskBase::setAndStartPeriod(periodTicks, &periodId);
|
||||||
for (const auto& object : objectList) {
|
initObjsAfterTaskCreation();
|
||||||
object->initializeAfterTaskCreation();
|
|
||||||
}
|
|
||||||
/* The task's "infinite" inner loop is entered. */
|
/* The task's "infinite" inner loop is entered. */
|
||||||
while (1) {
|
while (true) {
|
||||||
for (const auto& object : objectList) {
|
for (const auto& objectPair : objectList) {
|
||||||
object->performOperation();
|
objectPair.first->performOperation(objectPair.second);
|
||||||
}
|
}
|
||||||
rtems_status_code status = RTEMSTaskBase::restartPeriod(periodTicks, periodId);
|
rtems_status_code status = RTEMSTaskBase::restartPeriod(periodTicks, periodId);
|
||||||
if (status == RTEMS_TIMEOUT) {
|
if (status == RTEMS_TIMEOUT) {
|
||||||
if (this->deadlineMissedFunc != nullptr) {
|
if (dlmFunc != nullptr) {
|
||||||
this->deadlineMissedFunc();
|
dlmFunc();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t PeriodicTask::addComponent(object_id_t object) {
|
|
||||||
ExecutableObjectIF* newObject = ObjectManager::instance()->get<ExecutableObjectIF>(object);
|
|
||||||
return addComponent(newObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t PeriodicTask::addComponent(ExecutableObjectIF* object) {
|
|
||||||
if (object == nullptr) {
|
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
|
||||||
}
|
|
||||||
objectList.push_back(object);
|
|
||||||
object->setTaskIF(this);
|
|
||||||
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t PeriodicTask::getPeriodMs() const { return RtemsBasic::convertTicksToMs(periodTicks); }
|
|
||||||
|
@ -3,9 +3,10 @@
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "../../objectmanager/ObjectManagerIF.h"
|
|
||||||
#include "../../tasks/PeriodicTaskIF.h"
|
|
||||||
#include "RTEMSTaskBase.h"
|
#include "RTEMSTaskBase.h"
|
||||||
|
#include "fsfw/objectmanager/ObjectManagerIF.h"
|
||||||
|
#include "fsfw/tasks/PeriodicTaskBase.h"
|
||||||
|
#include "fsfw/tasks/PeriodicTaskIF.h"
|
||||||
|
|
||||||
class ExecutableObjectIF;
|
class ExecutableObjectIF;
|
||||||
|
|
||||||
@ -18,7 +19,7 @@ class ExecutableObjectIF;
|
|||||||
* @author baetz
|
* @author baetz
|
||||||
* @ingroup task_handling
|
* @ingroup task_handling
|
||||||
*/
|
*/
|
||||||
class PeriodicTask : public RTEMSTaskBase, public PeriodicTaskIF {
|
class PeriodicTask : public PeriodicTaskBase, public RTEMSTaskBase {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Standard constructor of the class.
|
* @brief Standard constructor of the class.
|
||||||
@ -36,12 +37,12 @@ class PeriodicTask : public RTEMSTaskBase, public PeriodicTaskIF {
|
|||||||
* that shall be assigned.
|
* that shall be assigned.
|
||||||
*/
|
*/
|
||||||
PeriodicTask(const char *name, rtems_task_priority setPriority, size_t setStack,
|
PeriodicTask(const char *name, rtems_task_priority setPriority, size_t setStack,
|
||||||
rtems_interval setPeriod, void (*setDeadlineMissedFunc)());
|
TaskPeriod setPeriod, TaskDeadlineMissedFunction dlmFunc);
|
||||||
/**
|
/**
|
||||||
* @brief Currently, the executed object's lifetime is not coupled with the task object's
|
* @brief Currently, the executed object's lifetime is not coupled with the task object's
|
||||||
* lifetime, so the destructor is empty.
|
* lifetime, so the destructor is empty.
|
||||||
*/
|
*/
|
||||||
virtual ~PeriodicTask(void);
|
~PeriodicTask() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The method to start the task.
|
* @brief The method to start the task.
|
||||||
@ -50,33 +51,11 @@ class PeriodicTask : public RTEMSTaskBase, public PeriodicTaskIF {
|
|||||||
* The address of the task object is passed as an argument
|
* The address of the task object is passed as an argument
|
||||||
* to the system call.
|
* to the system call.
|
||||||
*/
|
*/
|
||||||
ReturnValue_t startTask(void);
|
ReturnValue_t startTask() override;
|
||||||
/**
|
|
||||||
* Adds an object to the list of objects to be executed.
|
|
||||||
* The objects are executed in the order added.
|
|
||||||
* @param object Id of the object to add.
|
|
||||||
* @return RETURN_OK on success, RETURN_FAILED if the object could not be added.
|
|
||||||
*/
|
|
||||||
ReturnValue_t addComponent(object_id_t object) override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds an object to the list of objects to be executed.
|
|
||||||
* The objects are executed in the order added.
|
|
||||||
* @param object pointer to the object to add.
|
|
||||||
* @return RETURN_OK on success, RETURN_FAILED if the object could not be added.
|
|
||||||
*/
|
|
||||||
ReturnValue_t addComponent(ExecutableObjectIF *object) override;
|
|
||||||
|
|
||||||
uint32_t getPeriodMs() const override;
|
|
||||||
|
|
||||||
ReturnValue_t sleepFor(uint32_t ms) override;
|
ReturnValue_t sleepFor(uint32_t ms) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
typedef std::vector<ExecutableObjectIF *> ObjectList; //!< Typedef for the List of objects.
|
|
||||||
/**
|
|
||||||
* @brief This attribute holds a list of objects to be executed.
|
|
||||||
*/
|
|
||||||
ObjectList objectList;
|
|
||||||
/**
|
/**
|
||||||
* @brief The period of the task.
|
* @brief The period of the task.
|
||||||
* @details The period determines the frequency of the task's execution. It is expressed in
|
* @details The period determines the frequency of the task's execution. It is expressed in
|
||||||
@ -87,14 +66,7 @@ class PeriodicTask : public RTEMSTaskBase, public PeriodicTaskIF {
|
|||||||
* @brief id of the associated OS period
|
* @brief id of the associated OS period
|
||||||
*/
|
*/
|
||||||
rtems_id periodId = 0;
|
rtems_id periodId = 0;
|
||||||
/**
|
|
||||||
* @brief The pointer to the deadline-missed function.
|
|
||||||
* @details This pointer stores the function that is executed if the task's deadline is missed.
|
|
||||||
* So, each may react individually on a timing failure. The pointer may be
|
|
||||||
* nullptr, then nothing happens on missing the deadline. The deadline is equal to the next
|
|
||||||
* execution of the periodic task.
|
|
||||||
*/
|
|
||||||
void (*deadlineMissedFunc)(void);
|
|
||||||
/**
|
/**
|
||||||
* @brief This is the function executed in the new task's context.
|
* @brief This is the function executed in the new task's context.
|
||||||
* @details It converts the argument back to the thread object type and copies the class
|
* @details It converts the argument back to the thread object type and copies the class
|
||||||
@ -110,7 +82,7 @@ class PeriodicTask : public RTEMSTaskBase, public PeriodicTaskIF {
|
|||||||
* are called. Afterwards the checkAndRestartPeriod system call blocks the task until the next
|
* are called. Afterwards the checkAndRestartPeriod system call blocks the task until the next
|
||||||
* period. On missing the deadline, the deadlineMissedFunction is executed.
|
* period. On missing the deadline, the deadlineMissedFunction is executed.
|
||||||
*/
|
*/
|
||||||
void taskFunctionality(void);
|
[[noreturn]] void taskFunctionality();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_OSAL_RTEMS_PERIODICTASK_H_ */
|
#endif /* FSFW_OSAL_RTEMS_PERIODICTASK_H_ */
|
||||||
|
@ -45,9 +45,9 @@ QueueFactory* QueueFactory::instance() {
|
|||||||
return factoryInstance;
|
return factoryInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
QueueFactory::QueueFactory() {}
|
QueueFactory::QueueFactory() = default;
|
||||||
|
|
||||||
QueueFactory::~QueueFactory() {}
|
QueueFactory::~QueueFactory() = default;
|
||||||
|
|
||||||
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize,
|
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize,
|
||||||
MqArgs* args) {
|
MqArgs* args) {
|
||||||
|
@ -32,7 +32,7 @@ RTEMSTaskBase::RTEMSTaskBase(rtems_task_priority set_priority, size_t stack_size
|
|||||||
|
|
||||||
RTEMSTaskBase::~RTEMSTaskBase() { rtems_task_delete(id); }
|
RTEMSTaskBase::~RTEMSTaskBase() { rtems_task_delete(id); }
|
||||||
|
|
||||||
rtems_id RTEMSTaskBase::getId() { return this->id; }
|
rtems_id RTEMSTaskBase::getId() const { return this->id; }
|
||||||
|
|
||||||
ReturnValue_t RTEMSTaskBase::sleepFor(uint32_t ms) {
|
ReturnValue_t RTEMSTaskBase::sleepFor(uint32_t ms) {
|
||||||
rtems_status_code status = rtems_task_wake_after(RtemsBasic::convertMsToTicks(ms));
|
rtems_status_code status = rtems_task_wake_after(RtemsBasic::convertMsToTicks(ms));
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user