Compare commits
225 Commits
bbe21e7e89
...
mueller/sp
Author | SHA1 | Date | |
---|---|---|---|
06111ec3ed | |||
51087518b0 | |||
e3d1308205 | |||
99c72fd00b | |||
811287aac8 | |||
23fb06578b | |||
c86e99e6dc | |||
4092de911c | |||
00952e15b0 | |||
01ebf0f4d3 | |||
99fe6487c8 | |||
d4a6f987bc | |||
57bac4f262 | |||
cfa6843c8f | |||
b6b3221b22 | |||
deee4c43c0 | |||
ad0b6f1ed1 | |||
ec03a674bd | |||
9e3d5b6a0c | |||
994c7299b9 | |||
57a830cb46 | |||
c215508a12 | |||
ccadbb5942 | |||
a83b86ccd2 | |||
3046822e88 | |||
6442dd0c38 | |||
9b6fa646ed | |||
2d9d83a1c5 | |||
c561271070 | |||
b99160e850 | |||
d11f898f70 | |||
34e124f2db | |||
e05c72b062 | |||
2ca8523215 | |||
25775614de | |||
0410ecd9e3 | |||
0fe1b70bae | |||
c5b4499d98 | |||
458aa5c265 | |||
4499c9bf04 | |||
eb0223bc51 | |||
d8bd08dd8c | |||
18c2847b08 | |||
d45cda93b2 | |||
3448292e8a | |||
d983305ea5 | |||
c83cc492c0 | |||
ece32f88f4 | |||
dd9e28fca1 | |||
46cfe65321 | |||
7b7f5d7e0a | |||
fd112ed597 | |||
96eb8fc21f | |||
88fa4f1d9d | |||
5989c88c88 | |||
da8a108cb7 | |||
75132c1e39 | |||
281f91ec5d | |||
15352b539d | |||
4015e85506 | |||
118f1da8dd | |||
8b0508d50a | |||
8a40878eb5 | |||
220469a2dd | |||
83de5b4ec1 | |||
fe1c51ae6d | |||
10cc954d27 | |||
73ff9b97db | |||
b0d71597f0 | |||
226f28dc7b | |||
6308427d03 | |||
c78b7c432b | |||
6bfdace512 | |||
16e55a98ce | |||
79f17843d8 | |||
e5e163bdbf | |||
4e4820af05 | |||
637512ad77 | |||
a4bd5a2aaa | |||
a943e4eebb | |||
cb0c80d8dc | |||
3332f68ce7 | |||
2fbf847367 | |||
54feb77770 | |||
1a07864a5f | |||
3e9d6bdbb9 | |||
c295539c79 | |||
57e6c46e72 | |||
cddf16f941 | |||
a3dee05fe3 | |||
a3617cad11 | |||
8edf4c3c8d | |||
7801c6effe | |||
8cc94a55ab | |||
daffb6b666 | |||
7cfb1e6076 | |||
cc36baff78 | |||
4c65109ac0 | |||
861bd15eda | |||
7b979eadff | |||
16714ceb40 | |||
fea301bcc9 | |||
77450eb4b7 | |||
28015c4735 | |||
7d61e67d20 | |||
afcbc8be0a | |||
7a2269262b | |||
9731dc1e61 | |||
bf2e0f2d73 | |||
e98857fab4 | |||
29b0a352fc | |||
8642b13fd1 | |||
6aa72892ed | |||
70f0a72f1b | |||
b5d890eedd | |||
50b1b48678 | |||
0e0dbc74aa | |||
8c34051d8b | |||
b00d83cb1a | |||
17e609c3a5 | |||
64f0166b64 | |||
c80f06fbcb | |||
70eb8325a0 | |||
2c8531ea48 | |||
e796f82203 | |||
5b7ca8c13c | |||
031739ef51 | |||
b94685e045 | |||
572d602b72 | |||
88051c9302 | |||
80be937d9d | |||
b8516b15cb | |||
ac5a54b5da | |||
29015b340b | |||
64274acbeb | |||
ff98c42514 | |||
126ac52975 | |||
70d3197212 | |||
dd90980520 | |||
352ab43c1f | |||
07f5dbb9ac | |||
97e98eae24 | |||
5ac88f2b15 | |||
b03a6684f9 | |||
afce942bf8 | |||
7c2e50b665 | |||
c04ca704d2 | |||
6aa54fe1d4 | |||
a1d7a56dfa | |||
cb78fefbb3 | |||
c55925959b | |||
4f0669c574 | |||
f0d996ffd2 | |||
f4d05c2c9c | |||
d1151ca707 | |||
82f46992f6 | |||
4ed9cc933f | |||
9947a648df | |||
c0f80680ef | |||
7761b66fe2 | |||
acc4c8d975 | |||
fe739aa81a | |||
afe006e234 | |||
95f018a0b0 | |||
8c2105ae0a | |||
ed2c2af4a0 | |||
17771c0497 | |||
82df132e7d | |||
a02619e5a2 | |||
a011e70665 | |||
c05184e1c4 | |||
b2252bdc0b | |||
7e61ce1ed2 | |||
b764194ed0 | |||
2d0e4ba951 | |||
0d549b687d | |||
738f572043 | |||
cab508fd64 | |||
c20be13733 | |||
fcb6437388 | |||
6c1db8473b | |||
b42987059a | |||
a3930dafc5 | |||
4f9797af3b | |||
1a530633ca | |||
8037e8074b | |||
d07e0e5576 | |||
5525466b52 | |||
c2a89bf709 | |||
8dd0b2608d | |||
05495077ec | |||
8ff9eadf30 | |||
082c86ea18 | |||
2800d6f28c | |||
b4effe7a46 | |||
e6e71436c2 | |||
4be45adae6 | |||
a887f852c8 | |||
0d7d2203d2 | |||
cde184f428 | |||
0b3255e463 | |||
df3794dfd8 | |||
d02d5c351d | |||
631a531212 | |||
febecd4b30 | |||
964e311d8b | |||
d43caa8296 | |||
916ed3f56a | |||
23af170229 | |||
b32d1da421 | |||
6f0362b956 | |||
665d8cd479 | |||
10398855a9 | |||
d0fec93dc3 | |||
59ab54b2fb | |||
7095999bd2 | |||
7ffb4107d2 | |||
d9d9a28ef8 | |||
d95582b81b | |||
c60aa68d00 | |||
9ce59d3c75 | |||
a0dfdfab2c | |||
3e17011087 | |||
f441505476 | |||
7c64797f03 |
75
CHANGELOG.md
75
CHANGELOG.md
@ -12,6 +12,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
## Changes
|
## Changes
|
||||||
|
|
||||||
|
- 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
|
- HAL Linux SPI: Set the Clock Default State when setting new SPI speed
|
||||||
and mode
|
and mode
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/573
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/573
|
||||||
@ -22,6 +25,41 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/572
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/572
|
||||||
- HAL Devicehandlers: Periodic printout is run-time configurable now
|
- HAL Devicehandlers: Periodic printout is run-time configurable now
|
||||||
- `oneShotAction` flag in the `TestTask` class is not static anymore
|
- `oneShotAction` flag in the `TestTask` class is not static anymore
|
||||||
|
- IPC Message Queue Handling: Allow passing an optional `MqArgs` argument into the MessageQueue
|
||||||
|
creation call. It allows passing context information and an arbitrary user argument into
|
||||||
|
the message queue. Also streamlined and simplified `MessageQueue` implementation for all OSALs
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/583
|
||||||
|
|
||||||
|
### HAL
|
||||||
|
|
||||||
|
- HAL Linux SPI: Set the Clock Default State when setting new SPI speed
|
||||||
|
and mode
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/573
|
||||||
|
- GPIO HAL: `Direction`, `GpioOperation` and `Levels` are enum classes now, which prevents
|
||||||
|
name clashes with Windows defines.
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/572
|
||||||
|
- HAL Linux Uart: Baudrate and bits per word are enums now, avoiding misconfigurations
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/585
|
||||||
|
|
||||||
|
### Time
|
||||||
|
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/584 and
|
||||||
|
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/593
|
||||||
|
|
||||||
|
- `timeval` to `TimeOfDay_t`
|
||||||
|
- Added Mutex for gmtime calls: (compare http://www.opengate.at/blog/2020/01/timeless/)
|
||||||
|
- Moved the statics used by Clock in ClockCommon.cpp to this file
|
||||||
|
- Better check for leap seconds
|
||||||
|
- Added Unittests for Clock (only getter)
|
||||||
|
|
||||||
|
### Power
|
||||||
|
|
||||||
|
- `PowerSwitchIF`: Remove `const` specifier from `sendSwitchCommand` and `sendFuseOnCommand` and
|
||||||
|
also specify a `ReturnValue_t` return type
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/590
|
||||||
|
- Extend `PowerSwitcher` module to optionally check current state when calling `turnOn` or
|
||||||
|
`turnOff`. Tis can be helpful to avoid commanding switches which do not need commanding
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/590
|
||||||
|
|
||||||
## Removed
|
## Removed
|
||||||
|
|
||||||
@ -31,10 +69,47 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
## Additions
|
## Additions
|
||||||
|
|
||||||
|
- LTO support: Allow using LTO/IPO by setting `FSFW_ENABLE_LTO=1`. CMake is able to detect whether
|
||||||
|
the user compiler supports IPO/LPO. LTO is on by default now. Most modern compilers support it,
|
||||||
|
can make good use of it and it usually makes the code faster and/or smaller.
|
||||||
|
After some more research:
|
||||||
|
Enabling LTO will actually cause the compiler to only produce thin LTO by adding
|
||||||
|
`-flto -fno-fat-lto-objects` to the compiler options. I am not sure this is an ideal choice
|
||||||
|
because if an application linking against the FSFW does not use LTO, there can be compile
|
||||||
|
issues (e.g. observed when compiling the FSFW tests without LTO). This is a known issue as
|
||||||
|
can be seen in the multiple CMake issues for it:
|
||||||
|
- https://gitlab.kitware.com/cmake/cmake/-/issues/22913,
|
||||||
|
- https://gitlab.kitware.com/cmake/cmake/-/issues/16808,
|
||||||
|
- https://gitlab.kitware.com/cmake/cmake/-/issues/21696
|
||||||
|
Easiest solution for now: Keep this option OFF by default.
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/616
|
||||||
- Linux HAL: Add wiretapping option for I2C. Enabled with `FSFW_HAL_I2C_WIRETAPPING` defined to 1
|
- Linux HAL: Add wiretapping option for I2C. Enabled with `FSFW_HAL_I2C_WIRETAPPING` defined to 1
|
||||||
- Dedicated Version class and constant `fsfw::FSFW_VERSION` containing version information
|
- Dedicated Version class and constant `fsfw::FSFW_VERSION` containing version information
|
||||||
inside `fsfw/version.h`
|
inside `fsfw/version.h`
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/559
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/559
|
||||||
|
- Added ETL dependency and improved library dependency management
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/592
|
||||||
|
- Add a `DummyPowerSwitcher` module which can be useful for test setups when no PCDU is available
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/590
|
||||||
|
- New typedef for switcher type
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/590
|
||||||
|
- `Subsystem`: New API to add table and sequence entries
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
|
||||||
|
- TCP TMTC Server: `MutexGuard` was not created properly in
|
||||||
|
`TcpTmTcServer::handleTmSending(socket_t connSocket, bool& tmSent)` call.
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/618
|
||||||
|
- Fix infinite recursion in `prepareHealthSetReply` of PUS Health Service 201.
|
||||||
|
Is not currently used right now but might be used in the future
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/617
|
||||||
|
- Move some CMake directives further up top so they are not ignored
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/621
|
||||||
|
- Small bugfix in STM32 HAL for SPI
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/599
|
||||||
|
- HAL GPIO: Improved error checking in `LinuxLibgpioIF::configureGpios(...)`. If a GPIO
|
||||||
|
configuration fails, the function will exit prematurely with a dedicated error code
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/602
|
||||||
|
|
||||||
# [v4.0.0]
|
# [v4.0.0]
|
||||||
|
|
||||||
|
532
CMakeLists.txt
532
CMakeLists.txt
@ -1,5 +1,15 @@
|
|||||||
cmake_minimum_required(VERSION 3.13)
|
cmake_minimum_required(VERSION 3.13)
|
||||||
|
|
||||||
|
set(LIB_FSFW_NAME fsfw)
|
||||||
|
project(${LIB_FSFW_NAME})
|
||||||
|
|
||||||
|
if(NOT CMAKE_CXX_STANDARD)
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||||
|
elseif(${CMAKE_CXX_STANDARD} LESS 17)
|
||||||
|
message(FATAL_ERROR "Compiling the FSFW requires a minimum of C++17 support")
|
||||||
|
endif()
|
||||||
|
|
||||||
set(FSFW_VERSION 4)
|
set(FSFW_VERSION 4)
|
||||||
set(FSFW_SUBVERSION 0)
|
set(FSFW_SUBVERSION 0)
|
||||||
set(FSFW_REVISION 0)
|
set(FSFW_REVISION 0)
|
||||||
@ -7,17 +17,48 @@ set(FSFW_REVISION 0)
|
|||||||
# Add the cmake folder so the FindSphinx module is found
|
# Add the cmake folder so the FindSphinx module is found
|
||||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
|
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
|
||||||
|
|
||||||
option(FSFW_GENERATE_SECTIONS
|
set(FSFW_ETL_LIB_NAME etl)
|
||||||
"Generate function and data sections. Required to remove unused code" ON
|
set(FSFW_ETL_LIB_MAJOR_VERSION
|
||||||
)
|
20
|
||||||
if(FSFW_GENERATE_SECTIONS)
|
CACHE STRING "ETL library major version requirement")
|
||||||
option(FSFW_REMOVE_UNUSED_CODE "Remove unused code" ON)
|
set(FSFW_ETL_LIB_VERSION
|
||||||
|
${FSFW_ETL_LIB_MAJOR_VERSION}.27.3
|
||||||
|
CACHE STRING "ETL library exact version requirement")
|
||||||
|
set(FSFW_ETL_LINK_TARGET etl::etl)
|
||||||
|
|
||||||
|
set(FSFW_CATCH2_LIB_MAJOR_VERSION
|
||||||
|
3
|
||||||
|
CACHE STRING "Catch2 library major version requirement")
|
||||||
|
set(FSFW_CATCH2_LIB_VERSION
|
||||||
|
v${FSFW_CATCH2_LIB_MAJOR_VERSION}.0.0-preview5
|
||||||
|
CACHE STRING "Catch2 library exact version requirement")
|
||||||
|
|
||||||
|
# Keep this off by default for now. See PR:
|
||||||
|
# https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/616 for information which
|
||||||
|
# keeping this on by default is problematic
|
||||||
|
option(
|
||||||
|
FSFW_ENABLE_IPO
|
||||||
|
"Enable interprocedural optimization or link-time optimization if available"
|
||||||
|
OFF)
|
||||||
|
if(FSFW_ENABLE_IPO)
|
||||||
|
include(CheckIPOSupported)
|
||||||
|
check_ipo_supported(RESULT IPO_SUPPORTED OUTPUT IPO_ERROR)
|
||||||
|
if(NOT IPO_SUPPORTED)
|
||||||
|
message(STATUS "FSFW | IPO/LTO not supported: ${IPO_ERROR}")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
option(FSFW_BUILD_UNITTESTS "Build unittest binary in addition to static library" OFF)
|
option(FSFW_GENERATE_SECTIONS
|
||||||
|
"Generate function and data sections. Required to remove unused code" ON)
|
||||||
|
if(FSFW_GENERATE_SECTIONS)
|
||||||
|
option(FSFW_REMOVE_UNUSED_CODE "Remove unused code" ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
option(FSFW_BUILD_UNITTESTS
|
||||||
|
"Build unittest binary in addition to static library" OFF)
|
||||||
option(FSFW_BUILD_DOCS "Build documentation with Sphinx and Doxygen" OFF)
|
option(FSFW_BUILD_DOCS "Build documentation with Sphinx and Doxygen" OFF)
|
||||||
if(FSFW_BUILD_UNITTESTS)
|
if(FSFW_BUILD_UNITTESTS)
|
||||||
option(FSFW_TESTS_GEN_COV "Generate coverage data for unittests" ON)
|
option(FSFW_TESTS_GEN_COV "Generate coverage data for unittests" ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
option(FSFW_WARNING_SHADOW_LOCAL_GCC "Enable -Wshadow=local warning in GCC" ON)
|
option(FSFW_WARNING_SHADOW_LOCAL_GCC "Enable -Wshadow=local warning in GCC" ON)
|
||||||
@ -38,54 +79,96 @@ option(FSFW_ADD_TMSTORAGE "Compile with tm storage components" OFF)
|
|||||||
# Contrib sources
|
# Contrib sources
|
||||||
option(FSFW_ADD_SGP4_PROPAGATOR "Add SGP4 propagator code" OFF)
|
option(FSFW_ADD_SGP4_PROPAGATOR "Add SGP4 propagator code" OFF)
|
||||||
|
|
||||||
set(LIB_FSFW_NAME fsfw)
|
|
||||||
set(FSFW_TEST_TGT fsfw-tests)
|
set(FSFW_TEST_TGT fsfw-tests)
|
||||||
set(FSFW_DUMMY_TGT fsfw-dummy)
|
set(FSFW_DUMMY_TGT fsfw-dummy)
|
||||||
|
|
||||||
project(${LIB_FSFW_NAME})
|
|
||||||
add_library(${LIB_FSFW_NAME})
|
add_library(${LIB_FSFW_NAME})
|
||||||
|
|
||||||
|
if(IPO_SUPPORTED AND FSFW_ENABLE_IPO)
|
||||||
|
set_property(TARGET ${LIB_FSFW_NAME} PROPERTY INTERPROCEDURAL_OPTIMIZATION
|
||||||
|
TRUE)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(FSFW_BUILD_UNITTESTS)
|
if(FSFW_BUILD_UNITTESTS)
|
||||||
message(STATUS "Building the FSFW unittests in addition to the static library")
|
message(
|
||||||
# Check whether the user has already installed Catch2 first
|
STATUS "Building the FSFW unittests in addition to the static library")
|
||||||
find_package(Catch2 3)
|
# Check whether the user has already installed Catch2 first
|
||||||
# Not installed, so use FetchContent to download and provide Catch2
|
find_package(Catch2 ${FSFW_CATCH2_LIB_MAJOR_VERSION})
|
||||||
if(NOT Catch2_FOUND)
|
# Not installed, so use FetchContent to download and provide Catch2
|
||||||
include(FetchContent)
|
if(NOT Catch2_FOUND)
|
||||||
|
message(
|
||||||
|
STATUS
|
||||||
|
"Catch2 installation not found. Downloading Catch2 library with FetchContent"
|
||||||
|
)
|
||||||
|
include(FetchContent)
|
||||||
|
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
Catch2
|
Catch2
|
||||||
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
|
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
|
||||||
GIT_TAG v3.0.0-preview4
|
GIT_TAG ${FSFW_CATCH2_LIB_VERSION})
|
||||||
)
|
|
||||||
|
|
||||||
FetchContent_MakeAvailable(Catch2)
|
list(APPEND FSFW_FETCH_CONTENT_TARGETS Catch2)
|
||||||
#fixes regression -preview4, to be confirmed in later releases
|
endif()
|
||||||
set_target_properties(Catch2 PROPERTIES DEBUG_POSTFIX "")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(FSFW_CONFIG_PATH tests/src/fsfw_tests/unit/testcfg)
|
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/FSFWConfig.h.in FSFWConfig.h)
|
||||||
configure_file(tests/src/fsfw_tests/unit/testcfg/TestsConfig.h.in tests/TestsConfig.h)
|
configure_file(tests/src/fsfw_tests/unit/testcfg/TestsConfig.h.in
|
||||||
|
tests/TestsConfig.h)
|
||||||
|
|
||||||
project(${FSFW_TEST_TGT} CXX C)
|
project(${FSFW_TEST_TGT} CXX C)
|
||||||
add_executable(${FSFW_TEST_TGT})
|
add_executable(${FSFW_TEST_TGT})
|
||||||
|
if(IPO_SUPPORTED AND FSFW_ENABLE_IPO)
|
||||||
|
set_property(TARGET ${FSFW_TEST_TGT} PROPERTY INTERPROCEDURAL_OPTIMIZATION
|
||||||
|
TRUE)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(FSFW_TESTS_GEN_COV)
|
if(FSFW_TESTS_GEN_COV)
|
||||||
message(STATUS "Generating coverage data for the library")
|
message(STATUS "Generating coverage data for the library")
|
||||||
message(STATUS "Targets linking against ${LIB_FSFW_NAME} "
|
message(STATUS "Targets linking against ${LIB_FSFW_NAME} "
|
||||||
"will be compiled with coverage data as well"
|
"will be compiled with coverage data as well")
|
||||||
)
|
include(FetchContent)
|
||||||
include(FetchContent)
|
FetchContent_Declare(
|
||||||
FetchContent_Declare(
|
cmake-modules GIT_REPOSITORY https://github.com/bilke/cmake-modules.git)
|
||||||
cmake-modules
|
FetchContent_MakeAvailable(cmake-modules)
|
||||||
GIT_REPOSITORY https://github.com/bilke/cmake-modules.git
|
set(CMAKE_BUILD_TYPE "Debug")
|
||||||
)
|
list(APPEND CMAKE_MODULE_PATH ${cmake-modules_SOURCE_DIR})
|
||||||
FetchContent_MakeAvailable(cmake-modules)
|
include(CodeCoverage)
|
||||||
set(CMAKE_BUILD_TYPE "Debug")
|
endif()
|
||||||
list(APPEND CMAKE_MODULE_PATH ${cmake-modules_SOURCE_DIR})
|
endif()
|
||||||
include(CodeCoverage)
|
|
||||||
endif()
|
message(STATUS "Finding and/or providing ETL library")
|
||||||
|
|
||||||
|
# Check whether the user has already installed ETL first
|
||||||
|
find_package(${FSFW_ETL_LIB_NAME} ${FSFW_ETL_LIB_MAJOR_VERSION} QUIET)
|
||||||
|
# Not installed, so use FetchContent to download and provide etl
|
||||||
|
if(NOT ${FSFW_ETL_LIB_NAME}_FOUND)
|
||||||
|
message(
|
||||||
|
STATUS
|
||||||
|
"No ETL installation was found with find_package. Installing and providing "
|
||||||
|
"etl with FindPackage")
|
||||||
|
include(FetchContent)
|
||||||
|
|
||||||
|
FetchContent_Declare(
|
||||||
|
${FSFW_ETL_LIB_NAME}
|
||||||
|
GIT_REPOSITORY https://github.com/ETLCPP/etl
|
||||||
|
GIT_TAG ${FSFW_ETL_LIB_VERSION})
|
||||||
|
|
||||||
|
list(APPEND FSFW_FETCH_CONTENT_TARGETS ${FSFW_ETL_LIB_NAME})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# The documentation for FetchContent recommends declaring all the dependencies
|
||||||
|
# before making them available. We make all declared dependency available here
|
||||||
|
# after their declaration
|
||||||
|
if(FSFW_FETCH_CONTENT_TARGETS)
|
||||||
|
FetchContent_MakeAvailable(${FSFW_FETCH_CONTENT_TARGETS})
|
||||||
|
if(TARGET ${FSFW_ETL_LIB_NAME})
|
||||||
|
add_library(${FSFW_ETL_LINK_TARGET} ALIAS ${FSFW_ETL_LIB_NAME})
|
||||||
|
endif()
|
||||||
|
if(TARGET Catch2)
|
||||||
|
# Fixes regression -preview4, to be confirmed in later releases Related
|
||||||
|
# GitHub issue: https://github.com/catchorg/Catch2/issues/2417
|
||||||
|
set_target_properties(Catch2 PROPERTIES DEBUG_POSTFIX "")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(FSFW_CORE_INC_PATH "inc")
|
set(FSFW_CORE_INC_PATH "inc")
|
||||||
@ -93,65 +176,51 @@ set(FSFW_CORE_INC_PATH "inc")
|
|||||||
set_property(CACHE FSFW_OSAL PROPERTY STRINGS host linux rtems freertos)
|
set_property(CACHE FSFW_OSAL PROPERTY STRINGS host linux rtems freertos)
|
||||||
|
|
||||||
# For configure files
|
# For configure files
|
||||||
target_include_directories(${LIB_FSFW_NAME} PRIVATE
|
target_include_directories(${LIB_FSFW_NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
${CMAKE_CURRENT_BINARY_DIR}
|
target_include_directories(${LIB_FSFW_NAME}
|
||||||
)
|
INTERFACE ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
target_include_directories(${LIB_FSFW_NAME} INTERFACE
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}
|
|
||||||
)
|
|
||||||
|
|
||||||
if(NOT CMAKE_CXX_STANDARD)
|
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
|
||||||
elseif(${CMAKE_CXX_STANDARD} LESS 11)
|
|
||||||
message(FATAL_ERROR "Compiling the FSFW requires a minimum of C++11 support")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Backwards comptability
|
# Backwards comptability
|
||||||
if(OS_FSFW AND NOT FSFW_OSAL)
|
if(OS_FSFW AND NOT FSFW_OSAL)
|
||||||
message(WARNING "Please pass the FSFW OSAL as FSFW_OSAL instead of OS_FSFW")
|
message(WARNING "Please pass the FSFW OSAL as FSFW_OSAL instead of OS_FSFW")
|
||||||
set(FSFW_OSAL OS_FSFW)
|
set(FSFW_OSAL OS_FSFW)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT FSFW_OSAL)
|
if(NOT FSFW_OSAL)
|
||||||
message(STATUS "No OS for FSFW via FSFW_OSAL set. Assuming host OS")
|
message(STATUS "No OS for FSFW via FSFW_OSAL set. Assuming host OS")
|
||||||
# Assume host OS and autodetermine from OS_FSFW
|
# Assume host OS and autodetermine from OS_FSFW
|
||||||
if(UNIX)
|
if(UNIX)
|
||||||
set(FSFW_OSAL "linux"
|
set(FSFW_OSAL
|
||||||
CACHE STRING
|
"linux"
|
||||||
"OS abstraction layer used in the FSFW"
|
CACHE STRING "OS abstraction layer used in the FSFW")
|
||||||
)
|
elseif(WIN32)
|
||||||
elseif(WIN32)
|
set(FSFW_OSAL
|
||||||
set(FSFW_OSAL "host"
|
"host"
|
||||||
CACHE STRING "OS abstraction layer used in the FSFW"
|
CACHE STRING "OS abstraction layer used in the FSFW")
|
||||||
)
|
endif()
|
||||||
endif()
|
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(FSFW_OSAL_DEFINITION FSFW_OSAL_HOST)
|
set(FSFW_OSAL_DEFINITION FSFW_OSAL_HOST)
|
||||||
|
|
||||||
if(FSFW_OSAL MATCHES host)
|
if(FSFW_OSAL MATCHES host)
|
||||||
set(FSFW_OS_NAME "Host")
|
set(FSFW_OS_NAME "Host")
|
||||||
set(FSFW_OSAL_HOST ON)
|
set(FSFW_OSAL_HOST ON)
|
||||||
elseif(FSFW_OSAL MATCHES linux)
|
elseif(FSFW_OSAL MATCHES linux)
|
||||||
set(FSFW_OS_NAME "Linux")
|
set(FSFW_OS_NAME "Linux")
|
||||||
set(FSFW_OSAL_LINUX ON)
|
set(FSFW_OSAL_LINUX ON)
|
||||||
elseif(FSFW_OSAL MATCHES freertos)
|
elseif(FSFW_OSAL MATCHES freertos)
|
||||||
set(FSFW_OS_NAME "FreeRTOS")
|
set(FSFW_OS_NAME "FreeRTOS")
|
||||||
set(FSFW_OSAL_FREERTOS ON)
|
set(FSFW_OSAL_FREERTOS ON)
|
||||||
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
|
target_link_libraries(${LIB_FSFW_NAME} PRIVATE ${LIB_OS_NAME})
|
||||||
${LIB_OS_NAME}
|
|
||||||
)
|
|
||||||
elseif(FSFW_OSAL STREQUAL rtems)
|
elseif(FSFW_OSAL STREQUAL rtems)
|
||||||
set(FSFW_OS_NAME "RTEMS")
|
set(FSFW_OS_NAME "RTEMS")
|
||||||
set(FSFW_OSAL_RTEMS ON)
|
set(FSFW_OSAL_RTEMS ON)
|
||||||
else()
|
else()
|
||||||
message(WARNING
|
message(
|
||||||
"Invalid operating system for FSFW specified! Setting to host.."
|
WARNING "Invalid operating system for FSFW specified! Setting to host..")
|
||||||
)
|
set(FSFW_OS_NAME "Host")
|
||||||
set(FSFW_OS_NAME "Host")
|
set(OS_FSFW "host")
|
||||||
set(OS_FSFW "host")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
configure_file(src/fsfw/FSFW.h.in fsfw/FSFW.h)
|
configure_file(src/fsfw/FSFW.h.in fsfw/FSFW.h)
|
||||||
@ -162,205 +231,178 @@ message(STATUS "Compiling FSFW for the ${FSFW_OS_NAME} operating system.")
|
|||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
if(FSFW_ADD_HAL)
|
if(FSFW_ADD_HAL)
|
||||||
add_subdirectory(hal)
|
add_subdirectory(hal)
|
||||||
endif()
|
endif()
|
||||||
add_subdirectory(contrib)
|
add_subdirectory(contrib)
|
||||||
if(FSFW_BUILD_DOCS)
|
if(FSFW_BUILD_DOCS)
|
||||||
add_subdirectory(docs)
|
add_subdirectory(docs)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(FSFW_BUILD_UNITTESTS)
|
if(FSFW_BUILD_UNITTESTS)
|
||||||
if(FSFW_TESTS_GEN_COV)
|
if(FSFW_TESTS_GEN_COV)
|
||||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||||
include(CodeCoverage)
|
include(CodeCoverage)
|
||||||
|
|
||||||
# Remove quotes.
|
# Remove quotes.
|
||||||
separate_arguments(COVERAGE_COMPILER_FLAGS
|
separate_arguments(COVERAGE_COMPILER_FLAGS NATIVE_COMMAND
|
||||||
NATIVE_COMMAND "${COVERAGE_COMPILER_FLAGS}"
|
"${COVERAGE_COMPILER_FLAGS}")
|
||||||
)
|
|
||||||
|
|
||||||
# Add compile options manually, we don't want coverage for Catch2
|
# Add compile options manually, we don't want coverage for Catch2
|
||||||
target_compile_options(${FSFW_TEST_TGT} PRIVATE
|
target_compile_options(${FSFW_TEST_TGT}
|
||||||
"${COVERAGE_COMPILER_FLAGS}"
|
PRIVATE "${COVERAGE_COMPILER_FLAGS}")
|
||||||
)
|
target_compile_options(${LIB_FSFW_NAME}
|
||||||
target_compile_options(${LIB_FSFW_NAME} PRIVATE
|
PRIVATE "${COVERAGE_COMPILER_FLAGS}")
|
||||||
"${COVERAGE_COMPILER_FLAGS}"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Exclude directories here
|
# Exclude directories here
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(GCOVR_ADDITIONAL_ARGS
|
set(GCOVR_ADDITIONAL_ARGS "--exclude-throw-branches"
|
||||||
"--exclude-throw-branches"
|
"--exclude-unreachable-branches")
|
||||||
"--exclude-unreachable-branches"
|
set(COVERAGE_EXCLUDES "/c/msys64/mingw64/*" "*/fsfw_hal/*")
|
||||||
)
|
elseif(UNIX)
|
||||||
set(COVERAGE_EXCLUDES
|
set(COVERAGE_EXCLUDES
|
||||||
"/c/msys64/mingw64/*" "*/fsfw_hal/*"
|
"/usr/include/*"
|
||||||
)
|
"/usr/bin/*"
|
||||||
elseif(UNIX)
|
"Catch2/*"
|
||||||
set(COVERAGE_EXCLUDES
|
"/usr/local/include/*"
|
||||||
"/usr/include/*" "/usr/bin/*" "Catch2/*"
|
"*/fsfw_tests/*"
|
||||||
"/usr/local/include/*" "*/fsfw_tests/*"
|
"*/catch2-src/*"
|
||||||
"*/catch2-src/*" "*/fsfw_hal/*"
|
"*/fsfw_hal/*")
|
||||||
)
|
endif()
|
||||||
endif()
|
|
||||||
|
|
||||||
target_link_options(${FSFW_TEST_TGT} PRIVATE
|
target_link_options(${FSFW_TEST_TGT} PRIVATE -fprofile-arcs
|
||||||
-fprofile-arcs
|
-ftest-coverage)
|
||||||
-ftest-coverage
|
target_link_options(${LIB_FSFW_NAME} PRIVATE -fprofile-arcs
|
||||||
)
|
-ftest-coverage)
|
||||||
target_link_options(${LIB_FSFW_NAME} PRIVATE
|
# Need to specify this as an interface, otherwise there will the compile
|
||||||
-fprofile-arcs
|
# issues
|
||||||
-ftest-coverage
|
target_link_options(${LIB_FSFW_NAME} INTERFACE -fprofile-arcs
|
||||||
)
|
-ftest-coverage)
|
||||||
# Need to specify this as an interface, otherwise there will the compile issues
|
|
||||||
target_link_options(${LIB_FSFW_NAME} INTERFACE
|
|
||||||
-fprofile-arcs
|
|
||||||
-ftest-coverage
|
|
||||||
)
|
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
setup_target_for_coverage_gcovr_html(
|
setup_target_for_coverage_gcovr_html(
|
||||||
NAME ${FSFW_TEST_TGT}_coverage
|
NAME ${FSFW_TEST_TGT}_coverage EXECUTABLE ${FSFW_TEST_TGT}
|
||||||
EXECUTABLE ${FSFW_TEST_TGT}
|
DEPENDENCIES ${FSFW_TEST_TGT})
|
||||||
DEPENDENCIES ${FSFW_TEST_TGT}
|
else()
|
||||||
)
|
setup_target_for_coverage_lcov(
|
||||||
else()
|
NAME ${FSFW_TEST_TGT}_coverage EXECUTABLE ${FSFW_TEST_TGT}
|
||||||
setup_target_for_coverage_lcov(
|
DEPENDENCIES ${FSFW_TEST_TGT})
|
||||||
NAME ${FSFW_TEST_TGT}_coverage
|
endif()
|
||||||
EXECUTABLE ${FSFW_TEST_TGT}
|
|
||||||
DEPENDENCIES ${FSFW_TEST_TGT}
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
target_link_libraries(${FSFW_TEST_TGT} PRIVATE Catch2::Catch2 ${LIB_FSFW_NAME})
|
endif()
|
||||||
|
target_link_libraries(${FSFW_TEST_TGT} PRIVATE Catch2::Catch2
|
||||||
|
${LIB_FSFW_NAME})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# The project CMakeLists file has to set the FSFW_CONFIG_PATH and add it.
|
# The project CMakeLists file has to set the FSFW_CONFIG_PATH and add it. If
|
||||||
# If this is not given, we include the default configuration and emit a warning.
|
# this is not given, we include the default configuration and emit a warning.
|
||||||
if(NOT FSFW_CONFIG_PATH)
|
if(NOT FSFW_CONFIG_PATH)
|
||||||
set(DEF_CONF_PATH misc/defaultcfg/fsfwconfig)
|
set(DEF_CONF_PATH misc/defaultcfg/fsfwconfig)
|
||||||
if(NOT FSFW_BUILD_DOCS)
|
if(NOT FSFW_BUILD_DOCS)
|
||||||
message(WARNING "Flight Software Framework configuration path not set!")
|
message(WARNING "Flight Software Framework configuration path not set!")
|
||||||
message(WARNING "Setting default configuration from ${DEF_CONF_PATH} ..")
|
message(WARNING "Setting default configuration from ${DEF_CONF_PATH} ..")
|
||||||
endif()
|
endif()
|
||||||
add_subdirectory(${DEF_CONF_PATH})
|
add_subdirectory(${DEF_CONF_PATH})
|
||||||
set(FSFW_CONFIG_PATH ${DEF_CONF_PATH})
|
set(FSFW_CONFIG_PATH ${DEF_CONF_PATH})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# FSFW might be part of a possibly complicated folder structure, so we
|
# FSFW might be part of a possibly complicated folder structure, so we extract
|
||||||
# extract the absolute path of the fsfwconfig folder.
|
# the absolute path of the fsfwconfig folder.
|
||||||
if(IS_ABSOLUTE ${FSFW_CONFIG_PATH})
|
if(IS_ABSOLUTE ${FSFW_CONFIG_PATH})
|
||||||
set(FSFW_CONFIG_PATH_ABSOLUTE ${FSFW_CONFIG_PATH})
|
set(FSFW_CONFIG_PATH_ABSOLUTE ${FSFW_CONFIG_PATH})
|
||||||
else()
|
else()
|
||||||
get_filename_component(FSFW_CONFIG_PATH_ABSOLUTE
|
get_filename_component(FSFW_CONFIG_PATH_ABSOLUTE ${FSFW_CONFIG_PATH} REALPATH
|
||||||
${FSFW_CONFIG_PATH} REALPATH BASE_DIR ${CMAKE_SOURCE_DIR}
|
BASE_DIR ${CMAKE_SOURCE_DIR})
|
||||||
)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
foreach(INCLUDE_PATH ${FSFW_ADDITIONAL_INC_PATHS})
|
foreach(INCLUDE_PATH ${FSFW_ADDITIONAL_INC_PATHS})
|
||||||
if(IS_ABSOLUTE ${INCLUDE_PATH})
|
if(IS_ABSOLUTE ${INCLUDE_PATH})
|
||||||
set(CURR_ABS_INC_PATH "${INCLUDE_PATH}")
|
set(CURR_ABS_INC_PATH "${INCLUDE_PATH}")
|
||||||
else()
|
else()
|
||||||
get_filename_component(CURR_ABS_INC_PATH
|
get_filename_component(CURR_ABS_INC_PATH ${INCLUDE_PATH} REALPATH BASE_DIR
|
||||||
${INCLUDE_PATH} REALPATH BASE_DIR ${CMAKE_SOURCE_DIR})
|
${CMAKE_SOURCE_DIR})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CMAKE_VERBOSE)
|
if(CMAKE_VERBOSE)
|
||||||
message(STATUS "FSFW include path: ${CURR_ABS_INC_PATH}")
|
message(STATUS "FSFW include path: ${CURR_ABS_INC_PATH}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
list(APPEND FSFW_ADD_INC_PATHS_ABS ${CURR_ABS_INC_PATH})
|
list(APPEND FSFW_ADD_INC_PATHS_ABS ${CURR_ABS_INC_PATH})
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||||
if(NOT DEFINED FSFW_WARNING_FLAGS)
|
if(NOT DEFINED FSFW_WARNING_FLAGS)
|
||||||
set(FSFW_WARNING_FLAGS
|
set(FSFW_WARNING_FLAGS
|
||||||
-Wall
|
-Wall
|
||||||
-Wextra
|
-Wextra
|
||||||
-Wimplicit-fallthrough=1
|
-Wimplicit-fallthrough=1
|
||||||
-Wno-unused-parameter
|
-Wno-unused-parameter
|
||||||
-Wno-psabi
|
-Wno-psabi
|
||||||
-Wduplicated-cond # check for duplicate conditions
|
-Wduplicated-cond # check for duplicate conditions
|
||||||
-Wduplicated-branches # check for duplicate branches
|
-Wduplicated-branches # check for duplicate branches
|
||||||
-Wlogical-op # Search for bitwise operations instead of logical
|
-Wlogical-op # Search for bitwise operations instead of logical
|
||||||
-Wnull-dereference # Search for NULL dereference
|
-Wnull-dereference # Search for NULL dereference
|
||||||
-Wundef # Warn if undefind marcos are used
|
-Wundef # Warn if undefind marcos are used
|
||||||
-Wformat=2 # Format string problem detection
|
-Wformat=2 # Format string problem detection
|
||||||
-Wformat-overflow=2 # Formatting issues in printf
|
-Wformat-overflow=2 # Formatting issues in printf
|
||||||
-Wformat-truncation=2 # Formatting issues in printf
|
-Wformat-truncation=2 # Formatting issues in printf
|
||||||
-Wformat-security # Search for dangerous printf operations
|
-Wformat-security # Search for dangerous printf operations
|
||||||
-Wstrict-overflow=3 # Warn if integer overflows might happen
|
-Wstrict-overflow=3 # Warn if integer overflows might happen
|
||||||
-Warray-bounds=2 # Some array bounds violations will be found
|
-Warray-bounds=2 # Some array bounds violations will be found
|
||||||
-Wshift-overflow=2 # Search for bit left shift overflows (<c++14)
|
-Wshift-overflow=2 # Search for bit left shift overflows (<c++14)
|
||||||
-Wcast-qual # Warn if the constness is cast away
|
-Wcast-qual # Warn if the constness is cast away
|
||||||
-Wstringop-overflow=4
|
-Wstringop-overflow=4
|
||||||
# -Wstack-protector # Emits a few false positives for low level access
|
# -Wstack-protector # Emits a few false positives for low level access
|
||||||
# -Wconversion # Creates many false positives
|
# -Wconversion # Creates many false positives -Warith-conversion # Use
|
||||||
# -Warith-conversion # Use with Wconversion to find more implicit conversions
|
# with Wconversion to find more implicit conversions -fanalyzer # Should
|
||||||
# -fanalyzer # Should be used to look through problems
|
# be used to look through problems
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(FSFW_GENERATE_SECTIONS)
|
if(FSFW_GENERATE_SECTIONS)
|
||||||
target_compile_options(${LIB_FSFW_NAME} PRIVATE
|
target_compile_options(${LIB_FSFW_NAME} PRIVATE "-ffunction-sections"
|
||||||
"-ffunction-sections"
|
"-fdata-sections")
|
||||||
"-fdata-sections"
|
endif()
|
||||||
)
|
|
||||||
endif()
|
if(FSFW_REMOVE_UNUSED_CODE)
|
||||||
|
target_link_options(${LIB_FSFW_NAME} PRIVATE "Wl,--gc-sections")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(FSFW_WARNING_SHADOW_LOCAL_GCC)
|
||||||
|
list(APPEND WARNING_FLAGS "-Wshadow=local")
|
||||||
|
endif()
|
||||||
|
|
||||||
if(FSFW_REMOVE_UNUSED_CODE)
|
|
||||||
target_link_options(${LIB_FSFW_NAME} PRIVATE
|
|
||||||
"Wl,--gc-sections"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(FSFW_WARNING_SHADOW_LOCAL_GCC)
|
|
||||||
list(APPEND WARNING_FLAGS "-Wshadow=local")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||||
set(COMPILER_FLAGS "/permissive-")
|
set(COMPILER_FLAGS "/permissive-")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Required include paths to compile the FSFW
|
# Required include paths to compile the FSFW
|
||||||
target_include_directories(${LIB_FSFW_NAME} INTERFACE
|
target_include_directories(
|
||||||
${CMAKE_SOURCE_DIR}
|
${LIB_FSFW_NAME} INTERFACE ${CMAKE_SOURCE_DIR} ${FSFW_CONFIG_PATH_ABSOLUTE}
|
||||||
${FSFW_CONFIG_PATH_ABSOLUTE}
|
${FSFW_CORE_INC_PATH} ${FSFW_ADD_INC_PATHS_ABS})
|
||||||
${FSFW_CORE_INC_PATH}
|
|
||||||
${FSFW_ADD_INC_PATHS_ABS}
|
|
||||||
)
|
|
||||||
|
|
||||||
# Includes path required to compile FSFW itself as well
|
# Includes path required to compile FSFW itself as well We assume that the
|
||||||
# We assume that the fsfwconfig folder uses include relative to the project
|
# fsfwconfig folder uses include relative to the project root here!
|
||||||
# root here!
|
target_include_directories(
|
||||||
target_include_directories(${LIB_FSFW_NAME} PRIVATE
|
${LIB_FSFW_NAME} PRIVATE ${CMAKE_SOURCE_DIR} ${FSFW_CONFIG_PATH_ABSOLUTE}
|
||||||
${CMAKE_SOURCE_DIR}
|
${FSFW_CORE_INC_PATH} ${FSFW_ADD_INC_PATHS_ABS})
|
||||||
${FSFW_CONFIG_PATH_ABSOLUTE}
|
|
||||||
${FSFW_CORE_INC_PATH}
|
|
||||||
${FSFW_ADD_INC_PATHS_ABS}
|
|
||||||
)
|
|
||||||
|
|
||||||
target_compile_options(${LIB_FSFW_NAME} PRIVATE
|
target_compile_options(${LIB_FSFW_NAME} PRIVATE ${FSFW_WARNING_FLAGS}
|
||||||
${FSFW_WARNING_FLAGS}
|
${COMPILER_FLAGS})
|
||||||
${COMPILER_FLAGS}
|
|
||||||
)
|
|
||||||
|
|
||||||
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
|
target_link_libraries(${LIB_FSFW_NAME} PRIVATE ${FSFW_ETL_LINK_TARGET}
|
||||||
${FSFW_ADDITIONAL_LINK_LIBS}
|
${FSFW_ADDITIONAL_LINK_LIBS})
|
||||||
)
|
|
||||||
|
|
||||||
string(CONCAT POST_BUILD_COMMENT
|
string(
|
||||||
|
CONCAT
|
||||||
|
POST_BUILD_COMMENT
|
||||||
"######################################################################\n"
|
"######################################################################\n"
|
||||||
"Built FSFW v${FSFW_VERSION}.${FSFW_SUBVERSION}.${FSFW_REVISION}, "
|
"Built FSFW v${FSFW_VERSION}.${FSFW_SUBVERSION}.${FSFW_REVISION}, "
|
||||||
"Target OSAL: ${FSFW_OS_NAME}\n"
|
"Target OSAL: ${FSFW_OS_NAME}\n"
|
||||||
"######################################################################\n"
|
"######################################################################\n")
|
||||||
)
|
|
||||||
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
TARGET ${LIB_FSFW_NAME}
|
TARGET ${LIB_FSFW_NAME}
|
||||||
POST_BUILD
|
POST_BUILD
|
||||||
COMMENT ${POST_BUILD_COMMENT}
|
COMMENT ${POST_BUILD_COMMENT})
|
||||||
)
|
|
||||||
|
45
README.md
45
README.md
@ -11,9 +11,15 @@ with Airbus Defence and Space GmbH.
|
|||||||
|
|
||||||
## Quick facts
|
## Quick facts
|
||||||
|
|
||||||
The framework is designed for systems, which communicate with external devices, perform control loops, receive telecommands and send telemetry, and need to maintain a high level of availability. Therefore, a mode and health system provides control over the states of the software and the controlled devices. In addition, a simple mechanism of event based fault detection, isolation and recovery is implemented as well.
|
The framework is designed for systems, which communicate with external devices, perform control loops,
|
||||||
|
receive telecommands and send telemetry, and need to maintain a high level of availability. Therefore,
|
||||||
|
a mode and health system provides control over the states of the software and the controlled devices.
|
||||||
|
In addition, a simple mechanism of event based fault detection, isolation and recovery is implemented as well.
|
||||||
|
|
||||||
The FSFW provides abstraction layers for operating systems to provide a uniform operating system abstraction layer (OSAL). Some components of this OSAL are required internally by the FSFW but is also very useful for developers to implement the same application logic on different operating systems with a uniform interface.
|
The FSFW provides abstraction layers for operating systems to provide a uniform operating system
|
||||||
|
abstraction layer (OSAL). Some components of this OSAL are required internally by the FSFW but is
|
||||||
|
also very useful for developers to implement the same application logic on different operating
|
||||||
|
systems with a uniform interface.
|
||||||
|
|
||||||
Currently, the FSFW provides the following OSALs:
|
Currently, the FSFW provides the following OSALs:
|
||||||
|
|
||||||
@ -45,6 +51,28 @@ A template configuration folder was provided and can be copied into the project
|
|||||||
a starting point. The [configuration section](docs/README-config.md#top) provides more specific
|
a starting point. The [configuration section](docs/README-config.md#top) provides more specific
|
||||||
information about the possible options.
|
information about the possible options.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
The Embedded Template Library (etl) is a dependency of the FSFW which is automatically
|
||||||
|
installed and provided by the build system unless the correction version was installed.
|
||||||
|
The current recommended version can be found inside the fsfw `CMakeLists.txt` file or by using
|
||||||
|
`ccmake` and looking up the `FSFW_ETL_LIB_MAJOR_VERSION` variable.
|
||||||
|
|
||||||
|
You can install the ETL library like this. On Linux, it might be necessary to add `sudo` before
|
||||||
|
the install call:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
git clone https://github.com/ETLCPP/etl
|
||||||
|
cd etl
|
||||||
|
git checkout <currentRecommendedVersion>
|
||||||
|
mkdir build && cd build
|
||||||
|
cmake ..
|
||||||
|
cmake --install .
|
||||||
|
```
|
||||||
|
|
||||||
|
It is recommended to install `20.27.2` or newer for the package version handling of
|
||||||
|
ETL to work.
|
||||||
|
|
||||||
## Adding the library
|
## Adding the library
|
||||||
|
|
||||||
The following steps show how to add and use FSFW components. It is still recommended to
|
The following steps show how to add and use FSFW components. It is still recommended to
|
||||||
@ -83,6 +111,19 @@ The FSFW also has unittests which use the [Catch2 library](https://github.com/ca
|
|||||||
These are built by setting the CMake option `FSFW_BUILD_UNITTESTS` to `ON` or `TRUE`
|
These are built by setting the CMake option `FSFW_BUILD_UNITTESTS` to `ON` or `TRUE`
|
||||||
from your project `CMakeLists.txt` file or from the command line.
|
from your project `CMakeLists.txt` file or from the command line.
|
||||||
|
|
||||||
|
You can install the Catch2 library, which prevents the build system to avoid re-downloading
|
||||||
|
the dependency if the unit tests are completely rebuilt. The current recommended version
|
||||||
|
can be found inside the fsfw `CMakeLists.txt` file or by using `ccmake` and looking up
|
||||||
|
the `FSFW_CATCH2_LIB_VERSION` variable.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git clone https://github.com/catchorg/Catch2.git
|
||||||
|
cd Catch2
|
||||||
|
git checkout <currentRecommendedVersion>
|
||||||
|
cmake -Bbuild -H. -DBUILD_TESTING=OFF
|
||||||
|
sudo cmake --build build/ --target install
|
||||||
|
```
|
||||||
|
|
||||||
The fsfw-tests binary will be built as part of the static library and dropped alongside it.
|
The fsfw-tests binary will be built as part of the static library and dropped alongside it.
|
||||||
If the unittests are built, the library and the tests will be built with coverage information by
|
If the unittests are built, the library and the tests will be built with coverage information by
|
||||||
default. This can be disabled by setting the `FSFW_TESTS_COV_GEN` option to `OFF` or `FALSE`.
|
default. This can be disabled by setting the `FSFW_TESTS_COV_GEN` option to `OFF` or `FALSE`.
|
||||||
|
@ -6,3 +6,9 @@ RUN apt-get --yes upgrade
|
|||||||
#tzdata is a dependency, won't install otherwise
|
#tzdata is a dependency, won't install otherwise
|
||||||
ARG DEBIAN_FRONTEND=noninteractive
|
ARG DEBIAN_FRONTEND=noninteractive
|
||||||
RUN apt-get --yes install gcc g++ cmake make lcov git valgrind nano iputils-ping
|
RUN apt-get --yes install gcc g++ cmake make lcov git valgrind nano iputils-ping
|
||||||
|
|
||||||
|
RUN git clone https://github.com/catchorg/Catch2.git && \
|
||||||
|
cd Catch2 && \
|
||||||
|
git checkout v3.0.0-preview5 && \
|
||||||
|
cmake -Bbuild -H. -DBUILD_TESTING=OFF && \
|
||||||
|
cmake --build build/ --target install
|
||||||
|
2
automation/Jenkinsfile
vendored
2
automation/Jenkinsfile
vendored
@ -3,7 +3,7 @@ pipeline {
|
|||||||
BUILDDIR = 'build-tests'
|
BUILDDIR = 'build-tests'
|
||||||
}
|
}
|
||||||
agent {
|
agent {
|
||||||
docker { image 'fsfw-ci:d1'}
|
docker { image 'fsfw-ci:d2'}
|
||||||
}
|
}
|
||||||
stages {
|
stages {
|
||||||
stage('Clean') {
|
stage('Clean') {
|
||||||
|
@ -19,6 +19,29 @@ A template configuration folder was provided and can be copied into the project
|
|||||||
a starting point. The [configuration section](docs/README-config.md#top) provides more specific
|
a starting point. The [configuration section](docs/README-config.md#top) provides more specific
|
||||||
information about the possible options.
|
information about the possible options.
|
||||||
|
|
||||||
|
Prerequisites
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
The Embedded Template Library (etl) is a dependency of the FSFW which is automatically
|
||||||
|
installed and provided by the build system unless the correction version was installed.
|
||||||
|
The current recommended version can be found inside the fsfw ``CMakeLists.txt`` file or by using
|
||||||
|
``ccmake`` and looking up the ``FSFW_ETL_LIB_MAJOR_VERSION`` variable.
|
||||||
|
|
||||||
|
You can install the ETL library like this. On Linux, it might be necessary to add ``sudo`` before
|
||||||
|
the install call:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
git clone https://github.com/ETLCPP/etl
|
||||||
|
cd etl
|
||||||
|
git checkout <currentRecommendedVersion>
|
||||||
|
mkdir build && cd build
|
||||||
|
cmake ..
|
||||||
|
cmake --install .
|
||||||
|
|
||||||
|
It is recommended to install ``20.27.2`` or newer for the package version handling of
|
||||||
|
ETL to work.
|
||||||
|
|
||||||
Adding the library
|
Adding the library
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
@ -60,6 +83,20 @@ The FSFW also has unittests which use the `Catch2 library`_.
|
|||||||
These are built by setting the CMake option ``FSFW_BUILD_UNITTESTS`` to ``ON`` or `TRUE`
|
These are built by setting the CMake option ``FSFW_BUILD_UNITTESTS`` to ``ON`` or `TRUE`
|
||||||
from your project `CMakeLists.txt` file or from the command line.
|
from your project `CMakeLists.txt` file or from the command line.
|
||||||
|
|
||||||
|
You can install the Catch2 library, which prevents the build system to avoid re-downloading
|
||||||
|
the dependency if the unit tests are completely rebuilt. The current recommended version
|
||||||
|
can be found inside the fsfw ``CMakeLists.txt`` file or by using ``ccmake`` and looking up
|
||||||
|
the ``FSFW_CATCH2_LIB_VERSION`` variable.
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
git clone https://github.com/catchorg/Catch2.git
|
||||||
|
cd Catch2
|
||||||
|
git checkout <currentRecommendedVersion>
|
||||||
|
cmake -Bbuild -H. -DBUILD_TESTING=OFF
|
||||||
|
sudo cmake --build build/ --target install
|
||||||
|
|
||||||
|
|
||||||
The fsfw-tests binary will be built as part of the static library and dropped alongside it.
|
The fsfw-tests binary will be built as part of the static library and dropped alongside it.
|
||||||
If the unittests are built, the library and the tests will be built with coverage information by
|
If the unittests are built, the library and the tests will be built with coverage information by
|
||||||
default. This can be disabled by setting the `FSFW_TESTS_COV_GEN` option to `OFF` or `FALSE`.
|
default. This can be disabled by setting the `FSFW_TESTS_COV_GEN` option to `OFF` or `FALSE`.
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
#include "MgmLIS3MDLHandler.h"
|
#include "MgmLIS3MDLHandler.h"
|
||||||
|
|
||||||
#include "fsfw/datapool/PoolReadGuard.h"
|
|
||||||
#if FSFW_HAL_LIS3MDL_MGM_DEBUG == 1
|
|
||||||
#include "fsfw/globalfunctions/PeriodicOperationDivider.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
|
#include "fsfw/datapool/PoolReadGuard.h"
|
||||||
|
|
||||||
MgmLIS3MDLHandler::MgmLIS3MDLHandler(object_id_t objectId, object_id_t deviceCommunication,
|
MgmLIS3MDLHandler::MgmLIS3MDLHandler(object_id_t objectId, object_id_t deviceCommunication,
|
||||||
CookieIF *comCookie, uint32_t transitionDelay)
|
CookieIF *comCookie, uint32_t transitionDelay)
|
||||||
: DeviceHandlerBase(objectId, deviceCommunication, comCookie),
|
: DeviceHandlerBase(objectId, deviceCommunication, comCookie),
|
||||||
|
@ -12,9 +12,14 @@ if(FSFW_HAL_LINUX_ADD_PERIPHERAL_DRIVERS)
|
|||||||
if(FSFW_HAL_LINUX_ADD_LIBGPIOD)
|
if(FSFW_HAL_LINUX_ADD_LIBGPIOD)
|
||||||
add_subdirectory(gpio)
|
add_subdirectory(gpio)
|
||||||
endif()
|
endif()
|
||||||
add_subdirectory(spi)
|
|
||||||
add_subdirectory(i2c)
|
|
||||||
add_subdirectory(uart)
|
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()
|
endif()
|
||||||
|
|
||||||
add_subdirectory(uio)
|
add_subdirectory(uio)
|
||||||
|
@ -20,7 +20,9 @@ LinuxLibgpioIF::~LinuxLibgpioIF() {
|
|||||||
ReturnValue_t LinuxLibgpioIF::addGpios(GpioCookie* gpioCookie) {
|
ReturnValue_t LinuxLibgpioIF::addGpios(GpioCookie* gpioCookie) {
|
||||||
ReturnValue_t result;
|
ReturnValue_t result;
|
||||||
if (gpioCookie == nullptr) {
|
if (gpioCookie == nullptr) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "LinuxLibgpioIF::addGpios: Invalid cookie" << std::endl;
|
sif::error << "LinuxLibgpioIF::addGpios: Invalid cookie" << std::endl;
|
||||||
|
#endif
|
||||||
return RETURN_FAILED;
|
return RETURN_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,6 +46,7 @@ ReturnValue_t LinuxLibgpioIF::addGpios(GpioCookie* gpioCookie) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t LinuxLibgpioIF::configureGpios(GpioMap& mapToAdd) {
|
ReturnValue_t LinuxLibgpioIF::configureGpios(GpioMap& mapToAdd) {
|
||||||
|
ReturnValue_t result = RETURN_OK;
|
||||||
for (auto& gpioConfig : mapToAdd) {
|
for (auto& gpioConfig : mapToAdd) {
|
||||||
auto& gpioType = gpioConfig.second->gpioType;
|
auto& gpioType = gpioConfig.second->gpioType;
|
||||||
switch (gpioType) {
|
switch (gpioType) {
|
||||||
@ -55,7 +58,7 @@ ReturnValue_t LinuxLibgpioIF::configureGpios(GpioMap& mapToAdd) {
|
|||||||
if (regularGpio == nullptr) {
|
if (regularGpio == nullptr) {
|
||||||
return GPIO_INVALID_INSTANCE;
|
return GPIO_INVALID_INSTANCE;
|
||||||
}
|
}
|
||||||
configureGpioByChip(gpioConfig.first, *regularGpio);
|
result = configureGpioByChip(gpioConfig.first, *regularGpio);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (gpio::GpioTypes::GPIO_REGULAR_BY_LABEL): {
|
case (gpio::GpioTypes::GPIO_REGULAR_BY_LABEL): {
|
||||||
@ -63,7 +66,7 @@ ReturnValue_t LinuxLibgpioIF::configureGpios(GpioMap& mapToAdd) {
|
|||||||
if (regularGpio == nullptr) {
|
if (regularGpio == nullptr) {
|
||||||
return GPIO_INVALID_INSTANCE;
|
return GPIO_INVALID_INSTANCE;
|
||||||
}
|
}
|
||||||
configureGpioByLabel(gpioConfig.first, *regularGpio);
|
result = configureGpioByLabel(gpioConfig.first, *regularGpio);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (gpio::GpioTypes::GPIO_REGULAR_BY_LINE_NAME): {
|
case (gpio::GpioTypes::GPIO_REGULAR_BY_LINE_NAME): {
|
||||||
@ -71,7 +74,7 @@ ReturnValue_t LinuxLibgpioIF::configureGpios(GpioMap& mapToAdd) {
|
|||||||
if (regularGpio == nullptr) {
|
if (regularGpio == nullptr) {
|
||||||
return GPIO_INVALID_INSTANCE;
|
return GPIO_INVALID_INSTANCE;
|
||||||
}
|
}
|
||||||
configureGpioByLineName(gpioConfig.first, *regularGpio);
|
result = configureGpioByLineName(gpioConfig.first, *regularGpio);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case (gpio::GpioTypes::CALLBACK): {
|
case (gpio::GpioTypes::CALLBACK): {
|
||||||
@ -83,8 +86,11 @@ ReturnValue_t LinuxLibgpioIF::configureGpios(GpioMap& mapToAdd) {
|
|||||||
gpioCallback->initValue, gpioCallback->callbackArgs);
|
gpioCallback->initValue, gpioCallback->callbackArgs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (result != RETURN_OK) {
|
||||||
|
return GPIO_INIT_FAILED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return RETURN_OK;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t LinuxLibgpioIF::configureGpioByLabel(gpioId_t gpioId,
|
ReturnValue_t LinuxLibgpioIF::configureGpioByLabel(gpioId_t gpioId,
|
||||||
@ -92,8 +98,10 @@ ReturnValue_t LinuxLibgpioIF::configureGpioByLabel(gpioId_t gpioId,
|
|||||||
std::string& label = gpioByLabel.label;
|
std::string& label = gpioByLabel.label;
|
||||||
struct gpiod_chip* chip = gpiod_chip_open_by_label(label.c_str());
|
struct gpiod_chip* chip = gpiod_chip_open_by_label(label.c_str());
|
||||||
if (chip == nullptr) {
|
if (chip == nullptr) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "LinuxLibgpioIF::configureGpioByLabel: Failed to open gpio from gpio "
|
sif::warning << "LinuxLibgpioIF::configureGpioByLabel: Failed to open gpio from gpio "
|
||||||
<< "group with label " << label << ". Gpio ID: " << gpioId << std::endl;
|
<< "group with label " << label << ". Gpio ID: " << gpioId << std::endl;
|
||||||
|
#endif
|
||||||
return RETURN_FAILED;
|
return RETURN_FAILED;
|
||||||
}
|
}
|
||||||
std::string failOutput = "label: " + label;
|
std::string failOutput = "label: " + label;
|
||||||
@ -104,8 +112,10 @@ ReturnValue_t LinuxLibgpioIF::configureGpioByChip(gpioId_t gpioId, GpiodRegularB
|
|||||||
std::string& chipname = gpioByChip.chipname;
|
std::string& chipname = gpioByChip.chipname;
|
||||||
struct gpiod_chip* chip = gpiod_chip_open_by_name(chipname.c_str());
|
struct gpiod_chip* chip = gpiod_chip_open_by_name(chipname.c_str());
|
||||||
if (chip == nullptr) {
|
if (chip == nullptr) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "LinuxLibgpioIF::configureGpioByChip: Failed to open chip " << chipname
|
sif::warning << "LinuxLibgpioIF::configureGpioByChip: Failed to open chip " << chipname
|
||||||
<< ". Gpio ID: " << gpioId << std::endl;
|
<< ". Gpio ID: " << gpioId << std::endl;
|
||||||
|
#endif
|
||||||
return RETURN_FAILED;
|
return RETURN_FAILED;
|
||||||
}
|
}
|
||||||
std::string failOutput = "chipname: " + chipname;
|
std::string failOutput = "chipname: " + chipname;
|
||||||
@ -129,8 +139,10 @@ ReturnValue_t LinuxLibgpioIF::configureGpioByLineName(gpioId_t gpioId,
|
|||||||
|
|
||||||
struct gpiod_chip* chip = gpiod_chip_open_by_name(chipname);
|
struct gpiod_chip* chip = gpiod_chip_open_by_name(chipname);
|
||||||
if (chip == nullptr) {
|
if (chip == nullptr) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "LinuxLibgpioIF::configureGpioByLineName: Failed to open chip " << chipname
|
sif::warning << "LinuxLibgpioIF::configureGpioByLineName: Failed to open chip " << chipname
|
||||||
<< ". <Gpio ID: " << gpioId << std::endl;
|
<< ". <Gpio ID: " << gpioId << std::endl;
|
||||||
|
#endif
|
||||||
return RETURN_FAILED;
|
return RETURN_FAILED;
|
||||||
}
|
}
|
||||||
std::string failOutput = "line name: " + lineName;
|
std::string failOutput = "line name: " + lineName;
|
||||||
@ -149,10 +161,12 @@ ReturnValue_t LinuxLibgpioIF::configureRegularGpio(gpioId_t gpioId, struct gpiod
|
|||||||
lineNum = regularGpio.lineNum;
|
lineNum = regularGpio.lineNum;
|
||||||
lineHandle = gpiod_chip_get_line(chip, lineNum);
|
lineHandle = gpiod_chip_get_line(chip, lineNum);
|
||||||
if (!lineHandle) {
|
if (!lineHandle) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "LinuxLibgpioIF::configureRegularGpio: Failed to open line " << std::endl;
|
sif::warning << "LinuxLibgpioIF::configureRegularGpio: Failed to open line " << std::endl;
|
||||||
sif::warning << "GPIO ID: " << gpioId << ", line number: " << lineNum << ", " << failOutput
|
sif::warning << "GPIO ID: " << gpioId << ", line number: " << lineNum << ", " << failOutput
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
sif::warning << "Check if Linux GPIO configuration has changed. " << std::endl;
|
sif::warning << "Check if Linux GPIO configuration has changed. " << std::endl;
|
||||||
|
#endif
|
||||||
gpiod_chip_close(chip);
|
gpiod_chip_close(chip);
|
||||||
return RETURN_FAILED;
|
return RETURN_FAILED;
|
||||||
}
|
}
|
||||||
@ -171,7 +185,9 @@ ReturnValue_t LinuxLibgpioIF::configureRegularGpio(gpioId_t gpioId, struct gpiod
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "LinuxLibgpioIF::configureGpios: Invalid direction specified" << std::endl;
|
sif::error << "LinuxLibgpioIF::configureGpios: Invalid direction specified" << std::endl;
|
||||||
|
#endif
|
||||||
return GPIO_INVALID_INSTANCE;
|
return GPIO_INVALID_INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,7 +216,9 @@ ReturnValue_t LinuxLibgpioIF::configureRegularGpio(gpioId_t gpioId, struct gpiod
|
|||||||
ReturnValue_t LinuxLibgpioIF::pullHigh(gpioId_t gpioId) {
|
ReturnValue_t LinuxLibgpioIF::pullHigh(gpioId_t gpioId) {
|
||||||
gpioMapIter = gpioMap.find(gpioId);
|
gpioMapIter = gpioMap.find(gpioId);
|
||||||
if (gpioMapIter == gpioMap.end()) {
|
if (gpioMapIter == gpioMap.end()) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "LinuxLibgpioIF::pullHigh: Unknown GPIO ID " << gpioId << std::endl;
|
sif::warning << "LinuxLibgpioIF::pullHigh: Unknown GPIO ID " << gpioId << std::endl;
|
||||||
|
#endif
|
||||||
return UNKNOWN_GPIO_ID;
|
return UNKNOWN_GPIO_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,6 +29,8 @@ class LinuxLibgpioIF : public GpioIF, public SystemObject {
|
|||||||
HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 4);
|
HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 4);
|
||||||
static constexpr ReturnValue_t GPIO_DUPLICATE_DETECTED =
|
static constexpr ReturnValue_t GPIO_DUPLICATE_DETECTED =
|
||||||
HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 5);
|
HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 5);
|
||||||
|
static constexpr ReturnValue_t GPIO_INIT_FAILED =
|
||||||
|
HasReturnvaluesIF::makeReturnCode(gpioRetvalId, 6);
|
||||||
|
|
||||||
LinuxLibgpioIF(object_id_t objectId);
|
LinuxLibgpioIF(object_id_t objectId);
|
||||||
virtual ~LinuxLibgpioIF();
|
virtual ~LinuxLibgpioIF();
|
||||||
|
43
hal/src/fsfw_hal/linux/spi/ManualCsLockGuard.h
Normal file
43
hal/src/fsfw_hal/linux/spi/ManualCsLockGuard.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "fsfw/ipc/MutexIF.h"
|
||||||
|
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
|
||||||
|
#include "fsfw_hal/common/gpio/GpioIF.h"
|
||||||
|
|
||||||
|
class ManualCsLockWrapper : public HasReturnvaluesIF {
|
||||||
|
public:
|
||||||
|
ManualCsLockWrapper(MutexIF* lock, GpioIF* gpioIF, SpiCookie* cookie,
|
||||||
|
MutexIF::TimeoutType type = MutexIF::TimeoutType::BLOCKING,
|
||||||
|
uint32_t timeoutMs = 0)
|
||||||
|
: lock(lock), gpioIF(gpioIF), cookie(cookie), type(type), timeoutMs(timeoutMs) {
|
||||||
|
if (cookie == nullptr) {
|
||||||
|
// TODO: Error? Or maybe throw exception..
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cookie->setCsLockManual(true);
|
||||||
|
lockResult = lock->lockMutex(type, timeoutMs);
|
||||||
|
if (lockResult != RETURN_OK) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
gpioResult = gpioIF->pullLow(cookie->getChipSelectPin());
|
||||||
|
}
|
||||||
|
|
||||||
|
~ManualCsLockWrapper() {
|
||||||
|
if (gpioResult == RETURN_OK) {
|
||||||
|
gpioIF->pullHigh(cookie->getChipSelectPin());
|
||||||
|
}
|
||||||
|
cookie->setCsLockManual(false);
|
||||||
|
if (lockResult == RETURN_OK) {
|
||||||
|
lock->unlockMutex();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ReturnValue_t lockResult;
|
||||||
|
ReturnValue_t gpioResult;
|
||||||
|
|
||||||
|
private:
|
||||||
|
MutexIF* lock;
|
||||||
|
GpioIF* gpioIF;
|
||||||
|
SpiCookie* cookie;
|
||||||
|
MutexIF::TimeoutType type;
|
||||||
|
uint32_t timeoutMs = 0;
|
||||||
|
};
|
@ -196,16 +196,22 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const
|
|||||||
|
|
||||||
bool fullDuplex = spiCookie->isFullDuplex();
|
bool fullDuplex = spiCookie->isFullDuplex();
|
||||||
gpioId_t gpioId = spiCookie->getChipSelectPin();
|
gpioId_t gpioId = spiCookie->getChipSelectPin();
|
||||||
|
bool csLockManual = spiCookie->getCsLockManual();
|
||||||
|
|
||||||
/* Pull SPI CS low. For now, no support for active high given */
|
MutexIF::TimeoutType csType;
|
||||||
if (gpioId != gpio::NO_GPIO) {
|
dur_millis_t csTimeout = 0;
|
||||||
result = spiMutex->lockMutex(timeoutType, timeoutMs);
|
// Pull SPI CS low. For now, no support for active high given
|
||||||
|
if (gpioId != gpio::NO_GPIO and not csLockManual) {
|
||||||
|
spiCookie->getMutexParams(csType, csTimeout);
|
||||||
|
result = csMutex->lockMutex(csType, csTimeout);
|
||||||
if (result != RETURN_OK) {
|
if (result != RETURN_OK) {
|
||||||
#if FSFW_VERBOSE_LEVEL >= 1
|
#if FSFW_VERBOSE_LEVEL >= 1
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "SpiComIF::sendMessage: Failed to lock mutex" << std::endl;
|
sif::error << "SpiComIF::sendMessage: Failed to lock mutex with code "
|
||||||
|
<< "0x" << std::hex << std::setfill('0') << std::setw(4) << result << std::dec
|
||||||
|
<< std::endl;
|
||||||
#else
|
#else
|
||||||
sif::printError("SpiComIF::sendMessage: Failed to lock mutex\n");
|
sif::printError("SpiComIF::sendMessage: Failed to lock mutex with code %d\n", result);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
return result;
|
return result;
|
||||||
@ -248,7 +254,7 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gpioId != gpio::NO_GPIO) {
|
if (gpioId != gpio::NO_GPIO and not csLockManual) {
|
||||||
gpioComIF->pullHigh(gpioId);
|
gpioComIF->pullHigh(gpioId);
|
||||||
result = spiMutex->unlockMutex();
|
result = spiMutex->unlockMutex();
|
||||||
if (result != RETURN_OK) {
|
if (result != RETURN_OK) {
|
||||||
@ -292,12 +298,27 @@ ReturnValue_t SpiComIF::performHalfDuplexReception(SpiCookie* spiCookie) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool csLockManual = spiCookie->getCsLockManual();
|
||||||
gpioId_t gpioId = spiCookie->getChipSelectPin();
|
gpioId_t gpioId = spiCookie->getChipSelectPin();
|
||||||
|
<<<<<<< Updated upstream
|
||||||
if (gpioId != gpio::NO_GPIO) {
|
if (gpioId != gpio::NO_GPIO) {
|
||||||
result = spiMutex->lockMutex(timeoutType, timeoutMs);
|
result = spiMutex->lockMutex(timeoutType, timeoutMs);
|
||||||
|
=======
|
||||||
|
MutexIF::TimeoutType csType;
|
||||||
|
dur_millis_t csTimeout = 0;
|
||||||
|
if (gpioId != gpio::NO_GPIO and not csLockManual) {
|
||||||
|
spiCookie->getMutexParams(csType, csTimeout);
|
||||||
|
result = csMutex->lockMutex(csType, csTimeout);
|
||||||
|
>>>>>>> Stashed changes
|
||||||
if (result != RETURN_OK) {
|
if (result != RETURN_OK) {
|
||||||
|
#if FSFW_VERBOSE_LEVEL >= 1
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "SpiComIF::getSendSuccess: Failed to lock mutex" << std::endl;
|
sif::error << "SpiComIF::sendMessage: Failed to lock mutex with code "
|
||||||
|
<< "0x" << std::hex << std::setfill('0') << std::setw(4) << result << std::dec
|
||||||
|
<< std::endl;
|
||||||
|
#else
|
||||||
|
sif::printError("SpiComIF::sendMessage: Failed to lock mutex with code %d\n", result);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -315,7 +336,7 @@ ReturnValue_t SpiComIF::performHalfDuplexReception(SpiCookie* spiCookie) {
|
|||||||
result = HALF_DUPLEX_TRANSFER_FAILED;
|
result = HALF_DUPLEX_TRANSFER_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gpioId != gpio::NO_GPIO) {
|
if (gpioId != gpio::NO_GPIO and not csLockManual) {
|
||||||
gpioComIF->pullHigh(gpioId);
|
gpioComIF->pullHigh(gpioId);
|
||||||
result = spiMutex->unlockMutex();
|
result = spiMutex->unlockMutex();
|
||||||
if (result != RETURN_OK) {
|
if (result != RETURN_OK) {
|
||||||
@ -346,6 +367,7 @@ ReturnValue_t SpiComIF::readReceivedMessage(CookieIF* cookie, uint8_t** buffer,
|
|||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<<<<<<< Updated upstream
|
||||||
MutexIF* SpiComIF::getMutex(MutexIF::TimeoutType* timeoutType, uint32_t* timeoutMs) {
|
MutexIF* SpiComIF::getMutex(MutexIF::TimeoutType* timeoutType, uint32_t* timeoutMs) {
|
||||||
if (timeoutType != nullptr) {
|
if (timeoutType != nullptr) {
|
||||||
*timeoutType = this->timeoutType;
|
*timeoutType = this->timeoutType;
|
||||||
@ -355,6 +377,9 @@ MutexIF* SpiComIF::getMutex(MutexIF::TimeoutType* timeoutType, uint32_t* timeout
|
|||||||
}
|
}
|
||||||
return spiMutex;
|
return spiMutex;
|
||||||
}
|
}
|
||||||
|
=======
|
||||||
|
MutexIF* SpiComIF::getCsMutex() { return csMutex; }
|
||||||
|
>>>>>>> Stashed changes
|
||||||
|
|
||||||
void SpiComIF::performSpiWiretapping(SpiCookie* spiCookie) {
|
void SpiComIF::performSpiWiretapping(SpiCookie* spiCookie) {
|
||||||
if (spiCookie == nullptr) {
|
if (spiCookie == nullptr) {
|
||||||
|
@ -22,15 +22,15 @@ class SpiCookie;
|
|||||||
*/
|
*/
|
||||||
class SpiComIF : public DeviceCommunicationIF, public SystemObject {
|
class SpiComIF : public DeviceCommunicationIF, public SystemObject {
|
||||||
public:
|
public:
|
||||||
static constexpr uint8_t spiRetvalId = CLASS_ID::HAL_SPI;
|
static constexpr uint8_t CLASS_ID = CLASS_ID::HAL_SPI;
|
||||||
static constexpr ReturnValue_t OPENING_FILE_FAILED =
|
static constexpr ReturnValue_t OPENING_FILE_FAILED =
|
||||||
HasReturnvaluesIF::makeReturnCode(spiRetvalId, 0);
|
HasReturnvaluesIF::makeReturnCode(CLASS_ID, 0);
|
||||||
/* Full duplex (ioctl) transfer failure */
|
/* Full duplex (ioctl) transfer failure */
|
||||||
static constexpr ReturnValue_t FULL_DUPLEX_TRANSFER_FAILED =
|
static constexpr ReturnValue_t FULL_DUPLEX_TRANSFER_FAILED =
|
||||||
HasReturnvaluesIF::makeReturnCode(spiRetvalId, 1);
|
HasReturnvaluesIF::makeReturnCode(CLASS_ID, 1);
|
||||||
/* Half duplex (read/write) transfer failure */
|
/* Half duplex (read/write) transfer failure */
|
||||||
static constexpr ReturnValue_t HALF_DUPLEX_TRANSFER_FAILED =
|
static constexpr ReturnValue_t HALF_DUPLEX_TRANSFER_FAILED =
|
||||||
HasReturnvaluesIF::makeReturnCode(spiRetvalId, 2);
|
HasReturnvaluesIF::makeReturnCode(CLASS_ID, 2);
|
||||||
|
|
||||||
SpiComIF(object_id_t objectId, GpioIF* gpioComIF);
|
SpiComIF(object_id_t objectId, GpioIF* gpioComIF);
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ class SpiComIF : public DeviceCommunicationIF, public SystemObject {
|
|||||||
* @brief This function returns the mutex which can be used to protect the spi bus when
|
* @brief This function returns the mutex which can be used to protect the spi bus when
|
||||||
* the chip select must be driven from outside of the com if.
|
* the chip select must be driven from outside of the com if.
|
||||||
*/
|
*/
|
||||||
MutexIF* getMutex(MutexIF::TimeoutType* timeoutType = nullptr, uint32_t* timeoutMs = nullptr);
|
MutexIF* getCsMutex();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform a regular send operation using Linux iotcl. This is public so it can be used
|
* Perform a regular send operation using Linux iotcl. This is public so it can be used
|
||||||
@ -70,10 +70,13 @@ class SpiComIF : public DeviceCommunicationIF, public SystemObject {
|
|||||||
};
|
};
|
||||||
|
|
||||||
GpioIF* gpioComIF = nullptr;
|
GpioIF* gpioComIF = nullptr;
|
||||||
|
std::string dev = "";
|
||||||
|
/**
|
||||||
|
* Protects the chip select operations. Lock when GPIO is pulled low, unlock after it was
|
||||||
|
* pulled high
|
||||||
|
*/
|
||||||
|
MutexIF* csMutex = nullptr;
|
||||||
|
|
||||||
MutexIF* spiMutex = nullptr;
|
|
||||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
|
|
||||||
uint32_t timeoutMs = 20;
|
|
||||||
spi_ioc_transfer clockUpdateTransfer = {};
|
spi_ioc_transfer clockUpdateTransfer = {};
|
||||||
|
|
||||||
using SpiDeviceMap = std::unordered_map<address_t, SpiInstance>;
|
using SpiDeviceMap = std::unordered_map<address_t, SpiInstance>;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#include "fsfw_hal/linux/spi/SpiCookie.h"
|
#include "SpiCookie.h"
|
||||||
|
|
||||||
SpiCookie::SpiCookie(address_t spiAddress, gpioId_t chipSelect, std::string spiDev,
|
SpiCookie::SpiCookie(address_t spiAddress, gpioId_t chipSelect, std::string spiDev,
|
||||||
const size_t maxSize, spi::SpiModes spiMode, uint32_t spiSpeed)
|
const size_t maxSize, spi::SpiModes spiMode, uint32_t spiSpeed)
|
||||||
@ -107,3 +107,17 @@ void SpiCookie::getCallback(spi::send_callback_function_t* callback, void** args
|
|||||||
*callback = this->sendCallback;
|
*callback = this->sendCallback;
|
||||||
*args = this->callbackArgs;
|
*args = this->callbackArgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SpiCookie::setCsLockManual(bool enable) { manualCsLock = enable; }
|
||||||
|
|
||||||
|
bool SpiCookie::getCsLockManual() const { return manualCsLock; }
|
||||||
|
|
||||||
|
void SpiCookie::getMutexParams(MutexIF::TimeoutType& csTimeoutType, dur_millis_t& csTimeout) const {
|
||||||
|
csTimeoutType = this->csTimeoutType;
|
||||||
|
csTimeout = this->csTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpiCookie::setMutexParams(MutexIF::TimeoutType csTimeoutType, dur_millis_t csTimeout) {
|
||||||
|
this->csTimeoutType = csTimeoutType;
|
||||||
|
this->csTimeout = csTimeout;
|
||||||
|
}
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
#define LINUX_SPI_SPICOOKIE_H_
|
#define LINUX_SPI_SPICOOKIE_H_
|
||||||
|
|
||||||
#include <fsfw/devicehandlers/CookieIF.h>
|
#include <fsfw/devicehandlers/CookieIF.h>
|
||||||
|
#include <fsfw/ipc/MutexIF.h>
|
||||||
|
#include <fsfw/timemanager/clockDefinitions.h>
|
||||||
#include <linux/spi/spidev.h>
|
#include <linux/spi/spidev.h>
|
||||||
|
|
||||||
#include "../../common/gpio/gpioDefinitions.h"
|
#include "../../common/gpio/gpioDefinitions.h"
|
||||||
@ -20,6 +22,8 @@
|
|||||||
*/
|
*/
|
||||||
class SpiCookie : public CookieIF {
|
class SpiCookie : public CookieIF {
|
||||||
public:
|
public:
|
||||||
|
static constexpr dur_millis_t DEFAULT_MUTEX_TIMEOUT = 20;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Each SPI device will have a corresponding cookie. The cookie is used by the communication
|
* Each SPI device will have a corresponding cookie. The cookie is used by the communication
|
||||||
* interface and contains device specific information like the largest expected size to be
|
* interface and contains device specific information like the largest expected size to be
|
||||||
@ -139,9 +143,43 @@ class SpiCookie : public CookieIF {
|
|||||||
*/
|
*/
|
||||||
void activateCsDeselect(bool deselectCs, uint16_t delayUsecs);
|
void activateCsDeselect(bool deselectCs, uint16_t delayUsecs);
|
||||||
|
|
||||||
|
void getMutexParams(MutexIF::TimeoutType& csTimeoutType, dur_millis_t& csTimeout) const;
|
||||||
|
void setMutexParams(MutexIF::TimeoutType csTimeoutType, dur_millis_t csTimeout);
|
||||||
|
|
||||||
|
void setCsLockManual(bool enable);
|
||||||
|
bool getCsLockManual() const;
|
||||||
|
|
||||||
spi_ioc_transfer* getTransferStructHandle();
|
spi_ioc_transfer* getTransferStructHandle();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
address_t spiAddress;
|
||||||
|
gpioId_t chipSelectPin;
|
||||||
|
std::string spiDevice;
|
||||||
|
|
||||||
|
spi::SpiComIfModes comIfMode;
|
||||||
|
|
||||||
|
// Required for regular mode
|
||||||
|
const size_t maxSize;
|
||||||
|
spi::SpiModes spiMode;
|
||||||
|
/**
|
||||||
|
* If this is set to true, the SPI ComIF will not perform any mutex locking for the
|
||||||
|
* CS mechanism. The user is responsible to locking and unlocking the mutex for the
|
||||||
|
* whole duration of the transfers.
|
||||||
|
*/
|
||||||
|
bool manualCsLock = false;
|
||||||
|
uint32_t spiSpeed;
|
||||||
|
bool halfDuplex = false;
|
||||||
|
|
||||||
|
MutexIF::TimeoutType csTimeoutType = MutexIF::TimeoutType::WAITING;
|
||||||
|
dur_millis_t csTimeout = DEFAULT_MUTEX_TIMEOUT;
|
||||||
|
|
||||||
|
// Required for callback mode
|
||||||
|
spi::send_callback_function_t sendCallback = nullptr;
|
||||||
|
void* callbackArgs = nullptr;
|
||||||
|
|
||||||
|
struct spi_ioc_transfer spiTransferStruct = {};
|
||||||
|
UncommonParameters uncommonParameters;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal constructor which initializes every field
|
* Internal constructor which initializes every field
|
||||||
* @param spiAddress
|
* @param spiAddress
|
||||||
@ -154,27 +192,8 @@ class SpiCookie : public CookieIF {
|
|||||||
* @param args
|
* @param args
|
||||||
*/
|
*/
|
||||||
SpiCookie(spi::SpiComIfModes comIfMode, address_t spiAddress, gpioId_t chipSelect,
|
SpiCookie(spi::SpiComIfModes comIfMode, address_t spiAddress, gpioId_t chipSelect,
|
||||||
std::string spiDev, const size_t maxSize, spi::SpiModes spiMode, uint32_t spiSpeed,
|
const size_t maxSize, spi::SpiModes spiMode, uint32_t spiSpeed,
|
||||||
spi::send_callback_function_t callback, void* args);
|
spi::send_callback_function_t callback, void* args);
|
||||||
|
|
||||||
address_t spiAddress;
|
|
||||||
gpioId_t chipSelectPin;
|
|
||||||
std::string spiDevice;
|
|
||||||
|
|
||||||
spi::SpiComIfModes comIfMode;
|
|
||||||
|
|
||||||
// Required for regular mode
|
|
||||||
const size_t maxSize;
|
|
||||||
spi::SpiModes spiMode;
|
|
||||||
uint32_t spiSpeed;
|
|
||||||
bool halfDuplex = false;
|
|
||||||
|
|
||||||
// Required for callback mode
|
|
||||||
spi::send_callback_function_t sendCallback = nullptr;
|
|
||||||
void* callbackArgs = nullptr;
|
|
||||||
|
|
||||||
struct spi_ioc_transfer spiTransferStruct = {};
|
|
||||||
UncommonParameters uncommonParameters;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* LINUX_SPI_SPICOOKIE_H_ */
|
#endif /* LINUX_SPI_SPICOOKIE_H_ */
|
||||||
|
@ -148,16 +148,16 @@ void UartComIF::setDatasizeOptions(struct termios* options, UartCookie* uartCook
|
|||||||
/* Clear size bits */
|
/* Clear size bits */
|
||||||
options->c_cflag &= ~CSIZE;
|
options->c_cflag &= ~CSIZE;
|
||||||
switch (uartCookie->getBitsPerWord()) {
|
switch (uartCookie->getBitsPerWord()) {
|
||||||
case 5:
|
case BitsPerWord::BITS_5:
|
||||||
options->c_cflag |= CS5;
|
options->c_cflag |= CS5;
|
||||||
break;
|
break;
|
||||||
case 6:
|
case BitsPerWord::BITS_6:
|
||||||
options->c_cflag |= CS6;
|
options->c_cflag |= CS6;
|
||||||
break;
|
break;
|
||||||
case 7:
|
case BitsPerWord::BITS_7:
|
||||||
options->c_cflag |= CS7;
|
options->c_cflag |= CS7;
|
||||||
break;
|
break;
|
||||||
case 8:
|
case BitsPerWord::BITS_8:
|
||||||
options->c_cflag |= CS8;
|
options->c_cflag |= CS8;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -193,126 +193,128 @@ void UartComIF::setFixedOptions(struct termios* options) {
|
|||||||
|
|
||||||
void UartComIF::configureBaudrate(struct termios* options, UartCookie* uartCookie) {
|
void UartComIF::configureBaudrate(struct termios* options, UartCookie* uartCookie) {
|
||||||
switch (uartCookie->getBaudrate()) {
|
switch (uartCookie->getBaudrate()) {
|
||||||
case 50:
|
case UartBaudRate::RATE_50:
|
||||||
cfsetispeed(options, B50);
|
cfsetispeed(options, B50);
|
||||||
cfsetospeed(options, B50);
|
cfsetospeed(options, B50);
|
||||||
break;
|
break;
|
||||||
case 75:
|
case UartBaudRate::RATE_75:
|
||||||
cfsetispeed(options, B75);
|
cfsetispeed(options, B75);
|
||||||
cfsetospeed(options, B75);
|
cfsetospeed(options, B75);
|
||||||
break;
|
break;
|
||||||
case 110:
|
case UartBaudRate::RATE_110:
|
||||||
cfsetispeed(options, B110);
|
cfsetispeed(options, B110);
|
||||||
cfsetospeed(options, B110);
|
cfsetospeed(options, B110);
|
||||||
break;
|
break;
|
||||||
case 134:
|
case UartBaudRate::RATE_134:
|
||||||
cfsetispeed(options, B134);
|
cfsetispeed(options, B134);
|
||||||
cfsetospeed(options, B134);
|
cfsetospeed(options, B134);
|
||||||
break;
|
break;
|
||||||
case 150:
|
case UartBaudRate::RATE_150:
|
||||||
cfsetispeed(options, B150);
|
cfsetispeed(options, B150);
|
||||||
cfsetospeed(options, B150);
|
cfsetospeed(options, B150);
|
||||||
break;
|
break;
|
||||||
case 200:
|
case UartBaudRate::RATE_200:
|
||||||
cfsetispeed(options, B200);
|
cfsetispeed(options, B200);
|
||||||
cfsetospeed(options, B200);
|
cfsetospeed(options, B200);
|
||||||
break;
|
break;
|
||||||
case 300:
|
case UartBaudRate::RATE_300:
|
||||||
cfsetispeed(options, B300);
|
cfsetispeed(options, B300);
|
||||||
cfsetospeed(options, B300);
|
cfsetospeed(options, B300);
|
||||||
break;
|
break;
|
||||||
case 600:
|
case UartBaudRate::RATE_600:
|
||||||
cfsetispeed(options, B600);
|
cfsetispeed(options, B600);
|
||||||
cfsetospeed(options, B600);
|
cfsetospeed(options, B600);
|
||||||
break;
|
break;
|
||||||
case 1200:
|
case UartBaudRate::RATE_1200:
|
||||||
cfsetispeed(options, B1200);
|
cfsetispeed(options, B1200);
|
||||||
cfsetospeed(options, B1200);
|
cfsetospeed(options, B1200);
|
||||||
break;
|
break;
|
||||||
case 1800:
|
case UartBaudRate::RATE_1800:
|
||||||
cfsetispeed(options, B1800);
|
cfsetispeed(options, B1800);
|
||||||
cfsetospeed(options, B1800);
|
cfsetospeed(options, B1800);
|
||||||
break;
|
break;
|
||||||
case 2400:
|
case UartBaudRate::RATE_2400:
|
||||||
cfsetispeed(options, B2400);
|
cfsetispeed(options, B2400);
|
||||||
cfsetospeed(options, B2400);
|
cfsetospeed(options, B2400);
|
||||||
break;
|
break;
|
||||||
case 4800:
|
case UartBaudRate::RATE_4800:
|
||||||
cfsetispeed(options, B4800);
|
cfsetispeed(options, B4800);
|
||||||
cfsetospeed(options, B4800);
|
cfsetospeed(options, B4800);
|
||||||
break;
|
break;
|
||||||
case 9600:
|
case UartBaudRate::RATE_9600:
|
||||||
cfsetispeed(options, B9600);
|
cfsetispeed(options, B9600);
|
||||||
cfsetospeed(options, B9600);
|
cfsetospeed(options, B9600);
|
||||||
break;
|
break;
|
||||||
case 19200:
|
case UartBaudRate::RATE_19200:
|
||||||
cfsetispeed(options, B19200);
|
cfsetispeed(options, B19200);
|
||||||
cfsetospeed(options, B19200);
|
cfsetospeed(options, B19200);
|
||||||
break;
|
break;
|
||||||
case 38400:
|
case UartBaudRate::RATE_38400:
|
||||||
cfsetispeed(options, B38400);
|
cfsetispeed(options, B38400);
|
||||||
cfsetospeed(options, B38400);
|
cfsetospeed(options, B38400);
|
||||||
break;
|
break;
|
||||||
case 57600:
|
case UartBaudRate::RATE_57600:
|
||||||
cfsetispeed(options, B57600);
|
cfsetispeed(options, B57600);
|
||||||
cfsetospeed(options, B57600);
|
cfsetospeed(options, B57600);
|
||||||
break;
|
break;
|
||||||
case 115200:
|
case UartBaudRate::RATE_115200:
|
||||||
cfsetispeed(options, B115200);
|
cfsetispeed(options, B115200);
|
||||||
cfsetospeed(options, B115200);
|
cfsetospeed(options, B115200);
|
||||||
break;
|
break;
|
||||||
case 230400:
|
case UartBaudRate::RATE_230400:
|
||||||
cfsetispeed(options, B230400);
|
cfsetispeed(options, B230400);
|
||||||
cfsetospeed(options, B230400);
|
cfsetospeed(options, B230400);
|
||||||
break;
|
break;
|
||||||
case 460800:
|
#ifndef __APPLE__
|
||||||
|
case UartBaudRate::RATE_460800:
|
||||||
cfsetispeed(options, B460800);
|
cfsetispeed(options, B460800);
|
||||||
cfsetospeed(options, B460800);
|
cfsetospeed(options, B460800);
|
||||||
break;
|
break;
|
||||||
case 500000:
|
case UartBaudRate::RATE_500000:
|
||||||
cfsetispeed(options, B500000);
|
cfsetispeed(options, B500000);
|
||||||
cfsetospeed(options, B500000);
|
cfsetospeed(options, B500000);
|
||||||
break;
|
break;
|
||||||
case 576000:
|
case UartBaudRate::RATE_576000:
|
||||||
cfsetispeed(options, B576000);
|
cfsetispeed(options, B576000);
|
||||||
cfsetospeed(options, B576000);
|
cfsetospeed(options, B576000);
|
||||||
break;
|
break;
|
||||||
case 921600:
|
case UartBaudRate::RATE_921600:
|
||||||
cfsetispeed(options, B921600);
|
cfsetispeed(options, B921600);
|
||||||
cfsetospeed(options, B921600);
|
cfsetospeed(options, B921600);
|
||||||
break;
|
break;
|
||||||
case 1000000:
|
case UartBaudRate::RATE_1000000:
|
||||||
cfsetispeed(options, B1000000);
|
cfsetispeed(options, B1000000);
|
||||||
cfsetospeed(options, B1000000);
|
cfsetospeed(options, B1000000);
|
||||||
break;
|
break;
|
||||||
case 1152000:
|
case UartBaudRate::RATE_1152000:
|
||||||
cfsetispeed(options, B1152000);
|
cfsetispeed(options, B1152000);
|
||||||
cfsetospeed(options, B1152000);
|
cfsetospeed(options, B1152000);
|
||||||
break;
|
break;
|
||||||
case 1500000:
|
case UartBaudRate::RATE_1500000:
|
||||||
cfsetispeed(options, B1500000);
|
cfsetispeed(options, B1500000);
|
||||||
cfsetospeed(options, B1500000);
|
cfsetospeed(options, B1500000);
|
||||||
break;
|
break;
|
||||||
case 2000000:
|
case UartBaudRate::RATE_2000000:
|
||||||
cfsetispeed(options, B2000000);
|
cfsetispeed(options, B2000000);
|
||||||
cfsetospeed(options, B2000000);
|
cfsetospeed(options, B2000000);
|
||||||
break;
|
break;
|
||||||
case 2500000:
|
case UartBaudRate::RATE_2500000:
|
||||||
cfsetispeed(options, B2500000);
|
cfsetispeed(options, B2500000);
|
||||||
cfsetospeed(options, B2500000);
|
cfsetospeed(options, B2500000);
|
||||||
break;
|
break;
|
||||||
case 3000000:
|
case UartBaudRate::RATE_3000000:
|
||||||
cfsetispeed(options, B3000000);
|
cfsetispeed(options, B3000000);
|
||||||
cfsetospeed(options, B3000000);
|
cfsetospeed(options, B3000000);
|
||||||
break;
|
break;
|
||||||
case 3500000:
|
case UartBaudRate::RATE_3500000:
|
||||||
cfsetispeed(options, B3500000);
|
cfsetispeed(options, B3500000);
|
||||||
cfsetospeed(options, B3500000);
|
cfsetospeed(options, B3500000);
|
||||||
break;
|
break;
|
||||||
case 4000000:
|
case UartBaudRate::RATE_4000000:
|
||||||
cfsetispeed(options, B4000000);
|
cfsetispeed(options, B4000000);
|
||||||
cfsetospeed(options, B4000000);
|
cfsetospeed(options, B4000000);
|
||||||
break;
|
break;
|
||||||
|
#endif // ! __APPLE__
|
||||||
default:
|
default:
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "UartComIF::configureBaudrate: Baudrate not supported" << std::endl;
|
sif::warning << "UartComIF::configureBaudrate: Baudrate not supported" << std::endl;
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#include <fsfw/serviceinterface.h>
|
#include <fsfw/serviceinterface.h>
|
||||||
|
|
||||||
UartCookie::UartCookie(object_id_t handlerId, std::string deviceFile, UartModes uartMode,
|
UartCookie::UartCookie(object_id_t handlerId, std::string deviceFile, UartModes uartMode,
|
||||||
uint32_t baudrate, size_t maxReplyLen)
|
UartBaudRate baudrate, size_t maxReplyLen)
|
||||||
: handlerId(handlerId),
|
: handlerId(handlerId),
|
||||||
deviceFile(deviceFile),
|
deviceFile(deviceFile),
|
||||||
uartMode(uartMode),
|
uartMode(uartMode),
|
||||||
@ -12,7 +12,7 @@ UartCookie::UartCookie(object_id_t handlerId, std::string deviceFile, UartModes
|
|||||||
|
|
||||||
UartCookie::~UartCookie() {}
|
UartCookie::~UartCookie() {}
|
||||||
|
|
||||||
uint32_t UartCookie::getBaudrate() const { return baudrate; }
|
UartBaudRate UartCookie::getBaudrate() const { return baudrate; }
|
||||||
|
|
||||||
size_t UartCookie::getMaxReplyLen() const { return maxReplyLen; }
|
size_t UartCookie::getMaxReplyLen() const { return maxReplyLen; }
|
||||||
|
|
||||||
@ -24,23 +24,9 @@ void UartCookie::setParityEven() { parity = Parity::EVEN; }
|
|||||||
|
|
||||||
Parity UartCookie::getParity() const { return parity; }
|
Parity UartCookie::getParity() const { return parity; }
|
||||||
|
|
||||||
void UartCookie::setBitsPerWord(uint8_t bitsPerWord_) {
|
void UartCookie::setBitsPerWord(BitsPerWord bitsPerWord_) { bitsPerWord = bitsPerWord_; }
|
||||||
switch (bitsPerWord_) {
|
|
||||||
case 5:
|
|
||||||
case 6:
|
|
||||||
case 7:
|
|
||||||
case 8:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::debug << "UartCookie::setBitsPerWord: Invalid bits per word specified" << std::endl;
|
|
||||||
#endif
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
bitsPerWord = bitsPerWord_;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t UartCookie::getBitsPerWord() const { return bitsPerWord; }
|
BitsPerWord UartCookie::getBitsPerWord() const { return bitsPerWord; }
|
||||||
|
|
||||||
StopBits UartCookie::getStopBits() const { return stopBits; }
|
StopBits UartCookie::getStopBits() const { return stopBits; }
|
||||||
|
|
||||||
|
@ -12,6 +12,41 @@ enum class StopBits { ONE_STOP_BIT, TWO_STOP_BITS };
|
|||||||
|
|
||||||
enum class UartModes { CANONICAL, NON_CANONICAL };
|
enum class UartModes { CANONICAL, NON_CANONICAL };
|
||||||
|
|
||||||
|
enum class BitsPerWord { BITS_5, BITS_6, BITS_7, BITS_8 };
|
||||||
|
|
||||||
|
enum class UartBaudRate {
|
||||||
|
RATE_50,
|
||||||
|
RATE_75,
|
||||||
|
RATE_110,
|
||||||
|
RATE_134,
|
||||||
|
RATE_150,
|
||||||
|
RATE_200,
|
||||||
|
RATE_300,
|
||||||
|
RATE_600,
|
||||||
|
RATE_1200,
|
||||||
|
RATE_1800,
|
||||||
|
RATE_2400,
|
||||||
|
RATE_4800,
|
||||||
|
RATE_9600,
|
||||||
|
RATE_19200,
|
||||||
|
RATE_38400,
|
||||||
|
RATE_57600,
|
||||||
|
RATE_115200,
|
||||||
|
RATE_230400,
|
||||||
|
RATE_460800,
|
||||||
|
RATE_500000,
|
||||||
|
RATE_576000,
|
||||||
|
RATE_921600,
|
||||||
|
RATE_1000000,
|
||||||
|
RATE_1152000,
|
||||||
|
RATE_1500000,
|
||||||
|
RATE_2000000,
|
||||||
|
RATE_2500000,
|
||||||
|
RATE_3000000,
|
||||||
|
RATE_3500000,
|
||||||
|
RATE_4000000
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Cookie for the UartComIF. There are many options available to configure the UART driver.
|
* @brief Cookie for the UartComIF. There are many options available to configure the UART driver.
|
||||||
* The constructor only requests for common options like the baudrate. Other options can
|
* The constructor only requests for common options like the baudrate. Other options can
|
||||||
@ -27,25 +62,23 @@ class UartCookie : public CookieIF {
|
|||||||
* @param uartMode Specify the UART mode. The canonical mode should be used if the
|
* @param uartMode Specify the UART mode. The canonical mode should be used if the
|
||||||
* messages are separated by a delimited character like '\n'. See the
|
* messages are separated by a delimited character like '\n'. See the
|
||||||
* termios documentation for more information
|
* termios documentation for more information
|
||||||
* @param baudrate The baudrate to use for input and output. Possible Baudrates are: 50,
|
* @param baudrate The baudrate to use for input and output.
|
||||||
* 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, B19200,
|
|
||||||
* 38400, 57600, 115200, 230400, 460800
|
|
||||||
* @param maxReplyLen The maximum size an object using this cookie expects
|
* @param maxReplyLen The maximum size an object using this cookie expects
|
||||||
* @details
|
* @details
|
||||||
* Default configuration: No parity
|
* Default configuration: No parity
|
||||||
* 8 databits (number of bits transfered with one uart frame)
|
* 8 databits (number of bits transfered with one uart frame)
|
||||||
* One stop bit
|
* One stop bit
|
||||||
*/
|
*/
|
||||||
UartCookie(object_id_t handlerId, std::string deviceFile, UartModes uartMode, uint32_t baudrate,
|
UartCookie(object_id_t handlerId, std::string deviceFile, UartModes uartMode,
|
||||||
size_t maxReplyLen);
|
UartBaudRate baudrate, size_t maxReplyLen);
|
||||||
|
|
||||||
virtual ~UartCookie();
|
virtual ~UartCookie();
|
||||||
|
|
||||||
uint32_t getBaudrate() const;
|
UartBaudRate getBaudrate() const;
|
||||||
size_t getMaxReplyLen() const;
|
size_t getMaxReplyLen() const;
|
||||||
std::string getDeviceFile() const;
|
std::string getDeviceFile() const;
|
||||||
Parity getParity() const;
|
Parity getParity() const;
|
||||||
uint8_t getBitsPerWord() const;
|
BitsPerWord getBitsPerWord() const;
|
||||||
StopBits getStopBits() const;
|
StopBits getStopBits() const;
|
||||||
UartModes getUartMode() const;
|
UartModes getUartMode() const;
|
||||||
object_id_t getHandlerId() const;
|
object_id_t getHandlerId() const;
|
||||||
@ -76,7 +109,7 @@ class UartCookie : public CookieIF {
|
|||||||
/**
|
/**
|
||||||
* Function two set number of bits per UART frame.
|
* Function two set number of bits per UART frame.
|
||||||
*/
|
*/
|
||||||
void setBitsPerWord(uint8_t bitsPerWord_);
|
void setBitsPerWord(BitsPerWord bitsPerWord_);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function to specify the number of stopbits.
|
* Function to specify the number of stopbits.
|
||||||
@ -97,10 +130,10 @@ class UartCookie : public CookieIF {
|
|||||||
std::string deviceFile;
|
std::string deviceFile;
|
||||||
const UartModes uartMode;
|
const UartModes uartMode;
|
||||||
bool flushInput = false;
|
bool flushInput = false;
|
||||||
uint32_t baudrate;
|
UartBaudRate baudrate;
|
||||||
size_t maxReplyLen = 0;
|
size_t maxReplyLen = 0;
|
||||||
Parity parity = Parity::NONE;
|
Parity parity = Parity::NONE;
|
||||||
uint8_t bitsPerWord = 8;
|
BitsPerWord bitsPerWord = BitsPerWord::BITS_8;
|
||||||
uint8_t readCycles = 1;
|
uint8_t readCycles = 1;
|
||||||
StopBits stopBits = StopBits::ONE_STOP_BIT;
|
StopBits stopBits = StopBits::ONE_STOP_BIT;
|
||||||
bool replySizeFixed = true;
|
bool replySizeFixed = true;
|
||||||
|
@ -21,7 +21,7 @@ using mspCb = void (*)(void);
|
|||||||
namespace spi {
|
namespace spi {
|
||||||
|
|
||||||
struct MspCfgBase {
|
struct MspCfgBase {
|
||||||
MspCfgBase();
|
MspCfgBase() {}
|
||||||
MspCfgBase(stm32h7::GpioCfg sck, stm32h7::GpioCfg mosi, stm32h7::GpioCfg miso,
|
MspCfgBase(stm32h7::GpioCfg sck, stm32h7::GpioCfg mosi, stm32h7::GpioCfg miso,
|
||||||
mspCb cleanupCb = nullptr, mspCb setupCb = nullptr)
|
mspCb cleanupCb = nullptr, mspCb setupCb = nullptr)
|
||||||
: sck(sck), mosi(mosi), miso(miso), cleanupCb(cleanupCb), setupCb(setupCb) {}
|
: sck(sck), mosi(mosi), miso(miso), cleanupCb(cleanupCb), setupCb(setupCb) {}
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
if [[ ! -f README.md ]]; then
|
|
||||||
cd ..
|
|
||||||
fi
|
|
||||||
|
|
||||||
find ./src -iname *.h -o -iname *.cpp -o -iname *.c | xargs clang-format --style=file -i
|
|
||||||
find ./hal -iname *.h -o -iname *.cpp -o -iname *.c | xargs clang-format --style=file -i
|
|
||||||
find ./tests -iname *.h -o -iname *.cpp -o -iname *.c | xargs clang-format --style=file -i
|
|
22
scripts/auto-formatter.sh
Executable file
22
scripts/auto-formatter.sh
Executable file
@ -0,0 +1,22 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
if [[ ! -f README.md ]]; then
|
||||||
|
cd ..
|
||||||
|
fi
|
||||||
|
|
||||||
|
cmake_fmt="cmake-format"
|
||||||
|
if command -v ${cmake_fmt} &> /dev/null; then
|
||||||
|
cmake_fmt_cmd="${cmake_fmt} -i CMakeLists.txt"
|
||||||
|
eval ${cmake_fmt_cmd}
|
||||||
|
else
|
||||||
|
echo "No ${cmake_fmt} tool found, not formatting CMake files"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cpp_format="clang-format"
|
||||||
|
file_selectors="-iname *.h -o -iname *.cpp -o -iname *.c -o -iname *.tpp"
|
||||||
|
if command -v ${cpp_format} &> /dev/null; then
|
||||||
|
find ./src ${file_selectors} | xargs clang-format --style=file -i
|
||||||
|
find ./hal ${file_selectors} | xargs clang-format --style=file -i
|
||||||
|
find ./tests ${file_selectors} | xargs clang-format --style=file -i
|
||||||
|
else
|
||||||
|
echo "No ${cpp_format} tool found, not formatting C++/C files"
|
||||||
|
fi
|
@ -12,9 +12,7 @@ object_id_t CFDPHandler::packetDestination = 0;
|
|||||||
|
|
||||||
CFDPHandler::CFDPHandler(object_id_t setObjectId, CFDPDistributor* dist)
|
CFDPHandler::CFDPHandler(object_id_t setObjectId, CFDPDistributor* dist)
|
||||||
: SystemObject(setObjectId) {
|
: SystemObject(setObjectId) {
|
||||||
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
|
requestQueue = QueueFactory::instance()->createMessageQueue(CFDP_HANDLER_MAX_RECEPTION);
|
||||||
requestQueue = QueueFactory::instance()->createMessageQueue(
|
|
||||||
CFDP_HANDLER_MAX_RECEPTION, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
|
||||||
distributor = dist;
|
distributor = dist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ class HeaderSerializer : public SerializeIF, public PduHeaderIF {
|
|||||||
cfdp::WidthInBytes getLenEntityIds() const override;
|
cfdp::WidthInBytes getLenEntityIds() const override;
|
||||||
cfdp::WidthInBytes getLenSeqNum() const override;
|
cfdp::WidthInBytes getLenSeqNum() const override;
|
||||||
cfdp::SegmentMetadataFlag getSegmentMetadataFlag() const override;
|
cfdp::SegmentMetadataFlag getSegmentMetadataFlag() const override;
|
||||||
bool hasSegmentMetadataFlag() const;
|
bool hasSegmentMetadataFlag() const override;
|
||||||
void setSegmentationControl(cfdp::SegmentationControl);
|
void setSegmentationControl(cfdp::SegmentationControl);
|
||||||
|
|
||||||
void getSourceId(cfdp::EntityId& sourceId) const override;
|
void getSourceId(cfdp::EntityId& sourceId) const override;
|
||||||
|
@ -5,89 +5,88 @@
|
|||||||
#error Include FIFOBase.h before FIFOBase.tpp!
|
#error Include FIFOBase.h before FIFOBase.tpp!
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline FIFOBase<T>::FIFOBase(T* values, const size_t maxCapacity):
|
inline FIFOBase<T>::FIFOBase(T* values, const size_t maxCapacity)
|
||||||
maxCapacity(maxCapacity), values(values){};
|
: maxCapacity(maxCapacity), values(values){};
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline ReturnValue_t FIFOBase<T>::insert(T value) {
|
inline ReturnValue_t FIFOBase<T>::insert(T value) {
|
||||||
if (full()) {
|
if (full()) {
|
||||||
return FULL;
|
return FULL;
|
||||||
} else {
|
} else {
|
||||||
values[writeIndex] = value;
|
values[writeIndex] = value;
|
||||||
writeIndex = next(writeIndex);
|
writeIndex = next(writeIndex);
|
||||||
++currentSize;
|
++currentSize;
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline ReturnValue_t FIFOBase<T>::retrieve(T* value) {
|
inline ReturnValue_t FIFOBase<T>::retrieve(T* value) {
|
||||||
if (empty()) {
|
if (empty()) {
|
||||||
return EMPTY;
|
return EMPTY;
|
||||||
} else {
|
} else {
|
||||||
if (value == nullptr){
|
if (value == nullptr) {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
|
||||||
*value = values[readIndex];
|
|
||||||
readIndex = next(readIndex);
|
|
||||||
--currentSize;
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
|
||||||
}
|
}
|
||||||
|
*value = values[readIndex];
|
||||||
|
readIndex = next(readIndex);
|
||||||
|
--currentSize;
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline ReturnValue_t FIFOBase<T>::peek(T* value) {
|
inline ReturnValue_t FIFOBase<T>::peek(T* value) {
|
||||||
if(empty()) {
|
if (empty()) {
|
||||||
return EMPTY;
|
return EMPTY;
|
||||||
} else {
|
} else {
|
||||||
if (value == nullptr){
|
if (value == nullptr) {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
|
||||||
*value = values[readIndex];
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
|
||||||
}
|
}
|
||||||
|
*value = values[readIndex];
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline ReturnValue_t FIFOBase<T>::pop() {
|
inline ReturnValue_t FIFOBase<T>::pop() {
|
||||||
T value;
|
T value;
|
||||||
return this->retrieve(&value);
|
return this->retrieve(&value);
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline bool FIFOBase<T>::empty() {
|
inline bool FIFOBase<T>::empty() {
|
||||||
return (currentSize == 0);
|
return (currentSize == 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline bool FIFOBase<T>::full() {
|
inline bool FIFOBase<T>::full() {
|
||||||
return (currentSize == maxCapacity);
|
return (currentSize == maxCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline size_t FIFOBase<T>::size() {
|
inline size_t FIFOBase<T>::size() {
|
||||||
return currentSize;
|
return currentSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline size_t FIFOBase<T>::next(size_t current) {
|
inline size_t FIFOBase<T>::next(size_t current) {
|
||||||
++current;
|
++current;
|
||||||
if (current == maxCapacity) {
|
if (current == maxCapacity) {
|
||||||
current = 0;
|
current = 0;
|
||||||
}
|
}
|
||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline size_t FIFOBase<T>::getMaxCapacity() const {
|
inline size_t FIFOBase<T>::getMaxCapacity() const {
|
||||||
return maxCapacity;
|
return maxCapacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
template<typename T>
|
inline void FIFOBase<T>::setContainer(T* data) {
|
||||||
inline void FIFOBase<T>::setContainer(T *data) {
|
this->values = data;
|
||||||
this->values = data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define FIXEDARRAYLIST_H_
|
#define FIXEDARRAYLIST_H_
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
#include "ArrayList.h"
|
#include "ArrayList.h"
|
||||||
/**
|
/**
|
||||||
@ -9,10 +10,9 @@
|
|||||||
*/
|
*/
|
||||||
template <typename T, size_t MAX_SIZE, typename count_t = uint8_t>
|
template <typename T, size_t MAX_SIZE, typename count_t = uint8_t>
|
||||||
class FixedArrayList : public ArrayList<T, count_t> {
|
class FixedArrayList : public ArrayList<T, count_t> {
|
||||||
#if !defined(_MSC_VER)
|
static_assert(MAX_SIZE <= std::numeric_limits<count_t>::max(),
|
||||||
static_assert(MAX_SIZE <= (std::pow(2, sizeof(count_t) * 8) - 1),
|
|
||||||
"count_t is not large enough to hold MAX_SIZE");
|
"count_t is not large enough to hold MAX_SIZE");
|
||||||
#endif
|
|
||||||
private:
|
private:
|
||||||
T data[MAX_SIZE];
|
T data[MAX_SIZE];
|
||||||
|
|
||||||
|
@ -1,109 +1,109 @@
|
|||||||
#ifndef FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_
|
#ifndef FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_
|
||||||
#define FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_
|
#define FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_
|
||||||
|
|
||||||
|
template <typename key_t, typename T, typename KEY_COMPARE>
|
||||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::insert(key_t key, T value,
|
||||||
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::insert(key_t key, T value, Iterator *storedValue) {
|
Iterator *storedValue) {
|
||||||
if (_size == theMap.maxSize()) {
|
if (_size == theMap.maxSize()) {
|
||||||
return MAP_FULL;
|
return MAP_FULL;
|
||||||
}
|
}
|
||||||
size_t position = findNicePlace(key);
|
size_t position = findNicePlace(key);
|
||||||
memmove(static_cast<void*>(&theMap[position + 1]),static_cast<void*>(&theMap[position]),
|
memmove(static_cast<void *>(&theMap[position + 1]), static_cast<void *>(&theMap[position]),
|
||||||
(_size - position) * sizeof(std::pair<key_t,T>));
|
(_size - position) * sizeof(std::pair<key_t, T>));
|
||||||
theMap[position].first = key;
|
theMap[position].first = key;
|
||||||
theMap[position].second = value;
|
theMap[position].second = value;
|
||||||
++_size;
|
++_size;
|
||||||
if (storedValue != nullptr) {
|
if (storedValue != nullptr) {
|
||||||
*storedValue = Iterator(&theMap[position]);
|
*storedValue = Iterator(&theMap[position]);
|
||||||
}
|
}
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
template <typename key_t, typename T, typename KEY_COMPARE>
|
||||||
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::insert(std::pair<key_t, T> pair) {
|
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::insert(std::pair<key_t, T> pair) {
|
||||||
return insert(pair.first, pair.second);
|
return insert(pair.first, pair.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
template <typename key_t, typename T, typename KEY_COMPARE>
|
||||||
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::exists(key_t key) const {
|
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::exists(key_t key) const {
|
||||||
ReturnValue_t result = KEY_DOES_NOT_EXIST;
|
ReturnValue_t result = KEY_DOES_NOT_EXIST;
|
||||||
if (findFirstIndex(key) < _size) {
|
if (findFirstIndex(key) < _size) {
|
||||||
result = HasReturnvaluesIF::RETURN_OK;
|
result = HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
template <typename key_t, typename T, typename KEY_COMPARE>
|
||||||
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::erase(Iterator *iter) {
|
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::erase(Iterator *iter) {
|
||||||
size_t i;
|
size_t i;
|
||||||
if ((i = findFirstIndex((*iter).value->first)) >= _size) {
|
if ((i = findFirstIndex((*iter).value->first)) >= _size) {
|
||||||
return KEY_DOES_NOT_EXIST;
|
return KEY_DOES_NOT_EXIST;
|
||||||
}
|
}
|
||||||
removeFromPosition(i);
|
removeFromPosition(i);
|
||||||
if (*iter != begin()) {
|
if (*iter != begin()) {
|
||||||
(*iter)--;
|
(*iter)--;
|
||||||
} else {
|
} else {
|
||||||
*iter = begin();
|
*iter = begin();
|
||||||
}
|
}
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
template <typename key_t, typename T, typename KEY_COMPARE>
|
||||||
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::erase(key_t key) {
|
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::erase(key_t key) {
|
||||||
size_t i;
|
size_t i;
|
||||||
if ((i = findFirstIndex(key)) >= _size) {
|
if ((i = findFirstIndex(key)) >= _size) {
|
||||||
return KEY_DOES_NOT_EXIST;
|
return KEY_DOES_NOT_EXIST;
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
removeFromPosition(i);
|
removeFromPosition(i);
|
||||||
i = findFirstIndex(key, i);
|
i = findFirstIndex(key, i);
|
||||||
} while (i < _size);
|
} while (i < _size);
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
template <typename key_t, typename T, typename KEY_COMPARE>
|
||||||
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::find(key_t key, T **value) const {
|
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::find(key_t key, T **value) const {
|
||||||
ReturnValue_t result = exists(key);
|
ReturnValue_t result = exists(key);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
*value = &theMap[findFirstIndex(key)].second;
|
*value = &theMap[findFirstIndex(key)].second;
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
template <typename key_t, typename T, typename KEY_COMPARE>
|
||||||
inline size_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::findFirstIndex(key_t key, size_t startAt) const {
|
inline size_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::findFirstIndex(key_t key,
|
||||||
if (startAt >= _size) {
|
size_t startAt) const {
|
||||||
return startAt + 1;
|
if (startAt >= _size) {
|
||||||
|
return startAt + 1;
|
||||||
|
}
|
||||||
|
size_t i = startAt;
|
||||||
|
for (i = startAt; i < _size; ++i) {
|
||||||
|
if (theMap[i].first == key) {
|
||||||
|
return i;
|
||||||
}
|
}
|
||||||
size_t i = startAt;
|
}
|
||||||
for (i = startAt; i < _size; ++i) {
|
return i;
|
||||||
if (theMap[i].first == key) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
template <typename key_t, typename T, typename KEY_COMPARE>
|
||||||
inline size_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::findNicePlace(key_t key) const {
|
inline size_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::findNicePlace(key_t key) const {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
for (i = 0; i < _size; ++i) {
|
for (i = 0; i < _size; ++i) {
|
||||||
if (myComp(key, theMap[i].first)) {
|
if (myComp(key, theMap[i].first)) {
|
||||||
return i;
|
return i;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return i;
|
}
|
||||||
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
template <typename key_t, typename T, typename KEY_COMPARE>
|
||||||
inline void FixedOrderedMultimap<key_t, T, KEY_COMPARE>::removeFromPosition(size_t position) {
|
inline void FixedOrderedMultimap<key_t, T, KEY_COMPARE>::removeFromPosition(size_t position) {
|
||||||
if (_size <= position) {
|
if (_size <= position) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
memmove(static_cast<void*>(&theMap[position]), static_cast<void*>(&theMap[position + 1]),
|
memmove(static_cast<void *>(&theMap[position]), static_cast<void *>(&theMap[position + 1]),
|
||||||
(_size - position - 1) * sizeof(std::pair<key_t,T>));
|
(_size - position - 1) * sizeof(std::pair<key_t, T>));
|
||||||
--_size;
|
--_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif /* FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_ */
|
#endif /* FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_ */
|
||||||
|
@ -10,16 +10,23 @@ class HybridIterator : public LinkedElement<T>::Iterator, public ArrayList<T, co
|
|||||||
HybridIterator() {}
|
HybridIterator() {}
|
||||||
|
|
||||||
HybridIterator(typename LinkedElement<T>::Iterator *iter)
|
HybridIterator(typename LinkedElement<T>::Iterator *iter)
|
||||||
: LinkedElement<T>::Iterator(*iter), value(iter->value), linked(true) {}
|
: LinkedElement<T>::Iterator(*iter), linked(true) {
|
||||||
|
if (iter != nullptr) {
|
||||||
|
value = iter->value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
HybridIterator(LinkedElement<T> *start)
|
HybridIterator(LinkedElement<T> *start) : LinkedElement<T>::Iterator(start), linked(true) {
|
||||||
: LinkedElement<T>::Iterator(start), value(start->value), linked(true) {}
|
if (start != nullptr) {
|
||||||
|
value = start->value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
HybridIterator(typename ArrayList<T, count_t>::Iterator start,
|
HybridIterator(typename ArrayList<T, count_t>::Iterator start,
|
||||||
typename ArrayList<T, count_t>::Iterator end)
|
typename ArrayList<T, count_t>::Iterator end)
|
||||||
: ArrayList<T, count_t>::Iterator(start), value(start.value), linked(false), end(end.value) {
|
: ArrayList<T, count_t>::Iterator(start), value(start.value), linked(false), end(end.value) {
|
||||||
if (value == this->end) {
|
if (value == this->end) {
|
||||||
value = NULL;
|
value = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,9 +13,7 @@ ControllerBase::ControllerBase(object_id_t setObjectId, object_id_t parentId,
|
|||||||
submode(SUBMODE_NONE),
|
submode(SUBMODE_NONE),
|
||||||
modeHelper(this),
|
modeHelper(this),
|
||||||
healthHelper(this, setObjectId) {
|
healthHelper(this, setObjectId) {
|
||||||
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
|
commandQueue = QueueFactory::instance()->createMessageQueue(commandQueueDepth);
|
||||||
commandQueue = QueueFactory::instance()->createMessageQueue(
|
|
||||||
commandQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ControllerBase::~ControllerBase() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }
|
ControllerBase::~ControllerBase() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }
|
||||||
|
@ -55,7 +55,7 @@ class ControllerBase : public HasModesIF,
|
|||||||
virtual void performControlOperation() = 0;
|
virtual void performControlOperation() = 0;
|
||||||
|
|
||||||
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
||||||
uint32_t *msToReachTheMode) = 0;
|
uint32_t *msToReachTheMode) override = 0;
|
||||||
|
|
||||||
const object_id_t parentId;
|
const object_id_t parentId;
|
||||||
|
|
||||||
@ -80,9 +80,9 @@ class ControllerBase : public HasModesIF,
|
|||||||
|
|
||||||
/** Mode helpers */
|
/** Mode helpers */
|
||||||
virtual void modeChanged(Mode_t mode, Submode_t submode);
|
virtual void modeChanged(Mode_t mode, Submode_t submode);
|
||||||
virtual void startTransition(Mode_t mode, Submode_t submode);
|
virtual void startTransition(Mode_t mode, Submode_t submode) override;
|
||||||
virtual void getMode(Mode_t *mode, Submode_t *submode);
|
virtual void getMode(Mode_t *mode, Submode_t *submode) override;
|
||||||
virtual void setToExternalControl();
|
virtual void setToExternalControl() override;
|
||||||
virtual void announceMode(bool recursive);
|
virtual void announceMode(bool recursive);
|
||||||
/** HK helpers */
|
/** HK helpers */
|
||||||
virtual void changeHK(Mode_t mode, Submode_t submode, bool enable);
|
virtual void changeHK(Mode_t mode, Submode_t submode, bool enable);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||||
PoolDataSetBase.cpp
|
PoolDataSetBase.cpp
|
||||||
PoolEntry.cpp
|
PoolEntry.cpp
|
||||||
)
|
)
|
@ -109,7 +109,7 @@ class PoolDataSetBase : public PoolDataSetIF, public SerializeIF, public HasRetu
|
|||||||
*/
|
*/
|
||||||
virtual ReturnValue_t unlockDataPool() override;
|
virtual ReturnValue_t unlockDataPool() override;
|
||||||
|
|
||||||
virtual uint16_t getFillCount() const;
|
virtual uint16_t getFillCount() const override;
|
||||||
|
|
||||||
/* SerializeIF implementations */
|
/* SerializeIF implementations */
|
||||||
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, const size_t maxSize,
|
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, const size_t maxSize,
|
||||||
|
@ -787,6 +787,10 @@ ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid, bool i
|
|||||||
// Serialize set packet into store.
|
// Serialize set packet into store.
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
result = setPacket.serialize(&storePtr, &size, expectedSize, SerializeIF::Endianness::BIG);
|
result = setPacket.serialize(&storePtr, &size, expectedSize, SerializeIF::Endianness::BIG);
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
ipcStore->deleteData(storeId);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
if (expectedSize != size) {
|
if (expectedSize != size) {
|
||||||
printWarningOrError(sif::OutputTypes::OUT_WARNING, "generateSetStructurePacket",
|
printWarningOrError(sif::OutputTypes::OUT_WARNING, "generateSetStructurePacket",
|
||||||
HasReturnvaluesIF::RETURN_FAILED,
|
HasReturnvaluesIF::RETURN_FAILED,
|
||||||
@ -801,7 +805,10 @@ ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid, bool i
|
|||||||
HousekeepingMessage::setHkStuctureReportReply(&reply, sid, storeId);
|
HousekeepingMessage::setHkStuctureReportReply(&reply, sid, storeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
hkQueue->reply(&reply);
|
result = hkQueue->reply(&reply);
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
ipcStore->deleteData(storeId);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,13 +94,14 @@ ReturnValue_t LocalPoolDataSetBase::serializeWithValidityBuffer(
|
|||||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||||
const uint8_t validityMaskSize = std::ceil(static_cast<float>(fillCount) / 8.0);
|
const uint8_t validityMaskSize = std::ceil(static_cast<float>(fillCount) / 8.0);
|
||||||
uint8_t *validityPtr = nullptr;
|
uint8_t *validityPtr = nullptr;
|
||||||
#ifdef _MSC_VER
|
#if defined(_MSC_VER) || defined(__clang__)
|
||||||
/* Use a std::vector here because MSVC will (rightly) not create a fixed size array
|
// Use a std::vector here because MSVC will (rightly) not create a fixed size array
|
||||||
with a non constant size specifier */
|
// with a non constant size specifier. The Apple compiler (LLVM) will not accept
|
||||||
std::vector<uint8_t> validityMask(validityMaskSize);
|
// the initialization of a variable sized array
|
||||||
|
std::vector<uint8_t> validityMask(validityMaskSize, 0);
|
||||||
validityPtr = validityMask.data();
|
validityPtr = validityMask.data();
|
||||||
#else
|
#else
|
||||||
uint8_t validityMask[validityMaskSize] = {0};
|
uint8_t validityMask[validityMaskSize] = {};
|
||||||
validityPtr = validityMask;
|
validityPtr = validityMask;
|
||||||
#endif
|
#endif
|
||||||
uint8_t validBufferIndex = 0;
|
uint8_t validBufferIndex = 0;
|
||||||
|
@ -23,8 +23,8 @@ class LocalPoolObjectBase : public PoolVariableIF, public HasReturnvaluesIF, pub
|
|||||||
LocalPoolObjectBase(object_id_t poolOwner, lp_id_t poolId, DataSetIF* dataSet = nullptr,
|
LocalPoolObjectBase(object_id_t poolOwner, lp_id_t poolId, DataSetIF* dataSet = nullptr,
|
||||||
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
|
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
|
||||||
|
|
||||||
void setReadWriteMode(pool_rwm_t newReadWriteMode);
|
void setReadWriteMode(pool_rwm_t newReadWriteMode) override;
|
||||||
pool_rwm_t getReadWriteMode() const;
|
pool_rwm_t getReadWriteMode() const override;
|
||||||
|
|
||||||
bool isValid() const override;
|
bool isValid() const override;
|
||||||
void setValid(bool valid) override;
|
void setValid(bool valid) override;
|
||||||
|
@ -5,205 +5,189 @@
|
|||||||
#error Include LocalPoolVariable.h before LocalPoolVariable.tpp!
|
#error Include LocalPoolVariable.h before LocalPoolVariable.tpp!
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline LocalPoolVariable<T>::LocalPoolVariable(HasLocalDataPoolIF* hkOwner,
|
inline LocalPoolVariable<T>::LocalPoolVariable(HasLocalDataPoolIF* hkOwner, lp_id_t poolId,
|
||||||
lp_id_t poolId, DataSetIF* dataSet, pool_rwm_t setReadWriteMode):
|
DataSetIF* dataSet, pool_rwm_t setReadWriteMode)
|
||||||
LocalPoolObjectBase(poolId, hkOwner, dataSet, setReadWriteMode) {}
|
: LocalPoolObjectBase(poolId, hkOwner, dataSet, setReadWriteMode) {}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline LocalPoolVariable<T>::LocalPoolVariable(object_id_t poolOwner,
|
inline LocalPoolVariable<T>::LocalPoolVariable(object_id_t poolOwner, lp_id_t poolId,
|
||||||
lp_id_t poolId, DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
|
DataSetIF* dataSet, pool_rwm_t setReadWriteMode)
|
||||||
LocalPoolObjectBase(poolOwner, poolId, dataSet, setReadWriteMode) {}
|
: LocalPoolObjectBase(poolOwner, poolId, dataSet, setReadWriteMode) {}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline LocalPoolVariable<T>::LocalPoolVariable(gp_id_t globalPoolId, DataSetIF* dataSet,
|
||||||
|
pool_rwm_t setReadWriteMode)
|
||||||
|
: LocalPoolObjectBase(globalPoolId.objectId, globalPoolId.localPoolId, dataSet,
|
||||||
|
setReadWriteMode) {}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline LocalPoolVariable<T>::LocalPoolVariable(gp_id_t globalPoolId,
|
inline ReturnValue_t LocalPoolVariable<T>::read(MutexIF::TimeoutType timeoutType,
|
||||||
DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
|
uint32_t timeoutMs) {
|
||||||
LocalPoolObjectBase(globalPoolId.objectId, globalPoolId.localPoolId,
|
if (hkManager == nullptr) {
|
||||||
dataSet, setReadWriteMode){}
|
return readWithoutLock();
|
||||||
|
}
|
||||||
|
MutexIF* mutex = LocalDpManagerAttorney::getMutexHandle(*hkManager);
|
||||||
template<typename T>
|
ReturnValue_t result = mutex->lockMutex(timeoutType, timeoutMs);
|
||||||
inline ReturnValue_t LocalPoolVariable<T>::read(
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
|
|
||||||
if(hkManager == nullptr) {
|
|
||||||
return readWithoutLock();
|
|
||||||
}
|
|
||||||
MutexIF* mutex = LocalDpManagerAttorney::getMutexHandle(*hkManager);
|
|
||||||
ReturnValue_t result = mutex->lockMutex(timeoutType, timeoutMs);
|
|
||||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result = readWithoutLock();
|
|
||||||
mutex->unlockMutex();
|
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
result = readWithoutLock();
|
||||||
|
mutex->unlockMutex();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline ReturnValue_t LocalPoolVariable<T>::readWithoutLock() {
|
inline ReturnValue_t LocalPoolVariable<T>::readWithoutLock() {
|
||||||
if(readWriteMode == pool_rwm_t::VAR_WRITE) {
|
if (readWriteMode == pool_rwm_t::VAR_WRITE) {
|
||||||
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
||||||
reportReadCommitError("LocalPoolVector",
|
reportReadCommitError("LocalPoolVector", PoolVariableIF::INVALID_READ_WRITE_MODE, true,
|
||||||
PoolVariableIF::INVALID_READ_WRITE_MODE, true, targetObjectId,
|
targetObjectId, localPoolId);
|
||||||
localPoolId);
|
return PoolVariableIF::INVALID_READ_WRITE_MODE;
|
||||||
return PoolVariableIF::INVALID_READ_WRITE_MODE;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
PoolEntry<T>* poolEntry = nullptr;
|
PoolEntry<T>* poolEntry = nullptr;
|
||||||
ReturnValue_t result = LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId,
|
ReturnValue_t result =
|
||||||
&poolEntry);
|
LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId, &poolEntry);
|
||||||
if(result != RETURN_OK) {
|
if (result != RETURN_OK) {
|
||||||
object_id_t ownerObjectId = hkManager->getCreatorObjectId();
|
object_id_t ownerObjectId = hkManager->getCreatorObjectId();
|
||||||
reportReadCommitError("LocalPoolVariable", result,
|
reportReadCommitError("LocalPoolVariable", result, false, ownerObjectId, localPoolId);
|
||||||
false, ownerObjectId, localPoolId);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->value = *(poolEntry->getDataPtr());
|
|
||||||
this->valid = poolEntry->getValid();
|
|
||||||
return RETURN_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline ReturnValue_t LocalPoolVariable<T>::commit(bool setValid,
|
|
||||||
MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
|
|
||||||
this->setValid(setValid);
|
|
||||||
return commit(timeoutType, timeoutMs);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline ReturnValue_t LocalPoolVariable<T>::commit(
|
|
||||||
MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
|
|
||||||
if(hkManager == nullptr) {
|
|
||||||
return commitWithoutLock();
|
|
||||||
}
|
|
||||||
MutexIF* mutex = LocalDpManagerAttorney::getMutexHandle(*hkManager);
|
|
||||||
ReturnValue_t result = mutex->lockMutex(timeoutType, timeoutMs);
|
|
||||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result = commitWithoutLock();
|
|
||||||
mutex->unlockMutex();
|
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->value = *(poolEntry->getDataPtr());
|
||||||
|
this->valid = poolEntry->getValid();
|
||||||
|
return RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
|
inline ReturnValue_t LocalPoolVariable<T>::commit(bool setValid, MutexIF::TimeoutType timeoutType,
|
||||||
|
uint32_t timeoutMs) {
|
||||||
|
this->setValid(setValid);
|
||||||
|
return commit(timeoutType, timeoutMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline ReturnValue_t LocalPoolVariable<T>::commit(MutexIF::TimeoutType timeoutType,
|
||||||
|
uint32_t timeoutMs) {
|
||||||
|
if (hkManager == nullptr) {
|
||||||
|
return commitWithoutLock();
|
||||||
|
}
|
||||||
|
MutexIF* mutex = LocalDpManagerAttorney::getMutexHandle(*hkManager);
|
||||||
|
ReturnValue_t result = mutex->lockMutex(timeoutType, timeoutMs);
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
result = commitWithoutLock();
|
||||||
|
mutex->unlockMutex();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
inline ReturnValue_t LocalPoolVariable<T>::commitWithoutLock() {
|
inline ReturnValue_t LocalPoolVariable<T>::commitWithoutLock() {
|
||||||
if(readWriteMode == pool_rwm_t::VAR_READ) {
|
if (readWriteMode == pool_rwm_t::VAR_READ) {
|
||||||
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
||||||
reportReadCommitError("LocalPoolVector",
|
reportReadCommitError("LocalPoolVector", PoolVariableIF::INVALID_READ_WRITE_MODE, false,
|
||||||
PoolVariableIF::INVALID_READ_WRITE_MODE, false, targetObjectId,
|
targetObjectId, localPoolId);
|
||||||
localPoolId);
|
return PoolVariableIF::INVALID_READ_WRITE_MODE;
|
||||||
return PoolVariableIF::INVALID_READ_WRITE_MODE;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
PoolEntry<T>* poolEntry = nullptr;
|
PoolEntry<T>* poolEntry = nullptr;
|
||||||
ReturnValue_t result = LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId,
|
ReturnValue_t result =
|
||||||
&poolEntry);
|
LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId, &poolEntry);
|
||||||
if(result != RETURN_OK) {
|
if (result != RETURN_OK) {
|
||||||
object_id_t ownerObjectId = hkManager->getCreatorObjectId();
|
object_id_t ownerObjectId = hkManager->getCreatorObjectId();
|
||||||
reportReadCommitError("LocalPoolVariable", result,
|
reportReadCommitError("LocalPoolVariable", result, false, ownerObjectId, localPoolId);
|
||||||
false, ownerObjectId, localPoolId);
|
return result;
|
||||||
return result;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
*(poolEntry->getDataPtr()) = this->value;
|
*(poolEntry->getDataPtr()) = this->value;
|
||||||
poolEntry->setValid(this->valid);
|
poolEntry->setValid(this->valid);
|
||||||
return RETURN_OK;
|
return RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline ReturnValue_t LocalPoolVariable<T>::serialize(uint8_t** buffer,
|
inline ReturnValue_t LocalPoolVariable<T>::serialize(
|
||||||
size_t* size, const size_t max_size,
|
uint8_t** buffer, size_t* size, const size_t max_size,
|
||||||
SerializeIF::Endianness streamEndianness) const {
|
SerializeIF::Endianness streamEndianness) const {
|
||||||
return SerializeAdapter::serialize(&value,
|
return SerializeAdapter::serialize(&value, buffer, size, max_size, streamEndianness);
|
||||||
buffer, size ,max_size, streamEndianness);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline size_t LocalPoolVariable<T>::getSerializedSize() const {
|
inline size_t LocalPoolVariable<T>::getSerializedSize() const {
|
||||||
return SerializeAdapter::getSerializedSize(&value);
|
return SerializeAdapter::getSerializedSize(&value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline ReturnValue_t LocalPoolVariable<T>::deSerialize(const uint8_t** buffer,
|
inline ReturnValue_t LocalPoolVariable<T>::deSerialize(const uint8_t** buffer, size_t* size,
|
||||||
size_t* size, SerializeIF::Endianness streamEndianness) {
|
SerializeIF::Endianness streamEndianness) {
|
||||||
return SerializeAdapter::deSerialize(&value, buffer, size, streamEndianness);
|
return SerializeAdapter::deSerialize(&value, buffer, size, streamEndianness);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline std::ostream& operator<< (std::ostream &out,
|
inline std::ostream& operator<<(std::ostream& out, const LocalPoolVariable<T>& var) {
|
||||||
const LocalPoolVariable<T> &var) {
|
out << var.value;
|
||||||
out << var.value;
|
return out;
|
||||||
return out;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline LocalPoolVariable<T>::operator T() const {
|
inline LocalPoolVariable<T>::operator T() const {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline LocalPoolVariable<T> & LocalPoolVariable<T>::operator=(
|
inline LocalPoolVariable<T>& LocalPoolVariable<T>::operator=(const T& newValue) {
|
||||||
const T& newValue) {
|
value = newValue;
|
||||||
value = newValue;
|
return *this;
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline LocalPoolVariable<T>& LocalPoolVariable<T>::operator =(
|
inline LocalPoolVariable<T>& LocalPoolVariable<T>::operator=(
|
||||||
const LocalPoolVariable<T>& newPoolVariable) {
|
const LocalPoolVariable<T>& newPoolVariable) {
|
||||||
value = newPoolVariable.value;
|
value = newPoolVariable.value;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline bool LocalPoolVariable<T>::operator ==(
|
inline bool LocalPoolVariable<T>::operator==(const LocalPoolVariable<T>& other) const {
|
||||||
const LocalPoolVariable<T> &other) const {
|
return this->value == other.value;
|
||||||
return this->value == other.value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline bool LocalPoolVariable<T>::operator ==(const T &other) const {
|
inline bool LocalPoolVariable<T>::operator==(const T& other) const {
|
||||||
return this->value == other;
|
return this->value == other;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
template<typename T>
|
inline bool LocalPoolVariable<T>::operator!=(const LocalPoolVariable<T>& other) const {
|
||||||
inline bool LocalPoolVariable<T>::operator !=(
|
return not(*this == other);
|
||||||
const LocalPoolVariable<T> &other) const {
|
|
||||||
return not (*this == other);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline bool LocalPoolVariable<T>::operator !=(const T &other) const {
|
inline bool LocalPoolVariable<T>::operator!=(const T& other) const {
|
||||||
return not (*this == other);
|
return not(*this == other);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
template<typename T>
|
inline bool LocalPoolVariable<T>::operator<(const LocalPoolVariable<T>& other) const {
|
||||||
inline bool LocalPoolVariable<T>::operator <(
|
return this->value < other.value;
|
||||||
const LocalPoolVariable<T> &other) const {
|
|
||||||
return this->value < other.value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline bool LocalPoolVariable<T>::operator <(const T &other) const {
|
inline bool LocalPoolVariable<T>::operator<(const T& other) const {
|
||||||
return this->value < other;
|
return this->value < other;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
template<typename T>
|
inline bool LocalPoolVariable<T>::operator>(const LocalPoolVariable<T>& other) const {
|
||||||
inline bool LocalPoolVariable<T>::operator >(
|
return not(*this < other);
|
||||||
const LocalPoolVariable<T> &other) const {
|
|
||||||
return not (*this < other);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
inline bool LocalPoolVariable<T>::operator >(const T &other) const {
|
inline bool LocalPoolVariable<T>::operator>(const T& other) const {
|
||||||
return not (*this < other);
|
return not(*this < other);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* FSFW_DATAPOOLLOCAL_LOCALPOOLVARIABLE_TPP_ */
|
#endif /* FSFW_DATAPOOLLOCAL_LOCALPOOLVARIABLE_TPP_ */
|
||||||
|
@ -5,174 +5,172 @@
|
|||||||
#error Include LocalPoolVector.h before LocalPoolVector.tpp!
|
#error Include LocalPoolVector.h before LocalPoolVector.tpp!
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template<typename T, uint16_t vectorSize>
|
template <typename T, uint16_t vectorSize>
|
||||||
inline LocalPoolVector<T, vectorSize>::LocalPoolVector(
|
inline LocalPoolVector<T, vectorSize>::LocalPoolVector(HasLocalDataPoolIF* hkOwner, lp_id_t poolId,
|
||||||
HasLocalDataPoolIF* hkOwner, lp_id_t poolId, DataSetIF* dataSet,
|
DataSetIF* dataSet,
|
||||||
pool_rwm_t setReadWriteMode):
|
pool_rwm_t setReadWriteMode)
|
||||||
LocalPoolObjectBase(poolId, hkOwner, dataSet, setReadWriteMode) {}
|
: LocalPoolObjectBase(poolId, hkOwner, dataSet, setReadWriteMode) {}
|
||||||
|
|
||||||
template<typename T, uint16_t vectorSize>
|
template <typename T, uint16_t vectorSize>
|
||||||
inline LocalPoolVector<T, vectorSize>::LocalPoolVector(object_id_t poolOwner,
|
inline LocalPoolVector<T, vectorSize>::LocalPoolVector(object_id_t poolOwner, lp_id_t poolId,
|
||||||
lp_id_t poolId, DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
|
DataSetIF* dataSet,
|
||||||
LocalPoolObjectBase(poolOwner, poolId, dataSet, setReadWriteMode) {}
|
pool_rwm_t setReadWriteMode)
|
||||||
|
: LocalPoolObjectBase(poolOwner, poolId, dataSet, setReadWriteMode) {}
|
||||||
|
|
||||||
template<typename T, uint16_t vectorSize>
|
template <typename T, uint16_t vectorSize>
|
||||||
inline LocalPoolVector<T, vectorSize>::LocalPoolVector(gp_id_t globalPoolId,
|
inline LocalPoolVector<T, vectorSize>::LocalPoolVector(gp_id_t globalPoolId, DataSetIF* dataSet,
|
||||||
DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
|
pool_rwm_t setReadWriteMode)
|
||||||
LocalPoolObjectBase(globalPoolId.objectId, globalPoolId.localPoolId,
|
: LocalPoolObjectBase(globalPoolId.objectId, globalPoolId.localPoolId, dataSet,
|
||||||
dataSet, setReadWriteMode) {}
|
setReadWriteMode) {}
|
||||||
|
|
||||||
template<typename T, uint16_t vectorSize>
|
template <typename T, uint16_t vectorSize>
|
||||||
inline ReturnValue_t LocalPoolVector<T, vectorSize>::read(
|
inline ReturnValue_t LocalPoolVector<T, vectorSize>::read(MutexIF::TimeoutType timeoutType,
|
||||||
MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
|
uint32_t timeoutMs) {
|
||||||
MutexGuard(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs);
|
MutexGuard(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs);
|
||||||
return readWithoutLock();
|
return readWithoutLock();
|
||||||
}
|
}
|
||||||
template<typename T, uint16_t vectorSize>
|
template <typename T, uint16_t vectorSize>
|
||||||
inline ReturnValue_t LocalPoolVector<T, vectorSize>::readWithoutLock() {
|
inline ReturnValue_t LocalPoolVector<T, vectorSize>::readWithoutLock() {
|
||||||
if(readWriteMode == pool_rwm_t::VAR_WRITE) {
|
if (readWriteMode == pool_rwm_t::VAR_WRITE) {
|
||||||
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
||||||
reportReadCommitError("LocalPoolVector",
|
reportReadCommitError("LocalPoolVector", PoolVariableIF::INVALID_READ_WRITE_MODE, true,
|
||||||
PoolVariableIF::INVALID_READ_WRITE_MODE, true, targetObjectId,
|
targetObjectId, localPoolId);
|
||||||
localPoolId);
|
return PoolVariableIF::INVALID_READ_WRITE_MODE;
|
||||||
return PoolVariableIF::INVALID_READ_WRITE_MODE;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
PoolEntry<T>* poolEntry = nullptr;
|
PoolEntry<T>* poolEntry = nullptr;
|
||||||
ReturnValue_t result = LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId,
|
ReturnValue_t result =
|
||||||
&poolEntry);
|
LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId, &poolEntry);
|
||||||
memset(this->value, 0, vectorSize * sizeof(T));
|
memset(this->value, 0, vectorSize * sizeof(T));
|
||||||
|
|
||||||
if(result != RETURN_OK) {
|
if (result != RETURN_OK) {
|
||||||
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
||||||
reportReadCommitError("LocalPoolVector", result, true, targetObjectId,
|
reportReadCommitError("LocalPoolVector", result, true, targetObjectId, localPoolId);
|
||||||
localPoolId);
|
return result;
|
||||||
return result;
|
}
|
||||||
}
|
std::memcpy(this->value, poolEntry->getDataPtr(), poolEntry->getByteSize());
|
||||||
std::memcpy(this->value, poolEntry->getDataPtr(), poolEntry->getByteSize());
|
this->valid = poolEntry->getValid();
|
||||||
this->valid = poolEntry->getValid();
|
return RETURN_OK;
|
||||||
return RETURN_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, uint16_t vectorSize>
|
template <typename T, uint16_t vectorSize>
|
||||||
inline ReturnValue_t LocalPoolVector<T, vectorSize>::commit(bool valid,
|
inline ReturnValue_t LocalPoolVector<T, vectorSize>::commit(bool valid,
|
||||||
MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
|
MutexIF::TimeoutType timeoutType,
|
||||||
this->setValid(valid);
|
uint32_t timeoutMs) {
|
||||||
return commit(timeoutType, timeoutMs);
|
this->setValid(valid);
|
||||||
|
return commit(timeoutType, timeoutMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, uint16_t vectorSize>
|
template <typename T, uint16_t vectorSize>
|
||||||
inline ReturnValue_t LocalPoolVector<T, vectorSize>::commit(
|
inline ReturnValue_t LocalPoolVector<T, vectorSize>::commit(MutexIF::TimeoutType timeoutType,
|
||||||
MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
|
uint32_t timeoutMs) {
|
||||||
MutexGuard(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs);
|
MutexGuard(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs);
|
||||||
return commitWithoutLock();
|
return commitWithoutLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, uint16_t vectorSize>
|
template <typename T, uint16_t vectorSize>
|
||||||
inline ReturnValue_t LocalPoolVector<T, vectorSize>::commitWithoutLock() {
|
inline ReturnValue_t LocalPoolVector<T, vectorSize>::commitWithoutLock() {
|
||||||
if(readWriteMode == pool_rwm_t::VAR_READ) {
|
if (readWriteMode == pool_rwm_t::VAR_READ) {
|
||||||
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
||||||
reportReadCommitError("LocalPoolVector",
|
reportReadCommitError("LocalPoolVector", PoolVariableIF::INVALID_READ_WRITE_MODE, false,
|
||||||
PoolVariableIF::INVALID_READ_WRITE_MODE, false, targetObjectId,
|
targetObjectId, localPoolId);
|
||||||
localPoolId);
|
return PoolVariableIF::INVALID_READ_WRITE_MODE;
|
||||||
return PoolVariableIF::INVALID_READ_WRITE_MODE;
|
}
|
||||||
}
|
PoolEntry<T>* poolEntry = nullptr;
|
||||||
PoolEntry<T>* poolEntry = nullptr;
|
ReturnValue_t result =
|
||||||
ReturnValue_t result = LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId,
|
LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId, &poolEntry);
|
||||||
&poolEntry);
|
if (result != RETURN_OK) {
|
||||||
if(result != RETURN_OK) {
|
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
||||||
object_id_t targetObjectId = hkManager->getCreatorObjectId();
|
reportReadCommitError("LocalPoolVector", result, false, targetObjectId, localPoolId);
|
||||||
reportReadCommitError("LocalPoolVector", result, false, targetObjectId,
|
|
||||||
localPoolId);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
std::memcpy(poolEntry->getDataPtr(), this->value, poolEntry->getByteSize());
|
|
||||||
poolEntry->setValid(this->valid);
|
|
||||||
return RETURN_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, uint16_t vectorSize>
|
|
||||||
inline T& LocalPoolVector<T, vectorSize>::operator [](size_t i) {
|
|
||||||
if(i < vectorSize) {
|
|
||||||
return value[i];
|
|
||||||
}
|
|
||||||
// If this happens, I have to set some value. I consider this
|
|
||||||
// a configuration error, but I wont exit here.
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::warning << "LocalPoolVector: Invalid index. Setting or returning"
|
|
||||||
" last value!" << std::endl;
|
|
||||||
#else
|
|
||||||
sif::printWarning("LocalPoolVector: Invalid index. Setting or returning"
|
|
||||||
" last value!\n");
|
|
||||||
#endif
|
|
||||||
return value[vectorSize - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, uint16_t vectorSize>
|
|
||||||
inline const T& LocalPoolVector<T, vectorSize>::operator [](size_t i) const {
|
|
||||||
if(i < vectorSize) {
|
|
||||||
return value[i];
|
|
||||||
}
|
|
||||||
// If this happens, I have to set some value. I consider this
|
|
||||||
// a configuration error, but I wont exit here.
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::warning << "LocalPoolVector: Invalid index. Setting or returning"
|
|
||||||
" last value!" << std::endl;
|
|
||||||
#else
|
|
||||||
sif::printWarning("LocalPoolVector: Invalid index. Setting or returning"
|
|
||||||
" last value!\n");
|
|
||||||
#endif
|
|
||||||
return value[vectorSize - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, uint16_t vectorSize>
|
|
||||||
inline ReturnValue_t LocalPoolVector<T, vectorSize>::serialize(uint8_t** buffer,
|
|
||||||
size_t* size, size_t maxSize,
|
|
||||||
SerializeIF::Endianness streamEndianness) const {
|
|
||||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
|
|
||||||
for (uint16_t i = 0; i < vectorSize; i++) {
|
|
||||||
result = SerializeAdapter::serialize(&(value[i]), buffer, size,
|
|
||||||
maxSize, streamEndianness);
|
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
std::memcpy(poolEntry->getDataPtr(), this->value, poolEntry->getByteSize());
|
||||||
|
poolEntry->setValid(this->valid);
|
||||||
|
return RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, uint16_t vectorSize>
|
template <typename T, uint16_t vectorSize>
|
||||||
|
inline T& LocalPoolVector<T, vectorSize>::operator[](size_t i) {
|
||||||
|
if (i < vectorSize) {
|
||||||
|
return value[i];
|
||||||
|
}
|
||||||
|
// If this happens, I have to set some value. I consider this
|
||||||
|
// a configuration error, but I wont exit here.
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::warning << "LocalPoolVector: Invalid index. Setting or returning"
|
||||||
|
" last value!"
|
||||||
|
<< std::endl;
|
||||||
|
#else
|
||||||
|
sif::printWarning(
|
||||||
|
"LocalPoolVector: Invalid index. Setting or returning"
|
||||||
|
" last value!\n");
|
||||||
|
#endif
|
||||||
|
return value[vectorSize - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, uint16_t vectorSize>
|
||||||
|
inline const T& LocalPoolVector<T, vectorSize>::operator[](size_t i) const {
|
||||||
|
if (i < vectorSize) {
|
||||||
|
return value[i];
|
||||||
|
}
|
||||||
|
// If this happens, I have to set some value. I consider this
|
||||||
|
// a configuration error, but I wont exit here.
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::warning << "LocalPoolVector: Invalid index. Setting or returning"
|
||||||
|
" last value!"
|
||||||
|
<< std::endl;
|
||||||
|
#else
|
||||||
|
sif::printWarning(
|
||||||
|
"LocalPoolVector: Invalid index. Setting or returning"
|
||||||
|
" last value!\n");
|
||||||
|
#endif
|
||||||
|
return value[vectorSize - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, uint16_t vectorSize>
|
||||||
|
inline ReturnValue_t LocalPoolVector<T, vectorSize>::serialize(
|
||||||
|
uint8_t** buffer, size_t* size, size_t maxSize,
|
||||||
|
SerializeIF::Endianness streamEndianness) const {
|
||||||
|
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
for (uint16_t i = 0; i < vectorSize; i++) {
|
||||||
|
result = SerializeAdapter::serialize(&(value[i]), buffer, size, maxSize, streamEndianness);
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, uint16_t vectorSize>
|
||||||
inline size_t LocalPoolVector<T, vectorSize>::getSerializedSize() const {
|
inline size_t LocalPoolVector<T, vectorSize>::getSerializedSize() const {
|
||||||
return vectorSize * SerializeAdapter::getSerializedSize(value);
|
return vectorSize * SerializeAdapter::getSerializedSize(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, uint16_t vectorSize>
|
template <typename T, uint16_t vectorSize>
|
||||||
inline ReturnValue_t LocalPoolVector<T, vectorSize>::deSerialize(
|
inline ReturnValue_t LocalPoolVector<T, vectorSize>::deSerialize(
|
||||||
const uint8_t** buffer, size_t* size,
|
const uint8_t** buffer, size_t* size, SerializeIF::Endianness streamEndianness) {
|
||||||
SerializeIF::Endianness streamEndianness) {
|
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
|
||||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
|
for (uint16_t i = 0; i < vectorSize; i++) {
|
||||||
for (uint16_t i = 0; i < vectorSize; i++) {
|
result = SerializeAdapter::deSerialize(&(value[i]), buffer, size, streamEndianness);
|
||||||
result = SerializeAdapter::deSerialize(&(value[i]), buffer, size,
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
streamEndianness);
|
break;
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result;
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
template<typename T, uint16_t vectorSize>
|
template <typename T, uint16_t vectorSize>
|
||||||
inline std::ostream& operator<< (std::ostream &out,
|
inline std::ostream& operator<<(std::ostream& out, const LocalPoolVector<T, vectorSize>& var) {
|
||||||
const LocalPoolVector<T, vectorSize> &var) {
|
out << "Vector: [";
|
||||||
out << "Vector: [";
|
for (int i = 0; i < vectorSize; i++) {
|
||||||
for(int i = 0;i < vectorSize; i++) {
|
out << var.value[i];
|
||||||
out << var.value[i];
|
if (i < vectorSize - 1) {
|
||||||
if(i < vectorSize - 1) {
|
out << ", ";
|
||||||
out << ", ";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
out << "]";
|
}
|
||||||
return out;
|
out << "]";
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -26,7 +26,11 @@ void AssemblyBase::performChildOperation() {
|
|||||||
|
|
||||||
void AssemblyBase::startTransition(Mode_t mode, Submode_t submode) {
|
void AssemblyBase::startTransition(Mode_t mode, Submode_t submode) {
|
||||||
doStartTransition(mode, submode);
|
doStartTransition(mode, submode);
|
||||||
triggerModeHelperEvents(mode, submode);
|
if (modeHelper.isForced()) {
|
||||||
|
triggerEvent(FORCING_MODE, mode, submode);
|
||||||
|
} else {
|
||||||
|
triggerEvent(CHANGING_MODE, mode, submode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssemblyBase::doStartTransition(Mode_t mode, Submode_t submode) {
|
void AssemblyBase::doStartTransition(Mode_t mode, Submode_t submode) {
|
||||||
@ -73,10 +77,9 @@ bool AssemblyBase::handleChildrenChangedHealth() {
|
|||||||
}
|
}
|
||||||
HealthState healthState = healthHelper.healthTable->getHealth(iter->first);
|
HealthState healthState = healthHelper.healthTable->getHealth(iter->first);
|
||||||
if (healthState == HasHealthIF::NEEDS_RECOVERY) {
|
if (healthState == HasHealthIF::NEEDS_RECOVERY) {
|
||||||
triggerEvent(TRYING_RECOVERY, iter->first, 0);
|
triggerEvent(TRYING_RECOVERY);
|
||||||
recoveryState = RECOVERY_STARTED;
|
recoveryState = RECOVERY_STARTED;
|
||||||
recoveringDevice = iter;
|
recoveringDevice = iter;
|
||||||
// The user needs to take care of commanding the children off in commandChildren
|
|
||||||
doStartTransition(targetMode, targetSubmode);
|
doStartTransition(targetMode, targetSubmode);
|
||||||
} else {
|
} else {
|
||||||
triggerEvent(CHILD_CHANGED_HEALTH);
|
triggerEvent(CHILD_CHANGED_HEALTH);
|
||||||
@ -225,9 +228,6 @@ ReturnValue_t AssemblyBase::handleHealthReply(CommandMessage* message) {
|
|||||||
bool AssemblyBase::checkAndHandleRecovery() {
|
bool AssemblyBase::checkAndHandleRecovery() {
|
||||||
switch (recoveryState) {
|
switch (recoveryState) {
|
||||||
case RECOVERY_STARTED:
|
case RECOVERY_STARTED:
|
||||||
// The recovery was already start in #handleChildrenChangedHealth and we just need
|
|
||||||
// to wait for an off time period.
|
|
||||||
// TODO: make time period configurable
|
|
||||||
recoveryState = RECOVERY_WAIT;
|
recoveryState = RECOVERY_WAIT;
|
||||||
recoveryOffTimer.resetTimer();
|
recoveryOffTimer.resetTimer();
|
||||||
return true;
|
return true;
|
||||||
@ -266,11 +266,3 @@ void AssemblyBase::overwriteDeviceHealth(object_id_t objectId, HasHealthIF::Heal
|
|||||||
modeHelper.setForced(true);
|
modeHelper.setForced(true);
|
||||||
sendHealthCommand(childrenMap[objectId].commandQueue, EXTERNAL_CONTROL);
|
sendHealthCommand(childrenMap[objectId].commandQueue, EXTERNAL_CONTROL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssemblyBase::triggerModeHelperEvents(Mode_t mode, Submode_t submode) {
|
|
||||||
if (modeHelper.isForced()) {
|
|
||||||
triggerEvent(FORCING_MODE, mode, submode);
|
|
||||||
} else {
|
|
||||||
triggerEvent(CHANGING_MODE, mode, submode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -12,8 +12,7 @@
|
|||||||
* Documentation: Dissertation Baetz p.156, 157.
|
* Documentation: Dissertation Baetz p.156, 157.
|
||||||
*
|
*
|
||||||
* This class reduces the complexity of controller components which would
|
* This class reduces the complexity of controller components which would
|
||||||
* otherwise be needed for the handling of redundant devices. However, it can also be used to
|
* otherwise be needed for the handling of redundant devices.
|
||||||
* manage the mode keeping and recovery of non-redundant devices
|
|
||||||
*
|
*
|
||||||
* The template class monitors mode and health state of its children
|
* The template class monitors mode and health state of its children
|
||||||
* and checks availability of devices on every detected change.
|
* and checks availability of devices on every detected change.
|
||||||
@ -27,9 +26,11 @@
|
|||||||
*
|
*
|
||||||
* Important:
|
* Important:
|
||||||
*
|
*
|
||||||
* The implementation must call #registerChild for all commanded children during initialization.
|
* The implementation must call registerChild(object_id_t child)
|
||||||
|
* for all commanded children during initialization.
|
||||||
* The implementation must call the initialization function of the base class.
|
* The implementation must call the initialization function of the base class.
|
||||||
* (This will call the function in SubsystemBase)
|
* (This will call the function in SubsystemBase)
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
class AssemblyBase : public SubsystemBase {
|
class AssemblyBase : public SubsystemBase {
|
||||||
public:
|
public:
|
||||||
@ -46,14 +47,13 @@ class AssemblyBase : public SubsystemBase {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* Command children to reach [mode,submode] combination. Can be done by setting
|
* Command children to reach [mode,submode] combination
|
||||||
* #commandsOutstanding correctly, or using #executeTable. In case of an FDIR recovery,
|
* Can be done by setting #commandsOutstanding correctly,
|
||||||
* the user needs to ensure that the target devices are healthy. If a device is not healthy,
|
* or using executeTable()
|
||||||
* a recovery might be on-going and the device needs to be commanded to off first.
|
|
||||||
* @param mode
|
* @param mode
|
||||||
* @param submode
|
* @param submode
|
||||||
* @return
|
* @return
|
||||||
* - @c RETURN_OK if OK
|
* - @c RETURN_OK if ok
|
||||||
* - @c NEED_SECOND_STEP if children need to be commanded again
|
* - @c NEED_SECOND_STEP if children need to be commanded again
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t commandChildren(Mode_t mode, Submode_t submode) = 0;
|
virtual ReturnValue_t commandChildren(Mode_t mode, Submode_t submode) = 0;
|
||||||
@ -120,19 +120,8 @@ class AssemblyBase : public SubsystemBase {
|
|||||||
|
|
||||||
virtual ReturnValue_t handleHealthReply(CommandMessage *message);
|
virtual ReturnValue_t handleHealthReply(CommandMessage *message);
|
||||||
|
|
||||||
/**
|
virtual void performChildOperation();
|
||||||
* @brief Default periodic handler
|
|
||||||
* @details
|
|
||||||
* This is the default periodic handler which will be called by the SubsystemBase
|
|
||||||
* performOperation. It performs the child transitions or reacts to changed health/mode states
|
|
||||||
* of children objects
|
|
||||||
*/
|
|
||||||
virtual void performChildOperation() override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function handles changed mode or health states of children
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
bool handleChildrenChanged();
|
bool handleChildrenChanged();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -145,37 +134,12 @@ class AssemblyBase : public SubsystemBase {
|
|||||||
|
|
||||||
bool handleChildrenChangedHealth();
|
bool handleChildrenChangedHealth();
|
||||||
|
|
||||||
/**
|
|
||||||
* Core transition handler. The default implementation will only do something if
|
|
||||||
* #commandsOutstanding is smaller or equal to zero, which means that all mode commands
|
|
||||||
* from the #doPerformTransition call were executed successfully.
|
|
||||||
*
|
|
||||||
* Unless a second step was requested, the function will then use #checkChildrenState to
|
|
||||||
* determine whether the target mode was reached.
|
|
||||||
*
|
|
||||||
* There is some special handling for certain (internal) modes:
|
|
||||||
* - A second step is necessary. #commandChildren will be performed again
|
|
||||||
* - The device health was overwritten. #commandChildren will be called
|
|
||||||
* - A recovery is ongoing. #checkAndHandleRecovery will be called.
|
|
||||||
*/
|
|
||||||
virtual void handleChildrenTransition();
|
virtual void handleChildrenTransition();
|
||||||
|
|
||||||
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, uint32_t *msToReachTheMode);
|
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, uint32_t *msToReachTheMode);
|
||||||
|
|
||||||
/**
|
|
||||||
* Calls #doStartTransition and triggers an informative event as well that the mode will
|
|
||||||
* change
|
|
||||||
* @param mode
|
|
||||||
* @param submode
|
|
||||||
*/
|
|
||||||
virtual void startTransition(Mode_t mode, Submode_t submode);
|
virtual void startTransition(Mode_t mode, Submode_t submode);
|
||||||
|
|
||||||
/**
|
|
||||||
* This function starts the transition by setting the internal #targetSubmode and #targetMode
|
|
||||||
* variables and then calling the #commandChildren function.
|
|
||||||
* @param mode
|
|
||||||
* @param submode
|
|
||||||
*/
|
|
||||||
virtual void doStartTransition(Mode_t mode, Submode_t submode);
|
virtual void doStartTransition(Mode_t mode, Submode_t submode);
|
||||||
|
|
||||||
virtual bool isInTransition();
|
virtual bool isInTransition();
|
||||||
@ -196,7 +160,7 @@ class AssemblyBase : public SubsystemBase {
|
|||||||
* Manages recovery of a device
|
* Manages recovery of a device
|
||||||
* @return true if recovery is still ongoing, false else.
|
* @return true if recovery is still ongoing, false else.
|
||||||
*/
|
*/
|
||||||
virtual bool checkAndHandleRecovery();
|
bool checkAndHandleRecovery();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method to overwrite health state of one of the children.
|
* Helper method to overwrite health state of one of the children.
|
||||||
@ -204,8 +168,6 @@ class AssemblyBase : public SubsystemBase {
|
|||||||
* @param objectId Must be a registered child.
|
* @param objectId Must be a registered child.
|
||||||
*/
|
*/
|
||||||
void overwriteDeviceHealth(object_id_t objectId, HasHealthIF::HealthState oldHealth);
|
void overwriteDeviceHealth(object_id_t objectId, HasHealthIF::HealthState oldHealth);
|
||||||
|
|
||||||
void triggerModeHelperEvents(Mode_t mode, Submode_t submode);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_DEVICEHANDLERS_ASSEMBLYBASE_H_ */
|
#endif /* FSFW_DEVICEHANDLERS_ASSEMBLYBASE_H_ */
|
||||||
|
@ -39,9 +39,8 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, object_id_t device
|
|||||||
childTransitionDelay(5000),
|
childTransitionDelay(5000),
|
||||||
transitionSourceMode(_MODE_POWER_DOWN),
|
transitionSourceMode(_MODE_POWER_DOWN),
|
||||||
transitionSourceSubMode(SUBMODE_NONE) {
|
transitionSourceSubMode(SUBMODE_NONE) {
|
||||||
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
|
|
||||||
commandQueue = QueueFactory::instance()->createMessageQueue(
|
commandQueue = QueueFactory::instance()->createMessageQueue(
|
||||||
cmdQueueSize, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
cmdQueueSize, MessageQueueMessage::MAX_MESSAGE_SIZE);
|
||||||
insertInCommandMap(RAW_COMMAND_ID);
|
insertInCommandMap(RAW_COMMAND_ID);
|
||||||
cookieInfo.state = COOKIE_UNUSED;
|
cookieInfo.state = COOKIE_UNUSED;
|
||||||
cookieInfo.pendingCommand = deviceCommandMap.end();
|
cookieInfo.pendingCommand = deviceCommandMap.end();
|
||||||
@ -49,6 +48,9 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, object_id_t device
|
|||||||
printWarningOrError(sif::OutputTypes::OUT_ERROR, "DeviceHandlerBase",
|
printWarningOrError(sif::OutputTypes::OUT_ERROR, "DeviceHandlerBase",
|
||||||
HasReturnvaluesIF::RETURN_FAILED, "Invalid cookie");
|
HasReturnvaluesIF::RETURN_FAILED, "Invalid cookie");
|
||||||
}
|
}
|
||||||
|
if (this->fdirInstance == nullptr) {
|
||||||
|
this->fdirInstance = new DeviceHandlerFailureIsolation(setObjectId, defaultFdirParentId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceHandlerBase::setHkDestination(object_id_t hkDestination) {
|
void DeviceHandlerBase::setHkDestination(object_id_t hkDestination) {
|
||||||
@ -124,17 +126,6 @@ ReturnValue_t DeviceHandlerBase::initialize() {
|
|||||||
if (result != RETURN_OK) {
|
if (result != RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
if (this->fdirInstance == nullptr) {
|
|
||||||
this->fdirInstance = new DeviceHandlerFailureIsolation(this->getObjectId(), defaultFdirParentId);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(this->parent != objects::NO_OBJECT) {
|
|
||||||
HasModesIF* modeIF = ObjectManager::instance()->get<HasModesIF>(this->parent);
|
|
||||||
HasHealthIF* healthIF = ObjectManager::instance()->get<HasHealthIF>(this->parent);
|
|
||||||
if(modeIF != nullptr and healthIF != nullptr) {
|
|
||||||
setParentQueue(modeIF->getCommandQueue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
communicationInterface =
|
communicationInterface =
|
||||||
ObjectManager::instance()->get<DeviceCommunicationIF>(deviceCommunicationId);
|
ObjectManager::instance()->get<DeviceCommunicationIF>(deviceCommunicationId);
|
||||||
@ -419,7 +410,7 @@ ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap(
|
|||||||
DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles, LocalPoolDataSetBase* replyDataSet,
|
DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles, LocalPoolDataSetBase* replyDataSet,
|
||||||
size_t replyLen, bool periodic, bool hasDifferentReplyId, DeviceCommandId_t replyId) {
|
size_t replyLen, bool periodic, bool hasDifferentReplyId, DeviceCommandId_t replyId) {
|
||||||
// No need to check, as we may try to insert multiple times.
|
// No need to check, as we may try to insert multiple times.
|
||||||
insertInCommandMap(deviceCommand);
|
insertInCommandMap(deviceCommand, hasDifferentReplyId, replyId);
|
||||||
if (hasDifferentReplyId) {
|
if (hasDifferentReplyId) {
|
||||||
return insertInReplyMap(replyId, maxDelayCycles, replyDataSet, replyLen, periodic);
|
return insertInReplyMap(replyId, maxDelayCycles, replyDataSet, replyLen, periodic);
|
||||||
} else {
|
} else {
|
||||||
@ -446,11 +437,15 @@ ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t DeviceHandlerBase::insertInCommandMap(DeviceCommandId_t deviceCommand) {
|
ReturnValue_t DeviceHandlerBase::insertInCommandMap(DeviceCommandId_t deviceCommand,
|
||||||
|
bool useAlternativeReply,
|
||||||
|
DeviceCommandId_t alternativeReplyId) {
|
||||||
DeviceCommandInfo info;
|
DeviceCommandInfo info;
|
||||||
info.expectedReplies = 0;
|
info.expectedReplies = 0;
|
||||||
info.isExecuting = false;
|
info.isExecuting = false;
|
||||||
info.sendReplyTo = NO_COMMANDER;
|
info.sendReplyTo = NO_COMMANDER;
|
||||||
|
info.useAlternativeReplyId = alternativeReplyId;
|
||||||
|
info.alternativeReplyId = alternativeReplyId;
|
||||||
auto resultPair = deviceCommandMap.emplace(deviceCommand, info);
|
auto resultPair = deviceCommandMap.emplace(deviceCommand, info);
|
||||||
if (resultPair.second) {
|
if (resultPair.second) {
|
||||||
return RETURN_OK;
|
return RETURN_OK;
|
||||||
@ -460,12 +455,20 @@ ReturnValue_t DeviceHandlerBase::insertInCommandMap(DeviceCommandId_t deviceComm
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t DeviceHandlerBase::getNextReplyLength(DeviceCommandId_t commandId) {
|
size_t DeviceHandlerBase::getNextReplyLength(DeviceCommandId_t commandId) {
|
||||||
DeviceReplyIter iter = deviceReplyMap.find(commandId);
|
DeviceCommandId_t replyId = NO_COMMAND_ID;
|
||||||
if (iter != deviceReplyMap.end()) {
|
DeviceCommandMap::iterator command = cookieInfo.pendingCommand;
|
||||||
return iter->second.replyLen;
|
if (command->second.useAlternativeReplyId) {
|
||||||
|
replyId = command->second.alternativeReplyId;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
replyId = commandId;
|
||||||
}
|
}
|
||||||
|
DeviceReplyIter iter = deviceReplyMap.find(replyId);
|
||||||
|
if (iter != deviceReplyMap.end()) {
|
||||||
|
if (iter->second.delayCycles != 0) {
|
||||||
|
return iter->second.replyLen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t DeviceHandlerBase::updateReplyMapEntry(DeviceCommandId_t deviceReply,
|
ReturnValue_t DeviceHandlerBase::updateReplyMapEntry(DeviceCommandId_t deviceReply,
|
||||||
@ -660,7 +663,9 @@ void DeviceHandlerBase::doGetWrite() {
|
|||||||
|
|
||||||
// We need to distinguish here, because a raw command never expects a reply.
|
// We need to distinguish here, because a raw command never expects a reply.
|
||||||
//(Could be done in eRIRM, but then child implementations need to be careful.
|
//(Could be done in eRIRM, but then child implementations need to be careful.
|
||||||
result = enableReplyInReplyMap(cookieInfo.pendingCommand);
|
DeviceCommandMap::iterator command = cookieInfo.pendingCommand;
|
||||||
|
result = enableReplyInReplyMap(command, 1, command->second.useAlternativeReplyId,
|
||||||
|
command->second.alternativeReplyId);
|
||||||
} else {
|
} else {
|
||||||
// always generate a failure event, so that FDIR knows what's up
|
// always generate a failure event, so that FDIR knows what's up
|
||||||
triggerEvent(DEVICE_SENDING_COMMAND_FAILED, result, cookieInfo.pendingCommand->first);
|
triggerEvent(DEVICE_SENDING_COMMAND_FAILED, result, cookieInfo.pendingCommand->first);
|
||||||
@ -1394,8 +1399,6 @@ void DeviceHandlerBase::setTaskIF(PeriodicTaskIF* task) { executingTask = task;
|
|||||||
void DeviceHandlerBase::debugInterface(uint8_t positionTracker, object_id_t objectId,
|
void DeviceHandlerBase::debugInterface(uint8_t positionTracker, object_id_t objectId,
|
||||||
uint32_t parameter) {}
|
uint32_t parameter) {}
|
||||||
|
|
||||||
Submode_t DeviceHandlerBase::getInitialSubmode() { return SUBMODE_NONE; }
|
|
||||||
|
|
||||||
void DeviceHandlerBase::performOperationHook() {}
|
void DeviceHandlerBase::performOperationHook() {}
|
||||||
|
|
||||||
ReturnValue_t DeviceHandlerBase::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
ReturnValue_t DeviceHandlerBase::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
||||||
@ -1418,7 +1421,7 @@ ReturnValue_t DeviceHandlerBase::initializeAfterTaskCreation() {
|
|||||||
this->poolManager.initializeAfterTaskCreation();
|
this->poolManager.initializeAfterTaskCreation();
|
||||||
|
|
||||||
if (setStartupImmediately) {
|
if (setStartupImmediately) {
|
||||||
startTransition(MODE_ON, getInitialSubmode());
|
startTransition(MODE_ON, SUBMODE_NONE);
|
||||||
}
|
}
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
@ -1502,9 +1505,3 @@ MessageQueueId_t DeviceHandlerBase::getCommanderQueueId(DeviceCommandId_t replyI
|
|||||||
}
|
}
|
||||||
return commandIter->second.sendReplyTo;
|
return commandIter->second.sendReplyTo;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceHandlerBase::setCustomFdir(FailureIsolationBase* fdir) { this->fdirInstance = fdir; }
|
|
||||||
|
|
||||||
void DeviceHandlerBase::setParent(object_id_t parent) { this->parent = parent; }
|
|
||||||
|
|
||||||
void DeviceHandlerBase::setPowerSwitcher(PowerSwitchIF* switcher) { this->powerSwitcher = switcher; }
|
|
||||||
|
@ -103,9 +103,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
DeviceHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, CookieIF *comCookie,
|
DeviceHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, CookieIF *comCookie,
|
||||||
FailureIsolationBase *fdirInstance = nullptr, size_t cmdQueueSize = 20);
|
FailureIsolationBase *fdirInstance = nullptr, size_t cmdQueueSize = 20);
|
||||||
|
|
||||||
void setCustomFdir(FailureIsolationBase* fdir);
|
|
||||||
void setParent(object_id_t parent);
|
|
||||||
void setPowerSwitcher(PowerSwitchIF* switcher);
|
|
||||||
void setHkDestination(object_id_t hkDestination);
|
void setHkDestination(object_id_t hkDestination);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -166,7 +163,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
* @param counter Specifies which Action to perform
|
* @param counter Specifies which Action to perform
|
||||||
* @return RETURN_OK for successful execution
|
* @return RETURN_OK for successful execution
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t performOperation(uint8_t counter);
|
virtual ReturnValue_t performOperation(uint8_t counter) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initializes the device handler
|
* @brief Initializes the device handler
|
||||||
@ -176,7 +173,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
* Calls fillCommandAndReplyMap().
|
* Calls fillCommandAndReplyMap().
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t initialize();
|
virtual ReturnValue_t initialize() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Intialization steps performed after all tasks have been created.
|
* @brief Intialization steps performed after all tasks have been created.
|
||||||
@ -481,7 +478,9 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
* @return - @c RETURN_OK when the command was successfully inserted,
|
* @return - @c RETURN_OK when the command was successfully inserted,
|
||||||
* - @c RETURN_FAILED else.
|
* - @c RETURN_FAILED else.
|
||||||
*/
|
*/
|
||||||
ReturnValue_t insertInCommandMap(DeviceCommandId_t deviceCommand);
|
ReturnValue_t insertInCommandMap(DeviceCommandId_t deviceCommand,
|
||||||
|
bool useAlternativeReply = false,
|
||||||
|
DeviceCommandId_t alternativeReplyId = 0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enables a periodic reply for a given command. It sets to delay cycles to the specified
|
* Enables a periodic reply for a given command. It sets to delay cycles to the specified
|
||||||
@ -650,12 +649,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
virtual void debugInterface(uint8_t positionTracker = 0, object_id_t objectId = 0,
|
virtual void debugInterface(uint8_t positionTracker = 0, object_id_t objectId = 0,
|
||||||
uint32_t parameter = 0);
|
uint32_t parameter = 0);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Can be overwritten by a child to specify the initial submode when device has been set
|
|
||||||
* to startup immediately.
|
|
||||||
*/
|
|
||||||
virtual Submode_t getInitialSubmode();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_BASE;
|
static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_BASE;
|
||||||
|
|
||||||
@ -760,6 +753,8 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
//! if this is != NO_COMMANDER, DHB was commanded externally and shall
|
//! if this is != NO_COMMANDER, DHB was commanded externally and shall
|
||||||
//! report everything to commander.
|
//! report everything to commander.
|
||||||
MessageQueueId_t sendReplyTo;
|
MessageQueueId_t sendReplyTo;
|
||||||
|
bool useAlternativeReplyId;
|
||||||
|
DeviceCommandId_t alternativeReplyId;
|
||||||
};
|
};
|
||||||
using DeviceCommandMap = std::map<DeviceCommandId_t, DeviceCommandInfo>;
|
using DeviceCommandMap = std::map<DeviceCommandId_t, DeviceCommandInfo>;
|
||||||
/**
|
/**
|
||||||
@ -827,7 +822,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
/** Pointer to the used FDIR instance. If not provided by child,
|
/** Pointer to the used FDIR instance. If not provided by child,
|
||||||
* default class is instantiated. */
|
* default class is instantiated. */
|
||||||
FailureIsolationBase *fdirInstance;
|
FailureIsolationBase *fdirInstance;
|
||||||
object_id_t parent = objects::NO_OBJECT;
|
|
||||||
|
|
||||||
//! To correctly delete the default instance.
|
//! To correctly delete the default instance.
|
||||||
bool defaultFDIRUsed;
|
bool defaultFDIRUsed;
|
||||||
@ -1064,11 +1058,12 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
* @param parameter1 Optional parameter 1
|
* @param parameter1 Optional parameter 1
|
||||||
* @param parameter2 Optional parameter 2
|
* @param parameter2 Optional parameter 2
|
||||||
*/
|
*/
|
||||||
void triggerEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0);
|
void triggerEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0) override;
|
||||||
/**
|
/**
|
||||||
* Same as triggerEvent, but for forwarding if object is used as proxy.
|
* Same as triggerEvent, but for forwarding if object is used as proxy.
|
||||||
*/
|
*/
|
||||||
virtual void forwardEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0) const;
|
virtual void forwardEvent(Event event, uint32_t parameter1 = 0,
|
||||||
|
uint32_t parameter2 = 0) const override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if current mode is transitional mode.
|
* Checks if current mode is transitional mode.
|
||||||
|
@ -29,7 +29,6 @@ ReturnValue_t DeviceHandlerFailureIsolation::eventReceived(EventMessage* event)
|
|||||||
switch (event->getEvent()) {
|
switch (event->getEvent()) {
|
||||||
case HasModesIF::MODE_TRANSITION_FAILED:
|
case HasModesIF::MODE_TRANSITION_FAILED:
|
||||||
case HasModesIF::OBJECT_IN_INVALID_MODE:
|
case HasModesIF::OBJECT_IN_INVALID_MODE:
|
||||||
case DeviceHandlerIF::DEVICE_WANTS_HARD_REBOOT:
|
|
||||||
// We'll try a recovery as long as defined in MAX_REBOOT.
|
// We'll try a recovery as long as defined in MAX_REBOOT.
|
||||||
// Might cause some AssemblyBase cycles, so keep number low.
|
// Might cause some AssemblyBase cycles, so keep number low.
|
||||||
handleRecovery(event->getEvent());
|
handleRecovery(event->getEvent());
|
||||||
|
@ -109,7 +109,6 @@ class DeviceHandlerIF {
|
|||||||
static const Event INVALID_DEVICE_COMMAND = MAKE_EVENT(8, severity::LOW);
|
static const Event INVALID_DEVICE_COMMAND = MAKE_EVENT(8, severity::LOW);
|
||||||
static const Event MONITORING_LIMIT_EXCEEDED = MAKE_EVENT(9, severity::LOW);
|
static const Event MONITORING_LIMIT_EXCEEDED = MAKE_EVENT(9, severity::LOW);
|
||||||
static const Event MONITORING_AMBIGUOUS = MAKE_EVENT(10, severity::HIGH);
|
static const Event MONITORING_AMBIGUOUS = MAKE_EVENT(10, severity::HIGH);
|
||||||
static const Event DEVICE_WANTS_HARD_REBOOT = MAKE_EVENT(11, severity::HIGH);
|
|
||||||
|
|
||||||
static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_IF;
|
static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_IF;
|
||||||
|
|
||||||
|
@ -8,9 +8,7 @@ HealthDevice::HealthDevice(object_id_t setObjectId, MessageQueueId_t parentQueue
|
|||||||
parentQueue(parentQueue),
|
parentQueue(parentQueue),
|
||||||
commandQueue(),
|
commandQueue(),
|
||||||
healthHelper(this, setObjectId) {
|
healthHelper(this, setObjectId) {
|
||||||
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
|
commandQueue = QueueFactory::instance()->createMessageQueue(3);
|
||||||
commandQueue = QueueFactory::instance()->createMessageQueue(
|
|
||||||
3, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HealthDevice::~HealthDevice() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }
|
HealthDevice::~HealthDevice() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }
|
||||||
|
@ -18,9 +18,8 @@ const LocalPool::LocalPoolConfig EventManager::poolConfig = {
|
|||||||
EventManager::EventManager(object_id_t setObjectId)
|
EventManager::EventManager(object_id_t setObjectId)
|
||||||
: SystemObject(setObjectId), factoryBackend(0, poolConfig, false, true) {
|
: SystemObject(setObjectId), factoryBackend(0, poolConfig, false, true) {
|
||||||
mutex = MutexFactory::instance()->createMutex();
|
mutex = MutexFactory::instance()->createMutex();
|
||||||
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
|
eventReportQueue = QueueFactory::instance()->createMessageQueue(MAX_EVENTS_PER_CYCLE,
|
||||||
eventReportQueue = QueueFactory::instance()->createMessageQueue(
|
EventMessage::EVENT_MESSAGE_SIZE);
|
||||||
MAX_EVENTS_PER_CYCLE, EventMessage::EVENT_MESSAGE_SIZE, &mqArgs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EventManager::~EventManager() {
|
EventManager::~EventManager() {
|
||||||
@ -47,20 +46,9 @@ ReturnValue_t EventManager::performOperation(uint8_t opCode) {
|
|||||||
|
|
||||||
void EventManager::notifyListeners(EventMessage* message) {
|
void EventManager::notifyListeners(EventMessage* message) {
|
||||||
lockMutex();
|
lockMutex();
|
||||||
for (auto& listener : listenerList) {
|
for (auto iter = listenerList.begin(); iter != listenerList.end(); ++iter) {
|
||||||
if (listener.second.match(message)) {
|
if (iter->second.match(message)) {
|
||||||
ReturnValue_t result =
|
MessageQueueSenderIF::sendMessage(iter->first, message, message->getSender());
|
||||||
MessageQueueSenderIF::sendMessage(listener.first, message, message->getSender());
|
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::error << std::hex << "EventManager::notifyListeners: MSG to 0x" << std::setfill('0')
|
|
||||||
<< std::setw(8) << listener.first << " failed with result 0x" << std::setw(4)
|
|
||||||
<< result << std::setfill(' ') << std::endl;
|
|
||||||
#else
|
|
||||||
sif::printError("Sending message to listener 0x%08x failed with result %04x\n",
|
|
||||||
listener.first, result);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unlockMutex();
|
unlockMutex();
|
||||||
@ -201,19 +189,4 @@ void EventManager::printUtility(sif::OutputTypes printType, EventMessage* messag
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventManager::printListeners() {
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::info << "Event manager listener MQ IDs:" << std::setfill('0') << std::hex << std::endl;
|
|
||||||
for (auto& listener : listenerList) {
|
|
||||||
sif::info << "0x" << std::setw(8) << listener.first << std::endl;
|
|
||||||
}
|
|
||||||
sif::info << std::dec << std::setfill(' ');
|
|
||||||
#else
|
|
||||||
sif::printInfo("Event manager listener MQ IDs:\n");
|
|
||||||
for (auto& listener : listenerList) {
|
|
||||||
sif::printInfo("0x%08x\n", listener.first);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* FSFW_OBJ_EVENT_TRANSLATION == 1 */
|
#endif /* FSFW_OBJ_EVENT_TRANSLATION == 1 */
|
||||||
|
@ -42,7 +42,6 @@ class EventManager : public EventManagerIF, public ExecutableObjectIF, public Sy
|
|||||||
object_id_t reporterFrom = 0, object_id_t reporterTo = 0,
|
object_id_t reporterFrom = 0, object_id_t reporterTo = 0,
|
||||||
bool reporterInverted = false);
|
bool reporterInverted = false);
|
||||||
ReturnValue_t performOperation(uint8_t opCode);
|
ReturnValue_t performOperation(uint8_t opCode);
|
||||||
void printListeners();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
MessageQueueIF* eventReportQueue = nullptr;
|
MessageQueueIF* eventReportQueue = nullptr;
|
||||||
|
@ -9,9 +9,8 @@
|
|||||||
FailureIsolationBase::FailureIsolationBase(object_id_t owner, object_id_t parent,
|
FailureIsolationBase::FailureIsolationBase(object_id_t owner, object_id_t parent,
|
||||||
uint8_t messageDepth, uint8_t parameterDomainBase)
|
uint8_t messageDepth, uint8_t parameterDomainBase)
|
||||||
: ownerId(owner), faultTreeParent(parent), parameterDomainBase(parameterDomainBase) {
|
: ownerId(owner), faultTreeParent(parent), parameterDomainBase(parameterDomainBase) {
|
||||||
auto mqArgs = MqArgs(owner, static_cast<void*>(this));
|
eventQueue =
|
||||||
eventQueue = QueueFactory::instance()->createMessageQueue(
|
QueueFactory::instance()->createMessageQueue(messageDepth, EventMessage::EVENT_MESSAGE_SIZE);
|
||||||
messageDepth, EventMessage::EVENT_MESSAGE_SIZE, &mqArgs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FailureIsolationBase::~FailureIsolationBase() {
|
FailureIsolationBase::~FailureIsolationBase() {
|
||||||
@ -52,12 +51,11 @@ ReturnValue_t FailureIsolationBase::initialize() {
|
|||||||
ObjectManager::instance()->get<ConfirmsFailuresIF>(faultTreeParent);
|
ObjectManager::instance()->get<ConfirmsFailuresIF>(faultTreeParent);
|
||||||
if (parentIF == nullptr) {
|
if (parentIF == nullptr) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "FailureIsolationBase::intialize: Parent object "
|
sif::error << "FailureIsolationBase::intialize: Parent object"
|
||||||
<< "invalid" << std::endl;
|
<< "invalid." << std::endl;
|
||||||
sif::error << "Make sure it implements ConfirmsFailuresIF" << std::endl;
|
#endif
|
||||||
#else
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::printError("FailureIsolationBase::intialize: Parent object invalid\n");
|
sif::error << "Make sure it implements ConfirmsFailuresIF." << std::endl;
|
||||||
sif::printError("Make sure it implements ConfirmsFailuresIF\n");
|
|
||||||
#endif
|
#endif
|
||||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||||
return RETURN_FAILED;
|
return RETURN_FAILED;
|
||||||
|
@ -14,12 +14,13 @@ class FailureIsolationBase : public HasReturnvaluesIF,
|
|||||||
public HasParametersIF {
|
public HasParametersIF {
|
||||||
public:
|
public:
|
||||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::FDIR_1;
|
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::FDIR_1;
|
||||||
//! FDIR has an internal state, which changed from par2 (oldState) to par1 (newState).
|
static const Event FDIR_CHANGED_STATE =
|
||||||
static const Event FDIR_CHANGED_STATE = MAKE_EVENT(1, severity::INFO);
|
MAKE_EVENT(1, severity::INFO); //!< FDIR has an internal state, which changed from par2
|
||||||
//! FDIR tries to restart device. Par1: event that caused recovery.
|
//!< (oldState) to par1 (newState).
|
||||||
static const Event FDIR_STARTS_RECOVERY = MAKE_EVENT(2, severity::MEDIUM);
|
static const Event FDIR_STARTS_RECOVERY = MAKE_EVENT(
|
||||||
//! FDIR turns off device. Par1: event that caused recovery.
|
2, severity::MEDIUM); //!< FDIR tries to restart device. Par1: event that caused recovery.
|
||||||
static const Event FDIR_TURNS_OFF_DEVICE = MAKE_EVENT(3, severity::MEDIUM);
|
static const Event FDIR_TURNS_OFF_DEVICE = MAKE_EVENT(
|
||||||
|
3, severity::MEDIUM); //!< FDIR turns off device. Par1: event that caused recovery.
|
||||||
|
|
||||||
FailureIsolationBase(object_id_t owner, object_id_t parent = objects::NO_OBJECT,
|
FailureIsolationBase(object_id_t owner, object_id_t parent = objects::NO_OBJECT,
|
||||||
uint8_t messageDepth = 10, uint8_t parameterDomainBase = 0xF0);
|
uint8_t messageDepth = 10, uint8_t parameterDomainBase = 0xF0);
|
||||||
|
@ -25,7 +25,7 @@ class MatchTree : public SerializeableMatcherIF<T>, public BinaryTree<Serializea
|
|||||||
: BinaryTree<SerializeableMatcherIF<T>>(root.element), maxDepth(maxDepth) {}
|
: BinaryTree<SerializeableMatcherIF<T>>(root.element), maxDepth(maxDepth) {}
|
||||||
MatchTree() : BinaryTree<SerializeableMatcherIF<T>>(), maxDepth(-1) {}
|
MatchTree() : BinaryTree<SerializeableMatcherIF<T>>(), maxDepth(-1) {}
|
||||||
virtual ~MatchTree() {}
|
virtual ~MatchTree() {}
|
||||||
virtual bool match(T number) { return matchesTree(number); }
|
virtual bool match(T number) override { return matchesTree(number); }
|
||||||
bool matchesTree(T number) {
|
bool matchesTree(T number) {
|
||||||
iterator iter = this->begin();
|
iterator iter = this->begin();
|
||||||
if (iter == this->end()) {
|
if (iter == this->end()) {
|
||||||
@ -179,6 +179,9 @@ class MatchTree : public SerializeableMatcherIF<T>, public BinaryTree<Serializea
|
|||||||
virtual ReturnValue_t cleanUpElement(iterator position) { return HasReturnvaluesIF::RETURN_OK; }
|
virtual ReturnValue_t cleanUpElement(iterator position) { return HasReturnvaluesIF::RETURN_OK; }
|
||||||
|
|
||||||
bool matchSubtree(iterator iter, T number) {
|
bool matchSubtree(iterator iter, T number) {
|
||||||
|
if (iter == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
bool isMatch = iter->match(number);
|
bool isMatch = iter->match(number);
|
||||||
if (isMatch) {
|
if (isMatch) {
|
||||||
if (iter.left() == this->end()) {
|
if (iter.left() == this->end()) {
|
||||||
|
@ -15,7 +15,7 @@ class RangeMatcher : public SerializeableMatcherIF<T> {
|
|||||||
RangeMatcher(T lowerBound, T upperBound, bool inverted = false)
|
RangeMatcher(T lowerBound, T upperBound, bool inverted = false)
|
||||||
: inverted(inverted), lowerBound(lowerBound), upperBound(upperBound) {}
|
: inverted(inverted), lowerBound(lowerBound), upperBound(upperBound) {}
|
||||||
|
|
||||||
bool match(T input) {
|
bool match(T input) override {
|
||||||
if (inverted) {
|
if (inverted) {
|
||||||
return !doMatch(input);
|
return !doMatch(input);
|
||||||
} else {
|
} else {
|
||||||
|
@ -23,15 +23,19 @@ class HasHealthIF {
|
|||||||
static const Event HEALTH_INFO = MAKE_EVENT(6, severity::INFO);
|
static const Event HEALTH_INFO = MAKE_EVENT(6, severity::INFO);
|
||||||
static const Event CHILD_CHANGED_HEALTH = MAKE_EVENT(7, severity::INFO);
|
static const Event CHILD_CHANGED_HEALTH = MAKE_EVENT(7, severity::INFO);
|
||||||
static const Event CHILD_PROBLEMS = MAKE_EVENT(8, severity::LOW);
|
static const Event CHILD_PROBLEMS = MAKE_EVENT(8, severity::LOW);
|
||||||
//! Assembly overwrites health information of children to keep satellite alive.
|
static const Event OVERWRITING_HEALTH =
|
||||||
static const Event OVERWRITING_HEALTH = MAKE_EVENT(9, severity::LOW);
|
MAKE_EVENT(9, severity::LOW); //!< Assembly overwrites health information of children to keep
|
||||||
//! Someone starts a recovery of a component (typically power-cycle). No parameters.
|
//!< satellite alive.
|
||||||
static const Event TRYING_RECOVERY = MAKE_EVENT(10, severity::MEDIUM);
|
static const Event TRYING_RECOVERY =
|
||||||
//! Recovery is ongoing. Comes twice during recovery.
|
MAKE_EVENT(10, severity::MEDIUM); //!< Someone starts a recovery of a component (typically
|
||||||
//! P1: 0 for the first, 1 for the second event. P2: 0
|
//!< power-cycle). No parameters.
|
||||||
static const Event RECOVERY_STEP = MAKE_EVENT(11, severity::MEDIUM);
|
static const Event RECOVERY_STEP =
|
||||||
//! Recovery was completed. Not necessarily successful. No parameters.
|
MAKE_EVENT(11, severity::MEDIUM); //!< Recovery is ongoing. Comes twice during recovery. P1:
|
||||||
static const Event RECOVERY_DONE = MAKE_EVENT(12, severity::MEDIUM);
|
//!< 0 for the first, 1 for the second event. P2: 0
|
||||||
|
static const Event RECOVERY_DONE = MAKE_EVENT(
|
||||||
|
12,
|
||||||
|
severity::MEDIUM); //!< Recovery was completed. Not necessarily successful. No parameters.
|
||||||
|
|
||||||
virtual ~HasHealthIF() {}
|
virtual ~HasHealthIF() {}
|
||||||
|
|
||||||
virtual MessageQueueId_t getCommandQueue() const = 0;
|
virtual MessageQueueId_t getCommandQueue() const = 0;
|
||||||
|
@ -7,13 +7,11 @@
|
|||||||
|
|
||||||
InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth)
|
InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth)
|
||||||
: SystemObject(setObjectId),
|
: SystemObject(setObjectId),
|
||||||
|
commandQueue(QueueFactory::instance()->createMessageQueue(messageQueueDepth)),
|
||||||
poolManager(this, commandQueue),
|
poolManager(this, commandQueue),
|
||||||
internalErrorSid(setObjectId, InternalErrorDataset::ERROR_SET_ID),
|
internalErrorSid(setObjectId, InternalErrorDataset::ERROR_SET_ID),
|
||||||
internalErrorDataset(this) {
|
internalErrorDataset(this) {
|
||||||
mutex = MutexFactory::instance()->createMutex();
|
mutex = MutexFactory::instance()->createMutex();
|
||||||
auto mqArgs = MqArgs(setObjectId, static_cast<void *>(this));
|
|
||||||
commandQueue = QueueFactory::instance()->createMessageQueue(
|
|
||||||
messageQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
InternalErrorReporter::~InternalErrorReporter() { MutexFactory::instance()->deleteMutex(mutex); }
|
InternalErrorReporter::~InternalErrorReporter() { MutexFactory::instance()->deleteMutex(mutex); }
|
||||||
@ -38,14 +36,15 @@ ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) {
|
|||||||
if ((newQueueHits > 0) or (newTmHits > 0) or (newStoreHits > 0)) {
|
if ((newQueueHits > 0) or (newTmHits > 0) or (newStoreHits > 0)) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::debug << "InternalErrorReporter::performOperation: Errors "
|
sif::debug << "InternalErrorReporter::performOperation: Errors "
|
||||||
<< "occured: Queue | TM | Store : " << newQueueHits << " | " << newTmHits << " | "
|
<< "occured!" << std::endl;
|
||||||
<< newStoreHits << std::endl;
|
sif::debug << "Queue errors: " << newQueueHits << std::endl;
|
||||||
|
sif::debug << "TM errors: " << newTmHits << std::endl;
|
||||||
|
sif::debug << "Store errors: " << newStoreHits << std::endl;
|
||||||
#else
|
#else
|
||||||
sif::printDebug(
|
sif::printDebug("InternalErrorReporter::performOperation: Errors occured!\n");
|
||||||
"InternalErrorReporter::performOperation: Errors occured: Queue | TM | Store: %lu | %lu "
|
sif::printDebug("Queue errors: %lu\n", static_cast<unsigned int>(newQueueHits));
|
||||||
"| %lu\n",
|
sif::printDebug("TM errors: %lu\n", static_cast<unsigned int>(newTmHits));
|
||||||
static_cast<unsigned int>(newQueueHits), static_cast<unsigned int>(newTmHits),
|
sif::printDebug("Store errors: %lu\n", static_cast<unsigned int>(newStoreHits));
|
||||||
static_cast<unsigned int>(newStoreHits));
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
target_sources(${LIB_FSFW_NAME}
|
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||||
PRIVATE
|
CommandMessage.cpp
|
||||||
CommandMessage.cpp
|
CommandMessageCleaner.cpp
|
||||||
CommandMessageCleaner.cpp
|
MessageQueueMessage.cpp
|
||||||
MessageQueueMessage.cpp
|
MessageQueueBase.cpp
|
||||||
)
|
)
|
54
src/fsfw/ipc/MessageQueueBase.cpp
Normal file
54
src/fsfw/ipc/MessageQueueBase.cpp
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#include "MessageQueueBase.h"
|
||||||
|
|
||||||
|
MessageQueueBase::MessageQueueBase(MessageQueueId_t id, MessageQueueId_t defaultDest, MqArgs* args)
|
||||||
|
: id(id) {
|
||||||
|
this->defaultDest = defaultDest;
|
||||||
|
if (args != nullptr) {
|
||||||
|
this->args = *args;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageQueueBase::~MessageQueueBase() {}
|
||||||
|
|
||||||
|
ReturnValue_t MessageQueueBase::sendToDefault(MessageQueueMessageIF* message) {
|
||||||
|
return sendToDefaultFrom(message, this->getId(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t MessageQueueBase::reply(MessageQueueMessageIF* message) {
|
||||||
|
if (this->last != MessageQueueIF::NO_QUEUE) {
|
||||||
|
return sendMessageFrom(this->last, message, this->getId());
|
||||||
|
} else {
|
||||||
|
return NO_REPLY_PARTNER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t MessageQueueBase::receiveMessage(MessageQueueMessageIF* message,
|
||||||
|
MessageQueueId_t* receivedFrom) {
|
||||||
|
ReturnValue_t status = this->receiveMessage(message);
|
||||||
|
*receivedFrom = this->last;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageQueueId_t MessageQueueBase::getLastPartner() const { return last; }
|
||||||
|
|
||||||
|
MessageQueueId_t MessageQueueBase::getId() const { return id; }
|
||||||
|
|
||||||
|
MqArgs& MessageQueueBase::getMqArgs() { return args; }
|
||||||
|
|
||||||
|
void MessageQueueBase::setDefaultDestination(MessageQueueId_t defaultDestination) {
|
||||||
|
this->defaultDest = defaultDestination;
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageQueueId_t MessageQueueBase::getDefaultDestination() const { return defaultDest; }
|
||||||
|
|
||||||
|
bool MessageQueueBase::isDefaultDestinationSet() const { return (defaultDest != NO_QUEUE); }
|
||||||
|
|
||||||
|
ReturnValue_t MessageQueueBase::sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
||||||
|
bool ignoreFault) {
|
||||||
|
return sendMessageFrom(sendTo, message, this->getId(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t MessageQueueBase::sendToDefaultFrom(MessageQueueMessageIF* message,
|
||||||
|
MessageQueueId_t sentFrom, bool ignoreFault) {
|
||||||
|
return sendMessageFrom(defaultDest, message, sentFrom, ignoreFault);
|
||||||
|
}
|
40
src/fsfw/ipc/MessageQueueBase.h
Normal file
40
src/fsfw/ipc/MessageQueueBase.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#ifndef FSFW_SRC_FSFW_IPC_MESSAGEQUEUEBASE_H_
|
||||||
|
#define FSFW_SRC_FSFW_IPC_MESSAGEQUEUEBASE_H_
|
||||||
|
|
||||||
|
#include <fsfw/ipc/MessageQueueIF.h>
|
||||||
|
#include <fsfw/ipc/definitions.h>
|
||||||
|
|
||||||
|
class MessageQueueBase : public MessageQueueIF {
|
||||||
|
public:
|
||||||
|
MessageQueueBase(MessageQueueId_t id, MessageQueueId_t defaultDest, MqArgs* mqArgs);
|
||||||
|
virtual ~MessageQueueBase();
|
||||||
|
|
||||||
|
// Default implementations for MessageQueueIF where possible
|
||||||
|
virtual MessageQueueId_t getLastPartner() const override;
|
||||||
|
virtual MessageQueueId_t getId() const override;
|
||||||
|
virtual MqArgs& getMqArgs() override;
|
||||||
|
virtual void setDefaultDestination(MessageQueueId_t defaultDestination) override;
|
||||||
|
virtual MessageQueueId_t getDefaultDestination() const override;
|
||||||
|
virtual bool isDefaultDestinationSet() const override;
|
||||||
|
virtual ReturnValue_t sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
||||||
|
bool ignoreFault) override;
|
||||||
|
virtual ReturnValue_t sendToDefault(MessageQueueMessageIF* message) override;
|
||||||
|
virtual ReturnValue_t reply(MessageQueueMessageIF* message) override;
|
||||||
|
virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message,
|
||||||
|
MessageQueueId_t* receivedFrom) override;
|
||||||
|
virtual ReturnValue_t sendToDefaultFrom(MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
|
||||||
|
bool ignoreFault = false) override;
|
||||||
|
|
||||||
|
// OSAL specific, forward the abstract function
|
||||||
|
virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message) = 0;
|
||||||
|
virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
||||||
|
MessageQueueId_t sentFrom, bool ignoreFault = false) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
MessageQueueId_t id = MessageQueueIF::NO_QUEUE;
|
||||||
|
MessageQueueId_t last = MessageQueueIF::NO_QUEUE;
|
||||||
|
MessageQueueId_t defaultDest = MessageQueueIF::NO_QUEUE;
|
||||||
|
MqArgs args = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* FSFW_SRC_FSFW_IPC_MESSAGEQUEUEBASE_H_ */
|
@ -1,6 +1,8 @@
|
|||||||
#ifndef FSFW_IPC_MESSAGEQUEUEIF_H_
|
#ifndef FSFW_IPC_MESSAGEQUEUEIF_H_
|
||||||
#define FSFW_IPC_MESSAGEQUEUEIF_H_
|
#define FSFW_IPC_MESSAGEQUEUEIF_H_
|
||||||
|
|
||||||
|
#include <fsfw/ipc/definitions.h>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||||
@ -44,8 +46,8 @@ class MessageQueueIF {
|
|||||||
virtual ReturnValue_t reply(MessageQueueMessageIF* message) = 0;
|
virtual ReturnValue_t reply(MessageQueueMessageIF* message) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function reads available messages from the message queue
|
* @brief This function reads available messages from the message queue and returns the
|
||||||
* and returns the sender.
|
* sender.
|
||||||
* @details
|
* @details
|
||||||
* It works identically to the other receiveMessage call, but in addition
|
* It works identically to the other receiveMessage call, but in addition
|
||||||
* returns the sender's queue id.
|
* returns the sender's queue id.
|
||||||
@ -78,19 +80,16 @@ class MessageQueueIF {
|
|||||||
*/
|
*/
|
||||||
virtual ReturnValue_t flush(uint32_t* count) = 0;
|
virtual ReturnValue_t flush(uint32_t* count) = 0;
|
||||||
/**
|
/**
|
||||||
* @brief This method returns the message queue
|
* @brief This method returns the message queue ID of the last communication partner.
|
||||||
* id of the last communication partner.
|
|
||||||
*/
|
*/
|
||||||
virtual MessageQueueId_t getLastPartner() const = 0;
|
virtual MessageQueueId_t getLastPartner() const = 0;
|
||||||
/**
|
/**
|
||||||
* @brief This method returns the message queue
|
* @brief This method returns the message queue ID of this class's message queue.
|
||||||
* id of this class's message queue.
|
|
||||||
*/
|
*/
|
||||||
virtual MessageQueueId_t getId() const = 0;
|
virtual MessageQueueId_t getId() const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief With the sendMessage call, a queue message
|
* @brief With the sendMessage call, a queue message is sent to a receiving queue.
|
||||||
* is sent to a receiving queue.
|
|
||||||
* @details
|
* @details
|
||||||
* This method takes the message provided, adds the sentFrom information
|
* This method takes the message provided, adds the sentFrom information
|
||||||
* and passes it on to the destination provided with an operating system
|
* and passes it on to the destination provided with an operating system
|
||||||
@ -129,8 +128,7 @@ class MessageQueueIF {
|
|||||||
bool ignoreFault = false) = 0;
|
bool ignoreFault = false) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The sendToDefaultFrom method sends a queue message
|
* @brief The sendToDefaultFrom method sends a queue message to the default destination.
|
||||||
* to the default destination.
|
|
||||||
* @details
|
* @details
|
||||||
* In all other aspects, it works identical to the sendMessage method.
|
* In all other aspects, it works identical to the sendMessage method.
|
||||||
* @param message
|
* @param message
|
||||||
@ -164,6 +162,8 @@ class MessageQueueIF {
|
|||||||
virtual MessageQueueId_t getDefaultDestination() const = 0;
|
virtual MessageQueueId_t getDefaultDestination() const = 0;
|
||||||
|
|
||||||
virtual bool isDefaultDestinationSet() const = 0;
|
virtual bool isDefaultDestinationSet() const = 0;
|
||||||
|
|
||||||
|
virtual MqArgs& getMqArgs() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_IPC_MESSAGEQUEUEIF_H_ */
|
#endif /* FSFW_IPC_MESSAGEQUEUEIF_H_ */
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
#ifndef FSFW_SRC_FSFW_IPC_DEFINITIONS_H_
|
#ifndef FSFW_SRC_FSFW_IPC_DEFINITIONS_H_
|
||||||
#define FSFW_SRC_FSFW_IPC_DEFINITIONS_H_
|
#define FSFW_SRC_FSFW_IPC_DEFINITIONS_H_
|
||||||
|
|
||||||
#include <fsfw/objectmanager/SystemObjectIF.h>
|
#include <fsfw/objectmanager/SystemObjectIF.h>
|
||||||
|
#include <fsfw/objectmanager/frameworkObjects.h>
|
||||||
|
|
||||||
struct MqArgs {
|
struct MqArgs {
|
||||||
MqArgs(){};
|
MqArgs(){};
|
||||||
MqArgs(object_id_t objectId, void* args = nullptr) : objectId(objectId), args(args) {}
|
MqArgs(object_id_t objectId, void* args = nullptr) : objectId(objectId), args(args) {}
|
||||||
object_id_t objectId = 0;
|
object_id_t objectId = objects::NO_OBJECT;
|
||||||
void* args = nullptr;
|
void* args = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -19,33 +19,32 @@ class HasModesIF {
|
|||||||
static const ReturnValue_t INVALID_SUBMODE = MAKE_RETURN_CODE(0x04);
|
static const ReturnValue_t INVALID_SUBMODE = MAKE_RETURN_CODE(0x04);
|
||||||
|
|
||||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::SYSTEM_MANAGER;
|
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::SYSTEM_MANAGER;
|
||||||
//! An object announces changing the mode. p1: target mode. p2: target submode
|
static const Event CHANGING_MODE =
|
||||||
static const Event CHANGING_MODE = MAKE_EVENT(0, severity::INFO);
|
MAKE_EVENT(0, severity::INFO); //!< An object announces changing the mode. p1: target mode.
|
||||||
//! An Object announces its mode; parameter1 is mode, parameter2 is submode
|
//!< p2: target submode
|
||||||
static const Event MODE_INFO = MAKE_EVENT(1, severity::INFO);
|
static const Event MODE_INFO = MAKE_EVENT(
|
||||||
|
1,
|
||||||
|
severity::INFO); //!< An Object announces its mode; parameter1 is mode, parameter2 is submode
|
||||||
static const Event FALLBACK_FAILED = MAKE_EVENT(2, severity::HIGH);
|
static const Event FALLBACK_FAILED = MAKE_EVENT(2, severity::HIGH);
|
||||||
static const Event MODE_TRANSITION_FAILED = MAKE_EVENT(3, severity::LOW);
|
static const Event MODE_TRANSITION_FAILED = MAKE_EVENT(3, severity::LOW);
|
||||||
static const Event CANT_KEEP_MODE = MAKE_EVENT(4, severity::HIGH);
|
static const Event CANT_KEEP_MODE = MAKE_EVENT(4, severity::HIGH);
|
||||||
//! Indicates a bug or configuration failure: Object is in a mode it should never be in.
|
static const Event OBJECT_IN_INVALID_MODE =
|
||||||
static const Event OBJECT_IN_INVALID_MODE = MAKE_EVENT(5, severity::LOW);
|
MAKE_EVENT(5, severity::LOW); //!< Indicates a bug or configuration failure: Object is in a
|
||||||
//! The mode is changed, but for some reason, the change is forced, i.e. EXTERNAL_CONTROL ignored.
|
//!< mode it should never be in.
|
||||||
//! p1: target mode. p2: target submode
|
static const Event FORCING_MODE = MAKE_EVENT(
|
||||||
static const Event FORCING_MODE = MAKE_EVENT(6, severity::MEDIUM);
|
6, severity::MEDIUM); //!< The mode is changed, but for some reason, the change is forced,
|
||||||
//! A mode command was rejected by the called object. Par1: called object id, Par2: return code.
|
//!< i.e. EXTERNAL_CONTROL ignored. p1: target mode. p2: target submode
|
||||||
static const Event MODE_CMD_REJECTED = MAKE_EVENT(7, severity::LOW);
|
static const Event MODE_CMD_REJECTED =
|
||||||
|
MAKE_EVENT(7, severity::LOW); //!< A mode command was rejected by the called object. Par1:
|
||||||
|
//!< called object id, Par2: return code.
|
||||||
|
|
||||||
//! The device is powered and ready to perform operations. In this mode, no commands are
|
static const Mode_t MODE_ON =
|
||||||
//! sent by the device handler itself, but direct commands van be commanded and will be
|
1; //!< The device is powered and ready to perform operations. In this mode, no commands are
|
||||||
//! interpreted
|
//!< sent by the device handler itself, but direct commands van be commanded and will be
|
||||||
static constexpr Mode_t MODE_ON = 1;
|
//!< interpreted
|
||||||
//! The device is powered off. The only command accepted in this mode is a mode change to on.
|
static const Mode_t MODE_OFF = 0; //!< The device is powered off. The only command accepted in
|
||||||
static constexpr Mode_t MODE_OFF = 0;
|
//!< this mode is a mode change to on.
|
||||||
|
static const Submode_t SUBMODE_NONE = 0; //!< To avoid checks against magic number "0".
|
||||||
static constexpr Mode_t MODE_INVALID = -1;
|
|
||||||
static constexpr Mode_t MODE_UNDEFINED = -2;
|
|
||||||
|
|
||||||
//! To avoid checks against magic number "0".
|
|
||||||
static const Submode_t SUBMODE_NONE = 0;
|
|
||||||
|
|
||||||
virtual ~HasModesIF() {}
|
virtual ~HasModesIF() {}
|
||||||
virtual MessageQueueId_t getCommandQueue() const = 0;
|
virtual MessageQueueId_t getCommandQueue() const = 0;
|
||||||
|
@ -34,7 +34,7 @@ class MonitoringReportContent : public SerialLinkedListAdapter<SerializeIF> {
|
|||||||
SerializeElement<T> limitValue;
|
SerializeElement<T> limitValue;
|
||||||
SerializeElement<ReturnValue_t> oldState;
|
SerializeElement<ReturnValue_t> oldState;
|
||||||
SerializeElement<ReturnValue_t> newState;
|
SerializeElement<ReturnValue_t> newState;
|
||||||
uint8_t rawTimestamp[TimeStamperIF::MISSION_TIMESTAMP_SIZE];
|
uint8_t rawTimestamp[TimeStamperIF::MISSION_TIMESTAMP_SIZE] = {};
|
||||||
SerializeElement<SerialBufferAdapter<uint8_t>> timestampSerializer;
|
SerializeElement<SerialBufferAdapter<uint8_t>> timestampSerializer;
|
||||||
TimeStamperIF* timeStamper;
|
TimeStamperIF* timeStamper;
|
||||||
MonitoringReportContent()
|
MonitoringReportContent()
|
||||||
@ -46,7 +46,6 @@ class MonitoringReportContent : public SerialLinkedListAdapter<SerializeIF> {
|
|||||||
limitValue(0),
|
limitValue(0),
|
||||||
oldState(0),
|
oldState(0),
|
||||||
newState(0),
|
newState(0),
|
||||||
rawTimestamp({0}),
|
|
||||||
timestampSerializer(rawTimestamp, sizeof(rawTimestamp)),
|
timestampSerializer(rawTimestamp, sizeof(rawTimestamp)),
|
||||||
timeStamper(NULL) {
|
timeStamper(NULL) {
|
||||||
setAllNext();
|
setAllNext();
|
||||||
|
@ -95,16 +95,13 @@ void ObjectManager::initialize() {
|
|||||||
for (auto const& it : objectList) {
|
for (auto const& it : objectList) {
|
||||||
result = it.second->initialize();
|
result = it.second->initialize();
|
||||||
if (result != RETURN_OK) {
|
if (result != RETURN_OK) {
|
||||||
#if FSFW_VERBOSE_LEVEL >= 1
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
object_id_t var = it.first;
|
||||||
sif::error << "ObjectManager::initialize: Object 0x" << std::hex << std::setw(8)
|
sif::error << "ObjectManager::initialize: Object 0x" << std::hex << std::setw(8)
|
||||||
<< std::setfill('0') << it.first << " failed to initialize with code 0x" << result
|
<< std::setfill('0') << var
|
||||||
<< std::dec << std::setfill(' ') << std::endl;
|
<< " failed to "
|
||||||
#else
|
"initialize with code 0x"
|
||||||
sif::printError(
|
<< result << std::dec << std::setfill(' ') << std::endl;
|
||||||
"ObjectManager::initialize: Object 0x%08x failed to initialize with code 0x%04x\n", var,
|
|
||||||
it.first);
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
errorCount++;
|
errorCount++;
|
||||||
}
|
}
|
||||||
|
@ -48,9 +48,10 @@ class SystemObject : public SystemObjectIF {
|
|||||||
virtual ~SystemObject();
|
virtual ~SystemObject();
|
||||||
object_id_t getObjectId() const override;
|
object_id_t getObjectId() const override;
|
||||||
virtual ReturnValue_t initialize() override;
|
virtual ReturnValue_t initialize() override;
|
||||||
virtual ReturnValue_t checkObjectConnections();
|
virtual ReturnValue_t checkObjectConnections() override;
|
||||||
|
|
||||||
virtual void forwardEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0) const;
|
virtual void forwardEvent(Event event, uint32_t parameter1 = 0,
|
||||||
|
uint32_t parameter2 = 0) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_OBJECTMANAGER_SYSTEMOBJECT_H_ */
|
#endif /* FSFW_OBJECTMANAGER_SYSTEMOBJECT_H_ */
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
#include <ws2tcpip.h>
|
#include <ws2tcpip.h>
|
||||||
#elif defined(PLATFORM_UNIX)
|
#elif defined(PLATFORM_UNIX)
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const std::string TcpTmTcServer::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT;
|
const std::string TcpTmTcServer::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT;
|
||||||
@ -29,7 +31,7 @@ TcpTmTcServer::TcpTmTcServer(object_id_t objectId, object_id_t tmtcTcpBridge,
|
|||||||
: SystemObject(objectId),
|
: SystemObject(objectId),
|
||||||
tmtcBridgeId(tmtcTcpBridge),
|
tmtcBridgeId(tmtcTcpBridge),
|
||||||
receptionMode(receptionMode),
|
receptionMode(receptionMode),
|
||||||
tcpConfig(customTcpServerPort),
|
tcpConfig(std::move(customTcpServerPort)),
|
||||||
receptionBuffer(receptionBufferSize),
|
receptionBuffer(receptionBufferSize),
|
||||||
ringBuffer(ringBufferSize, true) {}
|
ringBuffer(ringBufferSize, true) {}
|
||||||
|
|
||||||
@ -103,7 +105,7 @@ ReturnValue_t TcpTmTcServer::initialize() {
|
|||||||
|
|
||||||
TcpTmTcServer::~TcpTmTcServer() { closeSocket(listenerTcpSocket); }
|
TcpTmTcServer::~TcpTmTcServer() { closeSocket(listenerTcpSocket); }
|
||||||
|
|
||||||
ReturnValue_t TcpTmTcServer::performOperation(uint8_t opCode) {
|
[[noreturn]] ReturnValue_t TcpTmTcServer::performOperation(uint8_t opCode) {
|
||||||
using namespace tcpip;
|
using namespace tcpip;
|
||||||
// If a connection is accepted, the corresponding socket will be assigned to the new socket
|
// If a connection is accepted, the corresponding socket will be assigned to the new socket
|
||||||
socket_t connSocket = 0;
|
socket_t connSocket = 0;
|
||||||
@ -138,7 +140,6 @@ ReturnValue_t TcpTmTcServer::performOperation(uint8_t opCode) {
|
|||||||
closeSocket(connSocket);
|
closeSocket(connSocket);
|
||||||
connSocket = 0;
|
connSocket = 0;
|
||||||
}
|
}
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t TcpTmTcServer::initializeAfterTaskCreation() {
|
ReturnValue_t TcpTmTcServer::initializeAfterTaskCreation() {
|
||||||
@ -159,8 +160,8 @@ void TcpTmTcServer::handleServerOperation(socket_t& connSocket) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
int retval = recv(connSocket, reinterpret_cast<char*>(receptionBuffer.data()),
|
ssize_t retval = recv(connSocket, reinterpret_cast<char*>(receptionBuffer.data()),
|
||||||
receptionBuffer.capacity(), tcpConfig.tcpFlags);
|
receptionBuffer.capacity(), tcpConfig.tcpFlags);
|
||||||
if (retval == 0) {
|
if (retval == 0) {
|
||||||
size_t availableReadData = ringBuffer.getAvailableReadData();
|
size_t availableReadData = ringBuffer.getAvailableReadData();
|
||||||
if (availableReadData > lastRingBufferSize) {
|
if (availableReadData > lastRingBufferSize) {
|
||||||
@ -252,17 +253,17 @@ ReturnValue_t TcpTmTcServer::handleTcReception(uint8_t* spacePacket, size_t pack
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string TcpTmTcServer::getTcpPort() const { return tcpConfig.tcpPort; }
|
const std::string& TcpTmTcServer::getTcpPort() const { return tcpConfig.tcpPort; }
|
||||||
|
|
||||||
void TcpTmTcServer::setSpacePacketParsingOptions(std::vector<uint16_t> validPacketIds) {
|
void TcpTmTcServer::setSpacePacketParsingOptions(std::vector<uint16_t> validPacketIds_) {
|
||||||
this->validPacketIds = validPacketIds;
|
this->validPacketIds = std::move(validPacketIds_);
|
||||||
}
|
}
|
||||||
|
|
||||||
TcpTmTcServer::TcpConfig& TcpTmTcServer::getTcpConfigStruct() { return tcpConfig; }
|
TcpTmTcServer::TcpConfig& TcpTmTcServer::getTcpConfigStruct() { return tcpConfig; }
|
||||||
|
|
||||||
ReturnValue_t TcpTmTcServer::handleTmSending(socket_t connSocket, bool& tmSent) {
|
ReturnValue_t TcpTmTcServer::handleTmSending(socket_t connSocket, bool& tmSent) {
|
||||||
// Access to the FIFO is mutex protected because it is filled by the bridge
|
// Access to the FIFO is mutex protected because it is filled by the bridge
|
||||||
MutexGuard(tmtcBridge->mutex, tmtcBridge->timeoutType, tmtcBridge->mutexTimeoutMs);
|
MutexGuard mg(tmtcBridge->mutex, tmtcBridge->timeoutType, tmtcBridge->mutexTimeoutMs);
|
||||||
store_address_t storeId;
|
store_address_t storeId;
|
||||||
while ((not tmtcBridge->tmFifo->empty()) and
|
while ((not tmtcBridge->tmFifo->empty()) and
|
||||||
(tmtcBridge->packetSentCounter < tmtcBridge->sentPacketsPerCycle)) {
|
(tmtcBridge->packetSentCounter < tmtcBridge->sentPacketsPerCycle)) {
|
||||||
@ -283,8 +284,8 @@ ReturnValue_t TcpTmTcServer::handleTmSending(socket_t connSocket, bool& tmSent)
|
|||||||
#endif
|
#endif
|
||||||
arrayprinter::print(storeAccessor.data(), storeAccessor.size());
|
arrayprinter::print(storeAccessor.data(), storeAccessor.size());
|
||||||
}
|
}
|
||||||
int retval = send(connSocket, reinterpret_cast<const char*>(storeAccessor.data()),
|
ssize_t retval = send(connSocket, reinterpret_cast<const char*>(storeAccessor.data()),
|
||||||
storeAccessor.size(), tcpConfig.tcpTmFlags);
|
storeAccessor.size(), tcpConfig.tcpTmFlags);
|
||||||
if (retval == static_cast<int>(storeAccessor.size())) {
|
if (retval == static_cast<int>(storeAccessor.size())) {
|
||||||
// Packet sent, clear FIFO entry
|
// Packet sent, clear FIFO entry
|
||||||
tmtcBridge->tmFifo->pop();
|
tmtcBridge->tmFifo->pop();
|
||||||
@ -339,6 +340,9 @@ ReturnValue_t TcpTmTcServer::handleTcRingBufferData(size_t availableReadData) {
|
|||||||
size_t foundSize = 0;
|
size_t foundSize = 0;
|
||||||
size_t readLen = 0;
|
size_t readLen = 0;
|
||||||
while (readLen < readAmount) {
|
while (readLen < readAmount) {
|
||||||
|
if (spacePacketParser == nullptr) {
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
result =
|
result =
|
||||||
spacePacketParser->parseSpacePackets(bufPtrPtr, readAmount, startIdx, foundSize, readLen);
|
spacePacketParser->parseSpacePackets(bufPtrPtr, readAmount, startIdx, foundSize, readLen);
|
||||||
switch (result) {
|
switch (result) {
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class TcpTmTcBridge;
|
class TcpTmTcBridge;
|
||||||
@ -44,7 +45,7 @@ class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableOb
|
|||||||
|
|
||||||
struct TcpConfig {
|
struct TcpConfig {
|
||||||
public:
|
public:
|
||||||
TcpConfig(std::string tcpPort) : tcpPort(tcpPort) {}
|
explicit TcpConfig(std::string tcpPort) : tcpPort(std::move(tcpPort)) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Passed to the recv call
|
* Passed to the recv call
|
||||||
@ -84,7 +85,7 @@ class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableOb
|
|||||||
size_t ringBufferSize = RING_BUFFER_SIZE,
|
size_t ringBufferSize = RING_BUFFER_SIZE,
|
||||||
std::string customTcpServerPort = DEFAULT_SERVER_PORT,
|
std::string customTcpServerPort = DEFAULT_SERVER_PORT,
|
||||||
ReceptionModes receptionMode = ReceptionModes::SPACE_PACKETS);
|
ReceptionModes receptionMode = ReceptionModes::SPACE_PACKETS);
|
||||||
virtual ~TcpTmTcServer();
|
~TcpTmTcServer() override;
|
||||||
|
|
||||||
void enableWiretapping(bool enable);
|
void enableWiretapping(bool enable);
|
||||||
|
|
||||||
@ -97,10 +98,10 @@ class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableOb
|
|||||||
void setSpacePacketParsingOptions(std::vector<uint16_t> validPacketIds);
|
void setSpacePacketParsingOptions(std::vector<uint16_t> validPacketIds);
|
||||||
|
|
||||||
ReturnValue_t initialize() override;
|
ReturnValue_t initialize() override;
|
||||||
ReturnValue_t performOperation(uint8_t opCode) override;
|
[[noreturn]] ReturnValue_t performOperation(uint8_t opCode) override;
|
||||||
ReturnValue_t initializeAfterTaskCreation() override;
|
ReturnValue_t initializeAfterTaskCreation() override;
|
||||||
|
|
||||||
std::string getTcpPort() const;
|
[[nodiscard]] const std::string& getTcpPort() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
StorageManagerIF* tcStore = nullptr;
|
StorageManagerIF* tcStore = nullptr;
|
||||||
@ -115,7 +116,7 @@ class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableOb
|
|||||||
|
|
||||||
ReceptionModes receptionMode;
|
ReceptionModes receptionMode;
|
||||||
TcpConfig tcpConfig;
|
TcpConfig tcpConfig;
|
||||||
struct sockaddr tcpAddress;
|
struct sockaddr tcpAddress = {};
|
||||||
socket_t listenerTcpSocket = 0;
|
socket_t listenerTcpSocket = 0;
|
||||||
|
|
||||||
MessageQueueId_t targetTcDestination = MessageQueueIF::NO_QUEUE;
|
MessageQueueId_t targetTcDestination = MessageQueueIF::NO_QUEUE;
|
||||||
|
@ -16,11 +16,13 @@
|
|||||||
//! Debugging preprocessor define.
|
//! Debugging preprocessor define.
|
||||||
#define FSFW_UDP_RECV_WIRETAPPING_ENABLED 0
|
#define FSFW_UDP_RECV_WIRETAPPING_ENABLED 0
|
||||||
|
|
||||||
|
const timeval UdpTcPollingTask::DEFAULT_TIMEOUT = {0, 500000};
|
||||||
|
|
||||||
UdpTcPollingTask::UdpTcPollingTask(object_id_t objectId, object_id_t tmtcUdpBridge,
|
UdpTcPollingTask::UdpTcPollingTask(object_id_t objectId, object_id_t tmtcUdpBridge,
|
||||||
size_t maxRecvSize, double timeoutSeconds)
|
size_t maxRecvSize, double timeoutSeconds)
|
||||||
: SystemObject(objectId), tmtcBridgeId(tmtcUdpBridge) {
|
: SystemObject(objectId), tmtcBridgeId(tmtcUdpBridge) {
|
||||||
if (frameSize > 0) {
|
if (maxRecvSize > 0) {
|
||||||
this->frameSize = frameSize;
|
this->frameSize = maxRecvSize;
|
||||||
} else {
|
} else {
|
||||||
this->frameSize = DEFAULT_MAX_RECV_SIZE;
|
this->frameSize = DEFAULT_MAX_RECV_SIZE;
|
||||||
}
|
}
|
||||||
@ -31,22 +33,20 @@ UdpTcPollingTask::UdpTcPollingTask(object_id_t objectId, object_id_t tmtcUdpBrid
|
|||||||
receptionBuffer.resize(this->frameSize);
|
receptionBuffer.resize(this->frameSize);
|
||||||
|
|
||||||
if (timeoutSeconds == -1) {
|
if (timeoutSeconds == -1) {
|
||||||
receptionTimeout = DEFAULT_TIMEOUT;
|
receptionTimeout = UdpTcPollingTask::DEFAULT_TIMEOUT;
|
||||||
} else {
|
} else {
|
||||||
receptionTimeout = timevalOperations::toTimeval(timeoutSeconds);
|
receptionTimeout = timevalOperations::toTimeval(timeoutSeconds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UdpTcPollingTask::~UdpTcPollingTask() {}
|
[[noreturn]] ReturnValue_t UdpTcPollingTask::performOperation(uint8_t opCode) {
|
||||||
|
|
||||||
ReturnValue_t UdpTcPollingTask::performOperation(uint8_t opCode) {
|
|
||||||
/* Sender Address is cached here. */
|
/* Sender Address is cached here. */
|
||||||
struct sockaddr senderAddress;
|
struct sockaddr senderAddress {};
|
||||||
socklen_t senderAddressSize = sizeof(senderAddress);
|
socklen_t senderAddressSize = sizeof(senderAddress);
|
||||||
|
|
||||||
/* Poll for new UDP datagrams in permanent loop. */
|
/* Poll for new UDP datagrams in permanent loop. */
|
||||||
while (true) {
|
while (true) {
|
||||||
int bytesReceived =
|
ssize_t bytesReceived =
|
||||||
recvfrom(this->serverSocket, reinterpret_cast<char*>(receptionBuffer.data()), frameSize,
|
recvfrom(this->serverSocket, reinterpret_cast<char*>(receptionBuffer.data()), frameSize,
|
||||||
receptionFlags, &senderAddress, &senderAddressSize);
|
receptionFlags, &senderAddress, &senderAddressSize);
|
||||||
if (bytesReceived == SOCKET_ERROR) {
|
if (bytesReceived == SOCKET_ERROR) {
|
||||||
@ -70,7 +70,6 @@ ReturnValue_t UdpTcPollingTask::performOperation(uint8_t opCode) {
|
|||||||
}
|
}
|
||||||
tmtcBridge->checkAndSetClientAddress(senderAddress);
|
tmtcBridge->checkAndSetClientAddress(senderAddress);
|
||||||
}
|
}
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t UdpTcPollingTask::handleSuccessfullTcRead(size_t bytesRead) {
|
ReturnValue_t UdpTcPollingTask::handleSuccessfullTcRead(size_t bytesRead) {
|
||||||
@ -155,7 +154,7 @@ void UdpTcPollingTask::setTimeout(double timeoutSeconds) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#elif defined(PLATFORM_UNIX)
|
#elif defined(PLATFORM_UNIX)
|
||||||
timeval tval;
|
timeval tval{};
|
||||||
tval = timevalOperations::toTimeval(timeoutSeconds);
|
tval = timevalOperations::toTimeval(timeoutSeconds);
|
||||||
int result = setsockopt(serverSocket, SOL_SOCKET, SO_RCVTIMEO, &tval, sizeof(receptionTimeout));
|
int result = setsockopt(serverSocket, SOL_SOCKET, SO_RCVTIMEO, &tval, sizeof(receptionTimeout));
|
||||||
if (result == -1) {
|
if (result == -1) {
|
||||||
|
@ -21,11 +21,11 @@ class UdpTcPollingTask : public TcpIpBase, public SystemObject, public Executabl
|
|||||||
public:
|
public:
|
||||||
static constexpr size_t DEFAULT_MAX_RECV_SIZE = 1500;
|
static constexpr size_t DEFAULT_MAX_RECV_SIZE = 1500;
|
||||||
//! 0.5 default milliseconds timeout for now.
|
//! 0.5 default milliseconds timeout for now.
|
||||||
static constexpr timeval DEFAULT_TIMEOUT = {0, 500};
|
static const timeval DEFAULT_TIMEOUT;
|
||||||
|
|
||||||
UdpTcPollingTask(object_id_t objectId, object_id_t tmtcUdpBridge, size_t maxRecvSize = 0,
|
UdpTcPollingTask(object_id_t objectId, object_id_t tmtcUdpBridge, size_t maxRecvSize = 0,
|
||||||
double timeoutSeconds = -1);
|
double timeoutSeconds = -1);
|
||||||
virtual ~UdpTcPollingTask();
|
~UdpTcPollingTask() override = default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Turn on optional timeout for UDP polling. In the default mode,
|
* Turn on optional timeout for UDP polling. In the default mode,
|
||||||
@ -34,9 +34,9 @@ class UdpTcPollingTask : public TcpIpBase, public SystemObject, public Executabl
|
|||||||
*/
|
*/
|
||||||
void setTimeout(double timeoutSeconds);
|
void setTimeout(double timeoutSeconds);
|
||||||
|
|
||||||
virtual ReturnValue_t performOperation(uint8_t opCode) override;
|
[[noreturn]] ReturnValue_t performOperation(uint8_t opCode) override;
|
||||||
virtual ReturnValue_t initialize() override;
|
ReturnValue_t initialize() override;
|
||||||
virtual ReturnValue_t initializeAfterTaskCreation() override;
|
ReturnValue_t initializeAfterTaskCreation() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
StorageManagerIF* tcStore = nullptr;
|
StorageManagerIF* tcStore = nullptr;
|
||||||
@ -51,7 +51,7 @@ class UdpTcPollingTask : public TcpIpBase, public SystemObject, public Executabl
|
|||||||
std::vector<uint8_t> receptionBuffer;
|
std::vector<uint8_t> receptionBuffer;
|
||||||
|
|
||||||
size_t frameSize = 0;
|
size_t frameSize = 0;
|
||||||
timeval receptionTimeout;
|
timeval receptionTimeout{};
|
||||||
|
|
||||||
ReturnValue_t handleSuccessfullTcRead(size_t bytesRead);
|
ReturnValue_t handleSuccessfullTcRead(size_t bytesRead);
|
||||||
};
|
};
|
||||||
|
@ -20,13 +20,13 @@
|
|||||||
const std::string UdpTmTcBridge::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT;
|
const std::string UdpTmTcBridge::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT;
|
||||||
|
|
||||||
UdpTmTcBridge::UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination,
|
UdpTmTcBridge::UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination,
|
||||||
std::string udpServerPort, object_id_t tmStoreId,
|
const std::string &udpServerPort_, object_id_t tmStoreId,
|
||||||
object_id_t tcStoreId)
|
object_id_t tcStoreId)
|
||||||
: TmTcBridge(objectId, tcDestination, tmStoreId, tcStoreId) {
|
: TmTcBridge(objectId, tcDestination, tmStoreId, tcStoreId) {
|
||||||
if (udpServerPort == "") {
|
if (udpServerPort_.empty()) {
|
||||||
this->udpServerPort = DEFAULT_SERVER_PORT;
|
udpServerPort = DEFAULT_SERVER_PORT;
|
||||||
} else {
|
} else {
|
||||||
this->udpServerPort = udpServerPort;
|
udpServerPort = udpServerPort_;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex = MutexFactory::instance()->createMutex();
|
mutex = MutexFactory::instance()->createMutex();
|
||||||
@ -117,8 +117,8 @@ ReturnValue_t UdpTmTcBridge::sendTm(const uint8_t *data, size_t dataLen) {
|
|||||||
tcpip::printAddress(&clientAddress);
|
tcpip::printAddress(&clientAddress);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int bytesSent = sendto(serverSocket, reinterpret_cast<const char *>(data), dataLen, flags,
|
ssize_t bytesSent = sendto(serverSocket, reinterpret_cast<const char *>(data), dataLen, flags,
|
||||||
&clientAddress, clientAddressLen);
|
&clientAddress, clientAddressLen);
|
||||||
if (bytesSent == SOCKET_ERROR) {
|
if (bytesSent == SOCKET_ERROR) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "TmTcUdpBridge::sendTm: Send operation failed." << std::endl;
|
sif::warning << "TmTcUdpBridge::sendTm: Send operation failed." << std::endl;
|
||||||
@ -150,7 +150,7 @@ void UdpTmTcBridge::checkAndSetClientAddress(sockaddr &newAddress) {
|
|||||||
clientAddressLen = sizeof(clientAddress);
|
clientAddressLen = sizeof(clientAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UdpTmTcBridge::setMutexProperties(MutexIF::TimeoutType timeoutType, dur_millis_t timeoutMs) {
|
void UdpTmTcBridge::setMutexProperties(MutexIF::TimeoutType timeoutType_, dur_millis_t timeoutMs) {
|
||||||
this->timeoutType = timeoutType;
|
timeoutType = timeoutType_;
|
||||||
this->mutexTimeoutMs = timeoutMs;
|
mutexTimeoutMs = timeoutMs;
|
||||||
}
|
}
|
||||||
|
@ -29,10 +29,10 @@ class UdpTmTcBridge : public TmTcBridge, public TcpIpBase {
|
|||||||
/* The ports chosen here should not be used by any other process. */
|
/* The ports chosen here should not be used by any other process. */
|
||||||
static const std::string DEFAULT_SERVER_PORT;
|
static const std::string DEFAULT_SERVER_PORT;
|
||||||
|
|
||||||
UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination, std::string udpServerPort = "",
|
UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination,
|
||||||
object_id_t tmStoreId = objects::TM_STORE,
|
const std::string& udpServerPort = "", object_id_t tmStoreId = objects::TM_STORE,
|
||||||
object_id_t tcStoreId = objects::TC_STORE);
|
object_id_t tcStoreId = objects::TC_STORE);
|
||||||
virtual ~UdpTmTcBridge();
|
~UdpTmTcBridge() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set properties of internal mutex.
|
* Set properties of internal mutex.
|
||||||
@ -46,12 +46,12 @@ class UdpTmTcBridge : public TmTcBridge, public TcpIpBase {
|
|||||||
std::string getUdpPort() const;
|
std::string getUdpPort() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ReturnValue_t sendTm(const uint8_t* data, size_t dataLen) override;
|
ReturnValue_t sendTm(const uint8_t* data, size_t dataLen) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string udpServerPort;
|
std::string udpServerPort;
|
||||||
|
|
||||||
struct sockaddr clientAddress;
|
struct sockaddr clientAddress = {};
|
||||||
socklen_t clientAddressLen = 0;
|
socklen_t clientAddressLen = 0;
|
||||||
|
|
||||||
//! Access to the client address is mutex protected as it is set by another task.
|
//! Access to the client address is mutex protected as it is set by another task.
|
||||||
|
@ -11,9 +11,6 @@
|
|||||||
// TODO sanitize input?
|
// TODO sanitize input?
|
||||||
// TODO much of this code can be reused for tick-only systems
|
// TODO much of this code can be reused for tick-only systems
|
||||||
|
|
||||||
uint16_t Clock::leapSeconds = 0;
|
|
||||||
MutexIF* Clock::timeMutex = nullptr;
|
|
||||||
|
|
||||||
uint32_t Clock::getTicksPerSecond(void) { return 1000; }
|
uint32_t Clock::getTicksPerSecond(void) { return 1000; }
|
||||||
|
|
||||||
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
|
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
|
||||||
|
@ -5,7 +5,8 @@
|
|||||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||||
|
|
||||||
MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize, MqArgs* args)
|
MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize, MqArgs* args)
|
||||||
: maxMessageSize(maxMessageSize) {
|
: MessageQueueBase(MessageQueueIF::NO_QUEUE, MessageQueueIF::NO_QUEUE, args),
|
||||||
|
maxMessageSize(maxMessageSize) {
|
||||||
handle = xQueueCreate(messageDepth, maxMessageSize);
|
handle = xQueueCreate(messageDepth, maxMessageSize);
|
||||||
if (handle == nullptr) {
|
if (handle == nullptr) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
@ -15,10 +16,10 @@ MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize, MqArgs* a
|
|||||||
#else
|
#else
|
||||||
sif::printError("MessageQueue::MessageQueue: Creation failed\n");
|
sif::printError("MessageQueue::MessageQueue: Creation failed\n");
|
||||||
sif::printError("Specified Message Depth: %d\n", messageDepth);
|
sif::printError("Specified Message Depth: %d\n", messageDepth);
|
||||||
sif::printError("Specified MAximum Message Size: %d\n", maxMessageSize);
|
sif::printError("Specified Maximum Message Size: %d\n", maxMessageSize);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
QueueMapManager::instance()->addMessageQueue(handle, &queueId);
|
QueueMapManager::instance()->addMessageQueue(handle, &id);
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageQueue::~MessageQueue() {
|
MessageQueue::~MessageQueue() {
|
||||||
@ -29,28 +30,6 @@ MessageQueue::~MessageQueue() {
|
|||||||
|
|
||||||
void MessageQueue::switchSystemContext(CallContext callContext) { this->callContext = callContext; }
|
void MessageQueue::switchSystemContext(CallContext callContext) { this->callContext = callContext; }
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
|
||||||
bool ignoreFault) {
|
|
||||||
return sendMessageFrom(sendTo, message, this->getId(), ignoreFault);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessageIF* message) {
|
|
||||||
return sendToDefaultFrom(message, this->getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessageIF* message,
|
|
||||||
MessageQueueId_t sentFrom, bool ignoreFault) {
|
|
||||||
return sendMessageFrom(defaultDestination, message, sentFrom, ignoreFault);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::reply(MessageQueueMessageIF* message) {
|
|
||||||
if (this->lastPartner != MessageQueueIF::NO_QUEUE) {
|
|
||||||
return sendMessageFrom(this->lastPartner, message, this->getId());
|
|
||||||
} else {
|
|
||||||
return NO_REPLY_PARTNER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
||||||
MessageQueueId_t sentFrom, bool ignoreFault) {
|
MessageQueueId_t sentFrom, bool ignoreFault) {
|
||||||
return sendMessageFromMessageQueue(sendTo, message, sentFrom, ignoreFault, callContext);
|
return sendMessageFromMessageQueue(sendTo, message, sentFrom, ignoreFault, callContext);
|
||||||
@ -72,27 +51,16 @@ ReturnValue_t MessageQueue::handleSendResult(BaseType_t result, bool ignoreFault
|
|||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message,
|
|
||||||
MessageQueueId_t* receivedFrom) {
|
|
||||||
ReturnValue_t status = this->receiveMessage(message);
|
|
||||||
if (status == HasReturnvaluesIF::RETURN_OK) {
|
|
||||||
*receivedFrom = this->lastPartner;
|
|
||||||
}
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
|
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
|
||||||
BaseType_t result = xQueueReceive(handle, reinterpret_cast<void*>(message->getBuffer()), 0);
|
BaseType_t result = xQueueReceive(handle, reinterpret_cast<void*>(message->getBuffer()), 0);
|
||||||
if (result == pdPASS) {
|
if (result == pdPASS) {
|
||||||
this->lastPartner = message->getSender();
|
this->last = message->getSender();
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
} else {
|
} else {
|
||||||
return MessageQueueIF::EMPTY;
|
return MessageQueueIF::EMPTY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageQueueId_t MessageQueue::getLastPartner() const { return lastPartner; }
|
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::flush(uint32_t* count) {
|
ReturnValue_t MessageQueue::flush(uint32_t* count) {
|
||||||
// TODO FreeRTOS does not support flushing partially
|
// TODO FreeRTOS does not support flushing partially
|
||||||
// Is always successful
|
// Is always successful
|
||||||
@ -100,17 +68,6 @@ ReturnValue_t MessageQueue::flush(uint32_t* count) {
|
|||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageQueueId_t MessageQueue::getId() const { return queueId; }
|
|
||||||
|
|
||||||
void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) {
|
|
||||||
defaultDestinationSet = true;
|
|
||||||
this->defaultDestination = defaultDestination;
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageQueueId_t MessageQueue::getDefaultDestination() const { return defaultDestination; }
|
|
||||||
|
|
||||||
bool MessageQueue::isDefaultDestinationSet() const { return defaultDestinationSet; }
|
|
||||||
|
|
||||||
// static core function to send messages.
|
// static core function to send messages.
|
||||||
ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
|
ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
|
||||||
MessageQueueMessageIF* message,
|
MessageQueueMessageIF* message,
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#ifndef FSFW_OSAL_FREERTOS_MESSAGEQUEUE_H_
|
#ifndef FSFW_OSAL_FREERTOS_MESSAGEQUEUE_H_
|
||||||
#define FSFW_OSAL_FREERTOS_MESSAGEQUEUE_H_
|
#define FSFW_OSAL_FREERTOS_MESSAGEQUEUE_H_
|
||||||
|
|
||||||
|
#include <fsfw/ipc/MessageQueueBase.h>
|
||||||
|
|
||||||
#include "FreeRTOS.h"
|
#include "FreeRTOS.h"
|
||||||
#include "TaskManagement.h"
|
#include "TaskManagement.h"
|
||||||
#include "fsfw/internalerror/InternalErrorReporterIF.h"
|
#include "fsfw/internalerror/InternalErrorReporterIF.h"
|
||||||
@ -33,7 +35,7 @@
|
|||||||
* @ingroup osal
|
* @ingroup osal
|
||||||
* @ingroup message_queue
|
* @ingroup message_queue
|
||||||
*/
|
*/
|
||||||
class MessageQueue : public MessageQueueIF {
|
class MessageQueue : public MessageQueueBase {
|
||||||
friend class MessageQueueSenderIF;
|
friend class MessageQueueSenderIF;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -75,40 +77,15 @@ class MessageQueue : public MessageQueueIF {
|
|||||||
*/
|
*/
|
||||||
void switchSystemContext(CallContext callContext);
|
void switchSystemContext(CallContext callContext);
|
||||||
|
|
||||||
/** MessageQueueIF implementation */
|
QueueHandle_t getNativeQueueHandle();
|
||||||
ReturnValue_t sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
|
||||||
bool ignoreFault = false) override;
|
|
||||||
|
|
||||||
ReturnValue_t sendToDefault(MessageQueueMessageIF* message) override;
|
// Implement non-generic MessageQueueIF functions not handled by MessageQueueBase
|
||||||
|
|
||||||
ReturnValue_t reply(MessageQueueMessageIF* message) override;
|
|
||||||
virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
||||||
MessageQueueId_t sentFrom = NO_QUEUE,
|
MessageQueueId_t sentFrom = NO_QUEUE,
|
||||||
bool ignoreFault = false) override;
|
bool ignoreFault = false) override;
|
||||||
|
|
||||||
virtual ReturnValue_t sendToDefaultFrom(MessageQueueMessageIF* message,
|
|
||||||
MessageQueueId_t sentFrom = NO_QUEUE,
|
|
||||||
bool ignoreFault = false) override;
|
|
||||||
|
|
||||||
ReturnValue_t receiveMessage(MessageQueueMessageIF* message,
|
|
||||||
MessageQueueId_t* receivedFrom) override;
|
|
||||||
|
|
||||||
ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override;
|
ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override;
|
||||||
|
|
||||||
ReturnValue_t flush(uint32_t* count) override;
|
ReturnValue_t flush(uint32_t* count) override;
|
||||||
|
|
||||||
MessageQueueId_t getLastPartner() const override;
|
|
||||||
|
|
||||||
MessageQueueId_t getId() const override;
|
|
||||||
|
|
||||||
void setDefaultDestination(MessageQueueId_t defaultDestination) override;
|
|
||||||
|
|
||||||
MessageQueueId_t getDefaultDestination() const override;
|
|
||||||
|
|
||||||
bool isDefaultDestinationSet() const override;
|
|
||||||
|
|
||||||
QueueHandle_t getNativeQueueHandle();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* @brief Implementation to be called from any send Call within
|
* @brief Implementation to be called from any send Call within
|
||||||
@ -138,12 +115,8 @@ class MessageQueue : public MessageQueueIF {
|
|||||||
static ReturnValue_t handleSendResult(BaseType_t result, bool ignoreFault);
|
static ReturnValue_t handleSendResult(BaseType_t result, bool ignoreFault);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool defaultDestinationSet = false;
|
|
||||||
QueueHandle_t handle;
|
QueueHandle_t handle;
|
||||||
MessageQueueId_t queueId = MessageQueueIF::NO_QUEUE;
|
|
||||||
|
|
||||||
MessageQueueId_t defaultDestination = MessageQueueIF::NO_QUEUE;
|
|
||||||
MessageQueueId_t lastPartner = MessageQueueIF::NO_QUEUE;
|
|
||||||
const size_t maxMessageSize;
|
const size_t maxMessageSize;
|
||||||
//! Stores the current system context
|
//! Stores the current system context
|
||||||
CallContext callContext = CallContext::TASK;
|
CallContext callContext = CallContext::TASK;
|
||||||
|
@ -97,7 +97,11 @@ void PeriodicTask::taskFunctionality() {
|
|||||||
|
|
||||||
ReturnValue_t PeriodicTask::addComponent(object_id_t object) {
|
ReturnValue_t PeriodicTask::addComponent(object_id_t object) {
|
||||||
ExecutableObjectIF* newObject = ObjectManager::instance()->get<ExecutableObjectIF>(object);
|
ExecutableObjectIF* newObject = ObjectManager::instance()->get<ExecutableObjectIF>(object);
|
||||||
if (newObject == nullptr) {
|
return addComponent(newObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t PeriodicTask::addComponent(ExecutableObjectIF* object) {
|
||||||
|
if (object == nullptr) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "PeriodicTask::addComponent: Invalid object. Make sure"
|
sif::error << "PeriodicTask::addComponent: Invalid object. Make sure"
|
||||||
"it implement ExecutableObjectIF"
|
"it implement ExecutableObjectIF"
|
||||||
@ -105,8 +109,8 @@ ReturnValue_t PeriodicTask::addComponent(object_id_t object) {
|
|||||||
#endif
|
#endif
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
objectList.push_back(newObject);
|
objectList.push_back(object);
|
||||||
newObject->setTaskIF(this);
|
object->setTaskIF(this);
|
||||||
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,16 @@ class PeriodicTask : public PeriodicTaskIF, public FreeRTOSTaskIF {
|
|||||||
*/
|
*/
|
||||||
ReturnValue_t addComponent(object_id_t object) override;
|
ReturnValue_t addComponent(object_id_t object) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an object to the list of objects to be executed.
|
||||||
|
* The objects are executed in the order added.
|
||||||
|
* @param object Id of the object to add.
|
||||||
|
* @return
|
||||||
|
* -@c RETURN_OK on success
|
||||||
|
* -@c RETURN_FAILED if the object could not be added.
|
||||||
|
*/
|
||||||
|
ReturnValue_t addComponent(ExecutableObjectIF* object) override;
|
||||||
|
|
||||||
uint32_t getPeriodMs() const override;
|
uint32_t getPeriodMs() const override;
|
||||||
|
|
||||||
ReturnValue_t sleepFor(uint32_t ms) override;
|
ReturnValue_t sleepFor(uint32_t ms) override;
|
||||||
|
@ -1,24 +1,27 @@
|
|||||||
target_sources(${LIB_FSFW_NAME}
|
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||||
PRIVATE
|
Clock.cpp
|
||||||
Clock.cpp
|
FixedTimeslotTask.cpp
|
||||||
FixedTimeslotTask.cpp
|
MessageQueue.cpp
|
||||||
MessageQueue.cpp
|
Mutex.cpp
|
||||||
Mutex.cpp
|
MutexFactory.cpp
|
||||||
MutexFactory.cpp
|
PeriodicTask.cpp
|
||||||
PeriodicTask.cpp
|
QueueFactory.cpp
|
||||||
QueueFactory.cpp
|
QueueMapManager.cpp
|
||||||
QueueMapManager.cpp
|
SemaphoreFactory.cpp
|
||||||
SemaphoreFactory.cpp
|
TaskFactory.cpp
|
||||||
TaskFactory.cpp
|
taskHelpers.cpp
|
||||||
taskHelpers.cpp
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if(UNIX)
|
if(UNIX)
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
|
|
||||||
target_link_libraries(${LIB_FSFW_NAME}
|
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
|
||||||
PRIVATE
|
${CMAKE_THREAD_LIBS_INIT}
|
||||||
rt
|
)
|
||||||
${CMAKE_THREAD_LIBS_INIT}
|
if(NOT APPLE)
|
||||||
)
|
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
|
||||||
|
rt
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
endif()
|
endif()
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
|
#include "fsfw/ipc/MutexGuard.h"
|
||||||
#include "fsfw/platform.h"
|
#include "fsfw/platform.h"
|
||||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||||
|
|
||||||
@ -11,9 +12,6 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint16_t Clock::leapSeconds = 0;
|
|
||||||
MutexIF* Clock::timeMutex = NULL;
|
|
||||||
|
|
||||||
using SystemClock = std::chrono::system_clock;
|
using SystemClock = std::chrono::system_clock;
|
||||||
|
|
||||||
uint32_t Clock::getTicksPerSecond(void) {
|
uint32_t Clock::getTicksPerSecond(void) {
|
||||||
@ -127,6 +125,13 @@ ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
|
|||||||
auto seconds = std::chrono::time_point_cast<std::chrono::seconds>(now);
|
auto seconds = std::chrono::time_point_cast<std::chrono::seconds>(now);
|
||||||
auto fraction = now - seconds;
|
auto fraction = now - seconds;
|
||||||
time_t tt = SystemClock::to_time_t(now);
|
time_t tt = SystemClock::to_time_t(now);
|
||||||
|
ReturnValue_t result = checkOrCreateClockMutex();
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
MutexGuard helper(timeMutex);
|
||||||
|
// gmtime writes its output in a global buffer which is not Thread Safe
|
||||||
|
// Therefore we have to use a Mutex here
|
||||||
struct tm* timeInfo;
|
struct tm* timeInfo;
|
||||||
timeInfo = gmtime(&tt);
|
timeInfo = gmtime(&tt);
|
||||||
time->year = timeInfo->tm_year + 1900;
|
time->year = timeInfo->tm_year + 1900;
|
||||||
|
@ -9,9 +9,11 @@
|
|||||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||||
|
|
||||||
MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize, MqArgs* args)
|
MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize, MqArgs* args)
|
||||||
: messageSize(maxMessageSize), messageDepth(messageDepth) {
|
: MessageQueueBase(MessageQueueIF::NO_QUEUE, MessageQueueIF::NO_QUEUE, args),
|
||||||
|
messageSize(maxMessageSize),
|
||||||
|
messageDepth(messageDepth) {
|
||||||
queueLock = MutexFactory::instance()->createMutex();
|
queueLock = MutexFactory::instance()->createMutex();
|
||||||
auto result = QueueMapManager::instance()->addMessageQueue(this, &mqId);
|
auto result = QueueMapManager::instance()->addMessageQueue(this, &id);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "MessageQueue::MessageQueue: Could not be created" << std::endl;
|
sif::error << "MessageQueue::MessageQueue: Could not be created" << std::endl;
|
||||||
@ -23,42 +25,11 @@ MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize, MqArgs* a
|
|||||||
|
|
||||||
MessageQueue::~MessageQueue() { MutexFactory::instance()->deleteMutex(queueLock); }
|
MessageQueue::~MessageQueue() { MutexFactory::instance()->deleteMutex(queueLock); }
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
|
||||||
bool ignoreFault) {
|
|
||||||
return sendMessageFrom(sendTo, message, this->getId(), ignoreFault);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessageIF* message) {
|
|
||||||
return sendToDefaultFrom(message, this->getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessageIF* message,
|
|
||||||
MessageQueueId_t sentFrom, bool ignoreFault) {
|
|
||||||
return sendMessageFrom(defaultDestination, message, sentFrom, ignoreFault);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::reply(MessageQueueMessageIF* message) {
|
|
||||||
if (this->lastPartner != MessageQueueIF::NO_QUEUE) {
|
|
||||||
return sendMessageFrom(this->lastPartner, message, this->getId());
|
|
||||||
} else {
|
|
||||||
return MessageQueueIF::NO_REPLY_PARTNER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
||||||
MessageQueueId_t sentFrom, bool ignoreFault) {
|
MessageQueueId_t sentFrom, bool ignoreFault) {
|
||||||
return sendMessageFromMessageQueue(sendTo, message, sentFrom, ignoreFault);
|
return sendMessageFromMessageQueue(sendTo, message, sentFrom, ignoreFault);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message,
|
|
||||||
MessageQueueId_t* receivedFrom) {
|
|
||||||
ReturnValue_t status = this->receiveMessage(message);
|
|
||||||
if (status == HasReturnvaluesIF::RETURN_OK) {
|
|
||||||
*receivedFrom = this->lastPartner;
|
|
||||||
}
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
|
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
|
||||||
if (messageQueue.empty()) {
|
if (messageQueue.empty()) {
|
||||||
return MessageQueueIF::EMPTY;
|
return MessageQueueIF::EMPTY;
|
||||||
@ -68,12 +39,10 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
|
|||||||
message->getBuffer());
|
message->getBuffer());
|
||||||
messageQueue.pop();
|
messageQueue.pop();
|
||||||
// The last partner is the first uint32_t field in the message
|
// The last partner is the first uint32_t field in the message
|
||||||
this->lastPartner = message->getSender();
|
this->last = message->getSender();
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageQueueId_t MessageQueue::getLastPartner() const { return lastPartner; }
|
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::flush(uint32_t* count) {
|
ReturnValue_t MessageQueue::flush(uint32_t* count) {
|
||||||
*count = messageQueue.size();
|
*count = messageQueue.size();
|
||||||
// Clears the queue.
|
// Clears the queue.
|
||||||
@ -81,17 +50,6 @@ ReturnValue_t MessageQueue::flush(uint32_t* count) {
|
|||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageQueueId_t MessageQueue::getId() const { return mqId; }
|
|
||||||
|
|
||||||
void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) {
|
|
||||||
defaultDestinationSet = true;
|
|
||||||
this->defaultDestination = defaultDestination;
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageQueueId_t MessageQueue::getDefaultDestination() const { return defaultDestination; }
|
|
||||||
|
|
||||||
bool MessageQueue::isDefaultDestinationSet() const { return defaultDestinationSet; }
|
|
||||||
|
|
||||||
// static core function to send messages.
|
// static core function to send messages.
|
||||||
ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
|
ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
|
||||||
MessageQueueMessageIF* message,
|
MessageQueueMessageIF* message,
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
#include "fsfw/internalerror/InternalErrorReporterIF.h"
|
#include "fsfw/internalerror/InternalErrorReporterIF.h"
|
||||||
|
#include "fsfw/ipc/MessageQueueBase.h"
|
||||||
#include "fsfw/ipc/MessageQueueIF.h"
|
#include "fsfw/ipc/MessageQueueIF.h"
|
||||||
#include "fsfw/ipc/MessageQueueMessage.h"
|
#include "fsfw/ipc/MessageQueueMessage.h"
|
||||||
#include "fsfw/ipc/MutexIF.h"
|
#include "fsfw/ipc/MutexIF.h"
|
||||||
@ -34,7 +35,7 @@
|
|||||||
* @ingroup osal
|
* @ingroup osal
|
||||||
* @ingroup message_queue
|
* @ingroup message_queue
|
||||||
*/
|
*/
|
||||||
class MessageQueue : public MessageQueueIF {
|
class MessageQueue : public MessageQueueBase {
|
||||||
friend class MessageQueueSenderIF;
|
friend class MessageQueueSenderIF;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -69,121 +70,12 @@ class MessageQueue : public MessageQueueIF {
|
|||||||
*/
|
*/
|
||||||
virtual ~MessageQueue();
|
virtual ~MessageQueue();
|
||||||
|
|
||||||
/**
|
// Implement non-generic MessageQueueIF functions not handled by MessageQueueBase
|
||||||
* @brief This operation sends a message to the given destination.
|
|
||||||
* @details It directly uses the sendMessage call of the MessageQueueSender
|
|
||||||
* parent, but passes its queue id as "sentFrom" parameter.
|
|
||||||
* @param sendTo This parameter specifies the message queue id of the
|
|
||||||
* destination message queue.
|
|
||||||
* @param message A pointer to a previously created message, which is sent.
|
|
||||||
* @param ignoreFault If set to true, the internal software fault counter
|
|
||||||
* is not incremented if queue is full.
|
|
||||||
*/
|
|
||||||
ReturnValue_t sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
|
||||||
bool ignoreFault = false) override;
|
|
||||||
/**
|
|
||||||
* @brief This operation sends a message to the default destination.
|
|
||||||
* @details As in the sendMessage method, this function uses the
|
|
||||||
* sendToDefault call of the MessageQueueSender parent class and adds its
|
|
||||||
* queue id as "sentFrom" information.
|
|
||||||
* @param message A pointer to a previously created message, which is sent.
|
|
||||||
*/
|
|
||||||
ReturnValue_t sendToDefault(MessageQueueMessageIF* message) override;
|
|
||||||
/**
|
|
||||||
* @brief This operation sends a message to the last communication partner.
|
|
||||||
* @details This operation simplifies answering an incoming message by using
|
|
||||||
* the stored lastPartner information as destination. If there was no
|
|
||||||
* message received yet (i.e. lastPartner is zero), an error code is returned.
|
|
||||||
* @param message A pointer to a previously created message, which is sent.
|
|
||||||
*/
|
|
||||||
ReturnValue_t reply(MessageQueueMessageIF* message) override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief With the sendMessage call, a queue message is sent to a
|
|
||||||
* receiving queue.
|
|
||||||
* @details
|
|
||||||
* This method takes the message provided, adds the sentFrom information and
|
|
||||||
* passes it on to the destination provided with an operating system call.
|
|
||||||
* The OS's return value is returned.
|
|
||||||
* @param sendTo This parameter specifies the message queue id to send
|
|
||||||
* the message to.
|
|
||||||
* @param message This is a pointer to a previously created message,
|
|
||||||
* which is sent.
|
|
||||||
* @param sentFrom The sentFrom information can be set to inject the
|
|
||||||
* sender's queue id into the message. This variable is set to zero by
|
|
||||||
* default.
|
|
||||||
* @param ignoreFault If set to true, the internal software fault counter
|
|
||||||
* is not incremented if queue is full.
|
|
||||||
*/
|
|
||||||
virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
||||||
MessageQueueId_t sentFrom = NO_QUEUE,
|
MessageQueueId_t sentFrom = NO_QUEUE,
|
||||||
bool ignoreFault = false) override;
|
bool ignoreFault = false) override;
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The sendToDefault method sends a queue message to the default
|
|
||||||
* destination.
|
|
||||||
* @details
|
|
||||||
* In all other aspects, it works identical to the sendMessage method.
|
|
||||||
* @param message This is a pointer to a previously created message,
|
|
||||||
* which is sent.
|
|
||||||
* @param sentFrom The sentFrom information can be set to inject the
|
|
||||||
* sender's queue id into the message. This variable is set to zero by
|
|
||||||
* default.
|
|
||||||
*/
|
|
||||||
virtual ReturnValue_t sendToDefaultFrom(MessageQueueMessageIF* message,
|
|
||||||
MessageQueueId_t sentFrom = NO_QUEUE,
|
|
||||||
bool ignoreFault = false) override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This function reads available messages from the message queue
|
|
||||||
* and returns the sender.
|
|
||||||
* @details
|
|
||||||
* It works identically to the other receiveMessage call, but in addition
|
|
||||||
* returns the sender's queue id.
|
|
||||||
* @param message A pointer to a message in which the received data is stored.
|
|
||||||
* @param receivedFrom A pointer to a queue id in which the sender's id is stored.
|
|
||||||
*/
|
|
||||||
ReturnValue_t receiveMessage(MessageQueueMessageIF* message,
|
|
||||||
MessageQueueId_t* receivedFrom) override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This function reads available messages from the message queue.
|
|
||||||
* @details
|
|
||||||
* If data is available it is stored in the passed message pointer.
|
|
||||||
* The message's original content is overwritten and the sendFrom
|
|
||||||
* information is stored in the lastPartner attribute. Else, the lastPartner
|
|
||||||
* information remains untouched, the message's content is cleared and the
|
|
||||||
* function returns immediately.
|
|
||||||
* @param message A pointer to a message in which the received data is stored.
|
|
||||||
*/
|
|
||||||
ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override;
|
ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override;
|
||||||
/**
|
|
||||||
* Deletes all pending messages in the queue.
|
|
||||||
* @param count The number of flushed messages.
|
|
||||||
* @return RETURN_OK on success.
|
|
||||||
*/
|
|
||||||
ReturnValue_t flush(uint32_t* count) override;
|
ReturnValue_t flush(uint32_t* count) override;
|
||||||
/**
|
|
||||||
* @brief This method returns the message queue id of the last
|
|
||||||
* communication partner.
|
|
||||||
*/
|
|
||||||
MessageQueueId_t getLastPartner() const override;
|
|
||||||
/**
|
|
||||||
* @brief This method returns the message queue id of this class's
|
|
||||||
* message queue.
|
|
||||||
*/
|
|
||||||
MessageQueueId_t getId() const override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This method is a simple setter for the default destination.
|
|
||||||
*/
|
|
||||||
void setDefaultDestination(MessageQueueId_t defaultDestination) override;
|
|
||||||
/**
|
|
||||||
* @brief This method is a simple getter for the default destination.
|
|
||||||
*/
|
|
||||||
MessageQueueId_t getDefaultDestination() const override;
|
|
||||||
|
|
||||||
bool isDefaultDestinationSet() const override;
|
|
||||||
|
|
||||||
ReturnValue_t lockQueue(MutexIF::TimeoutType timeoutType, dur_millis_t lockTimeout);
|
ReturnValue_t lockQueue(MutexIF::TimeoutType timeoutType, dur_millis_t lockTimeout);
|
||||||
ReturnValue_t unlockQueue();
|
ReturnValue_t unlockQueue();
|
||||||
@ -213,23 +105,14 @@ class MessageQueue : public MessageQueueIF {
|
|||||||
MessageQueueId_t sentFrom = NO_QUEUE,
|
MessageQueueId_t sentFrom = NO_QUEUE,
|
||||||
bool ignoreFault = false);
|
bool ignoreFault = false);
|
||||||
|
|
||||||
// static ReturnValue_t handleSendResult(BaseType_t result, bool ignoreFault);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::queue<std::vector<uint8_t>> messageQueue;
|
std::queue<std::vector<uint8_t>> messageQueue;
|
||||||
/**
|
|
||||||
* @brief The class stores the queue id it got assigned.
|
|
||||||
* If initialization fails, the queue id is set to zero.
|
|
||||||
*/
|
|
||||||
MessageQueueId_t mqId = MessageQueueIF::NO_QUEUE;
|
|
||||||
size_t messageSize = 0;
|
size_t messageSize = 0;
|
||||||
size_t messageDepth = 0;
|
size_t messageDepth = 0;
|
||||||
|
|
||||||
MutexIF* queueLock;
|
MutexIF* queueLock;
|
||||||
|
|
||||||
bool defaultDestinationSet = false;
|
|
||||||
MessageQueueId_t defaultDestination = MessageQueueIF::NO_QUEUE;
|
MessageQueueId_t defaultDestination = MessageQueueIF::NO_QUEUE;
|
||||||
MessageQueueId_t lastPartner = MessageQueueIF::NO_QUEUE;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_ */
|
#endif /* FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_ */
|
||||||
|
@ -102,11 +102,15 @@ void PeriodicTask::taskFunctionality() {
|
|||||||
|
|
||||||
ReturnValue_t PeriodicTask::addComponent(object_id_t object) {
|
ReturnValue_t PeriodicTask::addComponent(object_id_t object) {
|
||||||
ExecutableObjectIF* newObject = ObjectManager::instance()->get<ExecutableObjectIF>(object);
|
ExecutableObjectIF* newObject = ObjectManager::instance()->get<ExecutableObjectIF>(object);
|
||||||
if (newObject == nullptr) {
|
return addComponent(newObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t PeriodicTask::addComponent(ExecutableObjectIF* object) {
|
||||||
|
if (object == nullptr) {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
newObject->setTaskIF(this);
|
object->setTaskIF(this);
|
||||||
objectList.push_back(newObject);
|
objectList.push_back(object);
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,6 +59,16 @@ class PeriodicTask : public PeriodicTaskIF {
|
|||||||
*/
|
*/
|
||||||
ReturnValue_t addComponent(object_id_t object);
|
ReturnValue_t addComponent(object_id_t object);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an object to the list of objects to be executed.
|
||||||
|
* The objects are executed in the order added.
|
||||||
|
* @param object pointer to the object to add.
|
||||||
|
* @return
|
||||||
|
* -@c RETURN_OK on success
|
||||||
|
* -@c RETURN_FAILED if the object could not be added.
|
||||||
|
*/
|
||||||
|
ReturnValue_t addComponent(ExecutableObjectIF* object);
|
||||||
|
|
||||||
uint32_t getPeriodMs() const;
|
uint32_t getPeriodMs() const;
|
||||||
|
|
||||||
ReturnValue_t sleepFor(uint32_t ms);
|
ReturnValue_t sleepFor(uint32_t ms);
|
||||||
|
@ -1,29 +1,29 @@
|
|||||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||||
Clock.cpp
|
Clock.cpp
|
||||||
BinarySemaphore.cpp
|
BinarySemaphore.cpp
|
||||||
CountingSemaphore.cpp
|
CountingSemaphore.cpp
|
||||||
FixedTimeslotTask.cpp
|
FixedTimeslotTask.cpp
|
||||||
InternalErrorCodes.cpp
|
InternalErrorCodes.cpp
|
||||||
MessageQueue.cpp
|
MessageQueue.cpp
|
||||||
Mutex.cpp
|
Mutex.cpp
|
||||||
MutexFactory.cpp
|
MutexFactory.cpp
|
||||||
PeriodicPosixTask.cpp
|
PeriodicPosixTask.cpp
|
||||||
PosixThread.cpp
|
PosixThread.cpp
|
||||||
QueueFactory.cpp
|
QueueFactory.cpp
|
||||||
SemaphoreFactory.cpp
|
SemaphoreFactory.cpp
|
||||||
TaskFactory.cpp
|
TaskFactory.cpp
|
||||||
tcpipHelpers.cpp
|
tcpipHelpers.cpp
|
||||||
unixUtility.cpp
|
unixUtility.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
|
|
||||||
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
|
target_link_libraries(${LIB_FSFW_NAME} PUBLIC
|
||||||
${CMAKE_THREAD_LIBS_INIT}
|
${CMAKE_THREAD_LIBS_INIT}
|
||||||
|
)
|
||||||
|
|
||||||
|
if(NOT APPLE)
|
||||||
|
target_link_libraries(${LIB_FSFW_NAME} PUBLIC
|
||||||
rt
|
rt
|
||||||
)
|
)
|
||||||
|
endif()
|
||||||
target_link_libraries(${LIB_FSFW_NAME} INTERFACE
|
|
||||||
${CMAKE_THREAD_LIBS_INIT}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
@ -8,11 +8,9 @@
|
|||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
|
#include "fsfw/ipc/MutexGuard.h"
|
||||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||||
|
|
||||||
uint16_t Clock::leapSeconds = 0;
|
|
||||||
MutexIF* Clock::timeMutex = NULL;
|
|
||||||
|
|
||||||
uint32_t Clock::getTicksPerSecond(void) {
|
uint32_t Clock::getTicksPerSecond(void) {
|
||||||
uint32_t ticks = sysconf(_SC_CLK_TCK);
|
uint32_t ticks = sysconf(_SC_CLK_TCK);
|
||||||
return ticks;
|
return ticks;
|
||||||
@ -117,7 +115,13 @@ ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
|
|||||||
// TODO errno
|
// TODO errno
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
|
ReturnValue_t result = checkOrCreateClockMutex();
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
MutexGuard helper(timeMutex);
|
||||||
|
// gmtime writes its output in a global buffer which is not Thread Safe
|
||||||
|
// Therefore we have to use a Mutex here
|
||||||
struct tm* timeInfo;
|
struct tm* timeInfo;
|
||||||
timeInfo = gmtime(&timeUnix.tv_sec);
|
timeInfo = gmtime(&timeUnix.tv_sec);
|
||||||
time->year = timeInfo->tm_year + 1900;
|
time->year = timeInfo->tm_year + 1900;
|
||||||
|
@ -12,12 +12,9 @@
|
|||||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||||
|
|
||||||
MessageQueue::MessageQueue(uint32_t messageDepth, size_t maxMessageSize, MqArgs* args)
|
MessageQueue::MessageQueue(uint32_t messageDepth, size_t maxMessageSize, MqArgs* args)
|
||||||
: id(MessageQueueIF::NO_QUEUE),
|
: MessageQueueBase(MessageQueueIF::NO_QUEUE, MessageQueueIF::NO_QUEUE, args),
|
||||||
lastPartner(MessageQueueIF::NO_QUEUE),
|
|
||||||
defaultDestination(MessageQueueIF::NO_QUEUE),
|
|
||||||
maxMessageSize(maxMessageSize) {
|
maxMessageSize(maxMessageSize) {
|
||||||
mq_attr attributes;
|
mq_attr attributes;
|
||||||
this->id = 0;
|
|
||||||
// Set attributes
|
// Set attributes
|
||||||
attributes.mq_curmsgs = 0;
|
attributes.mq_curmsgs = 0;
|
||||||
attributes.mq_maxmsg = messageDepth;
|
attributes.mq_maxmsg = messageDepth;
|
||||||
@ -37,9 +34,6 @@ MessageQueue::MessageQueue(uint32_t messageDepth, size_t maxMessageSize, MqArgs*
|
|||||||
// Successful mq_open call
|
// Successful mq_open call
|
||||||
this->id = tempId;
|
this->id = tempId;
|
||||||
}
|
}
|
||||||
if (args != nullptr) {
|
|
||||||
this->mqArgs = *args;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageQueue::~MessageQueue() {
|
MessageQueue::~MessageQueue() {
|
||||||
@ -53,30 +47,6 @@ MessageQueue::~MessageQueue() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
|
||||||
bool ignoreFault) {
|
|
||||||
return sendMessageFrom(sendTo, message, this->getId(), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessageIF* message) {
|
|
||||||
return sendToDefaultFrom(message, this->getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::reply(MessageQueueMessageIF* message) {
|
|
||||||
if (this->lastPartner != 0) {
|
|
||||||
return sendMessageFrom(this->lastPartner, message, this->getId());
|
|
||||||
} else {
|
|
||||||
return NO_REPLY_PARTNER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message,
|
|
||||||
MessageQueueId_t* receivedFrom) {
|
|
||||||
ReturnValue_t status = this->receiveMessage(message);
|
|
||||||
*receivedFrom = this->lastPartner;
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
|
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
|
||||||
if (message == nullptr) {
|
if (message == nullptr) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
@ -99,7 +69,7 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
|
|||||||
int status = mq_receive(id, reinterpret_cast<char*>(message->getBuffer()),
|
int status = mq_receive(id, reinterpret_cast<char*>(message->getBuffer()),
|
||||||
message->getMaximumMessageSize(), &messagePriority);
|
message->getMaximumMessageSize(), &messagePriority);
|
||||||
if (status > 0) {
|
if (status > 0) {
|
||||||
this->lastPartner = message->getSender();
|
this->last = message->getSender();
|
||||||
// Check size of incoming message.
|
// Check size of incoming message.
|
||||||
if (message->getMessageSize() < message->getMinimumMessageSize()) {
|
if (message->getMessageSize() < message->getMinimumMessageSize()) {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
@ -167,8 +137,6 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageQueueId_t MessageQueue::getLastPartner() const { return this->lastPartner; }
|
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::flush(uint32_t* count) {
|
ReturnValue_t MessageQueue::flush(uint32_t* count) {
|
||||||
mq_attr attrib;
|
mq_attr attrib;
|
||||||
int status = mq_getattr(id, &attrib);
|
int status = mq_getattr(id, &attrib);
|
||||||
@ -215,26 +183,11 @@ ReturnValue_t MessageQueue::flush(uint32_t* count) {
|
|||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageQueueId_t MessageQueue::getId() const { return this->id; }
|
|
||||||
|
|
||||||
void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) {
|
|
||||||
this->defaultDestination = defaultDestination;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessageIF* message,
|
|
||||||
MessageQueueId_t sentFrom, bool ignoreFault) {
|
|
||||||
return sendMessageFrom(defaultDestination, message, sentFrom, ignoreFault);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
||||||
MessageQueueId_t sentFrom, bool ignoreFault) {
|
MessageQueueId_t sentFrom, bool ignoreFault) {
|
||||||
return sendMessageFromMessageQueue(sendTo, message, sentFrom, ignoreFault);
|
return sendMessageFromMessageQueue(sendTo, message, sentFrom, ignoreFault);
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageQueueId_t MessageQueue::getDefaultDestination() const { return this->defaultDestination; }
|
|
||||||
|
|
||||||
bool MessageQueue::isDefaultDestinationSet() const { return (defaultDestination != NO_QUEUE); }
|
|
||||||
|
|
||||||
uint16_t MessageQueue::queueCounter = 0;
|
uint16_t MessageQueue::queueCounter = 0;
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
|
ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#ifndef FSFW_OSAL_LINUX_MESSAGEQUEUE_H_
|
#ifndef FSFW_OSAL_LINUX_MESSAGEQUEUE_H_
|
||||||
#define FSFW_OSAL_LINUX_MESSAGEQUEUE_H_
|
#define FSFW_OSAL_LINUX_MESSAGEQUEUE_H_
|
||||||
|
|
||||||
|
#include <fsfw/ipc/MessageQueueBase.h>
|
||||||
#include <mqueue.h>
|
#include <mqueue.h>
|
||||||
|
|
||||||
#include "fsfw/internalerror/InternalErrorReporterIF.h"
|
#include "fsfw/internalerror/InternalErrorReporterIF.h"
|
||||||
@ -26,7 +27,7 @@
|
|||||||
* makes use of the operating system calls provided.
|
* makes use of the operating system calls provided.
|
||||||
* @ingroup message_queue
|
* @ingroup message_queue
|
||||||
*/
|
*/
|
||||||
class MessageQueue : public MessageQueueIF {
|
class MessageQueue : public MessageQueueBase {
|
||||||
friend class MessageQueueSenderIF;
|
friend class MessageQueueSenderIF;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -45,103 +46,22 @@ class MessageQueue : public MessageQueueIF {
|
|||||||
MessageQueue(uint32_t messageDepth = 3,
|
MessageQueue(uint32_t messageDepth = 3,
|
||||||
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE,
|
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE,
|
||||||
MqArgs* args = nullptr);
|
MqArgs* args = nullptr);
|
||||||
|
|
||||||
|
/** Copying message queues forbidden */
|
||||||
|
MessageQueue(const MessageQueue&) = delete;
|
||||||
|
MessageQueue& operator=(const MessageQueue&) = delete;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The destructor deletes the formerly created message queue.
|
* @brief The destructor deletes the formerly created message queue.
|
||||||
* @details This is accomplished by using the delete call provided by the operating system.
|
* @details This is accomplished by using the delete call provided by the operating system.
|
||||||
*/
|
*/
|
||||||
virtual ~MessageQueue();
|
virtual ~MessageQueue();
|
||||||
/**
|
|
||||||
* @brief This operation sends a message to the given destination.
|
|
||||||
* @details It directly uses the sendMessage call of the MessageQueueSender parent, but passes
|
|
||||||
* its queue id as "sentFrom" parameter.
|
|
||||||
* @param sendTo This parameter specifies the message queue id of the destination message
|
|
||||||
* queue.
|
|
||||||
* @param message A pointer to a previously created message, which is sent.
|
|
||||||
* @param ignoreFault If set to true, the internal software fault counter is not incremented if
|
|
||||||
* queue is full.
|
|
||||||
*/
|
|
||||||
virtual ReturnValue_t sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
|
||||||
bool ignoreFault = false);
|
|
||||||
/**
|
|
||||||
* @brief This operation sends a message to the default destination.
|
|
||||||
* @details As in the sendMessage method, this function uses the sendToDefault call of the
|
|
||||||
* MessageQueueSender parent class and adds its queue id as "sentFrom"
|
|
||||||
* information.
|
|
||||||
* @param message A pointer to a previously created message, which is sent.
|
|
||||||
*/
|
|
||||||
virtual ReturnValue_t sendToDefault(MessageQueueMessageIF* message);
|
|
||||||
/**
|
|
||||||
* @brief This operation sends a message to the last communication partner.
|
|
||||||
* @details This operation simplifies answering an incoming message by using the stored
|
|
||||||
* lastParnter information as destination. If there was no message received yet
|
|
||||||
* (i.e. lastPartner is zero), an error code is returned.
|
|
||||||
* @param message A pointer to a previously created message, which is sent.
|
|
||||||
*/
|
|
||||||
ReturnValue_t reply(MessageQueueMessageIF* message);
|
|
||||||
|
|
||||||
/**
|
// Implement non-generic MessageQueueIF functions not handled by MessageQueueBase
|
||||||
* @brief This function reads available messages from the message queue and returns the
|
ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override;
|
||||||
* sender.
|
ReturnValue_t flush(uint32_t* count) override;
|
||||||
* @details It works identically to the other receiveMessage call, but in addition returns the
|
ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
||||||
* sender's queue id.
|
MessageQueueId_t sentFrom, bool ignoreFault = false) override;
|
||||||
* @param message A pointer to a message in which the received data is stored.
|
|
||||||
* @param receivedFrom A pointer to a queue id in which the sender's id is stored.
|
|
||||||
*/
|
|
||||||
ReturnValue_t receiveMessage(MessageQueueMessageIF* message, MessageQueueId_t* receivedFrom);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This function reads available messages from the message queue.
|
|
||||||
* @details If data is available it is stored in the passed message pointer. The message's
|
|
||||||
* original content is overwritten and the sendFrom information is stored in
|
|
||||||
* the lastPartner attribute. Else, the lastPartner information remains untouched, the message's
|
|
||||||
* content is cleared and the function returns immediately.
|
|
||||||
* @param message A pointer to a message in which the received data is stored.
|
|
||||||
*/
|
|
||||||
ReturnValue_t receiveMessage(MessageQueueMessageIF* message);
|
|
||||||
/**
|
|
||||||
* Deletes all pending messages in the queue.
|
|
||||||
* @param count The number of flushed messages.
|
|
||||||
* @return RETURN_OK on success.
|
|
||||||
*/
|
|
||||||
ReturnValue_t flush(uint32_t* count);
|
|
||||||
/**
|
|
||||||
* @brief This method returns the message queue id of the last communication partner.
|
|
||||||
*/
|
|
||||||
MessageQueueId_t getLastPartner() const;
|
|
||||||
/**
|
|
||||||
* @brief This method returns the message queue id of this class's message queue.
|
|
||||||
*/
|
|
||||||
MessageQueueId_t getId() const;
|
|
||||||
/**
|
|
||||||
* \brief With the sendMessage call, a queue message is sent to a receiving queue.
|
|
||||||
* \param sendTo This parameter specifies the message queue id to send the message to.
|
|
||||||
* \param message This is a pointer to a previously created message, which is sent.
|
|
||||||
* \param sentFrom The sentFrom information can be set to inject the sender's queue id into the
|
|
||||||
* message. This variable is set to zero by default. \param ignoreFault If set to true, the
|
|
||||||
* internal software fault counter is not incremented if queue is full.
|
|
||||||
*/
|
|
||||||
virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
|
||||||
MessageQueueId_t sentFrom, bool ignoreFault = false);
|
|
||||||
/**
|
|
||||||
* \brief The sendToDefault method sends a queue message to the default destination.
|
|
||||||
* \details In all other aspects, it works identical to the sendMessage method.
|
|
||||||
* \param message This is a pointer to a previously created message, which is sent.
|
|
||||||
* \param sentFrom The sentFrom information can be set to inject the sender's queue id into the
|
|
||||||
* message. This variable is set to zero by default.
|
|
||||||
*/
|
|
||||||
virtual ReturnValue_t sendToDefaultFrom(MessageQueueMessageIF* message,
|
|
||||||
MessageQueueId_t sentFrom = NO_QUEUE,
|
|
||||||
bool ignoreFault = false);
|
|
||||||
/**
|
|
||||||
* \brief This method is a simple setter for the default destination.
|
|
||||||
*/
|
|
||||||
void setDefaultDestination(MessageQueueId_t defaultDestination);
|
|
||||||
/**
|
|
||||||
* \brief This method is a simple getter for the default destination.
|
|
||||||
*/
|
|
||||||
MessageQueueId_t getDefaultDestination() const;
|
|
||||||
|
|
||||||
bool isDefaultDestinationSet() const;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
@ -160,33 +80,10 @@ class MessageQueue : public MessageQueueIF {
|
|||||||
bool ignoreFault = false);
|
bool ignoreFault = false);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
|
||||||
* @brief The class stores the queue id it got assigned from the operating system in this
|
|
||||||
* attribute. If initialization fails, the queue id is set to zero.
|
|
||||||
*/
|
|
||||||
MessageQueueId_t id;
|
|
||||||
/**
|
|
||||||
* @brief In this attribute, the queue id of the last communication partner is stored
|
|
||||||
* to allow for replying.
|
|
||||||
*/
|
|
||||||
MessageQueueId_t lastPartner;
|
|
||||||
/**
|
|
||||||
* @brief The message queue's name -a user specific information for the operating system- is
|
|
||||||
* generated automatically with the help of this static counter.
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* \brief This attribute stores a default destination to send messages to.
|
|
||||||
* \details It is stored to simplify sending to always-the-same receiver. The attribute may
|
|
||||||
* be set in the constructor or by a setter call to setDefaultDestination.
|
|
||||||
*/
|
|
||||||
MessageQueueId_t defaultDestination;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name of the message queue, stored for unlinking
|
* The name of the message queue, stored for unlinking
|
||||||
*/
|
*/
|
||||||
char name[16];
|
char name[16] = {};
|
||||||
|
|
||||||
MqArgs mqArgs = {};
|
|
||||||
|
|
||||||
static uint16_t queueCounter;
|
static uint16_t queueCounter;
|
||||||
const size_t maxMessageSize;
|
const size_t maxMessageSize;
|
||||||
|
@ -28,7 +28,11 @@ void* PeriodicPosixTask::taskEntryPoint(void* arg) {
|
|||||||
|
|
||||||
ReturnValue_t PeriodicPosixTask::addComponent(object_id_t object) {
|
ReturnValue_t PeriodicPosixTask::addComponent(object_id_t object) {
|
||||||
ExecutableObjectIF* newObject = ObjectManager::instance()->get<ExecutableObjectIF>(object);
|
ExecutableObjectIF* newObject = ObjectManager::instance()->get<ExecutableObjectIF>(object);
|
||||||
if (newObject == nullptr) {
|
return addComponent(newObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t PeriodicPosixTask::addComponent(ExecutableObjectIF* object) {
|
||||||
|
if (object == nullptr) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "PeriodicTask::addComponent: Invalid object. Make sure"
|
sif::error << "PeriodicTask::addComponent: Invalid object. Make sure"
|
||||||
<< " it implements ExecutableObjectIF!" << std::endl;
|
<< " it implements ExecutableObjectIF!" << std::endl;
|
||||||
@ -39,8 +43,8 @@ ReturnValue_t PeriodicPosixTask::addComponent(object_id_t object) {
|
|||||||
#endif
|
#endif
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
objectList.push_back(newObject);
|
objectList.push_back(object);
|
||||||
newObject->setTaskIF(this);
|
object->setTaskIF(this);
|
||||||
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,14 @@ class PeriodicPosixTask : public PosixThread, public PeriodicTaskIF {
|
|||||||
*/
|
*/
|
||||||
ReturnValue_t addComponent(object_id_t object) override;
|
ReturnValue_t addComponent(object_id_t object) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an object to the list of objects to be executed.
|
||||||
|
* The objects are executed in the order added.
|
||||||
|
* @param object pointer to the object to add.
|
||||||
|
* @return RETURN_OK on success, RETURN_FAILED if the object could not be added.
|
||||||
|
*/
|
||||||
|
ReturnValue_t addComponent(ExecutableObjectIF* object) override;
|
||||||
|
|
||||||
uint32_t getPeriodMs() const override;
|
uint32_t getPeriodMs() const override;
|
||||||
|
|
||||||
ReturnValue_t sleepFor(uint32_t ms) override;
|
ReturnValue_t sleepFor(uint32_t ms) override;
|
||||||
|
@ -6,9 +6,6 @@
|
|||||||
#include "fsfw/ipc/MutexGuard.h"
|
#include "fsfw/ipc/MutexGuard.h"
|
||||||
#include "fsfw/osal/rtems/RtemsBasic.h"
|
#include "fsfw/osal/rtems/RtemsBasic.h"
|
||||||
|
|
||||||
uint16_t Clock::leapSeconds = 0;
|
|
||||||
MutexIF* Clock::timeMutex = nullptr;
|
|
||||||
|
|
||||||
uint32_t Clock::getTicksPerSecond(void) {
|
uint32_t Clock::getTicksPerSecond(void) {
|
||||||
rtems_interval ticks_per_second = rtems_clock_get_ticks_per_second();
|
rtems_interval ticks_per_second = rtems_clock_get_ticks_per_second();
|
||||||
return static_cast<uint32_t>(ticks_per_second);
|
return static_cast<uint32_t>(ticks_per_second);
|
||||||
|
@ -7,7 +7,8 @@
|
|||||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||||
|
|
||||||
MessageQueue::MessageQueue(size_t message_depth, size_t max_message_size, MqArgs* args)
|
MessageQueue::MessageQueue(size_t message_depth, size_t max_message_size, MqArgs* args)
|
||||||
: id(0), lastPartner(0), defaultDestination(NO_QUEUE), internalErrorReporter(nullptr) {
|
: MessageQueueBase(MessageQueueIF::NO_QUEUE, MessageQueueIF::NO_QUEUE, args),
|
||||||
|
internalErrorReporter(nullptr) {
|
||||||
rtems_name name = ('Q' << 24) + (queueCounter++ << 8);
|
rtems_name name = ('Q' << 24) + (queueCounter++ << 8);
|
||||||
rtems_status_code status =
|
rtems_status_code status =
|
||||||
rtems_message_queue_create(name, message_depth, max_message_size, 0, &(this->id));
|
rtems_message_queue_create(name, message_depth, max_message_size, 0, &(this->id));
|
||||||
@ -16,43 +17,19 @@ MessageQueue::MessageQueue(size_t message_depth, size_t max_message_size, MqArgs
|
|||||||
sif::error << "MessageQueue::MessageQueue: Creating Queue " << std::hex << name << std::dec
|
sif::error << "MessageQueue::MessageQueue: Creating Queue " << std::hex << name << std::dec
|
||||||
<< " failed with status:" << (uint32_t)status << std::endl;
|
<< " failed with status:" << (uint32_t)status << std::endl;
|
||||||
#endif
|
#endif
|
||||||
this->id = 0;
|
this->id = MessageQueueIF::NO_QUEUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageQueue::~MessageQueue() { rtems_message_queue_delete(id); }
|
MessageQueue::~MessageQueue() { rtems_message_queue_delete(id); }
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
|
||||||
bool ignoreFault) {
|
|
||||||
return sendMessageFrom(sendTo, message, this->getId(), ignoreFault);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessageIF* message) {
|
|
||||||
return sendToDefaultFrom(message, this->getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::reply(MessageQueueMessageIF* message) {
|
|
||||||
if (this->lastPartner != 0) {
|
|
||||||
return sendMessage(this->lastPartner, message, this->getId());
|
|
||||||
} else {
|
|
||||||
return NO_REPLY_PARTNER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message,
|
|
||||||
MessageQueueId_t* receivedFrom) {
|
|
||||||
ReturnValue_t status = this->receiveMessage(message);
|
|
||||||
*receivedFrom = this->lastPartner;
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
|
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
rtems_status_code status =
|
rtems_status_code status =
|
||||||
rtems_message_queue_receive(id, message->getBuffer(), &size, RTEMS_NO_WAIT, 1);
|
rtems_message_queue_receive(id, message->getBuffer(), &size, RTEMS_NO_WAIT, 1);
|
||||||
if (status == RTEMS_SUCCESSFUL) {
|
if (status == RTEMS_SUCCESSFUL) {
|
||||||
message->setMessageSize(size);
|
message->setMessageSize(size);
|
||||||
this->lastPartner = message->getSender();
|
this->last = message->getSender();
|
||||||
// Check size of incoming message.
|
// Check size of incoming message.
|
||||||
if (message->getMessageSize() < message->getMinimumMessageSize()) {
|
if (message->getMessageSize() < message->getMinimumMessageSize()) {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
@ -65,19 +42,11 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
|
|||||||
return convertReturnCode(status);
|
return convertReturnCode(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageQueueId_t MessageQueue::getLastPartner() const { return this->lastPartner; }
|
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::flush(uint32_t* count) {
|
ReturnValue_t MessageQueue::flush(uint32_t* count) {
|
||||||
rtems_status_code status = rtems_message_queue_flush(id, count);
|
rtems_status_code status = rtems_message_queue_flush(id, count);
|
||||||
return convertReturnCode(status);
|
return convertReturnCode(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageQueueId_t MessageQueue::getId() const { return this->id; }
|
|
||||||
|
|
||||||
void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) {
|
|
||||||
this->defaultDestination = defaultDestination;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
||||||
MessageQueueId_t sentFrom, bool ignoreFault) {
|
MessageQueueId_t sentFrom, bool ignoreFault) {
|
||||||
message->setSender(sentFrom);
|
message->setSender(sentFrom);
|
||||||
@ -103,15 +72,6 @@ ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, MessageQueu
|
|||||||
return returnCode;
|
return returnCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessageIF* message,
|
|
||||||
MessageQueueId_t sentFrom, bool ignoreFault) {
|
|
||||||
return sendMessageFrom(defaultDestination, message, sentFrom, ignoreFault);
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageQueueId_t MessageQueue::getDefaultDestination() const { return this->defaultDestination; }
|
|
||||||
|
|
||||||
bool MessageQueue::isDefaultDestinationSet() const { return (defaultDestination != NO_QUEUE); }
|
|
||||||
|
|
||||||
ReturnValue_t MessageQueue::convertReturnCode(rtems_status_code inValue) {
|
ReturnValue_t MessageQueue::convertReturnCode(rtems_status_code inValue) {
|
||||||
switch (inValue) {
|
switch (inValue) {
|
||||||
case RTEMS_SUCCESSFUL:
|
case RTEMS_SUCCESSFUL:
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#ifndef FSFW_OSAL_RTEMS_MESSAGEQUEUE_H_
|
#ifndef FSFW_OSAL_RTEMS_MESSAGEQUEUE_H_
|
||||||
#define FSFW_OSAL_RTEMS_MESSAGEQUEUE_H_
|
#define FSFW_OSAL_RTEMS_MESSAGEQUEUE_H_
|
||||||
|
|
||||||
|
#include <fsfw/ipc/MessageQueueBase.h>
|
||||||
|
|
||||||
#include "RtemsBasic.h"
|
#include "RtemsBasic.h"
|
||||||
#include "fsfw/internalerror/InternalErrorReporterIF.h"
|
#include "fsfw/internalerror/InternalErrorReporterIF.h"
|
||||||
#include "fsfw/ipc/MessageQueueIF.h"
|
#include "fsfw/ipc/MessageQueueIF.h"
|
||||||
@ -20,7 +22,7 @@
|
|||||||
*as well as sending and receiving messages, the class makes use of the operating system calls
|
*as well as sending and receiving messages, the class makes use of the operating system calls
|
||||||
*provided. \ingroup message_queue
|
*provided. \ingroup message_queue
|
||||||
*/
|
*/
|
||||||
class MessageQueue : public MessageQueueIF {
|
class MessageQueue : public MessageQueueBase {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief The constructor initializes and configures the message queue.
|
* @brief The constructor initializes and configures the message queue.
|
||||||
@ -37,130 +39,24 @@ class MessageQueue : public MessageQueueIF {
|
|||||||
MessageQueue(size_t message_depth = 3,
|
MessageQueue(size_t message_depth = 3,
|
||||||
size_t max_message_size = MessageQueueMessage::MAX_MESSAGE_SIZE,
|
size_t max_message_size = MessageQueueMessage::MAX_MESSAGE_SIZE,
|
||||||
MqArgs* args = nullptr);
|
MqArgs* args = nullptr);
|
||||||
|
|
||||||
|
/** Copying message queues forbidden */
|
||||||
|
MessageQueue(const MessageQueue&) = delete;
|
||||||
|
MessageQueue& operator=(const MessageQueue&) = delete;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The destructor deletes the formerly created message queue.
|
* @brief The destructor deletes the formerly created message queue.
|
||||||
* @details This is accomplished by using the delete call provided by the operating system.
|
* @details This is accomplished by using the delete call provided by the operating system.
|
||||||
*/
|
*/
|
||||||
virtual ~MessageQueue();
|
virtual ~MessageQueue();
|
||||||
/**
|
|
||||||
* @brief This operation sends a message to the given destination.
|
|
||||||
* @details It directly uses the sendMessage call of the MessageQueueSender parent, but passes
|
|
||||||
* its queue id as "sentFrom" parameter.
|
|
||||||
* @param sendTo This parameter specifies the message queue id of the destination message
|
|
||||||
* queue.
|
|
||||||
* @param message A pointer to a previously created message, which is sent.
|
|
||||||
* @param ignoreFault If set to true, the internal software fault counter is not incremented if
|
|
||||||
* queue is full.
|
|
||||||
*/
|
|
||||||
ReturnValue_t sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
|
||||||
bool ignoreFault = false);
|
|
||||||
/**
|
|
||||||
* @brief This operation sends a message to the default destination.
|
|
||||||
* @details As in the sendMessage method, this function uses the sendToDefault call of the
|
|
||||||
* MessageQueueSender parent class and adds its queue id as "sentFrom"
|
|
||||||
* information.
|
|
||||||
* @param message A pointer to a previously created message, which is sent.
|
|
||||||
*/
|
|
||||||
ReturnValue_t sendToDefault(MessageQueueMessageIF* message);
|
|
||||||
/**
|
|
||||||
* @brief This operation sends a message to the last communication partner.
|
|
||||||
* @details This operation simplifies answering an incoming message by using the stored
|
|
||||||
* lastParnter information as destination. If there was no message received yet
|
|
||||||
* (i.e. lastPartner is zero), an error code is returned.
|
|
||||||
* @param message A pointer to a previously created message, which is sent.
|
|
||||||
*/
|
|
||||||
ReturnValue_t reply(MessageQueueMessageIF* message);
|
|
||||||
|
|
||||||
/**
|
// Implement non-generic MessageQueueIF functions not handled by MessageQueueBase
|
||||||
* @brief This function reads available messages from the message queue and returns the
|
ReturnValue_t flush(uint32_t* count) override;
|
||||||
* sender.
|
ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
||||||
* @details It works identically to the other receiveMessage call, but in addition returns the
|
MessageQueueId_t sentFrom = NO_QUEUE,
|
||||||
* sender's queue id.
|
bool ignoreFault = false) override;
|
||||||
* @param message A pointer to a message in which the received data is stored.
|
|
||||||
* @param receivedFrom A pointer to a queue id in which the sender's id is stored.
|
|
||||||
*/
|
|
||||||
ReturnValue_t receiveMessage(MessageQueueMessageIF* message, MessageQueueId_t* receivedFrom);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This function reads available messages from the message queue.
|
|
||||||
* @details If data is available it is stored in the passed message pointer. The message's
|
|
||||||
* original content is overwritten and the sendFrom information is stored in
|
|
||||||
* the lastPartner attribute. Else, the lastPartner information remains untouched, the message's
|
|
||||||
* content is cleared and the function returns immediately.
|
|
||||||
* @param message A pointer to a message in which the received data is stored.
|
|
||||||
*/
|
|
||||||
ReturnValue_t receiveMessage(MessageQueueMessageIF* message);
|
|
||||||
/**
|
|
||||||
* Deletes all pending messages in the queue.
|
|
||||||
* @param count The number of flushed messages.
|
|
||||||
* @return RETURN_OK on success.
|
|
||||||
*/
|
|
||||||
ReturnValue_t flush(uint32_t* count);
|
|
||||||
/**
|
|
||||||
* @brief This method returns the message queue id of the last communication partner.
|
|
||||||
*/
|
|
||||||
MessageQueueId_t getLastPartner() const;
|
|
||||||
/**
|
|
||||||
* @brief This method returns the message queue id of this class's message queue.
|
|
||||||
*/
|
|
||||||
MessageQueueId_t getId() const;
|
|
||||||
/**
|
|
||||||
* \brief With the sendMessage call, a queue message is sent to a receiving queue.
|
|
||||||
* \details This method takes the message provided, adds the sentFrom information and passes
|
|
||||||
* it on to the destination provided with an operating system call. The OS's
|
|
||||||
* return value is returned.
|
|
||||||
* \param sendTo This parameter specifies the message queue id to send the message to.
|
|
||||||
* \param message This is a pointer to a previously created message, which is sent.
|
|
||||||
* \param sentFrom The sentFrom information can be set to inject the sender's queue id into the
|
|
||||||
* message. This variable is set to zero by default. \param ignoreFault If set to true, the
|
|
||||||
* internal software fault counter is not incremented if queue is full.
|
|
||||||
*/
|
|
||||||
virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
|
||||||
MessageQueueId_t sentFrom = NO_QUEUE,
|
|
||||||
bool ignoreFault = false);
|
|
||||||
/**
|
|
||||||
* \brief The sendToDefault method sends a queue message to the default destination.
|
|
||||||
* \details In all other aspects, it works identical to the sendMessage method.
|
|
||||||
* \param message This is a pointer to a previously created message, which is sent.
|
|
||||||
* \param sentFrom The sentFrom information can be set to inject the sender's queue id into the
|
|
||||||
* message. This variable is set to zero by default.
|
|
||||||
*/
|
|
||||||
virtual ReturnValue_t sendToDefaultFrom(MessageQueueMessageIF* message,
|
|
||||||
MessageQueueId_t sentFrom = NO_QUEUE,
|
|
||||||
bool ignoreFault = false);
|
|
||||||
/**
|
|
||||||
* \brief This method is a simple setter for the default destination.
|
|
||||||
*/
|
|
||||||
void setDefaultDestination(MessageQueueId_t defaultDestination);
|
|
||||||
/**
|
|
||||||
* \brief This method is a simple getter for the default destination.
|
|
||||||
*/
|
|
||||||
MessageQueueId_t getDefaultDestination() const;
|
|
||||||
|
|
||||||
bool isDefaultDestinationSet() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
|
||||||
* @brief The class stores the queue id it got assigned from the operating system in this
|
|
||||||
* attribute. If initialization fails, the queue id is set to zero.
|
|
||||||
*/
|
|
||||||
MessageQueueId_t id;
|
|
||||||
/**
|
|
||||||
* @brief In this attribute, the queue id of the last communication partner is stored
|
|
||||||
* to allow for replying.
|
|
||||||
*/
|
|
||||||
MessageQueueId_t lastPartner;
|
|
||||||
/**
|
|
||||||
* @brief The message queue's name -a user specific information for the operating system- is
|
|
||||||
* generated automatically with the help of this static counter.
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* \brief This attribute stores a default destination to send messages to.
|
|
||||||
* \details It is stored to simplify sending to always-the-same receiver. The attribute may
|
|
||||||
* be set in the constructor or by a setter call to setDefaultDestination.
|
|
||||||
*/
|
|
||||||
MessageQueueId_t defaultDestination;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief This attribute stores a reference to the internal error reporter for reporting full
|
* \brief This attribute stores a reference to the internal error reporter for reporting full
|
||||||
* queues. \details In the event of a full destination queue, the reporter will be notified. The
|
* queues. \details In the event of a full destination queue, the reporter will be notified. The
|
||||||
|
@ -68,11 +68,15 @@ void PeriodicTask::taskFunctionality() {
|
|||||||
|
|
||||||
ReturnValue_t PeriodicTask::addComponent(object_id_t object) {
|
ReturnValue_t PeriodicTask::addComponent(object_id_t object) {
|
||||||
ExecutableObjectIF* newObject = ObjectManager::instance()->get<ExecutableObjectIF>(object);
|
ExecutableObjectIF* newObject = ObjectManager::instance()->get<ExecutableObjectIF>(object);
|
||||||
if (newObject == nullptr) {
|
return addComponent(newObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t PeriodicTask::addComponent(ExecutableObjectIF* object) {
|
||||||
|
if (object == nullptr) {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
objectList.push_back(newObject);
|
objectList.push_back(object);
|
||||||
newObject->setTaskIF(this);
|
object->setTaskIF(this);
|
||||||
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
@ -59,6 +59,14 @@ class PeriodicTask : public RTEMSTaskBase, public PeriodicTaskIF {
|
|||||||
*/
|
*/
|
||||||
ReturnValue_t addComponent(object_id_t object) override;
|
ReturnValue_t addComponent(object_id_t object) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an object to the list of objects to be executed.
|
||||||
|
* The objects are executed in the order added.
|
||||||
|
* @param object pointer to the object to add.
|
||||||
|
* @return RETURN_OK on success, RETURN_FAILED if the object could not be added.
|
||||||
|
*/
|
||||||
|
ReturnValue_t addComponent(ExecutableObjectIF *object) override;
|
||||||
|
|
||||||
uint32_t getPeriodMs() const override;
|
uint32_t getPeriodMs() const override;
|
||||||
|
|
||||||
ReturnValue_t sleepFor(uint32_t ms) override;
|
ReturnValue_t sleepFor(uint32_t ms) override;
|
||||||
|
@ -66,7 +66,7 @@ class HasParametersIF {
|
|||||||
* @param newValues
|
* @param newValues
|
||||||
* @param startAtIndex Linear index, runs left to right, top to bottom for
|
* @param startAtIndex Linear index, runs left to right, top to bottom for
|
||||||
* matrix indexes.
|
* matrix indexes.
|
||||||
* @return RETURN_OK if parameter is valid and a set function of the parameter wrapper was called.
|
* @return
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueIdentifier,
|
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueIdentifier,
|
||||||
ParameterWrapper *parameterWrapper,
|
ParameterWrapper *parameterWrapper,
|
||||||
|
@ -211,13 +211,9 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
|
|||||||
if (data == nullptr) {
|
if (data == nullptr) {
|
||||||
#if FSFW_VERBOSE_LEVEL >= 1
|
#if FSFW_VERBOSE_LEVEL >= 1
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "ParameterWrapper::copyFrom: Called on read-only variable or "
|
sif::warning << "ParameterWrapper::copyFrom: Called on read-only variable!" << std::endl;
|
||||||
"data pointer not set"
|
|
||||||
<< std::endl;
|
|
||||||
#else
|
#else
|
||||||
sif::printWarning(
|
sif::printWarning("ParameterWrapper::copyFrom: Called on read-only variable!\n");
|
||||||
"ParameterWrapper::copyFrom: Called on read-only variable "
|
|
||||||
"or data pointer not set\n");
|
|
||||||
#endif
|
#endif
|
||||||
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||||
return READONLY;
|
return READONLY;
|
||||||
@ -226,9 +222,9 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
|
|||||||
if (from->readonlyData == nullptr) {
|
if (from->readonlyData == nullptr) {
|
||||||
#if FSFW_VERBOSE_LEVEL >= 1
|
#if FSFW_VERBOSE_LEVEL >= 1
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "ParameterWrapper::copyFrom: Source not set" << std::endl;
|
sif::warning << "ParameterWrapper::copyFrom: Source not set!" << std::endl;
|
||||||
#else
|
#else
|
||||||
sif::printWarning("ParameterWrapper::copyFrom: Source not set\n");
|
sif::printWarning("ParameterWrapper::copyFrom: Source not set!\n");
|
||||||
#endif
|
#endif
|
||||||
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||||
return SOURCE_NOT_SET;
|
return SOURCE_NOT_SET;
|
||||||
@ -237,9 +233,9 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
|
|||||||
if (type != from->type) {
|
if (type != from->type) {
|
||||||
#if FSFW_VERBOSE_LEVEL >= 1
|
#if FSFW_VERBOSE_LEVEL >= 1
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "ParameterWrapper::copyFrom: Datatype missmatch" << std::endl;
|
sif::warning << "ParameterWrapper::copyFrom: Datatype missmatch!" << std::endl;
|
||||||
#else
|
#else
|
||||||
sif::printWarning("ParameterWrapper::copyFrom: Datatype missmatch\n");
|
sif::printWarning("ParameterWrapper::copyFrom: Datatype missmatch!\n");
|
||||||
#endif
|
#endif
|
||||||
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||||
return DATATYPE_MISSMATCH;
|
return DATATYPE_MISSMATCH;
|
||||||
@ -249,9 +245,9 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
|
|||||||
if (rows == 0 or columns == 0) {
|
if (rows == 0 or columns == 0) {
|
||||||
#if FSFW_VERBOSE_LEVEL >= 1
|
#if FSFW_VERBOSE_LEVEL >= 1
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "ParameterWrapper::copyFrom: Columns or rows zero" << std::endl;
|
sif::warning << "ParameterWrapper::copyFrom: Columns or rows zero!" << std::endl;
|
||||||
#else
|
#else
|
||||||
sif::printWarning("ParameterWrapper::copyFrom: Columns or rows zero\n");
|
sif::printWarning("ParameterWrapper::copyFrom: Columns or rows zero!\n");
|
||||||
#endif
|
#endif
|
||||||
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||||
return COLUMN_OR_ROWS_ZERO;
|
return COLUMN_OR_ROWS_ZERO;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
target_sources(${LIB_FSFW_NAME}
|
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||||
PRIVATE
|
Fuse.cpp
|
||||||
Fuse.cpp
|
PowerComponent.cpp
|
||||||
PowerComponent.cpp
|
PowerSensor.cpp
|
||||||
PowerSensor.cpp
|
PowerSwitcher.cpp
|
||||||
PowerSwitcher.cpp
|
DummyPowerSwitcher.cpp
|
||||||
)
|
)
|
47
src/fsfw/power/DummyPowerSwitcher.cpp
Normal file
47
src/fsfw/power/DummyPowerSwitcher.cpp
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#include "DummyPowerSwitcher.h"
|
||||||
|
|
||||||
|
DummyPowerSwitcher::DummyPowerSwitcher(object_id_t objectId, size_t numberOfSwitches,
|
||||||
|
size_t numberOfFuses, bool registerGlobally,
|
||||||
|
uint32_t switchDelayMs)
|
||||||
|
: SystemObject(objectId, registerGlobally),
|
||||||
|
switcherList(numberOfSwitches),
|
||||||
|
fuseList(numberOfFuses),
|
||||||
|
switchDelayMs(switchDelayMs) {}
|
||||||
|
|
||||||
|
void DummyPowerSwitcher::setInitialSwitcherList(std::vector<ReturnValue_t> switcherList) {
|
||||||
|
this->switcherList = switcherList;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DummyPowerSwitcher::setInitialFusesList(std::vector<ReturnValue_t> fuseList) {
|
||||||
|
this->fuseList = fuseList;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t DummyPowerSwitcher::sendSwitchCommand(power::Switch_t switchNr, ReturnValue_t onOff) {
|
||||||
|
if (switchNr < switcherList.capacity()) {
|
||||||
|
switcherList[switchNr] = onOff;
|
||||||
|
}
|
||||||
|
return RETURN_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t DummyPowerSwitcher::sendFuseOnCommand(uint8_t fuseNr) {
|
||||||
|
if (fuseNr < fuseList.capacity()) {
|
||||||
|
fuseList[fuseNr] = FUSE_ON;
|
||||||
|
}
|
||||||
|
return RETURN_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t DummyPowerSwitcher::getSwitchState(power::Switch_t switchNr) const {
|
||||||
|
if (switchNr < switcherList.capacity()) {
|
||||||
|
return switcherList[switchNr];
|
||||||
|
}
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t DummyPowerSwitcher::getFuseState(uint8_t fuseNr) const {
|
||||||
|
if (fuseNr < fuseList.capacity()) {
|
||||||
|
return fuseList[fuseNr];
|
||||||
|
}
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t DummyPowerSwitcher::getSwitchDelayMs(void) const { return switchDelayMs; }
|
38
src/fsfw/power/DummyPowerSwitcher.h
Normal file
38
src/fsfw/power/DummyPowerSwitcher.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#ifndef FSFW_SRC_FSFW_POWER_DUMMYPOWERSWITCHER_H_
|
||||||
|
#define FSFW_SRC_FSFW_POWER_DUMMYPOWERSWITCHER_H_
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "PowerSwitchIF.h"
|
||||||
|
#include "definitions.h"
|
||||||
|
#include "fsfw/objectmanager/SystemObject.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This component can be used to simulate a power switcher like a
|
||||||
|
* Power Control Distribution Unit (PCDU)
|
||||||
|
* @details
|
||||||
|
* The dummy switcher will simply cache the commanded fuse and switch states and return them
|
||||||
|
* in the according switch getter functions. In that sense, it simulates an ideal PCDU.
|
||||||
|
*/
|
||||||
|
class DummyPowerSwitcher : public SystemObject, public PowerSwitchIF {
|
||||||
|
public:
|
||||||
|
DummyPowerSwitcher(object_id_t objectId, size_t numberOfSwitches, size_t numberOfFuses,
|
||||||
|
bool registerGlobally = true, uint32_t switchDelayMs = 5000);
|
||||||
|
|
||||||
|
void setInitialSwitcherList(std::vector<ReturnValue_t> switcherList);
|
||||||
|
void setInitialFusesList(std::vector<ReturnValue_t> switcherList);
|
||||||
|
|
||||||
|
virtual ReturnValue_t sendSwitchCommand(power::Switch_t switchNr, ReturnValue_t onOff) override;
|
||||||
|
virtual ReturnValue_t sendFuseOnCommand(uint8_t fuseNr) override;
|
||||||
|
virtual ReturnValue_t getSwitchState(power::Switch_t switchNr) const override;
|
||||||
|
virtual ReturnValue_t getFuseState(uint8_t fuseNr) const override;
|
||||||
|
virtual uint32_t getSwitchDelayMs(void) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<ReturnValue_t> switcherList;
|
||||||
|
std::vector<ReturnValue_t> fuseList;
|
||||||
|
uint32_t switchDelayMs = 5000;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* FSFW_SRC_FSFW_POWER_DUMMYPOWERSWITCHER_H_ */
|
@ -54,7 +54,7 @@ class Fuse : public SystemObject,
|
|||||||
|
|
||||||
ReturnValue_t check();
|
ReturnValue_t check();
|
||||||
uint8_t getFuseId() const;
|
uint8_t getFuseId() const;
|
||||||
ReturnValue_t initialize();
|
ReturnValue_t initialize() override;
|
||||||
DeviceList devices;
|
DeviceList devices;
|
||||||
ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||||
SerializeIF::Endianness streamEndianness) const override;
|
SerializeIF::Endianness streamEndianness) const override;
|
||||||
|
@ -15,9 +15,8 @@ PowerSensor::PowerSensor(object_id_t objectId, sid_t setId, VariableIds ids, Def
|
|||||||
limits.currentMin, limits.currentMax, events.currentLow, events.currentHigh),
|
limits.currentMin, limits.currentMax, events.currentLow, events.currentHigh),
|
||||||
voltageLimit(objectId, MODULE_ID_VOLTAGE, ids.pidVoltage, confirmationCount,
|
voltageLimit(objectId, MODULE_ID_VOLTAGE, ids.pidVoltage, confirmationCount,
|
||||||
limits.voltageMin, limits.voltageMax, events.voltageLow, events.voltageHigh) {
|
limits.voltageMin, limits.voltageMax, events.voltageLow, events.voltageHigh) {
|
||||||
auto mqArgs = MqArgs(objectId, static_cast<void*>(this));
|
commandQueue =
|
||||||
commandQueue = QueueFactory::instance()->createMessageQueue(
|
QueueFactory::instance()->createMessageQueue(3, MessageQueueMessage::MAX_MESSAGE_SIZE);
|
||||||
3, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PowerSensor::~PowerSensor() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }
|
PowerSensor::~PowerSensor() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#ifndef FSFW_POWER_POWERSWITCHIF_H_
|
#ifndef FSFW_POWER_POWERSWITCHIF_H_
|
||||||
#define FSFW_POWER_POWERSWITCHIF_H_
|
#define FSFW_POWER_POWERSWITCHIF_H_
|
||||||
|
|
||||||
#include "definitions.h"
|
|
||||||
#include "../events/Event.h"
|
#include "../events/Event.h"
|
||||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||||
|
#include "definitions.h"
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @brief This interface defines a connection to a device that is capable of
|
* @brief This interface defines a connection to a device that is capable of
|
||||||
@ -38,11 +38,11 @@ class PowerSwitchIF : public HasReturnvaluesIF {
|
|||||||
* @param switchNr
|
* @param switchNr
|
||||||
* @param onOff on == @c SWITCH_ON; off != @c SWITCH_ON
|
* @param onOff on == @c SWITCH_ON; off != @c SWITCH_ON
|
||||||
*/
|
*/
|
||||||
virtual void sendSwitchCommand(power::Switch_t switchNr, ReturnValue_t onOff) const = 0;
|
virtual ReturnValue_t sendSwitchCommand(power::Switch_t switchNr, ReturnValue_t onOff) = 0;
|
||||||
/**
|
/**
|
||||||
* Sends a command to the Power Unit to enable a certain fuse.
|
* Sends a command to the Power Unit to enable a certain fuse.
|
||||||
*/
|
*/
|
||||||
virtual void sendFuseOnCommand(uint8_t fuseNr) const = 0;
|
virtual ReturnValue_t sendFuseOnCommand(uint8_t fuseNr) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get the state of the Switches.
|
* get the state of the Switches.
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "definitions.h"
|
|
||||||
#include "fsfw/power/PowerSwitcher.h"
|
#include "fsfw/power/PowerSwitcher.h"
|
||||||
|
|
||||||
|
#include "definitions.h"
|
||||||
#include "fsfw/objectmanager/ObjectManager.h"
|
#include "fsfw/objectmanager/ObjectManager.h"
|
||||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||||
|
|
||||||
@ -45,18 +45,30 @@ void PowerSwitcher::commandSwitches(ReturnValue_t onOff) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PowerSwitcher::turnOn() {
|
void PowerSwitcher::turnOn(bool checkCurrentState) {
|
||||||
|
if (checkCurrentState) {
|
||||||
|
if (getStateOfSwitches() == PowerSwitchIF::SWITCH_ON) {
|
||||||
|
state = SWITCH_IS_ON;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
commandSwitches(PowerSwitchIF::SWITCH_ON);
|
commandSwitches(PowerSwitchIF::SWITCH_ON);
|
||||||
state = WAIT_ON;
|
state = WAIT_ON;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PowerSwitcher::turnOff() {
|
void PowerSwitcher::turnOff(bool checkCurrentState) {
|
||||||
|
if (checkCurrentState) {
|
||||||
|
if (getStateOfSwitches() == PowerSwitchIF::SWITCH_OFF) {
|
||||||
|
state = SWITCH_IS_OFF;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
commandSwitches(PowerSwitchIF::SWITCH_OFF);
|
commandSwitches(PowerSwitchIF::SWITCH_OFF);
|
||||||
state = WAIT_OFF;
|
state = WAIT_OFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PowerSwitcher::active() {
|
bool PowerSwitcher::active() {
|
||||||
if(state == WAIT_OFF or state == WAIT_ON) {
|
if (state == WAIT_OFF or state == WAIT_ON) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -18,10 +18,11 @@ class PowerSwitcher : public HasReturnvaluesIF {
|
|||||||
static const uint8_t INTERFACE_ID = CLASS_ID::POWER_SWITCHER;
|
static const uint8_t INTERFACE_ID = CLASS_ID::POWER_SWITCHER;
|
||||||
static const ReturnValue_t IN_POWER_TRANSITION = MAKE_RETURN_CODE(1);
|
static const ReturnValue_t IN_POWER_TRANSITION = MAKE_RETURN_CODE(1);
|
||||||
static const ReturnValue_t SWITCH_STATE_MISMATCH = MAKE_RETURN_CODE(2);
|
static const ReturnValue_t SWITCH_STATE_MISMATCH = MAKE_RETURN_CODE(2);
|
||||||
PowerSwitcher(PowerSwitchIF* switcher, uint8_t setSwitch1, uint8_t setSwitch2 = power::NO_SWITCH,
|
PowerSwitcher(PowerSwitchIF* switcher, power::Switch_t setSwitch1,
|
||||||
|
power::Switch_t setSwitch2 = power::NO_SWITCH,
|
||||||
State_t setStartState = SWITCH_IS_OFF);
|
State_t setStartState = SWITCH_IS_OFF);
|
||||||
void turnOn();
|
void turnOn(bool checkCurrentState = true);
|
||||||
void turnOff();
|
void turnOff(bool checkCurrentState = true);
|
||||||
bool active();
|
bool active();
|
||||||
void doStateMachine();
|
void doStateMachine();
|
||||||
State_t getState();
|
State_t getState();
|
||||||
|
@ -8,6 +8,6 @@ namespace power {
|
|||||||
using Switch_t = uint8_t;
|
using Switch_t = uint8_t;
|
||||||
static constexpr Switch_t NO_SWITCH = 0xFF;
|
static constexpr Switch_t NO_SWITCH = 0xFF;
|
||||||
|
|
||||||
}
|
} // namespace power
|
||||||
|
|
||||||
#endif /* FSFW_SRC_FSFW_POWER_DEFINITIONS_H_ */
|
#endif /* FSFW_SRC_FSFW_POWER_DEFINITIONS_H_ */
|
||||||
|
@ -13,8 +13,6 @@ CService201HealthCommanding::CService201HealthCommanding(object_id_t objectId, u
|
|||||||
: CommandingServiceBase(objectId, apid, serviceId, numParallelCommands, commandTimeoutSeconds) {
|
: CommandingServiceBase(objectId, apid, serviceId, numParallelCommands, commandTimeoutSeconds) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CService201HealthCommanding::~CService201HealthCommanding() {}
|
|
||||||
|
|
||||||
ReturnValue_t CService201HealthCommanding::isValidSubservice(uint8_t subservice) {
|
ReturnValue_t CService201HealthCommanding::isValidSubservice(uint8_t subservice) {
|
||||||
switch (subservice) {
|
switch (subservice) {
|
||||||
case (Subservice::COMMAND_SET_HEALTH):
|
case (Subservice::COMMAND_SET_HEALTH):
|
||||||
@ -43,8 +41,8 @@ ReturnValue_t CService201HealthCommanding::getMessageQueueAndObject(uint8_t subs
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t CService201HealthCommanding::checkInterfaceAndAcquireMessageQueue(
|
ReturnValue_t CService201HealthCommanding::checkInterfaceAndAcquireMessageQueue(
|
||||||
MessageQueueId_t *messageQueueToSet, object_id_t *objectId) {
|
MessageQueueId_t *messageQueueToSet, const object_id_t *objectId) {
|
||||||
HasHealthIF *destination = ObjectManager::instance()->get<HasHealthIF>(*objectId);
|
auto *destination = ObjectManager::instance()->get<HasHealthIF>(*objectId);
|
||||||
if (destination == nullptr) {
|
if (destination == nullptr) {
|
||||||
return CommandingServiceBase::INVALID_OBJECT;
|
return CommandingServiceBase::INVALID_OBJECT;
|
||||||
}
|
}
|
||||||
@ -77,6 +75,10 @@ ReturnValue_t CService201HealthCommanding::prepareCommand(CommandMessage *messag
|
|||||||
HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_ANNOUNCE_ALL);
|
HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_ANNOUNCE_ALL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
default: {
|
||||||
|
// Should never happen, subservice was already checked
|
||||||
|
result = RETURN_FAILED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -95,10 +97,10 @@ ReturnValue_t CService201HealthCommanding::handleReply(const CommandMessage *rep
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Not used for now, health state already reported by event
|
// Not used for now, health state already reported by event
|
||||||
ReturnValue_t CService201HealthCommanding::prepareHealthSetReply(const CommandMessage *reply) {
|
[[maybe_unused]] ReturnValue_t CService201HealthCommanding::prepareHealthSetReply(
|
||||||
prepareHealthSetReply(reply);
|
const CommandMessage *reply) {
|
||||||
uint8_t health = static_cast<uint8_t>(HealthMessage::getHealth(reply));
|
auto health = static_cast<uint8_t>(HealthMessage::getHealth(reply));
|
||||||
uint8_t oldHealth = static_cast<uint8_t>(HealthMessage::getOldHealth(reply));
|
auto oldHealth = static_cast<uint8_t>(HealthMessage::getOldHealth(reply));
|
||||||
HealthSetReply healthSetReply(health, oldHealth);
|
HealthSetReply healthSetReply(health, oldHealth);
|
||||||
return sendTmPacket(Subservice::REPLY_HEALTH_SET, &healthSetReply);
|
return sendTmPacket(Subservice::REPLY_HEALTH_SET, &healthSetReply);
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user