Compare commits
148 Commits
4b5e3e70f7
...
upstream-d
Author | SHA1 | Date | |
---|---|---|---|
4499c9bf04 | |||
d45cda93b2 | |||
3448292e8a | |||
c83cc492c0 | |||
ece32f88f4 | |||
46cfe65321 | |||
96eb8fc21f | |||
88fa4f1d9d | |||
281f91ec5d | |||
118f1da8dd | |||
8b0508d50a | |||
83de5b4ec1 | |||
fe1c51ae6d | |||
10cc954d27 | |||
73ff9b97db | |||
b0d71597f0 | |||
226f28dc7b | |||
6bfdace512 | |||
16e55a98ce | |||
79f17843d8 | |||
e5e163bdbf | |||
4e4820af05 | |||
3332f68ce7 | |||
54feb77770 | |||
1a07864a5f | |||
3e9d6bdbb9 | |||
c295539c79 | |||
cddf16f941 | |||
a3dee05fe3 | |||
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 | |||
e796f82203 | |||
5b7ca8c13c | |||
031739ef51 | |||
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 | |||
9947a648df | |||
c0f80680ef | |||
7761b66fe2 | |||
acc4c8d975 | |||
fe739aa81a | |||
afe006e234 | |||
95f018a0b0 | |||
8c2105ae0a | |||
ed2c2af4a0 | |||
17771c0497 | |||
82df132e7d | |||
a02619e5a2 | |||
a011e70665 | |||
c05184e1c4 | |||
![]() |
b2252bdc0b | ||
7e61ce1ed2 | |||
fcb6437388 | |||
![]() |
6c1db8473b | ||
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 | |||
665d8cd479 | |||
10398855a9 | |||
d0fec93dc3 | |||
59ab54b2fb | |||
7095999bd2 | |||
7ffb4107d2 | |||
d9d9a28ef8 | |||
![]() |
d95582b81b | ||
c60aa68d00 | |||
9ce59d3c75 | |||
a0dfdfab2c | |||
3e17011087 | |||
f441505476 | |||
7c64797f03 |
34
CHANGELOG.md
34
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,18 @@ 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
|
||||||
|
- HAL Linux Uart: Baudrate and bits per word are enums now, avoiding misconfigurations
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/585
|
||||||
|
- 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
|
||||||
|
- Clock:
|
||||||
|
- `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)
|
||||||
|
|
||||||
## Removed
|
## Removed
|
||||||
|
|
||||||
@@ -35,6 +50,25 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
- 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
|
||||||
|
- `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]
|
||||||
|
|
||||||
|
@@ -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,6 +17,23 @@ 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})
|
||||||
|
|
||||||
|
set(FSFW_ETL_LIB_MAJOR_VERSION 20 CACHE STRING
|
||||||
|
"ETL library major version requirement"
|
||||||
|
)
|
||||||
|
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"
|
||||||
|
)
|
||||||
|
|
||||||
|
set(FSFW_ETL_LIB_NAME etl)
|
||||||
|
|
||||||
option(FSFW_GENERATE_SECTIONS
|
option(FSFW_GENERATE_SECTIONS
|
||||||
"Generate function and data sections. Required to remove unused code" ON
|
"Generate function and data sections. Required to remove unused code" ON
|
||||||
)
|
)
|
||||||
@@ -38,30 +65,28 @@ 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(FSFW_BUILD_UNITTESTS)
|
if(FSFW_BUILD_UNITTESTS)
|
||||||
message(STATUS "Building the FSFW unittests in addition to the static library")
|
message(STATUS "Building the FSFW unittests in addition to the static library")
|
||||||
# Check whether the user has already installed Catch2 first
|
# Check whether the user has already installed Catch2 first
|
||||||
find_package(Catch2 3)
|
find_package(Catch2 ${FSFW_CATCH2_LIB_MAJOR_VERSION})
|
||||||
# Not installed, so use FetchContent to download and provide Catch2
|
# Not installed, so use FetchContent to download and provide Catch2
|
||||||
if(NOT Catch2_FOUND)
|
if(NOT Catch2_FOUND)
|
||||||
|
message(STATUS "Catch2 installation not found. Downloading Catch2 library with FetchContent")
|
||||||
include(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
|
|
||||||
set_target_properties(Catch2 PROPERTIES DEBUG_POSTFIX "")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(FSFW_CONFIG_PATH tests/src/fsfw_tests/unit/testcfg)
|
set(FSFW_CONFIG_PATH tests/src/fsfw_tests/unit/testcfg)
|
||||||
@@ -88,6 +113,42 @@ if(FSFW_BUILD_UNITTESTS)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
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()
|
||||||
|
|
||||||
set(FSFW_CORE_INC_PATH "inc")
|
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)
|
||||||
@@ -100,12 +161,6 @@ target_include_directories(${LIB_FSFW_NAME} INTERFACE
|
|||||||
${CMAKE_CURRENT_BINARY_DIR}
|
${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)
|
||||||
@@ -349,6 +404,7 @@ target_compile_options(${LIB_FSFW_NAME} PRIVATE
|
|||||||
)
|
)
|
||||||
|
|
||||||
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}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
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)
|
||||||
|
@@ -44,6 +44,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 +56,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 +64,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 +72,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 +84,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,
|
||||||
|
@@ -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();
|
||||||
|
@@ -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)
|
||||||
|
@@ -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) {}
|
||||||
|
@@ -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;
|
||||||
|
@@ -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,8 @@
|
|||||||
*/
|
*/
|
||||||
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];
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
|
@@ -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,11 @@ 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,9 @@ 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,7 +160,7 @@ 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();
|
||||||
@@ -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,7 +284,7 @@ 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
|
||||||
@@ -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,7 +117,7 @@ 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
|
||||||
@@ -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, const std::string& udpServerPort = "",
|
||||||
object_id_t tmStoreId = objects::TM_STORE,
|
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;
|
||||||
|
@@ -34,14 +34,14 @@ class Fuse : public SystemObject,
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PCDU_1;
|
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PCDU_1;
|
||||||
//! PSS detected that current on a fuse is totally out of bounds.
|
static const Event FUSE_CURRENT_HIGH = MAKE_EVENT(
|
||||||
static const Event FUSE_CURRENT_HIGH = MAKE_EVENT(1, severity::LOW);
|
1, severity::LOW); //!< PSS detected that current on a fuse is totally out of bounds.
|
||||||
//! PSS detected a fuse that went off.
|
static const Event FUSE_WENT_OFF =
|
||||||
static const Event FUSE_WENT_OFF = MAKE_EVENT(2, severity::LOW);
|
MAKE_EVENT(2, severity::LOW); //!< PSS detected a fuse that went off.
|
||||||
//! PSS detected a fuse that violates its limits.
|
static const Event POWER_ABOVE_HIGH_LIMIT =
|
||||||
static const Event POWER_ABOVE_HIGH_LIMIT = MAKE_EVENT(4, severity::LOW);
|
MAKE_EVENT(4, severity::LOW); //!< PSS detected a fuse that violates its limits.
|
||||||
//! PSS detected a fuse that violates its limits.
|
static const Event POWER_BELOW_LOW_LIMIT =
|
||||||
static const Event POWER_BELOW_LOW_LIMIT = MAKE_EVENT(5, severity::LOW);
|
MAKE_EVENT(5, severity::LOW); //!< PSS detected a fuse that violates its limits.
|
||||||
|
|
||||||
typedef std::list<PowerComponentIF *> DeviceList;
|
typedef std::list<PowerComponentIF *> DeviceList;
|
||||||
Fuse(object_id_t fuseObjectId, uint8_t fuseId, sid_t variableSet, VariableIds ids,
|
Fuse(object_id_t fuseObjectId, uint8_t fuseId, sid_t variableSet, VariableIds ids,
|
||||||
@@ -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,7 @@ 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 = QueueFactory::instance()->createMessageQueue();
|
||||||
commandQueue = QueueFactory::instance()->createMessageQueue(
|
|
||||||
3, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PowerSensor::~PowerSensor() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }
|
PowerSensor::~PowerSensor() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
#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"
|
||||||
/**
|
/**
|
||||||
@@ -38,7 +37,7 @@ 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 void sendSwitchCommand(uint8_t switchNr, ReturnValue_t onOff) const = 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.
|
||||||
*/
|
*/
|
||||||
@@ -52,7 +51,7 @@ class PowerSwitchIF : public HasReturnvaluesIF {
|
|||||||
* - @c SWITCH_OFF if the specified switch is off.
|
* - @c SWITCH_OFF if the specified switch is off.
|
||||||
* - @c RETURN_FAILED if an error occured
|
* - @c RETURN_FAILED if an error occured
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t getSwitchState(power::Switch_t switchNr) const = 0;
|
virtual ReturnValue_t getSwitchState(uint8_t switchNr) const = 0;
|
||||||
/**
|
/**
|
||||||
* get state of a fuse.
|
* get state of a fuse.
|
||||||
* @param fuseNr
|
* @param fuseNr
|
||||||
|
@@ -1,12 +1,19 @@
|
|||||||
#include "definitions.h"
|
|
||||||
#include "fsfw/power/PowerSwitcher.h"
|
#include "fsfw/power/PowerSwitcher.h"
|
||||||
|
|
||||||
#include "fsfw/objectmanager/ObjectManager.h"
|
#include "fsfw/objectmanager/ObjectManager.h"
|
||||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||||
|
|
||||||
PowerSwitcher::PowerSwitcher(PowerSwitchIF* switcher, power::Switch_t setSwitch1,
|
PowerSwitcher::PowerSwitcher(uint8_t setSwitch1, uint8_t setSwitch2,
|
||||||
power::Switch_t setSwitch2, PowerSwitcher::State_t setStartState)
|
PowerSwitcher::State_t setStartState)
|
||||||
: power(switcher), state(setStartState), firstSwitch(setSwitch1), secondSwitch(setSwitch2) {}
|
: state(setStartState), firstSwitch(setSwitch1), secondSwitch(setSwitch2) {}
|
||||||
|
|
||||||
|
ReturnValue_t PowerSwitcher::initialize(object_id_t powerSwitchId) {
|
||||||
|
power = ObjectManager::instance()->get<PowerSwitchIF>(powerSwitchId);
|
||||||
|
if (power == nullptr) {
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
ReturnValue_t PowerSwitcher::getStateOfSwitches() {
|
ReturnValue_t PowerSwitcher::getStateOfSwitches() {
|
||||||
SwitchReturn_t result = howManySwitches();
|
SwitchReturn_t result = howManySwitches();
|
||||||
@@ -45,37 +52,18 @@ void PowerSwitcher::commandSwitches(ReturnValue_t onOff) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PowerSwitcher::turnOn(bool checkCurrentState) {
|
void PowerSwitcher::turnOn() {
|
||||||
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(bool checkCurrentState) {
|
void PowerSwitcher::turnOff() {
|
||||||
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() {
|
|
||||||
if(state == WAIT_OFF or state == WAIT_ON) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
PowerSwitcher::SwitchReturn_t PowerSwitcher::howManySwitches() {
|
PowerSwitcher::SwitchReturn_t PowerSwitcher::howManySwitches() {
|
||||||
if (secondSwitch == power::NO_SWITCH) {
|
if (secondSwitch == NO_SWITCH) {
|
||||||
return ONE_SWITCH;
|
return ONE_SWITCH;
|
||||||
} else {
|
} else {
|
||||||
return TWO_SWITCHES;
|
return TWO_SWITCHES;
|
||||||
|
@@ -14,28 +14,28 @@ class PowerSwitcher : public HasReturnvaluesIF {
|
|||||||
SWITCH_IS_OFF,
|
SWITCH_IS_OFF,
|
||||||
SWITCH_IS_ON,
|
SWITCH_IS_ON,
|
||||||
};
|
};
|
||||||
|
State_t state;
|
||||||
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(uint8_t setSwitch1, uint8_t setSwitch2 = NO_SWITCH,
|
||||||
State_t setStartState = SWITCH_IS_OFF);
|
State_t setStartState = SWITCH_IS_OFF);
|
||||||
void turnOn(bool checkCurrentState = true);
|
ReturnValue_t initialize(object_id_t powerSwitchId);
|
||||||
void turnOff(bool checkCurrentState = true);
|
void turnOn();
|
||||||
bool active();
|
void turnOff();
|
||||||
void doStateMachine();
|
void doStateMachine();
|
||||||
State_t getState();
|
State_t getState();
|
||||||
ReturnValue_t checkSwitchState();
|
ReturnValue_t checkSwitchState();
|
||||||
uint32_t getSwitchDelay();
|
uint32_t getSwitchDelay();
|
||||||
power::Switch_t getFirstSwitch() const;
|
uint8_t getFirstSwitch() const;
|
||||||
power::Switch_t getSecondSwitch() const;
|
uint8_t getSecondSwitch() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
uint8_t firstSwitch;
|
||||||
|
uint8_t secondSwitch;
|
||||||
PowerSwitchIF* power = nullptr;
|
PowerSwitchIF* power = nullptr;
|
||||||
State_t state;
|
|
||||||
power::Switch_t firstSwitch = power::NO_SWITCH;
|
|
||||||
power::Switch_t secondSwitch = power::NO_SWITCH;
|
|
||||||
|
|
||||||
|
static const uint8_t NO_SWITCH = 0xFF;
|
||||||
enum SwitchReturn_t { ONE_SWITCH = 1, TWO_SWITCHES = 2 };
|
enum SwitchReturn_t { ONE_SWITCH = 1, TWO_SWITCHES = 2 };
|
||||||
ReturnValue_t getStateOfSwitches();
|
ReturnValue_t getStateOfSwitches();
|
||||||
void commandSwitches(ReturnValue_t onOff);
|
void commandSwitches(ReturnValue_t onOff);
|
||||||
|
@@ -1,13 +0,0 @@
|
|||||||
#ifndef FSFW_SRC_FSFW_POWER_DEFINITIONS_H_
|
|
||||||
#define FSFW_SRC_FSFW_POWER_DEFINITIONS_H_
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
namespace power {
|
|
||||||
|
|
||||||
using Switch_t = uint8_t;
|
|
||||||
static constexpr Switch_t NO_SWITCH = 0xFF;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#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,9 @@ 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(const CommandMessage *reply) {
|
||||||
prepareHealthSetReply(reply);
|
auto health = static_cast<uint8_t>(HealthMessage::getHealth(reply));
|
||||||
uint8_t health = static_cast<uint8_t>(HealthMessage::getHealth(reply));
|
auto oldHealth = static_cast<uint8_t>(HealthMessage::getOldHealth(reply));
|
||||||
uint8_t 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);
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
#ifndef FSFW_PUS_CSERVICE201HEALTHCOMMANDING_H_
|
#ifndef FSFW_PUS_CSERVICE201HEALTHCOMMANDING_H_
|
||||||
#define FSFW_PUS_CSERVICE201HEALTHCOMMANDING_H_
|
#define FSFW_PUS_CSERVICE201HEALTHCOMMANDING_H_
|
||||||
|
|
||||||
#include "../tmtcservices/CommandingServiceBase.h"
|
#include "fsfw/tmtcservices/CommandingServiceBase.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Custom PUS service to set health of all objects
|
* @brief Custom PUS service to set health of all objects
|
||||||
@@ -21,7 +21,7 @@ class CService201HealthCommanding : public CommandingServiceBase {
|
|||||||
public:
|
public:
|
||||||
CService201HealthCommanding(object_id_t objectId, uint16_t apid, uint8_t serviceId,
|
CService201HealthCommanding(object_id_t objectId, uint16_t apid, uint8_t serviceId,
|
||||||
uint8_t numParallelCommands = 4, uint16_t commandTimeoutSeconds = 60);
|
uint8_t numParallelCommands = 4, uint16_t commandTimeoutSeconds = 60);
|
||||||
virtual ~CService201HealthCommanding();
|
~CService201HealthCommanding() override = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/* CSB abstract function implementations */
|
/* CSB abstract function implementations */
|
||||||
@@ -38,12 +38,10 @@ class CService201HealthCommanding : public CommandingServiceBase {
|
|||||||
bool *isStep) override;
|
bool *isStep) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ReturnValue_t checkAndAcquireTargetID(object_id_t *objectIdToSet, const uint8_t *tcData,
|
static ReturnValue_t checkInterfaceAndAcquireMessageQueue(MessageQueueId_t *MessageQueueToSet,
|
||||||
size_t tcDataLen);
|
const object_id_t *objectId);
|
||||||
ReturnValue_t checkInterfaceAndAcquireMessageQueue(MessageQueueId_t *MessageQueueToSet,
|
|
||||||
object_id_t *objectId);
|
|
||||||
|
|
||||||
ReturnValue_t prepareHealthSetReply(const CommandMessage *reply);
|
[[maybe_unused]] ReturnValue_t prepareHealthSetReply(const CommandMessage *reply);
|
||||||
|
|
||||||
enum Subservice {
|
enum Subservice {
|
||||||
//! [EXPORT] : [TC] Set health of target object
|
//! [EXPORT] : [TC] Set health of target object
|
||||||
|
@@ -16,9 +16,7 @@ Service1TelecommandVerification::Service1TelecommandVerification(object_id_t obj
|
|||||||
apid(apid),
|
apid(apid),
|
||||||
serviceId(serviceId),
|
serviceId(serviceId),
|
||||||
targetDestination(targetDestination) {
|
targetDestination(targetDestination) {
|
||||||
auto mqArgs = MqArgs(objectId, static_cast<void*>(this));
|
tmQueue = QueueFactory::instance()->createMessageQueue(messageQueueDepth);
|
||||||
tmQueue = QueueFactory::instance()->createMessageQueue(
|
|
||||||
messageQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Service1TelecommandVerification::~Service1TelecommandVerification() {
|
Service1TelecommandVerification::~Service1TelecommandVerification() {
|
||||||
|
@@ -43,7 +43,7 @@ class Service3Housekeeping : public CommandingServiceBase, public AcceptsHkPacke
|
|||||||
CommandMessage* optionalNextCommand, object_id_t objectId,
|
CommandMessage* optionalNextCommand, object_id_t objectId,
|
||||||
bool* isStep) override;
|
bool* isStep) override;
|
||||||
|
|
||||||
virtual MessageQueueId_t getHkQueue() const;
|
virtual MessageQueueId_t getHkQueue() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class Subservice {
|
enum class Subservice {
|
||||||
|
@@ -12,9 +12,7 @@ Service5EventReporting::Service5EventReporting(object_id_t objectId, uint16_t ap
|
|||||||
uint32_t messageQueueDepth)
|
uint32_t messageQueueDepth)
|
||||||
: PusServiceBase(objectId, apid, serviceId),
|
: PusServiceBase(objectId, apid, serviceId),
|
||||||
maxNumberReportsPerCycle(maxNumberReportsPerCycle) {
|
maxNumberReportsPerCycle(maxNumberReportsPerCycle) {
|
||||||
auto mqArgs = MqArgs(objectId, static_cast<void*>(this));
|
eventQueue = QueueFactory::instance()->createMessageQueue(messageQueueDepth);
|
||||||
eventQueue = QueueFactory::instance()->createMessageQueue(
|
|
||||||
messageQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Service5EventReporting::~Service5EventReporting() {
|
Service5EventReporting::~Service5EventReporting() {
|
||||||
@@ -38,6 +36,9 @@ ReturnValue_t Service5EventReporting::performService() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::warning << "Service5EventReporting::generateEventReport: Too many events" << std::endl;
|
||||||
|
#endif
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +87,7 @@ ReturnValue_t Service5EventReporting::handleRequest(uint8_t subservice) {
|
|||||||
// to be registered to the event manager to listen for events.
|
// to be registered to the event manager to listen for events.
|
||||||
ReturnValue_t Service5EventReporting::initialize() {
|
ReturnValue_t Service5EventReporting::initialize() {
|
||||||
EventManagerIF* manager = ObjectManager::instance()->get<EventManagerIF>(objects::EVENT_MANAGER);
|
EventManagerIF* manager = ObjectManager::instance()->get<EventManagerIF>(objects::EVENT_MANAGER);
|
||||||
if (manager == nullptr) {
|
if (manager == NULL) {
|
||||||
return RETURN_FAILED;
|
return RETURN_FAILED;
|
||||||
}
|
}
|
||||||
// register Service 5 as listener for events
|
// register Service 5 as listener for events
|
||||||
|
@@ -41,7 +41,7 @@
|
|||||||
class Service5EventReporting : public PusServiceBase {
|
class Service5EventReporting : public PusServiceBase {
|
||||||
public:
|
public:
|
||||||
Service5EventReporting(object_id_t objectId, uint16_t apid, uint8_t serviceId,
|
Service5EventReporting(object_id_t objectId, uint16_t apid, uint8_t serviceId,
|
||||||
size_t maxNumberReportsPerCycle, uint32_t messageQueueDepth);
|
size_t maxNumberReportsPerCycle = 10, uint32_t messageQueueDepth = 10);
|
||||||
virtual ~Service5EventReporting();
|
virtual ~Service5EventReporting();
|
||||||
|
|
||||||
/***
|
/***
|
||||||
|
@@ -6,10 +6,10 @@
|
|||||||
class Service9TimeManagement : public PusServiceBase {
|
class Service9TimeManagement : public PusServiceBase {
|
||||||
public:
|
public:
|
||||||
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PUS_SERVICE_9;
|
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PUS_SERVICE_9;
|
||||||
//!< Clock has been set. P1: New Uptime. P2: Old Uptime
|
static constexpr Event CLOCK_SET =
|
||||||
static constexpr Event CLOCK_SET = MAKE_EVENT(0, severity::INFO);
|
MAKE_EVENT(0, severity::INFO); //!< Clock has been set. P1: New Uptime. P2: Old Uptime
|
||||||
//!< Clock could not be set. P1: Returncode.
|
static constexpr Event CLOCK_SET_FAILURE =
|
||||||
static constexpr Event CLOCK_SET_FAILURE = MAKE_EVENT(1, severity::LOW);
|
MAKE_EVENT(1, severity::LOW); //!< Clock could not be set. P1: Returncode.
|
||||||
|
|
||||||
static constexpr uint8_t CLASS_ID = CLASS_ID::PUS_SERVICE_9;
|
static constexpr uint8_t CLASS_ID = CLASS_ID::PUS_SERVICE_9;
|
||||||
|
|
||||||
|
@@ -30,11 +30,11 @@ ReturnValue_t Subsystem::checkSequence(HybridIterator<ModeListEntry> iter,
|
|||||||
return FALLBACK_SEQUENCE_DOES_NOT_EXIST;
|
return FALLBACK_SEQUENCE_DOES_NOT_EXIST;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iter.value == NULL) {
|
if (iter.value == nullptr) {
|
||||||
return NO_TARGET_TABLE;
|
return NO_TARGET_TABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; iter.value != NULL; ++iter) {
|
for (; iter.value != nullptr; ++iter) {
|
||||||
if (!existsModeTable(iter->getTableId())) {
|
if (!existsModeTable(iter->getTableId())) {
|
||||||
return TABLE_DOES_NOT_EXIST;
|
return TABLE_DOES_NOT_EXIST;
|
||||||
} else {
|
} else {
|
||||||
@@ -66,13 +66,18 @@ HybridIterator<ModeListEntry> Subsystem::getCurrentTable() {
|
|||||||
void Subsystem::performChildOperation() {
|
void Subsystem::performChildOperation() {
|
||||||
if (isInTransition) {
|
if (isInTransition) {
|
||||||
if (commandsOutstanding <= 0) { // all children of the current table were commanded and replied
|
if (commandsOutstanding <= 0) { // all children of the current table were commanded and replied
|
||||||
if (currentSequenceIterator.value == NULL) { // we're through with this sequence
|
if (currentSequenceIterator.value == nullptr) { // we're through with this sequence
|
||||||
if (checkStateAgainstTable(currentTargetTable, targetSubmode) == RETURN_OK) {
|
if (checkStateAgainstTable(currentTargetTable, targetSubmode) == RETURN_OK) {
|
||||||
setMode(targetMode, targetSubmode);
|
setMode(targetMode, targetSubmode);
|
||||||
isInTransition = false;
|
isInTransition = false;
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
transitionFailed(TARGET_TABLE_NOT_REACHED, getSequence(targetMode)->getTableId());
|
Mode_t tableId = 0;
|
||||||
|
auto seq = getSequence(targetMode);
|
||||||
|
if (seq.value != nullptr) {
|
||||||
|
tableId = seq->getTableId();
|
||||||
|
}
|
||||||
|
transitionFailed(TARGET_TABLE_NOT_REACHED, tableId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -248,10 +253,13 @@ ReturnValue_t Subsystem::handleCommandMessage(CommandMessage *message) {
|
|||||||
case ModeSequenceMessage::READ_TABLE: {
|
case ModeSequenceMessage::READ_TABLE: {
|
||||||
ReturnValue_t result;
|
ReturnValue_t result;
|
||||||
Mode_t table = ModeSequenceMessage::getSequenceId(message);
|
Mode_t table = ModeSequenceMessage::getSequenceId(message);
|
||||||
EntryPointer *entry = NULL;
|
EntryPointer *entry = nullptr;
|
||||||
result = modeTables.find(table, &entry);
|
result = modeTables.find(table, &entry);
|
||||||
if (result != RETURN_OK) {
|
if (result != RETURN_OK or entry == nullptr) {
|
||||||
replyToCommand(result, 0);
|
replyToCommand(result, 0);
|
||||||
|
if (entry == nullptr) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SerializeIF *elements[2];
|
SerializeIF *elements[2];
|
||||||
@@ -299,6 +307,11 @@ void Subsystem::replyToCommand(ReturnValue_t status, uint32_t parameter) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Subsystem::addSequence(SequenceEntry sequence) {
|
||||||
|
return addSequence(sequence.table, sequence.mode, sequence.fallbackMode, sequence.inStore,
|
||||||
|
sequence.preInit);
|
||||||
|
}
|
||||||
|
|
||||||
ReturnValue_t Subsystem::addSequence(ArrayList<ModeListEntry> *sequence, Mode_t id,
|
ReturnValue_t Subsystem::addSequence(ArrayList<ModeListEntry> *sequence, Mode_t id,
|
||||||
Mode_t fallbackSequence, bool inStore, bool preInit) {
|
Mode_t fallbackSequence, bool inStore, bool preInit) {
|
||||||
ReturnValue_t result;
|
ReturnValue_t result;
|
||||||
@@ -342,6 +355,10 @@ ReturnValue_t Subsystem::addSequence(ArrayList<ModeListEntry> *sequence, Mode_t
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Subsystem::addTable(TableEntry table) {
|
||||||
|
return addTable(table.table, table.mode, table.inStore, table.preInit);
|
||||||
|
}
|
||||||
|
|
||||||
ReturnValue_t Subsystem::addTable(ArrayList<ModeListEntry> *table, Mode_t id, bool inStore,
|
ReturnValue_t Subsystem::addTable(ArrayList<ModeListEntry> *table, Mode_t id, bool inStore,
|
||||||
bool preInit) {
|
bool preInit) {
|
||||||
ReturnValue_t result;
|
ReturnValue_t result;
|
||||||
@@ -450,6 +467,7 @@ ReturnValue_t Subsystem::initialize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mode = initialMode;
|
mode = initialMode;
|
||||||
|
submode = initSubmode;
|
||||||
|
|
||||||
return RETURN_OK;
|
return RETURN_OK;
|
||||||
}
|
}
|
||||||
@@ -587,7 +605,10 @@ ReturnValue_t Subsystem::checkObjectConnections() {
|
|||||||
return RETURN_OK;
|
return RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Subsystem::setInitialMode(Mode_t mode) { initialMode = mode; }
|
void Subsystem::setInitialMode(Mode_t mode, Submode_t submode) {
|
||||||
|
this->initialMode = mode;
|
||||||
|
this->initSubmode = submode;
|
||||||
|
}
|
||||||
|
|
||||||
void Subsystem::cantKeepMode() {
|
void Subsystem::cantKeepMode() {
|
||||||
ReturnValue_t result;
|
ReturnValue_t result;
|
||||||
|
@@ -1,23 +1,40 @@
|
|||||||
#ifndef FSFW_SUBSYSTEM_SUBSYSTEM_H_
|
#ifndef FSFW_SUBSYSTEM_SUBSYSTEM_H_
|
||||||
#define FSFW_SUBSYSTEM_SUBSYSTEM_H_
|
#define FSFW_SUBSYSTEM_SUBSYSTEM_H_
|
||||||
|
|
||||||
#include <FSFWConfig.h>
|
|
||||||
|
|
||||||
#include "../container/FixedArrayList.h"
|
#include "../container/FixedArrayList.h"
|
||||||
#include "../container/FixedMap.h"
|
#include "../container/FixedMap.h"
|
||||||
#include "../container/HybridIterator.h"
|
#include "../container/HybridIterator.h"
|
||||||
#include "../container/SinglyLinkedList.h"
|
#include "../container/SinglyLinkedList.h"
|
||||||
#include "../serialize/SerialArrayListAdapter.h"
|
#include "../serialize/SerialArrayListAdapter.h"
|
||||||
#include "SubsystemBase.h"
|
#include "SubsystemBase.h"
|
||||||
|
#include "fsfw/FSFW.h"
|
||||||
#include "modes/ModeDefinitions.h"
|
#include "modes/ModeDefinitions.h"
|
||||||
|
|
||||||
|
struct TableSequenceBase {
|
||||||
|
public:
|
||||||
|
TableSequenceBase(Mode_t mode, ArrayList<ModeListEntry> *table) : mode(mode), table(table){};
|
||||||
|
Mode_t mode;
|
||||||
|
ArrayList<ModeListEntry> *table;
|
||||||
|
bool inStore = false;
|
||||||
|
bool preInit = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TableEntry : public TableSequenceBase {
|
||||||
|
public:
|
||||||
|
TableEntry(Mode_t mode, ArrayList<ModeListEntry> *table) : TableSequenceBase(mode, table){};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SequenceEntry : public TableSequenceBase {
|
||||||
|
public:
|
||||||
|
SequenceEntry(Mode_t mode, ArrayList<ModeListEntry> *table, Mode_t fallbackMode)
|
||||||
|
: TableSequenceBase(mode, table), fallbackMode(fallbackMode) {}
|
||||||
|
|
||||||
|
Mode_t fallbackMode;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This class extends the SubsystemBase to perform the management of mode tables
|
* @brief TODO: documentation missing
|
||||||
* and mode sequences
|
|
||||||
* @details
|
* @details
|
||||||
* This class is able to use mode tables and sequences to command all its children into the
|
|
||||||
* right mode. Fallback sequences can be used to handle failed transitions or have a fallback
|
|
||||||
* in case a component can't keep its current mode.
|
|
||||||
*/
|
*/
|
||||||
class Subsystem : public SubsystemBase, public HasModeSequenceIF {
|
class Subsystem : public SubsystemBase, public HasModeSequenceIF {
|
||||||
public:
|
public:
|
||||||
@@ -49,13 +66,15 @@ class Subsystem : public SubsystemBase, public HasModeSequenceIF {
|
|||||||
uint32_t maxNumberOfTables);
|
uint32_t maxNumberOfTables);
|
||||||
virtual ~Subsystem();
|
virtual ~Subsystem();
|
||||||
|
|
||||||
|
ReturnValue_t addSequence(SequenceEntry sequence);
|
||||||
ReturnValue_t addSequence(ArrayList<ModeListEntry> *sequence, Mode_t id, Mode_t fallbackSequence,
|
ReturnValue_t addSequence(ArrayList<ModeListEntry> *sequence, Mode_t id, Mode_t fallbackSequence,
|
||||||
bool inStore = true, bool preInit = true);
|
bool inStore = true, bool preInit = true);
|
||||||
|
|
||||||
|
ReturnValue_t addTable(TableEntry table);
|
||||||
ReturnValue_t addTable(ArrayList<ModeListEntry> *table, Mode_t id, bool inStore = true,
|
ReturnValue_t addTable(ArrayList<ModeListEntry> *table, Mode_t id, bool inStore = true,
|
||||||
bool preInit = true);
|
bool preInit = true);
|
||||||
|
|
||||||
void setInitialMode(Mode_t mode);
|
void setInitialMode(Mode_t mode, Submode_t submode = SUBMODE_NONE);
|
||||||
|
|
||||||
virtual ReturnValue_t initialize() override;
|
virtual ReturnValue_t initialize() override;
|
||||||
|
|
||||||
@@ -94,6 +113,7 @@ class Subsystem : public SubsystemBase, public HasModeSequenceIF {
|
|||||||
Submode_t targetSubmode;
|
Submode_t targetSubmode;
|
||||||
|
|
||||||
Mode_t initialMode = 0;
|
Mode_t initialMode = 0;
|
||||||
|
Submode_t initSubmode = SUBMODE_NONE;
|
||||||
|
|
||||||
HybridIterator<ModeListEntry> currentSequenceIterator;
|
HybridIterator<ModeListEntry> currentSequenceIterator;
|
||||||
|
|
||||||
@@ -131,18 +151,18 @@ class Subsystem : public SubsystemBase, public HasModeSequenceIF {
|
|||||||
|
|
||||||
ReturnValue_t deleteTable(Mode_t id);
|
ReturnValue_t deleteTable(Mode_t id);
|
||||||
|
|
||||||
virtual void performChildOperation();
|
virtual void performChildOperation() override;
|
||||||
|
|
||||||
virtual ReturnValue_t handleCommandMessage(CommandMessage *message);
|
virtual ReturnValue_t handleCommandMessage(CommandMessage *message) override;
|
||||||
|
|
||||||
bool isFallbackSequence(Mode_t SequenceId);
|
bool isFallbackSequence(Mode_t SequenceId);
|
||||||
|
|
||||||
bool isTableUsed(Mode_t tableId);
|
bool isTableUsed(Mode_t tableId);
|
||||||
|
|
||||||
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
||||||
uint32_t *msToReachTheMode);
|
uint32_t *msToReachTheMode) override;
|
||||||
|
|
||||||
virtual void startTransition(Mode_t mode, Submode_t submode);
|
virtual void startTransition(Mode_t mode, Submode_t submode) override;
|
||||||
|
|
||||||
void sendSerializablesAsCommandMessage(Command_t command, SerializeIF **elements, uint8_t count);
|
void sendSerializablesAsCommandMessage(Command_t command, SerializeIF **elements, uint8_t count);
|
||||||
|
|
||||||
|
@@ -8,13 +8,11 @@ SubsystemBase::SubsystemBase(object_id_t setObjectId, object_id_t parent, Mode_t
|
|||||||
uint16_t commandQueueDepth)
|
uint16_t commandQueueDepth)
|
||||||
: SystemObject(setObjectId),
|
: SystemObject(setObjectId),
|
||||||
mode(initialMode),
|
mode(initialMode),
|
||||||
|
commandQueue(QueueFactory::instance()->createMessageQueue(commandQueueDepth,
|
||||||
|
CommandMessage::MAX_MESSAGE_SIZE)),
|
||||||
healthHelper(this, setObjectId),
|
healthHelper(this, setObjectId),
|
||||||
modeHelper(this),
|
modeHelper(this),
|
||||||
parentId(parent) {
|
parentId(parent) {}
|
||||||
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
|
|
||||||
commandQueue = QueueFactory::instance()->createMessageQueue(
|
|
||||||
commandQueueDepth, CommandMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
SubsystemBase::~SubsystemBase() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }
|
SubsystemBase::~SubsystemBase() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }
|
||||||
|
|
||||||
@@ -33,9 +31,8 @@ ReturnValue_t SubsystemBase::registerChild(object_id_t objectId) {
|
|||||||
info.mode = MODE_OFF;
|
info.mode = MODE_OFF;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// intentional to force an initial command during system startup
|
|
||||||
info.commandQueue = child->getCommandQueue();
|
info.commandQueue = child->getCommandQueue();
|
||||||
info.mode = HasModesIF::MODE_UNDEFINED;
|
info.mode = -1; // intentional to force an initial command during system startup
|
||||||
}
|
}
|
||||||
|
|
||||||
info.submode = SUBMODE_NONE;
|
info.submode = SUBMODE_NONE;
|
||||||
|
@@ -15,14 +15,7 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @defgroup subsystems Subsystem Objects
|
* @defgroup subsystems Subsystem Objects
|
||||||
* All Subsystem and Assemblies can derive from this class. It contains helper classes to
|
* Contains all Subsystem and Assemblies
|
||||||
* perform mode and health handling, which allows OBSW developers to build a mode tree for
|
|
||||||
* the whole satellite.
|
|
||||||
*
|
|
||||||
* Aside from setting up a mode tree and being able to executing mode tables, this class does not
|
|
||||||
* provide an implementation on what to do with the features. To build a mode tree, helper classes
|
|
||||||
* like the #AssemblyBase or the #Subsystem class extend and use the functionality of the base
|
|
||||||
* class.
|
|
||||||
*/
|
*/
|
||||||
class SubsystemBase : public SystemObject,
|
class SubsystemBase : public SystemObject,
|
||||||
public HasModesIF,
|
public HasModesIF,
|
||||||
@@ -103,7 +96,6 @@ class SubsystemBase : public SystemObject,
|
|||||||
Submode_t targetSubmode);
|
Submode_t targetSubmode);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function takes care of sending all according mode commands specified inside a mode table.
|
|
||||||
* We need to know the target Submode, as children are able to inherit the submode
|
* We need to know the target Submode, as children are able to inherit the submode
|
||||||
* Still, we have a default for all child implementations which do not use submode inheritance
|
* Still, we have a default for all child implementations which do not use submode inheritance
|
||||||
*/
|
*/
|
||||||
@@ -137,9 +129,9 @@ class SubsystemBase : public SystemObject,
|
|||||||
|
|
||||||
virtual void getMode(Mode_t *mode, Submode_t *submode) override;
|
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) override;
|
||||||
|
|
||||||
virtual void modeChanged();
|
virtual void modeChanged();
|
||||||
};
|
};
|
||||||
|
@@ -26,21 +26,25 @@ class PeriodicTaskIF {
|
|||||||
virtual ReturnValue_t startTask() = 0;
|
virtual ReturnValue_t startTask() = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a component (object) to a periodic task. The pointer to the
|
* Add a component (object) to a periodic task.
|
||||||
* task can be set optionally
|
|
||||||
* @param object
|
* @param object
|
||||||
* Add an object to the task. The most important case is to add an
|
* Add an object to the task. The object needs to implement ExecutableObjectIF
|
||||||
* executable object with a function which will be called regularly
|
|
||||||
* (see ExecutableObjectIF)
|
|
||||||
* @param setTaskIF
|
|
||||||
* Can be used to specify whether the task object pointer is passed
|
|
||||||
* to the component.
|
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t addComponent(object_id_t object) {
|
virtual ReturnValue_t addComponent(object_id_t object) {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an object to a periodic task.
|
||||||
|
* @param object
|
||||||
|
* Add an object to the task.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
virtual ReturnValue_t addComponent(ExecutableObjectIF* object) {
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
};
|
||||||
|
|
||||||
virtual ReturnValue_t sleepFor(uint32_t ms) = 0;
|
virtual ReturnValue_t sleepFor(uint32_t ms) = 0;
|
||||||
|
|
||||||
virtual uint32_t getPeriodMs() const = 0;
|
virtual uint32_t getPeriodMs() const = 0;
|
||||||
|
@@ -5,9 +5,7 @@
|
|||||||
#include "fsfw/tmtcservices/TmTcMessage.h"
|
#include "fsfw/tmtcservices/TmTcMessage.h"
|
||||||
|
|
||||||
TcDistributor::TcDistributor(object_id_t objectId) : SystemObject(objectId) {
|
TcDistributor::TcDistributor(object_id_t objectId) : SystemObject(objectId) {
|
||||||
auto mqArgs = MqArgs(objectId);
|
tcQueue = QueueFactory::instance()->createMessageQueue(DISTRIBUTER_MAX_PACKETS);
|
||||||
tcQueue = QueueFactory::instance()->createMessageQueue(
|
|
||||||
DISTRIBUTER_MAX_PACKETS, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TcDistributor::~TcDistributor() { QueueFactory::instance()->deleteMessageQueue(tcQueue); }
|
TcDistributor::~TcDistributor() { QueueFactory::instance()->deleteMessageQueue(tcQueue); }
|
||||||
|
@@ -4,13 +4,14 @@
|
|||||||
|
|
||||||
AbstractTemperatureSensor::AbstractTemperatureSensor(object_id_t setObjectid,
|
AbstractTemperatureSensor::AbstractTemperatureSensor(object_id_t setObjectid,
|
||||||
ThermalModuleIF *thermalModule)
|
ThermalModuleIF *thermalModule)
|
||||||
: SystemObject(setObjectid), healthHelper(this, setObjectid), parameterHelper(this) {
|
: SystemObject(setObjectid),
|
||||||
if (thermalModule != nullptr) {
|
commandQueue(NULL),
|
||||||
|
healthHelper(this, setObjectid),
|
||||||
|
parameterHelper(this) {
|
||||||
|
if (thermalModule != NULL) {
|
||||||
thermalModule->registerSensor(this);
|
thermalModule->registerSensor(this);
|
||||||
}
|
}
|
||||||
auto mqArgs = MqArgs(setObjectid, static_cast<void *>(this));
|
commandQueue = QueueFactory::instance()->createMessageQueue();
|
||||||
commandQueue = QueueFactory::instance()->createMessageQueue(
|
|
||||||
3, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractTemperatureSensor::~AbstractTemperatureSensor() {
|
AbstractTemperatureSensor::~AbstractTemperatureSensor() {
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user