Compare commits
80 Commits
mueller/cl
...
v5.0.0
Author | SHA1 | Date | |
---|---|---|---|
f11433e50f | |||
edc5a314b8 | |||
54fc35eae7 | |||
05d4162f5b | |||
e030878023 | |||
c96e304b68 | |||
9bbe1dc716 | |||
74794bb71b | |||
6f751c2cf9 | |||
9a2e68b37e | |||
91067cde98 | |||
428018e4f1 | |||
8b6dd3f868 | |||
f6ede7cd3e | |||
4da18172b3 | |||
6e5239e9a0 | |||
78b09ed0c9 | |||
fdf35232ee | |||
8465670374 | |||
3b23fb77b4 | |||
6f7be281ef | |||
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 | |||
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 |
@ -1,7 +0,0 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="fsfw-tests_coverage" type="CMakeRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="fsfw-example-hosted" TARGET_NAME="fsfw-tests_coverage" CONFIG_NAME="Debug Unittest" RUN_TARGET_PROJECT_NAME="fsfw-example-hosted" RUN_TARGET_NAME="fsfw-tests">
|
||||
<method v="2">
|
||||
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
@ -1,7 +0,0 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="fsfw" type="CMakeRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="fsfw-tests" TARGET_NAME="fsfw" CONFIG_NAME="Debug Unittest" RUN_TARGET_PROJECT_NAME="fsfw-tests" RUN_TARGET_NAME="fsfw-tests">
|
||||
<method v="2">
|
||||
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
16
CHANGELOG.md
16
CHANGELOG.md
@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
# [unreleased]
|
||||
|
||||
# [v5.0.0]
|
||||
# [v5.0.0] 25.07.2022
|
||||
|
||||
## Changes
|
||||
|
||||
@ -19,16 +19,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
- Bump C++ required version to C++17. Every project which uses the FSFW and every modern
|
||||
compiler supports it
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/622
|
||||
- HAL Linux SPI: Set the Clock Default State when setting new SPI speed
|
||||
and mode
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/573
|
||||
- GPIO HAL: `Direction`, `GpioOperation` and `Levels` are enum classes now, which prevents
|
||||
name clashes with Windows defines.
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/572
|
||||
- New CMake option `FSFW_HAL_LINUX_ADD_LIBGPIOD` to specifically exclude `gpiod` code.
|
||||
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)
|
||||
@ -46,6 +43,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
creation call. It allows passing context information and an arbitrary user argument into
|
||||
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
|
||||
|
||||
@ -120,6 +120,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
|
||||
|
@ -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()
|
||||
|
||||
@ -139,7 +140,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 +163,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})
|
||||
@ -281,16 +281,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)
|
||||
@ -447,8 +446,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
|
||||
|
@ -139,7 +139,7 @@ You can also use `-DFSFW_OSAL=linux` on Linux systems.
|
||||
|
||||
Coverage data in HTML format can be generated using the `CodeCoverage`
|
||||
[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/
|
||||
|
4
automation/Jenkinsfile
vendored
4
automation/Jenkinsfile
vendored
@ -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 ..'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
)
|
@ -16,8 +16,7 @@ cpp_format="clang-format"
|
||||
file_selectors="-iname *.h -o -iname *.cpp -o -iname *.c -o -iname *.tpp"
|
||||
if command -v ${cpp_format} &> /dev/null; then
|
||||
find ./src ${file_selectors} | xargs ${cpp_format} --style=file -i
|
||||
find ./hal ${file_selectors} | xargs ${cpp_format} --style=file -i
|
||||
find ./tests ${file_selectors} | xargs ${cpp_format} --style=file -i
|
||||
find ./unittests ${file_selectors} | xargs ${cpp_format} --style=file -i
|
||||
else
|
||||
echo "No ${cpp_format} tool found, not formatting C++/C files"
|
||||
fi
|
||||
|
@ -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)
|
||||
|
@ -13,12 +13,10 @@ AckInfo::AckInfo(cfdp::FileDirectives ackedDirective, cfdp::ConditionCode ackedC
|
||||
}
|
||||
}
|
||||
|
||||
AckInfo::AckInfo() = default;
|
||||
|
||||
cfdp::ConditionCode AckInfo::getAckedConditionCode() const { return ackedConditionCode; }
|
||||
|
||||
void AckInfo::setAckedConditionCode(cfdp::ConditionCode ackedConditionCode_) {
|
||||
ackedConditionCode = ackedConditionCode_;
|
||||
void AckInfo::setAckedConditionCode(cfdp::ConditionCode ackedConditionCode) {
|
||||
this->ackedConditionCode = ackedConditionCode;
|
||||
if (ackedDirective == cfdp::FileDirectives::FINISH) {
|
||||
this->directiveSubtypeCode = 0b0001;
|
||||
} else {
|
||||
@ -28,18 +26,20 @@ void AckInfo::setAckedConditionCode(cfdp::ConditionCode ackedConditionCode_) {
|
||||
|
||||
cfdp::FileDirectives AckInfo::getAckedDirective() const { return ackedDirective; }
|
||||
|
||||
void AckInfo::setAckedDirective(cfdp::FileDirectives ackedDirective_) {
|
||||
ackedDirective = ackedDirective_;
|
||||
void AckInfo::setAckedDirective(cfdp::FileDirectives ackedDirective) {
|
||||
this->ackedDirective = ackedDirective;
|
||||
}
|
||||
|
||||
uint8_t AckInfo::getDirectiveSubtypeCode() const { return directiveSubtypeCode; }
|
||||
|
||||
void AckInfo::setDirectiveSubtypeCode(uint8_t directiveSubtypeCode_) {
|
||||
directiveSubtypeCode = directiveSubtypeCode_;
|
||||
void AckInfo::setDirectiveSubtypeCode(uint8_t directiveSubtypeCode) {
|
||||
this->directiveSubtypeCode = directiveSubtypeCode;
|
||||
}
|
||||
|
||||
cfdp::AckTransactionStatus AckInfo::getTransactionStatus() const { return transactionStatus; }
|
||||
|
||||
void AckInfo::setTransactionStatus(cfdp::AckTransactionStatus transactionStatus_) {
|
||||
transactionStatus = transactionStatus_;
|
||||
AckInfo::AckInfo() {}
|
||||
|
||||
void AckInfo::setTransactionStatus(cfdp::AckTransactionStatus transactionStatus) {
|
||||
this->transactionStatus = transactionStatus;
|
||||
}
|
||||
|
@ -9,16 +9,16 @@ class AckInfo {
|
||||
AckInfo(cfdp::FileDirectives ackedDirective, cfdp::ConditionCode ackedConditionCode,
|
||||
cfdp::AckTransactionStatus transactionStatus, uint8_t directiveSubtypeCode = 0);
|
||||
|
||||
[[nodiscard]] cfdp::ConditionCode getAckedConditionCode() const;
|
||||
void setAckedConditionCode(cfdp::ConditionCode ackedConditionCode_);
|
||||
cfdp::ConditionCode getAckedConditionCode() const;
|
||||
void setAckedConditionCode(cfdp::ConditionCode ackedConditionCode);
|
||||
|
||||
[[nodiscard]] cfdp::FileDirectives getAckedDirective() const;
|
||||
cfdp::FileDirectives getAckedDirective() const;
|
||||
void setAckedDirective(cfdp::FileDirectives ackedDirective);
|
||||
|
||||
[[nodiscard]] uint8_t getDirectiveSubtypeCode() const;
|
||||
uint8_t getDirectiveSubtypeCode() const;
|
||||
void setDirectiveSubtypeCode(uint8_t directiveSubtypeCode);
|
||||
|
||||
[[nodiscard]] cfdp::AckTransactionStatus getTransactionStatus() const;
|
||||
cfdp::AckTransactionStatus getTransactionStatus() const;
|
||||
void setTransactionStatus(cfdp::AckTransactionStatus transactionStatus);
|
||||
|
||||
private:
|
||||
|
@ -13,7 +13,7 @@ class AckPduDeserializer : public FileDirectiveDeserializer {
|
||||
* @return
|
||||
* - cfdp::INVALID_DIRECTIVE_FIELDS: Invalid fields
|
||||
*/
|
||||
ReturnValue_t parseData() override;
|
||||
ReturnValue_t parseData();
|
||||
|
||||
private:
|
||||
bool checkAndSetCodes(uint8_t rawAckedByte, uint8_t rawAckedConditionCode);
|
||||
|
@ -18,7 +18,7 @@ class AckPduSerializer : public FileDirectiveSerializer {
|
||||
*/
|
||||
AckPduSerializer(AckInfo& ackInfo, PduConfig& pduConf);
|
||||
|
||||
[[nodiscard]] size_t getSerializedSize() const override;
|
||||
size_t getSerializedSize() const override;
|
||||
|
||||
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
||||
Endianness streamEndianness) const override;
|
||||
|
@ -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) {
|
||||
|
@ -30,7 +30,7 @@ class DataSetIF {
|
||||
* @brief This is an empty virtual destructor,
|
||||
* as it is proposed for C++ interfaces.
|
||||
*/
|
||||
virtual ~DataSetIF() = default;
|
||||
virtual ~DataSetIF() {}
|
||||
|
||||
/**
|
||||
* @brief This operation provides a method to register local data pool
|
||||
@ -39,7 +39,7 @@ class DataSetIF {
|
||||
*/
|
||||
virtual ReturnValue_t registerVariable(PoolVariableIF* variable) = 0;
|
||||
|
||||
[[nodiscard]] virtual uint16_t getFillCount() const = 0;
|
||||
virtual uint16_t getFillCount() const = 0;
|
||||
};
|
||||
|
||||
#endif /* FSFW_DATAPOOL_DATASETIF_H_ */
|
||||
|
@ -9,7 +9,7 @@ PoolDataSetBase::PoolDataSetBase(PoolVariableIF** registeredVariablesArray,
|
||||
const size_t maxFillCount)
|
||||
: registeredVariables(registeredVariablesArray), maxFillCount(maxFillCount) {}
|
||||
|
||||
PoolDataSetBase::~PoolDataSetBase() = default;
|
||||
PoolDataSetBase::~PoolDataSetBase() {}
|
||||
|
||||
ReturnValue_t PoolDataSetBase::registerVariable(PoolVariableIF* variable) {
|
||||
if (registeredVariables == nullptr) {
|
||||
|
@ -64,8 +64,8 @@ class PoolDataSetBase : public PoolDataSetIF, public SerializeIF, public HasRetu
|
||||
* - @c SET_WAS_ALREADY_READ if read() is called twice without calling
|
||||
* commit() in between
|
||||
*/
|
||||
ReturnValue_t read(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||
uint32_t lockTimeout = 20) override;
|
||||
virtual ReturnValue_t read(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||
uint32_t lockTimeout = 20) override;
|
||||
/**
|
||||
* @brief The commit call initializes writing back the registered variables.
|
||||
* @details
|
||||
@ -84,38 +84,39 @@ class PoolDataSetBase : public PoolDataSetIF, public SerializeIF, public HasRetu
|
||||
* - @c COMMITING_WITHOUT_READING if set was not read yet and
|
||||
* contains non write-only variables
|
||||
*/
|
||||
ReturnValue_t commit(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||
uint32_t lockTimeout = 20) override;
|
||||
virtual ReturnValue_t commit(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||
uint32_t lockTimeout = 20) override;
|
||||
|
||||
/**
|
||||
* Register the passed pool variable instance into the data set.
|
||||
* @param variable
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t registerVariable(PoolVariableIF* variable) override;
|
||||
virtual ReturnValue_t registerVariable(PoolVariableIF* variable) override;
|
||||
|
||||
/**
|
||||
* Provides the means to lock the underlying data structure to ensure
|
||||
* thread-safety. Default implementation is empty
|
||||
* @return Always returns -@c RETURN_OK
|
||||
*/
|
||||
ReturnValue_t lockDataPool(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||
uint32_t timeoutMs = 20) override;
|
||||
virtual ReturnValue_t lockDataPool(
|
||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||
uint32_t timeoutMs = 20) override;
|
||||
/**
|
||||
* Provides the means to unlock the underlying data structure to ensure
|
||||
* thread-safety. Default implementation is empty
|
||||
* @return Always returns -@c RETURN_OK
|
||||
*/
|
||||
ReturnValue_t unlockDataPool() override;
|
||||
virtual ReturnValue_t unlockDataPool() override;
|
||||
|
||||
[[nodiscard]] uint16_t getFillCount() const override;
|
||||
virtual uint16_t getFillCount() const override;
|
||||
|
||||
/* SerializeIF implementations */
|
||||
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
||||
SerializeIF::Endianness streamEndianness) const override;
|
||||
[[nodiscard]] size_t getSerializedSize() const override;
|
||||
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||
SerializeIF::Endianness streamEndianness) override;
|
||||
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, const size_t maxSize,
|
||||
SerializeIF::Endianness streamEndianness) const override;
|
||||
virtual size_t getSerializedSize() const override;
|
||||
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||
SerializeIF::Endianness streamEndianness) override;
|
||||
|
||||
/**
|
||||
* Can be used to individually protect every read and commit call.
|
||||
@ -155,7 +156,7 @@ class PoolDataSetBase : public PoolDataSetIF, public SerializeIF, public HasRetu
|
||||
const size_t maxFillCount = 0;
|
||||
|
||||
void setContainer(PoolVariableIF** variablesContainer);
|
||||
[[nodiscard]] PoolVariableIF** getContainer() const;
|
||||
PoolVariableIF** getContainer() const;
|
||||
|
||||
private:
|
||||
bool protectEveryReadCommitCall = false;
|
||||
|
@ -7,24 +7,26 @@
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
|
||||
template <typename T>
|
||||
PoolEntry<T>::PoolEntry(std::initializer_list<T> initValue, bool setValid)
|
||||
: length(static_cast<uint8_t>(initValue.size())), valid(setValid) {
|
||||
this->address = new T[this->length];
|
||||
if (initValue.size() == 0) {
|
||||
std::memset(this->address, 0, PoolEntry<T>::getByteSize());
|
||||
} else {
|
||||
std::copy(initValue.begin(), initValue.end(), this->address);
|
||||
PoolEntry<T>::PoolEntry(uint8_t len, bool setValid) : length(len), valid(setValid) {
|
||||
this->address = new T[this->length]();
|
||||
std::memset(this->address, 0, this->getByteSize());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
PoolEntry<T>::PoolEntry(std::initializer_list<T> initValues, bool setValid)
|
||||
: length(static_cast<uint8_t>(initValues.size())), valid(setValid) {
|
||||
this->address = new T[this->length]();
|
||||
if (initValues.size() > 0) {
|
||||
std::copy(initValues.begin(), initValues.end(), this->address);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
PoolEntry<T>::PoolEntry(T* initValue, uint8_t setLength, bool setValid)
|
||||
PoolEntry<T>::PoolEntry(const T* initValue, uint8_t setLength, bool setValid)
|
||||
: length(setLength), valid(setValid) {
|
||||
this->address = new T[this->length];
|
||||
this->address = new T[this->length]();
|
||||
if (initValue != nullptr) {
|
||||
std::memcpy(this->address, initValue, PoolEntry<T>::getByteSize());
|
||||
} else {
|
||||
std::memset(this->address, 0, PoolEntry<T>::getByteSize());
|
||||
std::memcpy(this->address, initValue, this->getByteSize());
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,7 +64,7 @@ bool PoolEntry<T>::getValid() {
|
||||
|
||||
template <typename T>
|
||||
void PoolEntry<T>::print() {
|
||||
const char* validString;
|
||||
const char* validString = nullptr;
|
||||
if (valid) {
|
||||
validString = "Valid";
|
||||
} else {
|
||||
|
@ -33,6 +33,9 @@ class PoolEntry : public PoolEntryIF {
|
||||
"instead! The ECSS standard defines a boolean as a one bit "
|
||||
"field. Therefore it is preferred to store a boolean as an "
|
||||
"uint8_t");
|
||||
|
||||
PoolEntry(uint8_t len = 1, bool setValid = false);
|
||||
|
||||
/**
|
||||
* @brief In the classe's constructor, space is allocated on the heap and
|
||||
* potential initialization values are copied to that space.
|
||||
@ -49,7 +52,7 @@ class PoolEntry : public PoolEntryIF {
|
||||
* @param setValid
|
||||
* Sets the initialization flag. It is invalid by default.
|
||||
*/
|
||||
PoolEntry(std::initializer_list<T> initValue = {0}, bool setValid = false);
|
||||
PoolEntry(std::initializer_list<T> initValue, bool setValid = false);
|
||||
|
||||
/**
|
||||
* @brief In the classe's constructor, space is allocated on the heap and
|
||||
@ -62,7 +65,7 @@ class PoolEntry : public PoolEntryIF {
|
||||
* @param setValid
|
||||
* Sets the initialization flag. It is invalid by default.
|
||||
*/
|
||||
explicit PoolEntry(T* initValue, uint8_t setLength = 1, bool setValid = false);
|
||||
PoolEntry(const T* initValue, uint8_t setLength = 1, bool setValid = false);
|
||||
|
||||
//! Explicitely deleted copy ctor, copying is not allowed.
|
||||
PoolEntry(const PoolEntry&) = delete;
|
||||
@ -77,7 +80,7 @@ class PoolEntry : public PoolEntryIF {
|
||||
* PoolEntries shall never be copied, as a copy might delete the variable
|
||||
* on the heap.
|
||||
*/
|
||||
~PoolEntry() override;
|
||||
~PoolEntry();
|
||||
|
||||
/**
|
||||
* Return typed pointer to start of data.
|
||||
@ -91,32 +94,32 @@ class PoolEntry : public PoolEntryIF {
|
||||
* For non-array pool entries return type size, for vector entries
|
||||
* return type size times the number of entries.
|
||||
*/
|
||||
uint8_t getSize() override;
|
||||
uint8_t getSize();
|
||||
/**
|
||||
* @brief This operation returns the size in bytes.
|
||||
* @details The size is calculated by sizeof(type) * array_size.
|
||||
*/
|
||||
uint16_t getByteSize() override;
|
||||
uint16_t getByteSize();
|
||||
/**
|
||||
* @brief This operation returns a the address pointer casted to void*.
|
||||
*/
|
||||
void* getRawData() override;
|
||||
void* getRawData();
|
||||
/**
|
||||
* @brief This method allows to set the valid information
|
||||
* of the pool entry.
|
||||
*/
|
||||
void setValid(bool isValid) override;
|
||||
void setValid(bool isValid);
|
||||
/**
|
||||
* @brief This method allows to get the valid information
|
||||
* of the pool entry.
|
||||
*/
|
||||
bool getValid() override;
|
||||
bool getValid();
|
||||
/**
|
||||
* @brief This is a debug method that prints all values and the valid
|
||||
* information to the screen. It prints all array entries in a row.
|
||||
*/
|
||||
void print() override;
|
||||
Type getType() override;
|
||||
void print();
|
||||
Type getType();
|
||||
|
||||
private:
|
||||
/**
|
||||
|
@ -24,7 +24,7 @@ class PoolEntryIF {
|
||||
* @brief This is an empty virtual destructor,
|
||||
* as it is required for C++ interfaces.
|
||||
*/
|
||||
virtual ~PoolEntryIF() = default;
|
||||
virtual ~PoolEntryIF() {}
|
||||
/**
|
||||
* @brief getSize returns the array size of the entry.
|
||||
* A single variable parameter has size 1.
|
||||
|
@ -11,9 +11,9 @@
|
||||
*/
|
||||
class PoolReadGuard {
|
||||
public:
|
||||
explicit PoolReadGuard(ReadCommitIF* readObject,
|
||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||
uint32_t mutexTimeout = 20)
|
||||
PoolReadGuard(ReadCommitIF* readObject,
|
||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||
uint32_t mutexTimeout = 20)
|
||||
: readObject(readObject), mutexTimeout(mutexTimeout) {
|
||||
if (readObject != nullptr) {
|
||||
readResult = readObject->read(timeoutType, mutexTimeout);
|
||||
@ -29,7 +29,7 @@ class PoolReadGuard {
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] ReturnValue_t getReadResult() const { return readResult; }
|
||||
ReturnValue_t getReadResult() const { return readResult; }
|
||||
|
||||
/**
|
||||
* @brief Can be used to suppress commit on destruction.
|
||||
|
28
src/fsfw/datapool/PoolVarList.h
Normal file
28
src/fsfw/datapool/PoolVarList.h
Normal file
@ -0,0 +1,28 @@
|
||||
#ifndef FSFW_DATAPOOL_POOLVARLIST_H_
|
||||
#define FSFW_DATAPOOL_POOLVARLIST_H_
|
||||
|
||||
#include "../datapool/PoolVariableIF.h"
|
||||
#include "../datapoolglob/GlobalPoolVariable.h"
|
||||
template <class T, uint8_t n_var>
|
||||
class PoolVarList {
|
||||
private:
|
||||
GlobPoolVar<T> variables[n_var];
|
||||
|
||||
public:
|
||||
PoolVarList(const uint32_t set_id[n_var], DataSetIF* dataSet,
|
||||
PoolVariableIF::ReadWriteMode_t setReadWriteMode) {
|
||||
// I really should have a look at the new init list c++ syntax.
|
||||
if (dataSet == NULL) {
|
||||
return;
|
||||
}
|
||||
for (uint8_t count = 0; count < n_var; count++) {
|
||||
variables[count].dataPoolId = set_id[count];
|
||||
variables[count].readWriteMode = setReadWriteMode;
|
||||
dataSet->registerVariable(&variables[count]);
|
||||
}
|
||||
}
|
||||
|
||||
GlobPoolVar<T>& operator[](int i) { return variables[i]; }
|
||||
};
|
||||
|
||||
#endif /* FSFW_DATAPOOL_POOLVARLIST_H_ */
|
@ -24,8 +24,8 @@ class PoolVariableIF : public SerializeIF, public ReadCommitIF {
|
||||
static constexpr ReturnValue_t INVALID_READ_WRITE_MODE = MAKE_RETURN_CODE(0xA0);
|
||||
static constexpr ReturnValue_t INVALID_POOL_ENTRY = MAKE_RETURN_CODE(0xA1);
|
||||
|
||||
static constexpr bool VALID = true;
|
||||
static constexpr bool INVALID = false;
|
||||
static constexpr bool VALID = 1;
|
||||
static constexpr bool INVALID = 0;
|
||||
static constexpr uint32_t NO_PARAMETER = 0xffffffff;
|
||||
|
||||
enum ReadWriteMode_t { VAR_READ, VAR_WRITE, VAR_READ_WRITE };
|
||||
@ -34,23 +34,23 @@ class PoolVariableIF : public SerializeIF, public ReadCommitIF {
|
||||
* @brief This is an empty virtual destructor,
|
||||
* as it is proposed for C++ interfaces.
|
||||
*/
|
||||
~PoolVariableIF() override = default;
|
||||
virtual ~PoolVariableIF() {}
|
||||
/**
|
||||
* @brief This method returns if the variable is write-only,
|
||||
* read-write or read-only.
|
||||
*/
|
||||
[[nodiscard]] virtual ReadWriteMode_t getReadWriteMode() const = 0;
|
||||
virtual ReadWriteMode_t getReadWriteMode() const = 0;
|
||||
virtual void setReadWriteMode(ReadWriteMode_t newMode) = 0;
|
||||
|
||||
/**
|
||||
* @brief This operation shall return the data pool id of the variable.
|
||||
*/
|
||||
[[nodiscard]] virtual uint32_t getDataPoolId() const = 0;
|
||||
virtual uint32_t getDataPoolId() const = 0;
|
||||
/**
|
||||
* @brief With this call, the valid information of the
|
||||
* variable is returned.
|
||||
*/
|
||||
[[nodiscard]] virtual bool isValid() const = 0;
|
||||
virtual bool isValid() const = 0;
|
||||
/**
|
||||
* @brief With this call, the valid information of the variable is set.
|
||||
*/
|
||||
|
@ -12,7 +12,7 @@ class ReadCommitIF {
|
||||
friend class ReadCommitIFAttorney;
|
||||
|
||||
public:
|
||||
virtual ~ReadCommitIF() = default;
|
||||
virtual ~ReadCommitIF() {}
|
||||
virtual ReturnValue_t read(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) = 0;
|
||||
virtual ReturnValue_t commit(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) = 0;
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
class SharedDataSetIF {
|
||||
public:
|
||||
virtual ~SharedDataSetIF() = default;
|
||||
virtual ~SharedDataSetIF(){};
|
||||
|
||||
private:
|
||||
virtual ReturnValue_t lockDataset(MutexIF::TimeoutType timeoutType,
|
||||
|
@ -9,8 +9,7 @@ class MutexIF;
|
||||
*/
|
||||
class AccessPoolManagerIF {
|
||||
public:
|
||||
virtual ~AccessPoolManagerIF() = default;
|
||||
;
|
||||
virtual ~AccessPoolManagerIF(){};
|
||||
|
||||
virtual MutexIF* getLocalPoolMutex() = 0;
|
||||
|
||||
|
@ -44,15 +44,14 @@ class HasLocalDataPoolIF {
|
||||
friend class HasLocalDpIFUserAttorney;
|
||||
|
||||
public:
|
||||
virtual ~HasLocalDataPoolIF() = default;
|
||||
;
|
||||
virtual ~HasLocalDataPoolIF(){};
|
||||
|
||||
static constexpr uint32_t INVALID_LPID = localpool::INVALID_LPID;
|
||||
|
||||
[[nodiscard]] virtual object_id_t getObjectId() const = 0;
|
||||
virtual object_id_t getObjectId() const = 0;
|
||||
|
||||
/** Command queue for housekeeping messages. */
|
||||
[[nodiscard]] virtual MessageQueueId_t getCommandQueue() const = 0;
|
||||
virtual MessageQueueId_t getCommandQueue() const = 0;
|
||||
|
||||
/**
|
||||
* Is used by pool owner to initialize the pool map once
|
||||
@ -67,7 +66,7 @@ class HasLocalDataPoolIF {
|
||||
* usually be the period the pool owner performs its periodic operation.
|
||||
* @return
|
||||
*/
|
||||
[[nodiscard]] virtual dur_millis_t getPeriodicOperationFrequency() const = 0;
|
||||
virtual dur_millis_t getPeriodicOperationFrequency() const = 0;
|
||||
|
||||
/**
|
||||
* @brief This function will be called by the manager if an update
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "fsfw/datapoollocal/LocalDataPoolManager.h"
|
||||
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
|
||||
#include "fsfw/datapoollocal.h"
|
||||
@ -56,7 +57,7 @@ ReturnValue_t LocalDataPoolManager::initialize(MessageQueueIF* queueToUse) {
|
||||
}
|
||||
|
||||
if (defaultHkDestination != objects::NO_OBJECT) {
|
||||
auto* hkPacketReceiver =
|
||||
AcceptsHkPacketsIF* hkPacketReceiver =
|
||||
ObjectManager::instance()->get<AcceptsHkPacketsIF>(defaultHkDestination);
|
||||
if (hkPacketReceiver != nullptr) {
|
||||
hkDestinationId = hkPacketReceiver->getHkQueue();
|
||||
@ -208,9 +209,9 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(HkReceiver& recei
|
||||
}
|
||||
|
||||
/* Prepare and send update snapshot */
|
||||
timeval now{};
|
||||
timeval now;
|
||||
Clock::getClock_timeval(&now);
|
||||
CCSDSTime::CDS_short cds{};
|
||||
CCSDSTime::CDS_short cds;
|
||||
CCSDSTime::convertToCcsds(&cds, &now);
|
||||
HousekeepingSnapshot updatePacket(
|
||||
reinterpret_cast<uint8_t*>(&cds), sizeof(cds),
|
||||
@ -244,9 +245,9 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(HkReceiver& recei
|
||||
}
|
||||
|
||||
/* Prepare and send update snapshot */
|
||||
timeval now{};
|
||||
timeval now;
|
||||
Clock::getClock_timeval(&now);
|
||||
CCSDSTime::CDS_short cds{};
|
||||
CCSDSTime::CDS_short cds;
|
||||
CCSDSTime::convertToCcsds(&cds, &now);
|
||||
HousekeepingSnapshot updatePacket(
|
||||
reinterpret_cast<uint8_t*>(&cds), sizeof(cds),
|
||||
@ -338,7 +339,8 @@ ReturnValue_t LocalDataPoolManager::subscribeForPeriodicPacket(sid_t sid, bool e
|
||||
float collectionInterval,
|
||||
bool isDiagnostics,
|
||||
object_id_t packetDestination) {
|
||||
auto* hkReceiverObject = ObjectManager::instance()->get<AcceptsHkPacketsIF>(packetDestination);
|
||||
AcceptsHkPacketsIF* hkReceiverObject =
|
||||
ObjectManager::instance()->get<AcceptsHkPacketsIF>(packetDestination);
|
||||
if (hkReceiverObject == nullptr) {
|
||||
printWarningOrError(sif::OutputTypes::OUT_WARNING, "subscribeForPeriodicPacket",
|
||||
QUEUE_OR_DESTINATION_INVALID);
|
||||
@ -366,7 +368,8 @@ ReturnValue_t LocalDataPoolManager::subscribeForPeriodicPacket(sid_t sid, bool e
|
||||
ReturnValue_t LocalDataPoolManager::subscribeForUpdatePacket(sid_t sid, bool isDiagnostics,
|
||||
bool reportingEnabled,
|
||||
object_id_t packetDestination) {
|
||||
auto* hkReceiverObject = ObjectManager::instance()->get<AcceptsHkPacketsIF>(packetDestination);
|
||||
AcceptsHkPacketsIF* hkReceiverObject =
|
||||
ObjectManager::instance()->get<AcceptsHkPacketsIF>(packetDestination);
|
||||
if (hkReceiverObject == nullptr) {
|
||||
printWarningOrError(sif::OutputTypes::OUT_WARNING, "subscribeForPeriodicPacket",
|
||||
QUEUE_OR_DESTINATION_INVALID);
|
||||
|
@ -80,7 +80,7 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
|
||||
*/
|
||||
LocalDataPoolManager(HasLocalDataPoolIF* owner, MessageQueueIF* queueToUse,
|
||||
bool appendValidityBuffer = true);
|
||||
~LocalDataPoolManager() override;
|
||||
virtual ~LocalDataPoolManager();
|
||||
|
||||
/**
|
||||
* Assigns the queue to use. Make sure to call this in the #initialize
|
||||
@ -151,7 +151,7 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
|
||||
* Otherwise, only an notification message is sent.
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t subscribeForSetUpdateMessage(uint32_t setId, object_id_t destinationObject,
|
||||
ReturnValue_t subscribeForSetUpdateMessage(const uint32_t setId, object_id_t destinationObject,
|
||||
MessageQueueId_t targetQueueId,
|
||||
bool generateSnapshot) override;
|
||||
|
||||
@ -169,7 +169,7 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
|
||||
* Otherwise, only an notification message is sent.
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t subscribeForVariableUpdateMessage(lp_id_t localPoolId,
|
||||
ReturnValue_t subscribeForVariableUpdateMessage(const lp_id_t localPoolId,
|
||||
object_id_t destinationObject,
|
||||
MessageQueueId_t targetQueueId,
|
||||
bool generateSnapshot) override;
|
||||
@ -252,7 +252,7 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
|
||||
*/
|
||||
void clearReceiversList();
|
||||
|
||||
[[nodiscard]] object_id_t getCreatorObjectId() const;
|
||||
object_id_t getCreatorObjectId() const;
|
||||
|
||||
/**
|
||||
* Get the pointer to the mutex. Can be used to lock the data pool
|
||||
@ -262,7 +262,7 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
|
||||
*/
|
||||
MutexIF* getMutexHandle();
|
||||
|
||||
LocalDataPoolManager* getPoolManagerHandle() override;
|
||||
virtual LocalDataPoolManager* getPoolManagerHandle() override;
|
||||
|
||||
protected:
|
||||
/** Core data structure for the actual pool data */
|
||||
@ -306,8 +306,8 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
|
||||
struct HkUpdateResetHelper {
|
||||
DataType dataType = DataType::DATA_SET;
|
||||
DataId dataId;
|
||||
uint8_t updateCounter{};
|
||||
uint8_t currentUpdateCounter{};
|
||||
uint8_t updateCounter;
|
||||
uint8_t currentUpdateCounter;
|
||||
};
|
||||
|
||||
using HkUpdateResetList = std::vector<struct HkUpdateResetHelper>;
|
||||
|
@ -65,7 +65,9 @@ void DeviceHandlerBase::setThermalStateRequestPoolIds(lp_id_t thermalStatePoolId
|
||||
}
|
||||
|
||||
DeviceHandlerBase::~DeviceHandlerBase() {
|
||||
delete comCookie;
|
||||
if (comCookie != nullptr) {
|
||||
delete comCookie;
|
||||
}
|
||||
if (defaultFDIRUsed) {
|
||||
delete fdirInstance;
|
||||
}
|
||||
@ -233,17 +235,26 @@ ReturnValue_t DeviceHandlerBase::initialize() {
|
||||
}
|
||||
|
||||
void DeviceHandlerBase::decrementDeviceReplyMap() {
|
||||
bool timedOut = false;
|
||||
for (std::pair<const DeviceCommandId_t, DeviceReplyInfo>& replyPair : deviceReplyMap) {
|
||||
if (replyPair.second.delayCycles != 0) {
|
||||
if (replyPair.second.countdown != nullptr && replyPair.second.active) {
|
||||
if (replyPair.second.countdown->hasTimedOut()) {
|
||||
resetTimeoutControlledReply(&replyPair.second);
|
||||
timedOut = true;
|
||||
}
|
||||
}
|
||||
if (replyPair.second.delayCycles != 0 && replyPair.second.countdown == nullptr) {
|
||||
replyPair.second.delayCycles--;
|
||||
if (replyPair.second.delayCycles == 0) {
|
||||
if (replyPair.second.periodic) {
|
||||
replyPair.second.delayCycles = replyPair.second.maxDelayCycles;
|
||||
}
|
||||
replyToReply(replyPair.first, replyPair.second, TIMEOUT);
|
||||
missedReply(replyPair.first);
|
||||
resetDelayCyclesControlledReply(&replyPair.second);
|
||||
timedOut = true;
|
||||
}
|
||||
}
|
||||
if (timedOut) {
|
||||
replyToReply(replyPair.first, replyPair.second, TIMEOUT);
|
||||
missedReply(replyPair.first);
|
||||
timedOut = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -359,7 +370,6 @@ void DeviceHandlerBase::doStateMachine() {
|
||||
setMode(MODE_OFF);
|
||||
break;
|
||||
}
|
||||
|
||||
if (currentUptime - timeoutStart >= powerSwitcher->getSwitchDelayMs()) {
|
||||
triggerEvent(MODE_TRANSITION_FAILED, PowerSwitchIF::SWITCH_TIMEOUT, 0);
|
||||
setMode(MODE_ERROR_ON);
|
||||
@ -408,20 +418,22 @@ ReturnValue_t DeviceHandlerBase::isModeCombinationValid(Mode_t mode, Submode_t s
|
||||
|
||||
ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap(
|
||||
DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles, LocalPoolDataSetBase* replyDataSet,
|
||||
size_t replyLen, bool periodic, bool hasDifferentReplyId, DeviceCommandId_t replyId) {
|
||||
size_t replyLen, bool periodic, bool hasDifferentReplyId, DeviceCommandId_t replyId,
|
||||
Countdown* countdown) {
|
||||
// No need to check, as we may try to insert multiple times.
|
||||
insertInCommandMap(deviceCommand, hasDifferentReplyId, replyId);
|
||||
if (hasDifferentReplyId) {
|
||||
return insertInReplyMap(replyId, maxDelayCycles, replyDataSet, replyLen, periodic);
|
||||
return insertInReplyMap(replyId, maxDelayCycles, replyDataSet, replyLen, periodic, countdown);
|
||||
} else {
|
||||
return insertInReplyMap(deviceCommand, maxDelayCycles, replyDataSet, replyLen, periodic);
|
||||
return insertInReplyMap(deviceCommand, maxDelayCycles, replyDataSet, replyLen, periodic,
|
||||
countdown);
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId,
|
||||
uint16_t maxDelayCycles,
|
||||
LocalPoolDataSetBase* dataSet, size_t replyLen,
|
||||
bool periodic) {
|
||||
bool periodic, Countdown* countdown) {
|
||||
DeviceReplyInfo info;
|
||||
info.maxDelayCycles = maxDelayCycles;
|
||||
info.periodic = periodic;
|
||||
@ -429,6 +441,7 @@ ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId,
|
||||
info.replyLen = replyLen;
|
||||
info.dataSet = dataSet;
|
||||
info.command = deviceCommandMap.end();
|
||||
info.countdown = countdown;
|
||||
auto resultPair = deviceReplyMap.emplace(replyId, info);
|
||||
if (resultPair.second) {
|
||||
return RETURN_OK;
|
||||
@ -464,7 +477,8 @@ size_t DeviceHandlerBase::getNextReplyLength(DeviceCommandId_t commandId) {
|
||||
}
|
||||
DeviceReplyIter iter = deviceReplyMap.find(replyId);
|
||||
if (iter != deviceReplyMap.end()) {
|
||||
if (iter->second.delayCycles != 0) {
|
||||
if ((iter->second.delayCycles != 0 && iter->second.countdown == nullptr) ||
|
||||
(iter->second.active && iter->second.countdown != nullptr)) {
|
||||
return iter->second.replyLen;
|
||||
}
|
||||
}
|
||||
@ -500,9 +514,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;
|
||||
@ -808,17 +832,18 @@ void DeviceHandlerBase::handleReply(const uint8_t* receivedData, DeviceCommandId
|
||||
|
||||
DeviceReplyInfo* info = &(iter->second);
|
||||
|
||||
if (info->delayCycles != 0) {
|
||||
if ((info->delayCycles != 0 && info->countdown == nullptr) ||
|
||||
(info->active && info->countdown != nullptr)) {
|
||||
result = interpretDeviceReply(foundId, receivedData);
|
||||
|
||||
if (result == IGNORE_REPLY_DATA) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (info->periodic) {
|
||||
info->delayCycles = info->maxDelayCycles;
|
||||
} else {
|
||||
info->delayCycles = 0;
|
||||
if (info->active && info->countdown != nullptr) {
|
||||
resetTimeoutControlledReply(info);
|
||||
} else if (info->delayCycles != 0) {
|
||||
resetDelayCyclesControlledReply(info);
|
||||
}
|
||||
|
||||
if (result != RETURN_OK) {
|
||||
@ -837,6 +862,24 @@ void DeviceHandlerBase::handleReply(const uint8_t* receivedData, DeviceCommandId
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceHandlerBase::resetTimeoutControlledReply(DeviceReplyInfo* info) {
|
||||
if (info->periodic) {
|
||||
info->countdown->resetTimer();
|
||||
} else {
|
||||
info->active = false;
|
||||
info->countdown->timeOut();
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceHandlerBase::resetDelayCyclesControlledReply(DeviceReplyInfo* info) {
|
||||
if (info->periodic) {
|
||||
info->delayCycles = info->maxDelayCycles;
|
||||
} else {
|
||||
info->delayCycles = 0;
|
||||
info->active = false;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t DeviceHandlerBase::getStorageData(store_address_t storageAddress, uint8_t** data,
|
||||
size_t* len) {
|
||||
size_t lenTmp;
|
||||
@ -959,9 +1002,15 @@ 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;
|
||||
if (info->countdown != nullptr) {
|
||||
info->countdown->resetTimer();
|
||||
}
|
||||
info->active = true;
|
||||
return RETURN_OK;
|
||||
} else {
|
||||
return NO_REPLY_EXPECTED;
|
||||
@ -1196,7 +1245,8 @@ void DeviceHandlerBase::setParentQueue(MessageQueueId_t parentQueueId) {
|
||||
bool DeviceHandlerBase::isAwaitingReply() {
|
||||
std::map<DeviceCommandId_t, DeviceReplyInfo>::iterator iter;
|
||||
for (iter = deviceReplyMap.begin(); iter != deviceReplyMap.end(); ++iter) {
|
||||
if (iter->second.delayCycles != 0) {
|
||||
if ((iter->second.delayCycles != 0 && iter->second.countdown == nullptr) ||
|
||||
(iter->second.active && iter->second.countdown != nullptr)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -1351,6 +1401,13 @@ uint8_t DeviceHandlerBase::getReplyDelayCycles(DeviceCommandId_t deviceCommand)
|
||||
DeviceReplyMap::iterator iter = deviceReplyMap.find(deviceCommand);
|
||||
if (iter == deviceReplyMap.end()) {
|
||||
return 0;
|
||||
} else if (iter->second.countdown != nullptr) {
|
||||
// fake a useful return value for legacy code
|
||||
if (iter->second.active) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return iter->second.delayCycles;
|
||||
}
|
||||
|
@ -207,11 +207,13 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
||||
|
||||
Mode_t getTransitionSourceMode() const;
|
||||
Submode_t getTransitionSourceSubMode() const;
|
||||
void getMode(Mode_t *mode, Submode_t *submode) override;
|
||||
HealthState getHealth() override;
|
||||
ReturnValue_t setHealth(HealthState health) override;
|
||||
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId, ParameterWrapper *parameterWrapper,
|
||||
const ParameterWrapper *newValues, uint16_t startAtIndex) override;
|
||||
virtual void getMode(Mode_t *mode, Submode_t *submode);
|
||||
HealthState getHealth();
|
||||
ReturnValue_t setHealth(HealthState health);
|
||||
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||
ParameterWrapper *parameterWrapper,
|
||||
const ParameterWrapper *newValues,
|
||||
uint16_t startAtIndex) override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
@ -446,6 +448,9 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
||||
* 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
|
||||
* @return - @c RETURN_OK when the command was successfully inserted,
|
||||
* - @c RETURN_FAILED else.
|
||||
*/
|
||||
@ -453,7 +458,8 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
||||
LocalPoolDataSetBase *replyDataSet = nullptr,
|
||||
size_t replyLen = 0, bool periodic = false,
|
||||
bool hasDifferentReplyId = false,
|
||||
DeviceCommandId_t replyId = 0);
|
||||
DeviceCommandId_t replyId = 0,
|
||||
Countdown *countdown = nullptr);
|
||||
/**
|
||||
* @brief This is a helper method to insert replies in the reply map.
|
||||
* @param deviceCommand Identifier of the reply to add.
|
||||
@ -463,12 +469,15 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
||||
* by the device repeatedly without request) or not. Default is aperiodic (0).
|
||||
* 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
|
||||
* @return - @c RETURN_OK when the command was successfully inserted,
|
||||
* - @c RETURN_FAILED else.
|
||||
*/
|
||||
ReturnValue_t insertInReplyMap(DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles,
|
||||
LocalPoolDataSetBase *dataSet = nullptr, size_t replyLen = 0,
|
||||
bool periodic = false);
|
||||
bool periodic = false, Countdown *countdown = nullptr);
|
||||
|
||||
/**
|
||||
* @brief A simple command to add a command to the commandList.
|
||||
@ -781,6 +790,11 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
||||
LocalPoolDataSetBase *dataSet = nullptr;
|
||||
//! The command that expects this reply.
|
||||
DeviceCommandMap::iterator command;
|
||||
//! Instead of using delayCycles to specify the maximum time to wait for the device reply, it
|
||||
//! is also possible specify a countdown
|
||||
Countdown *countdown = nullptr;
|
||||
//! will be set to true when reply is enabled
|
||||
bool active = false;
|
||||
};
|
||||
|
||||
using DeviceReplyMap = std::map<DeviceCommandId_t, DeviceReplyInfo>;
|
||||
@ -1040,9 +1054,11 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
||||
bool isAwaitingReply();
|
||||
|
||||
void handleDeviceTM(SerializeIF *dataSet, DeviceCommandId_t replyId, bool forceDirectTm = false);
|
||||
// void handleDeviceTM(uint8_t* data, size_t dataSize, DeviceCommandId_t replyId,
|
||||
// bool forceDirectTm);
|
||||
|
||||
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
||||
uint32_t *msToReachTheMode) override;
|
||||
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
||||
uint32_t *msToReachTheMode);
|
||||
|
||||
virtual ReturnValue_t letChildHandleMessage(CommandMessage *message);
|
||||
|
||||
@ -1058,7 +1074,8 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
||||
/**
|
||||
* Same as triggerEvent, but for forwarding if object is used as proxy.
|
||||
*/
|
||||
void forwardEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0) const override;
|
||||
virtual void forwardEvent(Event event, uint32_t parameter1 = 0,
|
||||
uint32_t parameter2 = 0) const override;
|
||||
|
||||
/**
|
||||
* Checks if current mode is transitional mode.
|
||||
@ -1239,6 +1256,17 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
||||
*/
|
||||
void doGetRead(void);
|
||||
|
||||
/**
|
||||
* @brief Resets replies which use a timeout to detect missed replies.
|
||||
*/
|
||||
void resetTimeoutControlledReply(DeviceReplyInfo *info);
|
||||
|
||||
/**
|
||||
* @brief Resets replies which use a number of maximum delay cycles to detect
|
||||
* missed replies.
|
||||
*/
|
||||
void resetDelayCyclesControlledReply(DeviceReplyInfo *info);
|
||||
|
||||
/**
|
||||
* Retrive data from the #IPCStore.
|
||||
*
|
||||
|
@ -88,6 +88,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,
|
||||
|
@ -14,6 +14,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);
|
||||
|
||||
|
@ -36,7 +36,7 @@ class HasHealthIF {
|
||||
12,
|
||||
severity::MEDIUM); //!< Recovery was completed. Not necessarily successful. No parameters.
|
||||
|
||||
virtual ~HasHealthIF() = default;
|
||||
virtual ~HasHealthIF() {}
|
||||
|
||||
virtual MessageQueueId_t getCommandQueue() const = 0;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -55,7 +55,7 @@ class HousekeepingSnapshot : public SerializeIF {
|
||||
: timeStamp(timeStamp), timeStampSize(timeStampSize), updateData(dataSetPtr){};
|
||||
|
||||
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
||||
Endianness streamEndianness) const override {
|
||||
Endianness streamEndianness) const {
|
||||
if (timeStamp != nullptr) {
|
||||
/* Endianness will always be MACHINE, so we can simply use memcpy
|
||||
here. */
|
||||
@ -70,7 +70,7 @@ class HousekeepingSnapshot : public SerializeIF {
|
||||
return updateData->serialize(buffer, size, maxSize, streamEndianness);
|
||||
}
|
||||
|
||||
virtual size_t getSerializedSize() const override {
|
||||
virtual size_t getSerializedSize() const {
|
||||
if (updateData == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -10,25 +10,25 @@ class MessageQueueBase : public MessageQueueIF {
|
||||
virtual ~MessageQueueBase();
|
||||
|
||||
// Default implementations for MessageQueueIF where possible
|
||||
MessageQueueId_t getLastPartner() const override;
|
||||
MessageQueueId_t getId() const override;
|
||||
MqArgs& getMqArgs() override;
|
||||
void setDefaultDestination(MessageQueueId_t defaultDestination) override;
|
||||
MessageQueueId_t getDefaultDestination() const override;
|
||||
bool isDefaultDestinationSet() const override;
|
||||
ReturnValue_t sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
||||
bool ignoreFault) override;
|
||||
ReturnValue_t sendToDefault(MessageQueueMessageIF* message) override;
|
||||
ReturnValue_t reply(MessageQueueMessageIF* message) override;
|
||||
ReturnValue_t receiveMessage(MessageQueueMessageIF* message,
|
||||
MessageQueueId_t* receivedFrom) override;
|
||||
ReturnValue_t sendToDefaultFrom(MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
|
||||
bool ignoreFault = false) override;
|
||||
virtual MessageQueueId_t getLastPartner() const override;
|
||||
virtual MessageQueueId_t getId() const override;
|
||||
virtual MqArgs& getMqArgs() override;
|
||||
virtual void setDefaultDestination(MessageQueueId_t defaultDestination) override;
|
||||
virtual MessageQueueId_t getDefaultDestination() const override;
|
||||
virtual bool isDefaultDestinationSet() const override;
|
||||
virtual ReturnValue_t sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
||||
bool ignoreFault) override;
|
||||
virtual ReturnValue_t sendToDefault(MessageQueueMessageIF* message) override;
|
||||
virtual ReturnValue_t reply(MessageQueueMessageIF* message) override;
|
||||
virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message,
|
||||
MessageQueueId_t* receivedFrom) override;
|
||||
virtual ReturnValue_t sendToDefaultFrom(MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
|
||||
bool ignoreFault = false) override;
|
||||
|
||||
// OSAL specific, forward the abstract function
|
||||
ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override = 0;
|
||||
ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
||||
MessageQueueId_t sentFrom, bool ignoreFault = false) override = 0;
|
||||
virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message) = 0;
|
||||
virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
||||
MessageQueueId_t sentFrom, bool ignoreFault = false) = 0;
|
||||
|
||||
protected:
|
||||
MessageQueueId_t id = MessageQueueIF::NO_QUEUE;
|
||||
|
@ -17,8 +17,8 @@ class AbsLimitMonitor : public MonitorBase<T> {
|
||||
limit(limit),
|
||||
violationEvent(violationEvent),
|
||||
aboveIsViolation(aboveIsViolation) {}
|
||||
virtual ~AbsLimitMonitor() = default;
|
||||
ReturnValue_t checkSample(T sample, T *crossedLimit) override {
|
||||
virtual ~AbsLimitMonitor() {}
|
||||
virtual ReturnValue_t checkSample(T sample, T *crossedLimit) {
|
||||
*crossedLimit = limit;
|
||||
if (aboveIsViolation) {
|
||||
if ((std::abs(sample) > limit)) {
|
||||
@ -32,9 +32,9 @@ class AbsLimitMonitor : public MonitorBase<T> {
|
||||
return HasReturnvaluesIF::RETURN_OK; // We're not out of range.
|
||||
}
|
||||
|
||||
ReturnValue_t getParameter(uint8_t domainId, uint8_t parameterId,
|
||||
ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
|
||||
uint16_t startAtIndex) override {
|
||||
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
||||
ParameterWrapper *parameterWrapper,
|
||||
const ParameterWrapper *newValues, uint16_t startAtIndex) {
|
||||
ReturnValue_t result = this->MonitorBase<T>::getParameter(
|
||||
domainId, parameterId, parameterWrapper, newValues, startAtIndex);
|
||||
// We'll reuse the DOMAIN_ID of MonitorReporter,
|
||||
@ -61,7 +61,7 @@ class AbsLimitMonitor : public MonitorBase<T> {
|
||||
void setLimit(T value) { limit = value; }
|
||||
|
||||
protected:
|
||||
void sendTransitionEvent(T currentValue, ReturnValue_t state) override {
|
||||
void sendTransitionEvent(T currentValue, ReturnValue_t state) {
|
||||
switch (state) {
|
||||
case MonitoringIF::OUT_OF_RANGE:
|
||||
EventManagerIF::triggerEvent(this->reportingId, violationEvent, this->globalPoolId.objectId,
|
||||
|
@ -51,8 +51,9 @@ class MonitorReporter : public HasParametersIF {
|
||||
return state;
|
||||
}
|
||||
|
||||
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId, ParameterWrapper *parameterWrapper,
|
||||
const ParameterWrapper *newValues, uint16_t startAtIndex) override {
|
||||
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||
ParameterWrapper *parameterWrapper,
|
||||
const ParameterWrapper *newValues, uint16_t startAtIndex) {
|
||||
if (domainId != monitorId) {
|
||||
return INVALID_DOMAIN_ID;
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -51,7 +51,7 @@ class HasParametersIF {
|
||||
return (domainId << 24) + (uniqueId << 16) + linearIndex;
|
||||
}
|
||||
|
||||
virtual ~HasParametersIF() = default;
|
||||
virtual ~HasParametersIF() {}
|
||||
|
||||
/**
|
||||
* This is the generic function overriden by child classes to set
|
||||
|
@ -63,13 +63,13 @@ class Fuse : public SystemObject,
|
||||
SerializeIF::Endianness streamEndianness) override;
|
||||
void setAllMonitorsToUnchecked();
|
||||
ReturnValue_t performOperation(uint8_t opCode);
|
||||
MessageQueueId_t getCommandQueue() const override;
|
||||
MessageQueueId_t getCommandQueue() const;
|
||||
void setDataPoolEntriesInvalid();
|
||||
ReturnValue_t setHealth(HealthState health) override;
|
||||
HasHealthIF::HealthState getHealth() override;
|
||||
ReturnValue_t setHealth(HealthState health);
|
||||
HasHealthIF::HealthState getHealth();
|
||||
|
||||
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId, ParameterWrapper *parameterWrapper,
|
||||
const ParameterWrapper *newValues, uint16_t startAtIndex) override;
|
||||
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
||||
|
||||
private:
|
||||
uint8_t oldFuseState;
|
||||
@ -81,7 +81,7 @@ class Fuse : public SystemObject,
|
||||
template <typename... Args>
|
||||
PowerMonitor(Args... args) : MonitorReporter<float>(std::forward<Args>(args)...) {}
|
||||
ReturnValue_t checkPower(float sample, float lowerLimit, float upperLimit);
|
||||
void sendTransitionEvent(float currentValue, ReturnValue_t state_) override {}
|
||||
void sendTransitionEvent(float currentValue, ReturnValue_t state) {}
|
||||
};
|
||||
PowerMonitor powerMonitor;
|
||||
StaticLocalDataSet<3> set;
|
||||
|
@ -10,15 +10,15 @@ class PowerComponent : public PowerComponentIF {
|
||||
PowerComponent(object_id_t setId, uint8_t moduleId, float minPower, float maxPower,
|
||||
uint8_t switchId1, bool twoSwitches = false, uint8_t switchId2 = 0xFF);
|
||||
|
||||
object_id_t getDeviceObjectId() override;
|
||||
virtual object_id_t getDeviceObjectId();
|
||||
|
||||
uint8_t getSwitchId1() override;
|
||||
uint8_t getSwitchId2() override;
|
||||
virtual uint8_t getSwitchId1();
|
||||
virtual uint8_t getSwitchId2();
|
||||
|
||||
bool hasTwoSwitches() override;
|
||||
bool hasTwoSwitches();
|
||||
|
||||
float getMin() override;
|
||||
float getMax() override;
|
||||
float getMin();
|
||||
float getMax();
|
||||
|
||||
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
||||
Endianness streamEndianness) const override;
|
||||
@ -29,7 +29,7 @@ class PowerComponent : public PowerComponentIF {
|
||||
Endianness streamEndianness) override;
|
||||
|
||||
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId, ParameterWrapper* parameterWrapper,
|
||||
const ParameterWrapper* newValues, uint16_t startAtIndex) override;
|
||||
const ParameterWrapper* newValues, uint16_t startAtIndex);
|
||||
|
||||
private:
|
||||
const object_id_t deviceObjectId = objects::NO_OBJECT;
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
class PowerComponentIF : public SerializeIF, public HasParametersIF {
|
||||
public:
|
||||
~PowerComponentIF() override = default;
|
||||
virtual ~PowerComponentIF() {}
|
||||
|
||||
virtual object_id_t getDeviceObjectId() = 0;
|
||||
|
||||
|
@ -69,7 +69,7 @@ class FailureReport : public SerializeIF { //!< [EXPORT] : [SUBSERVICE] 2, 4, 6
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t getSerializedSize() const override {
|
||||
virtual size_t getSerializedSize() const {
|
||||
size_t size = 0;
|
||||
size += SerializeAdapter::getSerializedSize(&packetId);
|
||||
size += sizeof(packetSequenceControl);
|
||||
|
@ -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() = default;
|
||||
virtual ~SerializeIF() {}
|
||||
/**
|
||||
* @brief
|
||||
* Function to serialize the object into a buffer with maxSize. Size represents the written
|
||||
@ -66,7 +66,7 @@ class SerializeIF {
|
||||
* Gets the size of a object if it would be serialized in a buffer
|
||||
* @return Size of serialized object
|
||||
*/
|
||||
[[nodiscard]] virtual size_t getSerializedSize() const = 0;
|
||||
virtual size_t getSerializedSize() const = 0;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
|
@ -10,7 +10,7 @@ StorageAccessor::StorageAccessor(store_address_t storeId) : ConstStorageAccessor
|
||||
StorageAccessor::StorageAccessor(store_address_t storeId, StorageManagerIF* store)
|
||||
: ConstStorageAccessor(storeId, store) {}
|
||||
|
||||
StorageAccessor& StorageAccessor::operator=(StorageAccessor&& other) noexcept {
|
||||
StorageAccessor& StorageAccessor::operator=(StorageAccessor&& other) {
|
||||
// Call the parent move assignment and also assign own member.
|
||||
dataPointer = other.dataPointer;
|
||||
ConstStorageAccessor::operator=(std::move(other));
|
||||
@ -18,7 +18,7 @@ StorageAccessor& StorageAccessor::operator=(StorageAccessor&& other) noexcept {
|
||||
}
|
||||
|
||||
// Call the parent move ctor and also transfer own member.
|
||||
StorageAccessor::StorageAccessor(StorageAccessor&& other) noexcept
|
||||
StorageAccessor::StorageAccessor(StorageAccessor&& other)
|
||||
: ConstStorageAccessor(std::move(other)), dataPointer(other.dataPointer) {}
|
||||
|
||||
ReturnValue_t StorageAccessor::getDataCopy(uint8_t* pointer, size_t maxSize) {
|
||||
|
@ -14,7 +14,7 @@ class StorageAccessor : public ConstStorageAccessor {
|
||||
friend class LocalPool;
|
||||
|
||||
public:
|
||||
explicit StorageAccessor(store_address_t storeId);
|
||||
StorageAccessor(store_address_t storeId);
|
||||
StorageAccessor(store_address_t storeId, StorageManagerIF* store);
|
||||
|
||||
/**
|
||||
@ -25,8 +25,8 @@ class StorageAccessor : public ConstStorageAccessor {
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
StorageAccessor& operator=(StorageAccessor&&) noexcept;
|
||||
StorageAccessor(StorageAccessor&&) noexcept;
|
||||
StorageAccessor& operator=(StorageAccessor&&);
|
||||
StorageAccessor(StorageAccessor&&);
|
||||
|
||||
ReturnValue_t write(uint8_t* data, size_t size, uint16_t offset = 0);
|
||||
uint8_t* data();
|
||||
|
@ -29,11 +29,11 @@ CFDPDistributor::TcMqMapIter CFDPDistributor::selectDestination() {
|
||||
storeId.packetIndex);
|
||||
#endif
|
||||
#endif
|
||||
auto queueMapIt = this->queueMap.end();
|
||||
TcMqMapIter queueMapIt = this->queueMap.end();
|
||||
if (this->currentPacket == nullptr) {
|
||||
return queueMapIt;
|
||||
}
|
||||
this->currentPacket->setStoreAddress(this->currentMessage.getStorageId(), currentPacket);
|
||||
this->currentPacket->setStoreAddress(this->currentMessage.getStorageId());
|
||||
if (currentPacket->getWholeData() != nullptr) {
|
||||
tcStatus = checker.checkPacket(currentPacket);
|
||||
if (tcStatus != HasReturnvaluesIF::RETURN_OK) {
|
||||
|
@ -190,13 +190,13 @@ ReturnValue_t Heater::performOperation(uint8_t opCode) {
|
||||
}
|
||||
|
||||
void Heater::setSwitch(uint8_t number, ReturnValue_t state, uint32_t* uptimeOfSwitching) {
|
||||
if (powerSwitcher == nullptr) {
|
||||
if (powerSwitcher == NULL) {
|
||||
return;
|
||||
}
|
||||
if (powerSwitcher->getSwitchState(number) == state) {
|
||||
*uptimeOfSwitching = INVALID_UPTIME;
|
||||
} else {
|
||||
if (*uptimeOfSwitching == INVALID_UPTIME) {
|
||||
if ((*uptimeOfSwitching == INVALID_UPTIME)) {
|
||||
powerSwitcher->sendSwitchCommand(number, state);
|
||||
Clock::getUptime(uptimeOfSwitching);
|
||||
} else {
|
||||
|
@ -11,11 +11,11 @@ class CFDPPacket : public SpacePacketBase {
|
||||
* forwards the data pointer to the parent SpacePacketBase class.
|
||||
* @param setData The position where the packet data lies.
|
||||
*/
|
||||
explicit CFDPPacket(const uint8_t* setData);
|
||||
CFDPPacket(const uint8_t* setData);
|
||||
/**
|
||||
* This is the empty default destructor.
|
||||
*/
|
||||
~CFDPPacket() override;
|
||||
virtual ~CFDPPacket();
|
||||
|
||||
/**
|
||||
* This is a debugging helper method that prints the whole packet content
|
||||
|
@ -2,44 +2,48 @@
|
||||
|
||||
#include "fsfw/objectmanager/ObjectManager.h"
|
||||
|
||||
StorageManagerIF* CFDPPacketStored::store = nullptr;
|
||||
|
||||
CFDPPacketStored::CFDPPacketStored() : CFDPPacket(nullptr) {}
|
||||
|
||||
CFDPPacketStored::CFDPPacketStored(store_address_t setAddress) : CFDPPacket(nullptr) {
|
||||
CFDPPacketStored::setStoreAddress(setAddress, this);
|
||||
this->setStoreAddress(setAddress);
|
||||
}
|
||||
|
||||
CFDPPacketStored::CFDPPacketStored(const uint8_t* data, size_t size) : CFDPPacket(data) {
|
||||
if (this->getFullSize() != size) {
|
||||
return;
|
||||
}
|
||||
if (CFDPPacketStored::checkAndSetStore()) {
|
||||
ReturnValue_t status = STORE->addData(&storeAddress, data, size);
|
||||
if (this->checkAndSetStore()) {
|
||||
ReturnValue_t status = store->addData(&storeAddress, data, size);
|
||||
if (status != HasReturnvaluesIF::RETURN_OK) {
|
||||
this->setData(nullptr, -1);
|
||||
}
|
||||
const uint8_t* storePtr = nullptr;
|
||||
// Repoint base data pointer to the data in the store.
|
||||
STORE->getData(storeAddress, &storePtr, &size);
|
||||
store->getData(storeAddress, &storePtr, &size);
|
||||
this->setData(const_cast<uint8_t*>(storePtr), size);
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t CFDPPacketStored::deletePacket() {
|
||||
ReturnValue_t result = CFDPPacketStored::STORE->deleteData(this->storeAddress);
|
||||
ReturnValue_t result = this->store->deleteData(this->storeAddress);
|
||||
this->storeAddress.raw = StorageManagerIF::INVALID_ADDRESS;
|
||||
// To circumvent size checks
|
||||
this->setData(nullptr, -1);
|
||||
return result;
|
||||
}
|
||||
|
||||
void CFDPPacketStored::setStoreAddress(store_address_t setAddress,
|
||||
RedirectableDataPointerIF* packet) {
|
||||
// CFDPPacket* CFDPPacketStored::getPacketBase() {
|
||||
// return this;
|
||||
// }
|
||||
void CFDPPacketStored::setStoreAddress(store_address_t setAddress) {
|
||||
this->storeAddress = setAddress;
|
||||
const uint8_t* tempData = nullptr;
|
||||
size_t tempSize;
|
||||
ReturnValue_t status = StorageManagerIF::RETURN_FAILED;
|
||||
if (CFDPPacketStored::checkAndSetStore()) {
|
||||
status = CFDPPacketStored::STORE->getData(this->storeAddress, &tempData, &tempSize);
|
||||
if (this->checkAndSetStore()) {
|
||||
status = this->store->getData(this->storeAddress, &tempData, &tempSize);
|
||||
}
|
||||
if (status == StorageManagerIF::RETURN_OK) {
|
||||
this->setData(const_cast<uint8_t*>(tempData), tempSize);
|
||||
@ -52,17 +56,33 @@ void CFDPPacketStored::setStoreAddress(store_address_t setAddress,
|
||||
|
||||
store_address_t CFDPPacketStored::getStoreAddress() { return this->storeAddress; }
|
||||
|
||||
CFDPPacketStored::~CFDPPacketStored() = default;
|
||||
CFDPPacketStored::~CFDPPacketStored() {}
|
||||
|
||||
ReturnValue_t CFDPPacketStored::getData(const uint8_t** dataPtr, size_t* dataSize) {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
// ReturnValue_t CFDPPacketStored::setData(const uint8_t *data) {
|
||||
// return HasReturnvaluesIF::RETURN_OK;
|
||||
// }
|
||||
|
||||
bool CFDPPacketStored::checkAndSetStore() {
|
||||
if (this->store == nullptr) {
|
||||
this->store = ObjectManager::instance()->get<StorageManagerIF>(objects::TC_STORE);
|
||||
if (this->store == nullptr) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "CFDPPacketStored::CFDPPacketStored: TC Store not found!" << std::endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CFDPPacketStored::isSizeCorrect() {
|
||||
const uint8_t* temp_data = nullptr;
|
||||
size_t temp_size;
|
||||
ReturnValue_t status =
|
||||
CFDPPacketStored::STORE->getData(this->storeAddress, &temp_data, &temp_size);
|
||||
ReturnValue_t status = this->store->getData(this->storeAddress, &temp_data, &temp_size);
|
||||
if (status == StorageManagerIF::RETURN_OK) {
|
||||
if (this->getFullSize() == temp_size) {
|
||||
return true;
|
||||
|
@ -16,10 +16,10 @@ class CFDPPacketStored : public CFDPPacket, public TcPacketStoredBase {
|
||||
* Create stored packet from existing packet in store
|
||||
* @param setAddress
|
||||
*/
|
||||
explicit CFDPPacketStored(store_address_t setAddress);
|
||||
CFDPPacketStored(store_address_t setAddress);
|
||||
CFDPPacketStored();
|
||||
|
||||
~CFDPPacketStored() override;
|
||||
virtual ~CFDPPacketStored();
|
||||
|
||||
/**
|
||||
* Getter function for the raw data.
|
||||
@ -27,22 +27,37 @@ class CFDPPacketStored : public CFDPPacket, public TcPacketStoredBase {
|
||||
* @param dataSize [out] Address of size to set.
|
||||
* @return -@c RETURN_OK if data was retrieved successfully.
|
||||
*/
|
||||
ReturnValue_t getData(const uint8_t** dataPtr, size_t* dataSize) override;
|
||||
ReturnValue_t getData(const uint8_t** dataPtr, size_t* dataSize);
|
||||
|
||||
void setStoreAddress(store_address_t setAddress, RedirectableDataPointerIF* packet) override;
|
||||
void setStoreAddress(store_address_t setAddress);
|
||||
|
||||
store_address_t getStoreAddress() override;
|
||||
store_address_t getStoreAddress();
|
||||
|
||||
ReturnValue_t deletePacket() override;
|
||||
ReturnValue_t deletePacket();
|
||||
|
||||
private:
|
||||
bool isSizeCorrect() override;
|
||||
bool isSizeCorrect();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* This is a pointer to the store all instances of the class use.
|
||||
* If the store is not yet set (i.e. @c store is NULL), every constructor
|
||||
* call tries to set it and throws an error message in case of failures.
|
||||
* The default store is objects::TC_STORE.
|
||||
*/
|
||||
static StorageManagerIF* store;
|
||||
/**
|
||||
* The address where the packet data of the object instance is stored.
|
||||
*/
|
||||
store_address_t storeAddress;
|
||||
/**
|
||||
* A helper method to check if a store is assigned to the class.
|
||||
* If not, the method tries to retrieve the store from the global
|
||||
* ObjectManager.
|
||||
* @return @li @c true if the store is linked or could be created.
|
||||
* @li @c false otherwise.
|
||||
*/
|
||||
bool checkAndSetStore();
|
||||
};
|
||||
|
||||
#endif /* FSFW_INC_FSFW_TMTCPACKET_CFDP_CFDPPACKETSTORED_H_ */
|
||||
|
@ -19,7 +19,7 @@ class TcPacketStoredBase : public TcPacketStoredIF {
|
||||
* Constructor to set to an existing store address.
|
||||
* @param setAddress
|
||||
*/
|
||||
explicit TcPacketStoredBase(store_address_t setAddress);
|
||||
TcPacketStoredBase(store_address_t setAddress);
|
||||
/**
|
||||
* Another constructor to create a TcPacket from a raw packet stream.
|
||||
* Takes the data and adds it unchecked to the TcStore.
|
||||
@ -28,7 +28,7 @@ class TcPacketStoredBase : public TcPacketStoredIF {
|
||||
*/
|
||||
TcPacketStoredBase(const uint8_t* data, uint32_t size);
|
||||
|
||||
~TcPacketStoredBase() override;
|
||||
virtual ~TcPacketStoredBase();
|
||||
|
||||
/**
|
||||
* Getter function for the raw data.
|
||||
@ -70,7 +70,6 @@ class TcPacketStoredBase : public TcPacketStoredIF {
|
||||
* The address where the packet data of the object instance is stored.
|
||||
*/
|
||||
store_address_t storeAddress;
|
||||
|
||||
/**
|
||||
* A helper method to check if a store is assigned to the class.
|
||||
* If not, the method tries to retrieve the store from the global
|
||||
|
@ -16,8 +16,6 @@ class TcPacketStoredIF {
|
||||
* With this call, the stored packet can be set to another packet in a store. This is useful
|
||||
* if the packet is a class member and used for more than one packet.
|
||||
* @param setAddress The new packet id to link to.
|
||||
* @param packet Explicit packet instance. The setData function should be called on this
|
||||
* pointer
|
||||
*/
|
||||
virtual void setStoreAddress(store_address_t setAddress, RedirectableDataPointerIF* packet) = 0;
|
||||
|
||||
|
@ -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()
|
1
src/fsfw_hal/common/gpio/CMakeLists.txt
Normal file
1
src/fsfw_hal/common/gpio/CMakeLists.txt
Normal file
@ -0,0 +1 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE GpioCookie.cpp)
|
3
src/fsfw_hal/devicehandlers/CMakeLists.txt
Normal file
3
src/fsfw_hal/devicehandlers/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
||||
target_sources(
|
||||
${LIB_FSFW_NAME} PRIVATE GyroL3GD20Handler.cpp MgmRM3100Handler.cpp
|
||||
MgmLIS3MDLHandler.cpp)
|
@ -17,6 +17,8 @@ MgmLIS3MDLHandler::MgmLIS3MDLHandler(object_id_t objectId, object_id_t deviceCom
|
||||
registers[4] = MGMLIS3MDL::CTRL_REG5_DEFAULT;
|
||||
}
|
||||
|
||||
MgmLIS3MDLHandler::~MgmLIS3MDLHandler() {}
|
||||
|
||||
void MgmLIS3MDLHandler::doStartUp() {
|
||||
switch (internalState) {
|
||||
case (InternalState::STATE_NONE): {
|
||||
@ -88,7 +90,7 @@ ReturnValue_t MgmLIS3MDLHandler::buildTransitionDeviceCommand(DeviceCommandId_t
|
||||
|
||||
uint8_t MgmLIS3MDLHandler::readCommand(uint8_t command, bool continuousCom) {
|
||||
command |= (1 << MGMLIS3MDL::RW_BIT);
|
||||
if (continuousCom) {
|
||||
if (continuousCom == true) {
|
||||
command |= (1 << MGMLIS3MDL::MS_BIT);
|
||||
}
|
||||
return command;
|
||||
@ -96,7 +98,7 @@ uint8_t MgmLIS3MDLHandler::readCommand(uint8_t command, bool continuousCom) {
|
||||
|
||||
uint8_t MgmLIS3MDLHandler::writeCommand(uint8_t command, bool continuousCom) {
|
||||
command &= ~(1 << MGMLIS3MDL::RW_BIT);
|
||||
if (continuousCom) {
|
||||
if (continuousCom == true) {
|
||||
command |= (1 << MGMLIS3MDL::MS_BIT);
|
||||
}
|
||||
return command;
|
@ -28,7 +28,7 @@ class MgmLIS3MDLHandler : public DeviceHandlerBase {
|
||||
|
||||
MgmLIS3MDLHandler(uint32_t objectId, object_id_t deviceCommunication, CookieIF *comCookie,
|
||||
uint32_t transitionDelay);
|
||||
~MgmLIS3MDLHandler() override = default;
|
||||
virtual ~MgmLIS3MDLHandler();
|
||||
|
||||
void enablePeriodicPrintouts(bool enable, uint8_t divider);
|
||||
/**
|
||||
@ -46,7 +46,7 @@ class MgmLIS3MDLHandler : public DeviceHandlerBase {
|
||||
void doShutDown() override;
|
||||
void doStartUp() override;
|
||||
void doTransition(Mode_t modeFrom, Submode_t subModeFrom) override;
|
||||
uint32_t getTransitionDelayMs(Mode_t from, Mode_t to) override;
|
||||
virtual uint32_t getTransitionDelayMs(Mode_t from, Mode_t to) override;
|
||||
ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand, const uint8_t *commandData,
|
||||
size_t commandDataLen) override;
|
||||
ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t *id) override;
|
||||
@ -60,9 +60,9 @@ class MgmLIS3MDLHandler : public DeviceHandlerBase {
|
||||
* @param packet
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) override;
|
||||
virtual ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) override;
|
||||
void fillCommandAndReplyMap() override;
|
||||
void modeChanged() override;
|
||||
void modeChanged(void) override;
|
||||
ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
|
||||
LocalDataPoolManager &poolManager) override;
|
||||
|
||||
@ -72,6 +72,8 @@ class MgmLIS3MDLHandler : public DeviceHandlerBase {
|
||||
static const uint8_t SINGLE_COMMAND_ANSWER_LEN = 2;
|
||||
|
||||
uint32_t transitionDelay;
|
||||
// Single SPI command has 2 bytes, first for adress, second for content
|
||||
size_t singleComandSize = 2;
|
||||
// Has the size for all adresses of the lis3mdl + the continous write bit
|
||||
uint8_t commandBuffer[MGMLIS3MDL::NR_OF_DATA_AND_CFG_REGISTERS + 1];
|
||||
|
||||
@ -86,6 +88,7 @@ class MgmLIS3MDLHandler : public DeviceHandlerBase {
|
||||
*/
|
||||
uint8_t registers[MGMLIS3MDL::NR_OF_CTRL_REGISTERS];
|
||||
|
||||
uint8_t statusRegister = 0;
|
||||
bool goToNormalMode = false;
|
||||
|
||||
enum class InternalState {
|
||||
@ -108,14 +111,14 @@ class MgmLIS3MDLHandler : public DeviceHandlerBase {
|
||||
* @param single command to set the read-bit at
|
||||
* @param boolean to select a continuous read bit, default = false
|
||||
*/
|
||||
static uint8_t readCommand(uint8_t command, bool continuousCom = false);
|
||||
uint8_t readCommand(uint8_t command, bool continuousCom = false);
|
||||
|
||||
/**
|
||||
* Sets the write bit for the command
|
||||
* @param single command to set the write-bit at
|
||||
* @param boolean to select a continuous write bit, default = false
|
||||
*/
|
||||
static uint8_t writeCommand(uint8_t command, bool continuousCom = false);
|
||||
uint8_t writeCommand(uint8_t command, bool continuousCom = false);
|
||||
|
||||
/**
|
||||
* This Method gets the full scale for the measurement range
|
@ -329,9 +329,9 @@ ReturnValue_t MgmRM3100Handler::handleDataReadout(const uint8_t *packet) {
|
||||
int32_t fieldStrengthRawZ = ((packet[7] << 24) | (packet[8] << 16) | (packet[3] << 8)) >> 8;
|
||||
|
||||
// Now scale to physical value in microtesla
|
||||
float fieldStrengthX = static_cast<float>(fieldStrengthRawX) * scaleFactorX;
|
||||
float fieldStrengthY = static_cast<float>(fieldStrengthRawY) * scaleFactorY;
|
||||
float fieldStrengthZ = static_cast<float>(fieldStrengthRawZ) * scaleFactorZ;
|
||||
float fieldStrengthX = fieldStrengthRawX * scaleFactorX;
|
||||
float fieldStrengthY = fieldStrengthRawY * scaleFactorX;
|
||||
float fieldStrengthZ = fieldStrengthRawZ * scaleFactorX;
|
||||
|
||||
if (periodicPrintout) {
|
||||
if (debugDivider.checkAndIncrement()) {
|
@ -72,6 +72,7 @@ class MgmRM3100Handler : public DeviceHandlerBase {
|
||||
RM3100::Rm3100PrimaryDataset primaryDataset;
|
||||
|
||||
uint8_t commandBuffer[10];
|
||||
uint8_t commandBufferLen = 0;
|
||||
|
||||
uint8_t cmmRegValue = RM3100::CMM_VALUE;
|
||||
uint8_t tmrcRegValue = RM3100::TMRC_DEFAULT_VALUE;
|
||||
@ -99,4 +100,4 @@ class MgmRM3100Handler : public DeviceHandlerBase {
|
||||
PeriodicOperationDivider debugDivider = PeriodicOperationDivider(3);
|
||||
};
|
||||
|
||||
#endif /* MISSION_DEVICES_MGMRM3100HANDLER_H_ */
|
||||
#endif /* MISSION_DEVICEHANDLING_MGMRM3100HANDLER_H_ */
|
21
src/fsfw_hal/linux/CMakeLists.txt
Normal file
21
src/fsfw_hal/linux/CMakeLists.txt
Normal file
@ -0,0 +1,21 @@
|
||||
if(FSFW_HAL_ADD_RASPBERRY_PI)
|
||||
add_subdirectory(rpi)
|
||||
endif()
|
||||
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE UnixFileGuard.cpp CommandExecutor.cpp
|
||||
utility.cpp)
|
||||
|
||||
if(FSFW_HAL_LINUX_ADD_PERIPHERAL_DRIVERS)
|
||||
if(FSFW_HAL_LINUX_ADD_LIBGPIOD)
|
||||
add_subdirectory(gpio)
|
||||
endif()
|
||||
add_subdirectory(uart)
|
||||
# Adding those does not really make sense on Apple systems which are generally
|
||||
# host systems. It won't even compile as the headers are missing
|
||||
if(NOT APPLE)
|
||||
add_subdirectory(i2c)
|
||||
add_subdirectory(spi)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_subdirectory(uio)
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user