1
0
forked from fsfw/fsfw

Compare commits

..

80 Commits

Author SHA1 Message Date
f11433e50f Merge pull request 'Release v5.0.0' (#657) from development into master
Reviewed-on: fsfw/fsfw#657
2022-07-25 15:05:56 +02:00
edc5a314b8 Merge pull request 'v5.0.0' (#654) from v5.0.0 into development
Reviewed-on: fsfw/fsfw#654
2022-07-25 14:53:35 +02:00
54fc35eae7 re-run afmt 2022-07-25 14:36:18 +02:00
05d4162f5b Merge branch 'development' into v5.0.0 2022-07-25 14:35:36 +02:00
e030878023 changelog 2022-07-25 14:33:10 +02:00
c96e304b68 Merge pull request 'Possible Ring Buffer Fix' (#586) from eive/fsfw:mueller/possible-ring-buffer-fix into development
Merged to avoid crashing bug until full functionality is fixed.

Reviewed-on: fsfw/fsfw#586
2022-07-25 10:12:39 +02:00
9bbe1dc716 Merge branch 'development' into mueller/possible-ring-buffer-fix 2022-07-21 13:23:44 +02:00
74794bb71b apply auto-formatter 2022-07-18 16:08:06 +02:00
6f751c2cf9 Merge branch 'development' into v5.0.0 2022-07-18 15:12:21 +02:00
9a2e68b37e Merge pull request 'Move HAL and Tests folder' (#653) from mueller/move-hal-tests-folder into development
Reviewed-on: fsfw/fsfw#653
2022-07-18 15:05:25 +02:00
91067cde98 typo 2022-07-18 15:00:40 +02:00
428018e4f1 update changelog 2022-07-18 14:59:25 +02:00
8b6dd3f868 add date to changelog 2022-07-18 14:49:27 +02:00
f6ede7cd3e bump version 2022-07-18 14:46:36 +02:00
4da18172b3 Merge branch 'development' into mueller/possible-ring-buffer-fix 2022-07-18 14:37:56 +02:00
6e5239e9a0 update jenkinsfile 2022-07-18 14:36:40 +02:00
78b09ed0c9 fixes includes 2022-07-18 11:58:55 +02:00
fdf35232ee some fixes 2022-07-18 11:47:00 +02:00
8465670374 separate unittest folder 2022-07-18 11:42:51 +02:00
3b23fb77b4 add obsolete add_subdirectory calls 2022-07-18 09:01:45 +02:00
6f7be281ef move HAL and tests folder 2022-07-18 08:59:40 +02:00
3686bbc486 Merge pull request 'DHB Reply Timeout' (#637) from meier/dhbReplyTimeout into development
Reviewed-on: fsfw/fsfw#637
2022-07-14 09:17:18 +02:00
ecac08814e better naming for functions which reset states of replies 2022-07-14 09:15:13 +02:00
e8b8fff0b5 Merge branch 'development' into meier/dhbReplyTimeout 2022-07-14 09:01:28 +02:00
4d34f93cfc missing reset of timedOut value in loop of decrementDeviceReplyMap 2022-07-14 08:58:23 +02:00
adbf375f38 some small fixes to dhb countdown addition 2022-07-13 21:58:07 +02:00
2e42f53682 Merge pull request 'New PoolEntry constructor' (#651) from eive/fsfw:mueller/new-pool-entry-ctor into development
Reviewed-on: fsfw/fsfw#651
2022-07-13 17:43:56 +02:00
c519b70302 Merge pull request 'printout tweak' (#652) from mueller/printout-tweak-mq-linux-osal into development
Reviewed-on: fsfw/fsfw#652
2022-07-13 17:35:53 +02:00
45ee307bc4 Merge pull request 'remove duplicate CHANGELOG entries' (#649) from eive/fsfw:mueller/clean-changelog into development
Reviewed-on: fsfw/fsfw#649
2022-07-13 16:50:50 +02:00
8a2068aca6 Merge pull request 'clang-tidy changes for controller module' (#648) from clang-tidy-controllers into development
Reviewed-on: fsfw/fsfw#648
2022-07-13 16:49:15 +02:00
aa60484111 Merge pull request 'clang-tidy changes for actions module' (#647) from clang-tidy-actions into development
Reviewed-on: fsfw/fsfw#647
2022-07-13 16:42:39 +02:00
e99c7f3824 Merge pull request 'Install ETL library in CI/CD' (#645) from mueller/install-etl-cicd into development
Reviewed-on: fsfw/fsfw#645
2022-07-13 16:39:29 +02:00
2ee3ef1f1d Merge branch 'development' into mueller/install-etl-cicd 2022-07-13 16:38:30 +02:00
ce48827ee5 Merge branch 'development' into clang-tidy-actions 2022-07-13 16:00:50 +02:00
0d80fad685 Merge branch 'development' into clang-tidy-controllers 2022-07-13 16:00:42 +02:00
c6253bf0dd Merge branch 'development' into mueller/new-pool-entry-ctor 2022-07-13 15:41:47 +02:00
93933dee02 Merge pull request 'delete run configs' (#646) from mueller/del-cmake-run-cfgs into development
Reviewed-on: fsfw/fsfw#646
2022-07-13 15:37:55 +02:00
0e49640306 update CHANGELOG 2022-07-08 17:59:43 +02:00
32fea9838e add new pool entry constructor
- This constructor allows to simply specify the length.
  This is also the new default constructor for scalar values
  which are initially invalid
2022-07-08 17:56:44 +02:00
0519083894 remove duplicate entries 2022-07-08 17:48:06 +02:00
14bac9a418 clang-tidy changes for controller module 2022-07-04 11:48:36 +02:00
3bef73708f clang-tidy changes for actions module 2022-07-04 11:44:26 +02:00
fef6ddceff delete run configs 2022-07-04 11:16:13 +02:00
5a9db72814 test public linkage 2022-07-04 10:27:14 +02:00
5cccd5caba bump used container 2022-07-04 10:21:47 +02:00
7de56f189b install etl library in ci/cd 2022-07-04 10:13:48 +02:00
df97bbc691 run auto-formatter 2022-06-23 11:56:46 +02:00
2d2f65bf89 moved activation of periodic replies to updatePeriodicReply 2022-06-23 11:54:51 +02:00
3e9ae62b28 Merge branch 'development' into meier/dhbReplyTimeout 2022-06-21 10:49:06 +02:00
2ebefdffae Merge remote-tracking branch 'upstream/development' into mueller/possible-ring-buffer-fix 2022-06-21 10:49:03 +02:00
45792e86b9 Merge remote-tracking branch 'upstream/development' into mueller/possible-ring-buffer-fix 2022-06-21 10:48:04 +02:00
21eb386f3c changed reply timeouts 2022-06-06 12:34:57 +02:00
ade36e65c6 missed reply check in simple command nominal test case 2022-06-06 12:30:27 +02:00
103661facc deugging 2022-06-06 12:26:00 +02:00
ae2f7219fd run auto-formatter 2022-06-06 11:55:42 +02:00
4fba2704aa unit test for detection of missed reply when commanded externally 2022-06-06 10:53:08 +02:00
161dbde0d7 fixed merge conflicts 2022-06-06 10:30:17 +02:00
2fa4fd61d0 device fdir mock 2022-06-05 12:54:13 +02:00
bf673c56c6 unit test for dhb 2022-06-05 12:52:55 +02:00
d871f55a89 Merge remote-tracking branch 'upstream/development' into mueller/possible-ring-buffer-fix 2022-05-16 15:13:47 +02:00
1611a4e1f0 device handler unittest wip 2022-05-16 11:10:35 +02:00
ff40a71582 Merge remote-tracking branch 'upstream/development' into mueller/possible-ring-buffer-fix 2022-05-13 11:30:32 +02:00
e1604b292c Merge branch 'development' into mueller/possible-ring-buffer-fix 2022-05-11 11:34:32 +02:00
7afe30ea88 fixed merge conflict 2022-05-09 12:56:22 +02:00
d3e7037759 Merge branch 'development' into mueller/possible-ring-buffer-fix 2022-04-27 08:42:24 +02:00
0aee86442e typo in readme 2022-04-26 11:48:18 +02:00
951c077abc option to use Countdown object to time out replies 2022-04-26 10:03:04 +02:00
755dcf66a3 Merge remote-tracking branch 'upstream/development' into mueller/possible-ring-buffer-fix 2022-04-25 15:16:52 +02:00
b7ffd2653b Merge remote-tracking branch 'upstream/development' into mueller/possible-ring-buffer-fix 2022-04-25 15:11:52 +02:00
7a5ce57bbc Merge branch 'development' into mueller/possible-ring-buffer-fix 2022-04-11 17:35:42 +02:00
adfefdd93f printout tweak 2022-04-11 14:19:01 +02:00
b7a316008a increase allowed read bytes 2022-03-28 15:07:46 +02:00
f598f7030f Merge remote-tracking branch 'upstream/development' into mueller/possible-ring-buffer-fix 2022-03-28 15:03:01 +02:00
70f575396d Added changelog 2022-03-25 15:27:22 +01:00
ad57e6713e Fixed Unittests 2022-03-25 15:20:06 +01:00
23f8e5cb41 some more tests fail 2022-03-24 21:01:21 +01:00
879223f38f added nullptr check 2022-03-24 20:57:42 +01:00
8a44c498c5 add two additional tests for ring buffer 2022-03-24 16:50:59 +01:00
a891769a02 ring buffer cfg error warning 2022-03-24 11:32:27 +01:00
df97c582d7 possibly important fix for ring buffer write 2022-03-23 16:48:17 +01:00
314 changed files with 1139 additions and 529 deletions

View File

@ -1,7 +0,0 @@
<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-example-hosted" TARGET_NAME="fsfw-tests_coverage" CONFIG_NAME="Debug Unittest" RUN_TARGET_PROJECT_NAME="fsfw-example-hosted" RUN_TARGET_NAME="fsfw-tests">
<method v="2">
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
</method>
</configuration>
</component>

View File

@ -1,7 +0,0 @@
<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>

View File

@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
# [unreleased] # [unreleased]
# [v5.0.0] # [v5.0.0] 25.07.2022
## Changes ## Changes
@ -19,16 +19,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Bump C++ required version to C++17. Every project which uses the FSFW and every modern - Bump C++ required version to C++17. Every project which uses the FSFW and every modern
compiler supports it compiler supports it
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/622 PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/622
- 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
- New CMake option `FSFW_HAL_LINUX_ADD_LIBGPIOD` to specifically exclude `gpiod` code. - New CMake option `FSFW_HAL_LINUX_ADD_LIBGPIOD` to specifically exclude `gpiod` code.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/572 PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/572
- HAL Devicehandlers: Periodic printout is run-time configurable now - HAL Devicehandlers: Periodic printout is run-time configurable now
- `oneShotAction` flag in the `TestTask` class is not static anymore - `oneShotAction` flag in the `TestTask` class is not static anymore
- `SimpleRingBuffer::writeData` now checks if the amount is larger than the total size of the
Buffer and rejects such writeData calls with `HasReturnvaluesIF::RETURN_FAILED`
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/586
- Major update for version handling, using `git describe` to fetch version information with git. - 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 PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/601
- Add helper functions provided by [`cmake-modules`](https://github.com/bilke/cmake-modules) - Add helper functions provided by [`cmake-modules`](https://github.com/bilke/cmake-modules)
@ -46,6 +43,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
creation call. It allows passing context information and an arbitrary user argument into creation call. It allows passing context information and an arbitrary user argument into
the message queue. Also streamlined and simplified `MessageQueue` implementation for all OSALs the message queue. Also streamlined and simplified `MessageQueue` implementation for all OSALs
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/583 PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/583
- Internal API change: Moved the `fsfw_hal` to the `src` folder and integration and internal
tests part of `fsfw_tests` to `src`. Unittests are now in a dedicated folder called `unittests`
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/653
### Task Module Refactoring ### Task Module Refactoring
@ -120,6 +120,8 @@ https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/593
## Additions ## Additions
- New constructor for PoolEntry which allows to simply specify the length of the pool entry.
This is also the new default constructor for scalar value with 0 as an initial value
- Added options for CI/CD builds: `FSFW_CICD_BUILD`. This allows the source code to know - Added options for CI/CD builds: `FSFW_CICD_BUILD`. This allows the source code to know
whether it is running in CI/CD whether it is running in CI/CD
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/623 PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/623

View File

@ -13,7 +13,7 @@ list(APPEND CMAKE_MODULE_PATH
# Version file handling # # Version file handling #
# ############################################################################## # ##############################################################################
set(FSFW_VERSION_IF_GIT_FAILS 4) set(FSFW_VERSION_IF_GIT_FAILS 5)
set(FSFW_SUBVERSION_IF_GIT_FAILS 0) set(FSFW_SUBVERSION_IF_GIT_FAILS 0)
set(FSFW_REVISION_IF_GIT_FAILS 0) set(FSFW_REVISION_IF_GIT_FAILS 0)
@ -67,6 +67,7 @@ endif()
set(FSFW_SOURCES_DIR "${CMAKE_SOURCE_DIR}/src/fsfw") set(FSFW_SOURCES_DIR "${CMAKE_SOURCE_DIR}/src/fsfw")
set(FSFW_ETL_LIB_NAME etl) set(FSFW_ETL_LIB_NAME etl)
set(FSFW_ETL_LINK_TARGET etl::etl)
set(FSFW_ETL_LIB_MAJOR_VERSION set(FSFW_ETL_LIB_MAJOR_VERSION
20 20
CACHE STRING "ETL library major version requirement") CACHE STRING "ETL library major version requirement")
@ -103,11 +104,11 @@ if(FSFW_GENERATE_SECTIONS)
option(FSFW_REMOVE_UNUSED_CODE "Remove unused code" ON) option(FSFW_REMOVE_UNUSED_CODE "Remove unused code" ON)
endif() endif()
option(FSFW_BUILD_UNITTESTS option(FSFW_BUILD_TESTS "Build unittest binary in addition to static library"
"Build unittest binary in addition to static library" OFF) OFF)
option(FSFW_CICD_BUILD "Build for CI/CD. This can disable problematic test" OFF) option(FSFW_CICD_BUILD "Build for CI/CD. This can disable problematic test" OFF)
option(FSFW_BUILD_DOCS "Build documentation with Sphinx and Doxygen" OFF) option(FSFW_BUILD_DOCS "Build documentation with Sphinx and Doxygen" OFF)
if(FSFW_BUILD_UNITTESTS) if(FSFW_BUILD_TESTS)
option(FSFW_TESTS_GEN_COV "Generate coverage data for unittests" ON) option(FSFW_TESTS_GEN_COV "Generate coverage data for unittests" ON)
endif() endif()
@ -139,7 +140,7 @@ if(IPO_SUPPORTED AND FSFW_ENABLE_IPO)
TRUE) TRUE)
endif() endif()
if(FSFW_BUILD_UNITTESTS) if(FSFW_BUILD_TESTS)
message( message(
STATUS STATUS
"${MSG_PREFIX} Building the FSFW unittests in addition to the static library" "${MSG_PREFIX} Building the FSFW unittests in addition to the static library"
@ -162,10 +163,9 @@ if(FSFW_BUILD_UNITTESTS)
list(APPEND FSFW_FETCH_CONTENT_TARGETS Catch2) list(APPEND FSFW_FETCH_CONTENT_TARGETS Catch2)
endif() endif()
set(FSFW_CONFIG_PATH tests/src/fsfw_tests/unit/testcfg) set(FSFW_CONFIG_PATH unittests/testcfg)
configure_file(tests/src/fsfw_tests/unit/testcfg/FSFWConfig.h.in FSFWConfig.h) configure_file(unittests/testcfg/FSFWConfig.h.in FSFWConfig.h)
configure_file(tests/src/fsfw_tests/unit/testcfg/TestsConfig.h.in configure_file(unittests/testcfg/TestsConfig.h.in tests/TestsConfig.h)
tests/TestsConfig.h)
project(${FSFW_TEST_TGT} CXX C) project(${FSFW_TEST_TGT} CXX C)
add_executable(${FSFW_TEST_TGT}) add_executable(${FSFW_TEST_TGT})
@ -281,16 +281,15 @@ message(
) )
add_subdirectory(src) add_subdirectory(src)
add_subdirectory(tests)
if(FSFW_ADD_HAL)
add_subdirectory(hal)
endif()
add_subdirectory(contrib) add_subdirectory(contrib)
if(FSFW_BUILD_TESTS)
add_subdirectory(unittests)
endif()
if(FSFW_BUILD_DOCS) if(FSFW_BUILD_DOCS)
add_subdirectory(docs) add_subdirectory(docs)
endif() endif()
if(FSFW_BUILD_UNITTESTS) if(FSFW_BUILD_TESTS)
if(FSFW_TESTS_GEN_COV) if(FSFW_TESTS_GEN_COV)
if(CMAKE_COMPILER_IS_GNUCXX) if(CMAKE_COMPILER_IS_GNUCXX)
include(CodeCoverage) include(CodeCoverage)
@ -447,8 +446,8 @@ target_include_directories(
target_compile_options(${LIB_FSFW_NAME} PRIVATE ${FSFW_WARNING_FLAGS} target_compile_options(${LIB_FSFW_NAME} PRIVATE ${FSFW_WARNING_FLAGS}
${COMPILER_FLAGS}) ${COMPILER_FLAGS})
target_link_libraries(${LIB_FSFW_NAME} PRIVATE ${FSFW_ETL_LINK_TARGET} target_link_libraries(${LIB_FSFW_NAME} PRIVATE ${FSFW_ADDITIONAL_LINK_LIBS})
${FSFW_ADDITIONAL_LINK_LIBS}) target_link_libraries(${LIB_FSFW_NAME} PUBLIC ${FSFW_ETL_LINK_TARGET})
string( string(
CONCAT CONCAT

View File

@ -139,7 +139,7 @@ You can also use `-DFSFW_OSAL=linux` on Linux systems.
Coverage data in HTML format can be generated using the `CodeCoverage` Coverage data in HTML format can be generated using the `CodeCoverage`
[CMake module](https://github.com/bilke/cmake-modules/tree/master). [CMake module](https://github.com/bilke/cmake-modules/tree/master).
To build the unittests, run them and then generare the coverage data in this format, To build the unittests, run them and then generate the coverage data in this format,
the following command can be used inside the build directory after the build system was set up the following command can be used inside the build directory after the build system was set up
```sh ```sh
@ -188,7 +188,10 @@ and open the documentation conveniently. Try `helper.py -h for more information.
The formatting is done by the `clang-format` tool. The configuration is contained within the The formatting is done by the `clang-format` tool. The configuration is contained within the
`.clang-format` file in the repository root. As long as `clang-format` is installed, you `.clang-format` file in the repository root. As long as `clang-format` is installed, you
can run the `apply-clang-format.sh` helper script to format all source files consistently. can run the `auto-format.sh` helper script to format all source files consistently. Furthermore cmake-format is required to format CMake files which can be installed with:
````sh
sudo pip install cmakelang
````
## Index ## Index

View File

@ -12,3 +12,9 @@ RUN git clone https://github.com/catchorg/Catch2.git && \
git checkout v3.0.0-preview5 && \ git checkout v3.0.0-preview5 && \
cmake -Bbuild -H. -DBUILD_TESTING=OFF && \ cmake -Bbuild -H. -DBUILD_TESTING=OFF && \
cmake --build build/ --target install cmake --build build/ --target install
RUN git clone https://github.com/ETLCPP/etl.git && \
cd etl && \
git checkout 20.28.0 && \
cmake -B build . && \
cmake --install build/

View File

@ -3,7 +3,7 @@ pipeline {
BUILDDIR = 'build-tests' BUILDDIR = 'build-tests'
} }
agent { agent {
docker { image 'fsfw-ci:d2'} docker { image 'fsfw-ci:d3'}
} }
stages { stages {
stage('Clean') { stage('Clean') {
@ -14,7 +14,7 @@ pipeline {
stage('Configure') { stage('Configure') {
steps { steps {
dir(BUILDDIR) { dir(BUILDDIR) {
sh 'cmake -DFSFW_OSAL=host -DFSFW_BUILD_UNITTESTS=ON -DFSFW_CICD_BUILD=ON ..' sh 'cmake -DFSFW_OSAL=host -DFSFW_BUILD_TESTS=ON -DFSFW_CICD_BUILD=ON ..'
} }
} }
} }

View File

@ -1,48 +0,0 @@
cmake_minimum_required(VERSION 3.13)
# Can also be changed by upper CMakeLists.txt file
find_library(LIB_FSFW_NAME fsfw REQUIRED)
option(FSFW_HAL_ADD_LINUX "Add the Linux HAL to the sources. Requires gpiod library" OFF)
# On by default for now because I did not have an issue including and compiling those files
# and libraries on a Desktop Linux system and the primary target of the FSFW is still embedded
# Linux. The only exception from this is the gpiod library which requires a dedicated installation,
# but CMake is able to determine whether this library is installed with find_library.
option(FSFW_HAL_LINUX_ADD_PERIPHERAL_DRIVERS "Add peripheral drivers for embedded Linux" ON)
option(FSFW_HAL_LINUX_ADD_LIBGPIOD "Target implements libgpiod" ON)
option(FSFW_HAL_ADD_RASPBERRY_PI "Add Raspberry Pi specific code to the sources" OFF)
option(FSFW_HAL_ADD_STM32H7 "Add the STM32H7 HAL to the sources" OFF)
option(FSFW_HAL_WARNING_SHADOW_LOCAL_GCC "Enable -Wshadow=local warning in GCC" ON)
set(LINUX_HAL_PATH_NAME linux)
set(STM32H7_PATH_NAME stm32h7)
add_subdirectory(src)
foreach(INCLUDE_PATH ${FSFW_HAL_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(CMAKE_VERBOSE)
message(STATUS "FSFW include path: ${CURR_ABS_INC_PATH}")
endif()
list(APPEND FSFW_HAL_ADD_INC_PATHS_ABS ${CURR_ABS_INC_PATH})
endforeach()
target_include_directories(${LIB_FSFW_NAME} PRIVATE
${FSFW_HAL_ADD_INC_PATHS_ABS}
)
target_compile_definitions(${LIB_FSFW_NAME} PRIVATE
${FSFW_HAL_DEFINES}
)
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
${FSFW_HAL_LINK_LIBS}
)

View File

@ -1,9 +0,0 @@
target_include_directories(${LIB_FSFW_NAME} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
)
target_include_directories(${LIB_FSFW_NAME} INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}
)
add_subdirectory(fsfw_hal)

View File

@ -1,3 +0,0 @@
target_sources(${LIB_FSFW_NAME} PRIVATE
GpioCookie.cpp
)

View File

@ -1,5 +0,0 @@
target_sources(${LIB_FSFW_NAME} PRIVATE
GyroL3GD20Handler.cpp
MgmRM3100Handler.cpp
MgmLIS3MDLHandler.cpp
)

View File

@ -1,25 +0,0 @@
if(FSFW_HAL_ADD_RASPBERRY_PI)
add_subdirectory(rpi)
endif()
target_sources(${LIB_FSFW_NAME} PRIVATE
UnixFileGuard.cpp
CommandExecutor.cpp
utility.cpp
)
if(FSFW_HAL_LINUX_ADD_PERIPHERAL_DRIVERS)
if(FSFW_HAL_LINUX_ADD_LIBGPIOD)
add_subdirectory(gpio)
endif()
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)

View File

@ -1,16 +0,0 @@
# This abstraction layer requires the gpiod library. You can install this library
# with "sudo apt-get install -y libgpiod-dev". If you are cross-compiling, you need
# to install the package before syncing the sysroot to your host computer.
find_library(LIB_GPIO gpiod)
if(${LIB_GPIO} MATCHES LIB_GPIO-NOTFOUND)
message(STATUS "gpiod library not found, not linking against it")
else()
target_sources(${LIB_FSFW_NAME} PRIVATE
LinuxLibgpioIF.cpp
)
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
${LIB_GPIO}
)
endif()

View File

@ -1,8 +0,0 @@
target_sources(${LIB_FSFW_NAME} PUBLIC
I2cComIF.cpp
I2cCookie.cpp
)

View File

@ -1,3 +0,0 @@
target_sources(${LIB_FSFW_NAME} PRIVATE
GpioRPi.cpp
)

View File

@ -1,8 +0,0 @@
target_sources(${LIB_FSFW_NAME} PUBLIC
SpiComIF.cpp
SpiCookie.cpp
)

View File

@ -1,4 +0,0 @@
target_sources(${LIB_FSFW_NAME} PUBLIC
UartComIF.cpp
UartCookie.cpp
)

View File

@ -1,3 +0,0 @@
target_sources(${LIB_FSFW_NAME} PUBLIC
UioMapper.cpp
)

View File

@ -1,3 +0,0 @@
target_sources(${LIB_FSFW_NAME} PRIVATE
GyroL3GD20H.cpp
)

View File

@ -1,3 +0,0 @@
target_sources(${LIB_FSFW_NAME} PRIVATE
gpio.cpp
)

View File

@ -1,2 +0,0 @@
target_sources(${LIB_FSFW_NAME} PRIVATE
)

View File

@ -1,9 +0,0 @@
target_sources(${LIB_FSFW_NAME} PRIVATE
spiCore.cpp
spiDefinitions.cpp
spiInterrupts.cpp
mspInit.cpp
SpiCookie.cpp
SpiComIF.cpp
stm32h743zi.cpp
)

View File

@ -1,2 +0,0 @@
target_sources(${LIB_FSFW_NAME} PRIVATE
)

View File

@ -16,8 +16,7 @@ cpp_format="clang-format"
file_selectors="-iname *.h -o -iname *.cpp -o -iname *.c -o -iname *.tpp" file_selectors="-iname *.h -o -iname *.cpp -o -iname *.c -o -iname *.tpp"
if command -v ${cpp_format} &> /dev/null; then if command -v ${cpp_format} &> /dev/null; then
find ./src ${file_selectors} | xargs ${cpp_format} --style=file -i find ./src ${file_selectors} | xargs ${cpp_format} --style=file -i
find ./hal ${file_selectors} | xargs ${cpp_format} --style=file -i find ./unittests ${file_selectors} | xargs ${cpp_format} --style=file -i
find ./tests ${file_selectors} | xargs ${cpp_format} --style=file -i
else else
echo "No ${cpp_format} tool found, not formatting C++/C files" echo "No ${cpp_format} tool found, not formatting C++/C files"
fi fi

View File

@ -48,6 +48,20 @@ def main():
action="store_true", action="store_true",
help="Run valgrind on generated test binary", help="Run valgrind on generated test binary",
) )
parser.add_argument(
"-g",
"--generators",
default = "Ninja",
action="store",
help="CMake generators",
)
parser.add_argument(
"-w",
"--windows",
default=False,
action="store_true",
help="Run on windows",
)
args = parser.parse_args() args = parser.parse_args()
if args.all: if args.all:
@ -115,14 +129,14 @@ def handle_tests_type(args, build_dir_list: list):
if args.create: if args.create:
if os.path.exists(UNITTEST_FOLDER_NAME): if os.path.exists(UNITTEST_FOLDER_NAME):
shutil.rmtree(UNITTEST_FOLDER_NAME) shutil.rmtree(UNITTEST_FOLDER_NAME)
create_tests_build_cfg() create_tests_build_cfg(args)
build_directory = UNITTEST_FOLDER_NAME build_directory = UNITTEST_FOLDER_NAME
elif len(build_dir_list) == 0: elif len(build_dir_list) == 0:
print( print(
"No valid CMake tests build directory found. " "No valid CMake tests build directory found. "
"Trying to set up test build system" "Trying to set up test build system"
) )
create_tests_build_cfg() create_tests_build_cfg(args)
build_directory = UNITTEST_FOLDER_NAME build_directory = UNITTEST_FOLDER_NAME
elif len(build_dir_list) == 1: elif len(build_dir_list) == 1:
build_directory = build_dir_list[0] build_directory = build_dir_list[0]
@ -147,10 +161,15 @@ def handle_tests_type(args, build_dir_list: list):
os.chdir("..") os.chdir("..")
def create_tests_build_cfg(): def create_tests_build_cfg(args):
os.mkdir(UNITTEST_FOLDER_NAME) os.mkdir(UNITTEST_FOLDER_NAME)
os.chdir(UNITTEST_FOLDER_NAME) os.chdir(UNITTEST_FOLDER_NAME)
cmd_runner("cmake -DFSFW_OSAL=host -DFSFW_BUILD_UNITTESTS=ON ..") if args.windows:
cmake_cmd = 'cmake -G "' + args.generators + '" -DFSFW_OSAL=host -DFSFW_BUILD_TESTS=ON \
-DGCOVR_PATH="py -m gcovr" ..'
else:
cmake_cmd = 'cmake -G "' + args.generators + '" -DFSFW_OSAL=host -DFSFW_BUILD_TESTS=ON ..'
cmd_runner(cmake_cmd)
os.chdir("..") os.chdir("..")

View File

@ -4,3 +4,8 @@ target_include_directories(${LIB_FSFW_NAME}
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
add_subdirectory(fsfw) add_subdirectory(fsfw)
if(FSFW_ADD_HAL)
add_subdirectory(fsfw_hal)
endif()
add_subdirectory(fsfw_tests)

View File

@ -13,12 +13,10 @@ AckInfo::AckInfo(cfdp::FileDirectives ackedDirective, cfdp::ConditionCode ackedC
} }
} }
AckInfo::AckInfo() = default;
cfdp::ConditionCode AckInfo::getAckedConditionCode() const { return ackedConditionCode; } cfdp::ConditionCode AckInfo::getAckedConditionCode() const { return ackedConditionCode; }
void AckInfo::setAckedConditionCode(cfdp::ConditionCode ackedConditionCode_) { void AckInfo::setAckedConditionCode(cfdp::ConditionCode ackedConditionCode) {
ackedConditionCode = ackedConditionCode_; this->ackedConditionCode = ackedConditionCode;
if (ackedDirective == cfdp::FileDirectives::FINISH) { if (ackedDirective == cfdp::FileDirectives::FINISH) {
this->directiveSubtypeCode = 0b0001; this->directiveSubtypeCode = 0b0001;
} else { } else {
@ -28,18 +26,20 @@ void AckInfo::setAckedConditionCode(cfdp::ConditionCode ackedConditionCode_) {
cfdp::FileDirectives AckInfo::getAckedDirective() const { return ackedDirective; } cfdp::FileDirectives AckInfo::getAckedDirective() const { return ackedDirective; }
void AckInfo::setAckedDirective(cfdp::FileDirectives ackedDirective_) { void AckInfo::setAckedDirective(cfdp::FileDirectives ackedDirective) {
ackedDirective = ackedDirective_; this->ackedDirective = ackedDirective;
} }
uint8_t AckInfo::getDirectiveSubtypeCode() const { return directiveSubtypeCode; } uint8_t AckInfo::getDirectiveSubtypeCode() const { return directiveSubtypeCode; }
void AckInfo::setDirectiveSubtypeCode(uint8_t directiveSubtypeCode_) { void AckInfo::setDirectiveSubtypeCode(uint8_t directiveSubtypeCode) {
directiveSubtypeCode = directiveSubtypeCode_; this->directiveSubtypeCode = directiveSubtypeCode;
} }
cfdp::AckTransactionStatus AckInfo::getTransactionStatus() const { return transactionStatus; } cfdp::AckTransactionStatus AckInfo::getTransactionStatus() const { return transactionStatus; }
void AckInfo::setTransactionStatus(cfdp::AckTransactionStatus transactionStatus_) { AckInfo::AckInfo() {}
transactionStatus = transactionStatus_;
void AckInfo::setTransactionStatus(cfdp::AckTransactionStatus transactionStatus) {
this->transactionStatus = transactionStatus;
} }

View File

@ -9,16 +9,16 @@ class AckInfo {
AckInfo(cfdp::FileDirectives ackedDirective, cfdp::ConditionCode ackedConditionCode, AckInfo(cfdp::FileDirectives ackedDirective, cfdp::ConditionCode ackedConditionCode,
cfdp::AckTransactionStatus transactionStatus, uint8_t directiveSubtypeCode = 0); cfdp::AckTransactionStatus transactionStatus, uint8_t directiveSubtypeCode = 0);
[[nodiscard]] cfdp::ConditionCode getAckedConditionCode() const; cfdp::ConditionCode getAckedConditionCode() const;
void setAckedConditionCode(cfdp::ConditionCode ackedConditionCode_); void setAckedConditionCode(cfdp::ConditionCode ackedConditionCode);
[[nodiscard]] cfdp::FileDirectives getAckedDirective() const; cfdp::FileDirectives getAckedDirective() const;
void setAckedDirective(cfdp::FileDirectives ackedDirective); void setAckedDirective(cfdp::FileDirectives ackedDirective);
[[nodiscard]] uint8_t getDirectiveSubtypeCode() const; uint8_t getDirectiveSubtypeCode() const;
void setDirectiveSubtypeCode(uint8_t directiveSubtypeCode); void setDirectiveSubtypeCode(uint8_t directiveSubtypeCode);
[[nodiscard]] cfdp::AckTransactionStatus getTransactionStatus() const; cfdp::AckTransactionStatus getTransactionStatus() const;
void setTransactionStatus(cfdp::AckTransactionStatus transactionStatus); void setTransactionStatus(cfdp::AckTransactionStatus transactionStatus);
private: private:

View File

@ -13,7 +13,7 @@ class AckPduDeserializer : public FileDirectiveDeserializer {
* @return * @return
* - cfdp::INVALID_DIRECTIVE_FIELDS: Invalid fields * - cfdp::INVALID_DIRECTIVE_FIELDS: Invalid fields
*/ */
ReturnValue_t parseData() override; ReturnValue_t parseData();
private: private:
bool checkAndSetCodes(uint8_t rawAckedByte, uint8_t rawAckedConditionCode); bool checkAndSetCodes(uint8_t rawAckedByte, uint8_t rawAckedConditionCode);

View File

@ -18,7 +18,7 @@ class AckPduSerializer : public FileDirectiveSerializer {
*/ */
AckPduSerializer(AckInfo& ackInfo, PduConfig& pduConf); AckPduSerializer(AckInfo& ackInfo, PduConfig& pduConf);
[[nodiscard]] size_t getSerializedSize() const override; size_t getSerializedSize() const override;
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const override; Endianness streamEndianness) const override;

View File

@ -2,6 +2,9 @@
#include <cstring> #include <cstring>
#include "fsfw/FSFW.h"
#include "fsfw/serviceinterface.h"
SimpleRingBuffer::SimpleRingBuffer(const size_t size, bool overwriteOld, size_t maxExcessBytes) SimpleRingBuffer::SimpleRingBuffer(const size_t size, bool overwriteOld, size_t maxExcessBytes)
: RingBufferBase<>(0, size, overwriteOld), maxExcessBytes(maxExcessBytes) { : RingBufferBase<>(0, size, overwriteOld), maxExcessBytes(maxExcessBytes) {
if (maxExcessBytes > size) { if (maxExcessBytes > size) {
@ -48,6 +51,19 @@ void SimpleRingBuffer::confirmBytesWritten(size_t amount) {
} }
ReturnValue_t SimpleRingBuffer::writeData(const uint8_t* data, size_t amount) { ReturnValue_t SimpleRingBuffer::writeData(const uint8_t* data, size_t amount) {
if (data == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
if (amount > getMaxSize()) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "SimpleRingBuffer::writeData: Amount of data too large" << std::endl;
#else
sif::printError("SimpleRingBuffer::writeData: Amount of data too large\n");
#endif
#endif
return HasReturnvaluesIF::RETURN_FAILED;
}
if (availableWriteSpace() >= amount or overwriteOld) { if (availableWriteSpace() >= amount or overwriteOld) {
size_t amountTillWrap = writeTillWrap(); size_t amountTillWrap = writeTillWrap();
if (amountTillWrap >= amount) { if (amountTillWrap >= amount) {

View File

@ -30,7 +30,7 @@ class DataSetIF {
* @brief This is an empty virtual destructor, * @brief This is an empty virtual destructor,
* as it is proposed for C++ interfaces. * as it is proposed for C++ interfaces.
*/ */
virtual ~DataSetIF() = default; virtual ~DataSetIF() {}
/** /**
* @brief This operation provides a method to register local data pool * @brief This operation provides a method to register local data pool
@ -39,7 +39,7 @@ class DataSetIF {
*/ */
virtual ReturnValue_t registerVariable(PoolVariableIF* variable) = 0; virtual ReturnValue_t registerVariable(PoolVariableIF* variable) = 0;
[[nodiscard]] virtual uint16_t getFillCount() const = 0; virtual uint16_t getFillCount() const = 0;
}; };
#endif /* FSFW_DATAPOOL_DATASETIF_H_ */ #endif /* FSFW_DATAPOOL_DATASETIF_H_ */

View File

@ -9,7 +9,7 @@ PoolDataSetBase::PoolDataSetBase(PoolVariableIF** registeredVariablesArray,
const size_t maxFillCount) const size_t maxFillCount)
: registeredVariables(registeredVariablesArray), maxFillCount(maxFillCount) {} : registeredVariables(registeredVariablesArray), maxFillCount(maxFillCount) {}
PoolDataSetBase::~PoolDataSetBase() = default; PoolDataSetBase::~PoolDataSetBase() {}
ReturnValue_t PoolDataSetBase::registerVariable(PoolVariableIF* variable) { ReturnValue_t PoolDataSetBase::registerVariable(PoolVariableIF* variable) {
if (registeredVariables == nullptr) { if (registeredVariables == nullptr) {

View File

@ -64,8 +64,8 @@ class PoolDataSetBase : public PoolDataSetIF, public SerializeIF, public HasRetu
* - @c SET_WAS_ALREADY_READ if read() is called twice without calling * - @c SET_WAS_ALREADY_READ if read() is called twice without calling
* commit() in between * commit() in between
*/ */
ReturnValue_t read(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING, virtual ReturnValue_t read(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
uint32_t lockTimeout = 20) override; uint32_t lockTimeout = 20) override;
/** /**
* @brief The commit call initializes writing back the registered variables. * @brief The commit call initializes writing back the registered variables.
* @details * @details
@ -84,38 +84,39 @@ class PoolDataSetBase : public PoolDataSetIF, public SerializeIF, public HasRetu
* - @c COMMITING_WITHOUT_READING if set was not read yet and * - @c COMMITING_WITHOUT_READING if set was not read yet and
* contains non write-only variables * contains non write-only variables
*/ */
ReturnValue_t commit(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING, virtual ReturnValue_t commit(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
uint32_t lockTimeout = 20) override; uint32_t lockTimeout = 20) override;
/** /**
* Register the passed pool variable instance into the data set. * Register the passed pool variable instance into the data set.
* @param variable * @param variable
* @return * @return
*/ */
ReturnValue_t registerVariable(PoolVariableIF* variable) override; virtual ReturnValue_t registerVariable(PoolVariableIF* variable) override;
/** /**
* Provides the means to lock the underlying data structure to ensure * Provides the means to lock the underlying data structure to ensure
* thread-safety. Default implementation is empty * thread-safety. Default implementation is empty
* @return Always returns -@c RETURN_OK * @return Always returns -@c RETURN_OK
*/ */
ReturnValue_t lockDataPool(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING, virtual ReturnValue_t lockDataPool(
uint32_t timeoutMs = 20) override; MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
uint32_t timeoutMs = 20) override;
/** /**
* Provides the means to unlock the underlying data structure to ensure * Provides the means to unlock the underlying data structure to ensure
* thread-safety. Default implementation is empty * thread-safety. Default implementation is empty
* @return Always returns -@c RETURN_OK * @return Always returns -@c RETURN_OK
*/ */
ReturnValue_t unlockDataPool() override; virtual ReturnValue_t unlockDataPool() override;
[[nodiscard]] uint16_t getFillCount() const override; virtual uint16_t getFillCount() const override;
/* SerializeIF implementations */ /* SerializeIF implementations */
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, const size_t maxSize,
SerializeIF::Endianness streamEndianness) const override; SerializeIF::Endianness streamEndianness) const override;
[[nodiscard]] size_t getSerializedSize() const override; virtual size_t getSerializedSize() const override;
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
SerializeIF::Endianness streamEndianness) override; SerializeIF::Endianness streamEndianness) override;
/** /**
* Can be used to individually protect every read and commit call. * Can be used to individually protect every read and commit call.
@ -155,7 +156,7 @@ class PoolDataSetBase : public PoolDataSetIF, public SerializeIF, public HasRetu
const size_t maxFillCount = 0; const size_t maxFillCount = 0;
void setContainer(PoolVariableIF** variablesContainer); void setContainer(PoolVariableIF** variablesContainer);
[[nodiscard]] PoolVariableIF** getContainer() const; PoolVariableIF** getContainer() const;
private: private:
bool protectEveryReadCommitCall = false; bool protectEveryReadCommitCall = false;

View File

@ -7,24 +7,26 @@
#include "fsfw/serviceinterface/ServiceInterface.h" #include "fsfw/serviceinterface/ServiceInterface.h"
template <typename T> template <typename T>
PoolEntry<T>::PoolEntry(std::initializer_list<T> initValue, bool setValid) PoolEntry<T>::PoolEntry(uint8_t len, bool setValid) : length(len), valid(setValid) {
: length(static_cast<uint8_t>(initValue.size())), valid(setValid) { this->address = new T[this->length]();
this->address = new T[this->length]; std::memset(this->address, 0, this->getByteSize());
if (initValue.size() == 0) { }
std::memset(this->address, 0, PoolEntry<T>::getByteSize());
} else { template <typename T>
std::copy(initValue.begin(), initValue.end(), this->address); PoolEntry<T>::PoolEntry(std::initializer_list<T> initValues, bool setValid)
: length(static_cast<uint8_t>(initValues.size())), valid(setValid) {
this->address = new T[this->length]();
if (initValues.size() > 0) {
std::copy(initValues.begin(), initValues.end(), this->address);
} }
} }
template <typename T> template <typename T>
PoolEntry<T>::PoolEntry(T* initValue, uint8_t setLength, bool setValid) PoolEntry<T>::PoolEntry(const T* initValue, uint8_t setLength, bool setValid)
: length(setLength), valid(setValid) { : length(setLength), valid(setValid) {
this->address = new T[this->length]; this->address = new T[this->length]();
if (initValue != nullptr) { if (initValue != nullptr) {
std::memcpy(this->address, initValue, PoolEntry<T>::getByteSize()); std::memcpy(this->address, initValue, this->getByteSize());
} else {
std::memset(this->address, 0, PoolEntry<T>::getByteSize());
} }
} }
@ -62,7 +64,7 @@ bool PoolEntry<T>::getValid() {
template <typename T> template <typename T>
void PoolEntry<T>::print() { void PoolEntry<T>::print() {
const char* validString; const char* validString = nullptr;
if (valid) { if (valid) {
validString = "Valid"; validString = "Valid";
} else { } else {

View File

@ -33,6 +33,9 @@ class PoolEntry : public PoolEntryIF {
"instead! The ECSS standard defines a boolean as a one bit " "instead! The ECSS standard defines a boolean as a one bit "
"field. Therefore it is preferred to store a boolean as an " "field. Therefore it is preferred to store a boolean as an "
"uint8_t"); "uint8_t");
PoolEntry(uint8_t len = 1, bool setValid = false);
/** /**
* @brief In the classe's constructor, space is allocated on the heap and * @brief In the classe's constructor, space is allocated on the heap and
* potential initialization values are copied to that space. * potential initialization values are copied to that space.
@ -49,7 +52,7 @@ class PoolEntry : public PoolEntryIF {
* @param setValid * @param setValid
* Sets the initialization flag. It is invalid by default. * Sets the initialization flag. It is invalid by default.
*/ */
PoolEntry(std::initializer_list<T> initValue = {0}, bool setValid = false); PoolEntry(std::initializer_list<T> initValue, bool setValid = false);
/** /**
* @brief In the classe's constructor, space is allocated on the heap and * @brief In the classe's constructor, space is allocated on the heap and
@ -62,7 +65,7 @@ class PoolEntry : public PoolEntryIF {
* @param setValid * @param setValid
* Sets the initialization flag. It is invalid by default. * Sets the initialization flag. It is invalid by default.
*/ */
explicit PoolEntry(T* initValue, uint8_t setLength = 1, bool setValid = false); PoolEntry(const T* initValue, uint8_t setLength = 1, bool setValid = false);
//! Explicitely deleted copy ctor, copying is not allowed. //! Explicitely deleted copy ctor, copying is not allowed.
PoolEntry(const PoolEntry&) = delete; PoolEntry(const PoolEntry&) = delete;
@ -77,7 +80,7 @@ class PoolEntry : public PoolEntryIF {
* PoolEntries shall never be copied, as a copy might delete the variable * PoolEntries shall never be copied, as a copy might delete the variable
* on the heap. * on the heap.
*/ */
~PoolEntry() override; ~PoolEntry();
/** /**
* Return typed pointer to start of data. * Return typed pointer to start of data.
@ -91,32 +94,32 @@ class PoolEntry : public PoolEntryIF {
* For non-array pool entries return type size, for vector entries * For non-array pool entries return type size, for vector entries
* return type size times the number of entries. * return type size times the number of entries.
*/ */
uint8_t getSize() override; uint8_t getSize();
/** /**
* @brief This operation returns the size in bytes. * @brief This operation returns the size in bytes.
* @details The size is calculated by sizeof(type) * array_size. * @details The size is calculated by sizeof(type) * array_size.
*/ */
uint16_t getByteSize() override; uint16_t getByteSize();
/** /**
* @brief This operation returns a the address pointer casted to void*. * @brief This operation returns a the address pointer casted to void*.
*/ */
void* getRawData() override; void* getRawData();
/** /**
* @brief This method allows to set the valid information * @brief This method allows to set the valid information
* of the pool entry. * of the pool entry.
*/ */
void setValid(bool isValid) override; void setValid(bool isValid);
/** /**
* @brief This method allows to get the valid information * @brief This method allows to get the valid information
* of the pool entry. * of the pool entry.
*/ */
bool getValid() override; bool getValid();
/** /**
* @brief This is a debug method that prints all values and the valid * @brief This is a debug method that prints all values and the valid
* information to the screen. It prints all array entries in a row. * information to the screen. It prints all array entries in a row.
*/ */
void print() override; void print();
Type getType() override; Type getType();
private: private:
/** /**

View File

@ -24,7 +24,7 @@ class PoolEntryIF {
* @brief This is an empty virtual destructor, * @brief This is an empty virtual destructor,
* as it is required for C++ interfaces. * as it is required for C++ interfaces.
*/ */
virtual ~PoolEntryIF() = default; virtual ~PoolEntryIF() {}
/** /**
* @brief getSize returns the array size of the entry. * @brief getSize returns the array size of the entry.
* A single variable parameter has size 1. * A single variable parameter has size 1.

View File

@ -11,9 +11,9 @@
*/ */
class PoolReadGuard { class PoolReadGuard {
public: public:
explicit PoolReadGuard(ReadCommitIF* readObject, PoolReadGuard(ReadCommitIF* readObject,
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING, MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
uint32_t mutexTimeout = 20) uint32_t mutexTimeout = 20)
: readObject(readObject), mutexTimeout(mutexTimeout) { : readObject(readObject), mutexTimeout(mutexTimeout) {
if (readObject != nullptr) { if (readObject != nullptr) {
readResult = readObject->read(timeoutType, mutexTimeout); readResult = readObject->read(timeoutType, mutexTimeout);
@ -29,7 +29,7 @@ class PoolReadGuard {
} }
} }
[[nodiscard]] ReturnValue_t getReadResult() const { return readResult; } ReturnValue_t getReadResult() const { return readResult; }
/** /**
* @brief Can be used to suppress commit on destruction. * @brief Can be used to suppress commit on destruction.

View File

@ -0,0 +1,28 @@
#ifndef FSFW_DATAPOOL_POOLVARLIST_H_
#define FSFW_DATAPOOL_POOLVARLIST_H_
#include "../datapool/PoolVariableIF.h"
#include "../datapoolglob/GlobalPoolVariable.h"
template <class T, uint8_t n_var>
class PoolVarList {
private:
GlobPoolVar<T> variables[n_var];
public:
PoolVarList(const uint32_t set_id[n_var], DataSetIF* dataSet,
PoolVariableIF::ReadWriteMode_t setReadWriteMode) {
// I really should have a look at the new init list c++ syntax.
if (dataSet == NULL) {
return;
}
for (uint8_t count = 0; count < n_var; count++) {
variables[count].dataPoolId = set_id[count];
variables[count].readWriteMode = setReadWriteMode;
dataSet->registerVariable(&variables[count]);
}
}
GlobPoolVar<T>& operator[](int i) { return variables[i]; }
};
#endif /* FSFW_DATAPOOL_POOLVARLIST_H_ */

View File

@ -24,8 +24,8 @@ class PoolVariableIF : public SerializeIF, public ReadCommitIF {
static constexpr ReturnValue_t INVALID_READ_WRITE_MODE = MAKE_RETURN_CODE(0xA0); static constexpr ReturnValue_t INVALID_READ_WRITE_MODE = MAKE_RETURN_CODE(0xA0);
static constexpr ReturnValue_t INVALID_POOL_ENTRY = MAKE_RETURN_CODE(0xA1); static constexpr ReturnValue_t INVALID_POOL_ENTRY = MAKE_RETURN_CODE(0xA1);
static constexpr bool VALID = true; static constexpr bool VALID = 1;
static constexpr bool INVALID = false; static constexpr bool INVALID = 0;
static constexpr uint32_t NO_PARAMETER = 0xffffffff; static constexpr uint32_t NO_PARAMETER = 0xffffffff;
enum ReadWriteMode_t { VAR_READ, VAR_WRITE, VAR_READ_WRITE }; enum ReadWriteMode_t { VAR_READ, VAR_WRITE, VAR_READ_WRITE };
@ -34,23 +34,23 @@ class PoolVariableIF : public SerializeIF, public ReadCommitIF {
* @brief This is an empty virtual destructor, * @brief This is an empty virtual destructor,
* as it is proposed for C++ interfaces. * as it is proposed for C++ interfaces.
*/ */
~PoolVariableIF() override = default; virtual ~PoolVariableIF() {}
/** /**
* @brief This method returns if the variable is write-only, * @brief This method returns if the variable is write-only,
* read-write or read-only. * read-write or read-only.
*/ */
[[nodiscard]] virtual ReadWriteMode_t getReadWriteMode() const = 0; virtual ReadWriteMode_t getReadWriteMode() const = 0;
virtual void setReadWriteMode(ReadWriteMode_t newMode) = 0; virtual void setReadWriteMode(ReadWriteMode_t newMode) = 0;
/** /**
* @brief This operation shall return the data pool id of the variable. * @brief This operation shall return the data pool id of the variable.
*/ */
[[nodiscard]] virtual uint32_t getDataPoolId() const = 0; virtual uint32_t getDataPoolId() const = 0;
/** /**
* @brief With this call, the valid information of the * @brief With this call, the valid information of the
* variable is returned. * variable is returned.
*/ */
[[nodiscard]] virtual bool isValid() const = 0; virtual bool isValid() const = 0;
/** /**
* @brief With this call, the valid information of the variable is set. * @brief With this call, the valid information of the variable is set.
*/ */

View File

@ -12,7 +12,7 @@ class ReadCommitIF {
friend class ReadCommitIFAttorney; friend class ReadCommitIFAttorney;
public: public:
virtual ~ReadCommitIF() = default; virtual ~ReadCommitIF() {}
virtual ReturnValue_t read(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) = 0; virtual ReturnValue_t read(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) = 0;
virtual ReturnValue_t commit(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) = 0; virtual ReturnValue_t commit(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) = 0;

View File

@ -5,7 +5,7 @@
class SharedDataSetIF { class SharedDataSetIF {
public: public:
virtual ~SharedDataSetIF() = default; virtual ~SharedDataSetIF(){};
private: private:
virtual ReturnValue_t lockDataset(MutexIF::TimeoutType timeoutType, virtual ReturnValue_t lockDataset(MutexIF::TimeoutType timeoutType,

View File

@ -9,8 +9,7 @@ class MutexIF;
*/ */
class AccessPoolManagerIF { class AccessPoolManagerIF {
public: public:
virtual ~AccessPoolManagerIF() = default; virtual ~AccessPoolManagerIF(){};
;
virtual MutexIF* getLocalPoolMutex() = 0; virtual MutexIF* getLocalPoolMutex() = 0;

View File

@ -44,15 +44,14 @@ class HasLocalDataPoolIF {
friend class HasLocalDpIFUserAttorney; friend class HasLocalDpIFUserAttorney;
public: public:
virtual ~HasLocalDataPoolIF() = default; virtual ~HasLocalDataPoolIF(){};
;
static constexpr uint32_t INVALID_LPID = localpool::INVALID_LPID; static constexpr uint32_t INVALID_LPID = localpool::INVALID_LPID;
[[nodiscard]] virtual object_id_t getObjectId() const = 0; virtual object_id_t getObjectId() const = 0;
/** Command queue for housekeeping messages. */ /** Command queue for housekeeping messages. */
[[nodiscard]] virtual MessageQueueId_t getCommandQueue() const = 0; virtual MessageQueueId_t getCommandQueue() const = 0;
/** /**
* Is used by pool owner to initialize the pool map once * Is used by pool owner to initialize the pool map once
@ -67,7 +66,7 @@ class HasLocalDataPoolIF {
* usually be the period the pool owner performs its periodic operation. * usually be the period the pool owner performs its periodic operation.
* @return * @return
*/ */
[[nodiscard]] virtual dur_millis_t getPeriodicOperationFrequency() const = 0; virtual dur_millis_t getPeriodicOperationFrequency() const = 0;
/** /**
* @brief This function will be called by the manager if an update * @brief This function will be called by the manager if an update

View File

@ -1,5 +1,6 @@
#include "fsfw/datapoollocal/LocalDataPoolManager.h" #include "fsfw/datapoollocal/LocalDataPoolManager.h"
#include <array>
#include <cmath> #include <cmath>
#include "fsfw/datapoollocal.h" #include "fsfw/datapoollocal.h"
@ -56,7 +57,7 @@ ReturnValue_t LocalDataPoolManager::initialize(MessageQueueIF* queueToUse) {
} }
if (defaultHkDestination != objects::NO_OBJECT) { if (defaultHkDestination != objects::NO_OBJECT) {
auto* hkPacketReceiver = AcceptsHkPacketsIF* hkPacketReceiver =
ObjectManager::instance()->get<AcceptsHkPacketsIF>(defaultHkDestination); ObjectManager::instance()->get<AcceptsHkPacketsIF>(defaultHkDestination);
if (hkPacketReceiver != nullptr) { if (hkPacketReceiver != nullptr) {
hkDestinationId = hkPacketReceiver->getHkQueue(); hkDestinationId = hkPacketReceiver->getHkQueue();
@ -208,9 +209,9 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(HkReceiver& recei
} }
/* Prepare and send update snapshot */ /* Prepare and send update snapshot */
timeval now{}; timeval now;
Clock::getClock_timeval(&now); Clock::getClock_timeval(&now);
CCSDSTime::CDS_short cds{}; CCSDSTime::CDS_short cds;
CCSDSTime::convertToCcsds(&cds, &now); CCSDSTime::convertToCcsds(&cds, &now);
HousekeepingSnapshot updatePacket( HousekeepingSnapshot updatePacket(
reinterpret_cast<uint8_t*>(&cds), sizeof(cds), reinterpret_cast<uint8_t*>(&cds), sizeof(cds),
@ -244,9 +245,9 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(HkReceiver& recei
} }
/* Prepare and send update snapshot */ /* Prepare and send update snapshot */
timeval now{}; timeval now;
Clock::getClock_timeval(&now); Clock::getClock_timeval(&now);
CCSDSTime::CDS_short cds{}; CCSDSTime::CDS_short cds;
CCSDSTime::convertToCcsds(&cds, &now); CCSDSTime::convertToCcsds(&cds, &now);
HousekeepingSnapshot updatePacket( HousekeepingSnapshot updatePacket(
reinterpret_cast<uint8_t*>(&cds), sizeof(cds), reinterpret_cast<uint8_t*>(&cds), sizeof(cds),
@ -338,7 +339,8 @@ ReturnValue_t LocalDataPoolManager::subscribeForPeriodicPacket(sid_t sid, bool e
float collectionInterval, float collectionInterval,
bool isDiagnostics, bool isDiagnostics,
object_id_t packetDestination) { object_id_t packetDestination) {
auto* hkReceiverObject = ObjectManager::instance()->get<AcceptsHkPacketsIF>(packetDestination); AcceptsHkPacketsIF* hkReceiverObject =
ObjectManager::instance()->get<AcceptsHkPacketsIF>(packetDestination);
if (hkReceiverObject == nullptr) { if (hkReceiverObject == nullptr) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "subscribeForPeriodicPacket", printWarningOrError(sif::OutputTypes::OUT_WARNING, "subscribeForPeriodicPacket",
QUEUE_OR_DESTINATION_INVALID); QUEUE_OR_DESTINATION_INVALID);
@ -366,7 +368,8 @@ ReturnValue_t LocalDataPoolManager::subscribeForPeriodicPacket(sid_t sid, bool e
ReturnValue_t LocalDataPoolManager::subscribeForUpdatePacket(sid_t sid, bool isDiagnostics, ReturnValue_t LocalDataPoolManager::subscribeForUpdatePacket(sid_t sid, bool isDiagnostics,
bool reportingEnabled, bool reportingEnabled,
object_id_t packetDestination) { object_id_t packetDestination) {
auto* hkReceiverObject = ObjectManager::instance()->get<AcceptsHkPacketsIF>(packetDestination); AcceptsHkPacketsIF* hkReceiverObject =
ObjectManager::instance()->get<AcceptsHkPacketsIF>(packetDestination);
if (hkReceiverObject == nullptr) { if (hkReceiverObject == nullptr) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "subscribeForPeriodicPacket", printWarningOrError(sif::OutputTypes::OUT_WARNING, "subscribeForPeriodicPacket",
QUEUE_OR_DESTINATION_INVALID); QUEUE_OR_DESTINATION_INVALID);

View File

@ -80,7 +80,7 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
*/ */
LocalDataPoolManager(HasLocalDataPoolIF* owner, MessageQueueIF* queueToUse, LocalDataPoolManager(HasLocalDataPoolIF* owner, MessageQueueIF* queueToUse,
bool appendValidityBuffer = true); bool appendValidityBuffer = true);
~LocalDataPoolManager() override; virtual ~LocalDataPoolManager();
/** /**
* Assigns the queue to use. Make sure to call this in the #initialize * Assigns the queue to use. Make sure to call this in the #initialize
@ -151,7 +151,7 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
* Otherwise, only an notification message is sent. * Otherwise, only an notification message is sent.
* @return * @return
*/ */
ReturnValue_t subscribeForSetUpdateMessage(uint32_t setId, object_id_t destinationObject, ReturnValue_t subscribeForSetUpdateMessage(const uint32_t setId, object_id_t destinationObject,
MessageQueueId_t targetQueueId, MessageQueueId_t targetQueueId,
bool generateSnapshot) override; bool generateSnapshot) override;
@ -169,7 +169,7 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
* Otherwise, only an notification message is sent. * Otherwise, only an notification message is sent.
* @return * @return
*/ */
ReturnValue_t subscribeForVariableUpdateMessage(lp_id_t localPoolId, ReturnValue_t subscribeForVariableUpdateMessage(const lp_id_t localPoolId,
object_id_t destinationObject, object_id_t destinationObject,
MessageQueueId_t targetQueueId, MessageQueueId_t targetQueueId,
bool generateSnapshot) override; bool generateSnapshot) override;
@ -252,7 +252,7 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
*/ */
void clearReceiversList(); void clearReceiversList();
[[nodiscard]] object_id_t getCreatorObjectId() const; object_id_t getCreatorObjectId() const;
/** /**
* Get the pointer to the mutex. Can be used to lock the data pool * Get the pointer to the mutex. Can be used to lock the data pool
@ -262,7 +262,7 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
*/ */
MutexIF* getMutexHandle(); MutexIF* getMutexHandle();
LocalDataPoolManager* getPoolManagerHandle() override; virtual LocalDataPoolManager* getPoolManagerHandle() override;
protected: protected:
/** Core data structure for the actual pool data */ /** Core data structure for the actual pool data */
@ -306,8 +306,8 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
struct HkUpdateResetHelper { struct HkUpdateResetHelper {
DataType dataType = DataType::DATA_SET; DataType dataType = DataType::DATA_SET;
DataId dataId; DataId dataId;
uint8_t updateCounter{}; uint8_t updateCounter;
uint8_t currentUpdateCounter{}; uint8_t currentUpdateCounter;
}; };
using HkUpdateResetList = std::vector<struct HkUpdateResetHelper>; using HkUpdateResetList = std::vector<struct HkUpdateResetHelper>;

View File

@ -65,7 +65,9 @@ void DeviceHandlerBase::setThermalStateRequestPoolIds(lp_id_t thermalStatePoolId
} }
DeviceHandlerBase::~DeviceHandlerBase() { DeviceHandlerBase::~DeviceHandlerBase() {
delete comCookie; if (comCookie != nullptr) {
delete comCookie;
}
if (defaultFDIRUsed) { if (defaultFDIRUsed) {
delete fdirInstance; delete fdirInstance;
} }
@ -233,17 +235,26 @@ ReturnValue_t DeviceHandlerBase::initialize() {
} }
void DeviceHandlerBase::decrementDeviceReplyMap() { void DeviceHandlerBase::decrementDeviceReplyMap() {
bool timedOut = false;
for (std::pair<const DeviceCommandId_t, DeviceReplyInfo>& replyPair : deviceReplyMap) { for (std::pair<const DeviceCommandId_t, DeviceReplyInfo>& replyPair : deviceReplyMap) {
if (replyPair.second.delayCycles != 0) { if (replyPair.second.countdown != nullptr && replyPair.second.active) {
if (replyPair.second.countdown->hasTimedOut()) {
resetTimeoutControlledReply(&replyPair.second);
timedOut = true;
}
}
if (replyPair.second.delayCycles != 0 && replyPair.second.countdown == nullptr) {
replyPair.second.delayCycles--; replyPair.second.delayCycles--;
if (replyPair.second.delayCycles == 0) { if (replyPair.second.delayCycles == 0) {
if (replyPair.second.periodic) { resetDelayCyclesControlledReply(&replyPair.second);
replyPair.second.delayCycles = replyPair.second.maxDelayCycles; timedOut = true;
}
replyToReply(replyPair.first, replyPair.second, TIMEOUT);
missedReply(replyPair.first);
} }
} }
if (timedOut) {
replyToReply(replyPair.first, replyPair.second, TIMEOUT);
missedReply(replyPair.first);
timedOut = false;
}
} }
} }
@ -359,7 +370,6 @@ void DeviceHandlerBase::doStateMachine() {
setMode(MODE_OFF); setMode(MODE_OFF);
break; break;
} }
if (currentUptime - timeoutStart >= powerSwitcher->getSwitchDelayMs()) { if (currentUptime - timeoutStart >= powerSwitcher->getSwitchDelayMs()) {
triggerEvent(MODE_TRANSITION_FAILED, PowerSwitchIF::SWITCH_TIMEOUT, 0); triggerEvent(MODE_TRANSITION_FAILED, PowerSwitchIF::SWITCH_TIMEOUT, 0);
setMode(MODE_ERROR_ON); setMode(MODE_ERROR_ON);
@ -408,20 +418,22 @@ ReturnValue_t DeviceHandlerBase::isModeCombinationValid(Mode_t mode, Submode_t s
ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap( ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap(
DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles, LocalPoolDataSetBase* replyDataSet, DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles, LocalPoolDataSetBase* replyDataSet,
size_t replyLen, bool periodic, bool hasDifferentReplyId, DeviceCommandId_t replyId) { size_t replyLen, bool periodic, bool hasDifferentReplyId, DeviceCommandId_t replyId,
Countdown* countdown) {
// No need to check, as we may try to insert multiple times. // No need to check, as we may try to insert multiple times.
insertInCommandMap(deviceCommand, hasDifferentReplyId, replyId); insertInCommandMap(deviceCommand, hasDifferentReplyId, replyId);
if (hasDifferentReplyId) { if (hasDifferentReplyId) {
return insertInReplyMap(replyId, maxDelayCycles, replyDataSet, replyLen, periodic); return insertInReplyMap(replyId, maxDelayCycles, replyDataSet, replyLen, periodic, countdown);
} else { } else {
return insertInReplyMap(deviceCommand, maxDelayCycles, replyDataSet, replyLen, periodic); return insertInReplyMap(deviceCommand, maxDelayCycles, replyDataSet, replyLen, periodic,
countdown);
} }
} }
ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId, ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId,
uint16_t maxDelayCycles, uint16_t maxDelayCycles,
LocalPoolDataSetBase* dataSet, size_t replyLen, LocalPoolDataSetBase* dataSet, size_t replyLen,
bool periodic) { bool periodic, Countdown* countdown) {
DeviceReplyInfo info; DeviceReplyInfo info;
info.maxDelayCycles = maxDelayCycles; info.maxDelayCycles = maxDelayCycles;
info.periodic = periodic; info.periodic = periodic;
@ -429,6 +441,7 @@ ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId,
info.replyLen = replyLen; info.replyLen = replyLen;
info.dataSet = dataSet; info.dataSet = dataSet;
info.command = deviceCommandMap.end(); info.command = deviceCommandMap.end();
info.countdown = countdown;
auto resultPair = deviceReplyMap.emplace(replyId, info); auto resultPair = deviceReplyMap.emplace(replyId, info);
if (resultPair.second) { if (resultPair.second) {
return RETURN_OK; return RETURN_OK;
@ -464,7 +477,8 @@ size_t DeviceHandlerBase::getNextReplyLength(DeviceCommandId_t commandId) {
} }
DeviceReplyIter iter = deviceReplyMap.find(replyId); DeviceReplyIter iter = deviceReplyMap.find(replyId);
if (iter != deviceReplyMap.end()) { if (iter != deviceReplyMap.end()) {
if (iter->second.delayCycles != 0) { if ((iter->second.delayCycles != 0 && iter->second.countdown == nullptr) ||
(iter->second.active && iter->second.countdown != nullptr)) {
return iter->second.replyLen; return iter->second.replyLen;
} }
} }
@ -500,9 +514,19 @@ ReturnValue_t DeviceHandlerBase::updatePeriodicReply(bool enable, DeviceCommandI
return COMMAND_NOT_SUPPORTED; return COMMAND_NOT_SUPPORTED;
} }
if (enable) { if (enable) {
info->delayCycles = info->maxDelayCycles; info->active = true;
if (info->countdown != nullptr) {
info->delayCycles = info->maxDelayCycles;
} else {
info->countdown->resetTimer();
}
} else { } else {
info->delayCycles = 0; info->active = false;
if (info->countdown != nullptr) {
info->delayCycles = 0;
} else {
info->countdown->timeOut();
}
} }
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
@ -808,17 +832,18 @@ void DeviceHandlerBase::handleReply(const uint8_t* receivedData, DeviceCommandId
DeviceReplyInfo* info = &(iter->second); DeviceReplyInfo* info = &(iter->second);
if (info->delayCycles != 0) { if ((info->delayCycles != 0 && info->countdown == nullptr) ||
(info->active && info->countdown != nullptr)) {
result = interpretDeviceReply(foundId, receivedData); result = interpretDeviceReply(foundId, receivedData);
if (result == IGNORE_REPLY_DATA) { if (result == IGNORE_REPLY_DATA) {
return; return;
} }
if (info->periodic) { if (info->active && info->countdown != nullptr) {
info->delayCycles = info->maxDelayCycles; resetTimeoutControlledReply(info);
} else { } else if (info->delayCycles != 0) {
info->delayCycles = 0; resetDelayCyclesControlledReply(info);
} }
if (result != RETURN_OK) { if (result != RETURN_OK) {
@ -837,6 +862,24 @@ void DeviceHandlerBase::handleReply(const uint8_t* receivedData, DeviceCommandId
} }
} }
void DeviceHandlerBase::resetTimeoutControlledReply(DeviceReplyInfo* info) {
if (info->periodic) {
info->countdown->resetTimer();
} else {
info->active = false;
info->countdown->timeOut();
}
}
void DeviceHandlerBase::resetDelayCyclesControlledReply(DeviceReplyInfo* info) {
if (info->periodic) {
info->delayCycles = info->maxDelayCycles;
} else {
info->delayCycles = 0;
info->active = false;
}
}
ReturnValue_t DeviceHandlerBase::getStorageData(store_address_t storageAddress, uint8_t** data, ReturnValue_t DeviceHandlerBase::getStorageData(store_address_t storageAddress, uint8_t** data,
size_t* len) { size_t* len) {
size_t lenTmp; size_t lenTmp;
@ -959,9 +1002,15 @@ ReturnValue_t DeviceHandlerBase::enableReplyInReplyMap(DeviceCommandMap::iterato
} }
if (iter != deviceReplyMap.end()) { if (iter != deviceReplyMap.end()) {
DeviceReplyInfo* info = &(iter->second); DeviceReplyInfo* info = &(iter->second);
// If a countdown has been set, the delay cycles will be ignored and the reply times out
// as soon as the countdown has expired
info->delayCycles = info->maxDelayCycles; info->delayCycles = info->maxDelayCycles;
info->command = command; info->command = command;
command->second.expectedReplies = expectedReplies; command->second.expectedReplies = expectedReplies;
if (info->countdown != nullptr) {
info->countdown->resetTimer();
}
info->active = true;
return RETURN_OK; return RETURN_OK;
} else { } else {
return NO_REPLY_EXPECTED; return NO_REPLY_EXPECTED;
@ -1196,7 +1245,8 @@ void DeviceHandlerBase::setParentQueue(MessageQueueId_t parentQueueId) {
bool DeviceHandlerBase::isAwaitingReply() { bool DeviceHandlerBase::isAwaitingReply() {
std::map<DeviceCommandId_t, DeviceReplyInfo>::iterator iter; std::map<DeviceCommandId_t, DeviceReplyInfo>::iterator iter;
for (iter = deviceReplyMap.begin(); iter != deviceReplyMap.end(); ++iter) { for (iter = deviceReplyMap.begin(); iter != deviceReplyMap.end(); ++iter) {
if (iter->second.delayCycles != 0) { if ((iter->second.delayCycles != 0 && iter->second.countdown == nullptr) ||
(iter->second.active && iter->second.countdown != nullptr)) {
return true; return true;
} }
} }
@ -1351,6 +1401,13 @@ uint8_t DeviceHandlerBase::getReplyDelayCycles(DeviceCommandId_t deviceCommand)
DeviceReplyMap::iterator iter = deviceReplyMap.find(deviceCommand); DeviceReplyMap::iterator iter = deviceReplyMap.find(deviceCommand);
if (iter == deviceReplyMap.end()) { if (iter == deviceReplyMap.end()) {
return 0; return 0;
} else if (iter->second.countdown != nullptr) {
// fake a useful return value for legacy code
if (iter->second.active) {
return 1;
} else {
return 0;
}
} }
return iter->second.delayCycles; return iter->second.delayCycles;
} }

View File

@ -207,11 +207,13 @@ class DeviceHandlerBase : public DeviceHandlerIF,
Mode_t getTransitionSourceMode() const; Mode_t getTransitionSourceMode() const;
Submode_t getTransitionSourceSubMode() const; Submode_t getTransitionSourceSubMode() const;
void getMode(Mode_t *mode, Submode_t *submode) override; virtual void getMode(Mode_t *mode, Submode_t *submode);
HealthState getHealth() override; HealthState getHealth();
ReturnValue_t setHealth(HealthState health) override; ReturnValue_t setHealth(HealthState health);
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId, ParameterWrapper *parameterWrapper, virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
const ParameterWrapper *newValues, uint16_t startAtIndex) override; ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues,
uint16_t startAtIndex) override;
protected: protected:
/** /**
@ -446,6 +448,9 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* by the device repeatedly without request) or not. Default is aperiodic (0). * by the device repeatedly without request) or not. Default is aperiodic (0).
* Please note that periodic replies are disabled by default. You can enable them with * Please note that periodic replies are disabled by default. You can enable them with
* #updatePeriodicReply * #updatePeriodicReply
* @param countdown Instead of using maxDelayCycles to timeout a device reply it is also possible
* to provide a pointer to a Countdown object which will signal the timeout
* when expired
* @return - @c RETURN_OK when the command was successfully inserted, * @return - @c RETURN_OK when the command was successfully inserted,
* - @c RETURN_FAILED else. * - @c RETURN_FAILED else.
*/ */
@ -453,7 +458,8 @@ class DeviceHandlerBase : public DeviceHandlerIF,
LocalPoolDataSetBase *replyDataSet = nullptr, LocalPoolDataSetBase *replyDataSet = nullptr,
size_t replyLen = 0, bool periodic = false, size_t replyLen = 0, bool periodic = false,
bool hasDifferentReplyId = false, bool hasDifferentReplyId = false,
DeviceCommandId_t replyId = 0); DeviceCommandId_t replyId = 0,
Countdown *countdown = nullptr);
/** /**
* @brief This is a helper method to insert replies in the reply map. * @brief This is a helper method to insert replies in the reply map.
* @param deviceCommand Identifier of the reply to add. * @param deviceCommand Identifier of the reply to add.
@ -463,12 +469,15 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* by the device repeatedly without request) or not. Default is aperiodic (0). * by the device repeatedly without request) or not. Default is aperiodic (0).
* Please note that periodic replies are disabled by default. You can enable them with * Please note that periodic replies are disabled by default. You can enable them with
* #updatePeriodicReply * #updatePeriodicReply
* @param countdown Instead of using maxDelayCycles to timeout a device reply it is also possible
* to provide a pointer to a Countdown object which will signal the timeout
* when expired
* @return - @c RETURN_OK when the command was successfully inserted, * @return - @c RETURN_OK when the command was successfully inserted,
* - @c RETURN_FAILED else. * - @c RETURN_FAILED else.
*/ */
ReturnValue_t insertInReplyMap(DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles, ReturnValue_t insertInReplyMap(DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles,
LocalPoolDataSetBase *dataSet = nullptr, size_t replyLen = 0, LocalPoolDataSetBase *dataSet = nullptr, size_t replyLen = 0,
bool periodic = false); bool periodic = false, Countdown *countdown = nullptr);
/** /**
* @brief A simple command to add a command to the commandList. * @brief A simple command to add a command to the commandList.
@ -781,6 +790,11 @@ class DeviceHandlerBase : public DeviceHandlerIF,
LocalPoolDataSetBase *dataSet = nullptr; LocalPoolDataSetBase *dataSet = nullptr;
//! The command that expects this reply. //! The command that expects this reply.
DeviceCommandMap::iterator command; DeviceCommandMap::iterator command;
//! Instead of using delayCycles to specify the maximum time to wait for the device reply, it
//! is also possible specify a countdown
Countdown *countdown = nullptr;
//! will be set to true when reply is enabled
bool active = false;
}; };
using DeviceReplyMap = std::map<DeviceCommandId_t, DeviceReplyInfo>; using DeviceReplyMap = std::map<DeviceCommandId_t, DeviceReplyInfo>;
@ -1040,9 +1054,11 @@ class DeviceHandlerBase : public DeviceHandlerIF,
bool isAwaitingReply(); bool isAwaitingReply();
void handleDeviceTM(SerializeIF *dataSet, DeviceCommandId_t replyId, bool forceDirectTm = false); void handleDeviceTM(SerializeIF *dataSet, DeviceCommandId_t replyId, bool forceDirectTm = false);
// void handleDeviceTM(uint8_t* data, size_t dataSize, DeviceCommandId_t replyId,
// bool forceDirectTm);
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode) override; uint32_t *msToReachTheMode);
virtual ReturnValue_t letChildHandleMessage(CommandMessage *message); virtual ReturnValue_t letChildHandleMessage(CommandMessage *message);
@ -1058,7 +1074,8 @@ class DeviceHandlerBase : public DeviceHandlerIF,
/** /**
* Same as triggerEvent, but for forwarding if object is used as proxy. * Same as triggerEvent, but for forwarding if object is used as proxy.
*/ */
void forwardEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0) const override; virtual void forwardEvent(Event event, uint32_t parameter1 = 0,
uint32_t parameter2 = 0) const override;
/** /**
* Checks if current mode is transitional mode. * Checks if current mode is transitional mode.
@ -1239,6 +1256,17 @@ class DeviceHandlerBase : public DeviceHandlerIF,
*/ */
void doGetRead(void); void doGetRead(void);
/**
* @brief Resets replies which use a timeout to detect missed replies.
*/
void resetTimeoutControlledReply(DeviceReplyInfo *info);
/**
* @brief Resets replies which use a number of maximum delay cycles to detect
* missed replies.
*/
void resetDelayCyclesControlledReply(DeviceReplyInfo *info);
/** /**
* Retrive data from the #IPCStore. * Retrive data from the #IPCStore.
* *

View File

@ -88,6 +88,11 @@ ReturnValue_t EventManager::subscribeToEventRange(MessageQueueId_t listener, Eve
return result; return result;
} }
ReturnValue_t EventManager::unsubscribeFromAllEvents(MessageQueueId_t listener,
object_id_t object) {
return unsubscribeFromEventRange(listener, 0, 0, true, object);
}
ReturnValue_t EventManager::unsubscribeFromEventRange(MessageQueueId_t listener, EventId_t idFrom, ReturnValue_t EventManager::unsubscribeFromEventRange(MessageQueueId_t listener, EventId_t idFrom,
EventId_t idTo, bool idInverted, EventId_t idTo, bool idInverted,
object_id_t reporterFrom, object_id_t reporterFrom,

View File

@ -37,6 +37,7 @@ class EventManager : public EventManagerIF, public ExecutableObjectIF, public Sy
EventId_t idTo = 0, bool idInverted = false, EventId_t idTo = 0, bool idInverted = false,
object_id_t reporterFrom = 0, object_id_t reporterTo = 0, object_id_t reporterFrom = 0, object_id_t reporterTo = 0,
bool reporterInverted = false); bool reporterInverted = false);
ReturnValue_t unsubscribeFromAllEvents(MessageQueueId_t listener, object_id_t object);
ReturnValue_t unsubscribeFromEventRange(MessageQueueId_t listener, EventId_t idFrom = 0, ReturnValue_t unsubscribeFromEventRange(MessageQueueId_t listener, EventId_t idFrom = 0,
EventId_t idTo = 0, bool idInverted = false, EventId_t idTo = 0, bool idInverted = false,
object_id_t reporterFrom = 0, object_id_t reporterTo = 0, object_id_t reporterFrom = 0, object_id_t reporterTo = 0,

View File

@ -20,6 +20,7 @@ class EventManagerIF {
bool forwardAllButSelected = false) = 0; bool forwardAllButSelected = false) = 0;
virtual ReturnValue_t subscribeToEvent(MessageQueueId_t listener, EventId_t event) = 0; virtual ReturnValue_t subscribeToEvent(MessageQueueId_t listener, EventId_t event) = 0;
virtual ReturnValue_t subscribeToAllEventsFrom(MessageQueueId_t listener, object_id_t object) = 0; virtual ReturnValue_t subscribeToAllEventsFrom(MessageQueueId_t listener, object_id_t object) = 0;
virtual ReturnValue_t unsubscribeFromAllEvents(MessageQueueId_t listener, object_id_t object) = 0;
virtual ReturnValue_t subscribeToEventRange(MessageQueueId_t listener, EventId_t idFrom = 0, virtual ReturnValue_t subscribeToEventRange(MessageQueueId_t listener, EventId_t idFrom = 0,
EventId_t idTo = 0, bool idInverted = false, EventId_t idTo = 0, bool idInverted = false,
object_id_t reporterFrom = 0, object_id_t reporterFrom = 0,

View File

@ -14,6 +14,16 @@ FailureIsolationBase::FailureIsolationBase(object_id_t owner, object_id_t parent
} }
FailureIsolationBase::~FailureIsolationBase() { FailureIsolationBase::~FailureIsolationBase() {
EventManagerIF* manager = ObjectManager::instance()->get<EventManagerIF>(objects::EVENT_MANAGER);
if (manager == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "FailureIsolationBase::~FailureIsolationBase: Event Manager has not"
" been initialized!"
<< std::endl;
#endif
return;
}
manager->unsubscribeFromAllEvents(eventQueue->getId(), ownerId);
QueueFactory::instance()->deleteMessageQueue(eventQueue); QueueFactory::instance()->deleteMessageQueue(eventQueue);
} }

View File

@ -60,14 +60,14 @@ ReturnValue_t FaultCounter::getParameter(uint8_t domainId, uint8_t uniqueId,
return INVALID_DOMAIN_ID; return INVALID_DOMAIN_ID;
} }
switch (uniqueId) { switch (static_cast<ParameterIds>(uniqueId)) {
case 0: case ParameterIds::FAILURE_THRESHOLD:
parameterWrapper->set(failureThreshold); parameterWrapper->set(failureThreshold);
break; break;
case 1: case ParameterIds::FAULT_COUNT:
parameterWrapper->set(faultCount); parameterWrapper->set(faultCount);
break; break;
case 2: case ParameterIds::TIMEOUT:
parameterWrapper->set(timer.timeout); parameterWrapper->set(timer.timeout);
break; break;
default: default:

View File

@ -6,6 +6,8 @@
class FaultCounter : public HasParametersIF { class FaultCounter : public HasParametersIF {
public: public:
enum class ParameterIds { FAILURE_THRESHOLD, FAULT_COUNT, TIMEOUT };
FaultCounter(); FaultCounter();
FaultCounter(uint32_t failureThreshold, uint32_t decrementAfterMs, FaultCounter(uint32_t failureThreshold, uint32_t decrementAfterMs,
uint8_t setParameterDomain = 0); uint8_t setParameterDomain = 0);
@ -25,7 +27,8 @@ class FaultCounter : public HasParametersIF {
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId, virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper *parameterWrapper, ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex); const ParameterWrapper *newValues = nullptr,
uint16_t startAtIndex = 0);
void setParameterDomain(uint8_t domain); void setParameterDomain(uint8_t domain);

View File

@ -36,7 +36,7 @@ class HasHealthIF {
12, 12,
severity::MEDIUM); //!< Recovery was completed. Not necessarily successful. No parameters. severity::MEDIUM); //!< Recovery was completed. Not necessarily successful. No parameters.
virtual ~HasHealthIF() = default; virtual ~HasHealthIF() {}
virtual MessageQueueId_t getCommandQueue() const = 0; virtual MessageQueueId_t getCommandQueue() const = 0;

View File

@ -5,7 +5,7 @@
HealthHelper::HealthHelper(HasHealthIF* owner, object_id_t objectId) HealthHelper::HealthHelper(HasHealthIF* owner, object_id_t objectId)
: objectId(objectId), owner(owner) {} : objectId(objectId), owner(owner) {}
HealthHelper::~HealthHelper() {} HealthHelper::~HealthHelper() { healthTable->removeObject(objectId); }
ReturnValue_t HealthHelper::handleHealthCommand(CommandMessage* message) { ReturnValue_t HealthHelper::handleHealthCommand(CommandMessage* message) {
switch (message->getCommand()) { switch (message->getCommand()) {

View File

@ -27,6 +27,15 @@ ReturnValue_t HealthTable::registerObject(object_id_t object,
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t HealthTable::removeObject(object_id_t object) {
mapIterator = healthMap.find(object);
if (mapIterator == healthMap.end()) {
return HasReturnvaluesIF::RETURN_FAILED;
}
healthMap.erase(mapIterator);
return HasReturnvaluesIF::RETURN_OK;
}
void HealthTable::setHealth(object_id_t object, HasHealthIF::HealthState newState) { void HealthTable::setHealth(object_id_t object, HasHealthIF::HealthState newState) {
MutexGuard(mutex, timeoutType, mutexTimeoutMs); MutexGuard(mutex, timeoutType, mutexTimeoutMs);
HealthMap::iterator iter = healthMap.find(object); HealthMap::iterator iter = healthMap.find(object);

View File

@ -17,6 +17,7 @@ class HealthTable : public HealthTableIF, public SystemObject {
/** HealthTableIF overrides */ /** HealthTableIF overrides */
virtual ReturnValue_t registerObject( virtual ReturnValue_t registerObject(
object_id_t object, HasHealthIF::HealthState initilialState = HasHealthIF::HEALTHY) override; object_id_t object, HasHealthIF::HealthState initilialState = HasHealthIF::HEALTHY) override;
ReturnValue_t removeObject(object_id_t object) override;
virtual size_t getPrintSize() override; virtual size_t getPrintSize() override;
virtual void printAll(uint8_t* pointer, size_t maxSize) override; virtual void printAll(uint8_t* pointer, size_t maxSize) override;

View File

@ -14,6 +14,8 @@ class HealthTableIF : public ManagesHealthIF {
virtual ReturnValue_t registerObject( virtual ReturnValue_t registerObject(
object_id_t object, HasHealthIF::HealthState initilialState = HasHealthIF::HEALTHY) = 0; object_id_t object, HasHealthIF::HealthState initilialState = HasHealthIF::HEALTHY) = 0;
virtual ReturnValue_t removeObject(object_id_t objectId) = 0;
virtual size_t getPrintSize() = 0; virtual size_t getPrintSize() = 0;
virtual void printAll(uint8_t *pointer, size_t maxSize) = 0; virtual void printAll(uint8_t *pointer, size_t maxSize) = 0;

View File

@ -55,7 +55,7 @@ class HousekeepingSnapshot : public SerializeIF {
: timeStamp(timeStamp), timeStampSize(timeStampSize), updateData(dataSetPtr){}; : timeStamp(timeStamp), timeStampSize(timeStampSize), updateData(dataSetPtr){};
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const override { Endianness streamEndianness) const {
if (timeStamp != nullptr) { if (timeStamp != nullptr) {
/* Endianness will always be MACHINE, so we can simply use memcpy /* Endianness will always be MACHINE, so we can simply use memcpy
here. */ here. */
@ -70,7 +70,7 @@ class HousekeepingSnapshot : public SerializeIF {
return updateData->serialize(buffer, size, maxSize, streamEndianness); return updateData->serialize(buffer, size, maxSize, streamEndianness);
} }
virtual size_t getSerializedSize() const override { virtual size_t getSerializedSize() const {
if (updateData == nullptr) { if (updateData == nullptr) {
return 0; return 0;
} }

View File

@ -10,25 +10,25 @@ class MessageQueueBase : public MessageQueueIF {
virtual ~MessageQueueBase(); virtual ~MessageQueueBase();
// Default implementations for MessageQueueIF where possible // Default implementations for MessageQueueIF where possible
MessageQueueId_t getLastPartner() const override; virtual MessageQueueId_t getLastPartner() const override;
MessageQueueId_t getId() const override; virtual MessageQueueId_t getId() const override;
MqArgs& getMqArgs() override; virtual MqArgs& getMqArgs() override;
void setDefaultDestination(MessageQueueId_t defaultDestination) override; virtual void setDefaultDestination(MessageQueueId_t defaultDestination) override;
MessageQueueId_t getDefaultDestination() const override; virtual MessageQueueId_t getDefaultDestination() const override;
bool isDefaultDestinationSet() const override; virtual bool isDefaultDestinationSet() const override;
ReturnValue_t sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message, virtual ReturnValue_t sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
bool ignoreFault) override; bool ignoreFault) override;
ReturnValue_t sendToDefault(MessageQueueMessageIF* message) override; virtual ReturnValue_t sendToDefault(MessageQueueMessageIF* message) override;
ReturnValue_t reply(MessageQueueMessageIF* message) override; virtual ReturnValue_t reply(MessageQueueMessageIF* message) override;
ReturnValue_t receiveMessage(MessageQueueMessageIF* message, virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message,
MessageQueueId_t* receivedFrom) override; MessageQueueId_t* receivedFrom) override;
ReturnValue_t sendToDefaultFrom(MessageQueueMessageIF* message, MessageQueueId_t sentFrom, virtual ReturnValue_t sendToDefaultFrom(MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
bool ignoreFault = false) override; bool ignoreFault = false) override;
// OSAL specific, forward the abstract function // OSAL specific, forward the abstract function
ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override = 0; virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message) = 0;
ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message, virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault = false) override = 0; MessageQueueId_t sentFrom, bool ignoreFault = false) = 0;
protected: protected:
MessageQueueId_t id = MessageQueueIF::NO_QUEUE; MessageQueueId_t id = MessageQueueIF::NO_QUEUE;

View File

@ -17,8 +17,8 @@ class AbsLimitMonitor : public MonitorBase<T> {
limit(limit), limit(limit),
violationEvent(violationEvent), violationEvent(violationEvent),
aboveIsViolation(aboveIsViolation) {} aboveIsViolation(aboveIsViolation) {}
virtual ~AbsLimitMonitor() = default; virtual ~AbsLimitMonitor() {}
ReturnValue_t checkSample(T sample, T *crossedLimit) override { virtual ReturnValue_t checkSample(T sample, T *crossedLimit) {
*crossedLimit = limit; *crossedLimit = limit;
if (aboveIsViolation) { if (aboveIsViolation) {
if ((std::abs(sample) > limit)) { if ((std::abs(sample) > limit)) {
@ -32,9 +32,9 @@ class AbsLimitMonitor : public MonitorBase<T> {
return HasReturnvaluesIF::RETURN_OK; // We're not out of range. return HasReturnvaluesIF::RETURN_OK; // We're not out of range.
} }
ReturnValue_t getParameter(uint8_t domainId, uint8_t parameterId, virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues, ParameterWrapper *parameterWrapper,
uint16_t startAtIndex) override { const ParameterWrapper *newValues, uint16_t startAtIndex) {
ReturnValue_t result = this->MonitorBase<T>::getParameter( ReturnValue_t result = this->MonitorBase<T>::getParameter(
domainId, parameterId, parameterWrapper, newValues, startAtIndex); domainId, parameterId, parameterWrapper, newValues, startAtIndex);
// We'll reuse the DOMAIN_ID of MonitorReporter, // We'll reuse the DOMAIN_ID of MonitorReporter,
@ -61,7 +61,7 @@ class AbsLimitMonitor : public MonitorBase<T> {
void setLimit(T value) { limit = value; } void setLimit(T value) { limit = value; }
protected: protected:
void sendTransitionEvent(T currentValue, ReturnValue_t state) override { void sendTransitionEvent(T currentValue, ReturnValue_t state) {
switch (state) { switch (state) {
case MonitoringIF::OUT_OF_RANGE: case MonitoringIF::OUT_OF_RANGE:
EventManagerIF::triggerEvent(this->reportingId, violationEvent, this->globalPoolId.objectId, EventManagerIF::triggerEvent(this->reportingId, violationEvent, this->globalPoolId.objectId,

View File

@ -51,8 +51,9 @@ class MonitorReporter : public HasParametersIF {
return state; return state;
} }
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId, ParameterWrapper *parameterWrapper, virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
const ParameterWrapper *newValues, uint16_t startAtIndex) override { ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex) {
if (domainId != monitorId) { if (domainId != monitorId) {
return INVALID_DOMAIN_ID; return INVALID_DOMAIN_ID;
} }

View File

@ -290,9 +290,9 @@ ReturnValue_t MessageQueue::handleOpenError(mq_attr* attributes, uint32_t messag
*/ */
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "MessageQueue::MessageQueue: Default MQ size " << defaultMqMaxMsg sif::error << "MessageQueue::MessageQueue: Default MQ size " << defaultMqMaxMsg
<< " is too small for requested size " << messageDepth << std::endl; << " is too small for requested message depth " << messageDepth << std::endl;
sif::error << "This error can be fixed by setting the maximum " sif::error << "This error can be fixed by setting the maximum "
"allowed message size higher!" "allowed message depth higher"
<< std::endl; << std::endl;
#else #else
sif::printError( sif::printError(

View File

@ -51,7 +51,7 @@ class HasParametersIF {
return (domainId << 24) + (uniqueId << 16) + linearIndex; return (domainId << 24) + (uniqueId << 16) + linearIndex;
} }
virtual ~HasParametersIF() = default; virtual ~HasParametersIF() {}
/** /**
* This is the generic function overriden by child classes to set * This is the generic function overriden by child classes to set

View File

@ -63,13 +63,13 @@ class Fuse : public SystemObject,
SerializeIF::Endianness streamEndianness) override; SerializeIF::Endianness streamEndianness) override;
void setAllMonitorsToUnchecked(); void setAllMonitorsToUnchecked();
ReturnValue_t performOperation(uint8_t opCode); ReturnValue_t performOperation(uint8_t opCode);
MessageQueueId_t getCommandQueue() const override; MessageQueueId_t getCommandQueue() const;
void setDataPoolEntriesInvalid(); void setDataPoolEntriesInvalid();
ReturnValue_t setHealth(HealthState health) override; ReturnValue_t setHealth(HealthState health);
HasHealthIF::HealthState getHealth() override; HasHealthIF::HealthState getHealth();
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId, ParameterWrapper *parameterWrapper, ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId, ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex) override; const ParameterWrapper *newValues, uint16_t startAtIndex);
private: private:
uint8_t oldFuseState; uint8_t oldFuseState;
@ -81,7 +81,7 @@ class Fuse : public SystemObject,
template <typename... Args> template <typename... Args>
PowerMonitor(Args... args) : MonitorReporter<float>(std::forward<Args>(args)...) {} PowerMonitor(Args... args) : MonitorReporter<float>(std::forward<Args>(args)...) {}
ReturnValue_t checkPower(float sample, float lowerLimit, float upperLimit); ReturnValue_t checkPower(float sample, float lowerLimit, float upperLimit);
void sendTransitionEvent(float currentValue, ReturnValue_t state_) override {} void sendTransitionEvent(float currentValue, ReturnValue_t state) {}
}; };
PowerMonitor powerMonitor; PowerMonitor powerMonitor;
StaticLocalDataSet<3> set; StaticLocalDataSet<3> set;

View File

@ -10,15 +10,15 @@ class PowerComponent : public PowerComponentIF {
PowerComponent(object_id_t setId, uint8_t moduleId, float minPower, float maxPower, PowerComponent(object_id_t setId, uint8_t moduleId, float minPower, float maxPower,
uint8_t switchId1, bool twoSwitches = false, uint8_t switchId2 = 0xFF); uint8_t switchId1, bool twoSwitches = false, uint8_t switchId2 = 0xFF);
object_id_t getDeviceObjectId() override; virtual object_id_t getDeviceObjectId();
uint8_t getSwitchId1() override; virtual uint8_t getSwitchId1();
uint8_t getSwitchId2() override; virtual uint8_t getSwitchId2();
bool hasTwoSwitches() override; bool hasTwoSwitches();
float getMin() override; float getMin();
float getMax() override; float getMax();
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const override; Endianness streamEndianness) const override;
@ -29,7 +29,7 @@ class PowerComponent : public PowerComponentIF {
Endianness streamEndianness) override; Endianness streamEndianness) override;
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId, ParameterWrapper* parameterWrapper, ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId, ParameterWrapper* parameterWrapper,
const ParameterWrapper* newValues, uint16_t startAtIndex) override; const ParameterWrapper* newValues, uint16_t startAtIndex);
private: private:
const object_id_t deviceObjectId = objects::NO_OBJECT; const object_id_t deviceObjectId = objects::NO_OBJECT;

View File

@ -7,7 +7,7 @@
class PowerComponentIF : public SerializeIF, public HasParametersIF { class PowerComponentIF : public SerializeIF, public HasParametersIF {
public: public:
~PowerComponentIF() override = default; virtual ~PowerComponentIF() {}
virtual object_id_t getDeviceObjectId() = 0; virtual object_id_t getDeviceObjectId() = 0;

View File

@ -69,7 +69,7 @@ class FailureReport : public SerializeIF { //!< [EXPORT] : [SUBSERVICE] 2, 4, 6
return result; return result;
} }
size_t getSerializedSize() const override { virtual size_t getSerializedSize() const {
size_t size = 0; size_t size = 0;
size += SerializeAdapter::getSerializedSize(&packetId); size += SerializeAdapter::getSerializedSize(&packetId);
size += sizeof(packetSequenceControl); size += sizeof(packetSequenceControl);

View File

@ -34,7 +34,7 @@ class SerializeIF {
static const ReturnValue_t TOO_MANY_ELEMENTS = static const ReturnValue_t TOO_MANY_ELEMENTS =
MAKE_RETURN_CODE(3); // !< There are too many elements to be deserialized MAKE_RETURN_CODE(3); // !< There are too many elements to be deserialized
virtual ~SerializeIF() = default; virtual ~SerializeIF() {}
/** /**
* @brief * @brief
* Function to serialize the object into a buffer with maxSize. Size represents the written * Function to serialize the object into a buffer with maxSize. Size represents the written
@ -66,7 +66,7 @@ class SerializeIF {
* Gets the size of a object if it would be serialized in a buffer * Gets the size of a object if it would be serialized in a buffer
* @return Size of serialized object * @return Size of serialized object
*/ */
[[nodiscard]] virtual size_t getSerializedSize() const = 0; virtual size_t getSerializedSize() const = 0;
/** /**
* @brief * @brief

View File

@ -10,7 +10,7 @@ StorageAccessor::StorageAccessor(store_address_t storeId) : ConstStorageAccessor
StorageAccessor::StorageAccessor(store_address_t storeId, StorageManagerIF* store) StorageAccessor::StorageAccessor(store_address_t storeId, StorageManagerIF* store)
: ConstStorageAccessor(storeId, store) {} : ConstStorageAccessor(storeId, store) {}
StorageAccessor& StorageAccessor::operator=(StorageAccessor&& other) noexcept { StorageAccessor& StorageAccessor::operator=(StorageAccessor&& other) {
// Call the parent move assignment and also assign own member. // Call the parent move assignment and also assign own member.
dataPointer = other.dataPointer; dataPointer = other.dataPointer;
ConstStorageAccessor::operator=(std::move(other)); ConstStorageAccessor::operator=(std::move(other));
@ -18,7 +18,7 @@ StorageAccessor& StorageAccessor::operator=(StorageAccessor&& other) noexcept {
} }
// Call the parent move ctor and also transfer own member. // Call the parent move ctor and also transfer own member.
StorageAccessor::StorageAccessor(StorageAccessor&& other) noexcept StorageAccessor::StorageAccessor(StorageAccessor&& other)
: ConstStorageAccessor(std::move(other)), dataPointer(other.dataPointer) {} : ConstStorageAccessor(std::move(other)), dataPointer(other.dataPointer) {}
ReturnValue_t StorageAccessor::getDataCopy(uint8_t* pointer, size_t maxSize) { ReturnValue_t StorageAccessor::getDataCopy(uint8_t* pointer, size_t maxSize) {

View File

@ -14,7 +14,7 @@ class StorageAccessor : public ConstStorageAccessor {
friend class LocalPool; friend class LocalPool;
public: public:
explicit StorageAccessor(store_address_t storeId); StorageAccessor(store_address_t storeId);
StorageAccessor(store_address_t storeId, StorageManagerIF* store); StorageAccessor(store_address_t storeId, StorageManagerIF* store);
/** /**
@ -25,8 +25,8 @@ class StorageAccessor : public ConstStorageAccessor {
* @param * @param
* @return * @return
*/ */
StorageAccessor& operator=(StorageAccessor&&) noexcept; StorageAccessor& operator=(StorageAccessor&&);
StorageAccessor(StorageAccessor&&) noexcept; StorageAccessor(StorageAccessor&&);
ReturnValue_t write(uint8_t* data, size_t size, uint16_t offset = 0); ReturnValue_t write(uint8_t* data, size_t size, uint16_t offset = 0);
uint8_t* data(); uint8_t* data();

View File

@ -29,11 +29,11 @@ CFDPDistributor::TcMqMapIter CFDPDistributor::selectDestination() {
storeId.packetIndex); storeId.packetIndex);
#endif #endif
#endif #endif
auto queueMapIt = this->queueMap.end(); TcMqMapIter queueMapIt = this->queueMap.end();
if (this->currentPacket == nullptr) { if (this->currentPacket == nullptr) {
return queueMapIt; return queueMapIt;
} }
this->currentPacket->setStoreAddress(this->currentMessage.getStorageId(), currentPacket); this->currentPacket->setStoreAddress(this->currentMessage.getStorageId());
if (currentPacket->getWholeData() != nullptr) { if (currentPacket->getWholeData() != nullptr) {
tcStatus = checker.checkPacket(currentPacket); tcStatus = checker.checkPacket(currentPacket);
if (tcStatus != HasReturnvaluesIF::RETURN_OK) { if (tcStatus != HasReturnvaluesIF::RETURN_OK) {

View File

@ -190,13 +190,13 @@ ReturnValue_t Heater::performOperation(uint8_t opCode) {
} }
void Heater::setSwitch(uint8_t number, ReturnValue_t state, uint32_t* uptimeOfSwitching) { void Heater::setSwitch(uint8_t number, ReturnValue_t state, uint32_t* uptimeOfSwitching) {
if (powerSwitcher == nullptr) { if (powerSwitcher == NULL) {
return; return;
} }
if (powerSwitcher->getSwitchState(number) == state) { if (powerSwitcher->getSwitchState(number) == state) {
*uptimeOfSwitching = INVALID_UPTIME; *uptimeOfSwitching = INVALID_UPTIME;
} else { } else {
if (*uptimeOfSwitching == INVALID_UPTIME) { if ((*uptimeOfSwitching == INVALID_UPTIME)) {
powerSwitcher->sendSwitchCommand(number, state); powerSwitcher->sendSwitchCommand(number, state);
Clock::getUptime(uptimeOfSwitching); Clock::getUptime(uptimeOfSwitching);
} else { } else {

View File

@ -11,11 +11,11 @@ class CFDPPacket : public SpacePacketBase {
* forwards the data pointer to the parent SpacePacketBase class. * forwards the data pointer to the parent SpacePacketBase class.
* @param setData The position where the packet data lies. * @param setData The position where the packet data lies.
*/ */
explicit CFDPPacket(const uint8_t* setData); CFDPPacket(const uint8_t* setData);
/** /**
* This is the empty default destructor. * This is the empty default destructor.
*/ */
~CFDPPacket() override; virtual ~CFDPPacket();
/** /**
* This is a debugging helper method that prints the whole packet content * This is a debugging helper method that prints the whole packet content

View File

@ -2,44 +2,48 @@
#include "fsfw/objectmanager/ObjectManager.h" #include "fsfw/objectmanager/ObjectManager.h"
StorageManagerIF* CFDPPacketStored::store = nullptr;
CFDPPacketStored::CFDPPacketStored() : CFDPPacket(nullptr) {} CFDPPacketStored::CFDPPacketStored() : CFDPPacket(nullptr) {}
CFDPPacketStored::CFDPPacketStored(store_address_t setAddress) : CFDPPacket(nullptr) { CFDPPacketStored::CFDPPacketStored(store_address_t setAddress) : CFDPPacket(nullptr) {
CFDPPacketStored::setStoreAddress(setAddress, this); this->setStoreAddress(setAddress);
} }
CFDPPacketStored::CFDPPacketStored(const uint8_t* data, size_t size) : CFDPPacket(data) { CFDPPacketStored::CFDPPacketStored(const uint8_t* data, size_t size) : CFDPPacket(data) {
if (this->getFullSize() != size) { if (this->getFullSize() != size) {
return; return;
} }
if (CFDPPacketStored::checkAndSetStore()) { if (this->checkAndSetStore()) {
ReturnValue_t status = STORE->addData(&storeAddress, data, size); ReturnValue_t status = store->addData(&storeAddress, data, size);
if (status != HasReturnvaluesIF::RETURN_OK) { if (status != HasReturnvaluesIF::RETURN_OK) {
this->setData(nullptr, -1); this->setData(nullptr, -1);
} }
const uint8_t* storePtr = nullptr; const uint8_t* storePtr = nullptr;
// Repoint base data pointer to the data in the store. // Repoint base data pointer to the data in the store.
STORE->getData(storeAddress, &storePtr, &size); store->getData(storeAddress, &storePtr, &size);
this->setData(const_cast<uint8_t*>(storePtr), size); this->setData(const_cast<uint8_t*>(storePtr), size);
} }
} }
ReturnValue_t CFDPPacketStored::deletePacket() { ReturnValue_t CFDPPacketStored::deletePacket() {
ReturnValue_t result = CFDPPacketStored::STORE->deleteData(this->storeAddress); ReturnValue_t result = this->store->deleteData(this->storeAddress);
this->storeAddress.raw = StorageManagerIF::INVALID_ADDRESS; this->storeAddress.raw = StorageManagerIF::INVALID_ADDRESS;
// To circumvent size checks // To circumvent size checks
this->setData(nullptr, -1); this->setData(nullptr, -1);
return result; return result;
} }
void CFDPPacketStored::setStoreAddress(store_address_t setAddress, // CFDPPacket* CFDPPacketStored::getPacketBase() {
RedirectableDataPointerIF* packet) { // return this;
// }
void CFDPPacketStored::setStoreAddress(store_address_t setAddress) {
this->storeAddress = setAddress; this->storeAddress = setAddress;
const uint8_t* tempData = nullptr; const uint8_t* tempData = nullptr;
size_t tempSize; size_t tempSize;
ReturnValue_t status = StorageManagerIF::RETURN_FAILED; ReturnValue_t status = StorageManagerIF::RETURN_FAILED;
if (CFDPPacketStored::checkAndSetStore()) { if (this->checkAndSetStore()) {
status = CFDPPacketStored::STORE->getData(this->storeAddress, &tempData, &tempSize); status = this->store->getData(this->storeAddress, &tempData, &tempSize);
} }
if (status == StorageManagerIF::RETURN_OK) { if (status == StorageManagerIF::RETURN_OK) {
this->setData(const_cast<uint8_t*>(tempData), tempSize); this->setData(const_cast<uint8_t*>(tempData), tempSize);
@ -52,17 +56,33 @@ void CFDPPacketStored::setStoreAddress(store_address_t setAddress,
store_address_t CFDPPacketStored::getStoreAddress() { return this->storeAddress; } store_address_t CFDPPacketStored::getStoreAddress() { return this->storeAddress; }
CFDPPacketStored::~CFDPPacketStored() = default; CFDPPacketStored::~CFDPPacketStored() {}
ReturnValue_t CFDPPacketStored::getData(const uint8_t** dataPtr, size_t* dataSize) { ReturnValue_t CFDPPacketStored::getData(const uint8_t** dataPtr, size_t* dataSize) {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
// ReturnValue_t CFDPPacketStored::setData(const uint8_t *data) {
// return HasReturnvaluesIF::RETURN_OK;
// }
bool CFDPPacketStored::checkAndSetStore() {
if (this->store == nullptr) {
this->store = ObjectManager::instance()->get<StorageManagerIF>(objects::TC_STORE);
if (this->store == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "CFDPPacketStored::CFDPPacketStored: TC Store not found!" << std::endl;
#endif
return false;
}
}
return true;
}
bool CFDPPacketStored::isSizeCorrect() { bool CFDPPacketStored::isSizeCorrect() {
const uint8_t* temp_data = nullptr; const uint8_t* temp_data = nullptr;
size_t temp_size; size_t temp_size;
ReturnValue_t status = ReturnValue_t status = this->store->getData(this->storeAddress, &temp_data, &temp_size);
CFDPPacketStored::STORE->getData(this->storeAddress, &temp_data, &temp_size);
if (status == StorageManagerIF::RETURN_OK) { if (status == StorageManagerIF::RETURN_OK) {
if (this->getFullSize() == temp_size) { if (this->getFullSize() == temp_size) {
return true; return true;

View File

@ -16,10 +16,10 @@ class CFDPPacketStored : public CFDPPacket, public TcPacketStoredBase {
* Create stored packet from existing packet in store * Create stored packet from existing packet in store
* @param setAddress * @param setAddress
*/ */
explicit CFDPPacketStored(store_address_t setAddress); CFDPPacketStored(store_address_t setAddress);
CFDPPacketStored(); CFDPPacketStored();
~CFDPPacketStored() override; virtual ~CFDPPacketStored();
/** /**
* Getter function for the raw data. * Getter function for the raw data.
@ -27,22 +27,37 @@ class CFDPPacketStored : public CFDPPacket, public TcPacketStoredBase {
* @param dataSize [out] Address of size to set. * @param dataSize [out] Address of size to set.
* @return -@c RETURN_OK if data was retrieved successfully. * @return -@c RETURN_OK if data was retrieved successfully.
*/ */
ReturnValue_t getData(const uint8_t** dataPtr, size_t* dataSize) override; ReturnValue_t getData(const uint8_t** dataPtr, size_t* dataSize);
void setStoreAddress(store_address_t setAddress, RedirectableDataPointerIF* packet) override; void setStoreAddress(store_address_t setAddress);
store_address_t getStoreAddress() override; store_address_t getStoreAddress();
ReturnValue_t deletePacket() override; ReturnValue_t deletePacket();
private: private:
bool isSizeCorrect() override; bool isSizeCorrect();
protected: protected:
/**
* This is a pointer to the store all instances of the class use.
* If the store is not yet set (i.e. @c store is NULL), every constructor
* call tries to set it and throws an error message in case of failures.
* The default store is objects::TC_STORE.
*/
static StorageManagerIF* store;
/** /**
* The address where the packet data of the object instance is stored. * The address where the packet data of the object instance is stored.
*/ */
store_address_t storeAddress; store_address_t storeAddress;
/**
* A helper method to check if a store is assigned to the class.
* If not, the method tries to retrieve the store from the global
* ObjectManager.
* @return @li @c true if the store is linked or could be created.
* @li @c false otherwise.
*/
bool checkAndSetStore();
}; };
#endif /* FSFW_INC_FSFW_TMTCPACKET_CFDP_CFDPPACKETSTORED_H_ */ #endif /* FSFW_INC_FSFW_TMTCPACKET_CFDP_CFDPPACKETSTORED_H_ */

View File

@ -19,7 +19,7 @@ class TcPacketStoredBase : public TcPacketStoredIF {
* Constructor to set to an existing store address. * Constructor to set to an existing store address.
* @param setAddress * @param setAddress
*/ */
explicit TcPacketStoredBase(store_address_t setAddress); TcPacketStoredBase(store_address_t setAddress);
/** /**
* Another constructor to create a TcPacket from a raw packet stream. * Another constructor to create a TcPacket from a raw packet stream.
* Takes the data and adds it unchecked to the TcStore. * Takes the data and adds it unchecked to the TcStore.
@ -28,7 +28,7 @@ class TcPacketStoredBase : public TcPacketStoredIF {
*/ */
TcPacketStoredBase(const uint8_t* data, uint32_t size); TcPacketStoredBase(const uint8_t* data, uint32_t size);
~TcPacketStoredBase() override; virtual ~TcPacketStoredBase();
/** /**
* Getter function for the raw data. * Getter function for the raw data.
@ -70,7 +70,6 @@ class TcPacketStoredBase : public TcPacketStoredIF {
* The address where the packet data of the object instance is stored. * The address where the packet data of the object instance is stored.
*/ */
store_address_t storeAddress; store_address_t storeAddress;
/** /**
* A helper method to check if a store is assigned to the class. * A helper method to check if a store is assigned to the class.
* If not, the method tries to retrieve the store from the global * If not, the method tries to retrieve the store from the global

View File

@ -16,8 +16,6 @@ class TcPacketStoredIF {
* With this call, the stored packet can be set to another packet in a store. This is useful * With this call, the stored packet can be set to another packet in a store. This is useful
* if the packet is a class member and used for more than one packet. * if the packet is a class member and used for more than one packet.
* @param setAddress The new packet id to link to. * @param setAddress The new packet id to link to.
* @param packet Explicit packet instance. The setData function should be called on this
* pointer
*/ */
virtual void setStoreAddress(store_address_t setAddress, RedirectableDataPointerIF* packet) = 0; virtual void setStoreAddress(store_address_t setAddress, RedirectableDataPointerIF* packet) = 0;

View File

@ -2,9 +2,9 @@ add_subdirectory(devicehandlers)
add_subdirectory(common) add_subdirectory(common)
if(UNIX) if(UNIX)
add_subdirectory(linux) add_subdirectory(linux)
endif() endif()
if(FSFW_HAL_ADD_STM32H7) if(FSFW_HAL_ADD_STM32H7)
add_subdirectory(stm32h7) add_subdirectory(stm32h7)
endif() endif()

View File

@ -0,0 +1 @@
target_sources(${LIB_FSFW_NAME} PRIVATE GpioCookie.cpp)

View File

@ -0,0 +1,3 @@
target_sources(
${LIB_FSFW_NAME} PRIVATE GyroL3GD20Handler.cpp MgmRM3100Handler.cpp
MgmLIS3MDLHandler.cpp)

View File

@ -17,6 +17,8 @@ MgmLIS3MDLHandler::MgmLIS3MDLHandler(object_id_t objectId, object_id_t deviceCom
registers[4] = MGMLIS3MDL::CTRL_REG5_DEFAULT; registers[4] = MGMLIS3MDL::CTRL_REG5_DEFAULT;
} }
MgmLIS3MDLHandler::~MgmLIS3MDLHandler() {}
void MgmLIS3MDLHandler::doStartUp() { void MgmLIS3MDLHandler::doStartUp() {
switch (internalState) { switch (internalState) {
case (InternalState::STATE_NONE): { case (InternalState::STATE_NONE): {
@ -88,7 +90,7 @@ ReturnValue_t MgmLIS3MDLHandler::buildTransitionDeviceCommand(DeviceCommandId_t
uint8_t MgmLIS3MDLHandler::readCommand(uint8_t command, bool continuousCom) { uint8_t MgmLIS3MDLHandler::readCommand(uint8_t command, bool continuousCom) {
command |= (1 << MGMLIS3MDL::RW_BIT); command |= (1 << MGMLIS3MDL::RW_BIT);
if (continuousCom) { if (continuousCom == true) {
command |= (1 << MGMLIS3MDL::MS_BIT); command |= (1 << MGMLIS3MDL::MS_BIT);
} }
return command; return command;
@ -96,7 +98,7 @@ uint8_t MgmLIS3MDLHandler::readCommand(uint8_t command, bool continuousCom) {
uint8_t MgmLIS3MDLHandler::writeCommand(uint8_t command, bool continuousCom) { uint8_t MgmLIS3MDLHandler::writeCommand(uint8_t command, bool continuousCom) {
command &= ~(1 << MGMLIS3MDL::RW_BIT); command &= ~(1 << MGMLIS3MDL::RW_BIT);
if (continuousCom) { if (continuousCom == true) {
command |= (1 << MGMLIS3MDL::MS_BIT); command |= (1 << MGMLIS3MDL::MS_BIT);
} }
return command; return command;

View File

@ -28,7 +28,7 @@ class MgmLIS3MDLHandler : public DeviceHandlerBase {
MgmLIS3MDLHandler(uint32_t objectId, object_id_t deviceCommunication, CookieIF *comCookie, MgmLIS3MDLHandler(uint32_t objectId, object_id_t deviceCommunication, CookieIF *comCookie,
uint32_t transitionDelay); uint32_t transitionDelay);
~MgmLIS3MDLHandler() override = default; virtual ~MgmLIS3MDLHandler();
void enablePeriodicPrintouts(bool enable, uint8_t divider); void enablePeriodicPrintouts(bool enable, uint8_t divider);
/** /**
@ -46,7 +46,7 @@ class MgmLIS3MDLHandler : public DeviceHandlerBase {
void doShutDown() override; void doShutDown() override;
void doStartUp() override; void doStartUp() override;
void doTransition(Mode_t modeFrom, Submode_t subModeFrom) override; void doTransition(Mode_t modeFrom, Submode_t subModeFrom) override;
uint32_t getTransitionDelayMs(Mode_t from, Mode_t to) override; virtual uint32_t getTransitionDelayMs(Mode_t from, Mode_t to) override;
ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand, const uint8_t *commandData, ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand, const uint8_t *commandData,
size_t commandDataLen) override; size_t commandDataLen) override;
ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t *id) override; ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t *id) override;
@ -60,9 +60,9 @@ class MgmLIS3MDLHandler : public DeviceHandlerBase {
* @param packet * @param packet
* @return * @return
*/ */
ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) override; virtual ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) override;
void fillCommandAndReplyMap() override; void fillCommandAndReplyMap() override;
void modeChanged() override; void modeChanged(void) override;
ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap, ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) override; LocalDataPoolManager &poolManager) override;
@ -72,6 +72,8 @@ class MgmLIS3MDLHandler : public DeviceHandlerBase {
static const uint8_t SINGLE_COMMAND_ANSWER_LEN = 2; static const uint8_t SINGLE_COMMAND_ANSWER_LEN = 2;
uint32_t transitionDelay; uint32_t transitionDelay;
// Single SPI command has 2 bytes, first for adress, second for content
size_t singleComandSize = 2;
// Has the size for all adresses of the lis3mdl + the continous write bit // Has the size for all adresses of the lis3mdl + the continous write bit
uint8_t commandBuffer[MGMLIS3MDL::NR_OF_DATA_AND_CFG_REGISTERS + 1]; uint8_t commandBuffer[MGMLIS3MDL::NR_OF_DATA_AND_CFG_REGISTERS + 1];
@ -86,6 +88,7 @@ class MgmLIS3MDLHandler : public DeviceHandlerBase {
*/ */
uint8_t registers[MGMLIS3MDL::NR_OF_CTRL_REGISTERS]; uint8_t registers[MGMLIS3MDL::NR_OF_CTRL_REGISTERS];
uint8_t statusRegister = 0;
bool goToNormalMode = false; bool goToNormalMode = false;
enum class InternalState { enum class InternalState {
@ -108,14 +111,14 @@ class MgmLIS3MDLHandler : public DeviceHandlerBase {
* @param single command to set the read-bit at * @param single command to set the read-bit at
* @param boolean to select a continuous read bit, default = false * @param boolean to select a continuous read bit, default = false
*/ */
static uint8_t readCommand(uint8_t command, bool continuousCom = false); uint8_t readCommand(uint8_t command, bool continuousCom = false);
/** /**
* Sets the write bit for the command * Sets the write bit for the command
* @param single command to set the write-bit at * @param single command to set the write-bit at
* @param boolean to select a continuous write bit, default = false * @param boolean to select a continuous write bit, default = false
*/ */
static uint8_t writeCommand(uint8_t command, bool continuousCom = false); uint8_t writeCommand(uint8_t command, bool continuousCom = false);
/** /**
* This Method gets the full scale for the measurement range * This Method gets the full scale for the measurement range

View File

@ -329,9 +329,9 @@ ReturnValue_t MgmRM3100Handler::handleDataReadout(const uint8_t *packet) {
int32_t fieldStrengthRawZ = ((packet[7] << 24) | (packet[8] << 16) | (packet[3] << 8)) >> 8; int32_t fieldStrengthRawZ = ((packet[7] << 24) | (packet[8] << 16) | (packet[3] << 8)) >> 8;
// Now scale to physical value in microtesla // Now scale to physical value in microtesla
float fieldStrengthX = static_cast<float>(fieldStrengthRawX) * scaleFactorX; float fieldStrengthX = fieldStrengthRawX * scaleFactorX;
float fieldStrengthY = static_cast<float>(fieldStrengthRawY) * scaleFactorY; float fieldStrengthY = fieldStrengthRawY * scaleFactorX;
float fieldStrengthZ = static_cast<float>(fieldStrengthRawZ) * scaleFactorZ; float fieldStrengthZ = fieldStrengthRawZ * scaleFactorX;
if (periodicPrintout) { if (periodicPrintout) {
if (debugDivider.checkAndIncrement()) { if (debugDivider.checkAndIncrement()) {

View File

@ -72,6 +72,7 @@ class MgmRM3100Handler : public DeviceHandlerBase {
RM3100::Rm3100PrimaryDataset primaryDataset; RM3100::Rm3100PrimaryDataset primaryDataset;
uint8_t commandBuffer[10]; uint8_t commandBuffer[10];
uint8_t commandBufferLen = 0;
uint8_t cmmRegValue = RM3100::CMM_VALUE; uint8_t cmmRegValue = RM3100::CMM_VALUE;
uint8_t tmrcRegValue = RM3100::TMRC_DEFAULT_VALUE; uint8_t tmrcRegValue = RM3100::TMRC_DEFAULT_VALUE;
@ -99,4 +100,4 @@ class MgmRM3100Handler : public DeviceHandlerBase {
PeriodicOperationDivider debugDivider = PeriodicOperationDivider(3); PeriodicOperationDivider debugDivider = PeriodicOperationDivider(3);
}; };
#endif /* MISSION_DEVICES_MGMRM3100HANDLER_H_ */ #endif /* MISSION_DEVICEHANDLING_MGMRM3100HANDLER_H_ */

View File

@ -0,0 +1,21 @@
if(FSFW_HAL_ADD_RASPBERRY_PI)
add_subdirectory(rpi)
endif()
target_sources(${LIB_FSFW_NAME} PRIVATE UnixFileGuard.cpp CommandExecutor.cpp
utility.cpp)
if(FSFW_HAL_LINUX_ADD_PERIPHERAL_DRIVERS)
if(FSFW_HAL_LINUX_ADD_LIBGPIOD)
add_subdirectory(gpio)
endif()
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)

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