Compare commits
351 Commits
280b641cbc
...
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 | |||
4499c9bf04 | |||
eb0223bc51 | |||
be6a492022 | |||
d8bd08dd8c | |||
18c2847b08 | |||
d45cda93b2 | |||
3448292e8a | |||
d983305ea5 | |||
c83cc492c0 | |||
ece32f88f4 | |||
dd9e28fca1 | |||
46cfe65321 | |||
7b7f5d7e0a | |||
fd112ed597 | |||
96eb8fc21f | |||
88fa4f1d9d | |||
5989c88c88 | |||
da8a108cb7 | |||
75132c1e39 | |||
eb494707af | |||
736f8d0238 | |||
f1acf8e18b | |||
281f91ec5d | |||
15352b539d | |||
4015e85506 | |||
aacaf52fd9 | |||
118f1da8dd | |||
89f83f4e3d | |||
39b7976056 | |||
8b0508d50a | |||
8a40878eb5 | |||
220469a2dd | |||
83de5b4ec1 | |||
fe1c51ae6d | |||
10cc954d27 | |||
73ff9b97db | |||
b0d71597f0 | |||
226f28dc7b | |||
6308427d03 | |||
398d04dc50 | |||
80a5ed3c5b | |||
5d5a355110 | |||
c78b7c432b | |||
6bfdace512 | |||
16e55a98ce | |||
79f17843d8 | |||
e5e163bdbf | |||
4e4820af05 | |||
637512ad77 | |||
a4bd5a2aaa | |||
a943e4eebb | |||
cb0c80d8dc | |||
3332f68ce7 | |||
2fbf847367 | |||
54feb77770 | |||
1a07864a5f | |||
3e9d6bdbb9 | |||
c295539c79 | |||
57e6c46e72 | |||
cddf16f941 | |||
a3dee05fe3 | |||
a3617cad11 | |||
8edf4c3c8d | |||
7801c6effe | |||
8cc94a55ab | |||
b62c19a364 | |||
daffb6b666 | |||
7cfb1e6076 | |||
cc36baff78 | |||
4c65109ac0 | |||
861bd15eda | |||
7b979eadff | |||
16714ceb40 | |||
fea301bcc9 | |||
77450eb4b7 | |||
28015c4735 | |||
7d61e67d20 | |||
afcbc8be0a | |||
7a2269262b | |||
9731dc1e61 | |||
bf2e0f2d73 | |||
e98857fab4 | |||
29b0a352fc | |||
8642b13fd1 | |||
6aa72892ed | |||
70f0a72f1b | |||
b5d890eedd | |||
50b1b48678 | |||
0e0dbc74aa | |||
8c34051d8b | |||
b00d83cb1a | |||
17e609c3a5 | |||
64f0166b64 | |||
c80f06fbcb | |||
70eb8325a0 | |||
8e4ad10627 | |||
496bc665d6 | |||
2c8531ea48 | |||
e796f82203 | |||
5b7ca8c13c | |||
031739ef51 | |||
b94685e045 | |||
572d602b72 | |||
88051c9302 | |||
80be937d9d | |||
d62ee6a611 | |||
91ef4ff30b | |||
b8516b15cb | |||
4032228005 | |||
50ce13d596 | |||
68302e7c5e | |||
ac5a54b5da | |||
29015b340b | |||
64274acbeb | |||
ff98c42514 | |||
126ac52975 | |||
70d3197212 | |||
dd90980520 | |||
352ab43c1f | |||
35f257800e | |||
07f5dbb9ac | |||
97e98eae24 | |||
afce942bf8 | |||
a1d7a56dfa | |||
cb78fefbb3 | |||
c55925959b | |||
4f0669c574 | |||
f0d996ffd2 | |||
d0b7c22afc | |||
a18bc15cbb | |||
f4d05c2c9c | |||
d1151ca707 | |||
82f46992f6 | |||
4ed9cc933f | |||
7af1c86f1c | |||
bd0b7aa230 | |||
72e0938f9a | |||
dd1b0a9380 | |||
9947a648df | |||
95f018a0b0 | |||
8c2105ae0a | |||
ed2c2af4a0 | |||
82df132e7d | |||
a02619e5a2 | |||
a011e70665 | |||
4dee913d51 | |||
b2252bdc0b | |||
b764194ed0 | |||
2d0e4ba951 | |||
0d549b687d | |||
738f572043 | |||
cab508fd64 | |||
c7daf697a8 | |||
c20be13733 | |||
fcb6437388 | |||
b42987059a | |||
82fc7f33a8 | |||
bfa77cf810 | |||
a3930dafc5 | |||
4f9797af3b | |||
1a530633ca | |||
8037e8074b | |||
d07e0e5576 | |||
5525466b52 | |||
c2a89bf709 | |||
8dd0b2608d | |||
05495077ec | |||
8ff9eadf30 | |||
082c86ea18 | |||
2800d6f28c | |||
b4effe7a46 | |||
e6e71436c2 | |||
a887f852c8 | |||
0b3255e463 | |||
631a531212 | |||
23af170229 | |||
b32d1da421 | |||
6f0362b956 | |||
665d8cd479 | |||
10398855a9 | |||
d0fec93dc3 | |||
59ab54b2fb | |||
7095999bd2 | |||
7ffb4107d2 | |||
9ce59d3c75 | |||
a0dfdfab2c |
8
.gitignore
vendored
8
.gitignore
vendored
@ -1,6 +1,14 @@
|
||||
# PyCharm and CLion
|
||||
/.idea/*
|
||||
!/.idea/runConfigurations
|
||||
!/.idea/cmake.xml
|
||||
!/.idea/codeStyles
|
||||
|
||||
# Eclipse
|
||||
.cproject
|
||||
.project
|
||||
.settings
|
||||
.metadata
|
||||
|
||||
/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>
|
119
CHANGELOG.md
119
CHANGELOG.md
@ -12,6 +12,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## 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
|
||||
compiler supports it
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/622
|
||||
- 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
|
||||
@ -22,11 +29,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/572
|
||||
- HAL Devicehandlers: Periodic printout is run-time configurable now
|
||||
- `oneShotAction` flag in the `TestTask` class is not static anymore
|
||||
- HAL Linux Uart: Baudrate and bits per word are enums now, avoiding misconfigurations
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/585
|
||||
- Major update for version handling, using `git describe` to fetch version information with git.
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/601
|
||||
- Place `Version` class outside of `fsfw` namespace. It is generic
|
||||
- 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
|
||||
@ -38,6 +42,75 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
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
|
||||
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
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/583
|
||||
|
||||
### Task Module Refactoring
|
||||
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/636
|
||||
|
||||
**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
|
||||
|
||||
@ -47,15 +120,55 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## 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
|
||||
- Dedicated Version class and constant `fsfw::FSFW_VERSION` containing version information
|
||||
inside `fsfw/version.h`
|
||||
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
|
||||
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
|
||||
|
||||
## Fixed
|
||||
|
||||
- TCP TMTC Server: `MutexGuard` was not created properly in
|
||||
`TcpTmTcServer::handleTmSending(socket_t connSocket, bool& tmSent)` call.
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/618
|
||||
- Fix infinite recursion in `prepareHealthSetReply` of PUS Health Service 201.
|
||||
Is not currently used right now but might be used in the future
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/617
|
||||
- Move some CMake directives further up top so they are not ignored
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/621
|
||||
- Small bugfix in STM32 HAL for SPI
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/599
|
||||
- HAL GPIO: Improved error checking in `LinuxLibgpioIF::configureGpios(...)`. If a GPIO
|
||||
configuration fails, the function will exit prematurely with a dedicated error code
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/602
|
||||
|
||||
# [v4.0.0]
|
||||
|
||||
|
622
CMakeLists.txt
622
CMakeLists.txt
@ -1,25 +1,114 @@
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
set(MSG_PREFIX "fsfw |")
|
||||
|
||||
# Add the cmake folder so the FindSphinx module is found
|
||||
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")
|
||||
|
||||
# ##############################################################################
|
||||
# Version file handling #
|
||||
# ##############################################################################
|
||||
|
||||
set(FSFW_VERSION_IF_GIT_FAILS 4)
|
||||
set(FSFW_SUBVERSION_IF_GIT_FAILS 0)
|
||||
set(FSFW_REVISION_IF_GIT_FAILS 0)
|
||||
|
||||
# Add the cmake folder so the FindSphinx module is found
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" )
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake-modules")
|
||||
set(MSG_PREFIX "fsfw |")
|
||||
|
||||
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)
|
||||
set(FSFW_GIT_VER_HANDLING_OK FALSE)
|
||||
# Version handling
|
||||
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git)
|
||||
message(STATUS "${MSG_PREFIX} Determining version information with git")
|
||||
include(FsfwHelpers)
|
||||
determine_version_with_git("--exclude" "docker_*")
|
||||
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()
|
||||
|
||||
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)
|
||||
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()
|
||||
|
||||
option(FSFW_WARNING_SHADOW_LOCAL_GCC "Enable -Wshadow=local warning in GCC" ON)
|
||||
@ -40,80 +129,93 @@ option(FSFW_ADD_TMSTORAGE "Compile with tm storage components" OFF)
|
||||
# Contrib sources
|
||||
option(FSFW_ADD_SGP4_PROPAGATOR "Add SGP4 propagator code" OFF)
|
||||
|
||||
set(LIB_FSFW_NAME fsfw)
|
||||
set(FSFW_TEST_TGT fsfw-tests)
|
||||
set(FSFW_DUMMY_TGT fsfw-dummy)
|
||||
|
||||
project(${LIB_FSFW_NAME})
|
||||
add_library(${LIB_FSFW_NAME})
|
||||
|
||||
set(FSFW_GIT_VER_HANDLING_OK FALSE)
|
||||
# Version handling
|
||||
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git)
|
||||
message(STATUS "${MSG_PREFIX} Determining version information with git")
|
||||
include(FsfwHelpers)
|
||||
determine_version_with_git("--exclude" "docker_*")
|
||||
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_VERSION_CST_GIT_SHA1)
|
||||
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})
|
||||
if(IPO_SUPPORTED AND FSFW_ENABLE_IPO)
|
||||
set_property(TARGET ${LIB_FSFW_NAME} PROPERTY INTERPROCEDURAL_OPTIMIZATION
|
||||
TRUE)
|
||||
endif()
|
||||
|
||||
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 3 QUIET)
|
||||
# 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)
|
||||
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 v3.0.0-preview4
|
||||
)
|
||||
FetchContent_Declare(
|
||||
Catch2
|
||||
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
|
||||
GIT_TAG ${FSFW_CATCH2_LIB_VERSION})
|
||||
|
||||
FetchContent_MakeAvailable(Catch2)
|
||||
#fixes regression -preview4, to be confirmed in later releases
|
||||
set_target_properties(Catch2 PROPERTIES DEBUG_POSTFIX "")
|
||||
endif()
|
||||
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)
|
||||
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})
|
||||
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()
|
||||
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
|
||||
find_package(${FSFW_ETL_LIB_NAME} ${FSFW_ETL_LIB_MAJOR_VERSION} QUIET)
|
||||
# Not installed, so use FetchContent to download and provide etl
|
||||
if(NOT ${FSFW_ETL_LIB_NAME}_FOUND)
|
||||
message(
|
||||
STATUS
|
||||
"No ETL installation was found with find_package. Installing and providing "
|
||||
"etl with FindPackage")
|
||||
include(FetchContent)
|
||||
|
||||
FetchContent_Declare(
|
||||
${FSFW_ETL_LIB_NAME}
|
||||
GIT_REPOSITORY https://github.com/ETLCPP/etl
|
||||
GIT_TAG ${FSFW_ETL_LIB_VERSION})
|
||||
|
||||
list(APPEND FSFW_FETCH_CONTENT_TARGETS ${FSFW_ETL_LIB_NAME})
|
||||
endif()
|
||||
|
||||
# The documentation for FetchContent recommends declaring all the dependencies
|
||||
# before making them available. We make all declared dependency available here
|
||||
# after their declaration
|
||||
if(FSFW_FETCH_CONTENT_TARGETS)
|
||||
FetchContent_MakeAvailable(${FSFW_FETCH_CONTENT_TARGETS})
|
||||
if(TARGET ${FSFW_ETL_LIB_NAME})
|
||||
add_library(${FSFW_ETL_LINK_TARGET} ALIAS ${FSFW_ETL_LIB_NAME})
|
||||
endif()
|
||||
if(TARGET Catch2)
|
||||
# Fixes regression -preview4, to be confirmed in later releases Related
|
||||
# GitHub issue: https://github.com/catchorg/Catch2/issues/2417
|
||||
set_target_properties(Catch2 PROPERTIES DEBUG_POSTFIX "")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(FSFW_CORE_INC_PATH "inc")
|
||||
@ -121,274 +223,242 @@ set(FSFW_CORE_INC_PATH "inc")
|
||||
set_property(CACHE FSFW_OSAL PROPERTY STRINGS host linux rtems freertos)
|
||||
|
||||
# For configure files
|
||||
target_include_directories(${LIB_FSFW_NAME} PRIVATE
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
target_include_directories(${LIB_FSFW_NAME} INTERFACE
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
if(NOT CMAKE_CXX_STANDARD)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
elseif(${CMAKE_CXX_STANDARD} LESS 11)
|
||||
message(FATAL_ERROR "${MSG_PREFIX} Compiling the FSFW requires a minimum of C++11 support")
|
||||
endif()
|
||||
target_include_directories(${LIB_FSFW_NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
||||
target_include_directories(${LIB_FSFW_NAME}
|
||||
INTERFACE ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
# Backwards comptability
|
||||
if(OS_FSFW AND NOT FSFW_OSAL)
|
||||
message(WARNING "${MSG_PREFIX} Please pass the FSFW OSAL as FSFW_OSAL instead of OS_FSFW")
|
||||
set(FSFW_OSAL OS_FSFW)
|
||||
message(
|
||||
WARNING
|
||||
"${MSG_PREFIX} Please pass the FSFW OSAL as FSFW_OSAL instead of OS_FSFW")
|
||||
set(FSFW_OSAL OS_FSFW)
|
||||
endif()
|
||||
|
||||
if(NOT FSFW_OSAL)
|
||||
message(STATUS "${MSG_PREFIX} No OS for FSFW via FSFW_OSAL set. Assuming host OS")
|
||||
# Assume host OS and autodetermine from OS_FSFW
|
||||
if(UNIX)
|
||||
set(FSFW_OSAL "linux"
|
||||
CACHE STRING
|
||||
"OS abstraction layer used in the FSFW"
|
||||
)
|
||||
elseif(WIN32)
|
||||
set(FSFW_OSAL "host"
|
||||
CACHE STRING "OS abstraction layer used in the FSFW"
|
||||
)
|
||||
endif()
|
||||
|
||||
message(STATUS "No OS for FSFW via FSFW_OSAL set. Assuming host OS")
|
||||
# Assume host OS and autodetermine from OS_FSFW
|
||||
if(UNIX)
|
||||
set(FSFW_OSAL
|
||||
"linux"
|
||||
CACHE STRING "OS abstraction layer used in the FSFW")
|
||||
elseif(WIN32)
|
||||
set(FSFW_OSAL
|
||||
"host"
|
||||
CACHE STRING "OS abstraction layer used in the FSFW")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(FSFW_OSAL_DEFINITION FSFW_OSAL_HOST)
|
||||
|
||||
if(FSFW_OSAL MATCHES host)
|
||||
set(FSFW_OS_NAME "Host")
|
||||
set(FSFW_OSAL_HOST ON)
|
||||
set(FSFW_OS_NAME "Host")
|
||||
set(FSFW_OSAL_HOST ON)
|
||||
elseif(FSFW_OSAL MATCHES linux)
|
||||
set(FSFW_OS_NAME "Linux")
|
||||
set(FSFW_OSAL_LINUX ON)
|
||||
set(FSFW_OS_NAME "Linux")
|
||||
set(FSFW_OSAL_LINUX ON)
|
||||
elseif(FSFW_OSAL MATCHES freertos)
|
||||
set(FSFW_OS_NAME "FreeRTOS")
|
||||
set(FSFW_OSAL_FREERTOS ON)
|
||||
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
|
||||
${LIB_OS_NAME}
|
||||
)
|
||||
set(FSFW_OS_NAME "FreeRTOS")
|
||||
set(FSFW_OSAL_FREERTOS ON)
|
||||
target_link_libraries(${LIB_FSFW_NAME} PRIVATE ${LIB_OS_NAME})
|
||||
elseif(FSFW_OSAL STREQUAL rtems)
|
||||
set(FSFW_OS_NAME "RTEMS")
|
||||
set(FSFW_OSAL_RTEMS ON)
|
||||
set(FSFW_OS_NAME "RTEMS")
|
||||
set(FSFW_OSAL_RTEMS ON)
|
||||
else()
|
||||
message(WARNING
|
||||
"${MSG_PREFIX} Invalid operating system for FSFW specified! Setting to host.."
|
||||
)
|
||||
set(FSFW_OS_NAME "Host")
|
||||
set(OS_FSFW "host")
|
||||
message(
|
||||
WARNING
|
||||
"${MSG_PREFIX} Invalid operating system for FSFW specified! Setting to host.."
|
||||
)
|
||||
set(FSFW_OS_NAME "Host")
|
||||
set(OS_FSFW "host")
|
||||
endif()
|
||||
|
||||
configure_file(src/fsfw/FSFW.h.in fsfw/FSFW.h)
|
||||
configure_file(src/fsfw/FSFWVersion.h.in fsfw/FSFWVersion.h)
|
||||
|
||||
message(STATUS "${MSG_PREFIX} 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(tests)
|
||||
if(FSFW_ADD_HAL)
|
||||
add_subdirectory(hal)
|
||||
add_subdirectory(hal)
|
||||
endif()
|
||||
add_subdirectory(contrib)
|
||||
if(FSFW_BUILD_DOCS)
|
||||
add_subdirectory(docs)
|
||||
add_subdirectory(docs)
|
||||
endif()
|
||||
|
||||
if(FSFW_BUILD_UNITTESTS)
|
||||
if(FSFW_TESTS_GEN_COV)
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
include(CodeCoverage)
|
||||
if(FSFW_TESTS_GEN_COV)
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
include(CodeCoverage)
|
||||
|
||||
# Remove quotes.
|
||||
separate_arguments(COVERAGE_COMPILER_FLAGS
|
||||
NATIVE_COMMAND "${COVERAGE_COMPILER_FLAGS}"
|
||||
)
|
||||
# Remove quotes.
|
||||
separate_arguments(COVERAGE_COMPILER_FLAGS NATIVE_COMMAND
|
||||
"${COVERAGE_COMPILER_FLAGS}")
|
||||
|
||||
# Add compile options manually, we don't want coverage for Catch2
|
||||
target_compile_options(${FSFW_TEST_TGT} PRIVATE
|
||||
"${COVERAGE_COMPILER_FLAGS}"
|
||||
)
|
||||
target_compile_options(${LIB_FSFW_NAME} PRIVATE
|
||||
"${COVERAGE_COMPILER_FLAGS}"
|
||||
)
|
||||
# Add compile options manually, we don't want coverage for Catch2
|
||||
target_compile_options(${FSFW_TEST_TGT}
|
||||
PRIVATE "${COVERAGE_COMPILER_FLAGS}")
|
||||
target_compile_options(${LIB_FSFW_NAME}
|
||||
PRIVATE "${COVERAGE_COMPILER_FLAGS}")
|
||||
|
||||
# Exclude directories here
|
||||
if(WIN32)
|
||||
set(GCOVR_ADDITIONAL_ARGS
|
||||
"--exclude-throw-branches"
|
||||
"--exclude-unreachable-branches"
|
||||
)
|
||||
set(COVERAGE_EXCLUDES
|
||||
"/c/msys64/mingw64/*" "*/fsfw_hal/*"
|
||||
)
|
||||
elseif(UNIX)
|
||||
set(COVERAGE_EXCLUDES
|
||||
"/usr/include/*" "/usr/bin/*" "Catch2/*"
|
||||
"/usr/local/include/*" "*/fsfw_tests/*"
|
||||
"*/catch2-src/*" "*/fsfw_hal/*"
|
||||
)
|
||||
endif()
|
||||
# Exclude directories here
|
||||
if(WIN32)
|
||||
set(GCOVR_ADDITIONAL_ARGS "--exclude-throw-branches"
|
||||
"--exclude-unreachable-branches")
|
||||
set(COVERAGE_EXCLUDES "/c/msys64/mingw64/*" "*/fsfw_hal/*")
|
||||
elseif(UNIX)
|
||||
set(COVERAGE_EXCLUDES
|
||||
"/usr/include/*"
|
||||
"/usr/bin/*"
|
||||
"Catch2/*"
|
||||
"/usr/local/include/*"
|
||||
"*/fsfw_tests/*"
|
||||
"*/catch2-src/*"
|
||||
"*/fsfw_hal/*")
|
||||
endif()
|
||||
|
||||
target_link_options(${FSFW_TEST_TGT} PRIVATE
|
||||
-fprofile-arcs
|
||||
-ftest-coverage
|
||||
)
|
||||
target_link_options(${LIB_FSFW_NAME} PRIVATE
|
||||
-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
|
||||
)
|
||||
target_link_options(${FSFW_TEST_TGT} PRIVATE -fprofile-arcs
|
||||
-ftest-coverage)
|
||||
target_link_options(${LIB_FSFW_NAME} PRIVATE -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)
|
||||
setup_target_for_coverage_gcovr_html(
|
||||
NAME ${FSFW_TEST_TGT}_coverage
|
||||
EXECUTABLE ${FSFW_TEST_TGT}
|
||||
DEPENDENCIES ${FSFW_TEST_TGT}
|
||||
)
|
||||
else()
|
||||
setup_target_for_coverage_lcov(
|
||||
NAME ${FSFW_TEST_TGT}_coverage
|
||||
EXECUTABLE ${FSFW_TEST_TGT}
|
||||
DEPENDENCIES ${FSFW_TEST_TGT}
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
if(WIN32)
|
||||
setup_target_for_coverage_gcovr_html(
|
||||
NAME ${FSFW_TEST_TGT}_coverage EXECUTABLE ${FSFW_TEST_TGT}
|
||||
DEPENDENCIES ${FSFW_TEST_TGT})
|
||||
else()
|
||||
setup_target_for_coverage_lcov(
|
||||
NAME ${FSFW_TEST_TGT}_coverage EXECUTABLE ${FSFW_TEST_TGT}
|
||||
DEPENDENCIES ${FSFW_TEST_TGT})
|
||||
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()
|
||||
|
||||
# The project CMakeLists file has to set the FSFW_CONFIG_PATH and add it.
|
||||
# If this is not given, we include the default configuration and emit a warning.
|
||||
# The project CMakeLists file has to set the FSFW_CONFIG_PATH and add it. If
|
||||
# this is not given, we include the default configuration and emit a warning.
|
||||
if(NOT FSFW_CONFIG_PATH)
|
||||
set(DEF_CONF_PATH misc/defaultcfg/fsfwconfig)
|
||||
if(NOT FSFW_BUILD_DOCS)
|
||||
message(WARNING "${MSG_PREFIX} Flight Software Framework configuration path not set")
|
||||
message(WARNING "${MSG_PREFIX} Setting default configuration from ${DEF_CONF_PATH} ..")
|
||||
endif()
|
||||
add_subdirectory(${DEF_CONF_PATH})
|
||||
set(FSFW_CONFIG_PATH ${DEF_CONF_PATH})
|
||||
set(DEF_CONF_PATH misc/defaultcfg/fsfwconfig)
|
||||
if(NOT FSFW_BUILD_DOCS)
|
||||
message(
|
||||
WARNING
|
||||
"${MSG_PREFIX} Flight Software Framework configuration path not set")
|
||||
message(
|
||||
WARNING
|
||||
"${MSG_PREFIX} Setting default configuration from ${DEF_CONF_PATH} ..")
|
||||
endif()
|
||||
add_subdirectory(${DEF_CONF_PATH})
|
||||
set(FSFW_CONFIG_PATH ${DEF_CONF_PATH})
|
||||
endif()
|
||||
|
||||
# FSFW might be part of a possibly complicated folder structure, so we
|
||||
# extract the absolute path of the fsfwconfig folder.
|
||||
# FSFW might be part of a possibly complicated folder structure, so we extract
|
||||
# the absolute path of the fsfwconfig folder.
|
||||
if(IS_ABSOLUTE ${FSFW_CONFIG_PATH})
|
||||
set(FSFW_CONFIG_PATH_ABSOLUTE ${FSFW_CONFIG_PATH})
|
||||
set(FSFW_CONFIG_PATH_ABSOLUTE ${FSFW_CONFIG_PATH})
|
||||
else()
|
||||
get_filename_component(FSFW_CONFIG_PATH_ABSOLUTE
|
||||
${FSFW_CONFIG_PATH} REALPATH BASE_DIR ${CMAKE_SOURCE_DIR}
|
||||
)
|
||||
get_filename_component(FSFW_CONFIG_PATH_ABSOLUTE ${FSFW_CONFIG_PATH} REALPATH
|
||||
BASE_DIR ${CMAKE_SOURCE_DIR})
|
||||
endif()
|
||||
|
||||
foreach(INCLUDE_PATH ${FSFW_ADDITIONAL_INC_PATHS})
|
||||
if(IS_ABSOLUTE ${INCLUDE_PATH})
|
||||
set(CURR_ABS_INC_PATH "${INCLUDE_PATH}")
|
||||
else()
|
||||
get_filename_component(CURR_ABS_INC_PATH
|
||||
${INCLUDE_PATH} REALPATH BASE_DIR ${CMAKE_SOURCE_DIR})
|
||||
endif()
|
||||
if(IS_ABSOLUTE ${INCLUDE_PATH})
|
||||
set(CURR_ABS_INC_PATH "${INCLUDE_PATH}")
|
||||
else()
|
||||
get_filename_component(CURR_ABS_INC_PATH ${INCLUDE_PATH} REALPATH BASE_DIR
|
||||
${CMAKE_SOURCE_DIR})
|
||||
endif()
|
||||
|
||||
if(CMAKE_VERBOSE)
|
||||
message(STATUS "FSFW include path: ${CURR_ABS_INC_PATH}")
|
||||
endif()
|
||||
if(CMAKE_VERBOSE)
|
||||
message(STATUS "FSFW include path: ${CURR_ABS_INC_PATH}")
|
||||
endif()
|
||||
|
||||
list(APPEND FSFW_ADD_INC_PATHS_ABS ${CURR_ABS_INC_PATH})
|
||||
list(APPEND FSFW_ADD_INC_PATHS_ABS ${CURR_ABS_INC_PATH})
|
||||
endforeach()
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
if(NOT DEFINED FSFW_WARNING_FLAGS)
|
||||
set(FSFW_WARNING_FLAGS
|
||||
-Wall
|
||||
-Wextra
|
||||
-Wimplicit-fallthrough=1
|
||||
-Wno-unused-parameter
|
||||
-Wno-psabi
|
||||
-Wduplicated-cond # check for duplicate conditions
|
||||
-Wduplicated-branches # check for duplicate branches
|
||||
-Wlogical-op # Search for bitwise operations instead of logical
|
||||
-Wnull-dereference # Search for NULL dereference
|
||||
-Wundef # Warn if undefind marcos are used
|
||||
-Wformat=2 # Format string problem detection
|
||||
-Wformat-overflow=2 # Formatting issues in printf
|
||||
-Wformat-truncation=2 # Formatting issues in printf
|
||||
-Wformat-security # Search for dangerous printf operations
|
||||
-Wstrict-overflow=3 # Warn if integer overflows might happen
|
||||
-Warray-bounds=2 # Some array bounds violations will be found
|
||||
-Wshift-overflow=2 # Search for bit left shift overflows (<c++14)
|
||||
-Wcast-qual # Warn if the constness is cast away
|
||||
-Wstringop-overflow=4
|
||||
# -Wstack-protector # Emits a few false positives for low level access
|
||||
# -Wconversion # Creates many false positives
|
||||
# -Warith-conversion # Use with Wconversion to find more implicit conversions
|
||||
# -fanalyzer # Should be used to look through problems
|
||||
)
|
||||
endif()
|
||||
if(NOT DEFINED FSFW_WARNING_FLAGS)
|
||||
set(FSFW_WARNING_FLAGS
|
||||
-Wall
|
||||
-Wextra
|
||||
-Wimplicit-fallthrough=1
|
||||
-Wno-unused-parameter
|
||||
-Wno-psabi
|
||||
-Wduplicated-cond # check for duplicate conditions
|
||||
-Wduplicated-branches # check for duplicate branches
|
||||
-Wlogical-op # Search for bitwise operations instead of logical
|
||||
-Wnull-dereference # Search for NULL dereference
|
||||
-Wundef # Warn if undefind marcos are used
|
||||
-Wformat=2 # Format string problem detection
|
||||
-Wformat-overflow=2 # Formatting issues in printf
|
||||
-Wformat-truncation=2 # Formatting issues in printf
|
||||
-Wformat-security # Search for dangerous printf operations
|
||||
-Wstrict-overflow=3 # Warn if integer overflows might happen
|
||||
-Warray-bounds=2 # Some array bounds violations will be found
|
||||
-Wshift-overflow=2 # Search for bit left shift overflows (<c++14)
|
||||
-Wcast-qual # Warn if the constness is cast away
|
||||
-Wstringop-overflow=4
|
||||
# -Wstack-protector # Emits a few false positives for low level access
|
||||
# -Wconversion # Creates many false positives -Warith-conversion # Use
|
||||
# with Wconversion to find more implicit conversions -fanalyzer # Should
|
||||
# be used to look through problems
|
||||
)
|
||||
endif()
|
||||
|
||||
if(FSFW_GENERATE_SECTIONS)
|
||||
target_compile_options(${LIB_FSFW_NAME} PRIVATE
|
||||
"-ffunction-sections"
|
||||
"-fdata-sections"
|
||||
)
|
||||
endif()
|
||||
if(FSFW_GENERATE_SECTIONS)
|
||||
target_compile_options(${LIB_FSFW_NAME} PRIVATE "-ffunction-sections"
|
||||
"-fdata-sections")
|
||||
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()
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
set(COMPILER_FLAGS "/permissive-")
|
||||
set(COMPILER_FLAGS "/permissive-")
|
||||
endif()
|
||||
|
||||
# Required include paths to compile the FSFW
|
||||
target_include_directories(${LIB_FSFW_NAME} INTERFACE
|
||||
${CMAKE_SOURCE_DIR}
|
||||
${FSFW_CONFIG_PATH_ABSOLUTE}
|
||||
${FSFW_CORE_INC_PATH}
|
||||
${FSFW_ADD_INC_PATHS_ABS}
|
||||
)
|
||||
target_include_directories(
|
||||
${LIB_FSFW_NAME} INTERFACE ${CMAKE_SOURCE_DIR} ${FSFW_CONFIG_PATH_ABSOLUTE}
|
||||
${FSFW_CORE_INC_PATH} ${FSFW_ADD_INC_PATHS_ABS})
|
||||
|
||||
# Includes path required to compile FSFW itself as well
|
||||
# We assume that the fsfwconfig folder uses include relative to the project
|
||||
# root here!
|
||||
target_include_directories(${LIB_FSFW_NAME} PRIVATE
|
||||
${CMAKE_SOURCE_DIR}
|
||||
${FSFW_CONFIG_PATH_ABSOLUTE}
|
||||
${FSFW_CORE_INC_PATH}
|
||||
${FSFW_ADD_INC_PATHS_ABS}
|
||||
)
|
||||
# Includes path required to compile FSFW itself as well We assume that the
|
||||
# fsfwconfig folder uses include relative to the project root here!
|
||||
target_include_directories(
|
||||
${LIB_FSFW_NAME} PRIVATE ${CMAKE_SOURCE_DIR} ${FSFW_CONFIG_PATH_ABSOLUTE}
|
||||
${FSFW_CORE_INC_PATH} ${FSFW_ADD_INC_PATHS_ABS})
|
||||
|
||||
target_compile_options(${LIB_FSFW_NAME} PRIVATE
|
||||
${FSFW_WARNING_FLAGS}
|
||||
${COMPILER_FLAGS}
|
||||
)
|
||||
target_compile_options(${LIB_FSFW_NAME} PRIVATE ${FSFW_WARNING_FLAGS}
|
||||
${COMPILER_FLAGS})
|
||||
|
||||
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
|
||||
${FSFW_ADDITIONAL_LINK_LIBS}
|
||||
)
|
||||
target_link_libraries(${LIB_FSFW_NAME} PRIVATE ${FSFW_ETL_LINK_TARGET}
|
||||
${FSFW_ADDITIONAL_LINK_LIBS})
|
||||
|
||||
string(CONCAT POST_BUILD_COMMENT
|
||||
string(
|
||||
CONCAT
|
||||
POST_BUILD_COMMENT
|
||||
"######################################################################\n"
|
||||
"Built FSFW v${FSFW_VERSION}.${FSFW_SUBVERSION}.${FSFW_REVISION}, "
|
||||
"Target OSAL: ${FSFW_OS_NAME}\n"
|
||||
"######################################################################\n"
|
||||
)
|
||||
"######################################################################\n")
|
||||
|
||||
add_custom_command(
|
||||
TARGET ${LIB_FSFW_NAME}
|
||||
POST_BUILD
|
||||
COMMENT ${POST_BUILD_COMMENT}
|
||||
)
|
||||
TARGET ${LIB_FSFW_NAME}
|
||||
POST_BUILD
|
||||
COMMENT ${POST_BUILD_COMMENT})
|
||||
|
0
FSFWVersion.h.in
Normal file
0
FSFWVersion.h.in
Normal file
49
README.md
49
README.md
@ -11,9 +11,15 @@ with Airbus Defence and Space GmbH.
|
||||
|
||||
## Quick facts
|
||||
|
||||
The framework is designed for systems, which communicate with external devices, perform control loops, receive telecommands and send telemetry, and need to maintain a high level of availability. Therefore, a mode and health system provides control over the states of the software and the controlled devices. In addition, a simple mechanism of event based fault detection, isolation and recovery is implemented as well.
|
||||
The framework is designed for systems, which communicate with external devices, perform control loops,
|
||||
receive telecommands and send telemetry, and need to maintain a high level of availability. Therefore,
|
||||
a mode and health system provides control over the states of the software and the controlled devices.
|
||||
In addition, a simple mechanism of event based fault detection, isolation and recovery is implemented as well.
|
||||
|
||||
The FSFW provides abstraction layers for operating systems to provide a uniform operating system abstraction layer (OSAL). Some components of this OSAL are required internally by the FSFW but is also very useful for developers to implement the same application logic on different operating systems with a uniform interface.
|
||||
The FSFW provides abstraction layers for operating systems to provide a uniform operating system
|
||||
abstraction layer (OSAL). Some components of this OSAL are required internally by the FSFW but is
|
||||
also very useful for developers to implement the same application logic on different operating
|
||||
systems with a uniform interface.
|
||||
|
||||
Currently, the FSFW provides the following OSALs:
|
||||
|
||||
@ -45,6 +51,28 @@ A template configuration folder was provided and can be copied into the project
|
||||
a starting point. The [configuration section](docs/README-config.md#top) provides more specific
|
||||
information about the possible options.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
The Embedded Template Library (etl) is a dependency of the FSFW which is automatically
|
||||
installed and provided by the build system unless the correction version was installed.
|
||||
The current recommended version can be found inside the fsfw `CMakeLists.txt` file or by using
|
||||
`ccmake` and looking up the `FSFW_ETL_LIB_MAJOR_VERSION` variable.
|
||||
|
||||
You can install the ETL library like this. On Linux, it might be necessary to add `sudo` before
|
||||
the install call:
|
||||
|
||||
```cpp
|
||||
git clone https://github.com/ETLCPP/etl
|
||||
cd etl
|
||||
git checkout <currentRecommendedVersion>
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
cmake --install .
|
||||
```
|
||||
|
||||
It is recommended to install `20.27.2` or newer for the package version handling of
|
||||
ETL to work.
|
||||
|
||||
## Adding the library
|
||||
|
||||
The following steps show how to add and use FSFW components. It is still recommended to
|
||||
@ -71,7 +99,7 @@ add and link against the FSFW library in general.
|
||||
|
||||
4. Link against the FSFW library
|
||||
|
||||
```cmake
|
||||
```sh
|
||||
target_link_libraries(${YourProjectName} PRIVATE fsfw)
|
||||
```
|
||||
|
||||
@ -83,6 +111,19 @@ The FSFW also has unittests which use the [Catch2 library](https://github.com/ca
|
||||
These are built by setting the CMake option `FSFW_BUILD_UNITTESTS` to `ON` or `TRUE`
|
||||
from your project `CMakeLists.txt` file or from the command line.
|
||||
|
||||
You can install the Catch2 library, which prevents the build system to avoid re-downloading
|
||||
the dependency if the unit tests are completely rebuilt. The current recommended version
|
||||
can be found inside the fsfw `CMakeLists.txt` file or by using `ccmake` and looking up
|
||||
the `FSFW_CATCH2_LIB_VERSION` variable.
|
||||
|
||||
```sh
|
||||
git clone https://github.com/catchorg/Catch2.git
|
||||
cd Catch2
|
||||
git checkout <currentRecommendedVersion>
|
||||
cmake -Bbuild -H. -DBUILD_TESTING=OFF
|
||||
sudo cmake --build build/ --target install
|
||||
```
|
||||
|
||||
The fsfw-tests binary will be built as part of the static library and dropped alongside it.
|
||||
If the unittests are built, the library and the tests will be built with coverage information by
|
||||
default. This can be disabled by setting the `FSFW_TESTS_COV_GEN` option to `OFF` or `FALSE`.
|
||||
@ -90,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
|
||||
|
||||
```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 ..
|
||||
```
|
||||
|
||||
|
@ -6,3 +6,15 @@ RUN apt-get --yes upgrade
|
||||
#tzdata is a dependency, won't install otherwise
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
RUN apt-get --yes install gcc g++ cmake make lcov git valgrind nano iputils-ping
|
||||
|
||||
RUN git clone https://github.com/catchorg/Catch2.git && \
|
||||
cd Catch2 && \
|
||||
git checkout v3.0.0-preview5 && \
|
||||
cmake -Bbuild -H. -DBUILD_TESTING=OFF && \
|
||||
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/
|
||||
|
4
automation/Jenkinsfile
vendored
4
automation/Jenkinsfile
vendored
@ -3,7 +3,7 @@ pipeline {
|
||||
BUILDDIR = 'build-tests'
|
||||
}
|
||||
agent {
|
||||
docker { image 'fsfw-ci:d1'}
|
||||
docker { image 'fsfw-ci:d2'}
|
||||
}
|
||||
stages {
|
||||
stage('Clean') {
|
||||
@ -14,7 +14,7 @@ pipeline {
|
||||
stage('Configure') {
|
||||
steps {
|
||||
dir(BUILDDIR) {
|
||||
sh 'cmake -DFSFW_OSAL=host -DFSFW_BUILD_UNITTESTS=ON ..'
|
||||
sh 'cmake -DFSFW_OSAL=host -DFSFW_BUILD_UNITTESTS=ON -DFSFW_CICD_BUILD=ON ..'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,141 +0,0 @@
|
||||
# - 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> [<additional arguments to git describe> ...])
|
||||
#
|
||||
# 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_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.
|
||||
#
|
||||
# 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 Iowa State University 2009-2010.
|
||||
# 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(get_git_head_revision _refspecvar _hashvar)
|
||||
set(GIT_PARENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
set(GIT_DIR "${GIT_PARENT_DIR}/.git")
|
||||
while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories
|
||||
set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}")
|
||||
get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH)
|
||||
if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT)
|
||||
# We have reached the root directory, we are not in git
|
||||
set(${_refspecvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
|
||||
set(${_hashvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
set(GIT_DIR "${GIT_PARENT_DIR}/.git")
|
||||
endwhile()
|
||||
# check if this is a submodule
|
||||
if(NOT IS_DIRECTORY ${GIT_DIR})
|
||||
file(READ ${GIT_DIR} submodule)
|
||||
string(REGEX REPLACE "gitdir: (.*)\n$" "\\1" GIT_DIR_RELATIVE ${submodule})
|
||||
get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH)
|
||||
|
||||
if (IS_ABSOLUTE ${GIT_DIR_RELATIVE})
|
||||
set(GIT_DIR ${GIT_DIR_RELATIVE})
|
||||
else()
|
||||
get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} ABSOLUTE)
|
||||
endif()
|
||||
|
||||
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 "${GIT_DIR}/HEAD")
|
||||
return()
|
||||
endif()
|
||||
set(HEAD_FILE "${GIT_DATA}/HEAD")
|
||||
configure_file("${GIT_DIR}/HEAD" "${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
|
||||
${hash}
|
||||
${ARGN}
|
||||
WORKING_DIRECTORY
|
||||
"${CMAKE_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_get_tag _var)
|
||||
git_describe(out --tags ${ARGN})
|
||||
set(${_var} "${out}" PARENT_SCOPE)
|
||||
endfunction()
|
@ -1,5 +1,7 @@
|
||||
The files in these folder were manually copy and pasted from the
|
||||
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 license file in included here as well.
|
||||
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.
|
||||
|
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()
|
@ -1,4 +1,4 @@
|
||||
#
|
||||
#
|
||||
# Internal file for GetGitRevisionDescription.cmake
|
||||
#
|
||||
# Requires CMake 2.6 or newer (uses the 'function' command)
|
||||
@ -8,10 +8,12 @@
|
||||
# http://academic.cleardefinition.com
|
||||
# Iowa State University HCI Graduate Program/VRAC
|
||||
#
|
||||
# Copyright Iowa State University 2009-2010.
|
||||
# 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)
|
||||
|
||||
@ -22,10 +24,13 @@ 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)
|
||||
elseif(EXISTS "@GIT_DIR@/logs/${HEAD_REF}")
|
||||
configure_file("@GIT_DIR@/logs/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
|
||||
set(HEAD_HASH "${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
|
||||
@ -33,6 +38,6 @@ else()
|
||||
endif()
|
||||
|
||||
if(NOT HEAD_HASH)
|
||||
file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024)
|
||||
string(STRIP "${HEAD_HASH}" 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.
|
@ -19,6 +19,29 @@ A template configuration folder was provided and can be copied into the project
|
||||
a starting point. The [configuration section](docs/README-config.md#top) provides more specific
|
||||
information about the possible options.
|
||||
|
||||
Prerequisites
|
||||
-------------------
|
||||
|
||||
The Embedded Template Library (etl) is a dependency of the FSFW which is automatically
|
||||
installed and provided by the build system unless the correction version was installed.
|
||||
The current recommended version can be found inside the fsfw ``CMakeLists.txt`` file or by using
|
||||
``ccmake`` and looking up the ``FSFW_ETL_LIB_MAJOR_VERSION`` variable.
|
||||
|
||||
You can install the ETL library like this. On Linux, it might be necessary to add ``sudo`` before
|
||||
the install call:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
git clone https://github.com/ETLCPP/etl
|
||||
cd etl
|
||||
git checkout <currentRecommendedVersion>
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
cmake --install .
|
||||
|
||||
It is recommended to install ``20.27.2`` or newer for the package version handling of
|
||||
ETL to work.
|
||||
|
||||
Adding the library
|
||||
-------------------
|
||||
|
||||
@ -60,6 +83,20 @@ The FSFW also has unittests which use the `Catch2 library`_.
|
||||
These are built by setting the CMake option ``FSFW_BUILD_UNITTESTS`` to ``ON`` or `TRUE`
|
||||
from your project `CMakeLists.txt` file or from the command line.
|
||||
|
||||
You can install the Catch2 library, which prevents the build system to avoid re-downloading
|
||||
the dependency if the unit tests are completely rebuilt. The current recommended version
|
||||
can be found inside the fsfw ``CMakeLists.txt`` file or by using ``ccmake`` and looking up
|
||||
the ``FSFW_CATCH2_LIB_VERSION`` variable.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
git clone https://github.com/catchorg/Catch2.git
|
||||
cd Catch2
|
||||
git checkout <currentRecommendedVersion>
|
||||
cmake -Bbuild -H. -DBUILD_TESTING=OFF
|
||||
sudo cmake --build build/ --target install
|
||||
|
||||
|
||||
The fsfw-tests binary will be built as part of the static library and dropped alongside it.
|
||||
If the unittests are built, the library and the tests will be built with coverage information by
|
||||
default. This can be disabled by setting the `FSFW_TESTS_COV_GEN` option to `OFF` or `FALSE`.
|
||||
|
@ -12,9 +12,14 @@ if(FSFW_HAL_LINUX_ADD_PERIPHERAL_DRIVERS)
|
||||
if(FSFW_HAL_LINUX_ADD_LIBGPIOD)
|
||||
add_subdirectory(gpio)
|
||||
endif()
|
||||
add_subdirectory(spi)
|
||||
add_subdirectory(i2c)
|
||||
add_subdirectory(uart)
|
||||
# Adding those does not really make sense on Apple systems which
|
||||
# are generally host systems. It won't even compile as the headers
|
||||
# are missing
|
||||
if(NOT APPLE)
|
||||
add_subdirectory(i2c)
|
||||
add_subdirectory(spi)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_subdirectory(uio)
|
||||
|
@ -20,7 +20,9 @@ LinuxLibgpioIF::~LinuxLibgpioIF() {
|
||||
ReturnValue_t LinuxLibgpioIF::addGpios(GpioCookie* gpioCookie) {
|
||||
ReturnValue_t result;
|
||||
if (gpioCookie == nullptr) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "LinuxLibgpioIF::addGpios: Invalid cookie" << std::endl;
|
||||
#endif
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
|
||||
@ -44,6 +46,7 @@ ReturnValue_t LinuxLibgpioIF::addGpios(GpioCookie* gpioCookie) {
|
||||
}
|
||||
|
||||
ReturnValue_t LinuxLibgpioIF::configureGpios(GpioMap& mapToAdd) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
for (auto& gpioConfig : mapToAdd) {
|
||||
auto& gpioType = gpioConfig.second->gpioType;
|
||||
switch (gpioType) {
|
||||
@ -55,7 +58,7 @@ ReturnValue_t LinuxLibgpioIF::configureGpios(GpioMap& mapToAdd) {
|
||||
if (regularGpio == nullptr) {
|
||||
return GPIO_INVALID_INSTANCE;
|
||||
}
|
||||
configureGpioByChip(gpioConfig.first, *regularGpio);
|
||||
result = configureGpioByChip(gpioConfig.first, *regularGpio);
|
||||
break;
|
||||
}
|
||||
case (gpio::GpioTypes::GPIO_REGULAR_BY_LABEL): {
|
||||
@ -63,7 +66,7 @@ ReturnValue_t LinuxLibgpioIF::configureGpios(GpioMap& mapToAdd) {
|
||||
if (regularGpio == nullptr) {
|
||||
return GPIO_INVALID_INSTANCE;
|
||||
}
|
||||
configureGpioByLabel(gpioConfig.first, *regularGpio);
|
||||
result = configureGpioByLabel(gpioConfig.first, *regularGpio);
|
||||
break;
|
||||
}
|
||||
case (gpio::GpioTypes::GPIO_REGULAR_BY_LINE_NAME): {
|
||||
@ -71,7 +74,7 @@ ReturnValue_t LinuxLibgpioIF::configureGpios(GpioMap& mapToAdd) {
|
||||
if (regularGpio == nullptr) {
|
||||
return GPIO_INVALID_INSTANCE;
|
||||
}
|
||||
configureGpioByLineName(gpioConfig.first, *regularGpio);
|
||||
result = configureGpioByLineName(gpioConfig.first, *regularGpio);
|
||||
break;
|
||||
}
|
||||
case (gpio::GpioTypes::CALLBACK): {
|
||||
@ -83,8 +86,11 @@ ReturnValue_t LinuxLibgpioIF::configureGpios(GpioMap& mapToAdd) {
|
||||
gpioCallback->initValue, gpioCallback->callbackArgs);
|
||||
}
|
||||
}
|
||||
if (result != RETURN_OK) {
|
||||
return GPIO_INIT_FAILED;
|
||||
}
|
||||
}
|
||||
return RETURN_OK;
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t LinuxLibgpioIF::configureGpioByLabel(gpioId_t gpioId,
|
||||
@ -92,8 +98,10 @@ ReturnValue_t LinuxLibgpioIF::configureGpioByLabel(gpioId_t gpioId,
|
||||
std::string& label = gpioByLabel.label;
|
||||
struct gpiod_chip* chip = gpiod_chip_open_by_label(label.c_str());
|
||||
if (chip == nullptr) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "LinuxLibgpioIF::configureGpioByLabel: Failed to open gpio from gpio "
|
||||
<< "group with label " << label << ". Gpio ID: " << gpioId << std::endl;
|
||||
#endif
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
std::string failOutput = "label: " + label;
|
||||
@ -104,8 +112,10 @@ ReturnValue_t LinuxLibgpioIF::configureGpioByChip(gpioId_t gpioId, GpiodRegularB
|
||||
std::string& chipname = gpioByChip.chipname;
|
||||
struct gpiod_chip* chip = gpiod_chip_open_by_name(chipname.c_str());
|
||||
if (chip == nullptr) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "LinuxLibgpioIF::configureGpioByChip: Failed to open chip " << chipname
|
||||
<< ". Gpio ID: " << gpioId << std::endl;
|
||||
#endif
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
std::string failOutput = "chipname: " + chipname;
|
||||
@ -129,8 +139,10 @@ ReturnValue_t LinuxLibgpioIF::configureGpioByLineName(gpioId_t gpioId,
|
||||
|
||||
struct gpiod_chip* chip = gpiod_chip_open_by_name(chipname);
|
||||
if (chip == nullptr) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "LinuxLibgpioIF::configureGpioByLineName: Failed to open chip " << chipname
|
||||
<< ". <Gpio ID: " << gpioId << std::endl;
|
||||
#endif
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
std::string failOutput = "line name: " + lineName;
|
||||
@ -149,10 +161,12 @@ ReturnValue_t LinuxLibgpioIF::configureRegularGpio(gpioId_t gpioId, struct gpiod
|
||||
lineNum = regularGpio.lineNum;
|
||||
lineHandle = gpiod_chip_get_line(chip, lineNum);
|
||||
if (!lineHandle) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "LinuxLibgpioIF::configureRegularGpio: Failed to open line " << std::endl;
|
||||
sif::warning << "GPIO ID: " << gpioId << ", line number: " << lineNum << ", " << failOutput
|
||||
<< std::endl;
|
||||
sif::warning << "Check if Linux GPIO configuration has changed. " << std::endl;
|
||||
#endif
|
||||
gpiod_chip_close(chip);
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
@ -171,7 +185,9 @@ ReturnValue_t LinuxLibgpioIF::configureRegularGpio(gpioId_t gpioId, struct gpiod
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "LinuxLibgpioIF::configureGpios: Invalid direction specified" << std::endl;
|
||||
#endif
|
||||
return GPIO_INVALID_INSTANCE;
|
||||
}
|
||||
|
||||
@ -200,7 +216,9 @@ ReturnValue_t LinuxLibgpioIF::configureRegularGpio(gpioId_t gpioId, struct gpiod
|
||||
ReturnValue_t LinuxLibgpioIF::pullHigh(gpioId_t gpioId) {
|
||||
gpioMapIter = gpioMap.find(gpioId);
|
||||
if (gpioMapIter == gpioMap.end()) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "LinuxLibgpioIF::pullHigh: Unknown GPIO ID " << gpioId << std::endl;
|
||||
#endif
|
||||
return UNKNOWN_GPIO_ID;
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,8 @@ class LinuxLibgpioIF : public GpioIF, public SystemObject {
|
||||
HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 4);
|
||||
static constexpr ReturnValue_t GPIO_DUPLICATE_DETECTED =
|
||||
HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 5);
|
||||
static constexpr ReturnValue_t GPIO_INIT_FAILED =
|
||||
HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 6);
|
||||
|
||||
LinuxLibgpioIF(object_id_t objectId);
|
||||
virtual ~LinuxLibgpioIF();
|
||||
|
@ -210,7 +210,7 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
ReturnValue_t result = gpioComIF->pullLow(gpioId);
|
||||
result = gpioComIF->pullLow(gpioId);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
#if FSFW_VERBOSE_LEVEL >= 1
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "fsfw_hal/linux/spi/SpiCookie.h"
|
||||
#include "SpiCookie.h"
|
||||
|
||||
SpiCookie::SpiCookie(address_t spiAddress, gpioId_t chipSelect, std::string spiDev,
|
||||
const size_t maxSize, spi::SpiModes spiMode, uint32_t spiSpeed)
|
||||
|
@ -265,6 +265,7 @@ void UartComIF::configureBaudrate(struct termios* options, UartCookie* uartCooki
|
||||
cfsetispeed(options, B230400);
|
||||
cfsetospeed(options, B230400);
|
||||
break;
|
||||
#ifndef __APPLE__
|
||||
case UartBaudRate::RATE_460800:
|
||||
cfsetispeed(options, B460800);
|
||||
cfsetospeed(options, B460800);
|
||||
@ -313,6 +314,7 @@ void UartComIF::configureBaudrate(struct termios* options, UartCookie* uartCooki
|
||||
cfsetispeed(options, B4000000);
|
||||
cfsetospeed(options, B4000000);
|
||||
break;
|
||||
#endif // ! __APPLE__
|
||||
default:
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "UartComIF::configureBaudrate: Baudrate not supported" << std::endl;
|
||||
|
@ -10,6 +10,10 @@
|
||||
#include "stm32h7xx_hal.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 };
|
||||
|
||||
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
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
target_include_directories(${LIB_FSFW_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
target_include_directories(${LIB_FSFW_NAME} INTERFACE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
target_include_directories(${LIB_FSFW_NAME}
|
||||
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
add_subdirectory(fsfw)
|
||||
|
@ -1,6 +1,4 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
version.cpp
|
||||
)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE version.cpp)
|
||||
|
||||
# Core
|
||||
|
||||
@ -37,22 +35,22 @@ add_subdirectory(tmtcservices)
|
||||
# Optional
|
||||
|
||||
if(FSFW_ADD_MONITORING)
|
||||
add_subdirectory(monitoring)
|
||||
add_subdirectory(monitoring)
|
||||
endif()
|
||||
if(FSFW_ADD_PUS)
|
||||
add_subdirectory(pus)
|
||||
add_subdirectory(pus)
|
||||
endif()
|
||||
if(FSFW_ADD_TMSTORAGE)
|
||||
add_subdirectory(tmstorage)
|
||||
add_subdirectory(tmstorage)
|
||||
endif()
|
||||
if(FSFW_ADD_COORDINATES)
|
||||
add_subdirectory(coordinates)
|
||||
add_subdirectory(coordinates)
|
||||
endif()
|
||||
if(FSFW_ADD_RMAP)
|
||||
add_subdirectory(rmap)
|
||||
add_subdirectory(rmap)
|
||||
endif()
|
||||
if(FSFW_ADD_DATALINKLAYER)
|
||||
add_subdirectory(datalinklayer)
|
||||
add_subdirectory(datalinklayer)
|
||||
endif()
|
||||
|
||||
# OSAL
|
||||
|
@ -6,6 +6,6 @@ static constexpr int FSFW_VERSION_MAJOR = @FSFW_VERSION@;
|
||||
static constexpr int FSFW_VERSION_MINOR = @FSFW_SUBVERSION@;
|
||||
static constexpr int FSFW_VERSION_REVISION = @FSFW_REVISION@;
|
||||
// Also contains CST (Commits since tag) information
|
||||
static const char FSFW_VERSION_CST_GIT_SHA1[] = "@FSFW_VERSION_CST_GIT_SHA1@";
|
||||
static const char FSFW_VCS_INFO[] = "@FSFW_VCS_INFO@";
|
||||
|
||||
#endif /* FSFW_VERSION_H_ */
|
||||
|
@ -1,7 +1,3 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
ActionHelper.cpp
|
||||
ActionMessage.cpp
|
||||
CommandActionHelper.cpp
|
||||
SimpleActionHelper.cpp
|
||||
)
|
||||
target_sources(
|
||||
${LIB_FSFW_NAME} PRIVATE ActionHelper.cpp ActionMessage.cpp
|
||||
CommandActionHelper.cpp SimpleActionHelper.cpp)
|
||||
|
@ -1,7 +1,4 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
CFDPHandler.cpp
|
||||
CFDPMessage.cpp
|
||||
)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE CFDPHandler.cpp CFDPMessage.cpp)
|
||||
|
||||
add_subdirectory(pdu)
|
||||
add_subdirectory(tlv)
|
||||
|
@ -1,32 +1,30 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
PduConfig.cpp
|
||||
VarLenField.cpp
|
||||
HeaderSerializer.cpp
|
||||
HeaderDeserializer.cpp
|
||||
FileDirectiveDeserializer.cpp
|
||||
FileDirectiveSerializer.cpp
|
||||
|
||||
AckInfo.cpp
|
||||
AckPduSerializer.cpp
|
||||
AckPduDeserializer.cpp
|
||||
EofInfo.cpp
|
||||
EofPduSerializer.cpp
|
||||
EofPduDeserializer.cpp
|
||||
NakInfo.cpp
|
||||
NakPduSerializer.cpp
|
||||
NakPduDeserializer.cpp
|
||||
FinishedInfo.cpp
|
||||
FinishedPduSerializer.cpp
|
||||
FinishedPduDeserializer.cpp
|
||||
MetadataInfo.cpp
|
||||
MetadataPduSerializer.cpp
|
||||
MetadataPduDeserializer.cpp
|
||||
KeepAlivePduSerializer.cpp
|
||||
KeepAlivePduDeserializer.cpp
|
||||
PromptPduSerializer.cpp
|
||||
PromptPduDeserializer.cpp
|
||||
|
||||
FileDataSerializer.cpp
|
||||
FileDataDeserializer.cpp
|
||||
FileDataInfo.cpp
|
||||
)
|
||||
target_sources(
|
||||
${LIB_FSFW_NAME}
|
||||
PRIVATE PduConfig.cpp
|
||||
VarLenField.cpp
|
||||
HeaderSerializer.cpp
|
||||
HeaderDeserializer.cpp
|
||||
FileDirectiveDeserializer.cpp
|
||||
FileDirectiveSerializer.cpp
|
||||
AckInfo.cpp
|
||||
AckPduSerializer.cpp
|
||||
AckPduDeserializer.cpp
|
||||
EofInfo.cpp
|
||||
EofPduSerializer.cpp
|
||||
EofPduDeserializer.cpp
|
||||
NakInfo.cpp
|
||||
NakPduSerializer.cpp
|
||||
NakPduDeserializer.cpp
|
||||
FinishedInfo.cpp
|
||||
FinishedPduSerializer.cpp
|
||||
FinishedPduDeserializer.cpp
|
||||
MetadataInfo.cpp
|
||||
MetadataPduSerializer.cpp
|
||||
MetadataPduDeserializer.cpp
|
||||
KeepAlivePduSerializer.cpp
|
||||
KeepAlivePduDeserializer.cpp
|
||||
PromptPduSerializer.cpp
|
||||
PromptPduDeserializer.cpp
|
||||
FileDataSerializer.cpp
|
||||
FileDataDeserializer.cpp
|
||||
FileDataInfo.cpp)
|
||||
|
@ -44,7 +44,7 @@ class HeaderSerializer : public SerializeIF, public PduHeaderIF {
|
||||
cfdp::WidthInBytes getLenEntityIds() const override;
|
||||
cfdp::WidthInBytes getLenSeqNum() const override;
|
||||
cfdp::SegmentMetadataFlag getSegmentMetadataFlag() const override;
|
||||
bool hasSegmentMetadataFlag() const;
|
||||
bool hasSegmentMetadataFlag() const override;
|
||||
void setSegmentationControl(cfdp::SegmentationControl);
|
||||
|
||||
void getSourceId(cfdp::EntityId& sourceId) const override;
|
||||
|
@ -1,10 +1,10 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
EntityIdTlv.cpp
|
||||
FilestoreRequestTlv.cpp
|
||||
FilestoreResponseTlv.cpp
|
||||
Lv.cpp
|
||||
Tlv.cpp
|
||||
FlowLabelTlv.cpp
|
||||
MessageToUserTlv.cpp
|
||||
FaultHandlerOverrideTlv.cpp
|
||||
)
|
||||
target_sources(
|
||||
${LIB_FSFW_NAME}
|
||||
PRIVATE EntityIdTlv.cpp
|
||||
FilestoreRequestTlv.cpp
|
||||
FilestoreResponseTlv.cpp
|
||||
Lv.cpp
|
||||
Tlv.cpp
|
||||
FlowLabelTlv.cpp
|
||||
MessageToUserTlv.cpp
|
||||
FaultHandlerOverrideTlv.cpp)
|
||||
|
@ -1,5 +1,2 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
SharedRingBuffer.cpp
|
||||
SimpleRingBuffer.cpp
|
||||
)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE SharedRingBuffer.cpp
|
||||
SimpleRingBuffer.cpp)
|
||||
|
@ -5,89 +5,88 @@
|
||||
#error Include FIFOBase.h before FIFOBase.tpp!
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
inline FIFOBase<T>::FIFOBase(T* values, const size_t maxCapacity):
|
||||
maxCapacity(maxCapacity), values(values){};
|
||||
template <typename T>
|
||||
inline FIFOBase<T>::FIFOBase(T* values, const size_t maxCapacity)
|
||||
: maxCapacity(maxCapacity), values(values){};
|
||||
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
inline ReturnValue_t FIFOBase<T>::insert(T value) {
|
||||
if (full()) {
|
||||
return FULL;
|
||||
} else {
|
||||
values[writeIndex] = value;
|
||||
writeIndex = next(writeIndex);
|
||||
++currentSize;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
if (full()) {
|
||||
return FULL;
|
||||
} else {
|
||||
values[writeIndex] = value;
|
||||
writeIndex = next(writeIndex);
|
||||
++currentSize;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
inline ReturnValue_t FIFOBase<T>::retrieve(T* value) {
|
||||
if (empty()) {
|
||||
return EMPTY;
|
||||
} else {
|
||||
if (value == nullptr){
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
*value = values[readIndex];
|
||||
readIndex = next(readIndex);
|
||||
--currentSize;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
if (empty()) {
|
||||
return EMPTY;
|
||||
} else {
|
||||
if (value == nullptr) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
*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) {
|
||||
if(empty()) {
|
||||
return EMPTY;
|
||||
} else {
|
||||
if (value == nullptr){
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
*value = values[readIndex];
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
if (empty()) {
|
||||
return EMPTY;
|
||||
} else {
|
||||
if (value == nullptr) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
*value = values[readIndex];
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
inline ReturnValue_t FIFOBase<T>::pop() {
|
||||
T value;
|
||||
return this->retrieve(&value);
|
||||
T value;
|
||||
return this->retrieve(&value);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
inline bool FIFOBase<T>::empty() {
|
||||
return (currentSize == 0);
|
||||
return (currentSize == 0);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
inline bool FIFOBase<T>::full() {
|
||||
return (currentSize == maxCapacity);
|
||||
return (currentSize == maxCapacity);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
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) {
|
||||
++current;
|
||||
if (current == maxCapacity) {
|
||||
current = 0;
|
||||
}
|
||||
return current;
|
||||
++current;
|
||||
if (current == maxCapacity) {
|
||||
current = 0;
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
inline size_t FIFOBase<T>::getMaxCapacity() const {
|
||||
return maxCapacity;
|
||||
return maxCapacity;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
inline void FIFOBase<T>::setContainer(T *data) {
|
||||
this->values = data;
|
||||
template <typename T>
|
||||
inline void FIFOBase<T>::setContainer(T* data) {
|
||||
this->values = data;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define FIXEDARRAYLIST_H_
|
||||
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
|
||||
#include "ArrayList.h"
|
||||
/**
|
||||
@ -9,10 +10,9 @@
|
||||
*/
|
||||
template <typename T, size_t MAX_SIZE, typename count_t = uint8_t>
|
||||
class FixedArrayList : public ArrayList<T, count_t> {
|
||||
#if !defined(_MSC_VER)
|
||||
static_assert(MAX_SIZE <= (std::pow(2, sizeof(count_t) * 8) - 1),
|
||||
static_assert(MAX_SIZE <= std::numeric_limits<count_t>::max(),
|
||||
"count_t is not large enough to hold MAX_SIZE");
|
||||
#endif
|
||||
|
||||
private:
|
||||
T data[MAX_SIZE];
|
||||
|
||||
|
@ -1,109 +1,109 @@
|
||||
#ifndef FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_
|
||||
#define FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_
|
||||
|
||||
|
||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
||||
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::insert(key_t key, T value, Iterator *storedValue) {
|
||||
if (_size == theMap.maxSize()) {
|
||||
return MAP_FULL;
|
||||
}
|
||||
size_t position = findNicePlace(key);
|
||||
memmove(static_cast<void*>(&theMap[position + 1]),static_cast<void*>(&theMap[position]),
|
||||
(_size - position) * sizeof(std::pair<key_t,T>));
|
||||
theMap[position].first = key;
|
||||
theMap[position].second = value;
|
||||
++_size;
|
||||
if (storedValue != nullptr) {
|
||||
*storedValue = Iterator(&theMap[position]);
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
template <typename key_t, typename T, typename KEY_COMPARE>
|
||||
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::insert(key_t key, T value,
|
||||
Iterator *storedValue) {
|
||||
if (_size == theMap.maxSize()) {
|
||||
return MAP_FULL;
|
||||
}
|
||||
size_t position = findNicePlace(key);
|
||||
memmove(static_cast<void *>(&theMap[position + 1]), static_cast<void *>(&theMap[position]),
|
||||
(_size - position) * sizeof(std::pair<key_t, T>));
|
||||
theMap[position].first = key;
|
||||
theMap[position].second = value;
|
||||
++_size;
|
||||
if (storedValue != nullptr) {
|
||||
*storedValue = Iterator(&theMap[position]);
|
||||
}
|
||||
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) {
|
||||
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 {
|
||||
ReturnValue_t result = KEY_DOES_NOT_EXIST;
|
||||
if (findFirstIndex(key) < _size) {
|
||||
result = HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
return result;
|
||||
ReturnValue_t result = KEY_DOES_NOT_EXIST;
|
||||
if (findFirstIndex(key) < _size) {
|
||||
result = HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
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) {
|
||||
size_t i;
|
||||
if ((i = findFirstIndex((*iter).value->first)) >= _size) {
|
||||
return KEY_DOES_NOT_EXIST;
|
||||
}
|
||||
removeFromPosition(i);
|
||||
if (*iter != begin()) {
|
||||
(*iter)--;
|
||||
} else {
|
||||
*iter = begin();
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
size_t i;
|
||||
if ((i = findFirstIndex((*iter).value->first)) >= _size) {
|
||||
return KEY_DOES_NOT_EXIST;
|
||||
}
|
||||
removeFromPosition(i);
|
||||
if (*iter != begin()) {
|
||||
(*iter)--;
|
||||
} else {
|
||||
*iter = begin();
|
||||
}
|
||||
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) {
|
||||
size_t i;
|
||||
if ((i = findFirstIndex(key)) >= _size) {
|
||||
return KEY_DOES_NOT_EXIST;
|
||||
}
|
||||
do {
|
||||
removeFromPosition(i);
|
||||
i = findFirstIndex(key, i);
|
||||
} while (i < _size);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
size_t i;
|
||||
if ((i = findFirstIndex(key)) >= _size) {
|
||||
return KEY_DOES_NOT_EXIST;
|
||||
}
|
||||
do {
|
||||
removeFromPosition(i);
|
||||
i = findFirstIndex(key, i);
|
||||
} while (i < _size);
|
||||
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 {
|
||||
ReturnValue_t result = exists(key);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
*value = &theMap[findFirstIndex(key)].second;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
ReturnValue_t result = exists(key);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
*value = &theMap[findFirstIndex(key)].second;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
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 {
|
||||
if (startAt >= _size) {
|
||||
return startAt + 1;
|
||||
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 {
|
||||
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) {
|
||||
if (theMap[i].first == key) {
|
||||
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 size_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::findNicePlace(key_t key) const {
|
||||
size_t i = 0;
|
||||
for (i = 0; i < _size; ++i) {
|
||||
if (myComp(key, theMap[i].first)) {
|
||||
return i;
|
||||
}
|
||||
size_t i = 0;
|
||||
for (i = 0; i < _size; ++i) {
|
||||
if (myComp(key, theMap[i].first)) {
|
||||
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) {
|
||||
if (_size <= position) {
|
||||
return;
|
||||
}
|
||||
memmove(static_cast<void*>(&theMap[position]), static_cast<void*>(&theMap[position + 1]),
|
||||
(_size - position - 1) * sizeof(std::pair<key_t,T>));
|
||||
--_size;
|
||||
if (_size <= position) {
|
||||
return;
|
||||
}
|
||||
memmove(static_cast<void *>(&theMap[position]), static_cast<void *>(&theMap[position + 1]),
|
||||
(_size - position - 1) * sizeof(std::pair<key_t, T>));
|
||||
--_size;
|
||||
}
|
||||
|
||||
|
||||
#endif /* FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_ */
|
||||
|
@ -10,16 +10,23 @@ class HybridIterator : public LinkedElement<T>::Iterator, public ArrayList<T, co
|
||||
HybridIterator() {}
|
||||
|
||||
HybridIterator(typename LinkedElement<T>::Iterator *iter)
|
||||
: LinkedElement<T>::Iterator(*iter), value(iter->value), linked(true) {}
|
||||
: LinkedElement<T>::Iterator(*iter), linked(true) {
|
||||
if (iter != nullptr) {
|
||||
value = iter->value;
|
||||
}
|
||||
}
|
||||
|
||||
HybridIterator(LinkedElement<T> *start)
|
||||
: LinkedElement<T>::Iterator(start), value(start->value), linked(true) {}
|
||||
HybridIterator(LinkedElement<T> *start) : LinkedElement<T>::Iterator(start), linked(true) {
|
||||
if (start != nullptr) {
|
||||
value = start->value;
|
||||
}
|
||||
}
|
||||
|
||||
HybridIterator(typename ArrayList<T, count_t>::Iterator start,
|
||||
typename ArrayList<T, count_t>::Iterator end)
|
||||
: ArrayList<T, count_t>::Iterator(start), value(start.value), linked(false), end(end.value) {
|
||||
if (value == this->end) {
|
||||
value = NULL;
|
||||
value = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,2 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
ControllerBase.cpp
|
||||
ExtendedControllerBase.cpp
|
||||
)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE ControllerBase.cpp
|
||||
ExtendedControllerBase.cpp)
|
||||
|
@ -55,7 +55,7 @@ class ControllerBase : public HasModesIF,
|
||||
virtual void performControlOperation() = 0;
|
||||
|
||||
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
||||
uint32_t *msToReachTheMode) = 0;
|
||||
uint32_t *msToReachTheMode) override = 0;
|
||||
|
||||
const object_id_t parentId;
|
||||
|
||||
@ -80,9 +80,9 @@ class ControllerBase : public HasModesIF,
|
||||
|
||||
/** Mode helpers */
|
||||
virtual void modeChanged(Mode_t mode, Submode_t submode);
|
||||
virtual void startTransition(Mode_t mode, Submode_t submode);
|
||||
virtual void getMode(Mode_t *mode, Submode_t *submode);
|
||||
virtual void setToExternalControl();
|
||||
virtual void startTransition(Mode_t mode, Submode_t submode) override;
|
||||
virtual void getMode(Mode_t *mode, Submode_t *submode) override;
|
||||
virtual void setToExternalControl() override;
|
||||
virtual void announceMode(bool recursive);
|
||||
/** HK helpers */
|
||||
virtual void changeHK(Mode_t mode, Submode_t submode, bool enable);
|
||||
|
@ -1,5 +1,2 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
CoordinateTransformations.cpp
|
||||
Sgp4Propagator.cpp
|
||||
)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE CoordinateTransformations.cpp
|
||||
Sgp4Propagator.cpp)
|
||||
|
@ -1,12 +1,11 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
Clcw.cpp
|
||||
DataLinkLayer.cpp
|
||||
Farm1StateLockout.cpp
|
||||
Farm1StateOpen.cpp
|
||||
Farm1StateWait.cpp
|
||||
MapPacketExtraction.cpp
|
||||
TcTransferFrame.cpp
|
||||
TcTransferFrameLocal.cpp
|
||||
VirtualChannelReception.cpp
|
||||
)
|
||||
target_sources(
|
||||
${LIB_FSFW_NAME}
|
||||
PRIVATE Clcw.cpp
|
||||
DataLinkLayer.cpp
|
||||
Farm1StateLockout.cpp
|
||||
Farm1StateOpen.cpp
|
||||
Farm1StateWait.cpp
|
||||
MapPacketExtraction.cpp
|
||||
TcTransferFrame.cpp
|
||||
TcTransferFrameLocal.cpp
|
||||
VirtualChannelReception.cpp)
|
||||
|
@ -1,4 +1 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
PoolDataSetBase.cpp
|
||||
PoolEntry.cpp
|
||||
)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE PoolDataSetBase.cpp PoolEntry.cpp)
|
||||
|
@ -109,7 +109,7 @@ class PoolDataSetBase : public PoolDataSetIF, public SerializeIF, public HasRetu
|
||||
*/
|
||||
virtual ReturnValue_t unlockDataPool() override;
|
||||
|
||||
virtual uint16_t getFillCount() const;
|
||||
virtual uint16_t getFillCount() const override;
|
||||
|
||||
/* SerializeIF implementations */
|
||||
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, const size_t maxSize,
|
||||
|
@ -1,10 +1,6 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
LocalDataPoolManager.cpp
|
||||
LocalDataSet.cpp
|
||||
LocalPoolDataSetBase.cpp
|
||||
LocalPoolObjectBase.cpp
|
||||
SharedLocalDataSet.cpp
|
||||
)
|
||||
target_sources(
|
||||
${LIB_FSFW_NAME}
|
||||
PRIVATE LocalDataPoolManager.cpp LocalDataSet.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) {
|
||||
/* Configuration error */
|
||||
#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
|
||||
sif::printWarning("LocalDataPoolManager::performHkOperation: HK generation failed.\n");
|
||||
sif::printWarning("LocalDataPoolManager::performPeriodicHkOperation: HK generation failed.\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -94,13 +94,14 @@ ReturnValue_t LocalPoolDataSetBase::serializeWithValidityBuffer(
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
const uint8_t validityMaskSize = std::ceil(static_cast<float>(fillCount) / 8.0);
|
||||
uint8_t *validityPtr = nullptr;
|
||||
#ifdef _MSC_VER
|
||||
/* Use a std::vector here because MSVC will (rightly) not create a fixed size array
|
||||
with a non constant size specifier */
|
||||
std::vector<uint8_t> validityMask(validityMaskSize);
|
||||
#if defined(_MSC_VER) || defined(__clang__)
|
||||
// Use a std::vector here because MSVC will (rightly) not create a fixed size array
|
||||
// with a non constant size specifier. The Apple compiler (LLVM) will not accept
|
||||
// the initialization of a variable sized array
|
||||
std::vector<uint8_t> validityMask(validityMaskSize, 0);
|
||||
validityPtr = validityMask.data();
|
||||
#else
|
||||
uint8_t validityMask[validityMaskSize] = {0};
|
||||
uint8_t validityMask[validityMaskSize] = {};
|
||||
validityPtr = validityMask;
|
||||
#endif
|
||||
uint8_t validBufferIndex = 0;
|
||||
|
@ -23,8 +23,8 @@ class LocalPoolObjectBase : public PoolVariableIF, public HasReturnvaluesIF, pub
|
||||
LocalPoolObjectBase(object_id_t poolOwner, lp_id_t poolId, DataSetIF* dataSet = nullptr,
|
||||
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
|
||||
|
||||
void setReadWriteMode(pool_rwm_t newReadWriteMode);
|
||||
pool_rwm_t getReadWriteMode() const;
|
||||
void setReadWriteMode(pool_rwm_t newReadWriteMode) override;
|
||||
pool_rwm_t getReadWriteMode() const override;
|
||||
|
||||
bool isValid() const override;
|
||||
void setValid(bool valid) override;
|
||||
|
@ -5,205 +5,189 @@
|
||||
#error Include LocalPoolVariable.h before LocalPoolVariable.tpp!
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
inline LocalPoolVariable<T>::LocalPoolVariable(HasLocalDataPoolIF* hkOwner,
|
||||
lp_id_t poolId, DataSetIF* dataSet, pool_rwm_t setReadWriteMode):
|
||||
LocalPoolObjectBase(poolId, hkOwner, dataSet, setReadWriteMode) {}
|
||||
template <typename T>
|
||||
inline LocalPoolVariable<T>::LocalPoolVariable(HasLocalDataPoolIF* hkOwner, lp_id_t poolId,
|
||||
DataSetIF* dataSet, pool_rwm_t setReadWriteMode)
|
||||
: LocalPoolObjectBase(poolId, hkOwner, dataSet, setReadWriteMode) {}
|
||||
|
||||
template<typename T>
|
||||
inline LocalPoolVariable<T>::LocalPoolVariable(object_id_t poolOwner,
|
||||
lp_id_t poolId, DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
|
||||
LocalPoolObjectBase(poolOwner, poolId, dataSet, setReadWriteMode) {}
|
||||
template <typename T>
|
||||
inline LocalPoolVariable<T>::LocalPoolVariable(object_id_t poolOwner, lp_id_t poolId,
|
||||
DataSetIF* dataSet, pool_rwm_t 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>
|
||||
inline LocalPoolVariable<T>::LocalPoolVariable(gp_id_t globalPoolId,
|
||||
DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
|
||||
LocalPoolObjectBase(globalPoolId.objectId, globalPoolId.localPoolId,
|
||||
dataSet, setReadWriteMode){}
|
||||
|
||||
|
||||
template<typename T>
|
||||
inline ReturnValue_t LocalPoolVariable<T>::read(
|
||||
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();
|
||||
template <typename T>
|
||||
inline ReturnValue_t LocalPoolVariable<T>::read(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;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
inline ReturnValue_t LocalPoolVariable<T>::readWithoutLock() {
|
||||
if(readWriteMode == pool_rwm_t::VAR_WRITE) {
|
||||
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
||||
reportReadCommitError("LocalPoolVector",
|
||||
PoolVariableIF::INVALID_READ_WRITE_MODE, true, targetObjectId,
|
||||
localPoolId);
|
||||
return PoolVariableIF::INVALID_READ_WRITE_MODE;
|
||||
}
|
||||
if (readWriteMode == pool_rwm_t::VAR_WRITE) {
|
||||
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
||||
reportReadCommitError("LocalPoolVector", PoolVariableIF::INVALID_READ_WRITE_MODE, true,
|
||||
targetObjectId, localPoolId);
|
||||
return PoolVariableIF::INVALID_READ_WRITE_MODE;
|
||||
}
|
||||
|
||||
PoolEntry<T>* poolEntry = nullptr;
|
||||
ReturnValue_t result = LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId,
|
||||
&poolEntry);
|
||||
if(result != RETURN_OK) {
|
||||
object_id_t ownerObjectId = hkManager->getCreatorObjectId();
|
||||
reportReadCommitError("LocalPoolVariable", result,
|
||||
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();
|
||||
PoolEntry<T>* poolEntry = nullptr;
|
||||
ReturnValue_t result =
|
||||
LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId, &poolEntry);
|
||||
if (result != RETURN_OK) {
|
||||
object_id_t ownerObjectId = hkManager->getCreatorObjectId();
|
||||
reportReadCommitError("LocalPoolVariable", result, false, ownerObjectId, localPoolId);
|
||||
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() {
|
||||
if(readWriteMode == pool_rwm_t::VAR_READ) {
|
||||
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
||||
reportReadCommitError("LocalPoolVector",
|
||||
PoolVariableIF::INVALID_READ_WRITE_MODE, false, targetObjectId,
|
||||
localPoolId);
|
||||
return PoolVariableIF::INVALID_READ_WRITE_MODE;
|
||||
}
|
||||
if (readWriteMode == pool_rwm_t::VAR_READ) {
|
||||
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
||||
reportReadCommitError("LocalPoolVector", PoolVariableIF::INVALID_READ_WRITE_MODE, false,
|
||||
targetObjectId, localPoolId);
|
||||
return PoolVariableIF::INVALID_READ_WRITE_MODE;
|
||||
}
|
||||
|
||||
PoolEntry<T>* poolEntry = nullptr;
|
||||
ReturnValue_t result = LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId,
|
||||
&poolEntry);
|
||||
if(result != RETURN_OK) {
|
||||
object_id_t ownerObjectId = hkManager->getCreatorObjectId();
|
||||
reportReadCommitError("LocalPoolVariable", result,
|
||||
false, ownerObjectId, localPoolId);
|
||||
return result;
|
||||
}
|
||||
PoolEntry<T>* poolEntry = nullptr;
|
||||
ReturnValue_t result =
|
||||
LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId, &poolEntry);
|
||||
if (result != RETURN_OK) {
|
||||
object_id_t ownerObjectId = hkManager->getCreatorObjectId();
|
||||
reportReadCommitError("LocalPoolVariable", result, false, ownerObjectId, localPoolId);
|
||||
return result;
|
||||
}
|
||||
|
||||
*(poolEntry->getDataPtr()) = this->value;
|
||||
poolEntry->setValid(this->valid);
|
||||
return RETURN_OK;
|
||||
*(poolEntry->getDataPtr()) = this->value;
|
||||
poolEntry->setValid(this->valid);
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline ReturnValue_t LocalPoolVariable<T>::serialize(uint8_t** buffer,
|
||||
size_t* size, const size_t max_size,
|
||||
SerializeIF::Endianness streamEndianness) const {
|
||||
return SerializeAdapter::serialize(&value,
|
||||
buffer, size ,max_size, streamEndianness);
|
||||
template <typename T>
|
||||
inline ReturnValue_t LocalPoolVariable<T>::serialize(
|
||||
uint8_t** buffer, size_t* size, const size_t max_size,
|
||||
SerializeIF::Endianness streamEndianness) const {
|
||||
return SerializeAdapter::serialize(&value, buffer, size, max_size, streamEndianness);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
inline size_t LocalPoolVariable<T>::getSerializedSize() const {
|
||||
return SerializeAdapter::getSerializedSize(&value);
|
||||
return SerializeAdapter::getSerializedSize(&value);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline ReturnValue_t LocalPoolVariable<T>::deSerialize(const uint8_t** buffer,
|
||||
size_t* size, SerializeIF::Endianness streamEndianness) {
|
||||
return SerializeAdapter::deSerialize(&value, buffer, size, streamEndianness);
|
||||
template <typename T>
|
||||
inline ReturnValue_t LocalPoolVariable<T>::deSerialize(const uint8_t** buffer, size_t* size,
|
||||
SerializeIF::Endianness streamEndianness) {
|
||||
return SerializeAdapter::deSerialize(&value, buffer, size, streamEndianness);
|
||||
}
|
||||
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
template<typename T>
|
||||
inline std::ostream& operator<< (std::ostream &out,
|
||||
const LocalPoolVariable<T> &var) {
|
||||
out << var.value;
|
||||
return out;
|
||||
template <typename T>
|
||||
inline std::ostream& operator<<(std::ostream& out, const LocalPoolVariable<T>& var) {
|
||||
out << var.value;
|
||||
return out;
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
inline LocalPoolVariable<T>::operator T() const {
|
||||
return value;
|
||||
return value;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline LocalPoolVariable<T> & LocalPoolVariable<T>::operator=(
|
||||
const T& newValue) {
|
||||
value = newValue;
|
||||
return *this;
|
||||
template <typename T>
|
||||
inline LocalPoolVariable<T>& LocalPoolVariable<T>::operator=(const T& newValue) {
|
||||
value = newValue;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline LocalPoolVariable<T>& LocalPoolVariable<T>::operator =(
|
||||
const LocalPoolVariable<T>& newPoolVariable) {
|
||||
value = newPoolVariable.value;
|
||||
return *this;
|
||||
template <typename T>
|
||||
inline LocalPoolVariable<T>& LocalPoolVariable<T>::operator=(
|
||||
const LocalPoolVariable<T>& newPoolVariable) {
|
||||
value = newPoolVariable.value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool LocalPoolVariable<T>::operator ==(
|
||||
const LocalPoolVariable<T> &other) const {
|
||||
return this->value == other.value;
|
||||
template <typename T>
|
||||
inline bool LocalPoolVariable<T>::operator==(const LocalPoolVariable<T>& other) const {
|
||||
return this->value == other.value;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool LocalPoolVariable<T>::operator ==(const T &other) const {
|
||||
return this->value == other;
|
||||
template <typename T>
|
||||
inline bool LocalPoolVariable<T>::operator==(const T& other) const {
|
||||
return this->value == other;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
inline bool LocalPoolVariable<T>::operator !=(
|
||||
const LocalPoolVariable<T> &other) const {
|
||||
return not (*this == other);
|
||||
template <typename T>
|
||||
inline bool LocalPoolVariable<T>::operator!=(const LocalPoolVariable<T>& other) const {
|
||||
return not(*this == other);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool LocalPoolVariable<T>::operator !=(const T &other) const {
|
||||
return not (*this == other);
|
||||
template <typename T>
|
||||
inline bool LocalPoolVariable<T>::operator!=(const T& other) const {
|
||||
return not(*this == other);
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
inline bool LocalPoolVariable<T>::operator <(
|
||||
const LocalPoolVariable<T> &other) const {
|
||||
return this->value < other.value;
|
||||
template <typename T>
|
||||
inline bool LocalPoolVariable<T>::operator<(const LocalPoolVariable<T>& other) const {
|
||||
return this->value < other.value;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool LocalPoolVariable<T>::operator <(const T &other) const {
|
||||
return this->value < other;
|
||||
template <typename T>
|
||||
inline bool LocalPoolVariable<T>::operator<(const T& other) const {
|
||||
return this->value < other;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
inline bool LocalPoolVariable<T>::operator >(
|
||||
const LocalPoolVariable<T> &other) const {
|
||||
return not (*this < other);
|
||||
template <typename T>
|
||||
inline bool LocalPoolVariable<T>::operator>(const LocalPoolVariable<T>& other) const {
|
||||
return not(*this < other);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline bool LocalPoolVariable<T>::operator >(const T &other) const {
|
||||
return not (*this < other);
|
||||
template <typename T>
|
||||
inline bool LocalPoolVariable<T>::operator>(const T& other) const {
|
||||
return not(*this < other);
|
||||
}
|
||||
|
||||
#endif /* FSFW_DATAPOOLLOCAL_LOCALPOOLVARIABLE_TPP_ */
|
||||
|
@ -5,174 +5,172 @@
|
||||
#error Include LocalPoolVector.h before LocalPoolVector.tpp!
|
||||
#endif
|
||||
|
||||
template<typename T, uint16_t vectorSize>
|
||||
inline LocalPoolVector<T, vectorSize>::LocalPoolVector(
|
||||
HasLocalDataPoolIF* hkOwner, lp_id_t poolId, DataSetIF* dataSet,
|
||||
pool_rwm_t setReadWriteMode):
|
||||
LocalPoolObjectBase(poolId, hkOwner, dataSet, setReadWriteMode) {}
|
||||
template <typename T, uint16_t vectorSize>
|
||||
inline LocalPoolVector<T, vectorSize>::LocalPoolVector(HasLocalDataPoolIF* hkOwner, lp_id_t poolId,
|
||||
DataSetIF* dataSet,
|
||||
pool_rwm_t setReadWriteMode)
|
||||
: LocalPoolObjectBase(poolId, hkOwner, dataSet, setReadWriteMode) {}
|
||||
|
||||
template<typename T, uint16_t vectorSize>
|
||||
inline LocalPoolVector<T, vectorSize>::LocalPoolVector(object_id_t poolOwner,
|
||||
lp_id_t poolId, DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
|
||||
LocalPoolObjectBase(poolOwner, poolId, dataSet, setReadWriteMode) {}
|
||||
template <typename T, uint16_t vectorSize>
|
||||
inline LocalPoolVector<T, vectorSize>::LocalPoolVector(object_id_t poolOwner, lp_id_t poolId,
|
||||
DataSetIF* dataSet,
|
||||
pool_rwm_t setReadWriteMode)
|
||||
: LocalPoolObjectBase(poolOwner, poolId, dataSet, setReadWriteMode) {}
|
||||
|
||||
template<typename T, uint16_t vectorSize>
|
||||
inline LocalPoolVector<T, vectorSize>::LocalPoolVector(gp_id_t globalPoolId,
|
||||
DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
|
||||
LocalPoolObjectBase(globalPoolId.objectId, globalPoolId.localPoolId,
|
||||
dataSet, setReadWriteMode) {}
|
||||
template <typename T, uint16_t vectorSize>
|
||||
inline LocalPoolVector<T, vectorSize>::LocalPoolVector(gp_id_t globalPoolId, DataSetIF* dataSet,
|
||||
pool_rwm_t setReadWriteMode)
|
||||
: LocalPoolObjectBase(globalPoolId.objectId, globalPoolId.localPoolId, dataSet,
|
||||
setReadWriteMode) {}
|
||||
|
||||
template<typename T, uint16_t vectorSize>
|
||||
inline ReturnValue_t LocalPoolVector<T, vectorSize>::read(
|
||||
MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
|
||||
MutexGuard(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs);
|
||||
return readWithoutLock();
|
||||
template <typename T, uint16_t vectorSize>
|
||||
inline ReturnValue_t LocalPoolVector<T, vectorSize>::read(MutexIF::TimeoutType timeoutType,
|
||||
uint32_t timeoutMs) {
|
||||
MutexGuard(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs);
|
||||
return readWithoutLock();
|
||||
}
|
||||
template<typename T, uint16_t vectorSize>
|
||||
template <typename T, uint16_t vectorSize>
|
||||
inline ReturnValue_t LocalPoolVector<T, vectorSize>::readWithoutLock() {
|
||||
if(readWriteMode == pool_rwm_t::VAR_WRITE) {
|
||||
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
||||
reportReadCommitError("LocalPoolVector",
|
||||
PoolVariableIF::INVALID_READ_WRITE_MODE, true, targetObjectId,
|
||||
localPoolId);
|
||||
return PoolVariableIF::INVALID_READ_WRITE_MODE;
|
||||
}
|
||||
if (readWriteMode == pool_rwm_t::VAR_WRITE) {
|
||||
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
||||
reportReadCommitError("LocalPoolVector", PoolVariableIF::INVALID_READ_WRITE_MODE, true,
|
||||
targetObjectId, localPoolId);
|
||||
return PoolVariableIF::INVALID_READ_WRITE_MODE;
|
||||
}
|
||||
|
||||
PoolEntry<T>* poolEntry = nullptr;
|
||||
ReturnValue_t result = LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId,
|
||||
&poolEntry);
|
||||
memset(this->value, 0, vectorSize * sizeof(T));
|
||||
PoolEntry<T>* poolEntry = nullptr;
|
||||
ReturnValue_t result =
|
||||
LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId, &poolEntry);
|
||||
memset(this->value, 0, vectorSize * sizeof(T));
|
||||
|
||||
if(result != RETURN_OK) {
|
||||
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
||||
reportReadCommitError("LocalPoolVector", result, true, targetObjectId,
|
||||
localPoolId);
|
||||
return result;
|
||||
}
|
||||
std::memcpy(this->value, poolEntry->getDataPtr(), poolEntry->getByteSize());
|
||||
this->valid = poolEntry->getValid();
|
||||
return RETURN_OK;
|
||||
if (result != RETURN_OK) {
|
||||
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
||||
reportReadCommitError("LocalPoolVector", result, true, targetObjectId, localPoolId);
|
||||
return result;
|
||||
}
|
||||
std::memcpy(this->value, poolEntry->getDataPtr(), poolEntry->getByteSize());
|
||||
this->valid = poolEntry->getValid();
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
template<typename T, uint16_t vectorSize>
|
||||
template <typename T, uint16_t vectorSize>
|
||||
inline ReturnValue_t LocalPoolVector<T, vectorSize>::commit(bool valid,
|
||||
MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
|
||||
this->setValid(valid);
|
||||
return commit(timeoutType, timeoutMs);
|
||||
MutexIF::TimeoutType timeoutType,
|
||||
uint32_t timeoutMs) {
|
||||
this->setValid(valid);
|
||||
return commit(timeoutType, timeoutMs);
|
||||
}
|
||||
|
||||
template<typename T, uint16_t vectorSize>
|
||||
inline ReturnValue_t LocalPoolVector<T, vectorSize>::commit(
|
||||
MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
|
||||
MutexGuard(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs);
|
||||
return commitWithoutLock();
|
||||
template <typename T, uint16_t vectorSize>
|
||||
inline ReturnValue_t LocalPoolVector<T, vectorSize>::commit(MutexIF::TimeoutType timeoutType,
|
||||
uint32_t timeoutMs) {
|
||||
MutexGuard(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs);
|
||||
return commitWithoutLock();
|
||||
}
|
||||
|
||||
template<typename T, uint16_t vectorSize>
|
||||
template <typename T, uint16_t vectorSize>
|
||||
inline ReturnValue_t LocalPoolVector<T, vectorSize>::commitWithoutLock() {
|
||||
if(readWriteMode == pool_rwm_t::VAR_READ) {
|
||||
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
||||
reportReadCommitError("LocalPoolVector",
|
||||
PoolVariableIF::INVALID_READ_WRITE_MODE, false, targetObjectId,
|
||||
localPoolId);
|
||||
return PoolVariableIF::INVALID_READ_WRITE_MODE;
|
||||
}
|
||||
PoolEntry<T>* poolEntry = nullptr;
|
||||
ReturnValue_t result = LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId,
|
||||
&poolEntry);
|
||||
if(result != RETURN_OK) {
|
||||
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (readWriteMode == pool_rwm_t::VAR_READ) {
|
||||
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
||||
reportReadCommitError("LocalPoolVector", PoolVariableIF::INVALID_READ_WRITE_MODE, false,
|
||||
targetObjectId, localPoolId);
|
||||
return PoolVariableIF::INVALID_READ_WRITE_MODE;
|
||||
}
|
||||
PoolEntry<T>* poolEntry = nullptr;
|
||||
ReturnValue_t result =
|
||||
LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId, &poolEntry);
|
||||
if (result != RETURN_OK) {
|
||||
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
||||
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>
|
||||
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 {
|
||||
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(
|
||||
const uint8_t** buffer, size_t* size,
|
||||
SerializeIF::Endianness streamEndianness) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
|
||||
for (uint16_t i = 0; i < vectorSize; i++) {
|
||||
result = SerializeAdapter::deSerialize(&(value[i]), buffer, size,
|
||||
streamEndianness);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
break;
|
||||
}
|
||||
const uint8_t** buffer, size_t* size, SerializeIF::Endianness streamEndianness) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
|
||||
for (uint16_t i = 0; i < vectorSize; i++) {
|
||||
result = SerializeAdapter::deSerialize(&(value[i]), buffer, size, streamEndianness);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
template<typename T, uint16_t vectorSize>
|
||||
inline std::ostream& operator<< (std::ostream &out,
|
||||
const LocalPoolVector<T, vectorSize> &var) {
|
||||
out << "Vector: [";
|
||||
for(int i = 0;i < vectorSize; i++) {
|
||||
out << var.value[i];
|
||||
if(i < vectorSize - 1) {
|
||||
out << ", ";
|
||||
}
|
||||
template <typename T, uint16_t vectorSize>
|
||||
inline std::ostream& operator<<(std::ostream& out, const LocalPoolVector<T, vectorSize>& var) {
|
||||
out << "Vector: [";
|
||||
for (int i = 0; i < vectorSize; i++) {
|
||||
out << var.value[i];
|
||||
if (i < vectorSize - 1) {
|
||||
out << ", ";
|
||||
}
|
||||
out << "]";
|
||||
return out;
|
||||
}
|
||||
out << "]";
|
||||
return out;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1,5 +1,2 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
HasLocalDpIFUserAttorney.cpp
|
||||
HasLocalDpIFManagerAttorney.cpp
|
||||
)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE HasLocalDpIFUserAttorney.cpp
|
||||
HasLocalDpIFManagerAttorney.cpp)
|
||||
|
@ -1,11 +1,10 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
AssemblyBase.cpp
|
||||
ChildHandlerBase.cpp
|
||||
ChildHandlerFDIR.cpp
|
||||
DeviceHandlerBase.cpp
|
||||
DeviceHandlerFailureIsolation.cpp
|
||||
DeviceHandlerMessage.cpp
|
||||
DeviceTmReportingWrapper.cpp
|
||||
HealthDevice.cpp
|
||||
)
|
||||
target_sources(
|
||||
${LIB_FSFW_NAME}
|
||||
PRIVATE AssemblyBase.cpp
|
||||
ChildHandlerBase.cpp
|
||||
ChildHandlerFDIR.cpp
|
||||
DeviceHandlerBase.cpp
|
||||
DeviceHandlerFailureIsolation.cpp
|
||||
DeviceHandlerMessage.cpp
|
||||
DeviceTmReportingWrapper.cpp
|
||||
HealthDevice.cpp)
|
||||
|
@ -163,7 +163,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
||||
* @param counter Specifies which Action to perform
|
||||
* @return RETURN_OK for successful execution
|
||||
*/
|
||||
virtual ReturnValue_t performOperation(uint8_t counter);
|
||||
virtual ReturnValue_t performOperation(uint8_t counter) override;
|
||||
|
||||
/**
|
||||
* @brief Initializes the device handler
|
||||
@ -173,7 +173,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
||||
* Calls fillCommandAndReplyMap().
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t initialize();
|
||||
virtual ReturnValue_t initialize() override;
|
||||
|
||||
/**
|
||||
* @brief Intialization steps performed after all tasks have been created.
|
||||
@ -1058,11 +1058,12 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
||||
* @param parameter1 Optional parameter 1
|
||||
* @param parameter2 Optional parameter 2
|
||||
*/
|
||||
void triggerEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0);
|
||||
void triggerEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0) override;
|
||||
/**
|
||||
* 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;
|
||||
virtual void forwardEvent(Event event, uint32_t parameter1 = 0,
|
||||
uint32_t parameter2 = 0) const override;
|
||||
|
||||
/**
|
||||
* Checks if current mode is transitional mode.
|
||||
|
@ -1,6 +1,3 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
EventManager.cpp
|
||||
EventMessage.cpp
|
||||
)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE EventManager.cpp EventMessage.cpp)
|
||||
|
||||
add_subdirectory(eventmatching)
|
||||
|
@ -1,7 +1,3 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
EventIdRangeMatcher.cpp
|
||||
EventMatchTree.cpp
|
||||
ReporterRangeMatcher.cpp
|
||||
SeverityRangeMatcher.cpp
|
||||
)
|
||||
target_sources(
|
||||
${LIB_FSFW_NAME} PRIVATE EventIdRangeMatcher.cpp EventMatchTree.cpp
|
||||
ReporterRangeMatcher.cpp SeverityRangeMatcher.cpp)
|
||||
|
@ -27,6 +27,7 @@ enum : uint8_t {
|
||||
PUS_SERVICE_6 = 86,
|
||||
PUS_SERVICE_8 = 88,
|
||||
PUS_SERVICE_9 = 89,
|
||||
PUS_SERVICE_11 = 91,
|
||||
PUS_SERVICE_17 = 97,
|
||||
PUS_SERVICE_23 = 103,
|
||||
MGM_LIS3MDL = 106,
|
||||
|
@ -1,6 +1,3 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
EventCorrelation.cpp
|
||||
FailureIsolationBase.cpp
|
||||
FaultCounter.cpp
|
||||
)
|
||||
target_sources(
|
||||
${LIB_FSFW_NAME} PRIVATE EventCorrelation.cpp FailureIsolationBase.cpp
|
||||
FaultCounter.cpp)
|
||||
|
@ -1,13 +1,12 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
arrayprinter.cpp
|
||||
AsciiConverter.cpp
|
||||
CRC.cpp
|
||||
DleEncoder.cpp
|
||||
PeriodicOperationDivider.cpp
|
||||
timevalOperations.cpp
|
||||
Type.cpp
|
||||
bitutility.cpp
|
||||
)
|
||||
target_sources(
|
||||
${LIB_FSFW_NAME}
|
||||
PRIVATE arrayprinter.cpp
|
||||
AsciiConverter.cpp
|
||||
CRC.cpp
|
||||
DleEncoder.cpp
|
||||
PeriodicOperationDivider.cpp
|
||||
timevalOperations.cpp
|
||||
Type.cpp
|
||||
bitutility.cpp)
|
||||
|
||||
add_subdirectory(math)
|
||||
|
@ -25,7 +25,7 @@ class MatchTree : public SerializeableMatcherIF<T>, public BinaryTree<Serializea
|
||||
: BinaryTree<SerializeableMatcherIF<T>>(root.element), maxDepth(maxDepth) {}
|
||||
MatchTree() : BinaryTree<SerializeableMatcherIF<T>>(), maxDepth(-1) {}
|
||||
virtual ~MatchTree() {}
|
||||
virtual bool match(T number) { return matchesTree(number); }
|
||||
virtual bool match(T number) override { return matchesTree(number); }
|
||||
bool matchesTree(T number) {
|
||||
iterator iter = this->begin();
|
||||
if (iter == this->end()) {
|
||||
@ -179,6 +179,9 @@ class MatchTree : public SerializeableMatcherIF<T>, public BinaryTree<Serializea
|
||||
virtual ReturnValue_t cleanUpElement(iterator position) { return HasReturnvaluesIF::RETURN_OK; }
|
||||
|
||||
bool matchSubtree(iterator iter, T number) {
|
||||
if (iter == nullptr) {
|
||||
return false;
|
||||
}
|
||||
bool isMatch = iter->match(number);
|
||||
if (isMatch) {
|
||||
if (iter.left() == this->end()) {
|
||||
|
@ -15,7 +15,7 @@ class RangeMatcher : public SerializeableMatcherIF<T> {
|
||||
RangeMatcher(T lowerBound, T upperBound, bool inverted = false)
|
||||
: inverted(inverted), lowerBound(lowerBound), upperBound(upperBound) {}
|
||||
|
||||
bool match(T input) {
|
||||
bool match(T input) override {
|
||||
if (inverted) {
|
||||
return !doMatch(input);
|
||||
} else {
|
||||
|
@ -1,4 +1 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
QuaternionOperations.cpp
|
||||
)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE QuaternionOperations.cpp)
|
||||
|
@ -1,6 +1,2 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
HealthHelper.cpp
|
||||
HealthMessage.cpp
|
||||
HealthTable.cpp
|
||||
)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE HealthHelper.cpp HealthMessage.cpp
|
||||
HealthTable.cpp)
|
||||
|
@ -1,5 +1,2 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
HousekeepingMessage.cpp
|
||||
PeriodicHousekeepingHelper.cpp
|
||||
)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE HousekeepingMessage.cpp
|
||||
PeriodicHousekeepingHelper.cpp)
|
||||
|
@ -1,4 +1 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
InternalErrorReporter.cpp
|
||||
)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE InternalErrorReporter.cpp)
|
||||
|
@ -1,6 +1,3 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
CommandMessage.cpp
|
||||
CommandMessageCleaner.cpp
|
||||
MessageQueueMessage.cpp
|
||||
)
|
||||
target_sources(
|
||||
${LIB_FSFW_NAME} PRIVATE CommandMessage.cpp CommandMessageCleaner.cpp
|
||||
MessageQueueMessage.cpp MessageQueueBase.cpp)
|
||||
|
54
src/fsfw/ipc/MessageQueueBase.cpp
Normal file
54
src/fsfw/ipc/MessageQueueBase.cpp
Normal file
@ -0,0 +1,54 @@
|
||||
#include "MessageQueueBase.h"
|
||||
|
||||
MessageQueueBase::MessageQueueBase(MessageQueueId_t id, MessageQueueId_t defaultDest, MqArgs* args)
|
||||
: id(id) {
|
||||
this->defaultDest = defaultDest;
|
||||
if (args != nullptr) {
|
||||
this->args = *args;
|
||||
}
|
||||
}
|
||||
|
||||
MessageQueueBase::~MessageQueueBase() {}
|
||||
|
||||
ReturnValue_t MessageQueueBase::sendToDefault(MessageQueueMessageIF* message) {
|
||||
return sendToDefaultFrom(message, this->getId(), false);
|
||||
}
|
||||
|
||||
ReturnValue_t MessageQueueBase::reply(MessageQueueMessageIF* message) {
|
||||
if (this->last != MessageQueueIF::NO_QUEUE) {
|
||||
return sendMessageFrom(this->last, message, this->getId());
|
||||
} else {
|
||||
return NO_REPLY_PARTNER;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t MessageQueueBase::receiveMessage(MessageQueueMessageIF* message,
|
||||
MessageQueueId_t* receivedFrom) {
|
||||
ReturnValue_t status = this->receiveMessage(message);
|
||||
*receivedFrom = this->last;
|
||||
return status;
|
||||
}
|
||||
|
||||
MessageQueueId_t MessageQueueBase::getLastPartner() const { return last; }
|
||||
|
||||
MessageQueueId_t MessageQueueBase::getId() const { return id; }
|
||||
|
||||
MqArgs& MessageQueueBase::getMqArgs() { return args; }
|
||||
|
||||
void MessageQueueBase::setDefaultDestination(MessageQueueId_t defaultDestination) {
|
||||
this->defaultDest = defaultDestination;
|
||||
}
|
||||
|
||||
MessageQueueId_t MessageQueueBase::getDefaultDestination() const { return defaultDest; }
|
||||
|
||||
bool MessageQueueBase::isDefaultDestinationSet() const { return (defaultDest != NO_QUEUE); }
|
||||
|
||||
ReturnValue_t MessageQueueBase::sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
||||
bool ignoreFault) {
|
||||
return sendMessageFrom(sendTo, message, this->getId(), false);
|
||||
}
|
||||
|
||||
ReturnValue_t MessageQueueBase::sendToDefaultFrom(MessageQueueMessageIF* message,
|
||||
MessageQueueId_t sentFrom, bool ignoreFault) {
|
||||
return sendMessageFrom(defaultDest, message, sentFrom, ignoreFault);
|
||||
}
|
40
src/fsfw/ipc/MessageQueueBase.h
Normal file
40
src/fsfw/ipc/MessageQueueBase.h
Normal file
@ -0,0 +1,40 @@
|
||||
#ifndef FSFW_SRC_FSFW_IPC_MESSAGEQUEUEBASE_H_
|
||||
#define FSFW_SRC_FSFW_IPC_MESSAGEQUEUEBASE_H_
|
||||
|
||||
#include <fsfw/ipc/MessageQueueIF.h>
|
||||
#include <fsfw/ipc/definitions.h>
|
||||
|
||||
class MessageQueueBase : public MessageQueueIF {
|
||||
public:
|
||||
MessageQueueBase(MessageQueueId_t id, MessageQueueId_t defaultDest, MqArgs* mqArgs);
|
||||
virtual ~MessageQueueBase();
|
||||
|
||||
// Default implementations for MessageQueueIF where possible
|
||||
virtual MessageQueueId_t getLastPartner() const override;
|
||||
virtual MessageQueueId_t getId() const override;
|
||||
virtual MqArgs& getMqArgs() override;
|
||||
virtual void setDefaultDestination(MessageQueueId_t defaultDestination) override;
|
||||
virtual MessageQueueId_t getDefaultDestination() const override;
|
||||
virtual bool isDefaultDestinationSet() const override;
|
||||
virtual ReturnValue_t sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
||||
bool ignoreFault) override;
|
||||
virtual ReturnValue_t sendToDefault(MessageQueueMessageIF* message) override;
|
||||
virtual ReturnValue_t reply(MessageQueueMessageIF* message) override;
|
||||
virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message,
|
||||
MessageQueueId_t* receivedFrom) override;
|
||||
virtual ReturnValue_t sendToDefaultFrom(MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
|
||||
bool ignoreFault = false) override;
|
||||
|
||||
// OSAL specific, forward the abstract function
|
||||
virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message) = 0;
|
||||
virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
||||
MessageQueueId_t sentFrom, bool ignoreFault = false) = 0;
|
||||
|
||||
protected:
|
||||
MessageQueueId_t id = MessageQueueIF::NO_QUEUE;
|
||||
MessageQueueId_t last = MessageQueueIF::NO_QUEUE;
|
||||
MessageQueueId_t defaultDest = MessageQueueIF::NO_QUEUE;
|
||||
MqArgs args = {};
|
||||
};
|
||||
|
||||
#endif /* FSFW_SRC_FSFW_IPC_MESSAGEQUEUEBASE_H_ */
|
@ -1,6 +1,8 @@
|
||||
#ifndef FSFW_IPC_MESSAGEQUEUEIF_H_
|
||||
#define FSFW_IPC_MESSAGEQUEUEIF_H_
|
||||
|
||||
#include <fsfw/ipc/definitions.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||
@ -44,8 +46,8 @@ class MessageQueueIF {
|
||||
virtual ReturnValue_t reply(MessageQueueMessageIF* message) = 0;
|
||||
|
||||
/**
|
||||
* @brief This function reads available messages from the message queue
|
||||
* and returns the sender.
|
||||
* @brief This function reads available messages from the message queue and returns the
|
||||
* sender.
|
||||
* @details
|
||||
* It works identically to the other receiveMessage call, but in addition
|
||||
* returns the sender's queue id.
|
||||
@ -78,19 +80,16 @@ class MessageQueueIF {
|
||||
*/
|
||||
virtual ReturnValue_t flush(uint32_t* count) = 0;
|
||||
/**
|
||||
* @brief This method returns the message queue
|
||||
* id of the last communication partner.
|
||||
* @brief This method returns the message queue ID of the last communication partner.
|
||||
*/
|
||||
virtual MessageQueueId_t getLastPartner() const = 0;
|
||||
/**
|
||||
* @brief This method returns the message queue
|
||||
* id of this class's message queue.
|
||||
* @brief This method returns the message queue ID of this class's message queue.
|
||||
*/
|
||||
virtual MessageQueueId_t getId() const = 0;
|
||||
|
||||
/**
|
||||
* @brief With the sendMessage call, a queue message
|
||||
* is sent to a receiving queue.
|
||||
* @brief With the sendMessage call, a queue message is sent to a receiving queue.
|
||||
* @details
|
||||
* This method takes the message provided, adds the sentFrom information
|
||||
* and passes it on to the destination provided with an operating system
|
||||
@ -129,8 +128,7 @@ class MessageQueueIF {
|
||||
bool ignoreFault = false) = 0;
|
||||
|
||||
/**
|
||||
* @brief The sendToDefaultFrom method sends a queue message
|
||||
* to the default destination.
|
||||
* @brief The sendToDefaultFrom method sends a queue message to the default destination.
|
||||
* @details
|
||||
* In all other aspects, it works identical to the sendMessage method.
|
||||
* @param message
|
||||
@ -164,6 +162,8 @@ class MessageQueueIF {
|
||||
virtual MessageQueueId_t getDefaultDestination() const = 0;
|
||||
|
||||
virtual bool isDefaultDestinationSet() const = 0;
|
||||
|
||||
virtual MqArgs& getMqArgs() = 0;
|
||||
};
|
||||
|
||||
#endif /* FSFW_IPC_MESSAGEQUEUEIF_H_ */
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include "MessageQueueIF.h"
|
||||
#include "MessageQueueMessage.h"
|
||||
#include "definitions.h"
|
||||
|
||||
/**
|
||||
* Creates message queues.
|
||||
@ -22,7 +23,8 @@ class QueueFactory {
|
||||
static QueueFactory* instance();
|
||||
|
||||
MessageQueueIF* createMessageQueue(uint32_t messageDepth = 3,
|
||||
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE);
|
||||
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE,
|
||||
MqArgs* args = nullptr);
|
||||
|
||||
void deleteMessageQueue(MessageQueueIF* queue);
|
||||
|
||||
|
14
src/fsfw/ipc/definitions.h
Normal file
14
src/fsfw/ipc/definitions.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef FSFW_SRC_FSFW_IPC_DEFINITIONS_H_
|
||||
#define FSFW_SRC_FSFW_IPC_DEFINITIONS_H_
|
||||
|
||||
#include <fsfw/objectmanager/SystemObjectIF.h>
|
||||
#include <fsfw/objectmanager/frameworkObjects.h>
|
||||
|
||||
struct MqArgs {
|
||||
MqArgs(){};
|
||||
MqArgs(object_id_t objectId, void* args = nullptr) : objectId(objectId), args(args) {}
|
||||
object_id_t objectId = objects::NO_OBJECT;
|
||||
void* args = nullptr;
|
||||
};
|
||||
|
||||
#endif /* FSFW_SRC_FSFW_IPC_DEFINITIONS_H_ */
|
@ -1,5 +1,2 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
MemoryHelper.cpp
|
||||
MemoryMessage.cpp
|
||||
GenericFileSystemMessage.cpp
|
||||
)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE MemoryHelper.cpp MemoryMessage.cpp
|
||||
GenericFileSystemMessage.cpp)
|
||||
|
@ -1,5 +1 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
ModeHelper.cpp
|
||||
ModeMessage.cpp
|
||||
)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE ModeHelper.cpp ModeMessage.cpp)
|
||||
|
@ -1,5 +1,2 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
LimitViolationReporter.cpp
|
||||
MonitoringMessage.cpp
|
||||
)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE LimitViolationReporter.cpp
|
||||
MonitoringMessage.cpp)
|
||||
|
@ -34,7 +34,7 @@ class MonitoringReportContent : public SerialLinkedListAdapter<SerializeIF> {
|
||||
SerializeElement<T> limitValue;
|
||||
SerializeElement<ReturnValue_t> oldState;
|
||||
SerializeElement<ReturnValue_t> newState;
|
||||
uint8_t rawTimestamp[TimeStamperIF::MISSION_TIMESTAMP_SIZE];
|
||||
uint8_t rawTimestamp[TimeStamperIF::MISSION_TIMESTAMP_SIZE] = {};
|
||||
SerializeElement<SerialBufferAdapter<uint8_t>> timestampSerializer;
|
||||
TimeStamperIF* timeStamper;
|
||||
MonitoringReportContent()
|
||||
@ -46,7 +46,6 @@ class MonitoringReportContent : public SerialLinkedListAdapter<SerializeIF> {
|
||||
limitValue(0),
|
||||
oldState(0),
|
||||
newState(0),
|
||||
rawTimestamp({0}),
|
||||
timestampSerializer(rawTimestamp, sizeof(rawTimestamp)),
|
||||
timeStamper(NULL) {
|
||||
setAllNext();
|
||||
|
@ -1,5 +1 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
ObjectManager.cpp
|
||||
SystemObject.cpp
|
||||
)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE ObjectManager.cpp SystemObject.cpp)
|
||||
|
@ -48,9 +48,10 @@ class SystemObject : public SystemObjectIF {
|
||||
virtual ~SystemObject();
|
||||
object_id_t getObjectId() const override;
|
||||
virtual ReturnValue_t initialize() override;
|
||||
virtual ReturnValue_t checkObjectConnections();
|
||||
virtual ReturnValue_t checkObjectConnections() override;
|
||||
|
||||
virtual void forwardEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0) const;
|
||||
virtual void forwardEvent(Event event, uint32_t parameter1 = 0,
|
||||
uint32_t parameter2 = 0) const override;
|
||||
};
|
||||
|
||||
#endif /* FSFW_OBJECTMANAGER_SYSTEMOBJECT_H_ */
|
||||
|
@ -14,6 +14,7 @@ enum framework_objects : object_id_t {
|
||||
PUS_SERVICE_5_EVENT_REPORTING = 0x53000005,
|
||||
PUS_SERVICE_8_FUNCTION_MGMT = 0x53000008,
|
||||
PUS_SERVICE_9_TIME_MGMT = 0x53000009,
|
||||
PUS_SERVICE_11_TC_SCHEDULER = 0x53000011,
|
||||
PUS_SERVICE_17_TEST = 0x53000017,
|
||||
PUS_SERVICE_20_PARAMETERS = 0x53000020,
|
||||
PUS_SERVICE_200_MODE_MGMT = 0x53000200,
|
||||
|
@ -1,35 +1,33 @@
|
||||
# Check the OS_FSFW variable
|
||||
if(FSFW_OSAL MATCHES "freertos")
|
||||
add_subdirectory(freertos)
|
||||
add_subdirectory(freertos)
|
||||
elseif(FSFW_OSAL MATCHES "rtems")
|
||||
add_subdirectory(rtems)
|
||||
add_subdirectory(rtems)
|
||||
elseif(FSFW_OSAL MATCHES "linux")
|
||||
add_subdirectory(linux)
|
||||
add_subdirectory(linux)
|
||||
elseif(FSFW_OSAL MATCHES "host")
|
||||
add_subdirectory(host)
|
||||
if (WIN32)
|
||||
add_subdirectory(windows)
|
||||
elseif(UNIX)
|
||||
# We still need to pull in some Linux specific sources
|
||||
target_sources(${LIB_FSFW_NAME} PUBLIC
|
||||
linux/tcpipHelpers.cpp
|
||||
)
|
||||
endif ()
|
||||
add_subdirectory(host)
|
||||
if(WIN32)
|
||||
add_subdirectory(windows)
|
||||
elseif(UNIX)
|
||||
# We still need to pull in some Linux specific sources
|
||||
target_sources(${LIB_FSFW_NAME} PUBLIC linux/tcpipHelpers.cpp)
|
||||
endif()
|
||||
|
||||
else()
|
||||
|
||||
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
|
||||
if (WIN32)
|
||||
add_subdirectory(host)
|
||||
add_subdirectory(windows)
|
||||
elseif (UNIX)
|
||||
add_subdirectory(linux)
|
||||
else ()
|
||||
# MacOS or other OSes have not been tested yet / are not supported.
|
||||
message(FATAL_ERROR "The host OS could not be determined! Aborting.")
|
||||
endif()
|
||||
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
|
||||
if(WIN32)
|
||||
add_subdirectory(host)
|
||||
add_subdirectory(windows)
|
||||
elseif(UNIX)
|
||||
add_subdirectory(linux)
|
||||
else()
|
||||
# MacOS or other OSes have not been tested yet / are not supported.
|
||||
message(FATAL_ERROR "The host OS could not be determined! Aborting.")
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
add_subdirectory(common)
|
||||
add_subdirectory(common)
|
||||
|
@ -1,17 +1,10 @@
|
||||
if(DEFINED WIN32 OR DEFINED UNIX)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
tcpipCommon.cpp
|
||||
TcpIpBase.cpp
|
||||
UdpTcPollingTask.cpp
|
||||
UdpTmTcBridge.cpp
|
||||
TcpTmTcServer.cpp
|
||||
TcpTmTcBridge.cpp
|
||||
)
|
||||
target_sources(
|
||||
${LIB_FSFW_NAME}
|
||||
PRIVATE tcpipCommon.cpp TcpIpBase.cpp UdpTcPollingTask.cpp
|
||||
UdpTmTcBridge.cpp TcpTmTcServer.cpp TcpTmTcBridge.cpp)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
|
||||
wsock32
|
||||
ws2_32
|
||||
)
|
||||
endif()
|
||||
target_link_libraries(${LIB_FSFW_NAME} PRIVATE wsock32 ws2_32)
|
||||
endif()
|
||||
|
@ -19,6 +19,8 @@
|
||||
#include <ws2tcpip.h>
|
||||
#elif defined(PLATFORM_UNIX)
|
||||
#include <netdb.h>
|
||||
|
||||
#include <utility>
|
||||
#endif
|
||||
|
||||
const std::string TcpTmTcServer::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT;
|
||||
@ -29,7 +31,7 @@ TcpTmTcServer::TcpTmTcServer(object_id_t objectId, object_id_t tmtcTcpBridge,
|
||||
: SystemObject(objectId),
|
||||
tmtcBridgeId(tmtcTcpBridge),
|
||||
receptionMode(receptionMode),
|
||||
tcpConfig(customTcpServerPort),
|
||||
tcpConfig(std::move(customTcpServerPort)),
|
||||
receptionBuffer(receptionBufferSize),
|
||||
ringBuffer(ringBufferSize, true) {}
|
||||
|
||||
@ -103,12 +105,12 @@ ReturnValue_t TcpTmTcServer::initialize() {
|
||||
|
||||
TcpTmTcServer::~TcpTmTcServer() { closeSocket(listenerTcpSocket); }
|
||||
|
||||
ReturnValue_t TcpTmTcServer::performOperation(uint8_t opCode) {
|
||||
[[noreturn]] ReturnValue_t TcpTmTcServer::performOperation(uint8_t opCode) {
|
||||
using namespace tcpip;
|
||||
// If a connection is accepted, the corresponding socket will be assigned to the new socket
|
||||
socket_t connSocket = 0;
|
||||
// sockaddr clientSockAddr = {};
|
||||
// socklen_t connectorSockAddrLen = 0;
|
||||
sockaddr clientSockAddr = {};
|
||||
socklen_t connectorSockAddrLen = 0;
|
||||
int retval = 0;
|
||||
|
||||
// Listen for connection requests permanently for lifetime of program
|
||||
@ -119,8 +121,7 @@ ReturnValue_t TcpTmTcServer::performOperation(uint8_t opCode) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// connSocket = accept(listenerTcpSocket, &clientSockAddr, &connectorSockAddrLen);
|
||||
connSocket = accept(listenerTcpSocket, nullptr, nullptr);
|
||||
connSocket = accept(listenerTcpSocket, &clientSockAddr, &connectorSockAddrLen);
|
||||
|
||||
if (connSocket == INVALID_SOCKET) {
|
||||
handleError(Protocol::TCP, ErrorSources::ACCEPT_CALL, 500);
|
||||
@ -135,10 +136,10 @@ ReturnValue_t TcpTmTcServer::performOperation(uint8_t opCode) {
|
||||
if (retval != 0) {
|
||||
handleError(Protocol::TCP, ErrorSources::SHUTDOWN_CALL);
|
||||
}
|
||||
|
||||
closeSocket(connSocket);
|
||||
connSocket = 0;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t TcpTmTcServer::initializeAfterTaskCreation() {
|
||||
@ -159,8 +160,8 @@ void TcpTmTcServer::handleServerOperation(socket_t& connSocket) {
|
||||
#endif
|
||||
|
||||
while (true) {
|
||||
int retval = recv(connSocket, reinterpret_cast<char*>(receptionBuffer.data()),
|
||||
receptionBuffer.capacity(), tcpConfig.tcpFlags);
|
||||
ssize_t retval = recv(connSocket, reinterpret_cast<char*>(receptionBuffer.data()),
|
||||
receptionBuffer.capacity(), tcpConfig.tcpFlags);
|
||||
if (retval == 0) {
|
||||
size_t availableReadData = ringBuffer.getAvailableReadData();
|
||||
if (availableReadData > lastRingBufferSize) {
|
||||
@ -252,17 +253,17 @@ ReturnValue_t TcpTmTcServer::handleTcReception(uint8_t* spacePacket, size_t pack
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string TcpTmTcServer::getTcpPort() const { return tcpConfig.tcpPort; }
|
||||
const std::string& TcpTmTcServer::getTcpPort() const { return tcpConfig.tcpPort; }
|
||||
|
||||
void TcpTmTcServer::setSpacePacketParsingOptions(std::vector<uint16_t> validPacketIds) {
|
||||
this->validPacketIds = validPacketIds;
|
||||
void TcpTmTcServer::setSpacePacketParsingOptions(std::vector<uint16_t> validPacketIds_) {
|
||||
this->validPacketIds = std::move(validPacketIds_);
|
||||
}
|
||||
|
||||
TcpTmTcServer::TcpConfig& TcpTmTcServer::getTcpConfigStruct() { return tcpConfig; }
|
||||
|
||||
ReturnValue_t TcpTmTcServer::handleTmSending(socket_t connSocket, bool& tmSent) {
|
||||
// Access to the FIFO is mutex protected because it is filled by the bridge
|
||||
MutexGuard(tmtcBridge->mutex, tmtcBridge->timeoutType, tmtcBridge->mutexTimeoutMs);
|
||||
MutexGuard mg(tmtcBridge->mutex, tmtcBridge->timeoutType, tmtcBridge->mutexTimeoutMs);
|
||||
store_address_t storeId;
|
||||
while ((not tmtcBridge->tmFifo->empty()) and
|
||||
(tmtcBridge->packetSentCounter < tmtcBridge->sentPacketsPerCycle)) {
|
||||
@ -283,8 +284,8 @@ ReturnValue_t TcpTmTcServer::handleTmSending(socket_t connSocket, bool& tmSent)
|
||||
#endif
|
||||
arrayprinter::print(storeAccessor.data(), storeAccessor.size());
|
||||
}
|
||||
int retval = send(connSocket, reinterpret_cast<const char*>(storeAccessor.data()),
|
||||
storeAccessor.size(), tcpConfig.tcpTmFlags);
|
||||
ssize_t retval = send(connSocket, reinterpret_cast<const char*>(storeAccessor.data()),
|
||||
storeAccessor.size(), tcpConfig.tcpTmFlags);
|
||||
if (retval == static_cast<int>(storeAccessor.size())) {
|
||||
// Packet sent, clear FIFO entry
|
||||
tmtcBridge->tmFifo->pop();
|
||||
@ -339,6 +340,9 @@ ReturnValue_t TcpTmTcServer::handleTcRingBufferData(size_t availableReadData) {
|
||||
size_t foundSize = 0;
|
||||
size_t readLen = 0;
|
||||
while (readLen < readAmount) {
|
||||
if (spacePacketParser == nullptr) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
result =
|
||||
spacePacketParser->parseSpacePackets(bufPtrPtr, readAmount, startIdx, foundSize, readLen);
|
||||
switch (result) {
|
||||
|
@ -17,6 +17,7 @@
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
class TcpTmTcBridge;
|
||||
@ -44,7 +45,7 @@ class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableOb
|
||||
|
||||
struct TcpConfig {
|
||||
public:
|
||||
TcpConfig(std::string tcpPort) : tcpPort(tcpPort) {}
|
||||
explicit TcpConfig(std::string tcpPort) : tcpPort(std::move(tcpPort)) {}
|
||||
|
||||
/**
|
||||
* Passed to the recv call
|
||||
@ -84,7 +85,7 @@ class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableOb
|
||||
size_t ringBufferSize = RING_BUFFER_SIZE,
|
||||
std::string customTcpServerPort = DEFAULT_SERVER_PORT,
|
||||
ReceptionModes receptionMode = ReceptionModes::SPACE_PACKETS);
|
||||
virtual ~TcpTmTcServer();
|
||||
~TcpTmTcServer() override;
|
||||
|
||||
void enableWiretapping(bool enable);
|
||||
|
||||
@ -97,10 +98,10 @@ class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableOb
|
||||
void setSpacePacketParsingOptions(std::vector<uint16_t> validPacketIds);
|
||||
|
||||
ReturnValue_t initialize() override;
|
||||
ReturnValue_t performOperation(uint8_t opCode) override;
|
||||
[[noreturn]] ReturnValue_t performOperation(uint8_t opCode) override;
|
||||
ReturnValue_t initializeAfterTaskCreation() override;
|
||||
|
||||
std::string getTcpPort() const;
|
||||
[[nodiscard]] const std::string& getTcpPort() const;
|
||||
|
||||
protected:
|
||||
StorageManagerIF* tcStore = nullptr;
|
||||
@ -115,7 +116,7 @@ class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableOb
|
||||
|
||||
ReceptionModes receptionMode;
|
||||
TcpConfig tcpConfig;
|
||||
struct sockaddr tcpAddress;
|
||||
struct sockaddr tcpAddress = {};
|
||||
socket_t listenerTcpSocket = 0;
|
||||
|
||||
MessageQueueId_t targetTcDestination = MessageQueueIF::NO_QUEUE;
|
||||
|
@ -16,11 +16,13 @@
|
||||
//! Debugging preprocessor define.
|
||||
#define FSFW_UDP_RECV_WIRETAPPING_ENABLED 0
|
||||
|
||||
const timeval UdpTcPollingTask::DEFAULT_TIMEOUT = {0, 500000};
|
||||
|
||||
UdpTcPollingTask::UdpTcPollingTask(object_id_t objectId, object_id_t tmtcUdpBridge,
|
||||
size_t maxRecvSize, double timeoutSeconds)
|
||||
: SystemObject(objectId), tmtcBridgeId(tmtcUdpBridge) {
|
||||
if (frameSize > 0) {
|
||||
this->frameSize = frameSize;
|
||||
if (maxRecvSize > 0) {
|
||||
this->frameSize = maxRecvSize;
|
||||
} else {
|
||||
this->frameSize = DEFAULT_MAX_RECV_SIZE;
|
||||
}
|
||||
@ -31,22 +33,20 @@ UdpTcPollingTask::UdpTcPollingTask(object_id_t objectId, object_id_t tmtcUdpBrid
|
||||
receptionBuffer.resize(this->frameSize);
|
||||
|
||||
if (timeoutSeconds == -1) {
|
||||
receptionTimeout = DEFAULT_TIMEOUT;
|
||||
receptionTimeout = UdpTcPollingTask::DEFAULT_TIMEOUT;
|
||||
} else {
|
||||
receptionTimeout = timevalOperations::toTimeval(timeoutSeconds);
|
||||
}
|
||||
}
|
||||
|
||||
UdpTcPollingTask::~UdpTcPollingTask() {}
|
||||
|
||||
ReturnValue_t UdpTcPollingTask::performOperation(uint8_t opCode) {
|
||||
[[noreturn]] ReturnValue_t UdpTcPollingTask::performOperation(uint8_t opCode) {
|
||||
/* Sender Address is cached here. */
|
||||
struct sockaddr senderAddress;
|
||||
struct sockaddr senderAddress {};
|
||||
socklen_t senderAddressSize = sizeof(senderAddress);
|
||||
|
||||
/* Poll for new UDP datagrams in permanent loop. */
|
||||
while (true) {
|
||||
int bytesReceived =
|
||||
ssize_t bytesReceived =
|
||||
recvfrom(this->serverSocket, reinterpret_cast<char*>(receptionBuffer.data()), frameSize,
|
||||
receptionFlags, &senderAddress, &senderAddressSize);
|
||||
if (bytesReceived == SOCKET_ERROR) {
|
||||
@ -70,7 +70,6 @@ ReturnValue_t UdpTcPollingTask::performOperation(uint8_t opCode) {
|
||||
}
|
||||
tmtcBridge->checkAndSetClientAddress(senderAddress);
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t UdpTcPollingTask::handleSuccessfullTcRead(size_t bytesRead) {
|
||||
@ -155,7 +154,7 @@ void UdpTcPollingTask::setTimeout(double timeoutSeconds) {
|
||||
#endif
|
||||
}
|
||||
#elif defined(PLATFORM_UNIX)
|
||||
timeval tval;
|
||||
timeval tval{};
|
||||
tval = timevalOperations::toTimeval(timeoutSeconds);
|
||||
int result = setsockopt(serverSocket, SOL_SOCKET, SO_RCVTIMEO, &tval, sizeof(receptionTimeout));
|
||||
if (result == -1) {
|
||||
|
@ -21,11 +21,11 @@ class UdpTcPollingTask : public TcpIpBase, public SystemObject, public Executabl
|
||||
public:
|
||||
static constexpr size_t DEFAULT_MAX_RECV_SIZE = 1500;
|
||||
//! 0.5 default milliseconds timeout for now.
|
||||
static constexpr timeval DEFAULT_TIMEOUT = {0, 500};
|
||||
static const timeval DEFAULT_TIMEOUT;
|
||||
|
||||
UdpTcPollingTask(object_id_t objectId, object_id_t tmtcUdpBridge, size_t maxRecvSize = 0,
|
||||
double timeoutSeconds = -1);
|
||||
virtual ~UdpTcPollingTask();
|
||||
~UdpTcPollingTask() override = default;
|
||||
|
||||
/**
|
||||
* Turn on optional timeout for UDP polling. In the default mode,
|
||||
@ -34,9 +34,9 @@ class UdpTcPollingTask : public TcpIpBase, public SystemObject, public Executabl
|
||||
*/
|
||||
void setTimeout(double timeoutSeconds);
|
||||
|
||||
virtual ReturnValue_t performOperation(uint8_t opCode) override;
|
||||
virtual ReturnValue_t initialize() override;
|
||||
virtual ReturnValue_t initializeAfterTaskCreation() override;
|
||||
[[noreturn]] ReturnValue_t performOperation(uint8_t opCode) override;
|
||||
ReturnValue_t initialize() override;
|
||||
ReturnValue_t initializeAfterTaskCreation() override;
|
||||
|
||||
protected:
|
||||
StorageManagerIF* tcStore = nullptr;
|
||||
@ -51,7 +51,7 @@ class UdpTcPollingTask : public TcpIpBase, public SystemObject, public Executabl
|
||||
std::vector<uint8_t> receptionBuffer;
|
||||
|
||||
size_t frameSize = 0;
|
||||
timeval receptionTimeout;
|
||||
timeval receptionTimeout{};
|
||||
|
||||
ReturnValue_t handleSuccessfullTcRead(size_t bytesRead);
|
||||
};
|
||||
|
@ -20,13 +20,13 @@
|
||||
const std::string UdpTmTcBridge::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT;
|
||||
|
||||
UdpTmTcBridge::UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination,
|
||||
std::string udpServerPort, object_id_t tmStoreId,
|
||||
const std::string &udpServerPort_, object_id_t tmStoreId,
|
||||
object_id_t tcStoreId)
|
||||
: TmTcBridge(objectId, tcDestination, tmStoreId, tcStoreId) {
|
||||
if (udpServerPort == "") {
|
||||
this->udpServerPort = DEFAULT_SERVER_PORT;
|
||||
if (udpServerPort_.empty()) {
|
||||
udpServerPort = DEFAULT_SERVER_PORT;
|
||||
} else {
|
||||
this->udpServerPort = udpServerPort;
|
||||
udpServerPort = udpServerPort_;
|
||||
}
|
||||
|
||||
mutex = MutexFactory::instance()->createMutex();
|
||||
@ -117,8 +117,8 @@ ReturnValue_t UdpTmTcBridge::sendTm(const uint8_t *data, size_t dataLen) {
|
||||
tcpip::printAddress(&clientAddress);
|
||||
#endif
|
||||
|
||||
int bytesSent = sendto(serverSocket, reinterpret_cast<const char *>(data), dataLen, flags,
|
||||
&clientAddress, clientAddressLen);
|
||||
ssize_t bytesSent = sendto(serverSocket, reinterpret_cast<const char *>(data), dataLen, flags,
|
||||
&clientAddress, clientAddressLen);
|
||||
if (bytesSent == SOCKET_ERROR) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "TmTcUdpBridge::sendTm: Send operation failed." << std::endl;
|
||||
@ -150,7 +150,7 @@ void UdpTmTcBridge::checkAndSetClientAddress(sockaddr &newAddress) {
|
||||
clientAddressLen = sizeof(clientAddress);
|
||||
}
|
||||
|
||||
void UdpTmTcBridge::setMutexProperties(MutexIF::TimeoutType timeoutType, dur_millis_t timeoutMs) {
|
||||
this->timeoutType = timeoutType;
|
||||
this->mutexTimeoutMs = timeoutMs;
|
||||
void UdpTmTcBridge::setMutexProperties(MutexIF::TimeoutType timeoutType_, dur_millis_t timeoutMs) {
|
||||
timeoutType = timeoutType_;
|
||||
mutexTimeoutMs = timeoutMs;
|
||||
}
|
||||
|
@ -29,10 +29,10 @@ class UdpTmTcBridge : public TmTcBridge, public TcpIpBase {
|
||||
/* The ports chosen here should not be used by any other process. */
|
||||
static const std::string DEFAULT_SERVER_PORT;
|
||||
|
||||
UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination, std::string udpServerPort = "",
|
||||
object_id_t tmStoreId = objects::TM_STORE,
|
||||
UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination,
|
||||
const std::string& udpServerPort = "", object_id_t tmStoreId = objects::TM_STORE,
|
||||
object_id_t tcStoreId = objects::TC_STORE);
|
||||
virtual ~UdpTmTcBridge();
|
||||
~UdpTmTcBridge() override;
|
||||
|
||||
/**
|
||||
* Set properties of internal mutex.
|
||||
@ -46,12 +46,12 @@ class UdpTmTcBridge : public TmTcBridge, public TcpIpBase {
|
||||
std::string getUdpPort() const;
|
||||
|
||||
protected:
|
||||
virtual ReturnValue_t sendTm(const uint8_t* data, size_t dataLen) override;
|
||||
ReturnValue_t sendTm(const uint8_t* data, size_t dataLen) override;
|
||||
|
||||
private:
|
||||
std::string udpServerPort;
|
||||
|
||||
struct sockaddr clientAddress;
|
||||
struct sockaddr clientAddress = {};
|
||||
socklen_t clientAddressLen = 0;
|
||||
|
||||
//! Access to the client address is mutex protected as it is set by another task.
|
||||
|
@ -1,32 +1,30 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
Clock.cpp
|
||||
FixedTimeslotTask.cpp
|
||||
BinarySemaphore.cpp
|
||||
BinSemaphUsingTask.cpp
|
||||
CountingSemaphore.cpp
|
||||
CountingSemaphUsingTask.cpp
|
||||
MessageQueue.cpp
|
||||
Mutex.cpp
|
||||
MutexFactory.cpp
|
||||
PeriodicTask.cpp
|
||||
QueueFactory.cpp
|
||||
SemaphoreFactory.cpp
|
||||
TaskFactory.cpp
|
||||
Timekeeper.cpp
|
||||
TaskManagement.cpp
|
||||
QueueMapManager.cpp
|
||||
)
|
||||
target_sources(
|
||||
${LIB_FSFW_NAME}
|
||||
PRIVATE Clock.cpp
|
||||
FixedTimeslotTask.cpp
|
||||
BinarySemaphore.cpp
|
||||
BinSemaphUsingTask.cpp
|
||||
CountingSemaphore.cpp
|
||||
CountingSemaphUsingTask.cpp
|
||||
MessageQueue.cpp
|
||||
Mutex.cpp
|
||||
MutexFactory.cpp
|
||||
PeriodicTask.cpp
|
||||
QueueFactory.cpp
|
||||
SemaphoreFactory.cpp
|
||||
TaskFactory.cpp
|
||||
Timekeeper.cpp
|
||||
TaskManagement.cpp
|
||||
QueueMapManager.cpp)
|
||||
|
||||
# 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 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
|
||||
# library.
|
||||
if(NOT LIB_OS_NAME)
|
||||
message(STATUS
|
||||
"LIB_OS_NAME is empty. Make sure to include the FreeRTOS header path properly."
|
||||
)
|
||||
message(
|
||||
STATUS
|
||||
"LIB_OS_NAME is empty. Make sure to include the FreeRTOS header path properly."
|
||||
)
|
||||
else()
|
||||
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
|
||||
${LIB_OS_NAME}
|
||||
)
|
||||
target_link_libraries(${LIB_FSFW_NAME} PRIVATE ${LIB_OS_NAME})
|
||||
endif()
|
||||
|
@ -11,9 +11,6 @@
|
||||
// TODO sanitize input?
|
||||
// TODO much of this code can be reused for tick-only systems
|
||||
|
||||
uint16_t Clock::leapSeconds = 0;
|
||||
MutexIF* Clock::timeMutex = nullptr;
|
||||
|
||||
uint32_t Clock::getTicksPerSecond(void) { return 1000; }
|
||||
|
||||
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
|
||||
|
@ -1,27 +1,23 @@
|
||||
#include "fsfw/osal/freertos/FixedTimeslotTask.h"
|
||||
|
||||
#include "fsfw/objectmanager/ObjectManager.h"
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
#include "fsfw/serviceinterface.h"
|
||||
|
||||
uint32_t FixedTimeslotTask::deadlineMissedCount = 0;
|
||||
const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = configMINIMAL_STACK_SIZE;
|
||||
|
||||
FixedTimeslotTask::FixedTimeslotTask(TaskName name, TaskPriority setPriority,
|
||||
TaskStackSize setStack, TaskPeriod overallPeriod,
|
||||
void (*setDeadlineMissedFunc)())
|
||||
: started(false), handle(nullptr), pst(overallPeriod * 1000) {
|
||||
TaskStackSize setStack, TaskPeriod period,
|
||||
TaskDeadlineMissedFunction dlmFunc_)
|
||||
: FixedTimeslotTaskBase(period, dlmFunc_), started(false), handle(nullptr) {
|
||||
configSTACK_DEPTH_TYPE stackSize = setStack / sizeof(configSTACK_DEPTH_TYPE);
|
||||
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) {
|
||||
// The argument is re-interpreted as FixedTimeslotTask. The Task object is
|
||||
// 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,
|
||||
* but in FreeRTOS, tasks start as soon as they are created if the scheduler
|
||||
* is running but not if the scheduler is not running.
|
||||
@ -32,26 +28,18 @@ void FixedTimeslotTask::taskEntryPoint(void* argument) {
|
||||
* can continue */
|
||||
|
||||
if (not originalTask->started) {
|
||||
vTaskSuspend(NULL);
|
||||
vTaskSuspend(nullptr);
|
||||
}
|
||||
|
||||
originalTask->taskFunctionality();
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::debug << "Polling task " << originalTask->handle << " returned from taskFunctionality."
|
||||
<< std::endl;
|
||||
#else
|
||||
sif::printDebug("Polling task returned from taskFunctionality\n");
|
||||
#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() {
|
||||
started = true;
|
||||
|
||||
@ -63,31 +51,12 @@ ReturnValue_t FixedTimeslotTask::startTask() {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, uint32_t slotTimeMs,
|
||||
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() {
|
||||
[[noreturn]] void FixedTimeslotTask::taskFunctionality() {
|
||||
// A local iterator for the Polling Sequence Table is created to find the
|
||||
// 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.
|
||||
uint32_t intervalMs = slotListIter->pollingTimeMs;
|
||||
@ -108,10 +77,10 @@ void FixedTimeslotTask::taskFunctionality() {
|
||||
/* Enter the loop that defines the task behavior. */
|
||||
for (;;) {
|
||||
// The component for this slot is executed and the next one is chosen.
|
||||
this->pst.executeAndAdvance();
|
||||
if (not pst.slotFollowsImmediately()) {
|
||||
this->pollingSeqTable.executeAndAdvance();
|
||||
if (not pollingSeqTable.slotFollowsImmediately()) {
|
||||
// Get the interval till execution of the next slot.
|
||||
intervalMs = this->pst.getIntervalToPreviousSlotMs();
|
||||
intervalMs = this->pollingSeqTable.getIntervalToPreviousSlotMs();
|
||||
interval = pdMS_TO_TICKS(intervalMs);
|
||||
|
||||
#if (tskKERNEL_VERSION_MAJOR == 10 && tskKERNEL_VERSION_MINOR >= 4) || tskKERNEL_VERSION_MAJOR > 10
|
||||
@ -132,8 +101,8 @@ void FixedTimeslotTask::taskFunctionality() {
|
||||
}
|
||||
|
||||
void FixedTimeslotTask::handleMissedDeadline() {
|
||||
if (deadlineMissedFunc != nullptr) {
|
||||
this->deadlineMissedFunc();
|
||||
if (dlmFunc != nullptr) {
|
||||
dlmFunc();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,11 +4,11 @@
|
||||
#include "FreeRTOS.h"
|
||||
#include "FreeRTOSTaskIF.h"
|
||||
#include "fsfw/tasks/FixedSlotSequence.h"
|
||||
#include "fsfw/tasks/FixedTimeslotTaskIF.h"
|
||||
#include "fsfw/tasks/Typedef.h"
|
||||
#include "fsfw/tasks/FixedTimeslotTaskBase.h"
|
||||
#include "fsfw/tasks/definitions.h"
|
||||
#include "task.h"
|
||||
|
||||
class FixedTimeslotTask : public FixedTimeslotTaskIF, public FreeRTOSTaskIF {
|
||||
class FixedTimeslotTask : public FixedTimeslotTaskBase, public FreeRTOSTaskIF {
|
||||
public:
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
FixedTimeslotTask(TaskName name, TaskPriority setPriority, TaskStackSize setStack,
|
||||
TaskPeriod overallPeriod, void (*setDeadlineMissedFunc)());
|
||||
TaskPeriod overallPeriod, TaskDeadlineMissedFunction dlmFunc);
|
||||
|
||||
/**
|
||||
* @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
|
||||
* calling the PST's destructor.
|
||||
*/
|
||||
virtual ~FixedTimeslotTask(void);
|
||||
~FixedTimeslotTask() override;
|
||||
|
||||
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) override;
|
||||
|
||||
uint32_t getPeriodMs() const override;
|
||||
|
||||
ReturnValue_t checkSequence() const override;
|
||||
ReturnValue_t startTask() override;
|
||||
|
||||
ReturnValue_t sleepFor(uint32_t ms) override;
|
||||
|
||||
@ -61,17 +44,6 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF, public FreeRTOSTaskIF {
|
||||
bool started;
|
||||
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.
|
||||
* @details
|
||||
@ -88,7 +60,7 @@ class FixedTimeslotTask : public FixedTimeslotTaskIF, public FreeRTOSTaskIF {
|
||||
* It links the functionalities provided by FixedSlotSequence with the
|
||||
* OS's System Calls to keep the timing of the periods.
|
||||
*/
|
||||
void taskFunctionality(void);
|
||||
[[noreturn]] void taskFunctionality();
|
||||
|
||||
void handleMissedDeadline();
|
||||
};
|
||||
|
@ -6,11 +6,11 @@
|
||||
|
||||
class FreeRTOSTaskIF {
|
||||
public:
|
||||
virtual ~FreeRTOSTaskIF() {}
|
||||
virtual ~FreeRTOSTaskIF() = default;
|
||||
virtual TaskHandle_t getTaskHandle() = 0;
|
||||
|
||||
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
|
||||
* into account. Drawing this on paper with a timeline helps to understand
|
||||
* it. */
|
||||
|
@ -4,8 +4,9 @@
|
||||
#include "fsfw/osal/freertos/QueueMapManager.h"
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
|
||||
MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize)
|
||||
: maxMessageSize(maxMessageSize) {
|
||||
MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize, MqArgs* args)
|
||||
: MessageQueueBase(MessageQueueIF::NO_QUEUE, MessageQueueIF::NO_QUEUE, args),
|
||||
maxMessageSize(maxMessageSize) {
|
||||
handle = xQueueCreate(messageDepth, maxMessageSize);
|
||||
if (handle == nullptr) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
@ -15,10 +16,10 @@ MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize)
|
||||
#else
|
||||
sif::printError("MessageQueue::MessageQueue: Creation failed\n");
|
||||
sif::printError("Specified Message Depth: %d\n", messageDepth);
|
||||
sif::printError("Specified MAximum Message Size: %d\n", maxMessageSize);
|
||||
sif::printError("Specified Maximum Message Size: %d\n", maxMessageSize);
|
||||
#endif
|
||||
}
|
||||
QueueMapManager::instance()->addMessageQueue(handle, &queueId);
|
||||
QueueMapManager::instance()->addMessageQueue(handle, &id);
|
||||
}
|
||||
|
||||
MessageQueue::~MessageQueue() {
|
||||
@ -29,28 +30,6 @@ MessageQueue::~MessageQueue() {
|
||||
|
||||
void MessageQueue::switchSystemContext(CallContext callContext) { this->callContext = callContext; }
|
||||
|
||||
ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
||||
bool ignoreFault) {
|
||||
return sendMessageFrom(sendTo, message, this->getId(), ignoreFault);
|
||||
}
|
||||
|
||||
ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessageIF* message) {
|
||||
return sendToDefaultFrom(message, this->getId());
|
||||
}
|
||||
|
||||
ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessageIF* message,
|
||||
MessageQueueId_t sentFrom, bool ignoreFault) {
|
||||
return sendMessageFrom(defaultDestination, message, sentFrom, ignoreFault);
|
||||
}
|
||||
|
||||
ReturnValue_t MessageQueue::reply(MessageQueueMessageIF* message) {
|
||||
if (this->lastPartner != MessageQueueIF::NO_QUEUE) {
|
||||
return sendMessageFrom(this->lastPartner, message, this->getId());
|
||||
} else {
|
||||
return NO_REPLY_PARTNER;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
||||
MessageQueueId_t sentFrom, bool ignoreFault) {
|
||||
return sendMessageFromMessageQueue(sendTo, message, sentFrom, ignoreFault, callContext);
|
||||
@ -72,27 +51,16 @@ ReturnValue_t MessageQueue::handleSendResult(BaseType_t result, bool ignoreFault
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message,
|
||||
MessageQueueId_t* receivedFrom) {
|
||||
ReturnValue_t status = this->receiveMessage(message);
|
||||
if (status == HasReturnvaluesIF::RETURN_OK) {
|
||||
*receivedFrom = this->lastPartner;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
|
||||
BaseType_t result = xQueueReceive(handle, reinterpret_cast<void*>(message->getBuffer()), 0);
|
||||
if (result == pdPASS) {
|
||||
this->lastPartner = message->getSender();
|
||||
this->last = message->getSender();
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
} else {
|
||||
return MessageQueueIF::EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
MessageQueueId_t MessageQueue::getLastPartner() const { return lastPartner; }
|
||||
|
||||
ReturnValue_t MessageQueue::flush(uint32_t* count) {
|
||||
// TODO FreeRTOS does not support flushing partially
|
||||
// Is always successful
|
||||
@ -100,17 +68,6 @@ ReturnValue_t MessageQueue::flush(uint32_t* count) {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
MessageQueueId_t MessageQueue::getId() const { return queueId; }
|
||||
|
||||
void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) {
|
||||
defaultDestinationSet = true;
|
||||
this->defaultDestination = defaultDestination;
|
||||
}
|
||||
|
||||
MessageQueueId_t MessageQueue::getDefaultDestination() const { return defaultDestination; }
|
||||
|
||||
bool MessageQueue::isDefaultDestinationSet() const { return defaultDestinationSet; }
|
||||
|
||||
// static core function to send messages.
|
||||
ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
|
||||
MessageQueueMessageIF* message,
|
||||
|
@ -1,12 +1,15 @@
|
||||
#ifndef FSFW_OSAL_FREERTOS_MESSAGEQUEUE_H_
|
||||
#define FSFW_OSAL_FREERTOS_MESSAGEQUEUE_H_
|
||||
|
||||
#include <fsfw/ipc/MessageQueueBase.h>
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "TaskManagement.h"
|
||||
#include "fsfw/internalerror/InternalErrorReporterIF.h"
|
||||
#include "fsfw/ipc/MessageQueueIF.h"
|
||||
#include "fsfw/ipc/MessageQueueMessage.h"
|
||||
#include "fsfw/ipc/MessageQueueMessageIF.h"
|
||||
#include "fsfw/ipc/definitions.h"
|
||||
#include "queue.h"
|
||||
|
||||
/**
|
||||
@ -32,7 +35,7 @@
|
||||
* @ingroup osal
|
||||
* @ingroup message_queue
|
||||
*/
|
||||
class MessageQueue : public MessageQueueIF {
|
||||
class MessageQueue : public MessageQueueBase {
|
||||
friend class MessageQueueSenderIF;
|
||||
|
||||
public:
|
||||
@ -53,7 +56,8 @@ class MessageQueue : public MessageQueueIF {
|
||||
* This should be left default.
|
||||
*/
|
||||
MessageQueue(size_t messageDepth = 3,
|
||||
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE);
|
||||
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE,
|
||||
MqArgs* args = nullptr);
|
||||
|
||||
/** Copying message queues forbidden */
|
||||
MessageQueue(const MessageQueue&) = delete;
|
||||
@ -73,40 +77,15 @@ class MessageQueue : public MessageQueueIF {
|
||||
*/
|
||||
void switchSystemContext(CallContext callContext);
|
||||
|
||||
/** MessageQueueIF implementation */
|
||||
ReturnValue_t sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
||||
bool ignoreFault = false) override;
|
||||
QueueHandle_t getNativeQueueHandle();
|
||||
|
||||
ReturnValue_t sendToDefault(MessageQueueMessageIF* message) override;
|
||||
|
||||
ReturnValue_t reply(MessageQueueMessageIF* message) override;
|
||||
// Implement non-generic MessageQueueIF functions not handled by MessageQueueBase
|
||||
virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
||||
MessageQueueId_t sentFrom = NO_QUEUE,
|
||||
bool ignoreFault = false) override;
|
||||
|
||||
virtual ReturnValue_t sendToDefaultFrom(MessageQueueMessageIF* message,
|
||||
MessageQueueId_t sentFrom = NO_QUEUE,
|
||||
bool ignoreFault = false) override;
|
||||
|
||||
ReturnValue_t receiveMessage(MessageQueueMessageIF* message,
|
||||
MessageQueueId_t* receivedFrom) override;
|
||||
|
||||
ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override;
|
||||
|
||||
ReturnValue_t flush(uint32_t* count) override;
|
||||
|
||||
MessageQueueId_t getLastPartner() const override;
|
||||
|
||||
MessageQueueId_t getId() const override;
|
||||
|
||||
void setDefaultDestination(MessageQueueId_t defaultDestination) override;
|
||||
|
||||
MessageQueueId_t getDefaultDestination() const override;
|
||||
|
||||
bool isDefaultDestinationSet() const override;
|
||||
|
||||
QueueHandle_t getNativeQueueHandle();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Implementation to be called from any send Call within
|
||||
@ -136,12 +115,8 @@ class MessageQueue : public MessageQueueIF {
|
||||
static ReturnValue_t handleSendResult(BaseType_t result, bool ignoreFault);
|
||||
|
||||
private:
|
||||
bool defaultDestinationSet = false;
|
||||
QueueHandle_t handle;
|
||||
MessageQueueId_t queueId = MessageQueueIF::NO_QUEUE;
|
||||
|
||||
MessageQueueId_t defaultDestination = MessageQueueIF::NO_QUEUE;
|
||||
MessageQueueId_t lastPartner = MessageQueueIF::NO_QUEUE;
|
||||
const size_t maxMessageSize;
|
||||
//! Stores the current system context
|
||||
CallContext callContext = CallContext::TASK;
|
||||
|
@ -5,27 +5,28 @@
|
||||
#include "fsfw/tasks/ExecutableObjectIF.h"
|
||||
|
||||
PeriodicTask::PeriodicTask(const char* name, TaskPriority setPriority, TaskStackSize setStack,
|
||||
TaskPeriod setPeriod, TaskDeadlineMissedFunction deadlineMissedFunc)
|
||||
: started(false), handle(NULL), period(setPeriod), deadlineMissedFunc(deadlineMissedFunc) {
|
||||
TaskPeriod setPeriod, TaskDeadlineMissedFunction dlmFunc_)
|
||||
: PeriodicTaskBase(setPeriod, dlmFunc_), started(false), handle(nullptr) {
|
||||
configSTACK_DEPTH_TYPE stackSize = setStack / sizeof(configSTACK_DEPTH_TYPE);
|
||||
BaseType_t status = xTaskCreate(taskEntryPoint, name, stackSize, this, setPriority, &handle);
|
||||
if (status != pdPASS) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::debug << "PeriodicTask Insufficient heap memory remaining. "
|
||||
"Status: "
|
||||
sif::debug << "PeriodicTask::PeriodicTask Insufficient heap memory remaining. Status: "
|
||||
<< status << std::endl;
|
||||
#else
|
||||
sif::printDebug("PeriodicTask::PeriodicTask: Insufficient heap memory remaining. Status: %d\n",
|
||||
status);
|
||||
#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) {
|
||||
// The argument is re-interpreted as PeriodicTask. The Task object is
|
||||
// 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,
|
||||
* but in FreeRTOS, tasks start as soon as they are created if the scheduler
|
||||
* is running but not if the scheduler is not running.
|
||||
@ -36,7 +37,7 @@ void PeriodicTask::taskEntryPoint(void* argument) {
|
||||
* can continue */
|
||||
|
||||
if (not originalTask->started) {
|
||||
vTaskSuspend(NULL);
|
||||
vTaskSuspend(nullptr);
|
||||
}
|
||||
|
||||
originalTask->taskFunctionality();
|
||||
@ -62,13 +63,11 @@ ReturnValue_t PeriodicTask::sleepFor(uint32_t ms) {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
void PeriodicTask::taskFunctionality() {
|
||||
[[noreturn]] void PeriodicTask::taskFunctionality() {
|
||||
TickType_t xLastWakeTime;
|
||||
const TickType_t xPeriod = pdMS_TO_TICKS(this->period * 1000.);
|
||||
|
||||
for (auto const& object : objectList) {
|
||||
object->initializeAfterTaskCreation();
|
||||
}
|
||||
initObjsAfterTaskCreation();
|
||||
|
||||
/* The xLastWakeTime variable needs to be initialized with the current tick
|
||||
count. Note that this is the only time the variable is written to
|
||||
@ -77,8 +76,8 @@ void PeriodicTask::taskFunctionality() {
|
||||
xLastWakeTime = xTaskGetTickCount();
|
||||
/* Enter the loop that defines the task behavior. */
|
||||
for (;;) {
|
||||
for (auto const& object : objectList) {
|
||||
object->performOperation();
|
||||
for (auto const& objectPair : objectList) {
|
||||
objectPair.first->performOperation(objectPair.second);
|
||||
}
|
||||
|
||||
#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; }
|
||||
|
||||
void PeriodicTask::handleMissedDeadline() {
|
||||
if (deadlineMissedFunc != nullptr) {
|
||||
this->deadlineMissedFunc();
|
||||
if (dlmFunc != nullptr) {
|
||||
dlmFunc();
|
||||
}
|
||||
}
|
||||
|
@ -6,8 +6,8 @@
|
||||
#include "FreeRTOS.h"
|
||||
#include "FreeRTOSTaskIF.h"
|
||||
#include "fsfw/objectmanager/ObjectManagerIF.h"
|
||||
#include "fsfw/tasks/PeriodicTaskIF.h"
|
||||
#include "fsfw/tasks/Typedef.h"
|
||||
#include "fsfw/tasks/PeriodicTaskBase.h"
|
||||
#include "fsfw/tasks/definitions.h"
|
||||
#include "task.h"
|
||||
|
||||
class ExecutableObjectIF;
|
||||
@ -17,7 +17,7 @@ class ExecutableObjectIF;
|
||||
* periodic activities of multiple objects.
|
||||
* @ingroup task_handling
|
||||
*/
|
||||
class PeriodicTask : public PeriodicTaskIF, public FreeRTOSTaskIF {
|
||||
class PeriodicTask : public PeriodicTaskBase, public FreeRTOSTaskIF {
|
||||
public:
|
||||
/**
|
||||
* 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
|
||||
* the task object's lifetime, so the destructor is empty.
|
||||
*/
|
||||
virtual ~PeriodicTask(void);
|
||||
~PeriodicTask() override;
|
||||
|
||||
/**
|
||||
* @brief The method to start the task.
|
||||
@ -53,27 +53,6 @@ class PeriodicTask : public PeriodicTaskIF, public FreeRTOSTaskIF {
|
||||
* to the system call.
|
||||
*/
|
||||
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;
|
||||
|
||||
@ -83,28 +62,6 @@ class PeriodicTask : public PeriodicTaskIF, public FreeRTOSTaskIF {
|
||||
bool started;
|
||||
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.
|
||||
* @details
|
||||
@ -125,7 +82,7 @@ class PeriodicTask : public PeriodicTaskIF, public FreeRTOSTaskIF {
|
||||
* the next period.
|
||||
* On missing the deadline, the deadlineMissedFunction is executed.
|
||||
*/
|
||||
void taskFunctionality(void);
|
||||
[[noreturn]] void taskFunctionality();
|
||||
|
||||
void handleMissedDeadline();
|
||||
};
|
||||
|
@ -22,8 +22,9 @@ QueueFactory::QueueFactory() {}
|
||||
|
||||
QueueFactory::~QueueFactory() {}
|
||||
|
||||
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize) {
|
||||
return new MessageQueue(messageDepth, maxMessageSize);
|
||||
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize,
|
||||
MqArgs* args) {
|
||||
return new MessageQueue(messageDepth, maxMessageSize, args);
|
||||
}
|
||||
|
||||
void QueueFactory::deleteMessageQueue(MessageQueueIF* queue) { delete queue; }
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user