Compare commits
315 Commits
v4.0.0
...
e949368b06
Author | SHA1 | Date | |
---|---|---|---|
e949368b06 | |||
4d49cb6a3c | |||
935a8e13a5 | |||
5ff88129b8 | |||
ce17be63f4 | |||
2734d9d758 | |||
c45328b34d | |||
478b305fbe | |||
28e93696df | |||
942d1e5e4b | |||
95f018a0b0 | |||
8c2105ae0a | |||
ed2c2af4a0 | |||
82df132e7d | |||
a02619e5a2 | |||
6ce09e968d | |||
290db6ccad | |||
94ed582297 | |||
47ced1efac | |||
85a6e4b129 | |||
f94bc02b6c | |||
5bda877d97 | |||
51e7f1c2f2 | |||
a11d7455df | |||
4dc903fe20 | |||
3325cc18fc | |||
43917d98c0 | |||
e3ffcae3e0 | |||
0677de39aa | |||
aded4fae1e | |||
a011e70665 | |||
7df51f7202 | |||
7530c44849 | |||
e4c6a69f77 | |||
761a0c9bac | |||
7e61ce1ed2 | |||
518666f822 | |||
318cd8e244 | |||
1bc7a91869 | |||
8e26e287c3 | |||
ce2f7c4fdf | |||
b3d2d440d7 | |||
![]() |
fbf9626fde | ||
fcb6437388 | |||
29cf8c9009 | |||
61d0815de8 | |||
127fbeb980 | |||
b42987059a | |||
c2581ff4f5 | |||
7b6f68c509 | |||
![]() |
532607bf8f | ||
![]() |
a230dc4313 | ||
4be45adae6 | |||
0d7d2203d2 | |||
cde184f428 | |||
df3794dfd8 | |||
d02d5c351d | |||
febecd4b30 | |||
964e311d8b | |||
d43caa8296 | |||
916ed3f56a | |||
3ea9f999b7 | |||
79f3c7324a | |||
23af170229 | |||
b32d1da421 | |||
6f0362b956 | |||
60972228ef | |||
6ea1eabb2d | |||
283a37dccc | |||
acf0cdfba3 | |||
a01002aa5d | |||
![]() |
b52f19254b | ||
79615e47e4 | |||
e6130263ef | |||
6895dbcc81 | |||
d9d9a28ef8 | |||
![]() |
d95582b81b | ||
c60aa68d00 | |||
4b5e3e70f7 | |||
a0dfdfab2c | |||
3e17011087 | |||
f441505476 | |||
7c64797f03 | |||
bbe21e7e89 | |||
2823420c46 | |||
6dd6f28db0 | |||
d791fc87b7 | |||
16f2fa9327 | |||
927041209b | |||
![]() |
bac8b40880 | ||
![]() |
caf78835b2 | ||
b6ed45a85c | |||
ddc1cdb1f5 | |||
543daaa95a | |||
38c87fdeb2 | |||
5ca5fe4040 | |||
![]() |
1b7e0371c3 | ||
e08bdd3e35 | |||
d2dd16aef3 | |||
b7a617dab3 | |||
bc95e7c886 | |||
fca43b3d34 | |||
48c5c3fbd5 | |||
b694aea100 | |||
6998626ad4 | |||
![]() |
d4ade5e885 | ||
24ad858b64 | |||
288d453978 | |||
522cbc7f3d | |||
ce5bcc5897 | |||
97c93afeff | |||
8704b9ab06 | |||
5a1585bd00 | |||
5d6de90859 | |||
378c6c8006 | |||
f4922a8686 | |||
0bdcb40609 | |||
fec5f83f4f | |||
17262a1da9 | |||
e684680d60 | |||
aa5d1042f0 | |||
b5d6b9745f | |||
60639f56dc | |||
3aa0bbde68 | |||
14ac852b7e | |||
6b1a81ee92 | |||
3779b44813 | |||
949549178a | |||
7daa9812ff | |||
97bc71a3ff | |||
06577ed78a | |||
ca508bfe61 | |||
b27f3b84aa | |||
345a799031 | |||
9509847b84 | |||
45b51f9ac8 | |||
445d5dd6f0 | |||
d5ff6da40b | |||
e498136273 | |||
238baa8597 | |||
47d158156b | |||
d63c01b96f | |||
3b497dbb8d | |||
bf733162eb | |||
7932afc315 | |||
d1e3dc4d49 | |||
73f0b9c0dc | |||
b5e55f64b0 | |||
77e5fba7fd | |||
ca70c8c614 | |||
7ca6d1a695 | |||
cc3210f366 | |||
155d66e534 | |||
d4c76a7e46 | |||
dba3c27b99 | |||
202cfc6dbb | |||
84f95e8d76 | |||
6de4798805 | |||
82a645deba | |||
8b1c277c58 | |||
14620fdd72 | |||
89c1878622 | |||
d6856fc54a | |||
e5a9cab34e | |||
5f23f709cc | |||
a4f97a7ba7 | |||
8b1af232c3 | |||
983fa346b3 | |||
32f420c4f0 | |||
41a82e923c | |||
5ddac36314 | |||
d06eecf9b0 | |||
a7cb2d4354 | |||
7571987a1d | |||
d6c1041133 | |||
5912ddd2a2 | |||
7db11588b4 | |||
c88b931ef1 | |||
10ffa2f44a | |||
dbe31dd339 | |||
14b44f8bb2 | |||
117747970d | |||
3c53e2c259 | |||
45f0d7fd45 | |||
c6540650e2 | |||
aebab4c73c | |||
c3c2e1c0dd | |||
4e6c1cb72a | |||
f659f13759 | |||
e2eb6a46b6 | |||
75c56280ad | |||
0ccaf27fcb | |||
95078e1103 | |||
e05e203c83 | |||
8920255565 | |||
ac036b2a70 | |||
2d12618c96 | |||
2d9216ba19 | |||
2fed161eff | |||
68ca6fd122 | |||
33e9592659 | |||
19d217e3b9 | |||
af286d3bc6 | |||
4cf2a384f3 | |||
27267b7cb0 | |||
20928732ec | |||
505e00c067 | |||
68225586d2 | |||
6d825a1aa6 | |||
a8426750f2 | |||
2635f39344 | |||
89327463e3 | |||
fa73ad6731 | |||
cf45eca100 | |||
c0fa365f8f | |||
9d9f19781d | |||
f4520ea346 | |||
331aa9442d | |||
bbacdc5cac | |||
28b28b5684 | |||
afd3a942e2 | |||
729bcc4aaf | |||
a6c0f3fef5 | |||
6e0b90696d | |||
![]() |
eacb4ac407 | ||
09c1918c1f | |||
123f2ff360 | |||
0e8328fca3 | |||
1ef3dae72e | |||
32381a7872 | |||
09815f5cce | |||
f6357b4531 | |||
a10e5c6ed4 | |||
d6d13eec95 | |||
457bc6609e | |||
e75155c329 | |||
d4e48006f2 | |||
d6508e23b6 | |||
2cb254a556 | |||
f99f5ed730 | |||
7ce2c1b624 | |||
5f7e384442 | |||
56d0c8c616 | |||
5ff0f8ea10 | |||
4747e54c5d | |||
2e230daa14 | |||
e909c6b6f7 | |||
d88d7c938f | |||
fdc8a3d4f7 | |||
389641f8fd | |||
e5e85bcff9 | |||
4862edfdb5 | |||
a50b52df51 | |||
eac7e6db07 | |||
0c4835bfb5 | |||
aebd4817b8 | |||
9c2ceb4a9f | |||
b440c30223 | |||
68ace0b74a | |||
d119479c0a | |||
6739890d53 | |||
90b8ad1e6d | |||
025f79fcb4 | |||
3966b656e9 | |||
6fb64f9ada | |||
3a5881a0cb | |||
2f1b923009 | |||
1e982ec00b | |||
701135e2a6 | |||
19f8e41c7f | |||
c4a055986c | |||
d74a373f1d | |||
cf69af4e7e | |||
45ea09291a | |||
b7f3eff742 | |||
508979d32d | |||
0d66569687 | |||
a5871ed0b1 | |||
a12e98d948 | |||
bd05afbddd | |||
b3482eba24 | |||
9e92afbf07 | |||
0d6d44f72f | |||
81f5b0c3bf | |||
062e93fd88 | |||
c20bf31d5d | |||
![]() |
3c06d2dbbb | ||
![]() |
018d814f29 | ||
![]() |
c0648a789b | ||
![]() |
9579e94a71 | ||
![]() |
235fd79dfb | ||
83635d3667 | |||
581ae4c990 | |||
32a9e0c704 | |||
940c53eba6 | |||
0d4bd856bd | |||
b7f6a6961b | |||
a910a05541 | |||
973996e102 | |||
b3aee76d91 | |||
b3151a0ba0 | |||
fca48257b7 | |||
8f95b03e6a | |||
527dba9a9d | |||
22cd38fffd | |||
1a518109d0 | |||
8030d9ac1b | |||
992c05df56 | |||
6698d283b6 | |||
33386550cf | |||
3a65c0db91 | |||
41614303d7 | |||
783176848a | |||
07cb980e06 | |||
d8c5bd125e |
30
CHANGELOG.md
30
CHANGELOG.md
@@ -8,6 +8,36 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
# [unreleased]
|
||||
|
||||
# [v5.0.0]
|
||||
|
||||
## Changes
|
||||
|
||||
- HAL Linux SPI: Set the Clock Default State when setting new SPI speed
|
||||
and mode
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/573
|
||||
- GPIO HAL: `Direction`, `GpioOperation` and `Levels` are enum classes now, which prevents
|
||||
name clashes with Windows defines.
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/572
|
||||
- New CMake option `FSFW_HAL_LINUX_ADD_LIBGPIOD` to specifically exclude `gpiod` code.
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/572
|
||||
- HAL Devicehandlers: Periodic printout is run-time configurable now
|
||||
- `oneShotAction` flag in the `TestTask` class is not static anymore
|
||||
- HAL Linux Uart: Baudrate and bits per word are enums now, avoiding misconfigurations
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/585
|
||||
|
||||
## Removed
|
||||
|
||||
- Removed the `HkSwitchHelper`. This module should not be needed anymore, now that the local
|
||||
datapools have been implemented.
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/557
|
||||
|
||||
## Additions
|
||||
|
||||
- Linux HAL: Add wiretapping option for I2C. Enabled with `FSFW_HAL_I2C_WIRETAPPING` defined to 1
|
||||
- Dedicated Version class and constant `fsfw::FSFW_VERSION` containing version information
|
||||
inside `fsfw/version.h`
|
||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/559
|
||||
|
||||
# [v4.0.0]
|
||||
|
||||
## Additions
|
||||
|
@@ -48,9 +48,10 @@ add_library(${LIB_FSFW_NAME})
|
||||
if(FSFW_BUILD_UNITTESTS)
|
||||
message(STATUS "Building the FSFW unittests in addition to the static library")
|
||||
# Check whether the user has already installed Catch2 first
|
||||
find_package(Catch2 3)
|
||||
find_package(Catch2 3 QUIET)
|
||||
# Not installed, so use FetchContent to download and provide Catch2
|
||||
if(NOT Catch2_FOUND)
|
||||
message(STATUS "Catch2 installation not found. Downloading Catch2 library with FetchContent")
|
||||
include(FetchContent)
|
||||
|
||||
FetchContent_Declare(
|
||||
@@ -281,6 +282,24 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
-Wimplicit-fallthrough=1
|
||||
-Wno-unused-parameter
|
||||
-Wno-psabi
|
||||
-Wduplicated-cond # check for duplicate conditions
|
||||
-Wduplicated-branches # check for duplicate branches
|
||||
-Wlogical-op # Search for bitwise operations instead of logical
|
||||
-Wnull-dereference # Search for NULL dereference
|
||||
-Wundef # Warn if undefind marcos are used
|
||||
-Wformat=2 # Format string problem detection
|
||||
-Wformat-overflow=2 # Formatting issues in printf
|
||||
-Wformat-truncation=2 # Formatting issues in printf
|
||||
-Wformat-security # Search for dangerous printf operations
|
||||
-Wstrict-overflow=3 # Warn if integer overflows might happen
|
||||
-Warray-bounds=2 # Some array bounds violations will be found
|
||||
-Wshift-overflow=2 # Search for bit left shift overflows (<c++14)
|
||||
-Wcast-qual # Warn if the constness is cast away
|
||||
-Wstringop-overflow=4
|
||||
# -Wstack-protector # Emits a few false positives for low level access
|
||||
# -Wconversion # Creates many false positives
|
||||
# -Warith-conversion # Use with Wconversion to find more implicit conversions
|
||||
# -fanalyzer # Should be used to look through problems
|
||||
)
|
||||
endif()
|
||||
|
||||
|
@@ -71,9 +71,9 @@ add and link against the FSFW library in general.
|
||||
|
||||
4. Link against the FSFW library
|
||||
|
||||
```cmake
|
||||
target_link_libraries(<YourProjectName> PRIVATE fsfw)
|
||||
```
|
||||
```cmake
|
||||
target_link_libraries(${YourProjectName} PRIVATE fsfw)
|
||||
```
|
||||
|
||||
5. It should now be possible use the FSFW as a static library from the user code.
|
||||
|
||||
|
4
automation/Jenkinsfile
vendored
4
automation/Jenkinsfile
vendored
@@ -21,14 +21,14 @@ pipeline {
|
||||
stage('Build') {
|
||||
steps {
|
||||
dir(BUILDDIR) {
|
||||
sh 'cmake --build . -j'
|
||||
sh 'cmake --build . -j4'
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Unittests') {
|
||||
steps {
|
||||
dir(BUILDDIR) {
|
||||
sh 'cmake --build . -- fsfw-tests_coverage -j'
|
||||
sh 'cmake --build . -- fsfw-tests_coverage -j4'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -9,6 +9,7 @@ option(FSFW_HAL_ADD_LINUX "Add the Linux HAL to the sources. Requires gpiod libr
|
||||
# Linux. The only exception from this is the gpiod library which requires a dedicated installation,
|
||||
# but CMake is able to determine whether this library is installed with find_library.
|
||||
option(FSFW_HAL_LINUX_ADD_PERIPHERAL_DRIVERS "Add peripheral drivers for embedded Linux" ON)
|
||||
option(FSFW_HAL_LINUX_ADD_LIBGPIOD "Target implements libgpiod" ON)
|
||||
|
||||
option(FSFW_HAL_ADD_RASPBERRY_PI "Add Raspberry Pi specific code to the sources" OFF)
|
||||
option(FSFW_HAL_ADD_STM32H7 "Add the STM32H7 HAL to the sources" OFF)
|
||||
|
@@ -9,11 +9,11 @@ using gpioId_t = uint16_t;
|
||||
|
||||
namespace gpio {
|
||||
|
||||
enum Levels : uint8_t { LOW = 0, HIGH = 1, NONE = 99 };
|
||||
enum class Levels : int { LOW = 0, HIGH = 1, NONE = 99 };
|
||||
|
||||
enum Direction : uint8_t { IN = 0, OUT = 1 };
|
||||
enum class Direction : int { IN = 0, OUT = 1 };
|
||||
|
||||
enum GpioOperation { READ, WRITE };
|
||||
enum class GpioOperation { READ, WRITE };
|
||||
|
||||
enum class GpioTypes {
|
||||
NONE,
|
||||
@@ -80,7 +80,7 @@ class GpiodRegularByChip : public GpiodRegularBase {
|
||||
public:
|
||||
GpiodRegularByChip()
|
||||
: GpiodRegularBase(gpio::GpioTypes::GPIO_REGULAR_BY_CHIP, std::string(), gpio::Direction::IN,
|
||||
gpio::LOW, 0) {}
|
||||
gpio::Levels::LOW, 0) {}
|
||||
|
||||
GpiodRegularByChip(std::string chipname_, int lineNum_, std::string consumer_,
|
||||
gpio::Direction direction_, gpio::Levels initValue_)
|
||||
@@ -90,7 +90,7 @@ class GpiodRegularByChip : public GpiodRegularBase {
|
||||
|
||||
GpiodRegularByChip(std::string chipname_, int lineNum_, std::string consumer_)
|
||||
: GpiodRegularBase(gpio::GpioTypes::GPIO_REGULAR_BY_CHIP, consumer_, gpio::Direction::IN,
|
||||
gpio::LOW, lineNum_),
|
||||
gpio::Levels::LOW, lineNum_),
|
||||
chipname(chipname_) {}
|
||||
|
||||
std::string chipname;
|
||||
@@ -106,7 +106,7 @@ class GpiodRegularByLabel : public GpiodRegularBase {
|
||||
|
||||
GpiodRegularByLabel(std::string label_, int lineNum_, std::string consumer_)
|
||||
: GpiodRegularBase(gpio::GpioTypes::GPIO_REGULAR_BY_LABEL, consumer_, gpio::Direction::IN,
|
||||
gpio::LOW, lineNum_),
|
||||
gpio::Levels::LOW, lineNum_),
|
||||
label(label_) {}
|
||||
|
||||
std::string label;
|
||||
@@ -127,7 +127,7 @@ class GpiodRegularByLineName : public GpiodRegularBase {
|
||||
|
||||
GpiodRegularByLineName(std::string lineName_, std::string consumer_)
|
||||
: GpiodRegularBase(gpio::GpioTypes::GPIO_REGULAR_BY_LINE_NAME, consumer_, gpio::Direction::IN,
|
||||
gpio::LOW),
|
||||
gpio::Levels::LOW),
|
||||
lineName(lineName_) {}
|
||||
|
||||
std::string lineName;
|
||||
|
@@ -8,11 +8,7 @@ GyroHandlerL3GD20H::GyroHandlerL3GD20H(object_id_t objectId, object_id_t deviceC
|
||||
CookieIF *comCookie, uint32_t transitionDelayMs)
|
||||
: DeviceHandlerBase(objectId, deviceCommunication, comCookie),
|
||||
transitionDelayMs(transitionDelayMs),
|
||||
dataset(this) {
|
||||
#if FSFW_HAL_L3GD20_GYRO_DEBUG == 1
|
||||
debugDivider = new PeriodicOperationDivider(3);
|
||||
#endif
|
||||
}
|
||||
dataset(this) {}
|
||||
|
||||
GyroHandlerL3GD20H::~GyroHandlerL3GD20H() {}
|
||||
|
||||
@@ -193,22 +189,22 @@ ReturnValue_t GyroHandlerL3GD20H::interpretDeviceReply(DeviceCommandId_t id,
|
||||
|
||||
int8_t temperaturOffset = (-1) * packet[L3GD20H::TEMPERATURE_IDX];
|
||||
float temperature = 25.0 + temperaturOffset;
|
||||
#if FSFW_HAL_L3GD20_GYRO_DEBUG == 1
|
||||
if (debugDivider->checkAndIncrement()) {
|
||||
/* Set terminal to utf-8 if there is an issue with micro printout. */
|
||||
if (periodicPrintout) {
|
||||
if (debugDivider.checkAndIncrement()) {
|
||||
/* Set terminal to utf-8 if there is an issue with micro printout. */
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::info << "GyroHandlerL3GD20H: Angular velocities (deg/s):" << std::endl;
|
||||
sif::info << "X: " << angVelocX << std::endl;
|
||||
sif::info << "Y: " << angVelocY << std::endl;
|
||||
sif::info << "Z: " << angVelocZ << std::endl;
|
||||
sif::info << "GyroHandlerL3GD20H: Angular velocities (deg/s):" << std::endl;
|
||||
sif::info << "X: " << angVelocX << std::endl;
|
||||
sif::info << "Y: " << angVelocY << std::endl;
|
||||
sif::info << "Z: " << angVelocZ << std::endl;
|
||||
#else
|
||||
sif::printInfo("GyroHandlerL3GD20H: Angular velocities (deg/s):\n");
|
||||
sif::printInfo("X: %f\n", angVelocX);
|
||||
sif::printInfo("Y: %f\n", angVelocY);
|
||||
sif::printInfo("Z: %f\n", angVelocZ);
|
||||
sif::printInfo("GyroHandlerL3GD20H: Angular velocities (deg/s):\n");
|
||||
sif::printInfo("X: %f\n", angVelocX);
|
||||
sif::printInfo("Y: %f\n", angVelocY);
|
||||
sif::printInfo("Z: %f\n", angVelocZ);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
PoolReadGuard readSet(&dataset);
|
||||
if (readSet.getReadResult() == HasReturnvaluesIF::RETURN_OK) {
|
||||
@@ -272,3 +268,8 @@ void GyroHandlerL3GD20H::setAbsoluteLimits(float limitX, float limitY, float lim
|
||||
this->absLimitY = limitY;
|
||||
this->absLimitZ = limitZ;
|
||||
}
|
||||
|
||||
void GyroHandlerL3GD20H::enablePeriodicPrintouts(bool enable, uint8_t divider) {
|
||||
periodicPrintout = enable;
|
||||
debugDivider.setDivider(divider);
|
||||
}
|
||||
|
@@ -5,7 +5,6 @@
|
||||
#include <fsfw/globalfunctions/PeriodicOperationDivider.h>
|
||||
|
||||
#include "devicedefinitions/GyroL3GD20Definitions.h"
|
||||
#include "fsfw/FSFW.h"
|
||||
|
||||
/**
|
||||
* @brief Device Handler for the L3GD20H gyroscope sensor
|
||||
@@ -22,6 +21,8 @@ class GyroHandlerL3GD20H : public DeviceHandlerBase {
|
||||
uint32_t transitionDelayMs);
|
||||
virtual ~GyroHandlerL3GD20H();
|
||||
|
||||
void enablePeriodicPrintouts(bool enable, uint8_t divider);
|
||||
|
||||
/**
|
||||
* Set the absolute limit for the values on the axis in degrees per second.
|
||||
* The dataset values will be marked as invalid if that limit is exceeded
|
||||
@@ -80,9 +81,8 @@ class GyroHandlerL3GD20H : public DeviceHandlerBase {
|
||||
// Set default value
|
||||
float sensitivity = L3GD20H::SENSITIVITY_00;
|
||||
|
||||
#if FSFW_HAL_L3GD20_GYRO_DEBUG == 1
|
||||
PeriodicOperationDivider *debugDivider = nullptr;
|
||||
#endif
|
||||
bool periodicPrintout = false;
|
||||
PeriodicOperationDivider debugDivider = PeriodicOperationDivider(3);
|
||||
};
|
||||
|
||||
#endif /* MISSION_DEVICES_GYROL3GD20HANDLER_H_ */
|
||||
|
@@ -1,9 +1,6 @@
|
||||
#include "MgmLIS3MDLHandler.h"
|
||||
|
||||
#include "fsfw/datapool/PoolReadGuard.h"
|
||||
#if FSFW_HAL_LIS3MDL_MGM_DEBUG == 1
|
||||
#include "fsfw/globalfunctions/PeriodicOperationDivider.h"
|
||||
#endif
|
||||
|
||||
#include <cmath>
|
||||
|
||||
@@ -12,9 +9,6 @@ MgmLIS3MDLHandler::MgmLIS3MDLHandler(object_id_t objectId, object_id_t deviceCom
|
||||
: DeviceHandlerBase(objectId, deviceCommunication, comCookie),
|
||||
dataset(this),
|
||||
transitionDelay(transitionDelay) {
|
||||
#if FSFW_HAL_LIS3MDL_MGM_DEBUG == 1
|
||||
debugDivider = new PeriodicOperationDivider(3);
|
||||
#endif
|
||||
// Set to default values right away
|
||||
registers[0] = MGMLIS3MDL::CTRL_REG1_DEFAULT;
|
||||
registers[1] = MGMLIS3MDL::CTRL_REG2_DEFAULT;
|
||||
@@ -264,7 +258,7 @@ ReturnValue_t MgmLIS3MDLHandler::interpretDeviceReply(DeviceCommandId_t id, cons
|
||||
int16_t mgmMeasurementRawZ =
|
||||
packet[MGMLIS3MDL::Z_HIGHBYTE_IDX] << 8 | packet[MGMLIS3MDL::Z_LOWBYTE_IDX];
|
||||
|
||||
/* Target value in microtesla */
|
||||
// Target value in microtesla
|
||||
float mgmX = static_cast<float>(mgmMeasurementRawX) * sensitivityFactor *
|
||||
MGMLIS3MDL::GAUSS_TO_MICROTESLA_FACTOR;
|
||||
float mgmY = static_cast<float>(mgmMeasurementRawY) * sensitivityFactor *
|
||||
@@ -272,23 +266,24 @@ ReturnValue_t MgmLIS3MDLHandler::interpretDeviceReply(DeviceCommandId_t id, cons
|
||||
float mgmZ = static_cast<float>(mgmMeasurementRawZ) * sensitivityFactor *
|
||||
MGMLIS3MDL::GAUSS_TO_MICROTESLA_FACTOR;
|
||||
|
||||
#if FSFW_HAL_LIS3MDL_MGM_DEBUG == 1
|
||||
if (debugDivider->checkAndIncrement()) {
|
||||
if (periodicPrintout) {
|
||||
if (debugDivider.checkAndIncrement()) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::info << "MGMHandlerLIS3: Magnetic field strength in"
|
||||
" microtesla:"
|
||||
<< std::endl;
|
||||
sif::info << "X: " << mgmX << " uT" << std::endl;
|
||||
sif::info << "Y: " << mgmY << " uT" << std::endl;
|
||||
sif::info << "Z: " << mgmZ << " uT" << std::endl;
|
||||
sif::info << "MGMHandlerLIS3: Magnetic field strength in"
|
||||
" microtesla:"
|
||||
<< std::endl;
|
||||
sif::info << "X: " << mgmX << " uT" << std::endl;
|
||||
sif::info << "Y: " << mgmY << " uT" << std::endl;
|
||||
sif::info << "Z: " << mgmZ << " uT" << std::endl;
|
||||
#else
|
||||
sif::printInfo("MGMHandlerLIS3: Magnetic field strength in microtesla:\n");
|
||||
sif::printInfo("X: %f uT\n", mgmX);
|
||||
sif::printInfo("Y: %f uT\n", mgmY);
|
||||
sif::printInfo("Z: %f uT\n", mgmZ);
|
||||
sif::printInfo("MGMHandlerLIS3: Magnetic field strength in microtesla:\n");
|
||||
sif::printInfo("X: %f uT\n", mgmX);
|
||||
sif::printInfo("Y: %f uT\n", mgmY);
|
||||
sif::printInfo("Z: %f uT\n", mgmZ);
|
||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 0 */
|
||||
}
|
||||
}
|
||||
#endif /* OBSW_VERBOSE_LEVEL >= 1 */
|
||||
|
||||
PoolReadGuard readHelper(&dataset);
|
||||
if (readHelper.getReadResult() == HasReturnvaluesIF::RETURN_OK) {
|
||||
if (std::abs(mgmX) < absLimitX) {
|
||||
@@ -318,15 +313,16 @@ ReturnValue_t MgmLIS3MDLHandler::interpretDeviceReply(DeviceCommandId_t id, cons
|
||||
case MGMLIS3MDL::READ_TEMPERATURE: {
|
||||
int16_t tempValueRaw = packet[2] << 8 | packet[1];
|
||||
float tempValue = 25.0 + ((static_cast<float>(tempValueRaw)) / 8.0);
|
||||
#if FSFW_HAL_LIS3MDL_MGM_DEBUG == 1
|
||||
if (debugDivider->check()) {
|
||||
if (periodicPrintout) {
|
||||
if (debugDivider.check()) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::info << "MGMHandlerLIS3: Temperature: " << tempValue << " C" << std::endl;
|
||||
sif::info << "MGMHandlerLIS3: Temperature: " << tempValue << " C" << std::endl;
|
||||
#else
|
||||
sif::printInfo("MGMHandlerLIS3: Temperature: %f C\n");
|
||||
sif::printInfo("MGMHandlerLIS3: Temperature: %f C\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
ReturnValue_t result = dataset.read();
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
dataset.temperature = tempValue;
|
||||
@@ -462,7 +458,9 @@ ReturnValue_t MgmLIS3MDLHandler::prepareCtrlRegisterWrite() {
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
void MgmLIS3MDLHandler::doTransition(Mode_t modeFrom, Submode_t subModeFrom) {}
|
||||
void MgmLIS3MDLHandler::doTransition(Mode_t modeFrom, Submode_t subModeFrom) {
|
||||
DeviceHandlerBase::doTransition(modeFrom, subModeFrom);
|
||||
}
|
||||
|
||||
uint32_t MgmLIS3MDLHandler::getTransitionDelayMs(Mode_t from, Mode_t to) { return transitionDelay; }
|
||||
|
||||
@@ -482,3 +480,8 @@ void MgmLIS3MDLHandler::setAbsoluteLimits(float xLimit, float yLimit, float zLim
|
||||
this->absLimitY = yLimit;
|
||||
this->absLimitZ = zLimit;
|
||||
}
|
||||
|
||||
void MgmLIS3MDLHandler::enablePeriodicPrintouts(bool enable, uint8_t divider) {
|
||||
periodicPrintout = enable;
|
||||
debugDivider.setDivider(divider);
|
||||
}
|
||||
|
@@ -3,8 +3,8 @@
|
||||
|
||||
#include "devicedefinitions/MgmLIS3HandlerDefs.h"
|
||||
#include "events/subsystemIdRanges.h"
|
||||
#include "fsfw/FSFW.h"
|
||||
#include "fsfw/devicehandlers/DeviceHandlerBase.h"
|
||||
#include "fsfw/globalfunctions/PeriodicOperationDivider.h"
|
||||
|
||||
class PeriodicOperationDivider;
|
||||
|
||||
@@ -30,6 +30,7 @@ class MgmLIS3MDLHandler : public DeviceHandlerBase {
|
||||
uint32_t transitionDelay);
|
||||
virtual ~MgmLIS3MDLHandler();
|
||||
|
||||
void enablePeriodicPrintouts(bool enable, uint8_t divider);
|
||||
/**
|
||||
* Set the absolute limit for the values on the axis in microtesla. The dataset values will
|
||||
* be marked as invalid if that limit is exceeded
|
||||
@@ -167,9 +168,8 @@ class MgmLIS3MDLHandler : public DeviceHandlerBase {
|
||||
*/
|
||||
ReturnValue_t prepareCtrlRegisterWrite();
|
||||
|
||||
#if FSFW_HAL_LIS3MDL_MGM_DEBUG == 1
|
||||
PeriodicOperationDivider *debugDivider;
|
||||
#endif
|
||||
bool periodicPrintout = false;
|
||||
PeriodicOperationDivider debugDivider = PeriodicOperationDivider(3);
|
||||
};
|
||||
|
||||
#endif /* MISSION_DEVICES_MGMLIS3MDLHANDLER_H_ */
|
||||
|
@@ -10,11 +10,7 @@ MgmRM3100Handler::MgmRM3100Handler(object_id_t objectId, object_id_t deviceCommu
|
||||
CookieIF *comCookie, uint32_t transitionDelay)
|
||||
: DeviceHandlerBase(objectId, deviceCommunication, comCookie),
|
||||
primaryDataset(this),
|
||||
transitionDelay(transitionDelay) {
|
||||
#if FSFW_HAL_RM3100_MGM_DEBUG == 1
|
||||
debugDivider = new PeriodicOperationDivider(3);
|
||||
#endif
|
||||
}
|
||||
transitionDelay(transitionDelay) {}
|
||||
|
||||
MgmRM3100Handler::~MgmRM3100Handler() {}
|
||||
|
||||
@@ -337,23 +333,23 @@ ReturnValue_t MgmRM3100Handler::handleDataReadout(const uint8_t *packet) {
|
||||
float fieldStrengthY = fieldStrengthRawY * scaleFactorX;
|
||||
float fieldStrengthZ = fieldStrengthRawZ * scaleFactorX;
|
||||
|
||||
#if FSFW_HAL_RM3100_MGM_DEBUG == 1
|
||||
if (debugDivider->checkAndIncrement()) {
|
||||
if (periodicPrintout) {
|
||||
if (debugDivider.checkAndIncrement()) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::info << "MgmRM3100Handler: Magnetic field strength in"
|
||||
" microtesla:"
|
||||
<< std::endl;
|
||||
sif::info << "X: " << fieldStrengthX << " uT" << std::endl;
|
||||
sif::info << "Y: " << fieldStrengthY << " uT" << std::endl;
|
||||
sif::info << "Z: " << fieldStrengthZ << " uT" << std::endl;
|
||||
sif::info << "MgmRM3100Handler: Magnetic field strength in"
|
||||
" microtesla:"
|
||||
<< std::endl;
|
||||
sif::info << "X: " << fieldStrengthX << " uT" << std::endl;
|
||||
sif::info << "Y: " << fieldStrengthY << " uT" << std::endl;
|
||||
sif::info << "Z: " << fieldStrengthZ << " uT" << std::endl;
|
||||
#else
|
||||
sif::printInfo("MgmRM3100Handler: Magnetic field strength in microtesla:\n");
|
||||
sif::printInfo("X: %f uT\n", fieldStrengthX);
|
||||
sif::printInfo("Y: %f uT\n", fieldStrengthY);
|
||||
sif::printInfo("Z: %f uT\n", fieldStrengthZ);
|
||||
sif::printInfo("MgmRM3100Handler: Magnetic field strength in microtesla:\n");
|
||||
sif::printInfo("X: %f uT\n", fieldStrengthX);
|
||||
sif::printInfo("Y: %f uT\n", fieldStrengthY);
|
||||
sif::printInfo("Z: %f uT\n", fieldStrengthZ);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// TODO: Sanity check on values?
|
||||
PoolReadGuard readGuard(&primaryDataset);
|
||||
@@ -365,3 +361,8 @@ ReturnValue_t MgmRM3100Handler::handleDataReadout(const uint8_t *packet) {
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
void MgmRM3100Handler::enablePeriodicPrintouts(bool enable, uint8_t divider) {
|
||||
periodicPrintout = enable;
|
||||
debugDivider.setDivider(divider);
|
||||
}
|
||||
|
@@ -2,12 +2,8 @@
|
||||
#define MISSION_DEVICES_MGMRM3100HANDLER_H_
|
||||
|
||||
#include "devicedefinitions/MgmRM3100HandlerDefs.h"
|
||||
#include "fsfw/FSFW.h"
|
||||
#include "fsfw/devicehandlers/DeviceHandlerBase.h"
|
||||
|
||||
#if FSFW_HAL_RM3100_MGM_DEBUG == 1
|
||||
#include "fsfw/globalfunctions/PeriodicOperationDivider.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Device Handler for the RM3100 geomagnetic magnetometer sensor
|
||||
@@ -33,6 +29,7 @@ class MgmRM3100Handler : public DeviceHandlerBase {
|
||||
uint32_t transitionDelay);
|
||||
virtual ~MgmRM3100Handler();
|
||||
|
||||
void enablePeriodicPrintouts(bool enable, uint8_t divider);
|
||||
/**
|
||||
* Configure device handler to go to normal mode after startup immediately
|
||||
* @param enable
|
||||
@@ -98,9 +95,9 @@ class MgmRM3100Handler : public DeviceHandlerBase {
|
||||
size_t commandDataLen);
|
||||
|
||||
ReturnValue_t handleDataReadout(const uint8_t *packet);
|
||||
#if FSFW_HAL_RM3100_MGM_DEBUG == 1
|
||||
PeriodicOperationDivider *debugDivider;
|
||||
#endif
|
||||
|
||||
bool periodicPrintout = false;
|
||||
PeriodicOperationDivider debugDivider = PeriodicOperationDivider(3);
|
||||
};
|
||||
|
||||
#endif /* MISSION_DEVICEHANDLING_MGMRM3100HANDLER_H_ */
|
||||
|
@@ -9,7 +9,9 @@ target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
)
|
||||
|
||||
if(FSFW_HAL_LINUX_ADD_PERIPHERAL_DRIVERS)
|
||||
if(FSFW_HAL_LINUX_ADD_LIBGPIOD)
|
||||
add_subdirectory(gpio)
|
||||
endif()
|
||||
add_subdirectory(spi)
|
||||
add_subdirectory(i2c)
|
||||
add_subdirectory(uart)
|
||||
|
27
hal/src/fsfw_hal/linux/gpio/Gpio.h
Normal file
27
hal/src/fsfw_hal/linux/gpio/Gpio.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef FSFW_HAL_SRC_FSFW_HAL_LINUX_GPIO_GPIO_H_
|
||||
#define FSFW_HAL_SRC_FSFW_HAL_LINUX_GPIO_GPIO_H_
|
||||
|
||||
#include "fsfw_hal/common/gpio/GpioIF.h"
|
||||
#include "fsfw_hal/common/gpio/gpioDefinitions.h"
|
||||
|
||||
/**
|
||||
* @brief Additional abstraction layer for handling GPIOs.
|
||||
*
|
||||
* @author J. Meier
|
||||
*/
|
||||
class Gpio {
|
||||
public:
|
||||
Gpio(gpioId_t gpioId, GpioIF* gpioIF) : gpioId(gpioId), gpioIF(gpioIF) {
|
||||
if (gpioIF == nullptr) {
|
||||
sif::error << "Gpio::Gpio: Invalid GpioIF" << std::endl;
|
||||
}
|
||||
}
|
||||
ReturnValue_t pullHigh() { return gpioIF->pullHigh(gpioId); }
|
||||
ReturnValue_t pullLow() { return gpioIF->pullLow(gpioId); }
|
||||
|
||||
private:
|
||||
gpioId_t gpioId = gpio::NO_GPIO;
|
||||
GpioIF* gpioIF = nullptr;
|
||||
};
|
||||
|
||||
#endif /* FSFW_HAL_SRC_FSFW_HAL_LINUX_GPIO_GPIO_H_ */
|
@@ -161,11 +161,12 @@ ReturnValue_t LinuxLibgpioIF::configureRegularGpio(gpioId_t gpioId, struct gpiod
|
||||
consumer = regularGpio.consumer;
|
||||
/* Configure direction and add a description to the GPIO */
|
||||
switch (direction) {
|
||||
case (gpio::OUT): {
|
||||
result = gpiod_line_request_output(lineHandle, consumer.c_str(), regularGpio.initValue);
|
||||
case (gpio::Direction::OUT): {
|
||||
result = gpiod_line_request_output(lineHandle, consumer.c_str(),
|
||||
static_cast<int>(regularGpio.initValue));
|
||||
break;
|
||||
}
|
||||
case (gpio::IN): {
|
||||
case (gpio::Direction::IN): {
|
||||
result = gpiod_line_request_input(lineHandle, consumer.c_str());
|
||||
break;
|
||||
}
|
||||
@@ -211,7 +212,7 @@ ReturnValue_t LinuxLibgpioIF::pullHigh(gpioId_t gpioId) {
|
||||
if (regularGpio == nullptr) {
|
||||
return GPIO_TYPE_FAILURE;
|
||||
}
|
||||
return driveGpio(gpioId, *regularGpio, gpio::HIGH);
|
||||
return driveGpio(gpioId, *regularGpio, gpio::Levels::HIGH);
|
||||
} else {
|
||||
auto gpioCallback = dynamic_cast<GpioCallback*>(gpioMapIter->second);
|
||||
if (gpioCallback->callback == nullptr) {
|
||||
@@ -243,7 +244,7 @@ ReturnValue_t LinuxLibgpioIF::pullLow(gpioId_t gpioId) {
|
||||
if (regularGpio == nullptr) {
|
||||
return GPIO_TYPE_FAILURE;
|
||||
}
|
||||
return driveGpio(gpioId, *regularGpio, gpio::LOW);
|
||||
return driveGpio(gpioId, *regularGpio, gpio::Levels::LOW);
|
||||
} else {
|
||||
auto gpioCallback = dynamic_cast<GpioCallback*>(gpioMapIter->second);
|
||||
if (gpioCallback->callback == nullptr) {
|
||||
@@ -258,11 +259,11 @@ ReturnValue_t LinuxLibgpioIF::pullLow(gpioId_t gpioId) {
|
||||
|
||||
ReturnValue_t LinuxLibgpioIF::driveGpio(gpioId_t gpioId, GpiodRegularBase& regularGpio,
|
||||
gpio::Levels logicLevel) {
|
||||
int result = gpiod_line_set_value(regularGpio.lineHandle, logicLevel);
|
||||
int result = gpiod_line_set_value(regularGpio.lineHandle, static_cast<int>(logicLevel));
|
||||
if (result < 0) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "LinuxLibgpioIF::driveGpio: Failed to pull GPIO with ID " << gpioId
|
||||
<< " to logic level " << logicLevel << std::endl;
|
||||
<< " to logic level " << static_cast<int>(logicLevel) << std::endl;
|
||||
#else
|
||||
sif::printWarning(
|
||||
"LinuxLibgpioIF::driveGpio: Failed to pull GPIO with ID %d to "
|
||||
|
@@ -1,4 +1,13 @@
|
||||
#include "fsfw_hal/linux/i2c/I2cComIF.h"
|
||||
#include "I2cComIF.h"
|
||||
|
||||
#include "fsfw/FSFW.h"
|
||||
#include "fsfw/serviceinterface.h"
|
||||
#include "fsfw_hal/linux/UnixFileGuard.h"
|
||||
#include "fsfw_hal/linux/utility.h"
|
||||
|
||||
#if FSFW_HAL_I2C_WIRETAPPING == 1
|
||||
#include "fsfw/globalfunctions/arrayprinter.h"
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
@@ -8,11 +17,6 @@
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "fsfw/FSFW.h"
|
||||
#include "fsfw/serviceinterface.h"
|
||||
#include "fsfw_hal/linux/UnixFileGuard.h"
|
||||
#include "fsfw_hal/linux/utility.h"
|
||||
|
||||
I2cComIF::I2cComIF(object_id_t objectId) : SystemObject(objectId) {}
|
||||
|
||||
I2cComIF::~I2cComIF() {}
|
||||
@@ -112,6 +116,11 @@ ReturnValue_t I2cComIF::sendMessage(CookieIF* cookie, const uint8_t* sendData, s
|
||||
#endif
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
#if FSFW_HAL_I2C_WIRETAPPING == 1
|
||||
sif::info << "Sent I2C data to bus " << deviceFile << ":" << std::endl;
|
||||
arrayprinter::print(sendData, sendLen);
|
||||
#endif
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
@@ -176,6 +185,11 @@ ReturnValue_t I2cComIF::requestReceiveMessage(CookieIF* cookie, size_t requestLe
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
#if FSFW_HAL_I2C_WIRETAPPING == 1
|
||||
sif::info << "I2C read bytes from bus " << deviceFile << ":" << std::endl;
|
||||
arrayprinter::print(replyBuffer, requestLen);
|
||||
#endif
|
||||
|
||||
i2cDeviceMapIter->second.replyLen = requestLen;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@
|
||||
|
||||
ReturnValue_t gpio::createRpiGpioConfig(GpioCookie* cookie, gpioId_t gpioId, int bcmPin,
|
||||
std::string consumer, gpio::Direction direction,
|
||||
int initValue) {
|
||||
gpio::Levels initValue) {
|
||||
if (cookie == nullptr) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
@@ -21,7 +21,8 @@ namespace gpio {
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t createRpiGpioConfig(GpioCookie* cookie, gpioId_t gpioId, int bcmPin,
|
||||
std::string consumer, gpio::Direction direction, int initValue);
|
||||
std::string consumer, gpio::Direction direction,
|
||||
gpio::Levels initValue);
|
||||
} // namespace gpio
|
||||
|
||||
#endif /* BSP_RPI_GPIO_GPIORPI_H_ */
|
||||
|
@@ -401,4 +401,12 @@ void SpiComIF::setSpiSpeedAndMode(int spiFd, spi::SpiModes mode, uint32_t speed)
|
||||
if (retval != 0) {
|
||||
utility::handleIoctlError("SpiComIF::setSpiSpeedAndMode: Setting SPI speed failed");
|
||||
}
|
||||
// This updates the SPI clock default polarity. Only setting the mode does not update
|
||||
// the line state, which can be an issue on mode switches because the clock line will
|
||||
// switch the state after the chip select is pulled low
|
||||
clockUpdateTransfer.len = 0;
|
||||
retval = ioctl(spiFd, SPI_IOC_MESSAGE(1), &clockUpdateTransfer);
|
||||
if (retval != 0) {
|
||||
utility::handleIoctlError("SpiComIF::setSpiSpeedAndMode: Updating SPI default clock failed");
|
||||
}
|
||||
}
|
||||
|
@@ -74,6 +74,7 @@ class SpiComIF : public DeviceCommunicationIF, public SystemObject {
|
||||
MutexIF* spiMutex = nullptr;
|
||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
|
||||
uint32_t timeoutMs = 20;
|
||||
spi_ioc_transfer clockUpdateTransfer = {};
|
||||
|
||||
using SpiDeviceMap = std::unordered_map<address_t, SpiInstance>;
|
||||
using SpiDeviceMapIter = SpiDeviceMap::iterator;
|
||||
|
@@ -148,16 +148,16 @@ void UartComIF::setDatasizeOptions(struct termios* options, UartCookie* uartCook
|
||||
/* Clear size bits */
|
||||
options->c_cflag &= ~CSIZE;
|
||||
switch (uartCookie->getBitsPerWord()) {
|
||||
case 5:
|
||||
case BitsPerWord::BITS_5:
|
||||
options->c_cflag |= CS5;
|
||||
break;
|
||||
case 6:
|
||||
case BitsPerWord::BITS_6:
|
||||
options->c_cflag |= CS6;
|
||||
break;
|
||||
case 7:
|
||||
case BitsPerWord::BITS_7:
|
||||
options->c_cflag |= CS7;
|
||||
break;
|
||||
case 8:
|
||||
case BitsPerWord::BITS_8:
|
||||
options->c_cflag |= CS8;
|
||||
break;
|
||||
default:
|
||||
@@ -193,82 +193,126 @@ void UartComIF::setFixedOptions(struct termios* options) {
|
||||
|
||||
void UartComIF::configureBaudrate(struct termios* options, UartCookie* uartCookie) {
|
||||
switch (uartCookie->getBaudrate()) {
|
||||
case 50:
|
||||
case UartBaudRate::RATE_50:
|
||||
cfsetispeed(options, B50);
|
||||
cfsetospeed(options, B50);
|
||||
break;
|
||||
case 75:
|
||||
case UartBaudRate::RATE_75:
|
||||
cfsetispeed(options, B75);
|
||||
cfsetospeed(options, B75);
|
||||
break;
|
||||
case 110:
|
||||
case UartBaudRate::RATE_110:
|
||||
cfsetispeed(options, B110);
|
||||
cfsetospeed(options, B110);
|
||||
break;
|
||||
case 134:
|
||||
case UartBaudRate::RATE_134:
|
||||
cfsetispeed(options, B134);
|
||||
cfsetospeed(options, B134);
|
||||
break;
|
||||
case 150:
|
||||
case UartBaudRate::RATE_150:
|
||||
cfsetispeed(options, B150);
|
||||
cfsetospeed(options, B150);
|
||||
break;
|
||||
case 200:
|
||||
case UartBaudRate::RATE_200:
|
||||
cfsetispeed(options, B200);
|
||||
cfsetospeed(options, B200);
|
||||
break;
|
||||
case 300:
|
||||
case UartBaudRate::RATE_300:
|
||||
cfsetispeed(options, B300);
|
||||
cfsetospeed(options, B300);
|
||||
break;
|
||||
case 600:
|
||||
case UartBaudRate::RATE_600:
|
||||
cfsetispeed(options, B600);
|
||||
cfsetospeed(options, B600);
|
||||
break;
|
||||
case 1200:
|
||||
case UartBaudRate::RATE_1200:
|
||||
cfsetispeed(options, B1200);
|
||||
cfsetospeed(options, B1200);
|
||||
break;
|
||||
case 1800:
|
||||
case UartBaudRate::RATE_1800:
|
||||
cfsetispeed(options, B1800);
|
||||
cfsetospeed(options, B1800);
|
||||
break;
|
||||
case 2400:
|
||||
case UartBaudRate::RATE_2400:
|
||||
cfsetispeed(options, B2400);
|
||||
cfsetospeed(options, B2400);
|
||||
break;
|
||||
case 4800:
|
||||
case UartBaudRate::RATE_4800:
|
||||
cfsetispeed(options, B4800);
|
||||
cfsetospeed(options, B4800);
|
||||
break;
|
||||
case 9600:
|
||||
case UartBaudRate::RATE_9600:
|
||||
cfsetispeed(options, B9600);
|
||||
cfsetospeed(options, B9600);
|
||||
break;
|
||||
case 19200:
|
||||
case UartBaudRate::RATE_19200:
|
||||
cfsetispeed(options, B19200);
|
||||
cfsetospeed(options, B19200);
|
||||
break;
|
||||
case 38400:
|
||||
case UartBaudRate::RATE_38400:
|
||||
cfsetispeed(options, B38400);
|
||||
cfsetospeed(options, B38400);
|
||||
break;
|
||||
case 57600:
|
||||
case UartBaudRate::RATE_57600:
|
||||
cfsetispeed(options, B57600);
|
||||
cfsetospeed(options, B57600);
|
||||
break;
|
||||
case 115200:
|
||||
case UartBaudRate::RATE_115200:
|
||||
cfsetispeed(options, B115200);
|
||||
cfsetospeed(options, B115200);
|
||||
break;
|
||||
case 230400:
|
||||
case UartBaudRate::RATE_230400:
|
||||
cfsetispeed(options, B230400);
|
||||
cfsetospeed(options, B230400);
|
||||
break;
|
||||
case 460800:
|
||||
case UartBaudRate::RATE_460800:
|
||||
cfsetispeed(options, B460800);
|
||||
cfsetospeed(options, B460800);
|
||||
break;
|
||||
case UartBaudRate::RATE_500000:
|
||||
cfsetispeed(options, B500000);
|
||||
cfsetospeed(options, B500000);
|
||||
break;
|
||||
case UartBaudRate::RATE_576000:
|
||||
cfsetispeed(options, B576000);
|
||||
cfsetospeed(options, B576000);
|
||||
break;
|
||||
case UartBaudRate::RATE_921600:
|
||||
cfsetispeed(options, B921600);
|
||||
cfsetospeed(options, B921600);
|
||||
break;
|
||||
case UartBaudRate::RATE_1000000:
|
||||
cfsetispeed(options, B1000000);
|
||||
cfsetospeed(options, B1000000);
|
||||
break;
|
||||
case UartBaudRate::RATE_1152000:
|
||||
cfsetispeed(options, B1152000);
|
||||
cfsetospeed(options, B1152000);
|
||||
break;
|
||||
case UartBaudRate::RATE_1500000:
|
||||
cfsetispeed(options, B1500000);
|
||||
cfsetospeed(options, B1500000);
|
||||
break;
|
||||
case UartBaudRate::RATE_2000000:
|
||||
cfsetispeed(options, B2000000);
|
||||
cfsetospeed(options, B2000000);
|
||||
break;
|
||||
case UartBaudRate::RATE_2500000:
|
||||
cfsetispeed(options, B2500000);
|
||||
cfsetospeed(options, B2500000);
|
||||
break;
|
||||
case UartBaudRate::RATE_3000000:
|
||||
cfsetispeed(options, B3000000);
|
||||
cfsetospeed(options, B3000000);
|
||||
break;
|
||||
case UartBaudRate::RATE_3500000:
|
||||
cfsetispeed(options, B3500000);
|
||||
cfsetospeed(options, B3500000);
|
||||
break;
|
||||
case UartBaudRate::RATE_4000000:
|
||||
cfsetispeed(options, B4000000);
|
||||
cfsetospeed(options, B4000000);
|
||||
break;
|
||||
default:
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "UartComIF::configureBaudrate: Baudrate not supported" << std::endl;
|
||||
@@ -427,7 +471,7 @@ ReturnValue_t UartComIF::handleNoncanonicalRead(UartCookie& uartCookie, UartDevi
|
||||
auto bufferPtr = iter->second.replyBuffer.data();
|
||||
// Size check to prevent buffer overflow
|
||||
if (requestLen > uartCookie.getMaxReplyLen()) {
|
||||
#if OBSW_VERBOSE_LEVEL >= 1
|
||||
#if FSFW_VERBOSE_LEVEL >= 1
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "UartComIF::requestReceiveMessage: Next read would cause overflow!"
|
||||
<< std::endl;
|
||||
|
@@ -1,9 +1,9 @@
|
||||
#include "fsfw_hal/linux/uart/UartCookie.h"
|
||||
#include "UartCookie.h"
|
||||
|
||||
#include <fsfw/serviceinterface.h>
|
||||
|
||||
UartCookie::UartCookie(object_id_t handlerId, std::string deviceFile, UartModes uartMode,
|
||||
uint32_t baudrate, size_t maxReplyLen)
|
||||
UartCookie::UartCookie(object_id_t handlerId, std::string deviceFile, UartBaudRate baudrate,
|
||||
size_t maxReplyLen, UartModes uartMode)
|
||||
: handlerId(handlerId),
|
||||
deviceFile(deviceFile),
|
||||
uartMode(uartMode),
|
||||
@@ -12,7 +12,7 @@ UartCookie::UartCookie(object_id_t handlerId, std::string deviceFile, UartModes
|
||||
|
||||
UartCookie::~UartCookie() {}
|
||||
|
||||
uint32_t UartCookie::getBaudrate() const { return baudrate; }
|
||||
UartBaudRate UartCookie::getBaudrate() const { return baudrate; }
|
||||
|
||||
size_t UartCookie::getMaxReplyLen() const { return maxReplyLen; }
|
||||
|
||||
@@ -24,23 +24,9 @@ void UartCookie::setParityEven() { parity = Parity::EVEN; }
|
||||
|
||||
Parity UartCookie::getParity() const { return parity; }
|
||||
|
||||
void UartCookie::setBitsPerWord(uint8_t 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_;
|
||||
}
|
||||
void UartCookie::setBitsPerWord(BitsPerWord bitsPerWord_) { bitsPerWord = bitsPerWord_; }
|
||||
|
||||
uint8_t UartCookie::getBitsPerWord() const { return bitsPerWord; }
|
||||
BitsPerWord UartCookie::getBitsPerWord() const { return bitsPerWord; }
|
||||
|
||||
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 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.
|
||||
* 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
|
||||
* messages are separated by a delimited character like '\n'. See the
|
||||
* termios documentation for more information
|
||||
* @param baudrate The baudrate to use for input and output. Possible Baudrates are: 50,
|
||||
* 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, B19200,
|
||||
* 38400, 57600, 115200, 230400, 460800
|
||||
* @param baudrate The baudrate to use for input and output.
|
||||
* @param maxReplyLen The maximum size an object using this cookie expects
|
||||
* @details
|
||||
* Default configuration: No parity
|
||||
* 8 databits (number of bits transfered with one uart frame)
|
||||
* One stop bit
|
||||
*/
|
||||
UartCookie(object_id_t handlerId, std::string deviceFile, UartModes uartMode, uint32_t baudrate,
|
||||
size_t maxReplyLen);
|
||||
UartCookie(object_id_t handlerId, std::string deviceFile, UartBaudRate baudrate,
|
||||
size_t maxReplyLen, UartModes uartMode = UartModes::NON_CANONICAL);
|
||||
|
||||
virtual ~UartCookie();
|
||||
|
||||
uint32_t getBaudrate() const;
|
||||
UartBaudRate getBaudrate() const;
|
||||
size_t getMaxReplyLen() const;
|
||||
std::string getDeviceFile() const;
|
||||
Parity getParity() const;
|
||||
uint8_t getBitsPerWord() const;
|
||||
BitsPerWord getBitsPerWord() const;
|
||||
StopBits getStopBits() const;
|
||||
UartModes getUartMode() const;
|
||||
object_id_t getHandlerId() const;
|
||||
@@ -76,7 +109,7 @@ class UartCookie : public CookieIF {
|
||||
/**
|
||||
* 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.
|
||||
@@ -97,10 +130,10 @@ class UartCookie : public CookieIF {
|
||||
std::string deviceFile;
|
||||
const UartModes uartMode;
|
||||
bool flushInput = false;
|
||||
uint32_t baudrate;
|
||||
UartBaudRate baudrate;
|
||||
size_t maxReplyLen = 0;
|
||||
Parity parity = Parity::NONE;
|
||||
uint8_t bitsPerWord = 8;
|
||||
BitsPerWord bitsPerWord = BitsPerWord::BITS_8;
|
||||
uint8_t readCycles = 1;
|
||||
StopBits stopBits = StopBits::ONE_STOP_BIT;
|
||||
bool replySizeFixed = true;
|
||||
|
@@ -97,11 +97,11 @@ def handle_docs_type(args, build_dir_list: list):
|
||||
build_directory = determine_build_dir(build_dir_list)
|
||||
os.chdir(build_directory)
|
||||
if args.build:
|
||||
os.system("cmake --build . -j")
|
||||
cmd_runner("cmake --build . -j")
|
||||
if args.open:
|
||||
if not os.path.isfile("docs/sphinx/index.html"):
|
||||
# try again..
|
||||
os.system("cmake --build . -j")
|
||||
cmd_runner("cmake --build . -j")
|
||||
if not os.path.isfile("docs/sphinx/index.html"):
|
||||
print(
|
||||
"No Sphinx documentation file detected. "
|
||||
@@ -143,25 +143,21 @@ def handle_tests_type(args, build_dir_list: list):
|
||||
if which("valgrind") is None:
|
||||
print("Please install valgrind first")
|
||||
sys.exit(1)
|
||||
if os.path.split(os.getcwd())[1] != UNITTEST_FOLDER_NAME:
|
||||
# If we are in a different directory we try to switch into it but
|
||||
# this might fail
|
||||
os.chdir(UNITTEST_FOLDER_NAME)
|
||||
os.system("valgrind --leak-check=full ./fsfw-tests")
|
||||
cmd_runner("valgrind --leak-check=full ./fsfw-tests")
|
||||
os.chdir("..")
|
||||
|
||||
|
||||
def create_tests_build_cfg():
|
||||
os.mkdir(UNITTEST_FOLDER_NAME)
|
||||
os.chdir(UNITTEST_FOLDER_NAME)
|
||||
os.system("cmake -DFSFW_OSAL=host -DFSFW_BUILD_UNITTESTS=ON ..")
|
||||
cmd_runner("cmake -DFSFW_OSAL=host -DFSFW_BUILD_UNITTESTS=ON ..")
|
||||
os.chdir("..")
|
||||
|
||||
|
||||
def create_docs_build_cfg():
|
||||
os.mkdir(DOCS_FOLDER_NAME)
|
||||
os.chdir(DOCS_FOLDER_NAME)
|
||||
os.system("cmake -DFSFW_OSAL=host -DFSFW_BUILD_DOCS=ON ..")
|
||||
cmd_runner("cmake -DFSFW_OSAL=host -DFSFW_BUILD_DOCS=ON ..")
|
||||
os.chdir("..")
|
||||
|
||||
|
||||
@@ -184,7 +180,7 @@ def check_for_cmake_build_dir(build_dir_list: list) -> list:
|
||||
def perform_lcov_operation(directory: str, chdir: bool):
|
||||
if chdir:
|
||||
os.chdir(directory)
|
||||
os.system("cmake --build . -- fsfw-tests_coverage -j")
|
||||
cmd_runner("cmake --build . -- fsfw-tests_coverage -j")
|
||||
|
||||
|
||||
def determine_build_dir(build_dir_list: List[str]):
|
||||
@@ -206,5 +202,10 @@ def determine_build_dir(build_dir_list: List[str]):
|
||||
return build_directory
|
||||
|
||||
|
||||
def cmd_runner(cmd: str):
|
||||
print(f"Executing command: {cmd}")
|
||||
os.system(cmd)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
@@ -1,3 +1,7 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
version.cpp
|
||||
)
|
||||
|
||||
# Core
|
||||
|
||||
add_subdirectory(action)
|
||||
|
@@ -30,6 +30,10 @@
|
||||
#define FSFW_VERBOSE_LEVEL 1
|
||||
#endif /* FSFW_VERBOSE_LEVEL */
|
||||
|
||||
#ifndef FSFW_DISABLE_PRINTOUT
|
||||
#define FSFW_DISABLE_PRINTOUT 0
|
||||
#endif
|
||||
|
||||
#ifndef FSFW_USE_REALTIME_FOR_LINUX
|
||||
#define FSFW_USE_REALTIME_FOR_LINUX 0
|
||||
#endif /* FSFW_USE_REALTIME_FOR_LINUX */
|
||||
@@ -57,16 +61,9 @@
|
||||
#define FSFW_HAL_SPI_WIRETAPPING 0
|
||||
#endif
|
||||
|
||||
#ifndef FSFW_HAL_L3GD20_GYRO_DEBUG
|
||||
#define FSFW_HAL_L3GD20_GYRO_DEBUG 0
|
||||
#endif /* FSFW_HAL_L3GD20_GYRO_DEBUG */
|
||||
|
||||
#ifndef FSFW_HAL_RM3100_MGM_DEBUG
|
||||
#define FSFW_HAL_RM3100_MGM_DEBUG 0
|
||||
#endif /* FSFW_HAL_RM3100_MGM_DEBUG */
|
||||
|
||||
#ifndef FSFW_HAL_LIS3MDL_MGM_DEBUG
|
||||
#define FSFW_HAL_LIS3MDL_MGM_DEBUG 0
|
||||
#endif /* FSFW_HAL_LIS3MDL_MGM_DEBUG */
|
||||
// Can be used for low-level debugging of the I2C bus
|
||||
#ifndef FSFW_HAL_I2C_WIRETAPPING
|
||||
#define FSFW_HAL_I2C_WIRETAPPING 0
|
||||
#endif
|
||||
|
||||
#endif /* FSFW_FSFW_H_ */
|
||||
|
@@ -2,8 +2,8 @@
|
||||
#define FSFW_VERSION_H_
|
||||
|
||||
// Versioning is kept in project CMakeLists.txt file
|
||||
#define FSFW_VERSION @FSFW_VERSION@
|
||||
#define FSFW_SUBVERSION @FSFW_SUBVERSION@
|
||||
#define FSFW_REVISION @FSFW_REVISION@
|
||||
#define FSFW_VERSION_MAJOR @FSFW_VERSION@
|
||||
#define FSFW_VERSION_MINOR @FSFW_SUBVERSION@
|
||||
#define FSFW_VERSION_REVISION @FSFW_REVISION@
|
||||
|
||||
#endif /* FSFW_VERSION_H_ */
|
||||
|
@@ -16,8 +16,8 @@ class CommandActionHelper {
|
||||
public:
|
||||
CommandActionHelper(CommandsActionsIF* owner);
|
||||
virtual ~CommandActionHelper();
|
||||
ReturnValue_t commandAction(object_id_t commandTo, ActionId_t actionId, const uint8_t* data,
|
||||
uint32_t size);
|
||||
ReturnValue_t commandAction(object_id_t commandTo, ActionId_t actionId,
|
||||
const uint8_t* data = nullptr, uint32_t size = 0);
|
||||
ReturnValue_t commandAction(object_id_t commandTo, ActionId_t actionId, SerializeIF* data);
|
||||
ReturnValue_t initialize();
|
||||
ReturnValue_t handleReply(CommandMessage* reply);
|
||||
|
@@ -12,7 +12,9 @@ object_id_t CFDPHandler::packetDestination = 0;
|
||||
|
||||
CFDPHandler::CFDPHandler(object_id_t setObjectId, CFDPDistributor* dist)
|
||||
: SystemObject(setObjectId) {
|
||||
requestQueue = QueueFactory::instance()->createMessageQueue(CFDP_HANDLER_MAX_RECEPTION);
|
||||
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
|
||||
requestQueue = QueueFactory::instance()->createMessageQueue(
|
||||
CFDP_HANDLER_MAX_RECEPTION, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
||||
distributor = dist;
|
||||
}
|
||||
|
||||
|
@@ -6,10 +6,13 @@
|
||||
#include <fsfw/cfdp/tlv/Tlv.h>
|
||||
#include <fsfw/cfdp/tlv/TlvIF.h>
|
||||
#include <fsfw/serialize/SerializeIF.h>
|
||||
#include <fsfw/serviceinterface/ServiceInterface.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
#include "fsfw/FSFW.h"
|
||||
|
||||
namespace cfdp {
|
||||
|
||||
enum FilestoreActionCode {
|
||||
|
@@ -10,16 +10,24 @@ class HybridIterator : public LinkedElement<T>::Iterator, public ArrayList<T, co
|
||||
HybridIterator() {}
|
||||
|
||||
HybridIterator(typename LinkedElement<T>::Iterator *iter)
|
||||
: LinkedElement<T>::Iterator(*iter), value(iter->value), linked(true) {}
|
||||
: LinkedElement<T>::Iterator(*iter), value(iter->value), linked(true) {
|
||||
if(iter != nullptr) {
|
||||
value = iter->value;
|
||||
}
|
||||
}
|
||||
|
||||
HybridIterator(LinkedElement<T> *start)
|
||||
: LinkedElement<T>::Iterator(start), value(start->value), linked(true) {}
|
||||
: LinkedElement<T>::Iterator(start), linked(true) {
|
||||
if(start != nullptr) {
|
||||
value = start->value;
|
||||
}
|
||||
}
|
||||
|
||||
HybridIterator(typename ArrayList<T, count_t>::Iterator start,
|
||||
typename ArrayList<T, count_t>::Iterator end)
|
||||
: ArrayList<T, count_t>::Iterator(start), value(start.value), linked(false), end(end.value) {
|
||||
if (value == this->end) {
|
||||
value = NULL;
|
||||
value = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -13,7 +13,9 @@ ControllerBase::ControllerBase(object_id_t setObjectId, object_id_t parentId,
|
||||
submode(SUBMODE_NONE),
|
||||
modeHelper(this),
|
||||
healthHelper(this, setObjectId) {
|
||||
commandQueue = QueueFactory::instance()->createMessageQueue(commandQueueDepth);
|
||||
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
|
||||
commandQueue = QueueFactory::instance()->createMessageQueue(
|
||||
commandQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
||||
}
|
||||
|
||||
ControllerBase::~ControllerBase() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }
|
||||
|
@@ -1,7 +1,6 @@
|
||||
#ifndef FSFW_CONTROLLER_CONTROLLERBASE_H_
|
||||
#define FSFW_CONTROLLER_CONTROLLERBASE_H_
|
||||
|
||||
#include "fsfw/datapool/HkSwitchHelper.h"
|
||||
#include "fsfw/health/HasHealthIF.h"
|
||||
#include "fsfw/health/HealthHelper.h"
|
||||
#include "fsfw/modes/HasModesIF.h"
|
||||
|
@@ -1,6 +1,4 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
HkSwitchHelper.cpp
|
||||
PoolDataSetBase.cpp
|
||||
PoolEntry.cpp
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
PoolDataSetBase.cpp
|
||||
PoolEntry.cpp
|
||||
)
|
@@ -1,67 +0,0 @@
|
||||
#include "fsfw/datapool/HkSwitchHelper.h"
|
||||
|
||||
#include "fsfw/ipc/QueueFactory.h"
|
||||
|
||||
HkSwitchHelper::HkSwitchHelper(EventReportingProxyIF* eventProxy)
|
||||
: commandActionHelper(this), eventProxy(eventProxy) {
|
||||
actionQueue = QueueFactory::instance()->createMessageQueue();
|
||||
}
|
||||
|
||||
HkSwitchHelper::~HkSwitchHelper() { QueueFactory::instance()->deleteMessageQueue(actionQueue); }
|
||||
|
||||
ReturnValue_t HkSwitchHelper::initialize() {
|
||||
ReturnValue_t result = commandActionHelper.initialize();
|
||||
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t HkSwitchHelper::performOperation(uint8_t operationCode) {
|
||||
CommandMessage command;
|
||||
while (actionQueue->receiveMessage(&command) == HasReturnvaluesIF::RETURN_OK) {
|
||||
ReturnValue_t result = commandActionHelper.handleReply(&command);
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
continue;
|
||||
}
|
||||
command.setToUnknownCommand();
|
||||
actionQueue->reply(&command);
|
||||
}
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
void HkSwitchHelper::stepSuccessfulReceived(ActionId_t actionId, uint8_t step) {}
|
||||
|
||||
void HkSwitchHelper::stepFailedReceived(ActionId_t actionId, uint8_t step,
|
||||
ReturnValue_t returnCode) {
|
||||
eventProxy->forwardEvent(SWITCHING_TM_FAILED, returnCode, actionId);
|
||||
}
|
||||
|
||||
void HkSwitchHelper::dataReceived(ActionId_t actionId, const uint8_t* data, uint32_t size) {}
|
||||
|
||||
void HkSwitchHelper::completionSuccessfulReceived(ActionId_t actionId) {}
|
||||
|
||||
void HkSwitchHelper::completionFailedReceived(ActionId_t actionId, ReturnValue_t returnCode) {
|
||||
eventProxy->forwardEvent(SWITCHING_TM_FAILED, returnCode, actionId);
|
||||
}
|
||||
|
||||
ReturnValue_t HkSwitchHelper::switchHK(SerializeIF* sids, bool enable) {
|
||||
// ActionId_t action = HKService::DISABLE_HK;
|
||||
// if (enable) {
|
||||
// action = HKService::ENABLE_HK;
|
||||
// }
|
||||
//
|
||||
// ReturnValue_t result = commandActionHelper.commandAction(
|
||||
// objects::PUS_HK_SERVICE, action, sids);
|
||||
//
|
||||
// if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
// eventProxy->forwardEvent(SWITCHING_TM_FAILED, result);
|
||||
// }
|
||||
// return result;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
MessageQueueIF* HkSwitchHelper::getCommandQueuePtr() { return actionQueue; }
|
@@ -1,44 +0,0 @@
|
||||
#ifndef FRAMEWORK_DATAPOOL_HKSWITCHHELPER_H_
|
||||
#define FRAMEWORK_DATAPOOL_HKSWITCHHELPER_H_
|
||||
|
||||
#include "fsfw/action/CommandsActionsIF.h"
|
||||
#include "fsfw/events/EventReportingProxyIF.h"
|
||||
#include "fsfw/tasks/ExecutableObjectIF.h"
|
||||
|
||||
// TODO this class violations separation between mission and framework
|
||||
// but it is only a transitional solution until the Datapool is
|
||||
// implemented decentrally
|
||||
|
||||
class HkSwitchHelper : public ExecutableObjectIF, public CommandsActionsIF {
|
||||
public:
|
||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::HK;
|
||||
static const Event SWITCHING_TM_FAILED =
|
||||
MAKE_EVENT(1, severity::LOW); //!< Commanding the HK Service failed, p1: error code, p2
|
||||
//!< action: 0 disable / 1 enable
|
||||
|
||||
HkSwitchHelper(EventReportingProxyIF* eventProxy);
|
||||
virtual ~HkSwitchHelper();
|
||||
|
||||
ReturnValue_t initialize();
|
||||
|
||||
virtual ReturnValue_t performOperation(uint8_t operationCode = 0);
|
||||
|
||||
ReturnValue_t switchHK(SerializeIF* sids, bool enable);
|
||||
|
||||
virtual void setTaskIF(PeriodicTaskIF* task_){};
|
||||
|
||||
protected:
|
||||
virtual void stepSuccessfulReceived(ActionId_t actionId, uint8_t step);
|
||||
virtual void stepFailedReceived(ActionId_t actionId, uint8_t step, ReturnValue_t returnCode);
|
||||
virtual void dataReceived(ActionId_t actionId, const uint8_t* data, uint32_t size);
|
||||
virtual void completionSuccessfulReceived(ActionId_t actionId);
|
||||
virtual void completionFailedReceived(ActionId_t actionId, ReturnValue_t returnCode);
|
||||
virtual MessageQueueIF* getCommandQueuePtr();
|
||||
|
||||
private:
|
||||
CommandActionHelper commandActionHelper;
|
||||
MessageQueueIF* actionQueue;
|
||||
EventReportingProxyIF* eventProxy;
|
||||
};
|
||||
|
||||
#endif /* FRAMEWORK_DATAPOOL_HKSWITCHHELPER_H_ */
|
@@ -7,24 +7,26 @@
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
|
||||
template <typename T>
|
||||
PoolEntry<T>::PoolEntry(std::initializer_list<T> initValue, bool setValid)
|
||||
: length(static_cast<uint8_t>(initValue.size())), valid(setValid) {
|
||||
this->address = new T[this->length];
|
||||
if (initValue.size() == 0) {
|
||||
std::memset(this->address, 0, this->getByteSize());
|
||||
} else {
|
||||
std::copy(initValue.begin(), initValue.end(), this->address);
|
||||
PoolEntry<T>::PoolEntry(uint8_t len, bool setValid): length(len), valid(setValid) {
|
||||
this->address = new T[this->length]();
|
||||
std::memset(this->address, 0, this->getByteSize());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
PoolEntry<T>::PoolEntry(std::initializer_list<T> initValues, bool setValid)
|
||||
: length(static_cast<uint8_t>(initValues.size())), valid(setValid) {
|
||||
this->address = new T[this->length]();
|
||||
if (initValues.size() > 0) {
|
||||
std::copy(initValues.begin(), initValues.end(), this->address);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
PoolEntry<T>::PoolEntry(T* initValue, uint8_t setLength, bool setValid)
|
||||
PoolEntry<T>::PoolEntry(const T* initValue, uint8_t setLength, bool setValid)
|
||||
: length(setLength), valid(setValid) {
|
||||
this->address = new T[this->length];
|
||||
this->address = new T[this->length]();
|
||||
if (initValue != nullptr) {
|
||||
std::memcpy(this->address, initValue, this->getByteSize());
|
||||
} else {
|
||||
std::memset(this->address, 0, this->getByteSize());
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -33,6 +33,9 @@ class PoolEntry : public PoolEntryIF {
|
||||
"instead! The ECSS standard defines a boolean as a one bit "
|
||||
"field. Therefore it is preferred to store a boolean as an "
|
||||
"uint8_t");
|
||||
|
||||
PoolEntry(uint8_t len = 1, bool setValid = false);
|
||||
|
||||
/**
|
||||
* @brief In the classe's constructor, space is allocated on the heap and
|
||||
* potential initialization values are copied to that space.
|
||||
@@ -49,7 +52,7 @@ class PoolEntry : public PoolEntryIF {
|
||||
* @param setValid
|
||||
* Sets the initialization flag. It is invalid by default.
|
||||
*/
|
||||
PoolEntry(std::initializer_list<T> initValue = {0}, bool setValid = false);
|
||||
PoolEntry(std::initializer_list<T> initValue, bool setValid = false);
|
||||
|
||||
/**
|
||||
* @brief In the classe's constructor, space is allocated on the heap and
|
||||
@@ -62,7 +65,7 @@ class PoolEntry : public PoolEntryIF {
|
||||
* @param setValid
|
||||
* Sets the initialization flag. It is invalid by default.
|
||||
*/
|
||||
PoolEntry(T* initValue, uint8_t setLength = 1, bool setValid = false);
|
||||
PoolEntry(const T* initValue, uint8_t setLength = 1, bool setValid = false);
|
||||
|
||||
//! Explicitely deleted copy ctor, copying is not allowed.
|
||||
PoolEntry(const PoolEntry&) = delete;
|
||||
|
@@ -84,8 +84,8 @@ ReturnValue_t LocalDataPoolManager::initializeHousekeepingPoolEntriesOnce() {
|
||||
return result;
|
||||
}
|
||||
|
||||
printWarningOrError(sif::OutputTypes::OUT_WARNING, "initialize", HasReturnvaluesIF::RETURN_FAILED,
|
||||
"The map should only be initialized once");
|
||||
printWarningOrError(sif::OutputTypes::OUT_WARNING, "initializeHousekeepingPoolEntriesOnce",
|
||||
HasReturnvaluesIF::RETURN_FAILED, "The map should only be initialized once");
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
|
@@ -162,6 +162,7 @@ class LocalPoolDataSetBase : public PoolDataSetBase, public MarkChangedIF {
|
||||
object_id_t getCreatorObjectId();
|
||||
|
||||
bool getReportingEnabled() const;
|
||||
void setReportingEnabled(bool enabled);
|
||||
|
||||
/**
|
||||
* Returns the current periodic HK generation interval this set
|
||||
@@ -189,7 +190,6 @@ class LocalPoolDataSetBase : public PoolDataSetBase, public MarkChangedIF {
|
||||
* Used for periodic generation.
|
||||
*/
|
||||
bool reportingEnabled = false;
|
||||
void setReportingEnabled(bool enabled);
|
||||
|
||||
void initializePeriodicHelper(float collectionInterval, dur_millis_t minimumPeriodicInterval,
|
||||
uint8_t nonDiagIntervalFactor = 5);
|
||||
|
@@ -47,13 +47,14 @@ LocalPoolObjectBase::LocalPoolObjectBase(object_id_t poolOwner, lp_id_t poolId,
|
||||
HasLocalDataPoolIF* hkOwner = ObjectManager::instance()->get<HasLocalDataPoolIF>(poolOwner);
|
||||
if (hkOwner == nullptr) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "LocalPoolVariable: The supplied pool owner did not implement the correct "
|
||||
"interface HasLocalDataPoolIF!"
|
||||
<< std::endl;
|
||||
sif::error << "LocalPoolVariable: The supplied pool owner 0x" << std::hex << poolOwner
|
||||
<< std::dec << " did not implement the correct interface "
|
||||
<< "HasLocalDataPoolIF" << std::endl;
|
||||
#else
|
||||
sif::printError(
|
||||
"LocalPoolVariable: The supplied pool owner did not implement the correct "
|
||||
"interface HasLocalDataPoolIF!\n");
|
||||
"LocalPoolVariable: The supplied pool owner 0x%08x did not implement the correct "
|
||||
"interface HasLocalDataPoolIF\n",
|
||||
poolOwner);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
@@ -46,7 +46,7 @@ class StaticLocalDataSet : public LocalPoolDataSetBase {
|
||||
}
|
||||
|
||||
private:
|
||||
std::array<PoolVariableIF*, NUM_VARIABLES> poolVarList;
|
||||
std::array<PoolVariableIF*, NUM_VARIABLES> poolVarList = {};
|
||||
};
|
||||
|
||||
#endif /* FSFW_DATAPOOLLOCAL_STATICLOCALDATASET_H_ */
|
||||
|
@@ -26,11 +26,7 @@ void AssemblyBase::performChildOperation() {
|
||||
|
||||
void AssemblyBase::startTransition(Mode_t mode, Submode_t submode) {
|
||||
doStartTransition(mode, submode);
|
||||
if (modeHelper.isForced()) {
|
||||
triggerEvent(FORCING_MODE, mode, submode);
|
||||
} else {
|
||||
triggerEvent(CHANGING_MODE, mode, submode);
|
||||
}
|
||||
triggerModeHelperEvents(mode, submode);
|
||||
}
|
||||
|
||||
void AssemblyBase::doStartTransition(Mode_t mode, Submode_t submode) {
|
||||
@@ -77,9 +73,10 @@ bool AssemblyBase::handleChildrenChangedHealth() {
|
||||
}
|
||||
HealthState healthState = healthHelper.healthTable->getHealth(iter->first);
|
||||
if (healthState == HasHealthIF::NEEDS_RECOVERY) {
|
||||
triggerEvent(TRYING_RECOVERY);
|
||||
triggerEvent(TRYING_RECOVERY, iter->first, 0);
|
||||
recoveryState = RECOVERY_STARTED;
|
||||
recoveringDevice = iter;
|
||||
// The user needs to take care of commanding the children off in commandChildren
|
||||
doStartTransition(targetMode, targetSubmode);
|
||||
} else {
|
||||
triggerEvent(CHILD_CHANGED_HEALTH);
|
||||
@@ -228,6 +225,9 @@ ReturnValue_t AssemblyBase::handleHealthReply(CommandMessage* message) {
|
||||
bool AssemblyBase::checkAndHandleRecovery() {
|
||||
switch (recoveryState) {
|
||||
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;
|
||||
recoveryOffTimer.resetTimer();
|
||||
return true;
|
||||
@@ -266,3 +266,11 @@ void AssemblyBase::overwriteDeviceHealth(object_id_t objectId, HasHealthIF::Heal
|
||||
modeHelper.setForced(true);
|
||||
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,7 +12,8 @@
|
||||
* Documentation: Dissertation Baetz p.156, 157.
|
||||
*
|
||||
* This class reduces the complexity of controller components which would
|
||||
* otherwise be needed for the handling of redundant devices.
|
||||
* otherwise be needed for the handling of redundant devices. However, it can also be used to
|
||||
* manage the mode keeping and recovery of non-redundant devices
|
||||
*
|
||||
* The template class monitors mode and health state of its children
|
||||
* and checks availability of devices on every detected change.
|
||||
@@ -26,11 +27,9 @@
|
||||
*
|
||||
* Important:
|
||||
*
|
||||
* The implementation must call registerChild(object_id_t child)
|
||||
* for all commanded children during initialization.
|
||||
* The implementation must call #registerChild for all commanded children during initialization.
|
||||
* The implementation must call the initialization function of the base class.
|
||||
* (This will call the function in SubsystemBase)
|
||||
*
|
||||
*/
|
||||
class AssemblyBase : public SubsystemBase {
|
||||
public:
|
||||
@@ -47,13 +46,14 @@ class AssemblyBase : public SubsystemBase {
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Command children to reach [mode,submode] combination
|
||||
* Can be done by setting #commandsOutstanding correctly,
|
||||
* or using executeTable()
|
||||
* Command children to reach [mode,submode] combination. Can be done by setting
|
||||
* #commandsOutstanding correctly, or using #executeTable. In case of an FDIR recovery,
|
||||
* the user needs to ensure that the target devices are healthy. If a device is not healthy,
|
||||
* a recovery might be on-going and the device needs to be commanded to off first.
|
||||
* @param mode
|
||||
* @param submode
|
||||
* @return
|
||||
* - @c RETURN_OK if ok
|
||||
* - @c RETURN_OK if OK
|
||||
* - @c NEED_SECOND_STEP if children need to be commanded again
|
||||
*/
|
||||
virtual ReturnValue_t commandChildren(Mode_t mode, Submode_t submode) = 0;
|
||||
@@ -120,8 +120,19 @@ class AssemblyBase : public SubsystemBase {
|
||||
|
||||
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();
|
||||
|
||||
/**
|
||||
@@ -134,12 +145,37 @@ class AssemblyBase : public SubsystemBase {
|
||||
|
||||
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();
|
||||
|
||||
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);
|
||||
|
||||
/**
|
||||
* 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 bool isInTransition();
|
||||
@@ -160,7 +196,7 @@ class AssemblyBase : public SubsystemBase {
|
||||
* Manages recovery of a device
|
||||
* @return true if recovery is still ongoing, false else.
|
||||
*/
|
||||
bool checkAndHandleRecovery();
|
||||
virtual bool checkAndHandleRecovery();
|
||||
|
||||
/**
|
||||
* Helper method to overwrite health state of one of the children.
|
||||
@@ -168,6 +204,8 @@ class AssemblyBase : public SubsystemBase {
|
||||
* @param objectId Must be a registered child.
|
||||
*/
|
||||
void overwriteDeviceHealth(object_id_t objectId, HasHealthIF::HealthState oldHealth);
|
||||
|
||||
void triggerModeHelperEvents(Mode_t mode, Submode_t submode);
|
||||
};
|
||||
|
||||
#endif /* FSFW_DEVICEHANDLERS_ASSEMBLYBASE_H_ */
|
||||
|
@@ -39,8 +39,9 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, object_id_t device
|
||||
childTransitionDelay(5000),
|
||||
transitionSourceMode(_MODE_POWER_DOWN),
|
||||
transitionSourceSubMode(SUBMODE_NONE) {
|
||||
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
|
||||
commandQueue = QueueFactory::instance()->createMessageQueue(
|
||||
cmdQueueSize, MessageQueueMessage::MAX_MESSAGE_SIZE);
|
||||
cmdQueueSize, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
||||
insertInCommandMap(RAW_COMMAND_ID);
|
||||
cookieInfo.state = COOKIE_UNUSED;
|
||||
cookieInfo.pendingCommand = deviceCommandMap.end();
|
||||
@@ -48,9 +49,6 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, object_id_t device
|
||||
printWarningOrError(sif::OutputTypes::OUT_ERROR, "DeviceHandlerBase",
|
||||
HasReturnvaluesIF::RETURN_FAILED, "Invalid cookie");
|
||||
}
|
||||
if (this->fdirInstance == nullptr) {
|
||||
this->fdirInstance = new DeviceHandlerFailureIsolation(setObjectId, defaultFdirParentId);
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceHandlerBase::setHkDestination(object_id_t hkDestination) {
|
||||
@@ -126,6 +124,18 @@ ReturnValue_t DeviceHandlerBase::initialize() {
|
||||
if (result != RETURN_OK) {
|
||||
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 =
|
||||
ObjectManager::instance()->get<DeviceCommunicationIF>(deviceCommunicationId);
|
||||
@@ -352,14 +362,12 @@ void DeviceHandlerBase::doStateMachine() {
|
||||
}
|
||||
} break;
|
||||
case _MODE_WAIT_OFF: {
|
||||
uint32_t currentUptime;
|
||||
Clock::getUptime(¤tUptime);
|
||||
|
||||
if (powerSwitcher == nullptr) {
|
||||
setMode(MODE_OFF);
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t currentUptime;
|
||||
Clock::getUptime(¤tUptime);
|
||||
if (currentUptime - timeoutStart >= powerSwitcher->getSwitchDelayMs()) {
|
||||
triggerEvent(MODE_TRANSITION_FAILED, PowerSwitchIF::SWITCH_TIMEOUT, 0);
|
||||
setMode(MODE_ERROR_ON);
|
||||
@@ -410,7 +418,7 @@ ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap(
|
||||
DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles, LocalPoolDataSetBase* replyDataSet,
|
||||
size_t replyLen, bool periodic, bool hasDifferentReplyId, DeviceCommandId_t replyId) {
|
||||
// No need to check, as we may try to insert multiple times.
|
||||
insertInCommandMap(deviceCommand);
|
||||
insertInCommandMap(deviceCommand, hasDifferentReplyId, replyId);
|
||||
if (hasDifferentReplyId) {
|
||||
return insertInReplyMap(replyId, maxDelayCycles, replyDataSet, replyLen, periodic);
|
||||
} else {
|
||||
@@ -437,11 +445,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;
|
||||
info.expectedReplies = 0;
|
||||
info.isExecuting = false;
|
||||
info.sendReplyTo = NO_COMMANDER;
|
||||
info.useAlternativeReplyId = alternativeReplyId;
|
||||
info.alternativeReplyId = alternativeReplyId;
|
||||
auto resultPair = deviceCommandMap.emplace(deviceCommand, info);
|
||||
if (resultPair.second) {
|
||||
return RETURN_OK;
|
||||
@@ -451,12 +463,20 @@ ReturnValue_t DeviceHandlerBase::insertInCommandMap(DeviceCommandId_t deviceComm
|
||||
}
|
||||
|
||||
size_t DeviceHandlerBase::getNextReplyLength(DeviceCommandId_t commandId) {
|
||||
DeviceReplyIter iter = deviceReplyMap.find(commandId);
|
||||
if (iter != deviceReplyMap.end()) {
|
||||
return iter->second.replyLen;
|
||||
DeviceCommandId_t replyId = NO_COMMAND_ID;
|
||||
DeviceCommandMap::iterator command = cookieInfo.pendingCommand;
|
||||
if (command->second.useAlternativeReplyId) {
|
||||
replyId = command->second.alternativeReplyId;
|
||||
} 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,
|
||||
@@ -651,7 +671,9 @@ void DeviceHandlerBase::doGetWrite() {
|
||||
|
||||
// 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.
|
||||
result = enableReplyInReplyMap(cookieInfo.pendingCommand);
|
||||
DeviceCommandMap::iterator command = cookieInfo.pendingCommand;
|
||||
result = enableReplyInReplyMap(command, 1, command->second.useAlternativeReplyId,
|
||||
command->second.alternativeReplyId);
|
||||
} else {
|
||||
// always generate a failure event, so that FDIR knows what's up
|
||||
triggerEvent(DEVICE_SENDING_COMMAND_FAILED, result, cookieInfo.pendingCommand->first);
|
||||
@@ -824,7 +846,7 @@ void DeviceHandlerBase::handleReply(const uint8_t* receivedData, DeviceCommandId
|
||||
}
|
||||
|
||||
ReturnValue_t DeviceHandlerBase::getStorageData(store_address_t storageAddress, uint8_t** data,
|
||||
uint32_t* len) {
|
||||
size_t* len) {
|
||||
size_t lenTmp;
|
||||
|
||||
if (IPCStore == nullptr) {
|
||||
@@ -1385,6 +1407,8 @@ void DeviceHandlerBase::setTaskIF(PeriodicTaskIF* task) { executingTask = task;
|
||||
void DeviceHandlerBase::debugInterface(uint8_t positionTracker, object_id_t objectId,
|
||||
uint32_t parameter) {}
|
||||
|
||||
Submode_t DeviceHandlerBase::getInitialSubmode() { return SUBMODE_NONE; }
|
||||
|
||||
void DeviceHandlerBase::performOperationHook() {}
|
||||
|
||||
ReturnValue_t DeviceHandlerBase::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
||||
@@ -1407,7 +1431,7 @@ ReturnValue_t DeviceHandlerBase::initializeAfterTaskCreation() {
|
||||
this->poolManager.initializeAfterTaskCreation();
|
||||
|
||||
if (setStartupImmediately) {
|
||||
startTransition(MODE_ON, SUBMODE_NONE);
|
||||
startTransition(MODE_ON, getInitialSubmode());
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
@@ -1491,3 +1515,11 @@ MessageQueueId_t DeviceHandlerBase::getCommanderQueueId(DeviceCommandId_t replyI
|
||||
}
|
||||
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,6 +103,9 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
||||
DeviceHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, CookieIF *comCookie,
|
||||
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);
|
||||
|
||||
/**
|
||||
@@ -478,7 +481,9 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
||||
* @return - @c RETURN_OK when the command was successfully inserted,
|
||||
* - @c RETURN_FAILED else.
|
||||
*/
|
||||
ReturnValue_t insertInCommandMap(DeviceCommandId_t deviceCommand);
|
||||
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
|
||||
@@ -647,6 +652,12 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
||||
virtual void debugInterface(uint8_t positionTracker = 0, object_id_t objectId = 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:
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_BASE;
|
||||
|
||||
@@ -673,7 +684,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
||||
//! Pointer to the raw packet that will be sent.
|
||||
uint8_t *rawPacket = nullptr;
|
||||
//! Size of the #rawPacket.
|
||||
uint32_t rawPacketLen = 0;
|
||||
size_t rawPacketLen = 0;
|
||||
|
||||
/**
|
||||
* The mode the device handler is currently in.
|
||||
@@ -751,6 +762,8 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
||||
//! if this is != NO_COMMANDER, DHB was commanded externally and shall
|
||||
//! report everything to commander.
|
||||
MessageQueueId_t sendReplyTo;
|
||||
bool useAlternativeReplyId;
|
||||
DeviceCommandId_t alternativeReplyId;
|
||||
};
|
||||
using DeviceCommandMap = std::map<DeviceCommandId_t, DeviceCommandInfo>;
|
||||
/**
|
||||
@@ -818,6 +831,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
||||
/** Pointer to the used FDIR instance. If not provided by child,
|
||||
* default class is instantiated. */
|
||||
FailureIsolationBase *fdirInstance;
|
||||
object_id_t parent = objects::NO_OBJECT;
|
||||
|
||||
//! To correctly delete the default instance.
|
||||
bool defaultFDIRUsed;
|
||||
@@ -1250,7 +1264,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
||||
* - @c RETURN_FAILED IPCStore is nullptr
|
||||
* - the return value from the IPCStore if it was not @c RETURN_OK
|
||||
*/
|
||||
ReturnValue_t getStorageData(store_address_t storageAddress, uint8_t **data, uint32_t *len);
|
||||
ReturnValue_t getStorageData(store_address_t storageAddress, uint8_t **data, size_t *len);
|
||||
|
||||
/**
|
||||
* @param modeTo either @c MODE_ON, MODE_NORMAL or MODE_RAW, nothing else!
|
||||
|
@@ -29,6 +29,7 @@ ReturnValue_t DeviceHandlerFailureIsolation::eventReceived(EventMessage* event)
|
||||
switch (event->getEvent()) {
|
||||
case HasModesIF::MODE_TRANSITION_FAILED:
|
||||
case HasModesIF::OBJECT_IN_INVALID_MODE:
|
||||
case DeviceHandlerIF::DEVICE_WANTS_HARD_REBOOT:
|
||||
// We'll try a recovery as long as defined in MAX_REBOOT.
|
||||
// Might cause some AssemblyBase cycles, so keep number low.
|
||||
handleRecovery(event->getEvent());
|
||||
|
@@ -109,6 +109,7 @@ class DeviceHandlerIF {
|
||||
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_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;
|
||||
|
||||
|
@@ -8,7 +8,9 @@ HealthDevice::HealthDevice(object_id_t setObjectId, MessageQueueId_t parentQueue
|
||||
parentQueue(parentQueue),
|
||||
commandQueue(),
|
||||
healthHelper(this, setObjectId) {
|
||||
commandQueue = QueueFactory::instance()->createMessageQueue(3);
|
||||
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
|
||||
commandQueue = QueueFactory::instance()->createMessageQueue(
|
||||
3, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
||||
}
|
||||
|
||||
HealthDevice::~HealthDevice() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }
|
||||
|
@@ -7,8 +7,14 @@
|
||||
// could be moved to more suitable location
|
||||
#include <events/subsystemIdRanges.h>
|
||||
|
||||
typedef uint16_t EventId_t;
|
||||
typedef uint8_t EventSeverity_t;
|
||||
using EventId_t = uint16_t;
|
||||
using EventSeverity_t = uint8_t;
|
||||
using UniqueEventId_t = uint8_t;
|
||||
|
||||
namespace severity {
|
||||
enum Severity : EventSeverity_t { INFO = 1, LOW = 2, MEDIUM = 3, HIGH = 4 };
|
||||
|
||||
} // namespace severity
|
||||
|
||||
#define MAKE_EVENT(id, severity) (((severity) << 16) + (SUBSYSTEM_ID * 100) + (id))
|
||||
|
||||
@@ -20,18 +26,11 @@ constexpr EventId_t getEventId(Event event) { return (event & 0xFFFF); }
|
||||
|
||||
constexpr EventSeverity_t getSeverity(Event event) { return ((event >> 16) & 0xFF); }
|
||||
|
||||
constexpr Event makeEvent(uint8_t subsystemId, uint8_t uniqueEventId,
|
||||
constexpr Event makeEvent(uint8_t subsystemId, UniqueEventId_t uniqueEventId,
|
||||
EventSeverity_t eventSeverity) {
|
||||
return (eventSeverity << 16) + (subsystemId * 100) + uniqueEventId;
|
||||
}
|
||||
|
||||
} // namespace event
|
||||
|
||||
namespace severity {
|
||||
static constexpr EventSeverity_t INFO = 1;
|
||||
static constexpr EventSeverity_t LOW = 2;
|
||||
static constexpr EventSeverity_t MEDIUM = 3;
|
||||
static constexpr EventSeverity_t HIGH = 4;
|
||||
} // namespace severity
|
||||
|
||||
#endif /* EVENTOBJECT_EVENT_H_ */
|
||||
|
@@ -18,8 +18,9 @@ const LocalPool::LocalPoolConfig EventManager::poolConfig = {
|
||||
EventManager::EventManager(object_id_t setObjectId)
|
||||
: SystemObject(setObjectId), factoryBackend(0, poolConfig, false, true) {
|
||||
mutex = MutexFactory::instance()->createMutex();
|
||||
eventReportQueue = QueueFactory::instance()->createMessageQueue(MAX_EVENTS_PER_CYCLE,
|
||||
EventMessage::EVENT_MESSAGE_SIZE);
|
||||
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
|
||||
eventReportQueue = QueueFactory::instance()->createMessageQueue(
|
||||
MAX_EVENTS_PER_CYCLE, EventMessage::EVENT_MESSAGE_SIZE, &mqArgs);
|
||||
}
|
||||
|
||||
EventManager::~EventManager() {
|
||||
@@ -46,9 +47,20 @@ ReturnValue_t EventManager::performOperation(uint8_t opCode) {
|
||||
|
||||
void EventManager::notifyListeners(EventMessage* message) {
|
||||
lockMutex();
|
||||
for (auto iter = listenerList.begin(); iter != listenerList.end(); ++iter) {
|
||||
if (iter->second.match(message)) {
|
||||
MessageQueueSenderIF::sendMessage(iter->first, message, message->getSender());
|
||||
for (auto& listener : listenerList) {
|
||||
if (listener.second.match(message)) {
|
||||
ReturnValue_t result =
|
||||
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();
|
||||
@@ -189,4 +201,19 @@ 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 */
|
||||
|
@@ -42,6 +42,7 @@ class EventManager : public EventManagerIF, public ExecutableObjectIF, public Sy
|
||||
object_id_t reporterFrom = 0, object_id_t reporterTo = 0,
|
||||
bool reporterInverted = false);
|
||||
ReturnValue_t performOperation(uint8_t opCode);
|
||||
void printListeners();
|
||||
|
||||
protected:
|
||||
MessageQueueIF* eventReportQueue = nullptr;
|
||||
|
@@ -9,8 +9,9 @@
|
||||
FailureIsolationBase::FailureIsolationBase(object_id_t owner, object_id_t parent,
|
||||
uint8_t messageDepth, uint8_t parameterDomainBase)
|
||||
: ownerId(owner), faultTreeParent(parent), parameterDomainBase(parameterDomainBase) {
|
||||
eventQueue =
|
||||
QueueFactory::instance()->createMessageQueue(messageDepth, EventMessage::EVENT_MESSAGE_SIZE);
|
||||
auto mqArgs = MqArgs(owner, static_cast<void*>(this));
|
||||
eventQueue = QueueFactory::instance()->createMessageQueue(
|
||||
messageDepth, EventMessage::EVENT_MESSAGE_SIZE, &mqArgs);
|
||||
}
|
||||
|
||||
FailureIsolationBase::~FailureIsolationBase() {
|
||||
@@ -51,11 +52,12 @@ ReturnValue_t FailureIsolationBase::initialize() {
|
||||
ObjectManager::instance()->get<ConfirmsFailuresIF>(faultTreeParent);
|
||||
if (parentIF == nullptr) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "FailureIsolationBase::intialize: Parent object"
|
||||
<< "invalid." << std::endl;
|
||||
#endif
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "Make sure it implements ConfirmsFailuresIF." << std::endl;
|
||||
sif::error << "FailureIsolationBase::intialize: Parent object "
|
||||
<< "invalid" << std::endl;
|
||||
sif::error << "Make sure it implements ConfirmsFailuresIF" << std::endl;
|
||||
#else
|
||||
sif::printError("FailureIsolationBase::intialize: Parent object invalid\n");
|
||||
sif::printError("Make sure it implements ConfirmsFailuresIF\n");
|
||||
#endif
|
||||
return ObjectManagerIF::CHILD_INIT_FAILED;
|
||||
return RETURN_FAILED;
|
||||
|
@@ -14,13 +14,12 @@ class FailureIsolationBase : public HasReturnvaluesIF,
|
||||
public HasParametersIF {
|
||||
public:
|
||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::FDIR_1;
|
||||
static const Event FDIR_CHANGED_STATE =
|
||||
MAKE_EVENT(1, severity::INFO); //!< FDIR has an internal state, which changed from par2
|
||||
//!< (oldState) to par1 (newState).
|
||||
static const Event FDIR_STARTS_RECOVERY = MAKE_EVENT(
|
||||
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); //!< FDIR turns off device. Par1: event that caused recovery.
|
||||
//! FDIR has an internal state, which changed from par2 (oldState) to par1 (newState).
|
||||
static const Event FDIR_CHANGED_STATE = MAKE_EVENT(1, severity::INFO);
|
||||
//! FDIR tries to restart device. Par1: event that caused recovery.
|
||||
static const Event FDIR_STARTS_RECOVERY = MAKE_EVENT(2, severity::MEDIUM);
|
||||
//! FDIR turns off device. Par1: event that caused recovery.
|
||||
static const Event FDIR_TURNS_OFF_DEVICE = MAKE_EVENT(3, severity::MEDIUM);
|
||||
|
||||
FailureIsolationBase(object_id_t owner, object_id_t parent = objects::NO_OBJECT,
|
||||
uint8_t messageDepth = 10, uint8_t parameterDomainBase = 0xF0);
|
||||
|
@@ -1,13 +1,13 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
arrayprinter.cpp
|
||||
AsciiConverter.cpp
|
||||
CRC.cpp
|
||||
DleEncoder.cpp
|
||||
PeriodicOperationDivider.cpp
|
||||
timevalOperations.cpp
|
||||
Type.cpp
|
||||
bitutility.cpp
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
arrayprinter.cpp
|
||||
AsciiConverter.cpp
|
||||
CRC.cpp
|
||||
DleEncoder.cpp
|
||||
DleParser.cpp
|
||||
PeriodicOperationDivider.cpp
|
||||
timevalOperations.cpp
|
||||
Type.cpp
|
||||
bitutility.cpp
|
||||
)
|
||||
|
||||
add_subdirectory(math)
|
||||
|
@@ -28,7 +28,7 @@ const uint16_t CRC::crc16ccitt_table[256] = {
|
||||
|
||||
// CRC implementation
|
||||
uint16_t CRC::crc16ccitt(uint8_t const input[], uint32_t length, uint16_t startingCrc) {
|
||||
uint8_t *data = (uint8_t *)input;
|
||||
const uint8_t *data = static_cast<const uint8_t *>(input);
|
||||
unsigned int tbl_idx;
|
||||
|
||||
while (length--) {
|
||||
@@ -39,88 +39,4 @@ uint16_t CRC::crc16ccitt(uint8_t const input[], uint32_t length, uint16_t starti
|
||||
}
|
||||
return startingCrc & 0xffff;
|
||||
|
||||
// The part below is not used!
|
||||
// bool temr[16];
|
||||
// bool xor_out[16];
|
||||
// bool r[16];
|
||||
// bool d[8];
|
||||
// uint16_t crc_value = 0;
|
||||
//
|
||||
//
|
||||
// for (int i=0; i<16 ;i++) {
|
||||
// temr[i] = false;
|
||||
// xor_out[i] = false;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// for (int i=0; i<16 ;i++)
|
||||
// r[i] = true; // initialize with 0xFFFF
|
||||
//
|
||||
//
|
||||
//
|
||||
// for (int j=0; j<length ;j++)
|
||||
// {
|
||||
//
|
||||
// for (int i=0; i<8 ;i++)
|
||||
// if ((input[j] & 1<<i) == 1<<i)
|
||||
// d[7-i]=true; // reverse input data
|
||||
// else
|
||||
// d[7-i]=false; // reverse input data
|
||||
//
|
||||
//
|
||||
//
|
||||
// temr[0] = d[4] ^ d[0];
|
||||
// temr[1] = d[5] ^ d[1];
|
||||
// temr[2] = d[6] ^ d[2];
|
||||
// temr[3] = d[7] ^ d[3];
|
||||
// temr[4] = r[12] ^ r[8];
|
||||
// temr[5] = r[13] ^ r[9];
|
||||
// temr[6] = r[14] ^ r[10];
|
||||
// temr[7] = r[15] ^ r[11];
|
||||
// temr[8] = d[4] ^ r[12];
|
||||
// temr[9] = d[5] ^ r[13];
|
||||
// temr[10] = d[6] ^ r[14];
|
||||
// temr[11] = d[7] ^ r[15];
|
||||
// temr[12] = temr[0] ^ temr[4];
|
||||
// temr[13] = temr[1] ^ temr[5];
|
||||
// temr[14] = temr[2] ^ temr[6];
|
||||
// temr[15] = temr[3] ^ temr[7];
|
||||
//
|
||||
//
|
||||
// xor_out[0] = temr[12];
|
||||
// xor_out[1] = temr[13];
|
||||
// xor_out[2] = temr[14];
|
||||
// xor_out[3] = temr[15];
|
||||
// xor_out[4] = temr[8];
|
||||
// xor_out[5] = temr[9] ^ temr[12];
|
||||
// xor_out[6] = temr[10] ^ temr[13];
|
||||
// xor_out[7] = temr[11] ^ temr[14];
|
||||
// xor_out[8] = temr[15] ^ r[0];
|
||||
// xor_out[9] = temr[8] ^ r[1];
|
||||
// xor_out[10] = temr[9] ^ r[2];
|
||||
// xor_out[11] = temr[10] ^ r[3];
|
||||
// xor_out[12] = temr[11] ^ temr[12] ^ r[4];
|
||||
// xor_out[13] = temr[13] ^ r[5];
|
||||
// xor_out[14] = temr[14] ^ r[6];
|
||||
// xor_out[15] = temr[15] ^ r[7];
|
||||
//
|
||||
// for (int i=0; i<16 ;i++)
|
||||
// {
|
||||
// r[i]= xor_out[i] ;
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
// for (int i=0; i<16 ;i++)
|
||||
// {
|
||||
// if (xor_out[i] == true)
|
||||
// crc_value = crc_value + pow(2,(15 -i)); // reverse CrC result before
|
||||
//Final XOR
|
||||
// }
|
||||
//
|
||||
// crc_value = 0;// for debug mode
|
||||
// return (crc_value);
|
||||
|
||||
} /* Calculate_CRC() */
|
||||
|
231
src/fsfw/globalfunctions/DleParser.cpp
Normal file
231
src/fsfw/globalfunctions/DleParser.cpp
Normal file
@@ -0,0 +1,231 @@
|
||||
#include "DleParser.h"
|
||||
|
||||
#include <fsfw/globalfunctions/DleEncoder.h>
|
||||
#include <fsfw/serviceinterface/ServiceInterface.h>
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
DleParser::DleParser(SimpleRingBuffer& decodeRingBuf, DleEncoder& decoder, BufPair encodedBuf,
|
||||
BufPair decodedBuf, UserHandler handler, void* args)
|
||||
: decodeRingBuf(decodeRingBuf),
|
||||
decoder(decoder),
|
||||
encodedBuf(encodedBuf),
|
||||
decodedBuf(decodedBuf),
|
||||
handler(handler),
|
||||
ctx(args) {
|
||||
if (handler == nullptr) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "DleParser::DleParser: Invalid user handler" << std::endl;
|
||||
#else
|
||||
sif::printError("DleParser::DleParser: Invalid user handler\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t DleParser::passData(uint8_t* data, size_t len) {
|
||||
if (data == nullptr or len == 0 or handler == nullptr) {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
size_t copyIntoRingBufFromHere = 0;
|
||||
size_t copyAmount = len;
|
||||
size_t startIdx = 0;
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
bool startFoundInThisPacket = false;
|
||||
for (size_t idx = 0; idx < len; idx++) {
|
||||
if (data[idx] == DleEncoder::STX_CHAR) {
|
||||
if (not startFound and not startFoundInThisPacket) {
|
||||
startIdx = idx;
|
||||
copyIntoRingBufFromHere = idx;
|
||||
copyAmount = len - idx;
|
||||
} else {
|
||||
// Maybe print warning, should not happen
|
||||
decodeRingBuf.clear();
|
||||
ErrorInfo info;
|
||||
info.len = idx;
|
||||
prepareErrorContext(ErrorTypes::CONSECUTIVE_STX_CHARS, info);
|
||||
handler(ctx);
|
||||
copyIntoRingBufFromHere = idx;
|
||||
copyAmount = len - idx;
|
||||
}
|
||||
startFound = true;
|
||||
startFoundInThisPacket = true;
|
||||
} else if (data[idx] == DleEncoder::ETX_CHAR) {
|
||||
if (startFoundInThisPacket) {
|
||||
size_t readLen = 0;
|
||||
size_t decodedLen = 0;
|
||||
result = decoder.decode(data + startIdx, idx + 1 - startIdx, &readLen, decodedBuf.first,
|
||||
decodedBuf.second, &decodedLen);
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
ctx.setType(ContextType::PACKET_FOUND);
|
||||
ctx.decodedPacket.first = decodedBuf.first;
|
||||
ctx.decodedPacket.second = decodedLen;
|
||||
this->handler(ctx);
|
||||
} else if (result == DleEncoder::STREAM_TOO_SHORT) {
|
||||
ErrorInfo info;
|
||||
info.res = result;
|
||||
prepareErrorContext(ErrorTypes::DECODING_BUF_TOO_SMALL, info);
|
||||
handler(ctx);
|
||||
} else {
|
||||
ErrorInfo info;
|
||||
info.res = result;
|
||||
prepareErrorContext(ErrorTypes::DECODING_BUF_TOO_SMALL, info);
|
||||
handler(ctx);
|
||||
}
|
||||
decodeRingBuf.clear();
|
||||
if ((idx + 1) < len) {
|
||||
copyIntoRingBufFromHere = idx + 1;
|
||||
copyAmount = len - idx - 1;
|
||||
} else {
|
||||
copyAmount = 0;
|
||||
}
|
||||
} else if (startFound) {
|
||||
// ETX found but STX was found in another mini packet. Reconstruct the full packet
|
||||
// to decode it
|
||||
result = decodeRingBuf.writeData(data, idx + 1);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
ErrorInfo info;
|
||||
info.res = result;
|
||||
prepareErrorContext(ErrorTypes::RING_BUF_ERROR, info);
|
||||
handler(ctx);
|
||||
}
|
||||
size_t fullEncodedLen = decodeRingBuf.getAvailableReadData();
|
||||
if (fullEncodedLen > encodedBuf.second) {
|
||||
ErrorInfo info;
|
||||
info.len = fullEncodedLen;
|
||||
prepareErrorContext(ErrorTypes::ENCODED_BUF_TOO_SMALL, info);
|
||||
handler(ctx);
|
||||
decodeRingBuf.clear();
|
||||
} else {
|
||||
size_t decodedLen = 0;
|
||||
size_t readLen = 0;
|
||||
decodeRingBuf.readData(encodedBuf.first, fullEncodedLen, true);
|
||||
result = decoder.decode(encodedBuf.first, fullEncodedLen, &readLen, decodedBuf.first,
|
||||
decodedBuf.second, &decodedLen);
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
if (this->handler != nullptr) {
|
||||
ctx.setType(ContextType::PACKET_FOUND);
|
||||
ctx.decodedPacket.first = decodedBuf.first;
|
||||
ctx.decodedPacket.second = decodedLen;
|
||||
this->handler(ctx);
|
||||
}
|
||||
} else if (result == DleEncoder::STREAM_TOO_SHORT) {
|
||||
ErrorInfo info;
|
||||
info.res = result;
|
||||
prepareErrorContext(ErrorTypes::DECODING_BUF_TOO_SMALL, info);
|
||||
handler(ctx);
|
||||
} else {
|
||||
ErrorInfo info;
|
||||
info.res = result;
|
||||
prepareErrorContext(ErrorTypes::DECODE_ERROR, info);
|
||||
handler(ctx);
|
||||
}
|
||||
decodeRingBuf.clear();
|
||||
startFound = false;
|
||||
startFoundInThisPacket = false;
|
||||
if ((idx + 1) < len) {
|
||||
copyIntoRingBufFromHere = idx + 1;
|
||||
copyAmount = len - idx - 1;
|
||||
} else {
|
||||
copyAmount = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// End data without preceeding STX
|
||||
ErrorInfo info;
|
||||
info.len = idx + 1;
|
||||
prepareErrorContext(ErrorTypes::CONSECUTIVE_ETX_CHARS, info);
|
||||
handler(ctx);
|
||||
decodeRingBuf.clear();
|
||||
if ((idx + 1) < len) {
|
||||
copyIntoRingBufFromHere = idx + 1;
|
||||
copyAmount = len - idx - 1;
|
||||
} else {
|
||||
copyAmount = 0;
|
||||
}
|
||||
}
|
||||
startFoundInThisPacket = false;
|
||||
startFound = false;
|
||||
}
|
||||
}
|
||||
if (copyAmount > 0) {
|
||||
result = decodeRingBuf.writeData(data + copyIntoRingBufFromHere, copyAmount);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
ErrorInfo info;
|
||||
info.res = result;
|
||||
prepareErrorContext(ErrorTypes::RING_BUF_ERROR, info);
|
||||
handler(ctx);
|
||||
}
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
void DleParser::defaultFoundPacketHandler(uint8_t* packet, size_t len, void* args) {
|
||||
#if FSFW_VERBOSE_LEVEL >= 1
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::info << "DleParserBase::handleFoundPacket: Detected DLE packet with " << len << " bytes"
|
||||
<< std::endl;
|
||||
#else
|
||||
sif::printInfo("DleParserBase::handleFoundPacket: Detected DLE packet with %d bytes\n", len);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void DleParser::defaultErrorHandler(ErrorTypes err, ErrorInfo ctx) {
|
||||
switch (err) {
|
||||
case (ErrorTypes::NONE): {
|
||||
errorPrinter("No error");
|
||||
break;
|
||||
}
|
||||
case (ErrorTypes::DECODE_ERROR): {
|
||||
errorPrinter("Decode Error");
|
||||
break;
|
||||
}
|
||||
case (ErrorTypes::RING_BUF_ERROR): {
|
||||
errorPrinter("Ring Buffer Error");
|
||||
break;
|
||||
}
|
||||
case (ErrorTypes::ENCODED_BUF_TOO_SMALL):
|
||||
case (ErrorTypes::DECODING_BUF_TOO_SMALL): {
|
||||
char opt[64];
|
||||
snprintf(opt, sizeof(opt), ": Too small for packet with length %d", ctx.len);
|
||||
if (err == ErrorTypes::ENCODED_BUF_TOO_SMALL) {
|
||||
errorPrinter("Encoded buf too small", opt);
|
||||
} else {
|
||||
errorPrinter("Decoding buf too small", opt);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (ErrorTypes::CONSECUTIVE_STX_CHARS): {
|
||||
errorPrinter("Consecutive STX chars detected");
|
||||
break;
|
||||
}
|
||||
case (ErrorTypes::CONSECUTIVE_ETX_CHARS): {
|
||||
errorPrinter("Consecutive ETX chars detected");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DleParser::errorPrinter(const char* str, const char* opt) {
|
||||
if (opt == nullptr) {
|
||||
opt = "";
|
||||
}
|
||||
#if FSFW_VERBOSE_LEVEL >= 1
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::info << "DleParserBase::handleParseError: " << str << opt << std::endl;
|
||||
#else
|
||||
sif::printInfo("DleParserBase::handleParseError: %s%s\n", str, opt);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void DleParser::prepareErrorContext(ErrorTypes err, ErrorInfo info) {
|
||||
ctx.setType(ContextType::ERROR);
|
||||
ctx.error.first = err;
|
||||
ctx.error.second = info;
|
||||
}
|
||||
|
||||
void DleParser::reset() {
|
||||
startFound = false;
|
||||
decodeRingBuf.clear();
|
||||
}
|
127
src/fsfw/globalfunctions/DleParser.h
Normal file
127
src/fsfw/globalfunctions/DleParser.h
Normal file
@@ -0,0 +1,127 @@
|
||||
#ifndef MISSION_DEVICES_DLEPARSER_H_
|
||||
#define MISSION_DEVICES_DLEPARSER_H_
|
||||
|
||||
#include <fsfw/container/SimpleRingBuffer.h>
|
||||
#include <fsfw/globalfunctions/DleEncoder.h>
|
||||
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <utility>
|
||||
|
||||
/**
|
||||
* @brief This base helper class can be used to extract DLE encoded packets from a data stream
|
||||
* @details
|
||||
* The core API of the parser takes received packets which can contains DLE packets. The parser
|
||||
* can deal with DLE packets split across multiple packets. It does so by using a dedicated
|
||||
* decoding ring buffer. The user can process received packets and detect errors by
|
||||
* overriding two provided virtual methods. This also allows detecting multiple DLE packets
|
||||
* inside one passed packet.
|
||||
*/
|
||||
class DleParser : public HasReturnvaluesIF {
|
||||
public:
|
||||
using BufPair = std::pair<uint8_t*, size_t>;
|
||||
|
||||
enum class ContextType { PACKET_FOUND, ERROR };
|
||||
|
||||
enum class ErrorTypes {
|
||||
NONE,
|
||||
ENCODED_BUF_TOO_SMALL,
|
||||
DECODING_BUF_TOO_SMALL,
|
||||
DECODE_ERROR,
|
||||
RING_BUF_ERROR,
|
||||
CONSECUTIVE_STX_CHARS,
|
||||
CONSECUTIVE_ETX_CHARS
|
||||
};
|
||||
|
||||
union ErrorInfo {
|
||||
size_t len;
|
||||
ReturnValue_t res;
|
||||
};
|
||||
|
||||
using ErrorPair = std::pair<ErrorTypes, ErrorInfo>;
|
||||
|
||||
struct Context {
|
||||
public:
|
||||
Context(void* args) : userArgs(args) { setType(ContextType::PACKET_FOUND); }
|
||||
|
||||
void setType(ContextType type) {
|
||||
if (type == ContextType::PACKET_FOUND) {
|
||||
error.first = ErrorTypes::NONE;
|
||||
error.second.len = 0;
|
||||
} else {
|
||||
decodedPacket.first = nullptr;
|
||||
decodedPacket.second = 0;
|
||||
}
|
||||
}
|
||||
|
||||
ContextType getType() const { return type; }
|
||||
|
||||
BufPair decodedPacket = {};
|
||||
ErrorPair error;
|
||||
void* userArgs;
|
||||
|
||||
private:
|
||||
ContextType type;
|
||||
};
|
||||
|
||||
using UserHandler = void (*)(const Context& ctx);
|
||||
|
||||
/**
|
||||
* Base class constructor
|
||||
* @param decodeRingBuf Ring buffer used to store multiple packets to allow detecting DLE packets
|
||||
* split across multiple packets
|
||||
* @param decoder Decoder instance
|
||||
* @param encodedBuf Buffer used to store encoded packets. It has to be large enough to hold
|
||||
* the largest expected encoded DLE packet size
|
||||
* @param decodedBuf Buffer used to store decoded packets. It has to be large enough to hold the
|
||||
* largest expected decoded DLE packet size
|
||||
* @param handler Function which will be called on a found packet
|
||||
* @param args Arbitrary user argument
|
||||
*/
|
||||
DleParser(SimpleRingBuffer& decodeRingBuf, DleEncoder& decoder, BufPair encodedBuf,
|
||||
BufPair decodedBuf, UserHandler handler, void* args);
|
||||
|
||||
/**
|
||||
* This function allows to pass new data into the parser. It then scans for DLE packets
|
||||
* automatically and inserts (part of) the packet into a ring buffer if necessary.
|
||||
* @param data
|
||||
* @param len
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t passData(uint8_t* data, size_t len);
|
||||
|
||||
/**
|
||||
* Example found packet handler
|
||||
* function call
|
||||
* @param packet Decoded packet
|
||||
* @param len Length of detected packet
|
||||
*/
|
||||
void defaultFoundPacketHandler(uint8_t* packet, size_t len, void* args);
|
||||
/**
|
||||
* Will be called if an error occured in the #passData call
|
||||
* @param err
|
||||
* @param ctx Context information depending on the error type
|
||||
* - For buffer length errors, will be set to the detected packet length which is too large
|
||||
* - For decode or ring buffer errors, will be set to the result returned from the failed call
|
||||
*/
|
||||
static void defaultErrorHandler(ErrorTypes err, ErrorInfo ctx);
|
||||
|
||||
static void errorPrinter(const char* str, const char* opt = nullptr);
|
||||
|
||||
void prepareErrorContext(ErrorTypes err, ErrorInfo ctx);
|
||||
/**
|
||||
* Resets the parser by resetting the internal states and clearing the decoding ring buffer
|
||||
*/
|
||||
void reset();
|
||||
|
||||
private:
|
||||
SimpleRingBuffer& decodeRingBuf;
|
||||
DleEncoder& decoder;
|
||||
BufPair encodedBuf;
|
||||
BufPair decodedBuf;
|
||||
UserHandler handler = nullptr;
|
||||
Context ctx;
|
||||
bool startFound = false;
|
||||
};
|
||||
|
||||
#endif /* MISSION_DEVICES_DLEPARSER_H_ */
|
@@ -1,6 +1,7 @@
|
||||
#include "fsfw/globalfunctions/arrayprinter.h"
|
||||
|
||||
#include <bitset>
|
||||
#include <cmath>
|
||||
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
|
||||
@@ -68,7 +69,7 @@ void arrayprinter::printHex(const uint8_t *data, size_t size, size_t maxCharPerL
|
||||
currentPos += snprintf(printBuffer + currentPos, 6, "%02x", data[i]);
|
||||
if (i < size - 1) {
|
||||
currentPos += sprintf(printBuffer + currentPos, ",");
|
||||
if (i > 0 and (i + 1) % maxCharPerLine == 0) {
|
||||
if ((i + 1) % maxCharPerLine == 0) {
|
||||
currentPos += sprintf(printBuffer + currentPos, "\n");
|
||||
}
|
||||
}
|
||||
@@ -97,20 +98,21 @@ void arrayprinter::printDec(const uint8_t *data, size_t size, size_t maxCharPerL
|
||||
}
|
||||
std::cout << "]" << std::endl;
|
||||
#else
|
||||
// General format: 32, 243, -12 so it is number of chars times 5
|
||||
// General format: 32,243,-12 so it is number of chars times 4
|
||||
// plus line break plus small safety margin.
|
||||
char printBuffer[(size + 1) * 5 + 1] = {};
|
||||
uint16_t expectedLines = ceil((double)size / maxCharPerLine);
|
||||
char printBuffer[size * 4 + 1 + expectedLines] = {};
|
||||
size_t currentPos = 0;
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
// To avoid buffer overflows.
|
||||
if (sizeof(printBuffer) - currentPos <= 5) {
|
||||
if (sizeof(printBuffer) - currentPos <= 4) {
|
||||
break;
|
||||
}
|
||||
|
||||
currentPos += snprintf(printBuffer + currentPos, 3, "%d", data[i]);
|
||||
currentPos += snprintf(printBuffer + currentPos, 4, "%d", data[i]);
|
||||
if (i < size - 1) {
|
||||
currentPos += sprintf(printBuffer + currentPos, ",");
|
||||
if (i > 0 and (i + 1) % maxCharPerLine == 0) {
|
||||
if ((i + 1) % maxCharPerLine == 0) {
|
||||
currentPos += sprintf(printBuffer + currentPos, "\n");
|
||||
}
|
||||
}
|
||||
|
@@ -179,6 +179,9 @@ class MatchTree : public SerializeableMatcherIF<T>, public BinaryTree<Serializea
|
||||
virtual ReturnValue_t cleanUpElement(iterator position) { return HasReturnvaluesIF::RETURN_OK; }
|
||||
|
||||
bool matchSubtree(iterator iter, T number) {
|
||||
if(iter == nullptr) {
|
||||
return false;
|
||||
}
|
||||
bool isMatch = iter->match(number);
|
||||
if (isMatch) {
|
||||
if (iter.left() == this->end()) {
|
||||
|
@@ -23,19 +23,15 @@ class HasHealthIF {
|
||||
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_PROBLEMS = MAKE_EVENT(8, severity::LOW);
|
||||
static const Event OVERWRITING_HEALTH =
|
||||
MAKE_EVENT(9, severity::LOW); //!< Assembly overwrites health information of children to keep
|
||||
//!< satellite alive.
|
||||
static const Event TRYING_RECOVERY =
|
||||
MAKE_EVENT(10, severity::MEDIUM); //!< Someone starts a recovery of a component (typically
|
||||
//!< power-cycle). No parameters.
|
||||
static const Event RECOVERY_STEP =
|
||||
MAKE_EVENT(11, severity::MEDIUM); //!< Recovery is ongoing. Comes twice during recovery. P1:
|
||||
//!< 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.
|
||||
|
||||
//! Assembly overwrites health information of children to keep satellite alive.
|
||||
static const Event OVERWRITING_HEALTH = MAKE_EVENT(9, severity::LOW);
|
||||
//! Someone starts a recovery of a component (typically power-cycle). No parameters.
|
||||
static const Event TRYING_RECOVERY = MAKE_EVENT(10, severity::MEDIUM);
|
||||
//! Recovery is ongoing. Comes twice during recovery.
|
||||
//! P1: 0 for the first, 1 for the second event. P2: 0
|
||||
static const Event RECOVERY_STEP = MAKE_EVENT(11, severity::MEDIUM);
|
||||
//! Recovery was completed. Not necessarily successful. No parameters.
|
||||
static const Event RECOVERY_DONE = MAKE_EVENT(12, severity::MEDIUM);
|
||||
virtual ~HasHealthIF() {}
|
||||
|
||||
virtual MessageQueueId_t getCommandQueue() const = 0;
|
||||
|
@@ -7,11 +7,13 @@
|
||||
|
||||
InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth)
|
||||
: SystemObject(setObjectId),
|
||||
commandQueue(QueueFactory::instance()->createMessageQueue(messageQueueDepth)),
|
||||
poolManager(this, commandQueue),
|
||||
internalErrorSid(setObjectId, InternalErrorDataset::ERROR_SET_ID),
|
||||
internalErrorDataset(this) {
|
||||
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); }
|
||||
@@ -36,15 +38,14 @@ ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) {
|
||||
if ((newQueueHits > 0) or (newTmHits > 0) or (newStoreHits > 0)) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::debug << "InternalErrorReporter::performOperation: Errors "
|
||||
<< "occured!" << std::endl;
|
||||
sif::debug << "Queue errors: " << newQueueHits << std::endl;
|
||||
sif::debug << "TM errors: " << newTmHits << std::endl;
|
||||
sif::debug << "Store errors: " << newStoreHits << std::endl;
|
||||
<< "occured: Queue | TM | Store : " << newQueueHits << " | " << newTmHits << " | "
|
||||
<< newStoreHits << std::endl;
|
||||
#else
|
||||
sif::printDebug("InternalErrorReporter::performOperation: Errors occured!\n");
|
||||
sif::printDebug("Queue errors: %lu\n", static_cast<unsigned int>(newQueueHits));
|
||||
sif::printDebug("TM errors: %lu\n", static_cast<unsigned int>(newTmHits));
|
||||
sif::printDebug("Store errors: %lu\n", static_cast<unsigned int>(newStoreHits));
|
||||
sif::printDebug(
|
||||
"InternalErrorReporter::performOperation: Errors occured: Queue | TM | Store: %lu | %lu "
|
||||
"| %lu\n",
|
||||
static_cast<unsigned int>(newQueueHits), static_cast<unsigned int>(newTmHits),
|
||||
static_cast<unsigned int>(newStoreHits));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -57,6 +58,9 @@ ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) {
|
||||
internalErrorDataset.storeHits.value += newStoreHits;
|
||||
internalErrorDataset.tmHits.value += newTmHits;
|
||||
internalErrorDataset.setValidity(true, true);
|
||||
if ((newQueueHits != 0) or (newStoreHits != 0) or (newTmHits != 0)) {
|
||||
internalErrorDataset.setChanged(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,14 +81,6 @@ uint32_t InternalErrorReporter::getAndResetQueueHits() {
|
||||
return value;
|
||||
}
|
||||
|
||||
uint32_t InternalErrorReporter::getQueueHits() {
|
||||
uint32_t value;
|
||||
mutex->lockMutex(timeoutType, timeoutMs);
|
||||
value = queueHits;
|
||||
mutex->unlockMutex();
|
||||
return value;
|
||||
}
|
||||
|
||||
void InternalErrorReporter::incrementQueueHits() {
|
||||
mutex->lockMutex(timeoutType, timeoutMs);
|
||||
queueHits++;
|
||||
@@ -100,14 +96,6 @@ uint32_t InternalErrorReporter::getAndResetTmHits() {
|
||||
return value;
|
||||
}
|
||||
|
||||
uint32_t InternalErrorReporter::getTmHits() {
|
||||
uint32_t value;
|
||||
mutex->lockMutex(timeoutType, timeoutMs);
|
||||
value = tmHits;
|
||||
mutex->unlockMutex();
|
||||
return value;
|
||||
}
|
||||
|
||||
void InternalErrorReporter::incrementTmHits() {
|
||||
mutex->lockMutex(timeoutType, timeoutMs);
|
||||
tmHits++;
|
||||
@@ -125,14 +113,6 @@ uint32_t InternalErrorReporter::getAndResetStoreHits() {
|
||||
return value;
|
||||
}
|
||||
|
||||
uint32_t InternalErrorReporter::getStoreHits() {
|
||||
uint32_t value;
|
||||
mutex->lockMutex(timeoutType, timeoutMs);
|
||||
value = storeHits;
|
||||
mutex->unlockMutex();
|
||||
return value;
|
||||
}
|
||||
|
||||
void InternalErrorReporter::incrementStoreHits() {
|
||||
mutex->lockMutex(timeoutType, timeoutMs);
|
||||
storeHits++;
|
||||
|
@@ -46,11 +46,11 @@ class InternalErrorReporter : public SystemObject,
|
||||
virtual ReturnValue_t initializeAfterTaskCreation() override;
|
||||
virtual ReturnValue_t performOperation(uint8_t opCode) override;
|
||||
|
||||
virtual void queueMessageNotSent();
|
||||
virtual void queueMessageNotSent() override;
|
||||
|
||||
virtual void lostTm();
|
||||
virtual void lostTm() override;
|
||||
|
||||
virtual void storeFull();
|
||||
virtual void storeFull() override;
|
||||
|
||||
virtual void setTaskIF(PeriodicTaskIF* task) override;
|
||||
|
||||
@@ -74,15 +74,12 @@ class InternalErrorReporter : public SystemObject,
|
||||
uint32_t storeHits = 0;
|
||||
|
||||
uint32_t getAndResetQueueHits();
|
||||
uint32_t getQueueHits();
|
||||
void incrementQueueHits();
|
||||
|
||||
uint32_t getAndResetTmHits();
|
||||
uint32_t getTmHits();
|
||||
void incrementTmHits();
|
||||
|
||||
uint32_t getAndResetStoreHits();
|
||||
uint32_t getStoreHits();
|
||||
void incrementStoreHits();
|
||||
};
|
||||
|
||||
|
@@ -1,22 +1,34 @@
|
||||
#ifndef INTERNALERRORREPORTERIF_H_
|
||||
#define INTERNALERRORREPORTERIF_H_
|
||||
|
||||
/**
|
||||
* @brief Interface which is used to report internal errors like full message queues or stores.
|
||||
* @details
|
||||
* This interface smust be used for the InteralErrorReporter object.
|
||||
* It should be used to indicate that there was a Problem with Queues or Stores.
|
||||
*
|
||||
* It can be used to report missing Telemetry which could not be sent due to a internal problem.
|
||||
*
|
||||
*/
|
||||
class InternalErrorReporterIF {
|
||||
public:
|
||||
virtual ~InternalErrorReporterIF() {}
|
||||
|
||||
/**
|
||||
* Thread safe
|
||||
* @brief Function to be called if a message queue could not be sent.
|
||||
* @details OSAL Implementations should call this function to indicate that
|
||||
* a message was lost.
|
||||
*
|
||||
* Implementations are required to be Thread safe
|
||||
*/
|
||||
virtual void queueMessageNotSent() = 0;
|
||||
|
||||
/**
|
||||
* Thread safe
|
||||
* @brief Function to be called if Telemetry could not be sent
|
||||
* @details Implementations must be Thread safe
|
||||
*/
|
||||
virtual void lostTm() = 0;
|
||||
|
||||
/**
|
||||
* Thread safe
|
||||
* @brief Function to be called if a onboard storage is full
|
||||
* @details Implementations must be Thread safe
|
||||
*/
|
||||
virtual void storeFull() = 0;
|
||||
};
|
||||
|
@@ -1,6 +1,6 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
CommandMessage.cpp
|
||||
CommandMessageCleaner.cpp
|
||||
MessageQueueMessage.cpp
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
CommandMessage.cpp
|
||||
CommandMessageCleaner.cpp
|
||||
MessageQueueMessage.cpp
|
||||
MessageQueueBase.cpp
|
||||
)
|
64
src/fsfw/ipc/MessageQueueBase.cpp
Normal file
64
src/fsfw/ipc/MessageQueueBase.cpp
Normal file
@@ -0,0 +1,64 @@
|
||||
#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);
|
||||
}
|
41
src/fsfw/ipc/MessageQueueBase.h
Normal file
41
src/fsfw/ipc/MessageQueueBase.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#ifndef FSFW_SRC_FSFW_IPC_MESSAGEQUEUEBASE_H_
|
||||
#define FSFW_SRC_FSFW_IPC_MESSAGEQUEUEBASE_H_
|
||||
|
||||
#include <fsfw/ipc/definitions.h>
|
||||
#include <fsfw/ipc/MessageQueueIF.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,7 @@
|
||||
#ifndef FSFW_IPC_MESSAGEQUEUEIF_H_
|
||||
#define FSFW_IPC_MESSAGEQUEUEIF_H_
|
||||
|
||||
#include <fsfw/ipc/definitions.h>
|
||||
#include <cstdint>
|
||||
|
||||
#include "../returnvalues/HasReturnvaluesIF.h"
|
||||
@@ -44,8 +45,7 @@ class MessageQueueIF {
|
||||
virtual ReturnValue_t reply(MessageQueueMessageIF* message) = 0;
|
||||
|
||||
/**
|
||||
* @brief This function reads available messages from the message queue
|
||||
* and returns the sender.
|
||||
* @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.
|
||||
@@ -78,19 +78,16 @@ class MessageQueueIF {
|
||||
*/
|
||||
virtual ReturnValue_t flush(uint32_t* count) = 0;
|
||||
/**
|
||||
* @brief This method returns the message queue
|
||||
* id of the last communication partner.
|
||||
* @brief This method returns the message queue ID of the last communication partner.
|
||||
*/
|
||||
virtual MessageQueueId_t getLastPartner() const = 0;
|
||||
/**
|
||||
* @brief This method returns the message queue
|
||||
* id of this class's message queue.
|
||||
* @brief This method returns the message queue ID of this class's message queue.
|
||||
*/
|
||||
virtual MessageQueueId_t getId() const = 0;
|
||||
|
||||
/**
|
||||
* @brief With the sendMessage call, a queue message
|
||||
* is sent to a receiving queue.
|
||||
* @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
|
||||
@@ -129,8 +126,7 @@ class MessageQueueIF {
|
||||
bool ignoreFault = false) = 0;
|
||||
|
||||
/**
|
||||
* @brief The sendToDefaultFrom method sends a queue message
|
||||
* to the default destination.
|
||||
* @brief The sendToDefaultFrom method sends a queue message to the default destination.
|
||||
* @details
|
||||
* In all other aspects, it works identical to the sendMessage method.
|
||||
* @param message
|
||||
@@ -164,6 +160,8 @@ class MessageQueueIF {
|
||||
virtual MessageQueueId_t getDefaultDestination() const = 0;
|
||||
|
||||
virtual bool isDefaultDestinationSet() const = 0;
|
||||
|
||||
virtual MqArgs& getMqArgs() = 0;
|
||||
};
|
||||
|
||||
#endif /* FSFW_IPC_MESSAGEQUEUEIF_H_ */
|
||||
|
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "MessageQueueIF.h"
|
||||
#include "MessageQueueMessage.h"
|
||||
#include "definitions.h"
|
||||
|
||||
/**
|
||||
* Creates message queues.
|
||||
@@ -22,7 +23,8 @@ class QueueFactory {
|
||||
static QueueFactory* instance();
|
||||
|
||||
MessageQueueIF* createMessageQueue(uint32_t messageDepth = 3,
|
||||
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE);
|
||||
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE,
|
||||
MqArgs* args = nullptr);
|
||||
|
||||
void deleteMessageQueue(MessageQueueIF* queue);
|
||||
|
||||
|
14
src/fsfw/ipc/definitions.h
Normal file
14
src/fsfw/ipc/definitions.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef FSFW_SRC_FSFW_IPC_DEFINITIONS_H_
|
||||
#define FSFW_SRC_FSFW_IPC_DEFINITIONS_H_
|
||||
|
||||
#include <fsfw/objectmanager/SystemObjectIF.h>
|
||||
#include <fsfw/objectmanager/frameworkObjects.h>
|
||||
|
||||
struct MqArgs {
|
||||
MqArgs(){};
|
||||
MqArgs(object_id_t objectId, void* args = nullptr) : objectId(objectId), args(args) {}
|
||||
object_id_t objectId = objects::NO_OBJECT;
|
||||
void* args = nullptr;
|
||||
};
|
||||
|
||||
#endif /* FSFW_SRC_FSFW_IPC_DEFINITIONS_H_ */
|
@@ -19,32 +19,33 @@ class HasModesIF {
|
||||
static const ReturnValue_t INVALID_SUBMODE = MAKE_RETURN_CODE(0x04);
|
||||
|
||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::SYSTEM_MANAGER;
|
||||
static const Event CHANGING_MODE =
|
||||
MAKE_EVENT(0, severity::INFO); //!< An object announces changing the mode. p1: target mode.
|
||||
//!< p2: target submode
|
||||
static const Event MODE_INFO = MAKE_EVENT(
|
||||
1,
|
||||
severity::INFO); //!< An Object announces its mode; parameter1 is mode, parameter2 is submode
|
||||
//! An object announces changing the mode. p1: target mode. p2: target submode
|
||||
static const Event CHANGING_MODE = MAKE_EVENT(0, severity::INFO);
|
||||
//! An Object announces its mode; parameter1 is mode, parameter2 is submode
|
||||
static const Event MODE_INFO = MAKE_EVENT(1, severity::INFO);
|
||||
static const Event FALLBACK_FAILED = MAKE_EVENT(2, severity::HIGH);
|
||||
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 OBJECT_IN_INVALID_MODE =
|
||||
MAKE_EVENT(5, severity::LOW); //!< Indicates a bug or configuration failure: Object is in a
|
||||
//!< mode it should never be in.
|
||||
static const Event FORCING_MODE = MAKE_EVENT(
|
||||
6, severity::MEDIUM); //!< The mode is changed, but for some reason, the change is forced,
|
||||
//!< i.e. EXTERNAL_CONTROL ignored. p1: target mode. p2: target submode
|
||||
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.
|
||||
//! Indicates a bug or configuration failure: Object is in a mode it should never be in.
|
||||
static const Event OBJECT_IN_INVALID_MODE = MAKE_EVENT(5, severity::LOW);
|
||||
//! The mode is changed, but for some reason, the change is forced, i.e. EXTERNAL_CONTROL ignored.
|
||||
//! p1: target mode. p2: target submode
|
||||
static const Event FORCING_MODE = MAKE_EVENT(6, severity::MEDIUM);
|
||||
//! A mode command was rejected by the called object. Par1: called object id, Par2: return code.
|
||||
static const Event MODE_CMD_REJECTED = MAKE_EVENT(7, severity::LOW);
|
||||
|
||||
static const Mode_t MODE_ON =
|
||||
1; //!< The device is powered and ready to perform operations. In this mode, no commands are
|
||||
//!< sent by the device handler itself, but direct commands van be commanded and will be
|
||||
//!< interpreted
|
||||
static const Mode_t MODE_OFF = 0; //!< The device is powered off. The only command accepted in
|
||||
//!< this mode is a mode change to on.
|
||||
static const Submode_t SUBMODE_NONE = 0; //!< To avoid checks against magic number "0".
|
||||
//! The device is powered and ready to perform operations. In this mode, no commands are
|
||||
//! sent by the device handler itself, but direct commands van be commanded and will be
|
||||
//! interpreted
|
||||
static constexpr Mode_t MODE_ON = 1;
|
||||
//! The device is powered off. The only command accepted in this mode is a mode change to on.
|
||||
static constexpr Mode_t MODE_OFF = 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 MessageQueueId_t getCommandQueue() const = 0;
|
||||
|
@@ -95,13 +95,16 @@ void ObjectManager::initialize() {
|
||||
for (auto const& it : objectList) {
|
||||
result = it.second->initialize();
|
||||
if (result != RETURN_OK) {
|
||||
#if FSFW_VERBOSE_LEVEL >= 1
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
object_id_t var = it.first;
|
||||
sif::error << "ObjectManager::initialize: Object 0x" << std::hex << std::setw(8)
|
||||
<< std::setfill('0') << var
|
||||
<< " failed to "
|
||||
"initialize with code 0x"
|
||||
<< result << std::dec << std::setfill(' ') << std::endl;
|
||||
<< std::setfill('0') << it.first << " failed to initialize with code 0x" << result
|
||||
<< std::dec << std::setfill(' ') << std::endl;
|
||||
#else
|
||||
sif::printError(
|
||||
"ObjectManager::initialize: Object 0x%08x failed to initialize with code 0x%04x\n", var,
|
||||
it.first);
|
||||
#endif
|
||||
#endif
|
||||
errorCount++;
|
||||
}
|
||||
|
@@ -4,8 +4,9 @@
|
||||
#include "fsfw/osal/freertos/QueueMapManager.h"
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
|
||||
MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize)
|
||||
: maxMessageSize(maxMessageSize) {
|
||||
MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize, MqArgs* args)
|
||||
: MessageQueueBase(MessageQueueIF::NO_QUEUE, MessageQueueIF::NO_QUEUE, args),
|
||||
maxMessageSize(maxMessageSize) {
|
||||
handle = xQueueCreate(messageDepth, maxMessageSize);
|
||||
if (handle == nullptr) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
@@ -15,10 +16,10 @@ MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize)
|
||||
#else
|
||||
sif::printError("MessageQueue::MessageQueue: Creation failed\n");
|
||||
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
|
||||
}
|
||||
QueueMapManager::instance()->addMessageQueue(handle, &queueId);
|
||||
QueueMapManager::instance()->addMessageQueue(handle, &id);
|
||||
}
|
||||
|
||||
MessageQueue::~MessageQueue() {
|
||||
@@ -29,28 +30,6 @@ MessageQueue::~MessageQueue() {
|
||||
|
||||
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,
|
||||
MessageQueueId_t sentFrom, bool ignoreFault) {
|
||||
return sendMessageFromMessageQueue(sendTo, message, sentFrom, ignoreFault, callContext);
|
||||
@@ -72,27 +51,16 @@ ReturnValue_t MessageQueue::handleSendResult(BaseType_t result, bool ignoreFault
|
||||
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) {
|
||||
BaseType_t result = xQueueReceive(handle, reinterpret_cast<void*>(message->getBuffer()), 0);
|
||||
if (result == pdPASS) {
|
||||
this->lastPartner = message->getSender();
|
||||
this->last = message->getSender();
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
} else {
|
||||
return MessageQueueIF::EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
MessageQueueId_t MessageQueue::getLastPartner() const { return lastPartner; }
|
||||
|
||||
ReturnValue_t MessageQueue::flush(uint32_t* count) {
|
||||
// TODO FreeRTOS does not support flushing partially
|
||||
// Is always successful
|
||||
@@ -100,17 +68,6 @@ ReturnValue_t MessageQueue::flush(uint32_t* count) {
|
||||
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.
|
||||
ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
|
||||
MessageQueueMessageIF* message,
|
||||
|
@@ -1,12 +1,14 @@
|
||||
#ifndef FSFW_OSAL_FREERTOS_MESSAGEQUEUE_H_
|
||||
#define FSFW_OSAL_FREERTOS_MESSAGEQUEUE_H_
|
||||
|
||||
#include <fsfw/ipc/MessageQueueBase.h>
|
||||
#include "FreeRTOS.h"
|
||||
#include "TaskManagement.h"
|
||||
#include "fsfw/internalerror/InternalErrorReporterIF.h"
|
||||
#include "fsfw/ipc/MessageQueueIF.h"
|
||||
#include "fsfw/ipc/MessageQueueMessage.h"
|
||||
#include "fsfw/ipc/MessageQueueMessageIF.h"
|
||||
#include "fsfw/ipc/definitions.h"
|
||||
#include "queue.h"
|
||||
|
||||
/**
|
||||
@@ -32,7 +34,7 @@
|
||||
* @ingroup osal
|
||||
* @ingroup message_queue
|
||||
*/
|
||||
class MessageQueue : public MessageQueueIF {
|
||||
class MessageQueue : public MessageQueueBase {
|
||||
friend class MessageQueueSenderIF;
|
||||
|
||||
public:
|
||||
@@ -53,7 +55,8 @@ class MessageQueue : public MessageQueueIF {
|
||||
* This should be left default.
|
||||
*/
|
||||
MessageQueue(size_t messageDepth = 3,
|
||||
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE);
|
||||
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE,
|
||||
MqArgs* args = nullptr);
|
||||
|
||||
/** Copying message queues forbidden */
|
||||
MessageQueue(const MessageQueue&) = delete;
|
||||
@@ -73,40 +76,15 @@ class MessageQueue : public MessageQueueIF {
|
||||
*/
|
||||
void switchSystemContext(CallContext callContext);
|
||||
|
||||
/** MessageQueueIF implementation */
|
||||
ReturnValue_t sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
||||
bool ignoreFault = false) override;
|
||||
QueueHandle_t getNativeQueueHandle();
|
||||
|
||||
ReturnValue_t sendToDefault(MessageQueueMessageIF* message) override;
|
||||
|
||||
ReturnValue_t reply(MessageQueueMessageIF* message) override;
|
||||
// Implement non-generic MessageQueueIF functions not handled by MessageQueueBase
|
||||
virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
||||
MessageQueueId_t sentFrom = NO_QUEUE,
|
||||
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 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:
|
||||
/**
|
||||
* @brief Implementation to be called from any send Call within
|
||||
@@ -136,12 +114,8 @@ class MessageQueue : public MessageQueueIF {
|
||||
static ReturnValue_t handleSendResult(BaseType_t result, bool ignoreFault);
|
||||
|
||||
private:
|
||||
bool defaultDestinationSet = false;
|
||||
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;
|
||||
//! Stores the current system context
|
||||
CallContext callContext = CallContext::TASK;
|
||||
|
@@ -97,7 +97,11 @@ void PeriodicTask::taskFunctionality() {
|
||||
|
||||
ReturnValue_t PeriodicTask::addComponent(object_id_t 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
|
||||
sif::error << "PeriodicTask::addComponent: Invalid object. Make sure"
|
||||
"it implement ExecutableObjectIF"
|
||||
@@ -105,8 +109,8 @@ ReturnValue_t PeriodicTask::addComponent(object_id_t object) {
|
||||
#endif
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
objectList.push_back(newObject);
|
||||
newObject->setTaskIF(this);
|
||||
objectList.push_back(object);
|
||||
object->setTaskIF(this);
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
@@ -63,6 +63,16 @@ class PeriodicTask : public PeriodicTaskIF, public FreeRTOSTaskIF {
|
||||
*/
|
||||
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;
|
||||
|
||||
ReturnValue_t sleepFor(uint32_t ms) override;
|
||||
|
@@ -22,8 +22,9 @@ QueueFactory::QueueFactory() {}
|
||||
|
||||
QueueFactory::~QueueFactory() {}
|
||||
|
||||
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize) {
|
||||
return new MessageQueue(messageDepth, maxMessageSize);
|
||||
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize,
|
||||
MqArgs* args) {
|
||||
return new MessageQueue(messageDepth, maxMessageSize, args);
|
||||
}
|
||||
|
||||
void QueueFactory::deleteMessageQueue(MessageQueueIF* queue) { delete queue; }
|
||||
|
@@ -150,17 +150,14 @@ ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval*
|
||||
time_tm.tm_hour = from->hour;
|
||||
time_tm.tm_min = from->minute;
|
||||
time_tm.tm_sec = from->second;
|
||||
time_tm.tm_isdst = 0;
|
||||
|
||||
time_t seconds = mktime(&time_tm);
|
||||
time_t seconds = timegm(&time_tm);
|
||||
|
||||
to->tv_sec = seconds;
|
||||
to->tv_usec = from->usecond;
|
||||
// Fails in 2038..
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "Clock::convertTimeBla: not implemented yet" << std::endl;
|
||||
#endif
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) {
|
||||
|
@@ -8,10 +8,12 @@
|
||||
#include "fsfw/osal/host/QueueMapManager.h"
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
|
||||
MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize)
|
||||
: messageSize(maxMessageSize), messageDepth(messageDepth) {
|
||||
MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize, MqArgs* args)
|
||||
: MessageQueueBase(MessageQueueIF::NO_QUEUE, MessageQueueIF::NO_QUEUE, args),
|
||||
messageSize(maxMessageSize),
|
||||
messageDepth(messageDepth) {
|
||||
queueLock = MutexFactory::instance()->createMutex();
|
||||
auto result = QueueMapManager::instance()->addMessageQueue(this, &mqId);
|
||||
auto result = QueueMapManager::instance()->addMessageQueue(this, &id);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "MessageQueue::MessageQueue: Could not be created" << std::endl;
|
||||
@@ -23,42 +25,11 @@ MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize)
|
||||
|
||||
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,
|
||||
MessageQueueId_t sentFrom, bool 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) {
|
||||
if (messageQueue.empty()) {
|
||||
return MessageQueueIF::EMPTY;
|
||||
@@ -68,12 +39,10 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
|
||||
message->getBuffer());
|
||||
messageQueue.pop();
|
||||
// The last partner is the first uint32_t field in the message
|
||||
this->lastPartner = message->getSender();
|
||||
this->last = message->getSender();
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
MessageQueueId_t MessageQueue::getLastPartner() const { return lastPartner; }
|
||||
|
||||
ReturnValue_t MessageQueue::flush(uint32_t* count) {
|
||||
*count = messageQueue.size();
|
||||
// Clears the queue.
|
||||
@@ -81,17 +50,6 @@ ReturnValue_t MessageQueue::flush(uint32_t* count) {
|
||||
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.
|
||||
ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
|
||||
MessageQueueMessageIF* message,
|
||||
@@ -125,6 +83,13 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
|
||||
memcpy(targetQueue->messageQueue.back().data(), message->getBuffer(),
|
||||
message->getMaximumMessageSize());
|
||||
} else {
|
||||
if (not ignoreFault) {
|
||||
InternalErrorReporterIF* internalErrorReporter =
|
||||
ObjectManager::instance()->get<InternalErrorReporterIF>(objects::INTERNAL_ERROR_REPORTER);
|
||||
if (internalErrorReporter != nullptr) {
|
||||
internalErrorReporter->queueMessageNotSent();
|
||||
}
|
||||
}
|
||||
return MessageQueueIF::FULL;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
|
@@ -1,15 +1,17 @@
|
||||
#ifndef FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_
|
||||
#define FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_
|
||||
|
||||
#include <memory>
|
||||
#include <queue>
|
||||
|
||||
#include "fsfw/ipc/MessageQueueBase.h"
|
||||
#include "fsfw/internalerror/InternalErrorReporterIF.h"
|
||||
#include "fsfw/ipc/MessageQueueIF.h"
|
||||
#include "fsfw/ipc/MessageQueueMessage.h"
|
||||
#include "fsfw/ipc/MutexIF.h"
|
||||
#include "fsfw/ipc/definitions.h"
|
||||
#include "fsfw/timemanager/Clock.h"
|
||||
|
||||
#include <memory>
|
||||
#include <queue>
|
||||
|
||||
/**
|
||||
* @brief This class manages sending and receiving of
|
||||
* message queue messages.
|
||||
@@ -33,7 +35,7 @@
|
||||
* @ingroup osal
|
||||
* @ingroup message_queue
|
||||
*/
|
||||
class MessageQueue : public MessageQueueIF {
|
||||
class MessageQueue : public MessageQueueBase {
|
||||
friend class MessageQueueSenderIF;
|
||||
|
||||
public:
|
||||
@@ -54,7 +56,8 @@ class MessageQueue : public MessageQueueIF {
|
||||
* This should be left default.
|
||||
*/
|
||||
MessageQueue(size_t messageDepth = 3,
|
||||
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE);
|
||||
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE,
|
||||
MqArgs* args = nullptr);
|
||||
|
||||
/** Copying message queues forbidden */
|
||||
MessageQueue(const MessageQueue&) = delete;
|
||||
@@ -67,121 +70,12 @@ class MessageQueue : public MessageQueueIF {
|
||||
*/
|
||||
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) 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.
|
||||
*/
|
||||
// Implement non-generic MessageQueueIF functions not handled by MessageQueueBase
|
||||
virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
||||
MessageQueueId_t sentFrom = NO_QUEUE,
|
||||
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;
|
||||
/**
|
||||
* 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;
|
||||
/**
|
||||
* @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 unlockQueue();
|
||||
@@ -211,23 +105,14 @@ class MessageQueue : public MessageQueueIF {
|
||||
MessageQueueId_t sentFrom = NO_QUEUE,
|
||||
bool ignoreFault = false);
|
||||
|
||||
// static ReturnValue_t handleSendResult(BaseType_t result, bool ignoreFault);
|
||||
|
||||
private:
|
||||
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 messageDepth = 0;
|
||||
|
||||
MutexIF* queueLock;
|
||||
|
||||
bool defaultDestinationSet = false;
|
||||
MessageQueueId_t defaultDestination = MessageQueueIF::NO_QUEUE;
|
||||
MessageQueueId_t lastPartner = MessageQueueIF::NO_QUEUE;
|
||||
};
|
||||
|
||||
#endif /* FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_ */
|
||||
|
@@ -102,11 +102,15 @@ void PeriodicTask::taskFunctionality() {
|
||||
|
||||
ReturnValue_t PeriodicTask::addComponent(object_id_t 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;
|
||||
}
|
||||
newObject->setTaskIF(this);
|
||||
objectList.push_back(newObject);
|
||||
object->setTaskIF(this);
|
||||
objectList.push_back(object);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
|
@@ -59,6 +59,16 @@ class PeriodicTask : public PeriodicTaskIF {
|
||||
*/
|
||||
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;
|
||||
|
||||
ReturnValue_t sleepFor(uint32_t ms);
|
||||
|
@@ -27,12 +27,13 @@ QueueFactory::QueueFactory() {}
|
||||
|
||||
QueueFactory::~QueueFactory() {}
|
||||
|
||||
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize) {
|
||||
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize,
|
||||
MqArgs* args) {
|
||||
// A thread-safe queue can be implemented by using a combination
|
||||
// of std::queue and std::mutex. This uses dynamic memory allocation
|
||||
// which could be alleviated by using a custom allocator, external library
|
||||
// (etl::queue) or simply using std::queue, we're on a host machine anyway.
|
||||
return new MessageQueue(messageDepth, maxMessageSize);
|
||||
return new MessageQueue(messageDepth, maxMessageSize, args);
|
||||
}
|
||||
|
||||
void QueueFactory::deleteMessageQueue(MessageQueueIF* queue) { delete queue; }
|
||||
|
@@ -1,6 +1,7 @@
|
||||
#include "fsfw/osal/linux/BinarySemaphore.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <cstring>
|
||||
|
@@ -1,29 +1,29 @@
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
Clock.cpp
|
||||
BinarySemaphore.cpp
|
||||
CountingSemaphore.cpp
|
||||
FixedTimeslotTask.cpp
|
||||
InternalErrorCodes.cpp
|
||||
MessageQueue.cpp
|
||||
Mutex.cpp
|
||||
MutexFactory.cpp
|
||||
PeriodicPosixTask.cpp
|
||||
PosixThread.cpp
|
||||
QueueFactory.cpp
|
||||
SemaphoreFactory.cpp
|
||||
TaskFactory.cpp
|
||||
tcpipHelpers.cpp
|
||||
unixUtility.cpp
|
||||
BinarySemaphore.cpp
|
||||
CountingSemaphore.cpp
|
||||
FixedTimeslotTask.cpp
|
||||
InternalErrorCodes.cpp
|
||||
MessageQueue.cpp
|
||||
Mutex.cpp
|
||||
MutexFactory.cpp
|
||||
PeriodicPosixTask.cpp
|
||||
PosixThread.cpp
|
||||
QueueFactory.cpp
|
||||
SemaphoreFactory.cpp
|
||||
TaskFactory.cpp
|
||||
tcpipHelpers.cpp
|
||||
unixUtility.cpp
|
||||
)
|
||||
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
rt
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
rt
|
||||
)
|
||||
|
||||
target_link_libraries(${LIB_FSFW_NAME} INTERFACE
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
)
|
||||
|
||||
|
@@ -1,4 +1,5 @@
|
||||
#include "fsfw/timemanager/Clock.h"
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
|
||||
#include <linux/sysinfo.h>
|
||||
#include <sys/sysinfo.h>
|
||||
@@ -7,12 +8,13 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
#include <cstring>
|
||||
|
||||
uint16_t Clock::leapSeconds = 0;
|
||||
MutexIF* Clock::timeMutex = NULL;
|
||||
|
||||
void handleClockError(const char* func);
|
||||
|
||||
uint32_t Clock::getTicksPerSecond(void) {
|
||||
uint32_t ticks = sysconf(_SC_CLK_TCK);
|
||||
return ticks;
|
||||
@@ -27,7 +29,7 @@ ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
|
||||
|
||||
int status = clock_settime(CLOCK_REALTIME, &timeUnix);
|
||||
if (status != 0) {
|
||||
// TODO errno
|
||||
handleClockError("setClock");
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
@@ -39,7 +41,7 @@ ReturnValue_t Clock::setClock(const timeval* time) {
|
||||
timeUnix.tv_nsec = (__syscall_slong_t)time->tv_usec * 1000;
|
||||
int status = clock_settime(CLOCK_REALTIME, &timeUnix);
|
||||
if (status != 0) {
|
||||
// TODO errno
|
||||
handleClockError("setClock");
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
@@ -49,6 +51,7 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
|
||||
timespec timeUnix;
|
||||
int status = clock_gettime(CLOCK_REALTIME, &timeUnix);
|
||||
if (status != 0) {
|
||||
handleClockError("getClock_timeval");
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
time->tv_sec = timeUnix.tv_sec;
|
||||
@@ -140,8 +143,9 @@ ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval*
|
||||
fromTm.tm_hour = from->hour;
|
||||
fromTm.tm_min = from->minute;
|
||||
fromTm.tm_sec = from->second;
|
||||
fromTm.tm_isdst = 0;
|
||||
|
||||
to->tv_sec = mktime(&fromTm);
|
||||
to->tv_sec = timegm(&fromTm);
|
||||
to->tv_usec = from->usecond;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
@@ -150,3 +154,15 @@ ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) {
|
||||
*JD2000 = (time.tv_sec - 946728000. + time.tv_usec / 1000000.) / 24. / 3600.;
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
|
||||
void handleClockError(const char* func) {
|
||||
#if FSFW_VERBOSE_LEVEL >= 1
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "Clock::" << func << ": Failed with code " << errno << ": " << strerror(errno)
|
||||
<< std::endl;
|
||||
#else
|
||||
sif::printWarning("Clock::%s: Failed with code %d: %s\n", func, errno, strerror(errno));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
@@ -11,13 +11,10 @@
|
||||
#include "fsfw/osal/linux/unixUtility.h"
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
|
||||
MessageQueue::MessageQueue(uint32_t messageDepth, size_t maxMessageSize)
|
||||
: id(MessageQueueIF::NO_QUEUE),
|
||||
lastPartner(MessageQueueIF::NO_QUEUE),
|
||||
defaultDestination(MessageQueueIF::NO_QUEUE),
|
||||
MessageQueue::MessageQueue(uint32_t messageDepth, size_t maxMessageSize, MqArgs* args)
|
||||
: MessageQueueBase(MessageQueueIF::NO_QUEUE, MessageQueueIF::NO_QUEUE, args),
|
||||
maxMessageSize(maxMessageSize) {
|
||||
mq_attr attributes;
|
||||
this->id = 0;
|
||||
// Set attributes
|
||||
attributes.mq_curmsgs = 0;
|
||||
attributes.mq_maxmsg = messageDepth;
|
||||
@@ -50,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) {
|
||||
if (message == nullptr) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
@@ -96,7 +69,7 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
|
||||
int status = mq_receive(id, reinterpret_cast<char*>(message->getBuffer()),
|
||||
message->getMaximumMessageSize(), &messagePriority);
|
||||
if (status > 0) {
|
||||
this->lastPartner = message->getSender();
|
||||
this->last = message->getSender();
|
||||
// Check size of incoming message.
|
||||
if (message->getMessageSize() < message->getMinimumMessageSize()) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
@@ -164,8 +137,6 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
|
||||
}
|
||||
}
|
||||
|
||||
MessageQueueId_t MessageQueue::getLastPartner() const { return this->lastPartner; }
|
||||
|
||||
ReturnValue_t MessageQueue::flush(uint32_t* count) {
|
||||
mq_attr attrib;
|
||||
int status = mq_getattr(id, &attrib);
|
||||
@@ -212,26 +183,11 @@ ReturnValue_t MessageQueue::flush(uint32_t* count) {
|
||||
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,
|
||||
MessageQueueId_t sentFrom, bool 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;
|
||||
|
||||
ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
|
||||
@@ -240,9 +196,9 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
|
||||
bool ignoreFault) {
|
||||
if (message == nullptr) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "MessageQueue::sendMessageFromMessageQueue: Message is nullptr!" << std::endl;
|
||||
sif::error << "MessageQueue::sendMessageFromMessageQueue: Message is nullptr" << std::endl;
|
||||
#else
|
||||
sif::printError("MessageQueue::sendMessageFromMessageQueue: Message is nullptr!\n");
|
||||
sif::printError("MessageQueue::sendMessageFromMessageQueue: Message is nullptr\n");
|
||||
#endif
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
@@ -256,7 +212,7 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
|
||||
if (!ignoreFault) {
|
||||
InternalErrorReporterIF* internalErrorReporter =
|
||||
ObjectManager::instance()->get<InternalErrorReporterIF>(objects::INTERNAL_ERROR_REPORTER);
|
||||
if (internalErrorReporter != NULL) {
|
||||
if (internalErrorReporter != nullptr) {
|
||||
internalErrorReporter->queueMessageNotSent();
|
||||
}
|
||||
}
|
||||
|
@@ -1,11 +1,13 @@
|
||||
#ifndef FSFW_OSAL_LINUX_MESSAGEQUEUE_H_
|
||||
#define FSFW_OSAL_LINUX_MESSAGEQUEUE_H_
|
||||
|
||||
#include <fsfw/ipc/MessageQueueBase.h>
|
||||
#include <mqueue.h>
|
||||
|
||||
#include "fsfw/internalerror/InternalErrorReporterIF.h"
|
||||
#include "fsfw/ipc/MessageQueueIF.h"
|
||||
#include "fsfw/ipc/MessageQueueMessage.h"
|
||||
#include "fsfw/ipc/definitions.h"
|
||||
/**
|
||||
* @brief This class manages sending and receiving of message queue messages.
|
||||
*
|
||||
@@ -25,7 +27,7 @@
|
||||
* makes use of the operating system calls provided.
|
||||
* @ingroup message_queue
|
||||
*/
|
||||
class MessageQueue : public MessageQueueIF {
|
||||
class MessageQueue : public MessageQueueBase {
|
||||
friend class MessageQueueSenderIF;
|
||||
|
||||
public:
|
||||
@@ -42,104 +44,25 @@ class MessageQueue : public MessageQueueIF {
|
||||
* This should be left default.
|
||||
*/
|
||||
MessageQueue(uint32_t messageDepth = 3,
|
||||
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE);
|
||||
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE,
|
||||
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.
|
||||
* @details This is accomplished by using the delete call provided by the operating system.
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* @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;
|
||||
// Implement non-generic MessageQueueIF functions not handled by MessageQueueBase
|
||||
ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override;
|
||||
ReturnValue_t flush(uint32_t* count) override;
|
||||
ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
|
||||
MessageQueueId_t sentFrom,
|
||||
bool ignoreFault = false) override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
@@ -158,31 +81,10 @@ class MessageQueue : public MessageQueueIF {
|
||||
bool ignoreFault = false);
|
||||
|
||||
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
|
||||
*/
|
||||
char name[16];
|
||||
char name[16] = {};
|
||||
|
||||
static uint16_t queueCounter;
|
||||
const size_t maxMessageSize;
|
||||
|
@@ -28,7 +28,11 @@ void* PeriodicPosixTask::taskEntryPoint(void* arg) {
|
||||
|
||||
ReturnValue_t PeriodicPosixTask::addComponent(object_id_t 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
|
||||
sif::error << "PeriodicTask::addComponent: Invalid object. Make sure"
|
||||
<< " it implements ExecutableObjectIF!" << std::endl;
|
||||
@@ -39,8 +43,8 @@ ReturnValue_t PeriodicPosixTask::addComponent(object_id_t object) {
|
||||
#endif
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
objectList.push_back(newObject);
|
||||
newObject->setTaskIF(this);
|
||||
objectList.push_back(object);
|
||||
object->setTaskIF(this);
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
@@ -42,6 +42,14 @@ class PeriodicPosixTask : public PosixThread, public PeriodicTaskIF {
|
||||
*/
|
||||
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;
|
||||
|
||||
ReturnValue_t sleepFor(uint32_t ms) override;
|
||||
@@ -65,9 +73,10 @@ class PeriodicPosixTask : public PosixThread, public PeriodicTaskIF {
|
||||
/**
|
||||
* @brief The function containing the actual functionality of the task.
|
||||
* @details The method sets and starts
|
||||
* the task's period, then enters a loop that is repeated indefinitely. Within the
|
||||
* loop, all performOperation methods of the added objects are called. Afterwards the task will be
|
||||
* blocked until the next period. On missing the deadline, the deadlineMissedFunction is executed.
|
||||
* the task's period, then enters a loop that is repeated indefinitely. Within
|
||||
* the loop, all performOperation methods of the added objects are called. Afterwards the task
|
||||
* will be blocked until the next period. On missing the deadline, the deadlineMissedFunction is
|
||||
* executed.
|
||||
*/
|
||||
virtual void taskFunctionality(void);
|
||||
/**
|
||||
|
@@ -28,8 +28,9 @@ QueueFactory::QueueFactory() {}
|
||||
|
||||
QueueFactory::~QueueFactory() {}
|
||||
|
||||
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize) {
|
||||
return new MessageQueue(messageDepth, maxMessageSize);
|
||||
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize,
|
||||
MqArgs* args) {
|
||||
return new MessageQueue(messageDepth, maxMessageSize, args);
|
||||
}
|
||||
|
||||
void QueueFactory::deleteMessageQueue(MessageQueueIF* queue) { delete queue; }
|
||||
|
@@ -6,8 +6,9 @@
|
||||
#include "fsfw/osal/rtems/RtemsBasic.h"
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
|
||||
MessageQueue::MessageQueue(size_t message_depth, size_t max_message_size)
|
||||
: id(0), lastPartner(0), defaultDestination(NO_QUEUE), internalErrorReporter(nullptr) {
|
||||
MessageQueue::MessageQueue(size_t message_depth, size_t max_message_size, MqArgs* args)
|
||||
: MessageQueueBase(MessageQueueIF::NO_QUEUE, MessageQueueIF::NO_QUEUE, args),
|
||||
internalErrorReporter(nullptr) {
|
||||
rtems_name name = ('Q' << 24) + (queueCounter++ << 8);
|
||||
rtems_status_code status =
|
||||
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)
|
||||
sif::error << "MessageQueue::MessageQueue: Creating Queue " << std::hex << name << std::dec
|
||||
<< " failed with status:" << (uint32_t)status << std::endl;
|
||||
#endif
|
||||
this->id = 0;
|
||||
this->id = MessageQueueIF::NO_QUEUE;
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
size_t size = 0;
|
||||
rtems_status_code status =
|
||||
rtems_message_queue_receive(id, message->getBuffer(), &size, RTEMS_NO_WAIT, 1);
|
||||
if (status == RTEMS_SUCCESSFUL) {
|
||||
message->setMessageSize(size);
|
||||
this->lastPartner = message->getSender();
|
||||
this->last = message->getSender();
|
||||
// Check size of incoming message.
|
||||
if (message->getMessageSize() < message->getMinimumMessageSize()) {
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
@@ -65,19 +42,11 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
|
||||
return convertReturnCode(status);
|
||||
}
|
||||
|
||||
MessageQueueId_t MessageQueue::getLastPartner() const { return this->lastPartner; }
|
||||
|
||||
ReturnValue_t MessageQueue::flush(uint32_t* count) {
|
||||
rtems_status_code status = rtems_message_queue_flush(id, count);
|
||||
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,
|
||||
MessageQueueId_t sentFrom, bool ignoreFault) {
|
||||
message->setSender(sentFrom);
|
||||
@@ -103,15 +72,6 @@ ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, MessageQueu
|
||||
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) {
|
||||
switch (inValue) {
|
||||
case RTEMS_SUCCESSFUL:
|
||||
|
@@ -1,10 +1,12 @@
|
||||
#ifndef FSFW_OSAL_RTEMS_MESSAGEQUEUE_H_
|
||||
#define FSFW_OSAL_RTEMS_MESSAGEQUEUE_H_
|
||||
|
||||
#include <fsfw/ipc/MessageQueueBase.h>
|
||||
#include "RtemsBasic.h"
|
||||
#include "fsfw/internalerror/InternalErrorReporterIF.h"
|
||||
#include "fsfw/ipc/MessageQueueIF.h"
|
||||
#include "fsfw/ipc/MessageQueueMessage.h"
|
||||
#include "fsfw/ipc/definitions.h"
|
||||
|
||||
/**
|
||||
* @brief This class manages sending and receiving of message queue messages.
|
||||
@@ -19,7 +21,7 @@
|
||||
*as well as sending and receiving messages, the class makes use of the operating system calls
|
||||
*provided. \ingroup message_queue
|
||||
*/
|
||||
class MessageQueue : public MessageQueueIF {
|
||||
class MessageQueue : public MessageQueueBase {
|
||||
public:
|
||||
/**
|
||||
* @brief The constructor initializes and configures the message queue.
|
||||
@@ -34,131 +36,26 @@ class MessageQueue : public MessageQueueIF {
|
||||
* This should be left default.
|
||||
*/
|
||||
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);
|
||||
|
||||
/** Copying message queues forbidden */
|
||||
MessageQueue(const MessageQueue&) = delete;
|
||||
MessageQueue& operator=(const MessageQueue&) = delete;
|
||||
|
||||
/**
|
||||
* @brief The destructor deletes the formerly created message queue.
|
||||
* @details This is accomplished by using the delete call provided by the operating system.
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* @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,
|
||||
// Implement non-generic MessageQueueIF functions not handled by MessageQueueBase
|
||||
ReturnValue_t flush(uint32_t* count) override;
|
||||
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;
|
||||
bool ignoreFault = false) override;
|
||||
|
||||
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
|
||||
* 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) {
|
||||
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;
|
||||
}
|
||||
objectList.push_back(newObject);
|
||||
newObject->setTaskIF(this);
|
||||
objectList.push_back(object);
|
||||
object->setTaskIF(this);
|
||||
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
@@ -13,8 +13,8 @@ class ExecutableObjectIF;
|
||||
* @brief This class represents a specialized task for periodic activities of multiple objects.
|
||||
*
|
||||
* @details MultiObjectTask is an extension to ObjectTask in the way that it is able to execute
|
||||
* multiple objects that implement the ExecutableObjectIF interface. The objects
|
||||
* must be added prior to starting the task.
|
||||
* multiple objects that implement the ExecutableObjectIF interface. The
|
||||
* objects must be added prior to starting the task.
|
||||
* @author baetz
|
||||
* @ingroup task_handling
|
||||
*/
|
||||
@@ -59,6 +59,15 @@ class PeriodicTask : public RTEMSTaskBase, public PeriodicTaskIF {
|
||||
*/
|
||||
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;
|
||||
|
||||
ReturnValue_t sleepFor(uint32_t ms) override;
|
||||
|
@@ -49,8 +49,9 @@ QueueFactory::QueueFactory() {}
|
||||
|
||||
QueueFactory::~QueueFactory() {}
|
||||
|
||||
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize) {
|
||||
return new MessageQueue(messageDepth, maxMessageSize);
|
||||
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize,
|
||||
MqArgs* args) {
|
||||
return new MessageQueue(messageDepth, maxMessageSize, args);
|
||||
}
|
||||
|
||||
void QueueFactory::deleteMessageQueue(MessageQueueIF* queue) { delete queue; }
|
||||
|
@@ -66,7 +66,7 @@ class HasParametersIF {
|
||||
* @param newValues
|
||||
* @param startAtIndex Linear index, runs left to right, top to bottom for
|
||||
* matrix indexes.
|
||||
* @return
|
||||
* @return RETURN_OK if parameter is valid and a set function of the parameter wrapper was called.
|
||||
*/
|
||||
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueIdentifier,
|
||||
ParameterWrapper *parameterWrapper,
|
||||
|
@@ -211,9 +211,13 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
|
||||
if (data == nullptr) {
|
||||
#if FSFW_VERBOSE_LEVEL >= 1
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "ParameterWrapper::copyFrom: Called on read-only variable!" << std::endl;
|
||||
sif::warning << "ParameterWrapper::copyFrom: Called on read-only variable or "
|
||||
"data pointer not set"
|
||||
<< std::endl;
|
||||
#else
|
||||
sif::printWarning("ParameterWrapper::copyFrom: Called on read-only variable!\n");
|
||||
sif::printWarning(
|
||||
"ParameterWrapper::copyFrom: Called on read-only variable "
|
||||
"or data pointer not set\n");
|
||||
#endif
|
||||
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||
return READONLY;
|
||||
@@ -222,9 +226,9 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
|
||||
if (from->readonlyData == nullptr) {
|
||||
#if FSFW_VERBOSE_LEVEL >= 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
|
||||
sif::printWarning("ParameterWrapper::copyFrom: Source not set!\n");
|
||||
sif::printWarning("ParameterWrapper::copyFrom: Source not set\n");
|
||||
#endif
|
||||
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||
return SOURCE_NOT_SET;
|
||||
@@ -233,9 +237,9 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
|
||||
if (type != from->type) {
|
||||
#if FSFW_VERBOSE_LEVEL >= 1
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "ParameterWrapper::copyFrom: Datatype missmatch!" << std::endl;
|
||||
sif::warning << "ParameterWrapper::copyFrom: Datatype missmatch" << std::endl;
|
||||
#else
|
||||
sif::printWarning("ParameterWrapper::copyFrom: Datatype missmatch!\n");
|
||||
sif::printWarning("ParameterWrapper::copyFrom: Datatype missmatch\n");
|
||||
#endif
|
||||
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||
return DATATYPE_MISSMATCH;
|
||||
@@ -245,9 +249,9 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
|
||||
if (rows == 0 or columns == 0) {
|
||||
#if FSFW_VERBOSE_LEVEL >= 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
|
||||
sif::printWarning("ParameterWrapper::copyFrom: Columns or rows zero!\n");
|
||||
sif::printWarning("ParameterWrapper::copyFrom: Columns or rows zero\n");
|
||||
#endif
|
||||
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||
return COLUMN_OR_ROWS_ZERO;
|
||||
|
@@ -1,7 +1,8 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
Fuse.cpp
|
||||
PowerComponent.cpp
|
||||
PowerSensor.cpp
|
||||
PowerSwitcher.cpp
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
Fuse.cpp
|
||||
PowerComponent.cpp
|
||||
PowerSensor.cpp
|
||||
PowerSwitcher.cpp
|
||||
DummyPowerSwitcher.cpp
|
||||
PowerSwitcherComponent.cpp
|
||||
)
|
46
src/fsfw/power/DummyPowerSwitcher.cpp
Normal file
46
src/fsfw/power/DummyPowerSwitcher.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
#include "DummyPowerSwitcher.h"
|
||||
|
||||
DummyPowerSwitcher::DummyPowerSwitcher(object_id_t objectId, size_t numberOfSwitches,
|
||||
size_t numberOfFuses, uint32_t switchDelayMs)
|
||||
: SystemObject(objectId),
|
||||
switcherList(numberOfSwitches),
|
||||
fuseList(numberOfFuses),
|
||||
switchDelayMs(switchDelayMs) {}
|
||||
|
||||
void DummyPowerSwitcher::setInitialSwitcherList(std::vector<ReturnValue_t> switcherList) {
|
||||
this->switcherList = switcherList;
|
||||
}
|
||||
|
||||
void DummyPowerSwitcher::setInitialFusesList(std::vector<ReturnValue_t> fuseList) {
|
||||
this->fuseList = fuseList;
|
||||
}
|
||||
|
||||
ReturnValue_t DummyPowerSwitcher::sendSwitchCommand(power::Switch_t switchNr, ReturnValue_t onOff) {
|
||||
if (switchNr < switcherList.capacity()) {
|
||||
switcherList[switchNr] = onOff;
|
||||
}
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
|
||||
ReturnValue_t DummyPowerSwitcher::sendFuseOnCommand(uint8_t fuseNr) {
|
||||
if (fuseNr < fuseList.capacity()) {
|
||||
fuseList[fuseNr] = FUSE_ON;
|
||||
}
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
|
||||
ReturnValue_t DummyPowerSwitcher::getSwitchState(power::Switch_t switchNr) const {
|
||||
if (switchNr < switcherList.capacity()) {
|
||||
return switcherList[switchNr];
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
ReturnValue_t DummyPowerSwitcher::getFuseState(uint8_t fuseNr) const {
|
||||
if (fuseNr < fuseList.capacity()) {
|
||||
return fuseList[fuseNr];
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
|
||||
uint32_t DummyPowerSwitcher::getSwitchDelayMs(void) const { return switchDelayMs; }
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user