Compare commits
137
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
31f59f915c | ||
|
|
d975958120 | ||
|
|
adcc375f25 | ||
|
|
4a10f76784 | ||
|
|
57ce5d1f34 | ||
|
|
90963b3940 | ||
|
|
71ed95b09a | ||
|
|
7ac4f1c64d | ||
|
|
9d64b96e9a | ||
|
|
5de2c6af66 | ||
|
|
ca2efb6021 | ||
|
|
deeeef553b | ||
|
|
0e7ec79af9 | ||
|
|
d3cabd8984 | ||
|
|
8efe85cb15 | ||
|
|
b28091e05b | ||
|
|
f4c4f9946c | ||
|
|
7f89022f5b | ||
|
|
b28c26b288 | ||
|
|
8b4253bc46 | ||
|
|
fdcfd89ed2 | ||
|
|
03fa77e2b3 | ||
|
|
8970a7379a | ||
|
|
cc56b00df3 | ||
|
|
43048c852a | ||
|
|
19817bd3a5 | ||
|
|
1db04cf20c | ||
|
|
52ee50ba8c | ||
|
|
96f092ef75 | ||
|
|
4a4d23573d | ||
|
|
47e148af8f | ||
|
|
c9bec03f00 | ||
|
|
6c5c59cad8 | ||
|
|
03e12a2388 | ||
|
|
cfdbe0f6cb | ||
|
|
dd281f8a67 | ||
|
|
f9e9ff320f | ||
|
|
b11cdf6184 | ||
|
|
dc31358d52 | ||
|
|
e7d9979078 | ||
|
|
8f07133e2c | ||
|
|
f11433e50f | ||
|
|
edc5a314b8 | ||
|
|
f80be9e9fa | ||
|
|
f3af88ae40 | ||
|
|
380f1d0206 | ||
|
|
54fc35eae7 | ||
|
|
05d4162f5b | ||
|
|
e030878023 | ||
|
|
180210dc38 | ||
|
|
2a34c831b1 | ||
|
|
c96e304b68 | ||
|
|
3708df2423 | ||
|
|
b809f90e72 | ||
|
|
f2bf4b463e | ||
|
|
8e05fc0417 | ||
|
|
ddad97033d | ||
|
|
42a1d6cccd | ||
|
|
9bbe1dc716 | ||
|
|
f56646d2c3 | ||
|
|
74794bb71b | ||
|
|
6f751c2cf9 | ||
|
|
9a2e68b37e | ||
|
|
91067cde98 | ||
|
|
428018e4f1 | ||
|
|
8b6dd3f868 | ||
|
|
f6ede7cd3e | ||
|
|
4da18172b3 | ||
|
|
6e5239e9a0 | ||
|
|
78b09ed0c9 | ||
|
|
fdf35232ee | ||
|
|
8465670374 | ||
|
|
3b23fb77b4 | ||
|
|
6f7be281ef | ||
|
|
b08d127e11 | ||
|
|
3686bbc486 | ||
|
|
ecac08814e | ||
|
|
e8b8fff0b5 | ||
|
|
4d34f93cfc | ||
|
|
adbf375f38 | ||
|
|
2e42f53682 | ||
|
|
c519b70302 | ||
|
|
45ee307bc4 | ||
|
|
8a2068aca6 | ||
|
|
aa60484111 | ||
|
|
e99c7f3824 | ||
|
|
2ee3ef1f1d | ||
|
|
ce48827ee5 | ||
|
|
0d80fad685 | ||
|
|
c6253bf0dd | ||
|
|
93933dee02 | ||
|
|
0e49640306 | ||
|
|
32fea9838e | ||
|
|
0519083894 | ||
|
|
14bac9a418 | ||
|
|
3bef73708f | ||
|
|
fef6ddceff | ||
|
|
5a9db72814 | ||
|
|
5cccd5caba | ||
|
|
7de56f189b | ||
|
|
ef18377cef | ||
|
|
0c057c66b1 | ||
|
|
34c50ce3e2 | ||
|
|
df97bbc691 | ||
|
|
2d2f65bf89 | ||
|
|
3e9ae62b28 | ||
|
|
2ebefdffae | ||
|
|
45792e86b9 | ||
|
|
21eb386f3c | ||
|
|
ade36e65c6 | ||
|
|
103661facc | ||
|
|
ae2f7219fd | ||
|
|
4fba2704aa | ||
|
|
161dbde0d7 | ||
|
|
2fa4fd61d0 | ||
|
|
bf673c56c6 | ||
|
|
d871f55a89 | ||
|
|
1611a4e1f0 | ||
|
|
ff40a71582 | ||
|
|
e1604b292c | ||
|
|
7afe30ea88 | ||
|
|
d3e7037759 | ||
|
|
0aee86442e | ||
|
|
951c077abc | ||
|
|
755dcf66a3 | ||
|
|
b7ffd2653b | ||
|
|
7a5ce57bbc | ||
|
|
adfefdd93f | ||
|
|
b7a316008a | ||
|
|
f598f7030f | ||
|
|
70f575396d | ||
|
|
ad57e6713e | ||
|
|
23f8e5cb41 | ||
|
|
879223f38f | ||
|
|
8a44c498c5 | ||
|
|
a891769a02 | ||
|
|
df97c582d7 |
No files matched your search
@@ -10,5 +10,8 @@
|
||||
.settings
|
||||
.metadata
|
||||
|
||||
# VSCode
|
||||
.vscode
|
||||
|
||||
/build*
|
||||
/cmake-build*
|
||||
+24
-2
@@ -8,7 +8,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
# [unreleased]
|
||||
|
||||
# [v5.0.0]
|
||||
## Added
|
||||
|
||||
- Add new `UnsignedByteField` class
|
||||
|
||||
# [v5.0.0] 25.07.2022
|
||||
|
||||
## Changes
|
||||
|
||||
@@ -23,6 +27,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/572
|
||||
- HAL Devicehandlers: Periodic printout is run-time configurable now
|
||||
- `oneShotAction` flag in the `TestTask` class is not static anymore
|
||||
- `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.
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/601
|
||||
- Add helper functions provided by [`cmake-modules`](https://github.com/bilke/cmake-modules)
|
||||
@@ -40,6 +47,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
creation call. It allows passing context information and an arbitrary user argument into
|
||||
the message queue. Also streamlined and simplified `MessageQueue` implementation for all OSALs
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/583
|
||||
- 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
|
||||
|
||||
@@ -85,7 +95,6 @@ PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/636
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/572
|
||||
- HAL Linux Uart: Baudrate and bits per word are enums now, avoiding misconfigurations
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/585
|
||||
- Linux HAL: Add wiretapping option for I2C. Enabled with `FSFW_HAL_I2C_WIRETAPPING` defined to 1
|
||||
|
||||
### Time
|
||||
|
||||
@@ -115,6 +124,8 @@ https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/593
|
||||
|
||||
## 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
|
||||
whether it is running in CI/CD
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/623
|
||||
@@ -148,6 +159,17 @@ https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/593
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/590
|
||||
- `Subsystem`: New API to add table and sequence entries
|
||||
|
||||
## HAL
|
||||
|
||||
- SPI: Cache the SPI device in the communication interface. Architecturally, this makes a
|
||||
lot more sense because each ComIF should be responsible for one SPI bus.
|
||||
- SPI: Move the empty transfer to update the line polarity to separate function. This means
|
||||
it is not automatically called when calling the setter function for SPI speed and mode.
|
||||
The user should call this function after locking the CS mutex if multiple SPI devices with
|
||||
differing speeds and modes are attached to one bus.
|
||||
- SPI: Getter functions for SPI speed and mode.
|
||||
- I2C: Add wiretapping option for I2C. Enabled with `FSFW_HAL_I2C_WIRETAPPING` defined to 1.
|
||||
|
||||
## Fixed
|
||||
|
||||
- TCP TMTC Server: `MutexGuard` was not created properly in
|
||||
|
||||
+22
-17
@@ -13,7 +13,7 @@ list(APPEND CMAKE_MODULE_PATH
|
||||
# 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_REVISION_IF_GIT_FAILS 0)
|
||||
|
||||
@@ -67,6 +67,7 @@ endif()
|
||||
set(FSFW_SOURCES_DIR "${CMAKE_SOURCE_DIR}/src/fsfw")
|
||||
|
||||
set(FSFW_ETL_LIB_NAME etl)
|
||||
set(FSFW_ETL_LINK_TARGET etl::etl)
|
||||
set(FSFW_ETL_LIB_MAJOR_VERSION
|
||||
20
|
||||
CACHE STRING "ETL library major version requirement")
|
||||
@@ -103,11 +104,11 @@ if(FSFW_GENERATE_SECTIONS)
|
||||
option(FSFW_REMOVE_UNUSED_CODE "Remove unused code" ON)
|
||||
endif()
|
||||
|
||||
option(FSFW_BUILD_UNITTESTS
|
||||
"Build unittest binary in addition to static library" OFF)
|
||||
option(FSFW_BUILD_TESTS "Build unittest binary in addition to static library"
|
||||
OFF)
|
||||
option(FSFW_CICD_BUILD "Build for CI/CD. This can disable problematic test" OFF)
|
||||
option(FSFW_BUILD_DOCS "Build documentation with Sphinx and Doxygen" OFF)
|
||||
if(FSFW_BUILD_UNITTESTS)
|
||||
if(FSFW_BUILD_TESTS)
|
||||
option(FSFW_TESTS_GEN_COV "Generate coverage data for unittests" ON)
|
||||
endif()
|
||||
|
||||
@@ -117,6 +118,12 @@ option(FSFW_ADD_INTERNAL_TESTS "Add internal unit tests" ON)
|
||||
option(FSFW_ADD_UNITTESTS "Add regular unittests. Requires Catch2" OFF)
|
||||
option(FSFW_ADD_HAL "Add Hardware Abstraction Layer" ON)
|
||||
|
||||
if(UNIX)
|
||||
option(FSFW_HAL_LINUX_ADD_PERIPHERAL_DRIVERS "Add Linux peripheral drivers"
|
||||
OFF)
|
||||
option(FSFW_HAL_LINUX_ADD_LIBGPIOD "Attempt to add Linux GPIOD drivers" OFF)
|
||||
endif()
|
||||
|
||||
# Optional sources
|
||||
option(FSFW_ADD_PUS "Compile with PUS sources" ON)
|
||||
option(FSFW_ADD_MONITORING "Compile with monitoring components" ON)
|
||||
@@ -139,7 +146,7 @@ if(IPO_SUPPORTED AND FSFW_ENABLE_IPO)
|
||||
TRUE)
|
||||
endif()
|
||||
|
||||
if(FSFW_BUILD_UNITTESTS)
|
||||
if(FSFW_BUILD_TESTS)
|
||||
message(
|
||||
STATUS
|
||||
"${MSG_PREFIX} Building the FSFW unittests in addition to the static library"
|
||||
@@ -162,10 +169,9 @@ if(FSFW_BUILD_UNITTESTS)
|
||||
list(APPEND FSFW_FETCH_CONTENT_TARGETS Catch2)
|
||||
endif()
|
||||
|
||||
set(FSFW_CONFIG_PATH tests/src/fsfw_tests/unit/testcfg)
|
||||
configure_file(tests/src/fsfw_tests/unit/testcfg/FSFWConfig.h.in FSFWConfig.h)
|
||||
configure_file(tests/src/fsfw_tests/unit/testcfg/TestsConfig.h.in
|
||||
tests/TestsConfig.h)
|
||||
set(FSFW_CONFIG_PATH unittests/testcfg)
|
||||
configure_file(unittests/testcfg/FSFWConfig.h.in FSFWConfig.h)
|
||||
configure_file(unittests/testcfg/TestsConfig.h.in tests/TestsConfig.h)
|
||||
|
||||
project(${FSFW_TEST_TGT} CXX C)
|
||||
add_executable(${FSFW_TEST_TGT})
|
||||
@@ -189,7 +195,7 @@ message(
|
||||
)
|
||||
|
||||
# Check whether the user has already installed ETL first
|
||||
find_package(${FSFW_ETL_LIB_NAME} ${FSFW_ETL_LIB_MAJOR_VERSION} QUIET)
|
||||
find_package(${FSFW_ETL_LIB_NAME} ${FSFW_ETL_LIB_MAJOR_VERSION} CONFIG QUIET)
|
||||
# Not installed, so use FetchContent to download and provide etl
|
||||
if(NOT ${FSFW_ETL_LIB_NAME}_FOUND)
|
||||
message(
|
||||
@@ -284,16 +290,15 @@ message(
|
||||
)
|
||||
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(tests)
|
||||
if(FSFW_ADD_HAL)
|
||||
add_subdirectory(hal)
|
||||
endif()
|
||||
add_subdirectory(contrib)
|
||||
if(FSFW_BUILD_TESTS)
|
||||
add_subdirectory(unittests)
|
||||
endif()
|
||||
if(FSFW_BUILD_DOCS)
|
||||
add_subdirectory(docs)
|
||||
endif()
|
||||
|
||||
if(FSFW_BUILD_UNITTESTS)
|
||||
if(FSFW_BUILD_TESTS)
|
||||
if(FSFW_TESTS_GEN_COV)
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
include(CodeCoverage)
|
||||
@@ -450,8 +455,8 @@ target_include_directories(
|
||||
target_compile_options(${LIB_FSFW_NAME} PRIVATE ${FSFW_WARNING_FLAGS}
|
||||
${COMPILER_FLAGS})
|
||||
|
||||
target_link_libraries(${LIB_FSFW_NAME} PRIVATE ${FSFW_ETL_LINK_TARGET}
|
||||
${FSFW_ADDITIONAL_LINK_LIBS})
|
||||
target_link_libraries(${LIB_FSFW_NAME} PRIVATE ${FSFW_ADDITIONAL_LINK_LIBS})
|
||||
target_link_libraries(${LIB_FSFW_NAME} PUBLIC ${FSFW_ETL_LINK_TARGET})
|
||||
|
||||
string(
|
||||
CONCAT
|
||||
|
||||
@@ -132,14 +132,14 @@ You can use the following commands inside the `fsfw` folder to set up the build
|
||||
|
||||
```sh
|
||||
mkdir build-tests && cd build-tests
|
||||
cmake -DFSFW_BUILD_UNITTESTS=ON -DFSFW_OSAL=host -DCMAKE_BUILD_TYPE=Debug ..
|
||||
cmake -DFSFW_BUILD_TESTS=ON -DFSFW_OSAL=host -DCMAKE_BUILD_TYPE=Debug ..
|
||||
```
|
||||
|
||||
You can also use `-DFSFW_OSAL=linux` on Linux systems.
|
||||
|
||||
Coverage data in HTML format can be generated using the `CodeCoverage`
|
||||
[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
|
||||
|
||||
```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
|
||||
`.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
|
||||
|
||||
|
||||
@@ -12,3 +12,9 @@ RUN git clone https://github.com/catchorg/Catch2.git && \
|
||||
git checkout v3.0.0-preview5 && \
|
||||
cmake -Bbuild -H. -DBUILD_TESTING=OFF && \
|
||||
cmake --build build/ --target install
|
||||
|
||||
RUN git clone https://github.com/ETLCPP/etl.git && \
|
||||
cd etl && \
|
||||
git checkout 20.28.0 && \
|
||||
cmake -B build . && \
|
||||
cmake --install build/
|
||||
Vendored
+2
-2
@@ -3,7 +3,7 @@ pipeline {
|
||||
BUILDDIR = 'build-tests'
|
||||
}
|
||||
agent {
|
||||
docker { image 'fsfw-ci:d2'}
|
||||
docker { image 'fsfw-ci:d3'}
|
||||
}
|
||||
stages {
|
||||
stage('Clean') {
|
||||
@@ -14,7 +14,7 @@ pipeline {
|
||||
stage('Configure') {
|
||||
steps {
|
||||
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 ..'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ You can use the following commands inside the ``fsfw`` folder to set up the buil
|
||||
.. code-block:: console
|
||||
|
||||
mkdir build-tests && cd build-tests
|
||||
cmake -DFSFW_BUILD_UNITTESTS=ON -DFSFW_OSAL=host ..
|
||||
cmake -DFSFW_BUILD_TESTS=ON -DFSFW_OSAL=host ..
|
||||
|
||||
|
||||
You can also use ``-DFSFW_OSAL=linux`` on Linux systems.
|
||||
|
||||
@@ -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}
|
||||
)
|
||||
@@ -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)
|
||||
@@ -1,3 +0,0 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
GpioCookie.cpp
|
||||
)
|
||||
@@ -1,5 +0,0 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
GyroL3GD20Handler.cpp
|
||||
MgmRM3100Handler.cpp
|
||||
MgmLIS3MDLHandler.cpp
|
||||
)
|
||||
@@ -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)
|
||||
@@ -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()
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
target_sources(${LIB_FSFW_NAME} PUBLIC
|
||||
I2cComIF.cpp
|
||||
I2cCookie.cpp
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
GpioRPi.cpp
|
||||
)
|
||||
@@ -1,8 +0,0 @@
|
||||
target_sources(${LIB_FSFW_NAME} PUBLIC
|
||||
SpiComIF.cpp
|
||||
SpiCookie.cpp
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
target_sources(${LIB_FSFW_NAME} PUBLIC
|
||||
UartComIF.cpp
|
||||
UartCookie.cpp
|
||||
)
|
||||
@@ -1,3 +0,0 @@
|
||||
target_sources(${LIB_FSFW_NAME} PUBLIC
|
||||
UioMapper.cpp
|
||||
)
|
||||
@@ -1,3 +0,0 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
GyroL3GD20H.cpp
|
||||
)
|
||||
@@ -1,3 +0,0 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
gpio.cpp
|
||||
)
|
||||
@@ -1,2 +0,0 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
)
|
||||
@@ -1,9 +0,0 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
spiCore.cpp
|
||||
spiDefinitions.cpp
|
||||
spiInterrupts.cpp
|
||||
mspInit.cpp
|
||||
SpiCookie.cpp
|
||||
SpiComIF.cpp
|
||||
stm32h743zi.cpp
|
||||
)
|
||||
@@ -1,2 +0,0 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
)
|
||||
@@ -5,8 +5,7 @@ fi
|
||||
|
||||
folder_list=(
|
||||
"./src"
|
||||
"./hal"
|
||||
"./tests"
|
||||
"./unittests"
|
||||
)
|
||||
|
||||
cmake_fmt="cmake-format"
|
||||
|
||||
+23
-4
@@ -48,6 +48,20 @@ def main():
|
||||
action="store_true",
|
||||
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()
|
||||
if args.all:
|
||||
@@ -115,14 +129,14 @@ def handle_tests_type(args, build_dir_list: list):
|
||||
if args.create:
|
||||
if os.path.exists(UNITTEST_FOLDER_NAME):
|
||||
shutil.rmtree(UNITTEST_FOLDER_NAME)
|
||||
create_tests_build_cfg()
|
||||
create_tests_build_cfg(args)
|
||||
build_directory = UNITTEST_FOLDER_NAME
|
||||
elif len(build_dir_list) == 0:
|
||||
print(
|
||||
"No valid CMake tests build directory found. "
|
||||
"Trying to set up test build system"
|
||||
)
|
||||
create_tests_build_cfg()
|
||||
create_tests_build_cfg(args)
|
||||
build_directory = UNITTEST_FOLDER_NAME
|
||||
elif len(build_dir_list) == 1:
|
||||
build_directory = build_dir_list[0]
|
||||
@@ -147,10 +161,15 @@ def handle_tests_type(args, build_dir_list: list):
|
||||
os.chdir("..")
|
||||
|
||||
|
||||
def create_tests_build_cfg():
|
||||
def create_tests_build_cfg(args):
|
||||
os.mkdir(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("..")
|
||||
|
||||
|
||||
|
||||
@@ -4,3 +4,8 @@ target_include_directories(${LIB_FSFW_NAME}
|
||||
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
add_subdirectory(fsfw)
|
||||
if(FSFW_ADD_HAL)
|
||||
add_subdirectory(fsfw_hal)
|
||||
endif()
|
||||
|
||||
add_subdirectory(fsfw_tests)
|
||||
@@ -15,6 +15,7 @@ add_subdirectory(globalfunctions)
|
||||
add_subdirectory(health)
|
||||
add_subdirectory(housekeeping)
|
||||
add_subdirectory(internalerror)
|
||||
add_subdirectory(introspection)
|
||||
add_subdirectory(ipc)
|
||||
add_subdirectory(memory)
|
||||
add_subdirectory(modes)
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
#include "Action.h"
|
||||
|
||||
#include <fsfw/serialize/SerializeAdapter.h>
|
||||
|
||||
#undef Action
|
||||
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
|
||||
Action::Action() {}
|
||||
|
||||
void Action::setEnum(EnumIF *theEnum) {
|
||||
id = theEnum->getValue();
|
||||
name = theEnum->getDescription();
|
||||
}
|
||||
|
||||
const char *Action::getName() { return name; }
|
||||
#else
|
||||
Action::Action(ActionId_t id) : id(id) {}
|
||||
#endif
|
||||
ActionId_t Action::getId() { return id; }
|
||||
|
||||
void Action::registerParameter(ParameterIF *parameter) { parameterList.push_back(parameter); }
|
||||
|
||||
std::vector<ParameterIF *> const *Action::getParameters() const { return ¶meterList; }
|
||||
|
||||
size_t Action::getSerializedSize() const {
|
||||
size_t size = SerializeAdapter::getSerializedSize(&id);
|
||||
for (auto parameter : *getParameters()) {
|
||||
size += parameter->getSerializedSize();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
ReturnValue_t Action::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||
Endianness streamEndianness) const {
|
||||
ReturnValue_t result = SerializeAdapter::serialize(&id, buffer, size, maxSize, streamEndianness);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
for (auto parameter : *getParameters()) {
|
||||
result = parameter->serialize(buffer, size, maxSize, streamEndianness);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t Action::deSerialize(const uint8_t **buffer, size_t *size,
|
||||
Endianness streamEndianness) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;/* TODO not needed as must have been read before to find this action = SerializeAdapter::deSerialize(&id, buffer, size, streamEndianness);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}*/
|
||||
for (auto parameter : *getParameters()) {
|
||||
result = parameter->deSerialize(buffer, size, streamEndianness);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <fsfw/serialize/SerializeIF.h>
|
||||
#include "ActionMessage.h"
|
||||
#include "ParameterIF.h"
|
||||
|
||||
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
#include "../introspection/Enum.h"
|
||||
#endif
|
||||
|
||||
class Action: public SerializeIF {
|
||||
public:
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
Action();
|
||||
void setEnum(EnumIF* id);
|
||||
const char *getName();
|
||||
#else
|
||||
Action(ActionId_t id);
|
||||
#endif
|
||||
ActionId_t getId();
|
||||
|
||||
MessageQueueId_t commandedBy;
|
||||
|
||||
[[nodiscard]] virtual ReturnValue_t handle() = 0;
|
||||
|
||||
void registerParameter(ParameterIF *parameter);
|
||||
|
||||
std::vector<ParameterIF *> const *getParameters() const;
|
||||
|
||||
ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||
Endianness streamEndianness) const override;
|
||||
|
||||
size_t getSerializedSize() const override;
|
||||
|
||||
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
|
||||
Endianness streamEndianness) override;
|
||||
|
||||
private:
|
||||
ActionId_t id;
|
||||
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
const char *name;
|
||||
#endif
|
||||
std::vector<ParameterIF *> parameterList;
|
||||
};
|
||||
@@ -6,7 +6,7 @@
|
||||
ActionHelper::ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue)
|
||||
: owner(setOwner), queueToUse(useThisQueue) {}
|
||||
|
||||
ActionHelper::~ActionHelper() {}
|
||||
ActionHelper::~ActionHelper() = default;
|
||||
|
||||
ReturnValue_t ActionHelper::handleActionMessage(CommandMessage* command) {
|
||||
if (command->getCommand() == ActionMessage::EXECUTE_ACTION) {
|
||||
@@ -57,18 +57,40 @@ void ActionHelper::finish(bool success, MessageQueueId_t reportTo, ActionId_t co
|
||||
|
||||
void ActionHelper::setQueueToUse(MessageQueueIF* queue) { queueToUse = queue; }
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId,
|
||||
store_address_t dataAddress) {
|
||||
const uint8_t* dataPtr = NULL;
|
||||
const uint8_t* dataPtr = nullptr;
|
||||
size_t size = 0;
|
||||
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
CommandMessage reply;
|
||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
ipcStore->deleteData(dataAddress);
|
||||
return;
|
||||
}
|
||||
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
|
||||
auto actionIter = actionMap.find(actionId);
|
||||
if (actionIter == actionMap.end()){
|
||||
CommandMessage reply;
|
||||
ActionMessage::setStepReply(&reply, actionId, 0, HasActionsIF::INVALID_ACTION_ID);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
ipcStore->deleteData(dataAddress);
|
||||
return;
|
||||
}
|
||||
Action* action = actionIter->second;
|
||||
result = action->deSerialize(&dataPtr, &size, SerializeIF::Endianness::NETWORK);
|
||||
if ((result != HasReturnvaluesIF::RETURN_OK) || (size != 0)){ //TODO write unittest for second condition
|
||||
CommandMessage reply;
|
||||
ActionMessage::setStepReply(&reply, actionId, 0, HasActionsIF::INVALID_PARAMETERS);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
ipcStore->deleteData(dataAddress);
|
||||
return;
|
||||
}
|
||||
//TODO call action->check()
|
||||
action->commandedBy = commandedBy;
|
||||
result = owner->executeAction(action);
|
||||
ipcStore->deleteData(dataAddress);
|
||||
if (result == HasActionsIF::EXECUTION_FINISHED) {
|
||||
CommandMessage reply;
|
||||
@@ -163,3 +185,11 @@ ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo, ActionId_t rep
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void ActionHelper::registerAction(Action* action) {
|
||||
//TODO error handling
|
||||
ActionId_t id = action->getId();
|
||||
actionMap.emplace(id, action);
|
||||
}
|
||||
|
||||
std::map<ActionId_t, Action*> const* ActionHelper::getActionMap() { return &actionMap; }
|
||||
@@ -1,9 +1,13 @@
|
||||
#ifndef FSFW_ACTION_ACTIONHELPER_H_
|
||||
#define FSFW_ACTION_ACTIONHELPER_H_
|
||||
|
||||
#include "../ipc/MessageQueueIF.h"
|
||||
#include "../serialize/SerializeIF.h"
|
||||
#include <map>
|
||||
|
||||
#include "Action.h"
|
||||
#include "ActionMessage.h"
|
||||
#include "fsfw/ipc/MessageQueueIF.h"
|
||||
#include "fsfw/serialize/SerializeIF.h"
|
||||
|
||||
/**
|
||||
* @brief Action Helper is a helper class which handles action messages
|
||||
*
|
||||
@@ -98,6 +102,10 @@ class ActionHelper {
|
||||
*/
|
||||
void setQueueToUse(MessageQueueIF* queue);
|
||||
|
||||
void registerAction(Action* action);
|
||||
|
||||
std::map<ActionId_t, Action*> const* getActionMap();
|
||||
|
||||
protected:
|
||||
//! Increase of value of this per step
|
||||
static const uint8_t STEP_OFFSET = 1;
|
||||
@@ -108,6 +116,8 @@ class ActionHelper {
|
||||
MessageQueueIF* queueToUse;
|
||||
//! Pointer to an IPC Store, initialized during construction or
|
||||
StorageManagerIF* ipcStore = nullptr;
|
||||
//! Map of all implemented Actions
|
||||
std::map<ActionId_t, Action*> actionMap;
|
||||
|
||||
/**
|
||||
* Internal function called by handleActionMessage
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
#include "fsfw/objectmanager/ObjectManager.h"
|
||||
#include "fsfw/storagemanager/StorageManagerIF.h"
|
||||
|
||||
ActionMessage::ActionMessage() {}
|
||||
ActionMessage::ActionMessage() = default;
|
||||
|
||||
ActionMessage::~ActionMessage() {}
|
||||
ActionMessage::~ActionMessage() = default;
|
||||
|
||||
void ActionMessage::setCommand(CommandMessage* message, ActionId_t fid,
|
||||
store_address_t parameters) {
|
||||
@@ -64,9 +64,8 @@ void ActionMessage::clear(CommandMessage* message) {
|
||||
switch (message->getCommand()) {
|
||||
case EXECUTE_ACTION:
|
||||
case DATA_REPLY: {
|
||||
StorageManagerIF* ipcStore =
|
||||
ObjectManager::instance()->get<StorageManagerIF>(objects::IPC_STORE);
|
||||
if (ipcStore != NULL) {
|
||||
auto* ipcStore = ObjectManager::instance()->get<StorageManagerIF>(objects::IPC_STORE);
|
||||
if (ipcStore != nullptr) {
|
||||
ipcStore->deleteData(getStoreId(message));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
target_sources(
|
||||
${LIB_FSFW_NAME} PRIVATE ActionHelper.cpp ActionMessage.cpp
|
||||
${LIB_FSFW_NAME} PRIVATE Action.cpp ActionHelper.cpp ActionMessage.cpp
|
||||
CommandActionHelper.cpp SimpleActionHelper.cpp)
|
||||
@@ -2,14 +2,14 @@
|
||||
#include "fsfw/objectmanager/ObjectManager.h"
|
||||
|
||||
CommandActionHelper::CommandActionHelper(CommandsActionsIF *setOwner)
|
||||
: owner(setOwner), queueToUse(NULL), ipcStore(NULL), commandCount(0), lastTarget(0) {}
|
||||
: owner(setOwner), queueToUse(nullptr), ipcStore(nullptr), commandCount(0), lastTarget(0) {}
|
||||
|
||||
CommandActionHelper::~CommandActionHelper() {}
|
||||
CommandActionHelper::~CommandActionHelper() = default;
|
||||
|
||||
ReturnValue_t CommandActionHelper::commandAction(object_id_t commandTo, ActionId_t actionId,
|
||||
SerializeIF *data) {
|
||||
HasActionsIF *receiver = ObjectManager::instance()->get<HasActionsIF>(commandTo);
|
||||
if (receiver == NULL) {
|
||||
auto *receiver = ObjectManager::instance()->get<HasActionsIF>(commandTo);
|
||||
if (receiver == nullptr) {
|
||||
return CommandsActionsIF::OBJECT_HAS_NO_FUNCTIONS;
|
||||
}
|
||||
store_address_t storeId;
|
||||
@@ -29,11 +29,8 @@ ReturnValue_t CommandActionHelper::commandAction(object_id_t commandTo, ActionId
|
||||
|
||||
ReturnValue_t CommandActionHelper::commandAction(object_id_t commandTo, ActionId_t actionId,
|
||||
const uint8_t *data, uint32_t size) {
|
||||
// if (commandCount != 0) {
|
||||
// return CommandsFunctionsIF::ALREADY_COMMANDING;
|
||||
// }
|
||||
HasActionsIF *receiver = ObjectManager::instance()->get<HasActionsIF>(commandTo);
|
||||
if (receiver == NULL) {
|
||||
auto *receiver = ObjectManager::instance()->get<HasActionsIF>(commandTo);
|
||||
if (receiver == nullptr) {
|
||||
return CommandsActionsIF::OBJECT_HAS_NO_FUNCTIONS;
|
||||
}
|
||||
store_address_t storeId;
|
||||
@@ -59,12 +56,12 @@ ReturnValue_t CommandActionHelper::sendCommand(MessageQueueId_t queueId, ActionI
|
||||
|
||||
ReturnValue_t CommandActionHelper::initialize() {
|
||||
ipcStore = ObjectManager::instance()->get<StorageManagerIF>(objects::IPC_STORE);
|
||||
if (ipcStore == NULL) {
|
||||
if (ipcStore == nullptr) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
queueToUse = owner->getCommandQueuePtr();
|
||||
if (queueToUse == NULL) {
|
||||
if (queueToUse == nullptr) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
@@ -104,7 +101,7 @@ ReturnValue_t CommandActionHelper::handleReply(CommandMessage *reply) {
|
||||
uint8_t CommandActionHelper::getCommandCount() const { return commandCount; }
|
||||
|
||||
void CommandActionHelper::extractDataForOwner(ActionId_t actionId, store_address_t storeId) {
|
||||
const uint8_t *data = NULL;
|
||||
const uint8_t *data = nullptr;
|
||||
size_t size = 0;
|
||||
ReturnValue_t result = ipcStore->getData(storeId, &data, &size);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
|
||||
@@ -14,14 +14,14 @@ class CommandActionHelper {
|
||||
friend class CommandsActionsIF;
|
||||
|
||||
public:
|
||||
CommandActionHelper(CommandsActionsIF* owner);
|
||||
explicit CommandActionHelper(CommandsActionsIF* owner);
|
||||
virtual ~CommandActionHelper();
|
||||
ReturnValue_t commandAction(object_id_t commandTo, ActionId_t actionId,
|
||||
const uint8_t* data = nullptr, uint32_t size = 0);
|
||||
ReturnValue_t commandAction(object_id_t commandTo, ActionId_t actionId, SerializeIF* data);
|
||||
ReturnValue_t initialize();
|
||||
ReturnValue_t handleReply(CommandMessage* reply);
|
||||
uint8_t getCommandCount() const;
|
||||
[[nodiscard]] uint8_t getCommandCount() const;
|
||||
|
||||
private:
|
||||
CommandsActionsIF* owner;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#ifndef FSFW_ACTION_COMMANDSACTIONSIF_H_
|
||||
#define FSFW_ACTION_COMMANDSACTIONSIF_H_
|
||||
|
||||
#include "../ipc/MessageQueueIF.h"
|
||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||
#include "CommandActionHelper.h"
|
||||
#include "fsfw/ipc/MessageQueueIF.h"
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
|
||||
/**
|
||||
* Interface to separate commanding actions of other objects.
|
||||
@@ -21,7 +21,7 @@ class CommandsActionsIF {
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::COMMANDS_ACTIONS_IF;
|
||||
static const ReturnValue_t OBJECT_HAS_NO_FUNCTIONS = MAKE_RETURN_CODE(1);
|
||||
static const ReturnValue_t ALREADY_COMMANDING = MAKE_RETURN_CODE(2);
|
||||
virtual ~CommandsActionsIF() {}
|
||||
virtual ~CommandsActionsIF() = default;
|
||||
virtual MessageQueueIF* getCommandQueuePtr() = 0;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#ifndef FSFW_ACTION_HASACTIONSIF_H_
|
||||
#define FSFW_ACTION_HASACTIONSIF_H_
|
||||
|
||||
#include "../ipc/MessageQueueIF.h"
|
||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||
#include "ActionHelper.h"
|
||||
#include "ActionMessage.h"
|
||||
#include "SimpleActionHelper.h"
|
||||
#include "fsfw/ipc/MessageQueueIF.h"
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
|
||||
/**
|
||||
* @brief
|
||||
@@ -40,12 +40,16 @@ class HasActionsIF {
|
||||
static const ReturnValue_t INVALID_PARAMETERS = MAKE_RETURN_CODE(2);
|
||||
static const ReturnValue_t EXECUTION_FINISHED = MAKE_RETURN_CODE(3);
|
||||
static const ReturnValue_t INVALID_ACTION_ID = MAKE_RETURN_CODE(4);
|
||||
virtual ~HasActionsIF() {}
|
||||
virtual ~HasActionsIF() = default;
|
||||
/**
|
||||
* Function to get the MessageQueueId_t of the implementing object
|
||||
* @return MessageQueueId_t of the object
|
||||
*
|
||||
*/
|
||||
virtual MessageQueueId_t getCommandQueue() const = 0;
|
||||
[[nodiscard]] virtual MessageQueueId_t getCommandQueue() const = 0;
|
||||
|
||||
[[nodiscard]] virtual ActionHelper* getActionHelper() = 0;
|
||||
|
||||
/**
|
||||
* Execute or initialize the execution of a certain function.
|
||||
* The ActionHelpers will execute this function and behave differently
|
||||
@@ -55,8 +59,7 @@ class HasActionsIF {
|
||||
* -@c EXECUTION_FINISHED Finish reply will be generated
|
||||
* -@c Not RETURN_OK Step failure reply will be generated
|
||||
*/
|
||||
virtual ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
|
||||
const uint8_t* data, size_t size) = 0;
|
||||
virtual ReturnValue_t executeAction(Action* action) = 0;
|
||||
};
|
||||
|
||||
#endif /* FSFW_ACTION_HASACTIONSIF_H_ */
|
||||
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include "Parameter.h"
|
||||
|
||||
template <typename T>
|
||||
class MinMaxParameter : public Parameter<T> {
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
private:
|
||||
MinMaxParameter(Action *owner, const char *name, T min, T max)
|
||||
: Parameter<T>(owner, name), min(min), max(max) {}
|
||||
|
||||
public:
|
||||
static MinMaxParameter createMinMaxParameter(Action *owner, const char *name, T min, T max) {
|
||||
return MinMaxParameter(owner, name, min, max);
|
||||
}
|
||||
virtual double getMinFloating() override { return static_cast<double>(min); }
|
||||
virtual int64_t getMinSigned() override { return static_cast<int64_t>(min); }
|
||||
|
||||
virtual double getMaxFloating() override { return static_cast<double>(max); }
|
||||
virtual int64_t getMaxSigned() override { return static_cast<int64_t>(max); }
|
||||
|
||||
#else
|
||||
private:
|
||||
MinMaxParameter(Action *owner, T min, T max) : Parameter<T>(owner), min(min), max(max) {}
|
||||
|
||||
public:
|
||||
static MinMaxParameter createMinMaxParameter(Action *owner, T min, T max) {
|
||||
return MinMaxParameter(owner, min, max);
|
||||
}
|
||||
#endif
|
||||
private:
|
||||
T min;
|
||||
T max;
|
||||
};
|
||||
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
#define createMinMaxParameter(p1, p2, p3, p4) createMinMaxParameter(p1, p2, p3, p4)
|
||||
#else
|
||||
#define createMinMaxParameter(p1, p2, p3, p4) createMinMaxParameter(p1, p3, p4)
|
||||
#endif
|
||||
@@ -0,0 +1,117 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "Action.h"
|
||||
#include <fsfw/introspection/Types.h>
|
||||
#include <fsfw/introspection/TypesHelper.h>
|
||||
#include "ParameterIF.h"
|
||||
// TODO: ifdef introspection stuff
|
||||
|
||||
|
||||
|
||||
template <typename T>
|
||||
class Parameter : public ParameterIF {
|
||||
protected:
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
Parameter(Action *owner, const char *name)
|
||||
: name(name)
|
||||
#else
|
||||
Parameter(Action *owner)
|
||||
#endif
|
||||
{
|
||||
owner->registerParameter(this);
|
||||
}
|
||||
|
||||
public:
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
static Parameter createParameter(Action *owner, const char *name) {
|
||||
return Parameter(owner, name);
|
||||
}
|
||||
#else
|
||||
static Parameter createParameter(Action *owner) { return Parameter(owner); }
|
||||
#endif
|
||||
|
||||
bool isValid() override {
|
||||
return enumHelper<std::is_base_of<EnumIF, T>::value>::isValid(&value);
|
||||
}
|
||||
|
||||
operator T(){
|
||||
return value;
|
||||
}
|
||||
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
Types::ParameterType getType() override {
|
||||
return enumHelper<std::is_base_of<EnumIF, T>::value>::template getType<T>();
|
||||
}
|
||||
#endif
|
||||
|
||||
T value;
|
||||
|
||||
ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||
Endianness streamEndianness) const override {
|
||||
return SerializeAdapter::serialize(&value, buffer, size, maxSize, streamEndianness);
|
||||
}
|
||||
|
||||
size_t getSerializedSize() const override { return SerializeAdapter::getSerializedSize(&value); }
|
||||
|
||||
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
|
||||
Endianness streamEndianness) override {
|
||||
return SerializeAdapter::deSerialize(&value, buffer, size, streamEndianness);
|
||||
}
|
||||
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
double getFloating() override { return (double)value; }
|
||||
int64_t getSigned() override { return (int64_t)value; }
|
||||
|
||||
bool setFloating(double value) override {
|
||||
if (getType() != Types::FLOATING) {
|
||||
puts("fups");
|
||||
return false;
|
||||
}
|
||||
this->value = T(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool setSigned(int64_t value) override {
|
||||
if ((getType() != Types::SIGNED) && (getType() != Types::ENUM)) {
|
||||
puts("sups");
|
||||
return false;
|
||||
}
|
||||
this->value = T(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
double getMinFloating() override {
|
||||
return enumHelper<std::is_base_of<EnumIF, T>::value>::template getMin<T>();
|
||||
}
|
||||
int64_t getMinSigned() override {
|
||||
return enumHelper<std::is_base_of<EnumIF, T>::value>::template getMin<T>();
|
||||
}
|
||||
|
||||
double getMaxFloating() override {
|
||||
return enumHelper<std::is_base_of<EnumIF, T>::value>::template getMax<T>();
|
||||
}
|
||||
int64_t getMaxSigned() override {
|
||||
return enumHelper<std::is_base_of<EnumIF, T>::value>::template getMax<T>();
|
||||
}
|
||||
|
||||
std::vector<int64_t> getEnumValues() override {
|
||||
return enumHelper<std::is_base_of<EnumIF, T>::value>::getEnumValues(&value);
|
||||
}
|
||||
const char *const *getEnumDescriptions() override {
|
||||
return enumHelper<std::is_base_of<EnumIF, T>::value>::getEnumDescriptions(&value);
|
||||
}
|
||||
|
||||
const char *getName() override { return name; }
|
||||
|
||||
private:
|
||||
const char *name;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
#define createParameter(p1, p2) createParameter(p1, p2)
|
||||
#else
|
||||
#define createParameter(p1, p2) createParameter(p1)
|
||||
#endif
|
||||
@@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include <fsfw/serialize/SerializeIF.h>
|
||||
#include <fsfw/introspection/Types.h>
|
||||
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
#include <vector>
|
||||
#endif
|
||||
|
||||
class ParameterIF : public SerializeIF {
|
||||
public:
|
||||
virtual bool isValid() = 0;
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
|
||||
|
||||
|
||||
virtual const char *getName() = 0;
|
||||
|
||||
virtual Types::ParameterType getType() = 0;
|
||||
|
||||
virtual double getFloating() = 0;
|
||||
virtual int64_t getSigned() = 0;
|
||||
|
||||
virtual bool setFloating(double value) = 0;
|
||||
virtual bool setSigned(int64_t value) = 0;
|
||||
|
||||
virtual double getMinFloating() = 0;
|
||||
virtual int64_t getMinSigned() = 0;
|
||||
|
||||
virtual double getMaxFloating() = 0;
|
||||
virtual int64_t getMaxSigned() = 0;
|
||||
|
||||
virtual std::vector<int64_t> getEnumValues() = 0;
|
||||
virtual const char *const * getEnumDescriptions() = 0;
|
||||
|
||||
// ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||
// Endianness streamEndianness) const override = 0;
|
||||
|
||||
// size_t getSerializedSize() const override = 0;
|
||||
|
||||
// ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
|
||||
// Endianness streamEndianness) override = 0;
|
||||
|
||||
#endif
|
||||
};
|
||||
@@ -3,7 +3,7 @@
|
||||
SimpleActionHelper::SimpleActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue)
|
||||
: ActionHelper(setOwner, useThisQueue), isExecuting(false) {}
|
||||
|
||||
SimpleActionHelper::~SimpleActionHelper() {}
|
||||
SimpleActionHelper::~SimpleActionHelper() = default;
|
||||
|
||||
void SimpleActionHelper::step(ReturnValue_t result) {
|
||||
// STEP_OFFESET is subtracted to compensate for adding offset in base
|
||||
@@ -38,17 +38,33 @@ void SimpleActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId
|
||||
ActionMessage::setStepReply(&reply, actionId, 0, HasActionsIF::IS_BUSY);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
}
|
||||
const uint8_t* dataPtr = NULL;
|
||||
const uint8_t* dataPtr = nullptr;
|
||||
size_t size = 0;
|
||||
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
ipcStore->deleteData(dataAddress);
|
||||
return;
|
||||
}
|
||||
lastCommander = commandedBy;
|
||||
lastAction = actionId;
|
||||
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
|
||||
auto actionIter = actionMap.find(actionId);
|
||||
if (actionIter == actionMap.end()){
|
||||
CommandMessage reply;
|
||||
ActionMessage::setStepReply(&reply, actionId, 0, HasActionsIF::INVALID_ACTION_ID);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
ipcStore->deleteData(dataAddress);
|
||||
return;
|
||||
}
|
||||
Action* action = actionIter->second;
|
||||
result = action->deSerialize(&dataPtr, &size, SerializeIF::Endianness::NETWORK);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK){
|
||||
CommandMessage reply;
|
||||
ActionMessage::setStepReply(&reply, actionId, 0, HasActionsIF::INVALID_PARAMETERS);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
ipcStore->deleteData(dataAddress);
|
||||
return;
|
||||
}
|
||||
result = action->handle();
|
||||
ipcStore->deleteData(dataAddress);
|
||||
switch (result) {
|
||||
case HasReturnvaluesIF::RETURN_OK:
|
||||
|
||||
@@ -11,15 +11,15 @@
|
||||
class SimpleActionHelper : public ActionHelper {
|
||||
public:
|
||||
SimpleActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue);
|
||||
virtual ~SimpleActionHelper();
|
||||
~SimpleActionHelper() override;
|
||||
void step(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||
void finish(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||
ReturnValue_t reportData(SerializeIF* data);
|
||||
|
||||
protected:
|
||||
void prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId,
|
||||
store_address_t dataAddress);
|
||||
virtual void resetHelper();
|
||||
store_address_t dataAddress) override;
|
||||
void resetHelper() override;
|
||||
|
||||
private:
|
||||
bool isExecuting;
|
||||
@@ -28,4 +28,4 @@ class SimpleActionHelper : public ActionHelper {
|
||||
uint8_t stepCount = 0;
|
||||
};
|
||||
|
||||
#endif /* SIMPLEACTIONHELPER_H_ */
|
||||
#endif /* FSFW_ACTION_SIMPLEACTIONHELPER_H_ */
|
||||
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include "Action.h"
|
||||
|
||||
template <class owner, class action, class ActionEnum>
|
||||
class TemplateAction : public Action {
|
||||
public:
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
TemplateAction(owner *myOwner, ActionEnum id) : Action(), myOwner(myOwner) {
|
||||
Action::setEnum(&id);
|
||||
myOwner->getActionHelper()->registerAction(this);
|
||||
}
|
||||
#else
|
||||
TemplateAction(owner *myOwner, ActionEnum id) : Action((uint32_t) id), myOwner(myOwner) {
|
||||
myOwner->getActionHelper()->registerAction(this);
|
||||
}
|
||||
#endif
|
||||
|
||||
ReturnValue_t handle() override { return myOwner->handleAction(dynamic_cast<action *>(this)); }
|
||||
|
||||
private:
|
||||
owner *myOwner;
|
||||
};
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "fsfw/FSFW.h"
|
||||
#include "fsfw/serviceinterface.h"
|
||||
|
||||
SimpleRingBuffer::SimpleRingBuffer(const size_t size, bool overwriteOld, size_t maxExcessBytes)
|
||||
: RingBufferBase<>(0, size, overwriteOld), maxExcessBytes(maxExcessBytes) {
|
||||
if (maxExcessBytes > size) {
|
||||
@@ -48,6 +51,19 @@ void SimpleRingBuffer::confirmBytesWritten(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) {
|
||||
size_t amountTillWrap = writeTillWrap();
|
||||
if (amountTillWrap >= amount) {
|
||||
|
||||
@@ -28,7 +28,7 @@ ReturnValue_t ControllerBase::initialize() {
|
||||
|
||||
MessageQueueId_t parentQueue = 0;
|
||||
if (parentId != objects::NO_OBJECT) {
|
||||
SubsystemBase* parent = ObjectManager::instance()->get<SubsystemBase>(parentId);
|
||||
auto* parent = ObjectManager::instance()->get<SubsystemBase>(parentId);
|
||||
if (parent == nullptr) {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
@@ -54,7 +54,7 @@ MessageQueueId_t ControllerBase::getCommandQueue() const { return commandQueue->
|
||||
|
||||
void ControllerBase::handleQueue() {
|
||||
CommandMessage command;
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
ReturnValue_t result;
|
||||
for (result = commandQueue->receiveMessage(&command); result == RETURN_OK;
|
||||
result = commandQueue->receiveMessage(&command)) {
|
||||
result = modeHelper.handleModeCommand(&command);
|
||||
@@ -75,20 +75,20 @@ void ControllerBase::handleQueue() {
|
||||
}
|
||||
}
|
||||
|
||||
void ControllerBase::startTransition(Mode_t mode, Submode_t submode) {
|
||||
void ControllerBase::startTransition(Mode_t mode_, Submode_t submode_) {
|
||||
changeHK(this->mode, this->submode, false);
|
||||
triggerEvent(CHANGING_MODE, mode, submode);
|
||||
this->mode = mode;
|
||||
this->submode = submode;
|
||||
mode = mode_;
|
||||
submode = submode_;
|
||||
modeHelper.modeChanged(mode, submode);
|
||||
modeChanged(mode, submode);
|
||||
announceMode(false);
|
||||
changeHK(this->mode, this->submode, true);
|
||||
}
|
||||
|
||||
void ControllerBase::getMode(Mode_t* mode, Submode_t* submode) {
|
||||
*mode = this->mode;
|
||||
*submode = this->submode;
|
||||
void ControllerBase::getMode(Mode_t* mode_, Submode_t* submode_) {
|
||||
*mode_ = this->mode;
|
||||
*submode_ = this->submode;
|
||||
}
|
||||
|
||||
void ControllerBase::setToExternalControl() { healthHelper.setHealth(EXTERNAL_CONTROL); }
|
||||
@@ -101,7 +101,7 @@ ReturnValue_t ControllerBase::performOperation(uint8_t opCode) {
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
void ControllerBase::modeChanged(Mode_t mode, Submode_t submode) { return; }
|
||||
void ControllerBase::modeChanged(Mode_t mode_, Submode_t submode_) {}
|
||||
|
||||
ReturnValue_t ControllerBase::setHealth(HealthState health) {
|
||||
switch (health) {
|
||||
@@ -117,6 +117,6 @@ ReturnValue_t ControllerBase::setHealth(HealthState health) {
|
||||
HasHealthIF::HealthState ControllerBase::getHealth() { return healthHelper.getHealth(); }
|
||||
void ControllerBase::setTaskIF(PeriodicTaskIF* task_) { executingTask = task_; }
|
||||
|
||||
void ControllerBase::changeHK(Mode_t mode, Submode_t submode, bool enable) {}
|
||||
void ControllerBase::changeHK(Mode_t mode_, Submode_t submode_, bool enable) {}
|
||||
|
||||
ReturnValue_t ControllerBase::initializeAfterTaskCreation() { return HasReturnvaluesIF::RETURN_OK; }
|
||||
@@ -24,21 +24,21 @@ class ControllerBase : public HasModesIF,
|
||||
static const Mode_t MODE_NORMAL = 2;
|
||||
|
||||
ControllerBase(object_id_t setObjectId, object_id_t parentId, size_t commandQueueDepth = 3);
|
||||
virtual ~ControllerBase();
|
||||
~ControllerBase() override;
|
||||
|
||||
/** SystemObject override */
|
||||
virtual ReturnValue_t initialize() override;
|
||||
ReturnValue_t initialize() override;
|
||||
|
||||
virtual MessageQueueId_t getCommandQueue() const override;
|
||||
[[nodiscard]] MessageQueueId_t getCommandQueue() const override;
|
||||
|
||||
/** HasHealthIF overrides */
|
||||
virtual ReturnValue_t setHealth(HealthState health) override;
|
||||
virtual HasHealthIF::HealthState getHealth() override;
|
||||
ReturnValue_t setHealth(HealthState health) override;
|
||||
HasHealthIF::HealthState getHealth() override;
|
||||
|
||||
/** ExecutableObjectIF overrides */
|
||||
virtual ReturnValue_t performOperation(uint8_t opCode) override;
|
||||
virtual void setTaskIF(PeriodicTaskIF *task) override;
|
||||
virtual ReturnValue_t initializeAfterTaskCreation() override;
|
||||
ReturnValue_t performOperation(uint8_t opCode) override;
|
||||
void setTaskIF(PeriodicTaskIF *task) override;
|
||||
ReturnValue_t initializeAfterTaskCreation() override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
@@ -54,8 +54,8 @@ class ControllerBase : public HasModesIF,
|
||||
*/
|
||||
virtual void performControlOperation() = 0;
|
||||
|
||||
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
||||
uint32_t *msToReachTheMode) override = 0;
|
||||
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
||||
uint32_t *msToReachTheMode) override = 0;
|
||||
|
||||
const object_id_t parentId;
|
||||
|
||||
@@ -80,10 +80,10 @@ class ControllerBase : public HasModesIF,
|
||||
|
||||
/** Mode helpers */
|
||||
virtual void modeChanged(Mode_t mode, Submode_t submode);
|
||||
virtual void startTransition(Mode_t mode, Submode_t submode) override;
|
||||
virtual void getMode(Mode_t *mode, Submode_t *submode) override;
|
||||
virtual void setToExternalControl() override;
|
||||
virtual void announceMode(bool recursive);
|
||||
void startTransition(Mode_t mode, Submode_t submode) override;
|
||||
void getMode(Mode_t *mode, Submode_t *submode) override;
|
||||
void setToExternalControl() override;
|
||||
void announceMode(bool recursive) override;
|
||||
/** HK helpers */
|
||||
virtual void changeHK(Mode_t mode, Submode_t submode, bool enable);
|
||||
};
|
||||
|
||||
@@ -6,13 +6,14 @@ ExtendedControllerBase::ExtendedControllerBase(object_id_t objectId, object_id_t
|
||||
poolManager(this, commandQueue),
|
||||
actionHelper(this, commandQueue) {}
|
||||
|
||||
ExtendedControllerBase::~ExtendedControllerBase() {}
|
||||
ExtendedControllerBase::~ExtendedControllerBase() = default;
|
||||
|
||||
ReturnValue_t ExtendedControllerBase::executeAction(ActionId_t actionId,
|
||||
MessageQueueId_t commandedBy,
|
||||
const uint8_t *data, size_t size) {
|
||||
/* Needs to be overriden and implemented by child class. */
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
ActionHelper *ExtendedControllerBase::getActionHelper() {
|
||||
return &actionHelper;
|
||||
}
|
||||
|
||||
ReturnValue_t ExtendedControllerBase::executeAction(Action *action) {
|
||||
return action->handle();
|
||||
}
|
||||
|
||||
object_id_t ExtendedControllerBase::getObjectId() const { return SystemObject::getObjectId(); }
|
||||
@@ -31,7 +32,7 @@ ReturnValue_t ExtendedControllerBase::handleCommandMessage(CommandMessage *messa
|
||||
|
||||
void ExtendedControllerBase::handleQueue() {
|
||||
CommandMessage command;
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
ReturnValue_t result;
|
||||
for (result = commandQueue->receiveMessage(&command); result == RETURN_OK;
|
||||
result = commandQueue->receiveMessage(&command)) {
|
||||
result = actionHelper.handleActionMessage(&command);
|
||||
|
||||
@@ -18,16 +18,20 @@ class ExtendedControllerBase : public ControllerBase,
|
||||
public HasLocalDataPoolIF {
|
||||
public:
|
||||
ExtendedControllerBase(object_id_t objectId, object_id_t parentId, size_t commandQueueDepth = 3);
|
||||
virtual ~ExtendedControllerBase();
|
||||
~ExtendedControllerBase() override;
|
||||
|
||||
/* SystemObjectIF overrides */
|
||||
virtual ReturnValue_t initialize() override;
|
||||
ReturnValue_t initialize() override;
|
||||
|
||||
virtual MessageQueueId_t getCommandQueue() const override;
|
||||
[[nodiscard]] MessageQueueId_t getCommandQueue() const override;
|
||||
|
||||
/* ExecutableObjectIF overrides */
|
||||
virtual ReturnValue_t performOperation(uint8_t opCode) override;
|
||||
virtual ReturnValue_t initializeAfterTaskCreation() override;
|
||||
ReturnValue_t performOperation(uint8_t opCode) override;
|
||||
ReturnValue_t initializeAfterTaskCreation() override;
|
||||
|
||||
/* HasActionsIF overrides */
|
||||
ActionHelper* getActionHelper() override;
|
||||
ReturnValue_t executeAction(Action* actionId) override;
|
||||
|
||||
protected:
|
||||
LocalDataPoolManager poolManager;
|
||||
@@ -39,32 +43,28 @@ class ExtendedControllerBase : public ControllerBase,
|
||||
* @param message
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t handleCommandMessage(CommandMessage* message) = 0;
|
||||
ReturnValue_t handleCommandMessage(CommandMessage* message) override = 0;
|
||||
|
||||
/**
|
||||
* Periodic helper from ControllerBase, implemented by child class.
|
||||
*/
|
||||
virtual void performControlOperation() = 0;
|
||||
void performControlOperation() override = 0;
|
||||
|
||||
/* Handle the four messages mentioned above */
|
||||
void handleQueue() override;
|
||||
|
||||
/* HasActionsIF overrides */
|
||||
virtual ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
|
||||
const uint8_t* data, size_t size) override;
|
||||
|
||||
/* HasLocalDatapoolIF overrides */
|
||||
virtual LocalDataPoolManager* getHkManagerHandle() override;
|
||||
virtual object_id_t getObjectId() const override;
|
||||
virtual uint32_t getPeriodicOperationFrequency() const override;
|
||||
LocalDataPoolManager* getHkManagerHandle() override;
|
||||
[[nodiscard]] object_id_t getObjectId() const override;
|
||||
[[nodiscard]] uint32_t getPeriodicOperationFrequency() const override;
|
||||
|
||||
virtual ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
||||
LocalDataPoolManager& poolManager) override = 0;
|
||||
virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override = 0;
|
||||
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
||||
LocalDataPoolManager& poolManager) override = 0;
|
||||
LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override = 0;
|
||||
|
||||
// Mode abstract functions
|
||||
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
||||
uint32_t* msToReachTheMode) override = 0;
|
||||
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
||||
uint32_t* msToReachTheMode) override = 0;
|
||||
};
|
||||
|
||||
#endif /* FSFW_CONTROLLER_EXTENDEDCONTROLLERBASE_H_ */
|
||||
@@ -700,7 +700,8 @@ void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver& receiver) {
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
/* Configuration error */
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "LocalDataPoolManager::performPeriodicHkOperation: HK generation failed." << std::endl;
|
||||
sif::warning << "LocalDataPoolManager::performPeriodicHkOperation: HK generation failed."
|
||||
<< std::endl;
|
||||
#else
|
||||
sif::printWarning("LocalDataPoolManager::performPeriodicHkOperation: HK generation failed.\n");
|
||||
#endif
|
||||
|
||||
@@ -63,7 +63,9 @@ void DeviceHandlerBase::setThermalStateRequestPoolIds(lp_id_t thermalStatePoolId
|
||||
}
|
||||
|
||||
DeviceHandlerBase::~DeviceHandlerBase() {
|
||||
delete comCookie;
|
||||
if (comCookie != nullptr) {
|
||||
delete comCookie;
|
||||
}
|
||||
if (defaultFDIRUsed) {
|
||||
delete fdirInstance;
|
||||
}
|
||||
@@ -247,15 +249,14 @@ void DeviceHandlerBase::decrementDeviceReplyMap() {
|
||||
for (std::pair<const DeviceCommandId_t, DeviceReplyInfo>& replyPair : deviceReplyMap) {
|
||||
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--;
|
||||
if (replyPair.second.delayCycles == 0) {
|
||||
if (replyPair.second.periodic) {
|
||||
replyPair.second.delayCycles = replyPair.second.maxDelayCycles;
|
||||
}
|
||||
resetDelayCyclesControlledReply(&replyPair.second);
|
||||
timedOut = true;
|
||||
}
|
||||
}
|
||||
@@ -263,7 +264,6 @@ void DeviceHandlerBase::decrementDeviceReplyMap() {
|
||||
replyToReply(replyPair.first, replyPair.second, TIMEOUT);
|
||||
missedReply(replyPair.first);
|
||||
timedOut = false;
|
||||
replyPair.second.active = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -451,9 +451,6 @@ ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId,
|
||||
info.dataSet = dataSet;
|
||||
info.command = deviceCommandMap.end();
|
||||
info.countdown = countdown;
|
||||
if (info.periodic) {
|
||||
info.active = true;
|
||||
}
|
||||
auto resultPair = deviceReplyMap.emplace(replyId, info);
|
||||
if (resultPair.second) {
|
||||
return RETURN_OK;
|
||||
@@ -526,9 +523,19 @@ ReturnValue_t DeviceHandlerBase::updatePeriodicReply(bool enable, DeviceCommandI
|
||||
return COMMAND_NOT_SUPPORTED;
|
||||
}
|
||||
if (enable) {
|
||||
info->delayCycles = info->maxDelayCycles;
|
||||
info->active = true;
|
||||
if (info->countdown != nullptr) {
|
||||
info->delayCycles = info->maxDelayCycles;
|
||||
} else {
|
||||
info->countdown->resetTimer();
|
||||
}
|
||||
} else {
|
||||
info->delayCycles = 0;
|
||||
info->active = false;
|
||||
if (info->countdown != nullptr) {
|
||||
info->delayCycles = 0;
|
||||
} else {
|
||||
info->countdown->timeOut();
|
||||
}
|
||||
}
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
@@ -846,9 +853,9 @@ void DeviceHandlerBase::handleReply(const uint8_t* receivedData, DeviceCommandId
|
||||
}
|
||||
|
||||
if (info->active && info->countdown != nullptr) {
|
||||
disableTimeoutControlledReply(info);
|
||||
resetTimeoutControlledReply(info);
|
||||
} else if (info->delayCycles != 0) {
|
||||
disableDelayCyclesControlledReply(info);
|
||||
resetDelayCyclesControlledReply(info);
|
||||
}
|
||||
|
||||
if (result != RETURN_OK) {
|
||||
@@ -867,7 +874,7 @@ void DeviceHandlerBase::handleReply(const uint8_t* receivedData, DeviceCommandId
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceHandlerBase::disableTimeoutControlledReply(DeviceReplyInfo* info) {
|
||||
void DeviceHandlerBase::resetTimeoutControlledReply(DeviceReplyInfo* info) {
|
||||
if (info->periodic) {
|
||||
info->countdown->resetTimer();
|
||||
} else {
|
||||
@@ -876,7 +883,7 @@ void DeviceHandlerBase::disableTimeoutControlledReply(DeviceReplyInfo* info) {
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceHandlerBase::disableDelayCyclesControlledReply(DeviceReplyInfo* info) {
|
||||
void DeviceHandlerBase::resetDelayCyclesControlledReply(DeviceReplyInfo* info) {
|
||||
if (info->periodic) {
|
||||
info->delayCycles = info->maxDelayCycles;
|
||||
} else {
|
||||
@@ -1007,6 +1014,8 @@ ReturnValue_t DeviceHandlerBase::enableReplyInReplyMap(DeviceCommandMap::iterato
|
||||
}
|
||||
if (iter != deviceReplyMap.end()) {
|
||||
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->command = command;
|
||||
command->second.expectedReplies = expectedReplies;
|
||||
@@ -1316,22 +1325,25 @@ void DeviceHandlerBase::handleDeviceTM(SerializeIF* dataSet, DeviceCommandId_t r
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t DeviceHandlerBase::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
|
||||
const uint8_t* data, size_t size) {
|
||||
ActionHelper *DeviceHandlerBase::getActionHelper() {
|
||||
return &actionHelper;
|
||||
}
|
||||
|
||||
ReturnValue_t DeviceHandlerBase::executeAction(Action *action) {
|
||||
ReturnValue_t result = acceptExternalDeviceCommands();
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
DeviceCommandMap::iterator iter = deviceCommandMap.find(actionId);
|
||||
DeviceCommandMap::iterator iter = deviceCommandMap.find(action->getId());
|
||||
if (iter == deviceCommandMap.end()) {
|
||||
result = COMMAND_NOT_SUPPORTED;
|
||||
} else if (iter->second.isExecuting) {
|
||||
result = COMMAND_ALREADY_SENT;
|
||||
} else {
|
||||
result = buildCommandFromCommand(actionId, data, size);
|
||||
result = action->handle();
|
||||
}
|
||||
if (result == RETURN_OK) {
|
||||
iter->second.sendReplyTo = commandedBy;
|
||||
iter->second.sendReplyTo = action->commandedBy;
|
||||
iter->second.isExecuting = true;
|
||||
cookieInfo.pendingCommand = iter;
|
||||
cookieInfo.state = COOKIE_WRITE_READY;
|
||||
@@ -1405,7 +1417,12 @@ uint8_t DeviceHandlerBase::getReplyDelayCycles(DeviceCommandId_t deviceCommand)
|
||||
if (iter == deviceReplyMap.end()) {
|
||||
return 0;
|
||||
} else if (iter->second.countdown != nullptr) {
|
||||
return 0;
|
||||
// fake a useful return value for legacy code
|
||||
if (iter->second.active) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return iter->second.delayCycles;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include "DeviceHandlerFailureIsolation.h"
|
||||
#include "DeviceHandlerIF.h"
|
||||
#include "DeviceHandlerThermalSet.h"
|
||||
#include "DhbCfgHelpers.h"
|
||||
#include "fsfw/action/ActionHelper.h"
|
||||
#include "fsfw/action/HasActionsIF.h"
|
||||
#include "fsfw/datapool/PoolVariableIF.h"
|
||||
@@ -205,9 +204,9 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
||||
*/
|
||||
virtual void setParentQueue(MessageQueueId_t parentQueueId);
|
||||
|
||||
/** @brief Implementation required for HasActionIF */
|
||||
ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
|
||||
const uint8_t *data, size_t size) override;
|
||||
/** @brief Implementations required for HasActionIF */
|
||||
ActionHelper* getActionHelper() override;
|
||||
ReturnValue_t executeAction(Action *action) override;
|
||||
|
||||
Mode_t getTransitionSourceMode() const;
|
||||
Submode_t getTransitionSourceSubMode() const;
|
||||
@@ -315,6 +314,8 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
||||
* - Anything else triggers an even with the returnvalue as a parameter
|
||||
*/
|
||||
virtual ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t *id) = 0;
|
||||
|
||||
//TODO Remove and update documentation
|
||||
/**
|
||||
* @brief Build a device command packet from data supplied by a direct
|
||||
* command (PUS Service 8)
|
||||
@@ -470,12 +471,21 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
||||
* @param maxDelayCycles The maximum number of delay cycles the reply waits
|
||||
* until it times out.
|
||||
* @param periodic Indicates if the command is periodic (i.e. it is sent
|
||||
<<<<<<< HEAD
|
||||
* 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
|
||||
* #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
|
||||
=======
|
||||
* 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
|
||||
* #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
|
||||
>>>>>>> upstream/development
|
||||
* @return - @c RETURN_OK when the command was successfully inserted,
|
||||
* - @c RETURN_FAILED else.
|
||||
*/
|
||||
@@ -489,9 +499,9 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
||||
* @return - @c RETURN_OK when the command was successfully inserted,
|
||||
* - @c RETURN_FAILED else.
|
||||
*/
|
||||
ReturnValue_t insertInCommandMap(
|
||||
DeviceCommandId_t deviceCommand, bool useAlternativeReply = false,
|
||||
DeviceCommandId_t alternativeReplyId = DeviceHandlerIF::NO_COMMAND_ID);
|
||||
ReturnValue_t insertInCommandMap(DeviceCommandId_t deviceCommand,
|
||||
bool useAlternativeReply = false,
|
||||
DeviceCommandId_t alternativeReplyId = 0);
|
||||
|
||||
/**
|
||||
* Enables a periodic reply for a given command. It sets to delay cycles to the specified
|
||||
@@ -1275,15 +1285,15 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
||||
void doGetRead(void);
|
||||
|
||||
/**
|
||||
* @brief Handles disabling of replies which use a timeout to detect missed replies.
|
||||
* @brief Resets replies which use a timeout to detect missed replies.
|
||||
*/
|
||||
void disableTimeoutControlledReply(DeviceReplyInfo *info);
|
||||
void resetTimeoutControlledReply(DeviceReplyInfo *info);
|
||||
|
||||
/**
|
||||
* @brief Handles disabling of replies which use a number of maximum delay cycles to detect
|
||||
* @brief Resets replies which use a number of maximum delay cycles to detect
|
||||
* missed replies.
|
||||
*/
|
||||
void disableDelayCyclesControlledReply(DeviceReplyInfo *info);
|
||||
void resetDelayCyclesControlledReply(DeviceReplyInfo *info);
|
||||
|
||||
/**
|
||||
* Retrive data from the #IPCStore.
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
#ifndef FSFW_SRC_FSFW_DEVICEHANDLERS_DHBCFGHELPERS_H_
|
||||
#define FSFW_SRC_FSFW_DEVICEHANDLERS_DHBCFGHELPERS_H_
|
||||
|
||||
/**
|
||||
* @brief This is the base class for configuration related to both DHB commands, replies and their
|
||||
* combination
|
||||
*/
|
||||
struct CfgBase {
|
||||
public:
|
||||
explicit CfgBase(DeviceCommandId_t cmdAndOrReplyId) : cmdAndOrReplyId(cmdAndOrReplyId){};
|
||||
DeviceCommandId_t cmdAndOrReplyId;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Configuration class for commands
|
||||
*/
|
||||
struct CmdCfg {
|
||||
public:
|
||||
explicit CmdCfg(DeviceCommandId_t cmdId) : baseCfg(cmdId){};
|
||||
|
||||
CfgBase baseCfg;
|
||||
//! This can be used if a command can trigger multiple replies
|
||||
std::pair<bool, DeviceCommandId_t> alternativeReply = {false, DeviceHandlerIF::NO_COMMAND_ID};
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Configuration class for replies
|
||||
*/
|
||||
struct ReplyCfg {
|
||||
public:
|
||||
ReplyCfg(DeviceCommandId_t replyId, uint16_t maxDelayCycles)
|
||||
: baseCfg(replyId), maxDelayCycles(maxDelayCycles){};
|
||||
ReplyCfg(DeviceCommandId_t replyId, uint16_t maxDelayCycles, LocalPoolDataSetBase* set)
|
||||
: ReplyCfg(replyId, maxDelayCycles) {
|
||||
dataSet = set;
|
||||
};
|
||||
|
||||
CfgBase baseCfg;
|
||||
//! A data set can be mapped to a reply ID. This allows to omit the #getDataSetHandle
|
||||
//! override in a user device handler as this pointer will be passed as long as the device
|
||||
//! command ID is equal to the set ID.
|
||||
LocalPoolDataSetBase* dataSet = nullptr;
|
||||
//! For Command-Reply combinations:
|
||||
//! The maximum number of cycles the handler should wait for a reply
|
||||
//! to this command.
|
||||
//!
|
||||
//! Reply Only:
|
||||
//! For periodic replies, this variable will be the number of delay cycles between the replies.
|
||||
//! For the non-periodic variant, this variable is not used as there is no meaningful
|
||||
//! definition for delay
|
||||
uint16_t maxDelayCycles = 0;
|
||||
//! First parameter: Specify whether reply is arriving periodically
|
||||
//! Second parameter: Specify whether periodic reply should be enabled immediately
|
||||
std::pair<bool, bool> periodicCfg = {false, false};
|
||||
//! If a reply needs to be requested with a specific length, the length can be specified here
|
||||
size_t replyLen = 0;
|
||||
//! It is also possible to use a time based instead of a cycle based mechanism to specify
|
||||
//! how long a reply takes. For non-periodic replies without a command, this variable is not used.
|
||||
Countdown* countdown = nullptr;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Configuration class for commands and replies
|
||||
*/
|
||||
struct CmdReplyCfg {
|
||||
public:
|
||||
CmdReplyCfg(CmdCfg cmdCfg, ReplyCfg replyCfg) : cmdCfg(cmdCfg), replyCfg(replyCfg) {}
|
||||
CmdCfg cmdCfg;
|
||||
ReplyCfg replyCfg;
|
||||
};
|
||||
|
||||
#endif /* FSFW_SRC_FSFW_DEVICEHANDLERS_DHBCFGHELPERS_H_ */
|
||||
@@ -100,6 +100,11 @@ ReturnValue_t EventManager::subscribeToEventRange(MessageQueueId_t listener, Eve
|
||||
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,
|
||||
EventId_t idTo, bool idInverted,
|
||||
object_id_t reporterFrom,
|
||||
|
||||
@@ -37,6 +37,7 @@ class EventManager : public EventManagerIF, public ExecutableObjectIF, public Sy
|
||||
EventId_t idTo = 0, bool idInverted = false,
|
||||
object_id_t reporterFrom = 0, object_id_t reporterTo = 0,
|
||||
bool reporterInverted = false);
|
||||
ReturnValue_t unsubscribeFromAllEvents(MessageQueueId_t listener, object_id_t object);
|
||||
ReturnValue_t unsubscribeFromEventRange(MessageQueueId_t listener, EventId_t idFrom = 0,
|
||||
EventId_t idTo = 0, bool idInverted = false,
|
||||
object_id_t reporterFrom = 0, object_id_t reporterTo = 0,
|
||||
|
||||
@@ -20,6 +20,7 @@ class EventManagerIF {
|
||||
bool forwardAllButSelected = false) = 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 unsubscribeFromAllEvents(MessageQueueId_t listener, object_id_t object) = 0;
|
||||
virtual ReturnValue_t subscribeToEventRange(MessageQueueId_t listener, EventId_t idFrom = 0,
|
||||
EventId_t idTo = 0, bool idInverted = false,
|
||||
object_id_t reporterFrom = 0,
|
||||
|
||||
@@ -15,6 +15,16 @@ FailureIsolationBase::FailureIsolationBase(object_id_t owner, object_id_t parent
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -60,14 +60,14 @@ ReturnValue_t FaultCounter::getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||
return INVALID_DOMAIN_ID;
|
||||
}
|
||||
|
||||
switch (uniqueId) {
|
||||
case 0:
|
||||
switch (static_cast<ParameterIds>(uniqueId)) {
|
||||
case ParameterIds::FAILURE_THRESHOLD:
|
||||
parameterWrapper->set(failureThreshold);
|
||||
break;
|
||||
case 1:
|
||||
case ParameterIds::FAULT_COUNT:
|
||||
parameterWrapper->set(faultCount);
|
||||
break;
|
||||
case 2:
|
||||
case ParameterIds::TIMEOUT:
|
||||
parameterWrapper->set(timer.timeout);
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
class FaultCounter : public HasParametersIF {
|
||||
public:
|
||||
enum class ParameterIds { FAILURE_THRESHOLD, FAULT_COUNT, TIMEOUT };
|
||||
|
||||
FaultCounter();
|
||||
FaultCounter(uint32_t failureThreshold, uint32_t decrementAfterMs,
|
||||
uint8_t setParameterDomain = 0);
|
||||
@@ -25,7 +27,8 @@ class FaultCounter : public HasParametersIF {
|
||||
|
||||
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||
ParameterWrapper *parameterWrapper,
|
||||
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
||||
const ParameterWrapper *newValues = nullptr,
|
||||
uint16_t startAtIndex = 0);
|
||||
|
||||
void setParameterDomain(uint8_t domain);
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
HealthHelper::HealthHelper(HasHealthIF* owner, object_id_t objectId)
|
||||
: objectId(objectId), owner(owner) {}
|
||||
|
||||
HealthHelper::~HealthHelper() {}
|
||||
HealthHelper::~HealthHelper() { healthTable->removeObject(objectId); }
|
||||
|
||||
ReturnValue_t HealthHelper::handleHealthCommand(CommandMessage* message) {
|
||||
switch (message->getCommand()) {
|
||||
|
||||
@@ -27,6 +27,15 @@ ReturnValue_t HealthTable::registerObject(object_id_t object,
|
||||
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) {
|
||||
MutexGuard(mutex, timeoutType, mutexTimeoutMs);
|
||||
HealthMap::iterator iter = healthMap.find(object);
|
||||
|
||||
@@ -17,6 +17,7 @@ class HealthTable : public HealthTableIF, public SystemObject {
|
||||
/** HealthTableIF overrides */
|
||||
virtual ReturnValue_t registerObject(
|
||||
object_id_t object, HasHealthIF::HealthState initilialState = HasHealthIF::HEALTHY) override;
|
||||
ReturnValue_t removeObject(object_id_t object) override;
|
||||
virtual size_t getPrintSize() override;
|
||||
virtual void printAll(uint8_t* pointer, size_t maxSize) override;
|
||||
|
||||
|
||||
@@ -14,6 +14,8 @@ class HealthTableIF : public ManagesHealthIF {
|
||||
virtual ReturnValue_t registerObject(
|
||||
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 void printAll(uint8_t *pointer, size_t maxSize) = 0;
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE ParameterTypeSelector.cpp)
|
||||
@@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
|
||||
|
||||
#include <boost/preprocessor.hpp>
|
||||
|
||||
// TODO ifdef EnumIF, consistent naming of functions arrays and macros (probably enum values and
|
||||
// descriptions)
|
||||
|
||||
#include "EnumIF.h"
|
||||
#include "EnumCommon.h"
|
||||
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
|
||||
#define FSFW_CLASSLESS_ENUM(name, type, elements) \
|
||||
enum : type { BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_FOR_EACH(CLEAN_ENUM_ITEM, "", elements)) }; \
|
||||
\
|
||||
class name : public EnumIF { \
|
||||
public: \
|
||||
enum : type { BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_FOR_EACH(CLEAN_ENUM_ITEM, "", elements)) }; \
|
||||
name(type value) : value(value) {} \
|
||||
name() : value(-1) {} \
|
||||
name(const name &other) : value(other.value) {} \
|
||||
int64_t getValue() const override { return value; } \
|
||||
operator type() { return value; } \
|
||||
name &operator=(name other) { \
|
||||
value = other.value; \
|
||||
return *this; \
|
||||
} \
|
||||
name &operator=(type value) { \
|
||||
this->value = value; \
|
||||
return *this; \
|
||||
} \
|
||||
CREATE_KEY_ARRAY(elements, type) \
|
||||
VALUE_CHECK(type) \
|
||||
GET_INDEX() \
|
||||
CREATE_DESCRIPTION_ARRAY(elements) \
|
||||
GET_DESCRIPTION_FUNC() \
|
||||
private: \
|
||||
type value; \
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
#define FSFW_CLASSLESS_ENUM(name, type, elements) \
|
||||
enum name : type { BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_FOR_EACH(CLEAN_ENUM_ITEM, "", elements)) };
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,64 @@
|
||||
#pragma once
|
||||
|
||||
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
|
||||
#include <fsfw/serialize/SerializeAdapter.h>
|
||||
|
||||
#include <boost/preprocessor.hpp>
|
||||
|
||||
// TODO ifdef EnumIF, consistent naming of functions arrays and macros (probably enum values and
|
||||
// descriptions)
|
||||
|
||||
#include "EnumIF.h"
|
||||
#include "EnumCommon.h"
|
||||
|
||||
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
|
||||
#define FSFW_ENUM(name, type, elements) \
|
||||
class name : public EnumIF, public SerializeIF { \
|
||||
public: \
|
||||
enum : type { BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_FOR_EACH(CLEAN_ENUM_ITEM, "", elements)) }; \
|
||||
name(type value) : value(value) {} \
|
||||
name() : value(-1) {} \
|
||||
name(const name &other) : value(other.value) {} \
|
||||
int64_t getValue() const override { return value; } \
|
||||
operator type() { return value; } \
|
||||
name &operator=(name other) { \
|
||||
value = other.value; \
|
||||
return *this; \
|
||||
} \
|
||||
name &operator=(type value) { \
|
||||
this->value = value; \
|
||||
return *this; \
|
||||
} \
|
||||
CREATE_KEY_ARRAY(elements, type) \
|
||||
VALUE_CHECK(type) \
|
||||
GET_INDEX() \
|
||||
CREATE_DESCRIPTION_ARRAY(elements) \
|
||||
GET_DESCRIPTION_FUNC() \
|
||||
virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, \
|
||||
Endianness streamEndianness) const override { \
|
||||
return SerializeAdapter::serialize<>(&value, buffer, size, maxSize, streamEndianness); \
|
||||
} \
|
||||
virtual size_t getSerializedSize() const override { \
|
||||
return SerializeAdapter::getSerializedSize<>(&value); \
|
||||
} \
|
||||
virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, \
|
||||
Endianness streamEndianness) override { \
|
||||
return SerializeAdapter::deSerialize<>(&value, buffer, size, streamEndianness); \
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
type value; \
|
||||
};
|
||||
|
||||
|
||||
#else
|
||||
|
||||
#define FSFW_ENUM(name, type, elements) \
|
||||
enum class name : type { \
|
||||
BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_FOR_EACH(CLEAN_ENUM_ITEM, "", elements)) \
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,62 @@
|
||||
#define CLEAN_ENUM_ITEM(r, data, element) \
|
||||
BOOST_PP_IF(BOOST_PP_SUB(BOOST_PP_TUPLE_SIZE(element), 2), \
|
||||
(BOOST_PP_TUPLE_ELEM(0, element) = BOOST_PP_TUPLE_ELEM(1, element)), \
|
||||
(BOOST_PP_TUPLE_ELEM(0, element)))
|
||||
|
||||
#if defined FSFW_ENUM_VALUE_CHECKS || defined FSFW_INTROSPECTION
|
||||
|
||||
|
||||
#define GET_KEY(r, data, element) (BOOST_PP_TUPLE_ELEM(0, element))
|
||||
#define GET_DESCRIPTION(r, data, element) \
|
||||
BOOST_PP_IF(BOOST_PP_SUB(BOOST_PP_TUPLE_SIZE(element), 2), (BOOST_PP_TUPLE_ELEM(2, element)), \
|
||||
(BOOST_PP_TUPLE_ELEM(1, element)))
|
||||
|
||||
#define CREATE_KEY_ARRAY(enum_elements, type) \
|
||||
/*was static constexpr, but clang won't compile that*/ \
|
||||
int64_t elements[BOOST_PP_SEQ_SIZE(BOOST_PP_SEQ_FOR_EACH(GET_KEY, "", enum_elements))] = { \
|
||||
BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_FOR_EACH(GET_KEY, "", enum_elements))}; \
|
||||
const int64_t *getElements() const override { return elements; } \
|
||||
size_t getSize() const override { \
|
||||
return BOOST_PP_SEQ_SIZE(BOOST_PP_SEQ_FOR_EACH(GET_KEY, "", enum_elements)); \
|
||||
}
|
||||
#define VALUE_CHECK(type) \
|
||||
bool isValid() const override { \
|
||||
for (size_t i = 0; i < sizeof(elements) / sizeof(elements[0]); i++) { \
|
||||
if (value == elements[i]) { \
|
||||
return true; \
|
||||
} \
|
||||
} \
|
||||
return false; \
|
||||
}
|
||||
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
#define CREATE_DESCRIPTION_ARRAY(elements) \
|
||||
/*was static constexpr, but clang won't compile that*/ \
|
||||
const char \
|
||||
*descriptions[BOOST_PP_SEQ_SIZE(BOOST_PP_SEQ_FOR_EACH(GET_DESCRIPTION, "", elements))] = { \
|
||||
BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_FOR_EACH(GET_DESCRIPTION, "", elements))}; \
|
||||
const char *const *getDescriptions() const override { return descriptions; }
|
||||
#define GET_INDEX() \
|
||||
size_t getIndex(int64_t value) const override { \
|
||||
for (size_t i = 0; i < sizeof(elements) / sizeof(elements[0]); i++) { \
|
||||
if (value == elements[i]) { \
|
||||
return i; \
|
||||
} \
|
||||
} \
|
||||
return -1; \
|
||||
}
|
||||
#define GET_DESCRIPTION_FUNC() \
|
||||
const char *getDescription() const override { \
|
||||
if (getIndex(value) == static_cast<size_t>(-1)) { \
|
||||
return nullptr; \
|
||||
} else { \
|
||||
return descriptions[getIndex(value)]; \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define GET_INDEX()
|
||||
#define CREATE_DESCRIPTION_ARRAY(elements)
|
||||
#define GET_DESCRIPTION_FUNC()
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
|
||||
class EnumIF {
|
||||
public:
|
||||
virtual int64_t getValue() const = 0;
|
||||
virtual bool isValid() const = 0;
|
||||
virtual size_t getSize() const = 0;
|
||||
virtual size_t getIndex(int64_t value) const = 0;
|
||||
virtual const int64_t *getElements() const = 0;
|
||||
virtual const char *const *getDescriptions() const = 0;
|
||||
virtual const char *getDescription() const = 0;
|
||||
};
|
||||
@@ -0,0 +1,56 @@
|
||||
#include "ParameterTypeSelector.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
|
||||
template <typename T>
|
||||
Types::ParameterType ParameterTypeSelector::getType() {
|
||||
return Types::UNSUPPORTED;
|
||||
}
|
||||
|
||||
template <>
|
||||
Types::ParameterType ParameterTypeSelector::getType<uint8_t>() {
|
||||
return Types::SIGNED;
|
||||
}
|
||||
template <>
|
||||
Types::ParameterType ParameterTypeSelector::getType<int8_t>() {
|
||||
return Types::SIGNED;
|
||||
}
|
||||
|
||||
template <>
|
||||
Types::ParameterType ParameterTypeSelector::getType<uint16_t>() {
|
||||
return Types::SIGNED;
|
||||
}
|
||||
template <>
|
||||
Types::ParameterType ParameterTypeSelector::getType<int16_t>() {
|
||||
return Types::SIGNED;
|
||||
}
|
||||
template <>
|
||||
Types::ParameterType ParameterTypeSelector::getType<uint32_t>() {
|
||||
return Types::SIGNED;
|
||||
}
|
||||
template <>
|
||||
Types::ParameterType ParameterTypeSelector::getType<int32_t>() {
|
||||
return Types::SIGNED;
|
||||
}
|
||||
// template <>
|
||||
// Types::ParameterType ParameterTypeSelector::getType<uint64_t>() {
|
||||
// return Types::UNSIGNED;
|
||||
// }
|
||||
template <>
|
||||
Types::ParameterType ParameterTypeSelector::getType<int64_t>() {
|
||||
return Types::SIGNED;
|
||||
}
|
||||
template <>
|
||||
Types::ParameterType ParameterTypeSelector::getType<float>() {
|
||||
return Types::FLOATING;
|
||||
}
|
||||
template <>
|
||||
Types::ParameterType ParameterTypeSelector::getType<double>() {
|
||||
return Types::FLOATING;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
|
||||
class ParameterTypeSelector {
|
||||
public:
|
||||
template <typename T>
|
||||
static Types::ParameterType getType();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
//maybe call them MIB types as these are the ones exposed to the MIB?
|
||||
// Note: some DBs (Postgress, Mongo) only support signed 64bit integers. To have a common denominator, all integers are int64_t.
|
||||
// As such, ther is no unsigned Type, as there can not be a uint64_t and uint32_t completely fits into int64_t
|
||||
namespace Types {
|
||||
enum ParameterType { SIGNED, FLOATING, ENUM, UNSUPPORTED };
|
||||
} // namespace Types
|
||||
@@ -0,0 +1,74 @@
|
||||
#pragma once
|
||||
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
#include "Enum.h"
|
||||
#include "Types.h"
|
||||
#include "ParameterTypeSelector.h"
|
||||
|
||||
template <bool>
|
||||
class enumHelper;
|
||||
|
||||
template <>
|
||||
class enumHelper<true> {
|
||||
public:
|
||||
static bool isValid(EnumIF *anEnum) { return anEnum->isValid(); }
|
||||
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
template <typename T>
|
||||
static Types::ParameterType getType() {
|
||||
return Types::ENUM;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static T getMin() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static T getMax() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static std::vector<int64_t> getEnumValues() { return std::vector<int64_t>(); }
|
||||
|
||||
static std::vector<int64_t> getEnumValues(EnumIF *anEnum) {
|
||||
std::vector<int64_t> vector;
|
||||
for (size_t i = 0; i < anEnum->getSize(); i++) {
|
||||
vector.push_back(anEnum->getElements()[i]);
|
||||
}
|
||||
return vector;
|
||||
}
|
||||
|
||||
static const char *const *getEnumDescriptions(EnumIF *anEnum) {
|
||||
return anEnum->getDescriptions();
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
template <>
|
||||
class enumHelper<false> {
|
||||
public:
|
||||
static bool isValid(void *) { return true; }
|
||||
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
template <typename T>
|
||||
static Types::ParameterType getType() {
|
||||
return ParameterTypeSelector::getType<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static T getMin() {
|
||||
return std::numeric_limits<T>::lowest();
|
||||
}
|
||||
template <typename T>
|
||||
static T getMax() {
|
||||
return std::numeric_limits<T>::max();
|
||||
}
|
||||
|
||||
static std::vector<int64_t> getEnumValues(void *) { return std::vector<int64_t>(); }
|
||||
|
||||
static const char *const *getEnumDescriptions(void *) { return nullptr; }
|
||||
#endif
|
||||
};
|
||||
@@ -16,7 +16,7 @@
|
||||
* This is the typedef for object identifiers.
|
||||
* @ingroup system_objects
|
||||
*/
|
||||
typedef uint32_t object_id_t;
|
||||
using object_id_t = uint32_t;
|
||||
|
||||
/**
|
||||
* This interface allows a class to be included in the object manager
|
||||
|
||||
@@ -54,7 +54,7 @@ ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) {
|
||||
// If the deadline was missed, the deadlineMissedFunc is called.
|
||||
if (!PosixThread::delayUntil(&lastWakeTime, interval)) {
|
||||
// No time left on timer -> we missed the deadline
|
||||
if(dlmFunc != nullptr){
|
||||
if (dlmFunc != nullptr) {
|
||||
dlmFunc();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,9 +290,9 @@ ReturnValue_t MessageQueue::handleOpenError(mq_attr* attributes, uint32_t messag
|
||||
*/
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
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 "
|
||||
"allowed message size higher!"
|
||||
"allowed message depth higher"
|
||||
<< std::endl;
|
||||
#else
|
||||
sif::printError(
|
||||
|
||||
@@ -249,9 +249,12 @@ void Service3Housekeeping::handleUnrequestedReply(CommandMessage* reply) {
|
||||
break;
|
||||
}
|
||||
case (CommandMessage::REPLY_REJECTED): {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "Service3Housekeeping::handleUnrequestedReply: Unexpected reply "
|
||||
"rejected with error code"
|
||||
<< reply->getParameter() << std::endl;
|
||||
#else
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#ifndef FSFW_INC_FSFW_SERIALIZE_H_
|
||||
#define FSFW_INC_FSFW_SERIALIZE_H_
|
||||
|
||||
#include "src/core/serialize/EndianConverter.h"
|
||||
#include "src/core/serialize/SerialArrayListAdapter.h"
|
||||
#include "src/core/serialize/SerialBufferAdapter.h"
|
||||
#include "src/core/serialize/SerialLinkedListAdapter.h"
|
||||
#include "src/core/serialize/SerializeElement.h"
|
||||
#include "fsfw/serialize/EndianConverter.h"
|
||||
#include "fsfw/serialize/SerialArrayListAdapter.h"
|
||||
#include "fsfw/serialize/SerialBufferAdapter.h"
|
||||
#include "fsfw/serialize/SerialLinkedListAdapter.h"
|
||||
#include "fsfw/serialize/SerializeElement.h"
|
||||
|
||||
#endif /* FSFW_INC_FSFW_SERIALIZE_H_ */
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
#include "../osal/Endiness.h"
|
||||
#include "fsfw/osal/Endiness.h"
|
||||
|
||||
/**
|
||||
* Helper class to convert variables or bitstreams between machine
|
||||
@@ -36,7 +36,7 @@
|
||||
*/
|
||||
class EndianConverter {
|
||||
private:
|
||||
EndianConverter(){};
|
||||
EndianConverter() = default;
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -49,8 +49,8 @@ class EndianConverter {
|
||||
#error BYTE_ORDER_SYSTEM not defined
|
||||
#elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN
|
||||
T tmp;
|
||||
uint8_t *pointerOut = (uint8_t *)&tmp;
|
||||
uint8_t *pointerIn = (uint8_t *)∈
|
||||
auto *pointerOut = reinterpret_cast<uint8_t *>(&tmp);
|
||||
auto *pointerIn = reinterpret_cast<uint8_t *>(&in);
|
||||
for (size_t count = 0; count < sizeof(T); count++) {
|
||||
pointerOut[sizeof(T) - count - 1] = pointerIn[count];
|
||||
}
|
||||
@@ -73,10 +73,8 @@ class EndianConverter {
|
||||
for (size_t count = 0; count < size; count++) {
|
||||
out[size - count - 1] = in[count];
|
||||
}
|
||||
return;
|
||||
#elif BYTE_ORDER_SYSTEM == BIG_ENDIAN
|
||||
memcpy(out, in, size);
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -90,8 +88,8 @@ class EndianConverter {
|
||||
#error BYTE_ORDER_SYSTEM not defined
|
||||
#elif BYTE_ORDER_SYSTEM == BIG_ENDIAN
|
||||
T tmp;
|
||||
uint8_t *pointerOut = (uint8_t *)&tmp;
|
||||
uint8_t *pointerIn = (uint8_t *)∈
|
||||
auto *pointerOut = reinterpret_cast<uint8_t *>(&tmp);
|
||||
auto *pointerIn = reinterpret_cast<uint8_t *>(&in);
|
||||
for (size_t count = 0; count < sizeof(T); count++) {
|
||||
pointerOut[sizeof(T) - count - 1] = pointerIn[count];
|
||||
}
|
||||
@@ -113,10 +111,8 @@ class EndianConverter {
|
||||
for (size_t count = 0; count < size; count++) {
|
||||
out[size - count - 1] = in[count];
|
||||
}
|
||||
return;
|
||||
#elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN
|
||||
memcpy(out, in, size);
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||
|
||||
/**
|
||||
* @defgroup serialize Serialization
|
||||
@@ -34,7 +34,7 @@ class SerializeIF {
|
||||
static const ReturnValue_t TOO_MANY_ELEMENTS =
|
||||
MAKE_RETURN_CODE(3); // !< There are too many elements to be deserialized
|
||||
|
||||
virtual ~SerializeIF() {}
|
||||
virtual ~SerializeIF() = default;
|
||||
/**
|
||||
* @brief
|
||||
* Function to serialize the object into a buffer with maxSize. Size represents the written
|
||||
@@ -59,14 +59,21 @@ class SerializeIF {
|
||||
* - @c RETURN_FAILED Generic error
|
||||
* - @c RETURN_OK Successful serialization
|
||||
*/
|
||||
virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||
Endianness streamEndianness) const = 0;
|
||||
[[nodiscard]] virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||
Endianness streamEndianness) const = 0;
|
||||
/**
|
||||
* Forwards to regular @serialize call with big (network) endianness
|
||||
*/
|
||||
[[nodiscard]] virtual ReturnValue_t serializeBe(uint8_t **buffer, size_t *size,
|
||||
size_t maxSize) const {
|
||||
return serialize(buffer, size, maxSize, SerializeIF::Endianness::NETWORK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the size of a object if it would be serialized in a buffer
|
||||
* @return Size of serialized object
|
||||
*/
|
||||
virtual size_t getSerializedSize() const = 0;
|
||||
[[nodiscard]] virtual size_t getSerializedSize() const = 0;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
@@ -90,6 +97,57 @@ class SerializeIF {
|
||||
*/
|
||||
virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
|
||||
Endianness streamEndianness) = 0;
|
||||
/**
|
||||
* Forwards to regular @deSerialize call with big (network) endianness
|
||||
*/
|
||||
virtual ReturnValue_t deSerializeBe(const uint8_t **buffer, size_t *size) {
|
||||
return deSerialize(buffer, size, SerializeIF::Endianness::NETWORK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method which can be used if serialization should be performed without any additional
|
||||
* pointer arithmetic on a passed buffer pointer
|
||||
* @param buffer
|
||||
* @param maxSize
|
||||
* @param streamEndianness
|
||||
* @return
|
||||
*/
|
||||
[[nodiscard]] virtual ReturnValue_t serialize(uint8_t *buffer, size_t &serLen, size_t maxSize,
|
||||
Endianness streamEndianness) const {
|
||||
size_t tmpSize = 0;
|
||||
ReturnValue_t result = serialize(&buffer, &tmpSize, maxSize, streamEndianness);
|
||||
serLen = tmpSize;
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* Forwards to regular @serialize call with big (network) endianness
|
||||
*/
|
||||
[[nodiscard]] virtual ReturnValue_t serializeBe(uint8_t *buffer, size_t &serLen,
|
||||
size_t maxSize) const {
|
||||
return serialize(buffer, serLen, maxSize, SerializeIF::Endianness::NETWORK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper methods which can be used if deserialization should be performed without any additional
|
||||
* pointer arithmetic on a passed buffer pointer
|
||||
* @param buffer
|
||||
* @param maxSize
|
||||
* @param streamEndianness
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t deSerialize(const uint8_t *buffer, size_t &deserSize, size_t maxSize,
|
||||
Endianness streamEndianness) {
|
||||
size_t deserLen = maxSize;
|
||||
ReturnValue_t result = deSerialize(&buffer, &deserLen, streamEndianness);
|
||||
deserSize = maxSize - deserLen;
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* Forwards to regular @serialize call with big (network) endianness
|
||||
*/
|
||||
virtual ReturnValue_t deSerializeBe(const uint8_t *buffer, size_t &deserSize, size_t maxSize) {
|
||||
return deSerialize(buffer, deserSize, maxSize, SerializeIF::Endianness::NETWORK);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* FSFW_SERIALIZE_SERIALIZEIF_H_ */
|
||||
@@ -0,0 +1,52 @@
|
||||
#ifndef FSFW_UTIL_UNSIGNEDBYTEFIELD_H
|
||||
#define FSFW_UTIL_UNSIGNEDBYTEFIELD_H
|
||||
|
||||
#include "fsfw/serialize.h"
|
||||
|
||||
template<typename T>
|
||||
class UnsignedByteField: public SerializeIF {
|
||||
public:
|
||||
static_assert(std::is_unsigned<T>::value);
|
||||
|
||||
explicit UnsignedByteField(T value): value(value) {}
|
||||
[[nodiscard]] ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||
Endianness streamEndianness) const override {
|
||||
return SerializeAdapter::serialize(&value, buffer, size, maxSize, streamEndianness);
|
||||
}
|
||||
|
||||
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
|
||||
Endianness streamEndianness) override {
|
||||
return SerializeAdapter::deSerialize(&value, buffer, size, streamEndianness);
|
||||
}
|
||||
|
||||
[[nodiscard]] size_t getSerializedSize() const override {
|
||||
return sizeof(T);
|
||||
}
|
||||
|
||||
[[nodiscard]] T getValue() const {
|
||||
return value;
|
||||
}
|
||||
|
||||
void setValue(T value_) {
|
||||
value = value_;
|
||||
}
|
||||
private:
|
||||
T value;
|
||||
};
|
||||
|
||||
class U32ByteField: public UnsignedByteField<uint32_t> {
|
||||
public:
|
||||
explicit U32ByteField(uint32_t value): UnsignedByteField<uint32_t>(value) {}
|
||||
};
|
||||
|
||||
class U16ByteField: public UnsignedByteField<uint16_t> {
|
||||
public:
|
||||
explicit U16ByteField(uint16_t value): UnsignedByteField<uint16_t>(value) {}
|
||||
};
|
||||
|
||||
class U8ByteField: public UnsignedByteField<uint8_t> {
|
||||
public:
|
||||
explicit U8ByteField(uint8_t value): UnsignedByteField<uint8_t>(value) {}
|
||||
};
|
||||
|
||||
#endif // FSFW_UTIL_UNSIGNEDBYTEFIELD_H
|
||||
@@ -2,9 +2,9 @@ add_subdirectory(devicehandlers)
|
||||
add_subdirectory(common)
|
||||
|
||||
if(UNIX)
|
||||
add_subdirectory(linux)
|
||||
add_subdirectory(linux)
|
||||
endif()
|
||||
|
||||
if(FSFW_HAL_ADD_STM32H7)
|
||||
add_subdirectory(stm32h7)
|
||||
add_subdirectory(stm32h7)
|
||||
endif()
|
||||
File renamed without changes.
@@ -0,0 +1 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE GpioCookie.cpp)
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,3 @@
|
||||
target_sources(
|
||||
${LIB_FSFW_NAME} PRIVATE GyroL3GD20Handler.cpp MgmRM3100Handler.cpp
|
||||
MgmLIS3MDLHandler.cpp)
|
||||
File renamed without changes.
File renamed without changes.
+10
-16
@@ -286,26 +286,22 @@ ReturnValue_t MgmLIS3MDLHandler::interpretDeviceReply(DeviceCommandId_t id, cons
|
||||
|
||||
PoolReadGuard readHelper(&dataset);
|
||||
if (readHelper.getReadResult() == HasReturnvaluesIF::RETURN_OK) {
|
||||
if (std::abs(mgmX) > absLimitX or std::abs(mgmY) > absLimitY or
|
||||
std::abs(mgmZ) > absLimitZ) {
|
||||
dataset.fieldStrengths.setValid(false);
|
||||
}
|
||||
if (std::abs(mgmX) < absLimitX) {
|
||||
dataset.fieldStrengthX = mgmX;
|
||||
dataset.fieldStrengthX.setValid(true);
|
||||
} else {
|
||||
dataset.fieldStrengthX.setValid(false);
|
||||
dataset.fieldStrengths[0] = mgmX;
|
||||
}
|
||||
|
||||
if (std::abs(mgmY) < absLimitY) {
|
||||
dataset.fieldStrengthY = mgmY;
|
||||
dataset.fieldStrengthY.setValid(true);
|
||||
} else {
|
||||
dataset.fieldStrengthY.setValid(false);
|
||||
dataset.fieldStrengths[1] = mgmY;
|
||||
}
|
||||
|
||||
if (std::abs(mgmZ) < absLimitZ) {
|
||||
dataset.fieldStrengthZ = mgmZ;
|
||||
dataset.fieldStrengthZ.setValid(true);
|
||||
} else {
|
||||
dataset.fieldStrengthZ.setValid(false);
|
||||
dataset.fieldStrengths[2] = mgmZ;
|
||||
}
|
||||
dataset.fieldStrengths.setValid(true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -471,10 +467,8 @@ void MgmLIS3MDLHandler::modeChanged(void) { internalState = InternalState::STATE
|
||||
|
||||
ReturnValue_t MgmLIS3MDLHandler::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
|
||||
LocalDataPoolManager &poolManager) {
|
||||
localDataPoolMap.emplace(MGMLIS3MDL::FIELD_STRENGTH_X, new PoolEntry<float>({0.0}));
|
||||
localDataPoolMap.emplace(MGMLIS3MDL::FIELD_STRENGTH_Y, new PoolEntry<float>({0.0}));
|
||||
localDataPoolMap.emplace(MGMLIS3MDL::FIELD_STRENGTH_Z, new PoolEntry<float>({0.0}));
|
||||
localDataPoolMap.emplace(MGMLIS3MDL::TEMPERATURE_CELCIUS, new PoolEntry<float>({0.0}));
|
||||
localDataPoolMap.emplace(MGMLIS3MDL::FIELD_STRENGTHS, &mgmXYZ);
|
||||
localDataPoolMap.emplace(MGMLIS3MDL::TEMPERATURE_CELCIUS, &temperature);
|
||||
poolManager.subscribeForPeriodicPacket(dataset.getSid(), false, 10.0, false);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
+2
@@ -103,6 +103,8 @@ class MgmLIS3MDLHandler : public DeviceHandlerBase {
|
||||
CommunicationStep communicationStep = CommunicationStep::DATA;
|
||||
bool commandExecuted = false;
|
||||
|
||||
PoolEntry<float> mgmXYZ = PoolEntry<float>(3);
|
||||
PoolEntry<float> temperature = PoolEntry<float>();
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Device specific commands and variables */
|
||||
/*------------------------------------------------------------------------*/
|
||||
+4
-6
@@ -309,9 +309,7 @@ void MgmRM3100Handler::modeChanged(void) { internalState = InternalState::NONE;
|
||||
|
||||
ReturnValue_t MgmRM3100Handler::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
|
||||
LocalDataPoolManager &poolManager) {
|
||||
localDataPoolMap.emplace(RM3100::FIELD_STRENGTH_X, new PoolEntry<float>({0.0}));
|
||||
localDataPoolMap.emplace(RM3100::FIELD_STRENGTH_Y, new PoolEntry<float>({0.0}));
|
||||
localDataPoolMap.emplace(RM3100::FIELD_STRENGTH_Z, new PoolEntry<float>({0.0}));
|
||||
localDataPoolMap.emplace(RM3100::FIELD_STRENGTHS, &mgmXYZ);
|
||||
poolManager.subscribeForPeriodicPacket(primaryDataset.getSid(), false, 10.0, false);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
@@ -355,9 +353,9 @@ ReturnValue_t MgmRM3100Handler::handleDataReadout(const uint8_t *packet) {
|
||||
// TODO: Sanity check on values?
|
||||
PoolReadGuard readGuard(&primaryDataset);
|
||||
if (readGuard.getReadResult() == HasReturnvaluesIF::RETURN_OK) {
|
||||
primaryDataset.fieldStrengthX = fieldStrengthX;
|
||||
primaryDataset.fieldStrengthY = fieldStrengthY;
|
||||
primaryDataset.fieldStrengthZ = fieldStrengthZ;
|
||||
primaryDataset.fieldStrengths[0] = fieldStrengthX;
|
||||
primaryDataset.fieldStrengths[1] = fieldStrengthY;
|
||||
primaryDataset.fieldStrengths[2] = fieldStrengthZ;
|
||||
primaryDataset.setValidity(true, true);
|
||||
}
|
||||
return RETURN_OK;
|
||||
+1
@@ -85,6 +85,7 @@ class MgmRM3100Handler : public DeviceHandlerBase {
|
||||
|
||||
bool goToNormalModeAtStartup = false;
|
||||
uint32_t transitionDelay;
|
||||
PoolEntry<float> mgmXYZ = PoolEntry<float>(3);
|
||||
|
||||
ReturnValue_t handleCycleCountConfigCommand(DeviceCommandId_t deviceCommand,
|
||||
const uint8_t *commandData, size_t commandDataLen);
|
||||
File renamed without changes.
+5
-9
@@ -139,12 +139,7 @@ static const uint8_t CTRL_REG5_DEFAULT = 0;
|
||||
|
||||
static const uint32_t MGM_DATA_SET_ID = READ_CONFIG_AND_DATA;
|
||||
|
||||
enum MgmPoolIds : lp_id_t {
|
||||
FIELD_STRENGTH_X,
|
||||
FIELD_STRENGTH_Y,
|
||||
FIELD_STRENGTH_Z,
|
||||
TEMPERATURE_CELCIUS
|
||||
};
|
||||
enum MgmPoolIds : lp_id_t { FIELD_STRENGTHS, TEMPERATURE_CELCIUS };
|
||||
|
||||
class MgmPrimaryDataset : public StaticLocalDataSet<4> {
|
||||
public:
|
||||
@@ -152,9 +147,10 @@ class MgmPrimaryDataset : public StaticLocalDataSet<4> {
|
||||
|
||||
MgmPrimaryDataset(object_id_t mgmId) : StaticLocalDataSet(sid_t(mgmId, MGM_DATA_SET_ID)) {}
|
||||
|
||||
lp_var_t<float> fieldStrengthX = lp_var_t<float>(sid.objectId, FIELD_STRENGTH_X, this);
|
||||
lp_var_t<float> fieldStrengthY = lp_var_t<float>(sid.objectId, FIELD_STRENGTH_Y, this);
|
||||
lp_var_t<float> fieldStrengthZ = lp_var_t<float>(sid.objectId, FIELD_STRENGTH_Z, this);
|
||||
/**
|
||||
* Field strenghts in uT
|
||||
*/
|
||||
lp_vec_t<float, 3> fieldStrengths = lp_vec_t<float, 3>(sid.objectId, FIELD_STRENGTHS, this);
|
||||
lp_var_t<float> temperature = lp_var_t<float>(sid.objectId, TEMPERATURE_CELCIUS, this);
|
||||
};
|
||||
|
||||
+5
-9
@@ -101,11 +101,7 @@ class CycleCountCommand : public SerialLinkedListAdapter<SerializeIF> {
|
||||
|
||||
static constexpr uint32_t MGM_DATASET_ID = READ_DATA;
|
||||
|
||||
enum MgmPoolIds : lp_id_t {
|
||||
FIELD_STRENGTH_X,
|
||||
FIELD_STRENGTH_Y,
|
||||
FIELD_STRENGTH_Z,
|
||||
};
|
||||
enum MgmPoolIds : lp_id_t { FIELD_STRENGTHS };
|
||||
|
||||
class Rm3100PrimaryDataset : public StaticLocalDataSet<3> {
|
||||
public:
|
||||
@@ -113,10 +109,10 @@ class Rm3100PrimaryDataset : public StaticLocalDataSet<3> {
|
||||
|
||||
Rm3100PrimaryDataset(object_id_t mgmId) : StaticLocalDataSet(sid_t(mgmId, MGM_DATASET_ID)) {}
|
||||
|
||||
// Field strengths in micro Tesla.
|
||||
lp_var_t<float> fieldStrengthX = lp_var_t<float>(sid.objectId, FIELD_STRENGTH_X, this);
|
||||
lp_var_t<float> fieldStrengthY = lp_var_t<float>(sid.objectId, FIELD_STRENGTH_Y, this);
|
||||
lp_var_t<float> fieldStrengthZ = lp_var_t<float>(sid.objectId, FIELD_STRENGTH_Z, this);
|
||||
/**
|
||||
* Field strenghts in uT
|
||||
*/
|
||||
lp_vec_t<float, 3> fieldStrengths = lp_vec_t<float, 3>(sid.objectId, FIELD_STRENGTHS, this);
|
||||
};
|
||||
|
||||
} // namespace RM3100
|
||||
File renamed without changes.
@@ -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)
|
||||
File renamed without changes.
Loaded 100 of 322 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user