Compare commits
335 Commits
mohr/dhb2n
...
move_seman
Author | SHA1 | Date | |
---|---|---|---|
6fa453940f | |||
9a8d775eb1 | |||
4d6f6e6b23 | |||
55f6825a03 | |||
c162acb7df | |||
87462afe6d | |||
a8de395ea0 | |||
f0bddfcb21 | |||
23d9b44b3e | |||
26e4445189 | |||
9ee3cdf729 | |||
1b7493f945 | |||
7f6ba5f40b | |||
070b48ada2 | |||
d9a139e1ef | |||
c80a3752d9 | |||
af58c414fc | |||
4c48668125 | |||
2745b2080d | |||
e9d9f44605 | |||
2c5af91db1 | |||
5cd7b98ba7 | |||
a39f1271ec | |||
bbf0d7a0d2 | |||
04ee3c7362 | |||
95dab69b35 | |||
33de15205b | |||
4d353a1ad2 | |||
6006c97e48 | |||
6e17e45506 | |||
64537d442a | |||
78cf00315d | |||
245886c555 | |||
f84097543e | |||
511d07c0c7 | |||
cf735143fe | |||
bdfe31dba4 | |||
216f603d62 | |||
174a6aa862 | |||
c2d9370aa1 | |||
893b434728 | |||
6eba84566d | |||
f0415a97b1 | |||
abcf1b29b2 | |||
d373c45d36 | |||
bd208038dd | |||
206af00c8b | |||
2efff4d2c5 | |||
2a0c244468 | |||
e1711f0345 | |||
c327985222 | |||
b45206ccd6 | |||
c8469ca647 | |||
2d6622b8b8 | |||
5f9eb01d94 | |||
3568bdbecf | |||
fcd84b59ae | |||
e3c968096b | |||
c745c0c8b4 | |||
be015b4c66 | |||
dae5e988fd | |||
a6d707a7db | |||
fe41d73895 | |||
70b785984c | |||
9de6c4b3aa | |||
d256ede8c1 | |||
f0b8457ba2 | |||
dac2d210b5 | |||
8b4f73a97b | |||
7fae6cbd6d | |||
d302ba7185 | |||
14a92b3d89 | |||
e4fd424d66 | |||
341a66c265 | |||
b9b076aa4c | |||
d93486a340 | |||
820a7f059c | |||
f4d188c36f | |||
1841f92944 | |||
b279985859 | |||
fa7675897d | |||
3a2393885f | |||
c752b6d143 | |||
b676040c7c | |||
010509efb4 | |||
dfb1633f00 | |||
5f7172e130 | |||
0c6465cd95 | |||
f94987c46d | |||
1809ce359b | |||
8c712441ab | |||
6ce80ea6c5 | |||
f1b0ca7cff | |||
000df85556 | |||
1fffcc2229 | |||
6f05d6b7b0 | |||
7f907fb9d3 | |||
a419806a05 | |||
84bbef0167 | |||
88b2b0e005 | |||
6445debfa1 | |||
8014e4adf9 | |||
84dc7ac0ce | |||
ec12ab5daa | |||
134d908f26 | |||
40a9e12416 | |||
f39054edd4 | |||
5adf89b911 | |||
c2e6a22dec | |||
c8e065a713 | |||
69c94645df | |||
37e850c5a7 | |||
3ed49dbae3 | |||
a1567de9e8 | |||
4cf52d5dfe | |||
2646707d3f | |||
539d7aac9e | |||
0a23f2c85a | |||
06e30684fe | |||
46230e6c6d | |||
b22d439300 | |||
7e7b3bbbc9 | |||
06dca7608a | |||
6af5274b68 | |||
e2b66df72e | |||
7b828f233a | |||
c3d1000cd5 | |||
8e0e57714d | |||
cc9e54ea6b | |||
31465a4e0f | |||
c0e5d1eb99 | |||
3bc5d4a2e0 | |||
b1e9dd9e4a | |||
ab86599db3 | |||
034eb34c2e | |||
38789e053b | |||
4374c7c4f4 | |||
5343844be5 | |||
e11eabdbcf | |||
3250bbf269 | |||
a78fe0a7f3 | |||
acfc1cbf21 | |||
d17ec02cf0 | |||
e300490b93 | |||
f2461cd7e9 | |||
01cc619e67 | |||
0f811777a7 | |||
e93137939e | |||
2339712373 | |||
d9d253d3bb | |||
bd586f6564 | |||
1f88c006d9 | |||
5f481739d8 | |||
7e94baceef | |||
7ee83e4e5d | |||
64787f85ca | |||
1cacceddad | |||
5c35b8e3cd | |||
9b05e8f274 | |||
7766b24a1d | |||
eb223dae88 | |||
3656662d88 | |||
fe71978467 | |||
b646717a76 | |||
99d8c845f2 | |||
9a4ae550ab | |||
c64b9b3e71 | |||
226818886f | |||
da12495335 | |||
0cc3231ceb | |||
049e3b431d | |||
bd189518b6 | |||
0e7c6b117f | |||
accaf855ee | |||
75fa7caf25 | |||
d16c5024dc | |||
a4531e4ced | |||
97c629ad84 | |||
bf12f284fa | |||
ba62c28b64 | |||
041d1b8795 | |||
7adb47aecb | |||
5bb66c9723 | |||
8589f4d63a | |||
ca80589233 | |||
f2ebaed092 | |||
f0b89e98df | |||
2aa4af6974 | |||
75fc7a056d | |||
05cad893a2 | |||
5557d95994 | |||
fc24c9b5d8 | |||
1b005d706a | |||
5b0ea91222 | |||
7ef69c839c | |||
9b798d798e | |||
e68f54b9bd | |||
8eb869e073 | |||
b13453f46b | |||
d0e322d7e2 | |||
46a1c2bace | |||
2643ff194c | |||
ecde164f68 | |||
50930b41ba | |||
296bc56e2a | |||
d6ee2ed400 | |||
f2150ff9c2 | |||
1b9c98f3fe | |||
742152b28e | |||
bf4ca56658 | |||
16ffa00155 | |||
14c681c93a | |||
0958c3a00e | |||
d699d16307 | |||
3b0fed733f | |||
23d3812fe3 | |||
dec7db3ae2 | |||
65a5abab49 | |||
0129783e34 | |||
cabe0868ec | |||
f05295bada | |||
160ff799ac | |||
b85ca64690 | |||
3bc3da5a8d | |||
f8c07ec9cf | |||
8199b8f359 | |||
cbc8dbcdd4 | |||
d31a5306f0 | |||
a236a5ec50 | |||
03620970e2 | |||
8fe8d810e9 | |||
9483c2809d | |||
fe3d6bd432 | |||
c5f91926c9 | |||
be4a87535d | |||
99927b8e95 | |||
5e5eb82830 | |||
686dc97234 | |||
2a842666d5 | |||
c013fcc1f5 | |||
1f58ba1f9b | |||
002845108d | |||
1b8fc2af19 | |||
72d7c43445 | |||
ab9b6c8c89 | |||
69d338f9bb | |||
68223869d5 | |||
93fda71989 | |||
7b0db08962 | |||
0956fbc740 | |||
b48e0fdc0d | |||
1d084ee22f | |||
1bea2344f6 | |||
d7e16a67a7 | |||
6021d897b8 | |||
83a6f0b5f8 | |||
a9c6c088f2 | |||
2b6a33e718 | |||
61fd5d1b62 | |||
046dbe1deb | |||
e03e7f5260 | |||
b6a3c206cc | |||
5b352978c5 | |||
0303c1a885 | |||
4d2802a470 | |||
819a298b19 | |||
39946bff58 | |||
16246d6ece | |||
5c84f12440 | |||
2a203ae13d | |||
6ca1a5c796 | |||
83c2c4825c | |||
194b3e100a | |||
177c39dd53 | |||
530a261e14 | |||
c913fe40bf | |||
70ec08bf1d | |||
ef23665d9c | |||
eefc122292 | |||
bee33526a1 | |||
0e8f5ddd26 | |||
672fca5169 | |||
84b9d1ce21 | |||
e5b5c7d253 | |||
9a0cc64be3 | |||
00f1c5bbe9 | |||
8a61af779d | |||
6efa482eb0 | |||
f0fa1bf477 | |||
91ebf98c28 | |||
e1d4209fbe | |||
e302c89f74 | |||
a38279f813 | |||
7600ed1ea7 | |||
61ab770d9d | |||
f715b65d6e | |||
c11af63015 | |||
852f27cec2 | |||
fa01798ebb | |||
819a2bfac4 | |||
dc1583c932 | |||
81a7de2814 | |||
d26f230bee | |||
4db124c680 | |||
2df66c9304 | |||
54ad6b3016 | |||
73e313c35b | |||
dd2f42d22b | |||
096af44e39 | |||
56e8e5a8b3 | |||
11422a658c | |||
ec7566fb8c | |||
652c31a683 | |||
bfe120636c | |||
a8041f220f | |||
dd636b186b | |||
3349fc36f8 | |||
df06064df0 | |||
1d6ccfe5ab | |||
221df7ece6 | |||
7f180ac1fa | |||
1eceef4645 | |||
acab5f6bce | |||
10dd855244 | |||
f824004897 | |||
7c5308429c | |||
f78344b8fb | |||
77f7fa2ef1 | |||
78314ad966 | |||
e0c780f21c | |||
876815b1c9 | |||
b0ecf87580 | |||
68ce8b5b08 | |||
fe03da6def | |||
4f7f8310c9 |
81
CHANGELOG.md
81
CHANGELOG.md
@ -12,6 +12,31 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
## Fixes
|
## Fixes
|
||||||
|
|
||||||
|
- Add monotonic watchdog Clock API and use it in `Countdown` and `Stopwatch` class.
|
||||||
|
- Bugfix in `Service11TelecommandScheduling` which allowed commands
|
||||||
|
time tagged in the past to be inserted.
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/738
|
||||||
|
- `CService200ModeManagement`: Various bugfixes which lead to now execution complete being generated
|
||||||
|
on mode announcements, duplicate mode reply generated on announce commands, and the mode read
|
||||||
|
subservice not working properly.
|
||||||
|
- Memory leak fixes for the TCP/IP TMTC bridge.
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/737
|
||||||
|
- `Service9TimeManagement`: Fix the time dump at the `SET_TIME` subservice: Include clock timeval
|
||||||
|
seconds instead of uptime.
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/726
|
||||||
|
- HAL MGM3100 Handler: Use axis specific gain/scaling factors. Previously,
|
||||||
|
only the X scaling factor was used.
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/724
|
||||||
|
- Bugfix for RM3100 MGM sensors. Z value was previously calculated
|
||||||
|
with bytes of the X value.
|
||||||
|
- DHB `setNormalDatapoolEntriesInvalid`: The default implementation did not set the validity
|
||||||
|
to false correctly because the `read` and `write` calls were missing.
|
||||||
|
- PUS TMTC creator module: Sequence flags were set to continuation segment (0b00) instead
|
||||||
|
of the correct unsegmented flags (0b11) as specified in the standard.
|
||||||
|
- TC Scheduler Service 11: Add size and CRC check for contained TC.
|
||||||
|
- Only delete health table entry in `HealthHelper` destructor if
|
||||||
|
health table was set.
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/710/files
|
||||||
- I2C Bugfixes: Do not keep iterator as member and fix some incorrect handling with the iterator.
|
- I2C Bugfixes: Do not keep iterator as member and fix some incorrect handling with the iterator.
|
||||||
Also properly reset the reply size for successfull transfers and erroneous transfers.
|
Also properly reset the reply size for successfull transfers and erroneous transfers.
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/700
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/700
|
||||||
@ -24,19 +49,33 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
## Added
|
## Added
|
||||||
|
|
||||||
- DHB TM handler `handleDeviceTM` renamed to `handleDeviceTm` and now takes
|
- `CServiceHealthCommanding`: Add announce all health info implementation
|
||||||
`util::DataWrapper` as the data input argument. This allows more flexibility in the possible
|
PR: https://egit.irs.uni-stuttgart.de/eive/fsfw/pulls/122
|
||||||
types of telemetry.
|
- Empty constructor for `CdsShortTimeStamper` which does not do an object manager registration.
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/669
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/730
|
||||||
- Add `util::DataWrapper` class inside the `util` module. This is a tagged union which allows
|
- `Service9TimeManagement`: Add `DUMP_TIME` (129) subservice.
|
||||||
to specify raw data either as a classic C-style raw pointer and size or as a `SerializeIF`
|
- `TcpTmTcServer`: Allow setting the `SO_REUSEADDR` and `SO_REUSEPORT`
|
||||||
pointer.
|
option on the TCP server. CTOR prototype has changed and expects an explicit
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/668
|
TCP configuration struct to be passed.
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/722
|
||||||
|
- `DleParser` helper class to parse DLE encoded packets from a byte stream.
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/711
|
||||||
|
- `UioMapper` is able to resolve symlinks now.
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/709
|
||||||
- Add new `UnsignedByteField` class
|
- Add new `UnsignedByteField` class
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/660
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/660
|
||||||
|
|
||||||
## Changes
|
## Changes
|
||||||
|
|
||||||
|
- `CService201HealthCommanding` renamed to `CServiceHealthCommanding`,
|
||||||
|
service ID customizable now. `CServiceHealthCommanding` expects configuration struct
|
||||||
|
`HealthServiceCfg` now
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/eive/fsfw/pulls/122
|
||||||
|
- `AcceptsTelemetryIF`: `getReportReceptionQueue` is const now
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/712
|
||||||
|
- Moved some container returnvalues to dedicated header and namespace
|
||||||
|
to they can be used without template specification.
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/707
|
||||||
- Remove default secondary header argument for
|
- Remove default secondary header argument for
|
||||||
`uint16_t getTcSpacePacketIdFromApid(uint16_t apid, bool secondaryHeaderFlag)` and
|
`uint16_t getTcSpacePacketIdFromApid(uint16_t apid, bool secondaryHeaderFlag)` and
|
||||||
`uint16_t getTmSpacePacketIdFromApid(uint16_t apid, bool secondaryHeaderFlag)`
|
`uint16_t getTmSpacePacketIdFromApid(uint16_t apid, bool secondaryHeaderFlag)`
|
||||||
@ -65,6 +104,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
- `DeviceHandlerBase`: New signature of `handleDeviceTm` which expects
|
- `DeviceHandlerBase`: New signature of `handleDeviceTm` which expects
|
||||||
a `const SerializeIF&` and additional helper variant which expects `const uint8_t*`
|
a `const SerializeIF&` and additional helper variant which expects `const uint8_t*`
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/671
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/671
|
||||||
|
- Move some generic `StorageManagerIF` implementations from `LocalPool` to
|
||||||
|
interface itself so it can be re-used more easily. Also add new
|
||||||
|
abstract function `bool hasDataAtId(store_address_t storeId) const`.
|
||||||
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/685
|
||||||
- Improvements for `AcceptsTelemetryIF` and `AcceptsTelecommandsIF`:
|
- Improvements for `AcceptsTelemetryIF` and `AcceptsTelecommandsIF`:
|
||||||
- Make functions `const` where it makes sense
|
- Make functions `const` where it makes sense
|
||||||
- Add `const char* getName const` abstract function
|
- Add `const char* getName const` abstract function
|
||||||
@ -92,6 +135,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
implementation without an extra component
|
implementation without an extra component
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/682
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/682
|
||||||
|
|
||||||
|
## HAL
|
||||||
|
|
||||||
|
- SPI: Cache the SPI device in the communication interface. Architecturally, this makes a
|
||||||
|
lot more sense because each ComIF should be responsible for one SPI bus.
|
||||||
|
- SPI: Move the empty transfer to update the line polarity to separate function. This means
|
||||||
|
it is not automatically called when calling the setter function for SPI speed and mode.
|
||||||
|
The user should call this function after locking the CS mutex if multiple SPI devices with
|
||||||
|
differing speeds and modes are attached to one bus.
|
||||||
|
- SPI: Getter functions for SPI speed and mode.
|
||||||
|
|
||||||
# [v5.0.0] 25.07.2022
|
# [v5.0.0] 25.07.2022
|
||||||
|
|
||||||
## Changes
|
## Changes
|
||||||
@ -225,6 +278,7 @@ https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/593
|
|||||||
- https://gitlab.kitware.com/cmake/cmake/-/issues/21696
|
- https://gitlab.kitware.com/cmake/cmake/-/issues/21696
|
||||||
Easiest solution for now: Keep this option OFF by default.
|
Easiest solution for now: Keep this option OFF by default.
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/616
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/616
|
||||||
|
- Linux HAL: Add wiretapping option for I2C. Enabled with `FSFW_HAL_I2C_WIRETAPPING` defined to 1
|
||||||
- Dedicated Version class and constant `fsfw::FSFW_VERSION` containing version information
|
- Dedicated Version class and constant `fsfw::FSFW_VERSION` containing version information
|
||||||
inside `fsfw/version.h`
|
inside `fsfw/version.h`
|
||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/559
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/559
|
||||||
@ -239,17 +293,6 @@ https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/593
|
|||||||
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/590
|
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/590
|
||||||
- `Subsystem`: New API to add table and sequence entries
|
- `Subsystem`: New API to add table and sequence entries
|
||||||
|
|
||||||
## HAL
|
|
||||||
|
|
||||||
- SPI: Cache the SPI device in the communication interface. Architecturally, this makes a
|
|
||||||
lot more sense because each ComIF should be responsible for one SPI bus.
|
|
||||||
- SPI: Move the empty transfer to update the line polarity to separate function. This means
|
|
||||||
it is not automatically called when calling the setter function for SPI speed and mode.
|
|
||||||
The user should call this function after locking the CS mutex if multiple SPI devices with
|
|
||||||
differing speeds and modes are attached to one bus.
|
|
||||||
- SPI: Getter functions for SPI speed and mode.
|
|
||||||
- I2C: Add wiretapping option for I2C. Enabled with `FSFW_HAL_I2C_WIRETAPPING` defined to 1.
|
|
||||||
|
|
||||||
## Fixed
|
## Fixed
|
||||||
|
|
||||||
- TCP TMTC Server: `MutexGuard` was not created properly in
|
- TCP TMTC Server: `MutexGuard` was not created properly in
|
||||||
|
@ -122,6 +122,7 @@ if(UNIX)
|
|||||||
option(FSFW_HAL_LINUX_ADD_PERIPHERAL_DRIVERS "Add Linux peripheral drivers"
|
option(FSFW_HAL_LINUX_ADD_PERIPHERAL_DRIVERS "Add Linux peripheral drivers"
|
||||||
OFF)
|
OFF)
|
||||||
option(FSFW_HAL_LINUX_ADD_LIBGPIOD "Attempt to add Linux GPIOD drivers" OFF)
|
option(FSFW_HAL_LINUX_ADD_LIBGPIOD "Attempt to add Linux GPIOD drivers" OFF)
|
||||||
|
option(FSFW_HAL_LINUX_ADD_SERIAL_DRIVERS "Add serial drivers" ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Optional sources
|
# Optional sources
|
||||||
@ -152,12 +153,12 @@ if(FSFW_BUILD_TESTS)
|
|||||||
"${MSG_PREFIX} Building the FSFW unittests in addition to the static library"
|
"${MSG_PREFIX} Building the FSFW unittests in addition to the static library"
|
||||||
)
|
)
|
||||||
# Check whether the user has already installed Catch2 first
|
# Check whether the user has already installed Catch2 first
|
||||||
find_package(Catch2 ${FSFW_CATCH2_LIB_MAJOR_VERSION})
|
find_package(Catch2 ${FSFW_CATCH2_LIB_MAJOR_VERSION} QUIET)
|
||||||
# Not installed, so use FetchContent to download and provide Catch2
|
# Not installed, so use FetchContent to download and provide Catch2
|
||||||
if(NOT Catch2_FOUND)
|
if(NOT Catch2_FOUND)
|
||||||
message(
|
message(
|
||||||
STATUS
|
STATUS
|
||||||
"${MSG_PREFIX} Catch2 installation not found. Downloading Catch2 library with FetchContent"
|
"${MSG_PREFIX} Catch2 installation not found. Downloading Catch2 library with FetchContent."
|
||||||
)
|
)
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
|
||||||
@ -195,13 +196,13 @@ message(
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Check whether the user has already installed ETL first
|
# Check whether the user has already installed ETL first
|
||||||
find_package(${FSFW_ETL_LIB_NAME} ${FSFW_ETL_LIB_MAJOR_VERSION} CONFIG QUIET)
|
find_package(${FSFW_ETL_LIB_NAME} ${FSFW_ETL_LIB_MAJOR_VERSION} QUIET)
|
||||||
# Not installed, so use FetchContent to download and provide etl
|
# Not installed, so use FetchContent to download and provide etl
|
||||||
if(NOT ${FSFW_ETL_LIB_NAME}_FOUND)
|
if(NOT ${FSFW_ETL_LIB_NAME}_FOUND)
|
||||||
message(
|
message(
|
||||||
STATUS
|
STATUS
|
||||||
"${MSG_PREFIX} No ETL installation was found with find_package. Installing and providing "
|
"${MSG_PREFIX} ETL installation not found. Downloading ETL with FetchContent."
|
||||||
"etl with FindPackage")
|
)
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
|
96
automation/Jenkinsfile
vendored
96
automation/Jenkinsfile
vendored
@ -1,45 +1,87 @@
|
|||||||
pipeline {
|
pipeline {
|
||||||
environment {
|
environment {
|
||||||
BUILDDIR = 'cmake-build-tests'
|
BUILDDIR_HOST = 'cmake-build-tests-host'
|
||||||
|
BUILDDIR_LINUX = 'cmake-build-tests-linux'
|
||||||
DOCDDIR = 'cmake-build-documentation'
|
DOCDDIR = 'cmake-build-documentation'
|
||||||
}
|
}
|
||||||
agent {
|
agent {
|
||||||
docker {
|
docker {
|
||||||
image 'fsfw-ci:d6'
|
image 'fsfw-ci:d6'
|
||||||
args '--network host'
|
args '--network host --sysctl fs.mqueue.msg_max=100'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stages {
|
stages {
|
||||||
stage('Clean') {
|
stage('Host') {
|
||||||
steps {
|
stages{
|
||||||
sh 'rm -rf $BUILDDIR'
|
stage('Clean') {
|
||||||
}
|
steps {
|
||||||
}
|
sh 'rm -rf $BUILDDIR_HOST'
|
||||||
stage('Configure') {
|
}
|
||||||
steps {
|
}
|
||||||
dir(BUILDDIR) {
|
stage('Configure') {
|
||||||
sh 'cmake -DFSFW_OSAL=host -DFSFW_BUILD_TESTS=ON -DFSFW_CICD_BUILD=ON ..'
|
steps {
|
||||||
|
dir(BUILDDIR_HOST) {
|
||||||
|
sh 'cmake -DFSFW_OSAL=host -DFSFW_BUILD_TESTS=ON -DFSFW_CICD_BUILD=ON ..'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stage('Build') {
|
||||||
|
steps {
|
||||||
|
dir(BUILDDIR_HOST) {
|
||||||
|
sh 'cmake --build . -j4'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stage('Unittests') {
|
||||||
|
steps {
|
||||||
|
dir(BUILDDIR_HOST) {
|
||||||
|
sh 'cmake --build . -- fsfw-tests_coverage -j4'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stage('Valgrind') {
|
||||||
|
steps {
|
||||||
|
dir(BUILDDIR_HOST) {
|
||||||
|
sh 'valgrind --leak-check=full --error-exitcode=1 ./fsfw-tests'
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage('Build') {
|
stage('Linux') {
|
||||||
steps {
|
stages{
|
||||||
dir(BUILDDIR) {
|
stage('Clean') {
|
||||||
sh 'cmake --build . -j4'
|
steps {
|
||||||
|
sh 'rm -rf $BUILDDIR_LINUX'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
stage('Configure') {
|
||||||
}
|
steps {
|
||||||
stage('Unittests') {
|
dir(BUILDDIR_LINUX) {
|
||||||
steps {
|
sh 'cmake -DFSFW_OSAL=linux -DFSFW_BUILD_TESTS=ON -DFSFW_CICD_BUILD=ON ..'
|
||||||
dir(BUILDDIR) {
|
}
|
||||||
sh 'cmake --build . -- fsfw-tests_coverage -j4'
|
}
|
||||||
}
|
}
|
||||||
}
|
stage('Build') {
|
||||||
}
|
steps {
|
||||||
stage('Valgrind') {
|
dir(BUILDDIR_LINUX) {
|
||||||
steps {
|
sh 'cmake --build . -j4'
|
||||||
dir(BUILDDIR) {
|
}
|
||||||
sh 'valgrind --leak-check=full --error-exitcode=1 ./fsfw-tests'
|
}
|
||||||
|
}
|
||||||
|
stage('Unittests') {
|
||||||
|
steps {
|
||||||
|
dir(BUILDDIR_LINUX) {
|
||||||
|
sh 'cmake --build . -- fsfw-tests_coverage -j4'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stage('Valgrind') {
|
||||||
|
steps {
|
||||||
|
dir(BUILDDIR_LINUX) {
|
||||||
|
sh 'valgrind --leak-check=full --error-exitcode=1 ./fsfw-tests'
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -140,7 +140,7 @@ find_program( GCOV_PATH gcov )
|
|||||||
find_program( LCOV_PATH NAMES lcov lcov.bat lcov.exe lcov.perl)
|
find_program( LCOV_PATH NAMES lcov lcov.bat lcov.exe lcov.perl)
|
||||||
find_program( FASTCOV_PATH NAMES fastcov fastcov.py )
|
find_program( FASTCOV_PATH NAMES fastcov fastcov.py )
|
||||||
find_program( GENHTML_PATH NAMES genhtml genhtml.perl genhtml.bat )
|
find_program( GENHTML_PATH NAMES genhtml genhtml.perl genhtml.bat )
|
||||||
find_program( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/scripts/test)
|
find_program( GCOVR_PATH gcovr )
|
||||||
find_program( CPPFILT_PATH NAMES c++filt )
|
find_program( CPPFILT_PATH NAMES c++filt )
|
||||||
|
|
||||||
if(NOT GCOV_PATH)
|
if(NOT GCOV_PATH)
|
||||||
|
@ -51,7 +51,10 @@ exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
|
|||||||
html_theme = "alabaster"
|
html_theme = "alabaster"
|
||||||
|
|
||||||
html_theme_options = {
|
html_theme_options = {
|
||||||
"extra_nav_links": {"Impressum" : "https://www.uni-stuttgart.de/impressum", "Datenschutz": "https://info.irs.uni-stuttgart.de/datenschutz/datenschutzWebmit.html"}
|
"extra_nav_links": {
|
||||||
|
"Impressum": "https://www.uni-stuttgart.de/impressum",
|
||||||
|
"Datenschutz": "https://info.irs.uni-stuttgart.de/datenschutz/datenschutzWebmit.html",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -178,16 +178,25 @@ ReturnValue_t cfdp::DestHandler::handleFileDataPdu(const cfdp::PacketInfo& info)
|
|||||||
dp.user.fileSegmentRecvdIndication(segParams);
|
dp.user.fileSegmentRecvdIndication(segParams);
|
||||||
}
|
}
|
||||||
result = dp.user.vfs.writeToFile(fileOpParams, fileData);
|
result = dp.user.vfs.writeToFile(fileOpParams, fileData);
|
||||||
if (offset.value() + fileSegmentLen > tp.progress) {
|
|
||||||
tp.progress = offset.value() + fileSegmentLen;
|
|
||||||
}
|
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
// TODO: Proper Error handling
|
// TODO: Proper Error handling
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "File write error" << std::endl;
|
sif::error << "cfdp::DestHandler: VFS file write error with code 0x" << std::hex << std::setw(2)
|
||||||
|
<< result << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
tp.vfsErrorCount++;
|
||||||
|
if (tp.vfsErrorCount < 3) {
|
||||||
|
// TODO: Provide execution step as parameter
|
||||||
|
fp.eventReporter->forwardEvent(events::FILESTORE_ERROR, static_cast<uint8_t>(fsmRes.step),
|
||||||
|
result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
} else {
|
} else {
|
||||||
tp.deliveryStatus = FileDeliveryStatus::RETAINED_IN_FILESTORE;
|
tp.deliveryStatus = FileDeliveryStatus::RETAINED_IN_FILESTORE;
|
||||||
|
tp.vfsErrorCount = 0;
|
||||||
|
}
|
||||||
|
if (offset.value() + fileSegmentLen > tp.progress) {
|
||||||
|
tp.progress = offset.value() + fileSegmentLen;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -271,35 +280,55 @@ ReturnValue_t cfdp::DestHandler::startTransaction(MetadataPduReader& reader, Met
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
ReturnValue_t result = OK;
|
ReturnValue_t result = OK;
|
||||||
fsmRes.step = TransactionStep::TRANSACTION_START;
|
|
||||||
if (reader.getTransmissionMode() == TransmissionMode::UNACKNOWLEDGED) {
|
|
||||||
fsmRes.state = CfdpStates::BUSY_CLASS_1_NACKED;
|
|
||||||
} else if (reader.getTransmissionMode() == TransmissionMode::ACKNOWLEDGED) {
|
|
||||||
fsmRes.state = CfdpStates::BUSY_CLASS_2_ACKED;
|
|
||||||
}
|
|
||||||
tp.checksumType = info.getChecksumType();
|
|
||||||
tp.closureRequested = info.isClosureRequested();
|
|
||||||
size_t sourceNameSize = 0;
|
size_t sourceNameSize = 0;
|
||||||
|
|
||||||
const uint8_t* sourceNamePtr = info.getSourceFileName().getValue(&sourceNameSize);
|
const uint8_t* sourceNamePtr = info.getSourceFileName().getValue(&sourceNameSize);
|
||||||
if (sourceNameSize > tp.sourceName.size()) {
|
if (sourceNameSize + 1 > tp.sourceName.size()) {
|
||||||
// TODO: Warning, event etc.
|
fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "source filename too large");
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
std::memcpy(tp.sourceName.data(), sourceNamePtr, sourceNameSize);
|
std::memcpy(tp.sourceName.data(), sourceNamePtr, sourceNameSize);
|
||||||
tp.sourceName[sourceNameSize] = '\0';
|
tp.sourceName[sourceNameSize] = '\0';
|
||||||
size_t destNameSize = 0;
|
size_t destNameSize = 0;
|
||||||
const uint8_t* destNamePtr = info.getDestFileName().getValue(&destNameSize);
|
const uint8_t* destNamePtr = info.getDestFileName().getValue(&destNameSize);
|
||||||
if (destNameSize > tp.destName.size()) {
|
if (destNameSize + 1 > tp.destName.size()) {
|
||||||
// TODO: Warning, event etc.
|
fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "dest filename too large");
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
std::memcpy(tp.destName.data(), destNamePtr, destNameSize);
|
std::memcpy(tp.destName.data(), destNamePtr, destNameSize);
|
||||||
tp.destName[destNameSize] = '\0';
|
tp.destName[destNameSize] = '\0';
|
||||||
reader.fillConfig(tp.pduConf);
|
|
||||||
tp.pduConf.direction = Direction::TOWARDS_SENDER;
|
// If both dest name size and source name size are 0, we are dealing with a metadata only PDU,
|
||||||
tp.transactionId.entityId = tp.pduConf.sourceId;
|
// so there is no need to create a file or truncate an existing file
|
||||||
tp.transactionId.seqNum = tp.pduConf.seqNum;
|
if (destNameSize > 0 and sourceNameSize > 0) {
|
||||||
if (not dp.remoteCfgTable.getRemoteCfg(tp.pduConf.sourceId, &tp.remoteCfg)) {
|
FilesystemParams fparams(tp.destName.data());
|
||||||
|
// handling to allow only specifying target directory. Example:
|
||||||
|
// Source path /test/hello.txt, dest path /tmp -> dest path /tmp/hello.txt
|
||||||
|
if (dp.user.vfs.isDirectory(tp.destName.data())) {
|
||||||
|
result = tryBuildingAbsoluteDestName(destNameSize);
|
||||||
|
if (result != OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dp.user.vfs.fileExists(fparams)) {
|
||||||
|
result = dp.user.vfs.truncateFile(fparams);
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
fileErrorHandler(events::FILESTORE_ERROR, result, "file truncation error");
|
||||||
|
return FAILED;
|
||||||
|
// TODO: Relevant for filestore rejection error?
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result = dp.user.vfs.createFile(fparams);
|
||||||
|
if (result != OK) {
|
||||||
|
fileErrorHandler(events::FILESTORE_ERROR, result, "file creation error");
|
||||||
|
return FAILED;
|
||||||
|
// TODO: Relevant for filestore rejection error?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EntityId sourceId;
|
||||||
|
reader.getSourceId(sourceId);
|
||||||
|
if (not dp.remoteCfgTable.getRemoteCfg(sourceId, &tp.remoteCfg)) {
|
||||||
// TODO: Warning, event etc.
|
// TODO: Warning, event etc.
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "cfdp::DestHandler" << __func__
|
sif::warning << "cfdp::DestHandler" << __func__
|
||||||
@ -308,22 +337,18 @@ ReturnValue_t cfdp::DestHandler::startTransaction(MetadataPduReader& reader, Met
|
|||||||
#endif
|
#endif
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
// If both dest name size and source name size are 0, we are dealing with a metadata only PDU,
|
fsmRes.step = TransactionStep::TRANSACTION_START;
|
||||||
// so there is no need to create a file or truncate an existing file
|
if (reader.getTransmissionMode() == TransmissionMode::UNACKNOWLEDGED) {
|
||||||
if (destNameSize > 0 and sourceNameSize > 0) {
|
fsmRes.state = CfdpStates::BUSY_CLASS_1_NACKED;
|
||||||
FilesystemParams fparams(tp.destName.data());
|
} else if (reader.getTransmissionMode() == TransmissionMode::ACKNOWLEDGED) {
|
||||||
// TODO: Filesystem errors?
|
fsmRes.state = CfdpStates::BUSY_CLASS_2_ACKED;
|
||||||
if (dp.user.vfs.fileExists(fparams)) {
|
|
||||||
dp.user.vfs.truncateFile(fparams);
|
|
||||||
} else {
|
|
||||||
result = dp.user.vfs.createFile(fparams);
|
|
||||||
if (result != OK) {
|
|
||||||
// TODO: Handle FS error. This is probably a case for the filestore rejection mechanism of
|
|
||||||
// CFDP.
|
|
||||||
// In any case, it does not really make sense to continue here
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
tp.checksumType = info.getChecksumType();
|
||||||
|
tp.closureRequested = info.isClosureRequested();
|
||||||
|
reader.fillConfig(tp.pduConf);
|
||||||
|
tp.pduConf.direction = Direction::TOWARDS_SENDER;
|
||||||
|
tp.transactionId.entityId = tp.pduConf.sourceId;
|
||||||
|
tp.transactionId.seqNum = tp.pduConf.seqNum;
|
||||||
fsmRes.step = TransactionStep::RECEIVING_FILE_DATA_PDUS;
|
fsmRes.step = TransactionStep::RECEIVING_FILE_DATA_PDUS;
|
||||||
MetadataRecvdParams params(tp.transactionId, tp.pduConf.sourceId);
|
MetadataRecvdParams params(tp.transactionId, tp.pduConf.sourceId);
|
||||||
params.fileSize = tp.fileSize.getSize();
|
params.fileSize = tp.fileSize.getSize();
|
||||||
@ -362,6 +387,37 @@ ReturnValue_t cfdp::DestHandler::handleTransferCompletion() {
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReturnValue_t cfdp::DestHandler::tryBuildingAbsoluteDestName(size_t destNameSize) {
|
||||||
|
char baseNameBuf[tp.destName.size()]{};
|
||||||
|
FilesystemParams fparamsSrc(tp.sourceName.data());
|
||||||
|
size_t baseNameLen = 0;
|
||||||
|
ReturnValue_t result =
|
||||||
|
dp.user.vfs.getBaseFilename(fparamsSrc, baseNameBuf, sizeof(baseNameBuf), baseNameLen);
|
||||||
|
if (result != returnvalue::OK or baseNameLen == 0) {
|
||||||
|
fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "error retrieving source base name");
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
// Destination name + slash + base name + null termination
|
||||||
|
if (destNameSize + 1 + baseNameLen + 1 > tp.destName.size()) {
|
||||||
|
fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0,
|
||||||
|
"dest filename too large after adding source base name");
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
tp.destName[destNameSize++] = '/';
|
||||||
|
std::memcpy(tp.destName.data() + destNameSize, baseNameBuf, baseNameLen);
|
||||||
|
destNameSize += baseNameLen;
|
||||||
|
tp.destName[destNameSize++] = '\0';
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cfdp::DestHandler::fileErrorHandler(Event event, ReturnValue_t result, const char* info) {
|
||||||
|
fp.eventReporter->forwardEvent(events::FILENAME_TOO_LARGE_ERROR,
|
||||||
|
static_cast<uint8_t>(fsmRes.step), result);
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::warning << "cfdp::DestHandler: " << info << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void cfdp::DestHandler::finish() {
|
void cfdp::DestHandler::finish() {
|
||||||
tp.reset();
|
tp.reset();
|
||||||
dp.packetListRef.clear();
|
dp.packetListRef.clear();
|
||||||
|
@ -84,7 +84,7 @@ enum class CallStatus { DONE, CALL_AFTER_DELAY, CALL_AGAIN };
|
|||||||
|
|
||||||
class DestHandler {
|
class DestHandler {
|
||||||
public:
|
public:
|
||||||
enum class TransactionStep {
|
enum class TransactionStep : uint8_t {
|
||||||
IDLE = 0,
|
IDLE = 0,
|
||||||
TRANSACTION_START = 1,
|
TRANSACTION_START = 1,
|
||||||
RECEIVING_FILE_DATA_PDUS = 2,
|
RECEIVING_FILE_DATA_PDUS = 2,
|
||||||
@ -157,11 +157,13 @@ class DestHandler {
|
|||||||
progress = 0;
|
progress = 0;
|
||||||
remoteCfg = nullptr;
|
remoteCfg = nullptr;
|
||||||
closureRequested = false;
|
closureRequested = false;
|
||||||
|
vfsErrorCount = 0;
|
||||||
checksumType = ChecksumType::NULL_CHECKSUM;
|
checksumType = ChecksumType::NULL_CHECKSUM;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChecksumType checksumType = ChecksumType::NULL_CHECKSUM;
|
ChecksumType checksumType = ChecksumType::NULL_CHECKSUM;
|
||||||
bool closureRequested = false;
|
bool closureRequested = false;
|
||||||
|
uint16_t vfsErrorCount = 0;
|
||||||
std::vector<char> sourceName;
|
std::vector<char> sourceName;
|
||||||
std::vector<char> destName;
|
std::vector<char> destName;
|
||||||
cfdp::FileSize fileSize;
|
cfdp::FileSize fileSize;
|
||||||
@ -189,9 +191,11 @@ class DestHandler {
|
|||||||
ReturnValue_t handleMetadataParseError(ReturnValue_t result, const uint8_t* rawData,
|
ReturnValue_t handleMetadataParseError(ReturnValue_t result, const uint8_t* rawData,
|
||||||
size_t maxSize);
|
size_t maxSize);
|
||||||
ReturnValue_t handleTransferCompletion();
|
ReturnValue_t handleTransferCompletion();
|
||||||
|
ReturnValue_t tryBuildingAbsoluteDestName(size_t destNameSize);
|
||||||
ReturnValue_t sendFinishedPdu();
|
ReturnValue_t sendFinishedPdu();
|
||||||
ReturnValue_t noticeOfCompletion();
|
ReturnValue_t noticeOfCompletion();
|
||||||
ReturnValue_t checksumVerification();
|
ReturnValue_t checksumVerification();
|
||||||
|
void fileErrorHandler(Event event, ReturnValue_t result, const char* info);
|
||||||
const FsmResult& updateFsmRes(uint8_t errors);
|
const FsmResult& updateFsmRes(uint8_t errors);
|
||||||
void checkAndHandleError(ReturnValue_t result, uint8_t& errorIdx);
|
void checkAndHandleError(ReturnValue_t result, uint8_t& errorIdx);
|
||||||
void finish();
|
void finish();
|
||||||
|
@ -12,6 +12,9 @@ namespace events {
|
|||||||
static constexpr Event STORE_ERROR = event::makeEvent(SSID, 0, severity::LOW);
|
static constexpr Event STORE_ERROR = event::makeEvent(SSID, 0, severity::LOW);
|
||||||
static constexpr Event MSG_QUEUE_ERROR = event::makeEvent(SSID, 1, severity::LOW);
|
static constexpr Event MSG_QUEUE_ERROR = event::makeEvent(SSID, 1, severity::LOW);
|
||||||
static constexpr Event SERIALIZATION_ERROR = event::makeEvent(SSID, 2, severity::LOW);
|
static constexpr Event SERIALIZATION_ERROR = event::makeEvent(SSID, 2, severity::LOW);
|
||||||
|
static constexpr Event FILESTORE_ERROR = event::makeEvent(SSID, 3, severity::LOW);
|
||||||
|
//! [EXPORT] : [COMMENT] P1: Transaction step ID, P2: 0 for source file name, 1 for dest file name
|
||||||
|
static constexpr Event FILENAME_TOO_LARGE_ERROR = event::makeEvent(SSID, 4, severity::LOW);
|
||||||
|
|
||||||
} // namespace events
|
} // namespace events
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "../returnvalues/returnvalue.h"
|
#include "../returnvalues/returnvalue.h"
|
||||||
#include "../serialize/SerializeAdapter.h"
|
#include "../serialize/SerializeAdapter.h"
|
||||||
#include "../serialize/SerializeIF.h"
|
#include "../serialize/SerializeIF.h"
|
||||||
|
#include "definitions.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A List that stores its values in an array.
|
* @brief A List that stores its values in an array.
|
||||||
@ -19,9 +20,6 @@ class ArrayList {
|
|||||||
friend class SerialArrayListAdapter;
|
friend class SerialArrayListAdapter;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const uint8_t INTERFACE_ID = CLASS_ID::ARRAY_LIST;
|
|
||||||
static const ReturnValue_t FULL = MAKE_RETURN_CODE(0x01);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the allocating constructor.
|
* This is the allocating constructor.
|
||||||
* It allocates an array of the specified size.
|
* It allocates an array of the specified size.
|
||||||
@ -187,7 +185,7 @@ class ArrayList {
|
|||||||
*/
|
*/
|
||||||
ReturnValue_t insert(T entry) {
|
ReturnValue_t insert(T entry) {
|
||||||
if (size >= maxSize_) {
|
if (size >= maxSize_) {
|
||||||
return FULL;
|
return containers::LIST_FULL;
|
||||||
}
|
}
|
||||||
entries[size] = entry;
|
entries[size] = entry;
|
||||||
++size;
|
++size;
|
||||||
|
@ -12,6 +12,7 @@ template <typename T, size_t MAX_SIZE, typename count_t = uint8_t>
|
|||||||
class FixedArrayList : public ArrayList<T, count_t> {
|
class FixedArrayList : public ArrayList<T, count_t> {
|
||||||
static_assert(MAX_SIZE <= std::numeric_limits<count_t>::max(),
|
static_assert(MAX_SIZE <= std::numeric_limits<count_t>::max(),
|
||||||
"count_t is not large enough to hold MAX_SIZE");
|
"count_t is not large enough to hold MAX_SIZE");
|
||||||
|
static_assert(MAX_SIZE > 0, "MAX_SIZE is 0");
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T data[MAX_SIZE];
|
T data[MAX_SIZE];
|
||||||
@ -20,15 +21,19 @@ class FixedArrayList : public ArrayList<T, count_t> {
|
|||||||
FixedArrayList() : ArrayList<T, count_t>(data, MAX_SIZE) {}
|
FixedArrayList() : ArrayList<T, count_t>(data, MAX_SIZE) {}
|
||||||
|
|
||||||
FixedArrayList(const FixedArrayList& other) : ArrayList<T, count_t>(data, MAX_SIZE) {
|
FixedArrayList(const FixedArrayList& other) : ArrayList<T, count_t>(data, MAX_SIZE) {
|
||||||
memcpy(this->data, other.data, sizeof(this->data));
|
|
||||||
this->entries = data;
|
this->entries = data;
|
||||||
this->size = other.size;
|
this->size = other.size;
|
||||||
|
for (size_t idx = 0; idx < this->size; idx++) {
|
||||||
|
data[idx] = other.data[idx];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FixedArrayList& operator=(FixedArrayList other) {
|
FixedArrayList& operator=(FixedArrayList other) {
|
||||||
memcpy(this->data, other.data, sizeof(this->data));
|
|
||||||
this->entries = data;
|
this->entries = data;
|
||||||
this->size = other.size;
|
this->size = other.size;
|
||||||
|
for (size_t idx = 0; idx < this->size; idx++) {
|
||||||
|
data[idx] = other.data[idx];
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "../returnvalues/returnvalue.h"
|
|
||||||
#include "ArrayList.h"
|
#include "ArrayList.h"
|
||||||
|
#include "definitions.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Map implementation for maps with a pre-defined size.
|
* @brief Map implementation for maps with a pre-defined size.
|
||||||
@ -24,11 +24,6 @@ class FixedMap : public SerializeIF {
|
|||||||
"derived class from SerializeIF to be serialize-able");
|
"derived class from SerializeIF to be serialize-able");
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MAP;
|
|
||||||
static const ReturnValue_t KEY_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01);
|
|
||||||
static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x02);
|
|
||||||
static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x03);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const key_t EMPTY_SLOT = -1;
|
static const key_t EMPTY_SLOT = -1;
|
||||||
ArrayList<std::pair<key_t, T>, uint32_t> theMap;
|
ArrayList<std::pair<key_t, T>, uint32_t> theMap;
|
||||||
@ -76,10 +71,10 @@ class FixedMap : public SerializeIF {
|
|||||||
|
|
||||||
ReturnValue_t insert(key_t key, T value, Iterator* storedValue = nullptr) {
|
ReturnValue_t insert(key_t key, T value, Iterator* storedValue = nullptr) {
|
||||||
if (exists(key) == returnvalue::OK) {
|
if (exists(key) == returnvalue::OK) {
|
||||||
return KEY_ALREADY_EXISTS;
|
return containers::KEY_ALREADY_EXISTS;
|
||||||
}
|
}
|
||||||
if (_size == theMap.maxSize()) {
|
if (_size == theMap.maxSize()) {
|
||||||
return MAP_FULL;
|
return containers::MAP_FULL;
|
||||||
}
|
}
|
||||||
theMap[_size].first = key;
|
theMap[_size].first = key;
|
||||||
theMap[_size].second = value;
|
theMap[_size].second = value;
|
||||||
@ -93,7 +88,7 @@ class FixedMap : public SerializeIF {
|
|||||||
ReturnValue_t insert(std::pair<key_t, T> pair) { return insert(pair.first, pair.second); }
|
ReturnValue_t insert(std::pair<key_t, T> pair) { return insert(pair.first, pair.second); }
|
||||||
|
|
||||||
ReturnValue_t exists(key_t key) const {
|
ReturnValue_t exists(key_t key) const {
|
||||||
ReturnValue_t result = KEY_DOES_NOT_EXIST;
|
ReturnValue_t result = containers::KEY_DOES_NOT_EXIST;
|
||||||
if (findIndex(key) < _size) {
|
if (findIndex(key) < _size) {
|
||||||
result = returnvalue::OK;
|
result = returnvalue::OK;
|
||||||
}
|
}
|
||||||
@ -103,7 +98,7 @@ class FixedMap : public SerializeIF {
|
|||||||
ReturnValue_t erase(Iterator* iter) {
|
ReturnValue_t erase(Iterator* iter) {
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
if ((i = findIndex((*iter).value->first)) >= _size) {
|
if ((i = findIndex((*iter).value->first)) >= _size) {
|
||||||
return KEY_DOES_NOT_EXIST;
|
return containers::KEY_DOES_NOT_EXIST;
|
||||||
}
|
}
|
||||||
theMap[i] = theMap[_size - 1];
|
theMap[i] = theMap[_size - 1];
|
||||||
--_size;
|
--_size;
|
||||||
@ -114,7 +109,7 @@ class FixedMap : public SerializeIF {
|
|||||||
ReturnValue_t erase(key_t key) {
|
ReturnValue_t erase(key_t key) {
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
if ((i = findIndex(key)) >= _size) {
|
if ((i = findIndex(key)) >= _size) {
|
||||||
return KEY_DOES_NOT_EXIST;
|
return containers::KEY_DOES_NOT_EXIST;
|
||||||
}
|
}
|
||||||
theMap[i] = theMap[_size - 1];
|
theMap[i] = theMap[_size - 1];
|
||||||
--_size;
|
--_size;
|
||||||
|
14
src/fsfw/container/definitions.h
Normal file
14
src/fsfw/container/definitions.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#ifndef FSFW_CONTAINER_DEFINITIONS_H_
|
||||||
|
#define FSFW_CONTAINER_DEFINITIONS_H_
|
||||||
|
|
||||||
|
#include "fsfw/retval.h"
|
||||||
|
|
||||||
|
namespace containers {
|
||||||
|
static const ReturnValue_t KEY_ALREADY_EXISTS = returnvalue::makeCode(CLASS_ID::FIXED_MAP, 0x01);
|
||||||
|
static const ReturnValue_t MAP_FULL = returnvalue::makeCode(CLASS_ID::FIXED_MAP, 0x02);
|
||||||
|
static const ReturnValue_t KEY_DOES_NOT_EXIST = returnvalue::makeCode(CLASS_ID::FIXED_MAP, 0x03);
|
||||||
|
|
||||||
|
static const ReturnValue_t LIST_FULL = returnvalue::makeCode(CLASS_ID::ARRAY_LIST, 0x01);
|
||||||
|
} // namespace containers
|
||||||
|
|
||||||
|
#endif /* FSFW_CONTAINER_DEFINITIONS_H_ */
|
@ -4,11 +4,10 @@
|
|||||||
#include "fsfw/ipc/QueueFactory.h"
|
#include "fsfw/ipc/QueueFactory.h"
|
||||||
#include "fsfw/objectmanager/ObjectManager.h"
|
#include "fsfw/objectmanager/ObjectManager.h"
|
||||||
#include "fsfw/subsystem/SubsystemBase.h"
|
#include "fsfw/subsystem/SubsystemBase.h"
|
||||||
|
#include "fsfw/subsystem/helper.h"
|
||||||
|
|
||||||
ControllerBase::ControllerBase(object_id_t setObjectId, object_id_t parentId,
|
ControllerBase::ControllerBase(object_id_t setObjectId, size_t commandQueueDepth)
|
||||||
size_t commandQueueDepth)
|
|
||||||
: SystemObject(setObjectId),
|
: SystemObject(setObjectId),
|
||||||
parentId(parentId),
|
|
||||||
mode(MODE_OFF),
|
mode(MODE_OFF),
|
||||||
submode(SUBMODE_NONE),
|
submode(SUBMODE_NONE),
|
||||||
modeHelper(this),
|
modeHelper(this),
|
||||||
@ -21,33 +20,15 @@ ControllerBase::ControllerBase(object_id_t setObjectId, object_id_t parentId,
|
|||||||
ControllerBase::~ControllerBase() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }
|
ControllerBase::~ControllerBase() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }
|
||||||
|
|
||||||
ReturnValue_t ControllerBase::initialize() {
|
ReturnValue_t ControllerBase::initialize() {
|
||||||
ReturnValue_t result = SystemObject::initialize();
|
ReturnValue_t result = modeHelper.initialize();
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
result = healthHelper.initialize();
|
||||||
MessageQueueId_t parentQueue = 0;
|
|
||||||
if (parentId != objects::NO_OBJECT) {
|
|
||||||
auto* parent = ObjectManager::instance()->get<SubsystemBase>(parentId);
|
|
||||||
if (parent == nullptr) {
|
|
||||||
return returnvalue::FAILED;
|
|
||||||
}
|
|
||||||
parentQueue = parent->getCommandQueue();
|
|
||||||
|
|
||||||
parent->registerChild(getObjectId());
|
|
||||||
}
|
|
||||||
|
|
||||||
result = healthHelper.initialize(parentQueue);
|
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
return SystemObject::initialize();
|
||||||
result = modeHelper.initialize(parentQueue);
|
|
||||||
if (result != returnvalue::OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
return returnvalue::OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageQueueId_t ControllerBase::getCommandQueue() const { return commandQueue->getId(); }
|
MessageQueueId_t ControllerBase::getCommandQueue() const { return commandQueue->getId(); }
|
||||||
@ -120,3 +101,13 @@ void ControllerBase::setTaskIF(PeriodicTaskIF* task_) { executingTask = task_; }
|
|||||||
void ControllerBase::changeHK(Mode_t mode_, Submode_t submode_, bool enable) {}
|
void ControllerBase::changeHK(Mode_t mode_, Submode_t submode_, bool enable) {}
|
||||||
|
|
||||||
ReturnValue_t ControllerBase::initializeAfterTaskCreation() { return returnvalue::OK; }
|
ReturnValue_t ControllerBase::initializeAfterTaskCreation() { return returnvalue::OK; }
|
||||||
|
|
||||||
|
const HasHealthIF* ControllerBase::getOptHealthIF() const { return this; }
|
||||||
|
|
||||||
|
const HasModesIF& ControllerBase::getModeIF() const { return *this; }
|
||||||
|
|
||||||
|
ModeTreeChildIF& ControllerBase::getModeTreeChildIF() { return *this; }
|
||||||
|
|
||||||
|
ReturnValue_t ControllerBase::connectModeTreeParent(HasModeTreeChildrenIF& parent) {
|
||||||
|
return modetree::connectModeTreeParent(parent, *this, &healthHelper, modeHelper);
|
||||||
|
}
|
||||||
|
@ -6,6 +6,9 @@
|
|||||||
#include "fsfw/modes/HasModesIF.h"
|
#include "fsfw/modes/HasModesIF.h"
|
||||||
#include "fsfw/modes/ModeHelper.h"
|
#include "fsfw/modes/ModeHelper.h"
|
||||||
#include "fsfw/objectmanager/SystemObject.h"
|
#include "fsfw/objectmanager/SystemObject.h"
|
||||||
|
#include "fsfw/subsystem/HasModeTreeChildrenIF.h"
|
||||||
|
#include "fsfw/subsystem/ModeTreeChildIF.h"
|
||||||
|
#include "fsfw/subsystem/ModeTreeConnectionIF.h"
|
||||||
#include "fsfw/tasks/ExecutableObjectIF.h"
|
#include "fsfw/tasks/ExecutableObjectIF.h"
|
||||||
#include "fsfw/tasks/PeriodicTaskIF.h"
|
#include "fsfw/tasks/PeriodicTaskIF.h"
|
||||||
|
|
||||||
@ -18,13 +21,18 @@
|
|||||||
class ControllerBase : public HasModesIF,
|
class ControllerBase : public HasModesIF,
|
||||||
public HasHealthIF,
|
public HasHealthIF,
|
||||||
public ExecutableObjectIF,
|
public ExecutableObjectIF,
|
||||||
|
public ModeTreeChildIF,
|
||||||
|
public ModeTreeConnectionIF,
|
||||||
public SystemObject {
|
public SystemObject {
|
||||||
public:
|
public:
|
||||||
static const Mode_t MODE_NORMAL = 2;
|
static const Mode_t MODE_NORMAL = 2;
|
||||||
|
|
||||||
ControllerBase(object_id_t setObjectId, object_id_t parentId, size_t commandQueueDepth = 3);
|
ControllerBase(object_id_t setObjectId, size_t commandQueueDepth = 3);
|
||||||
~ControllerBase() override;
|
~ControllerBase() override;
|
||||||
|
|
||||||
|
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF &parent) override;
|
||||||
|
ModeTreeChildIF &getModeTreeChildIF() override;
|
||||||
|
|
||||||
/** SystemObject override */
|
/** SystemObject override */
|
||||||
ReturnValue_t initialize() override;
|
ReturnValue_t initialize() override;
|
||||||
|
|
||||||
@ -38,6 +46,8 @@ class ControllerBase : public HasModesIF,
|
|||||||
ReturnValue_t performOperation(uint8_t opCode) override;
|
ReturnValue_t performOperation(uint8_t opCode) override;
|
||||||
void setTaskIF(PeriodicTaskIF *task) override;
|
void setTaskIF(PeriodicTaskIF *task) override;
|
||||||
ReturnValue_t initializeAfterTaskCreation() override;
|
ReturnValue_t initializeAfterTaskCreation() override;
|
||||||
|
const HasHealthIF *getOptHealthIF() const override;
|
||||||
|
const HasModesIF &getModeIF() const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
@ -56,8 +66,6 @@ class ControllerBase : public HasModesIF,
|
|||||||
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
||||||
uint32_t *msToReachTheMode) override = 0;
|
uint32_t *msToReachTheMode) override = 0;
|
||||||
|
|
||||||
const object_id_t parentId;
|
|
||||||
|
|
||||||
Mode_t mode;
|
Mode_t mode;
|
||||||
|
|
||||||
Submode_t submode;
|
Submode_t submode;
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
#include "fsfw/controller/ExtendedControllerBase.h"
|
#include "fsfw/controller/ExtendedControllerBase.h"
|
||||||
|
|
||||||
ExtendedControllerBase::ExtendedControllerBase(object_id_t objectId, object_id_t parentId,
|
ExtendedControllerBase::ExtendedControllerBase(object_id_t objectId, size_t commandQueueDepth)
|
||||||
size_t commandQueueDepth)
|
: ControllerBase(objectId, commandQueueDepth),
|
||||||
: ControllerBase(objectId, parentId, commandQueueDepth),
|
|
||||||
poolManager(this, commandQueue),
|
poolManager(this, commandQueue),
|
||||||
actionHelper(this, commandQueue) {}
|
actionHelper(this, commandQueue) {}
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ class ExtendedControllerBase : public ControllerBase,
|
|||||||
public HasActionsIF,
|
public HasActionsIF,
|
||||||
public HasLocalDataPoolIF {
|
public HasLocalDataPoolIF {
|
||||||
public:
|
public:
|
||||||
ExtendedControllerBase(object_id_t objectId, object_id_t parentId, size_t commandQueueDepth = 3);
|
ExtendedControllerBase(object_id_t objectId, size_t commandQueueDepth = 3);
|
||||||
~ExtendedControllerBase() override;
|
~ExtendedControllerBase() override;
|
||||||
|
|
||||||
/* SystemObjectIF overrides */
|
/* SystemObjectIF overrides */
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include "fsfw/devicehandlers/AssemblyBase.h"
|
#include "fsfw/devicehandlers/AssemblyBase.h"
|
||||||
|
|
||||||
AssemblyBase::AssemblyBase(object_id_t objectId, object_id_t parentId, uint16_t commandQueueDepth)
|
AssemblyBase::AssemblyBase(object_id_t objectId, uint16_t commandQueueDepth)
|
||||||
: SubsystemBase(objectId, parentId, MODE_OFF, commandQueueDepth),
|
: SubsystemBase(objectId, MODE_OFF, commandQueueDepth),
|
||||||
internalState(STATE_NONE),
|
internalState(STATE_NONE),
|
||||||
recoveryState(RECOVERY_IDLE),
|
recoveryState(RECOVERY_IDLE),
|
||||||
recoveringDevice(childrenMap.end()),
|
recoveringDevice(childrenMap.end()),
|
||||||
|
@ -41,7 +41,7 @@ class AssemblyBase : public SubsystemBase {
|
|||||||
static const ReturnValue_t NEED_TO_CHANGE_HEALTH = MAKE_RETURN_CODE(0x05);
|
static const ReturnValue_t NEED_TO_CHANGE_HEALTH = MAKE_RETURN_CODE(0x05);
|
||||||
static const ReturnValue_t NOT_ENOUGH_CHILDREN_IN_CORRECT_STATE = MAKE_RETURN_CODE(0xa1);
|
static const ReturnValue_t NOT_ENOUGH_CHILDREN_IN_CORRECT_STATE = MAKE_RETURN_CODE(0xa1);
|
||||||
|
|
||||||
AssemblyBase(object_id_t objectId, object_id_t parentId, uint16_t commandQueueDepth = 8);
|
AssemblyBase(object_id_t objectId, uint16_t commandQueueDepth = 8);
|
||||||
virtual ~AssemblyBase();
|
virtual ~AssemblyBase();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -3,17 +3,12 @@
|
|||||||
#include "fsfw/subsystem/SubsystemBase.h"
|
#include "fsfw/subsystem/SubsystemBase.h"
|
||||||
|
|
||||||
ChildHandlerBase::ChildHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication,
|
ChildHandlerBase::ChildHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication,
|
||||||
CookieIF* cookie, object_id_t hkDestination,
|
CookieIF* cookie, HasModeTreeChildrenIF& parent,
|
||||||
uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId,
|
FailureIsolationBase* customFdir, size_t cmdQueueSize)
|
||||||
object_id_t parent, FailureIsolationBase* customFdir,
|
|
||||||
size_t cmdQueueSize)
|
|
||||||
: DeviceHandlerBase(setObjectId, deviceCommunication, cookie,
|
: DeviceHandlerBase(setObjectId, deviceCommunication, cookie,
|
||||||
(customFdir == nullptr ? &childHandlerFdir : customFdir), cmdQueueSize),
|
(customFdir == nullptr ? &childHandlerFdir : customFdir), cmdQueueSize),
|
||||||
parentId(parent),
|
parent(parent),
|
||||||
childHandlerFdir(setObjectId) {
|
childHandlerFdir(setObjectId) {}
|
||||||
this->setHkDestination(hkDestination);
|
|
||||||
this->setThermalStateRequestPoolIds(thermalStatePoolId, thermalRequestPoolId);
|
|
||||||
}
|
|
||||||
|
|
||||||
ChildHandlerBase::~ChildHandlerBase() {}
|
ChildHandlerBase::~ChildHandlerBase() {}
|
||||||
|
|
||||||
@ -23,21 +18,5 @@ ReturnValue_t ChildHandlerBase::initialize() {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageQueueId_t parentQueue = 0;
|
return DeviceHandlerBase::connectModeTreeParent(parent);
|
||||||
|
|
||||||
if (parentId != objects::NO_OBJECT) {
|
|
||||||
SubsystemBase* parent = ObjectManager::instance()->get<SubsystemBase>(parentId);
|
|
||||||
if (parent == NULL) {
|
|
||||||
return returnvalue::FAILED;
|
|
||||||
}
|
|
||||||
parentQueue = parent->getCommandQueue();
|
|
||||||
|
|
||||||
parent->registerChild(getObjectId());
|
|
||||||
}
|
|
||||||
|
|
||||||
healthHelper.setParentQueue(parentQueue);
|
|
||||||
|
|
||||||
modeHelper.setParentQueue(parentQueue);
|
|
||||||
|
|
||||||
return returnvalue::OK;
|
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,23 @@
|
|||||||
#ifndef FSFW_DEVICEHANDLER_CHILDHANDLERBASE_H_
|
#ifndef FSFW_DEVICEHANDLER_CHILDHANDLERBASE_H_
|
||||||
#define FSFW_DEVICEHANDLER_CHILDHANDLERBASE_H_
|
#define FSFW_DEVICEHANDLER_CHILDHANDLERBASE_H_
|
||||||
|
|
||||||
|
#include <fsfw/subsystem/HasModeTreeChildrenIF.h>
|
||||||
|
|
||||||
#include "ChildHandlerFDIR.h"
|
#include "ChildHandlerFDIR.h"
|
||||||
#include "DeviceHandlerBase.h"
|
#include "DeviceHandlerBase.h"
|
||||||
|
|
||||||
class ChildHandlerBase : public DeviceHandlerBase {
|
class ChildHandlerBase : public DeviceHandlerBase {
|
||||||
public:
|
public:
|
||||||
ChildHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, CookieIF* cookie,
|
ChildHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, CookieIF* cookie,
|
||||||
object_id_t hkDestination, uint32_t thermalStatePoolId,
|
HasModeTreeChildrenIF& parent, FailureIsolationBase* customFdir = nullptr,
|
||||||
uint32_t thermalRequestPoolId, object_id_t parent = objects::NO_OBJECT,
|
size_t cmdQueueSize = 20);
|
||||||
FailureIsolationBase* customFdir = nullptr, size_t cmdQueueSize = 20);
|
|
||||||
|
|
||||||
virtual ~ChildHandlerBase();
|
virtual ~ChildHandlerBase();
|
||||||
|
|
||||||
virtual ReturnValue_t initialize();
|
virtual ReturnValue_t initialize();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const uint32_t parentId;
|
HasModeTreeChildrenIF& parent;
|
||||||
ChildHandlerFDIR childHandlerFdir;
|
ChildHandlerFDIR childHandlerFdir;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "fsfw/devicehandlers/DeviceHandlerBase.h"
|
#include "DeviceHandlerBase.h"
|
||||||
|
|
||||||
|
#include "fsfw/datapool/PoolReadGuard.h"
|
||||||
#include "fsfw/datapoollocal/LocalPoolVariable.h"
|
#include "fsfw/datapoollocal/LocalPoolVariable.h"
|
||||||
#include "fsfw/devicehandlers/AcceptsDeviceResponsesIF.h"
|
#include "fsfw/devicehandlers/AcceptsDeviceResponsesIF.h"
|
||||||
#include "fsfw/devicehandlers/DeviceTmReportingWrapper.h"
|
#include "fsfw/devicehandlers/DeviceTmReportingWrapper.h"
|
||||||
@ -12,6 +13,7 @@
|
|||||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||||
#include "fsfw/storagemanager/StorageManagerIF.h"
|
#include "fsfw/storagemanager/StorageManagerIF.h"
|
||||||
#include "fsfw/subsystem/SubsystemBase.h"
|
#include "fsfw/subsystem/SubsystemBase.h"
|
||||||
|
#include "fsfw/subsystem/helper.h"
|
||||||
#include "fsfw/thermal/ThermalComponentIF.h"
|
#include "fsfw/thermal/ThermalComponentIF.h"
|
||||||
|
|
||||||
object_id_t DeviceHandlerBase::powerSwitcherId = objects::NO_OBJECT;
|
object_id_t DeviceHandlerBase::powerSwitcherId = objects::NO_OBJECT;
|
||||||
@ -56,12 +58,7 @@ void DeviceHandlerBase::setHkDestination(object_id_t hkDestination) {
|
|||||||
this->hkDestination = hkDestination;
|
this->hkDestination = hkDestination;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeviceHandlerBase::setThermalStateRequestPoolIds(lp_id_t thermalStatePoolId,
|
void DeviceHandlerBase::enableThermalModule(ThermalStateCfg cfg) { this->thermalStateCfg = cfg; }
|
||||||
lp_id_t heaterRequestPoolId,
|
|
||||||
uint32_t thermalSetId) {
|
|
||||||
thermalSet =
|
|
||||||
new DeviceHandlerThermalSet(this, thermalSetId, thermalStatePoolId, heaterRequestPoolId);
|
|
||||||
}
|
|
||||||
|
|
||||||
DeviceHandlerBase::~DeviceHandlerBase() {
|
DeviceHandlerBase::~DeviceHandlerBase() {
|
||||||
if (comCookie != nullptr) {
|
if (comCookie != nullptr) {
|
||||||
@ -132,14 +129,6 @@ ReturnValue_t DeviceHandlerBase::initialize() {
|
|||||||
new DeviceHandlerFailureIsolation(this->getObjectId(), defaultFdirParentId);
|
new DeviceHandlerFailureIsolation(this->getObjectId(), defaultFdirParentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->parent != objects::NO_OBJECT) {
|
|
||||||
HasModesIF* modeIF = ObjectManager::instance()->get<HasModesIF>(this->parent);
|
|
||||||
HasHealthIF* healthIF = ObjectManager::instance()->get<HasHealthIF>(this->parent);
|
|
||||||
if (modeIF != nullptr and healthIF != nullptr) {
|
|
||||||
setParentQueue(modeIF->getCommandQueue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
communicationInterface =
|
communicationInterface =
|
||||||
ObjectManager::instance()->get<DeviceCommunicationIF>(deviceCommunicationId);
|
ObjectManager::instance()->get<DeviceCommunicationIF>(deviceCommunicationId);
|
||||||
if (communicationInterface == nullptr) {
|
if (communicationInterface == nullptr) {
|
||||||
@ -233,12 +222,11 @@ ReturnValue_t DeviceHandlerBase::initialize() {
|
|||||||
fillCommandAndReplyMap();
|
fillCommandAndReplyMap();
|
||||||
|
|
||||||
if (thermalSet != nullptr) {
|
if (thermalSet != nullptr) {
|
||||||
|
PoolReadGuard pg(thermalSet);
|
||||||
// Set temperature target state to NON_OP.
|
// Set temperature target state to NON_OP.
|
||||||
result = thermalSet->read();
|
if (pg.getReadResult() == returnvalue::OK) {
|
||||||
if (result == returnvalue::OK) {
|
|
||||||
thermalSet->heaterRequest.value = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL;
|
thermalSet->heaterRequest.value = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL;
|
||||||
thermalSet->heaterRequest.setValid(true);
|
thermalSet->heaterRequest.setValid(true);
|
||||||
thermalSet->commit();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -368,6 +356,8 @@ void DeviceHandlerBase::doStateMachine() {
|
|||||||
if ((switchState == PowerSwitchIF::SWITCH_ON) || (switchState == NO_SWITCH)) {
|
if ((switchState == PowerSwitchIF::SWITCH_ON) || (switchState == NO_SWITCH)) {
|
||||||
// NOTE: TransitionSourceMode and -SubMode are set by handleCommandedModeTransition
|
// NOTE: TransitionSourceMode and -SubMode are set by handleCommandedModeTransition
|
||||||
childTransitionFailure = CHILD_TIMEOUT;
|
childTransitionFailure = CHILD_TIMEOUT;
|
||||||
|
transitionSourceMode = _MODE_SHUT_DOWN;
|
||||||
|
transitionSourceSubMode = SUBMODE_NONE;
|
||||||
setMode(_MODE_START_UP);
|
setMode(_MODE_START_UP);
|
||||||
callChildStatemachine();
|
callChildStatemachine();
|
||||||
}
|
}
|
||||||
@ -386,7 +376,7 @@ void DeviceHandlerBase::doStateMachine() {
|
|||||||
}
|
}
|
||||||
ReturnValue_t switchState = getStateOfSwitches();
|
ReturnValue_t switchState = getStateOfSwitches();
|
||||||
if ((switchState == PowerSwitchIF::SWITCH_OFF) || (switchState == NO_SWITCH)) {
|
if ((switchState == PowerSwitchIF::SWITCH_OFF) || (switchState == NO_SWITCH)) {
|
||||||
setMode(_MODE_SWITCH_IS_OFF);
|
setMode(MODE_OFF, SUBMODE_NONE);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case MODE_OFF:
|
case MODE_OFF:
|
||||||
@ -399,9 +389,6 @@ void DeviceHandlerBase::doStateMachine() {
|
|||||||
case MODE_NORMAL:
|
case MODE_NORMAL:
|
||||||
case MODE_ERROR_ON:
|
case MODE_ERROR_ON:
|
||||||
break;
|
break;
|
||||||
case _MODE_SWITCH_IS_OFF:
|
|
||||||
setMode(MODE_OFF, SUBMODE_NONE);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
triggerEvent(OBJECT_IN_INVALID_MODE, mode, submode);
|
triggerEvent(OBJECT_IN_INVALID_MODE, mode, submode);
|
||||||
setMode(_MODE_POWER_DOWN, 0);
|
setMode(_MODE_POWER_DOWN, 0);
|
||||||
@ -573,12 +560,14 @@ void DeviceHandlerBase::setTransition(Mode_t modeTo, Submode_t submodeTo) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) {
|
void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* handle transition from OFF to NORMAL by continuing towards normal when ON is reached
|
* handle transition from OFF to NORMAL by continuing towards normal when ON is reached
|
||||||
*/
|
*/
|
||||||
if (newMode == MODE_ON and continueToNormal) {
|
if (newMode == MODE_ON and continueToNormal) {
|
||||||
continueToNormal = false;
|
continueToNormal = false;
|
||||||
|
// TODO: Check whether the following two lines are okay to do so.
|
||||||
|
transitionSourceMode = MODE_ON;
|
||||||
|
transitionSourceSubMode = submode;
|
||||||
mode = _MODE_TO_NORMAL;
|
mode = _MODE_TO_NORMAL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -599,12 +588,12 @@ void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) {
|
|||||||
Clock::getUptime(&timeoutStart);
|
Clock::getUptime(&timeoutStart);
|
||||||
|
|
||||||
if (mode == MODE_OFF and thermalSet != nullptr) {
|
if (mode == MODE_OFF and thermalSet != nullptr) {
|
||||||
ReturnValue_t result = thermalSet->read();
|
PoolReadGuard pg(thermalSet);
|
||||||
if (result == returnvalue::OK) {
|
if (pg.getReadResult() == returnvalue::OK) {
|
||||||
if (thermalSet->heaterRequest.value != ThermalComponentIF::STATE_REQUEST_IGNORE) {
|
if (thermalSet->heaterRequest.value != ThermalComponentIF::STATE_REQUEST_IGNORE) {
|
||||||
thermalSet->heaterRequest.value = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL;
|
thermalSet->heaterRequest.value = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL;
|
||||||
}
|
}
|
||||||
thermalSet->heaterRequest.commit(PoolVariableIF::VALID);
|
thermalSet->heaterRequest.setValid(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* TODO: This will probably be done by the LocalDataPoolManager now */
|
/* TODO: This will probably be done by the LocalDataPoolManager now */
|
||||||
@ -1093,8 +1082,8 @@ ReturnValue_t DeviceHandlerBase::checkModeCommand(Mode_t commandedMode, Submode_
|
|||||||
// Do not check thermal state for MODE_RAW
|
// Do not check thermal state for MODE_RAW
|
||||||
if ((mode == MODE_OFF) and ((commandedMode == MODE_ON) or (commandedMode == MODE_NORMAL)) and
|
if ((mode == MODE_OFF) and ((commandedMode == MODE_ON) or (commandedMode == MODE_NORMAL)) and
|
||||||
(thermalSet != nullptr)) {
|
(thermalSet != nullptr)) {
|
||||||
ReturnValue_t result = thermalSet->read();
|
PoolReadGuard pg(thermalSet);
|
||||||
if (result == returnvalue::OK) {
|
if (pg.getReadResult() == returnvalue::OK) {
|
||||||
if ((thermalSet->heaterRequest.value != ThermalComponentIF::STATE_REQUEST_IGNORE) and
|
if ((thermalSet->heaterRequest.value != ThermalComponentIF::STATE_REQUEST_IGNORE) and
|
||||||
(not ThermalComponentIF::isOperational(thermalSet->thermalState.value))) {
|
(not ThermalComponentIF::isOperational(thermalSet->thermalState.value))) {
|
||||||
triggerEvent(ThermalComponentIF::TEMP_NOT_IN_OP_RANGE, thermalSet->thermalState.value);
|
triggerEvent(ThermalComponentIF::TEMP_NOT_IN_OP_RANGE, thermalSet->thermalState.value);
|
||||||
@ -1155,11 +1144,10 @@ void DeviceHandlerBase::handleTransitionToOnMode(Mode_t commandedMode, Submode_t
|
|||||||
childTransitionDelay = getTransitionDelayMs(_MODE_START_UP, MODE_ON);
|
childTransitionDelay = getTransitionDelayMs(_MODE_START_UP, MODE_ON);
|
||||||
triggerEvent(CHANGING_MODE, commandedMode, commandedSubmode);
|
triggerEvent(CHANGING_MODE, commandedMode, commandedSubmode);
|
||||||
if (thermalSet != nullptr) {
|
if (thermalSet != nullptr) {
|
||||||
ReturnValue_t result = thermalSet->read();
|
PoolReadGuard pg(thermalSet);
|
||||||
if (result == returnvalue::OK) {
|
if (pg.getReadResult() == returnvalue::OK) {
|
||||||
if (thermalSet->heaterRequest != ThermalComponentIF::STATE_REQUEST_IGNORE) {
|
if (thermalSet->heaterRequest != ThermalComponentIF::STATE_REQUEST_IGNORE) {
|
||||||
thermalSet->heaterRequest = ThermalComponentIF::STATE_REQUEST_OPERATIONAL;
|
thermalSet->heaterRequest = ThermalComponentIF::STATE_REQUEST_OPERATIONAL;
|
||||||
thermalSet->commit();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1482,11 +1470,11 @@ void DeviceHandlerBase::performOperationHook() {}
|
|||||||
|
|
||||||
ReturnValue_t DeviceHandlerBase::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
ReturnValue_t DeviceHandlerBase::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
||||||
LocalDataPoolManager& poolManager) {
|
LocalDataPoolManager& poolManager) {
|
||||||
if (thermalSet != nullptr) {
|
if (thermalStateCfg.has_value()) {
|
||||||
localDataPoolMap.emplace(thermalSet->thermalStatePoolId,
|
localDataPoolMap.emplace(thermalStateCfg.value().thermalStatePoolId,
|
||||||
new PoolEntry<DeviceHandlerIF::dh_thermal_state_t>);
|
new PoolEntry<DeviceHandlerIF::dh_thermal_state_t>());
|
||||||
localDataPoolMap.emplace(thermalSet->heaterRequestPoolId,
|
localDataPoolMap.emplace(thermalStateCfg.value().thermalRequestPoolId,
|
||||||
new PoolEntry<DeviceHandlerIF::dh_heater_request_t>);
|
new PoolEntry<DeviceHandlerIF::dh_heater_request_t>());
|
||||||
}
|
}
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
@ -1499,6 +1487,10 @@ ReturnValue_t DeviceHandlerBase::initializeAfterTaskCreation() {
|
|||||||
}
|
}
|
||||||
this->poolManager.initializeAfterTaskCreation();
|
this->poolManager.initializeAfterTaskCreation();
|
||||||
|
|
||||||
|
if (thermalStateCfg.has_value()) {
|
||||||
|
ThermalStateCfg& cfg = thermalStateCfg.value();
|
||||||
|
thermalSet = new DeviceHandlerThermalSet(this, cfg);
|
||||||
|
}
|
||||||
if (setStartupImmediately) {
|
if (setStartupImmediately) {
|
||||||
startTransition(MODE_ON, getInitialSubmode());
|
startTransition(MODE_ON, getInitialSubmode());
|
||||||
}
|
}
|
||||||
@ -1530,7 +1522,10 @@ DeviceCommandId_t DeviceHandlerBase::getPendingCommand() const {
|
|||||||
void DeviceHandlerBase::setNormalDatapoolEntriesInvalid() {
|
void DeviceHandlerBase::setNormalDatapoolEntriesInvalid() {
|
||||||
for (const auto& reply : deviceReplyMap) {
|
for (const auto& reply : deviceReplyMap) {
|
||||||
if (reply.second.dataSet != nullptr) {
|
if (reply.second.dataSet != nullptr) {
|
||||||
reply.second.dataSet->setValidity(false, true);
|
PoolReadGuard pg(reply.second.dataSet);
|
||||||
|
if (pg.getReadResult() == returnvalue::OK) {
|
||||||
|
reply.second.dataSet->setValidity(false, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1587,19 +1582,13 @@ MessageQueueId_t DeviceHandlerBase::getCommanderQueueId(DeviceCommandId_t replyI
|
|||||||
|
|
||||||
void DeviceHandlerBase::setCustomFdir(FailureIsolationBase* fdir) { this->fdirInstance = fdir; }
|
void DeviceHandlerBase::setCustomFdir(FailureIsolationBase* fdir) { this->fdirInstance = fdir; }
|
||||||
|
|
||||||
void DeviceHandlerBase::setParent(object_id_t parent) { this->parent = parent; }
|
|
||||||
|
|
||||||
void DeviceHandlerBase::setPowerSwitcher(PowerSwitchIF* switcher) {
|
void DeviceHandlerBase::setPowerSwitcher(PowerSwitchIF* switcher) {
|
||||||
this->powerSwitcher = switcher;
|
this->powerSwitcher = switcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
Mode_t DeviceHandlerBase::getMode() {
|
Mode_t DeviceHandlerBase::getMode() { return mode; }
|
||||||
return mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
Submode_t DeviceHandlerBase::getSubmode() {
|
Submode_t DeviceHandlerBase::getSubmode() { return submode; }
|
||||||
return submode;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceHandlerBase::disableCommandsAndReplies() {
|
void DeviceHandlerBase::disableCommandsAndReplies() {
|
||||||
for (auto& command : deviceCommandMap) {
|
for (auto& command : deviceCommandMap) {
|
||||||
@ -1619,6 +1608,16 @@ void DeviceHandlerBase::disableCommandsAndReplies() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReturnValue_t DeviceHandlerBase::connectModeTreeParent(HasModeTreeChildrenIF& parent) {
|
||||||
|
return modetree::connectModeTreeParent(parent, *this, &healthHelper, modeHelper);
|
||||||
|
}
|
||||||
|
|
||||||
|
const HasHealthIF* DeviceHandlerBase::getOptHealthIF() const { return this; }
|
||||||
|
|
||||||
|
const HasModesIF& DeviceHandlerBase::getModeIF() const { return *this; }
|
||||||
|
|
||||||
|
ModeTreeChildIF& DeviceHandlerBase::getModeTreeChildIF() { return *this; }
|
||||||
|
|
||||||
ReturnValue_t DeviceHandlerBase::finishAction(bool success, DeviceCommandId_t action,
|
ReturnValue_t DeviceHandlerBase::finishAction(bool success, DeviceCommandId_t action,
|
||||||
ReturnValue_t result) {
|
ReturnValue_t result) {
|
||||||
auto commandIter = deviceCommandMap.find(action);
|
auto commandIter = deviceCommandMap.find(action);
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define FSFW_DEVICEHANDLERS_DEVICEHANDLERBASE_H_
|
#define FSFW_DEVICEHANDLERS_DEVICEHANDLERBASE_H_
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
#include "DeviceCommunicationIF.h"
|
#include "DeviceCommunicationIF.h"
|
||||||
#include "DeviceHandlerFailureIsolation.h"
|
#include "DeviceHandlerFailureIsolation.h"
|
||||||
@ -21,9 +22,9 @@
|
|||||||
#include "fsfw/returnvalues/returnvalue.h"
|
#include "fsfw/returnvalues/returnvalue.h"
|
||||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||||
#include "fsfw/serviceinterface/serviceInterfaceDefintions.h"
|
#include "fsfw/serviceinterface/serviceInterfaceDefintions.h"
|
||||||
|
#include "fsfw/subsystem/ModeTreeConnectionIF.h"
|
||||||
#include "fsfw/tasks/ExecutableObjectIF.h"
|
#include "fsfw/tasks/ExecutableObjectIF.h"
|
||||||
#include "fsfw/tasks/PeriodicTaskIF.h"
|
#include "fsfw/tasks/PeriodicTaskIF.h"
|
||||||
#include "fsfw/util/dataWrapper.h"
|
|
||||||
|
|
||||||
namespace Factory {
|
namespace Factory {
|
||||||
void setStaticFrameworkObjectIds();
|
void setStaticFrameworkObjectIds();
|
||||||
@ -84,6 +85,8 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
public HasModesIF,
|
public HasModesIF,
|
||||||
public HasHealthIF,
|
public HasHealthIF,
|
||||||
public HasActionsIF,
|
public HasActionsIF,
|
||||||
|
public ModeTreeChildIF,
|
||||||
|
public ModeTreeConnectionIF,
|
||||||
public ReceivesParameterMessagesIF,
|
public ReceivesParameterMessagesIF,
|
||||||
public HasLocalDataPoolIF {
|
public HasLocalDataPoolIF {
|
||||||
friend void(Factory::setStaticFrameworkObjectIds)();
|
friend void(Factory::setStaticFrameworkObjectIds)();
|
||||||
@ -104,7 +107,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
FailureIsolationBase *fdirInstance = nullptr, size_t cmdQueueSize = 20);
|
FailureIsolationBase *fdirInstance = nullptr, size_t cmdQueueSize = 20);
|
||||||
|
|
||||||
void setCustomFdir(FailureIsolationBase *fdir);
|
void setCustomFdir(FailureIsolationBase *fdir);
|
||||||
void setParent(object_id_t parent);
|
|
||||||
void setPowerSwitcher(PowerSwitchIF *switcher);
|
void setPowerSwitcher(PowerSwitchIF *switcher);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -148,11 +150,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
//! has been commanded on and the handler waits for it to be on.
|
//! has been commanded on and the handler waits for it to be on.
|
||||||
//! When the switch is on, the mode changes to @c _MODE_TO_ON.
|
//! When the switch is on, the mode changes to @c _MODE_TO_ON.
|
||||||
static const Mode_t _MODE_WAIT_ON = TRANSITION_MODE_BASE_ACTION_MASK | 4;
|
static const Mode_t _MODE_WAIT_ON = TRANSITION_MODE_BASE_ACTION_MASK | 4;
|
||||||
//! This is a transitional state which can not be commanded. The switch has
|
|
||||||
//! been commanded off and is off now. This state is only to do an RMAP
|
|
||||||
//! cycle once more where the doSendRead() function will set the mode to
|
|
||||||
//! MODE_OFF. The reason to do this is to get rid of stuck packets in the IO Board.
|
|
||||||
static const Mode_t _MODE_SWITCH_IS_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 5;
|
|
||||||
|
|
||||||
void setHkDestination(object_id_t hkDestination);
|
void setHkDestination(object_id_t hkDestination);
|
||||||
|
|
||||||
@ -162,13 +159,12 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
* The device handler will then take care of creating local pool entries
|
* The device handler will then take care of creating local pool entries
|
||||||
* for the device thermal state and device heating request.
|
* for the device thermal state and device heating request.
|
||||||
* Custom local pool IDs can be assigned as well.
|
* Custom local pool IDs can be assigned as well.
|
||||||
* @param thermalStatePoolId
|
|
||||||
* @param thermalRequestPoolId
|
|
||||||
*/
|
*/
|
||||||
void setThermalStateRequestPoolIds(
|
void enableThermalModule(ThermalStateCfg cfg);
|
||||||
lp_id_t thermalStatePoolId = DeviceHandlerIF::DEFAULT_THERMAL_STATE_POOL_ID,
|
|
||||||
lp_id_t thermalRequestPoolId = DeviceHandlerIF::DEFAULT_THERMAL_HEATING_REQUEST_POOL_ID,
|
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF &parent) override;
|
||||||
uint32_t thermalSetId = DeviceHandlerIF::DEFAULT_THERMAL_SET_ID);
|
ModeTreeChildIF &getModeTreeChildIF() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Helper function to ease device handler development.
|
* @brief Helper function to ease device handler development.
|
||||||
* This will instruct the transition to MODE_ON immediately
|
* This will instruct the transition to MODE_ON immediately
|
||||||
@ -214,7 +210,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
* @param counter Specifies which Action to perform
|
* @param counter Specifies which Action to perform
|
||||||
* @return returnvalue::OK for successful execution
|
* @return returnvalue::OK for successful execution
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t performOperation(uint8_t counter) override;
|
ReturnValue_t performOperation(uint8_t counter) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initializes the device handler
|
* @brief Initializes the device handler
|
||||||
@ -224,14 +220,14 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
* Calls fillCommandAndReplyMap().
|
* Calls fillCommandAndReplyMap().
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t initialize() override;
|
ReturnValue_t initialize() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Intialization steps performed after all tasks have been created.
|
* @brief Intialization steps performed after all tasks have been created.
|
||||||
* This function will be called by the executing task.
|
* This function will be called by the executing task.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t initializeAfterTaskCreation() override;
|
ReturnValue_t initializeAfterTaskCreation() override;
|
||||||
|
|
||||||
/** Destructor. */
|
/** Destructor. */
|
||||||
virtual ~DeviceHandlerBase();
|
virtual ~DeviceHandlerBase();
|
||||||
@ -248,6 +244,8 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
virtual object_id_t getObjectId() const override;
|
virtual object_id_t getObjectId() const override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* This is a helper method for classes which are parent nodes in the mode tree.
|
||||||
|
* It registers the passed queue as the destination for mode and health messages.
|
||||||
* @param parentQueueId
|
* @param parentQueueId
|
||||||
*/
|
*/
|
||||||
virtual void setParentQueue(MessageQueueId_t parentQueueId);
|
virtual void setParentQueue(MessageQueueId_t parentQueueId);
|
||||||
@ -924,6 +922,8 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
//! Object which may be the root cause of an identified fault.
|
//! Object which may be the root cause of an identified fault.
|
||||||
static object_id_t defaultFdirParentId;
|
static object_id_t defaultFdirParentId;
|
||||||
|
|
||||||
|
std::optional<ThermalStateCfg> thermalStateCfg;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Send a reply to a received device handler command.
|
* @brief Send a reply to a received device handler command.
|
||||||
*
|
*
|
||||||
@ -1012,6 +1012,9 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
*/
|
*/
|
||||||
LocalDataPoolManager *getHkManagerHandle() override;
|
LocalDataPoolManager *getHkManagerHandle() override;
|
||||||
|
|
||||||
|
const HasHealthIF *getOptHealthIF() const override;
|
||||||
|
const HasModesIF &getModeIF() const override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the delay cycle count of a reply.
|
* Returns the delay cycle count of a reply.
|
||||||
* A count != 0 indicates that the command is already executed.
|
* A count != 0 indicates that the command is already executed.
|
||||||
|
@ -136,4 +136,10 @@ class DeviceHandlerIF {
|
|||||||
virtual MessageQueueId_t getCommandQueue() const = 0;
|
virtual MessageQueueId_t getCommandQueue() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ThermalStateCfg {
|
||||||
|
lp_id_t thermalStatePoolId = DeviceHandlerIF::DEFAULT_THERMAL_STATE_POOL_ID;
|
||||||
|
lp_id_t thermalRequestPoolId = DeviceHandlerIF::DEFAULT_THERMAL_HEATING_REQUEST_POOL_ID;
|
||||||
|
uint32_t thermalSetId = DeviceHandlerIF::DEFAULT_THERMAL_SET_ID;
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERIF_H_ */
|
#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERIF_H_ */
|
||||||
|
@ -7,27 +7,21 @@
|
|||||||
|
|
||||||
class DeviceHandlerThermalSet : public StaticLocalDataSet<2> {
|
class DeviceHandlerThermalSet : public StaticLocalDataSet<2> {
|
||||||
public:
|
public:
|
||||||
DeviceHandlerThermalSet(
|
DeviceHandlerThermalSet(HasLocalDataPoolIF* hkOwner, ThermalStateCfg cfg)
|
||||||
HasLocalDataPoolIF* hkOwner, uint32_t setId = DeviceHandlerIF::DEFAULT_THERMAL_SET_ID,
|
: DeviceHandlerThermalSet(hkOwner->getObjectId(), cfg) {}
|
||||||
lp_id_t thermalStateId = DeviceHandlerIF::DEFAULT_THERMAL_STATE_POOL_ID,
|
|
||||||
lp_id_t heaterRequestId = DeviceHandlerIF::DEFAULT_THERMAL_HEATING_REQUEST_POOL_ID)
|
|
||||||
: DeviceHandlerThermalSet(hkOwner->getObjectId(), setId, thermalStateId, heaterRequestId) {}
|
|
||||||
|
|
||||||
DeviceHandlerThermalSet(
|
DeviceHandlerThermalSet(object_id_t deviceHandler, ThermalStateCfg cfg)
|
||||||
object_id_t deviceHandler, uint32_t setId = DeviceHandlerIF::DEFAULT_THERMAL_SET_ID,
|
: StaticLocalDataSet(sid_t(deviceHandler, cfg.thermalSetId)),
|
||||||
lp_id_t thermalStateId = DeviceHandlerIF::DEFAULT_THERMAL_STATE_POOL_ID,
|
thermalStatePoolId(cfg.thermalStatePoolId),
|
||||||
lp_id_t thermalStateRequestId = DeviceHandlerIF::DEFAULT_THERMAL_HEATING_REQUEST_POOL_ID)
|
heaterRequestPoolId(cfg.thermalRequestPoolId) {}
|
||||||
: StaticLocalDataSet(sid_t(deviceHandler, setId)),
|
|
||||||
thermalStatePoolId(thermalStateId),
|
|
||||||
heaterRequestPoolId(thermalStateRequestId) {}
|
|
||||||
|
|
||||||
const lp_id_t thermalStatePoolId;
|
const lp_id_t thermalStatePoolId;
|
||||||
const lp_id_t heaterRequestPoolId;
|
const lp_id_t heaterRequestPoolId;
|
||||||
|
|
||||||
lp_var_t<DeviceHandlerIF::dh_thermal_state_t> thermalState =
|
lp_var_t<DeviceHandlerIF::dh_thermal_state_t> thermalState =
|
||||||
lp_var_t<DeviceHandlerIF::dh_thermal_state_t>(thermalStatePoolId, sid.objectId, this);
|
lp_var_t<DeviceHandlerIF::dh_thermal_state_t>(sid.objectId, thermalStatePoolId, this);
|
||||||
lp_var_t<DeviceHandlerIF::dh_heater_request_t> heaterRequest =
|
lp_var_t<DeviceHandlerIF::dh_heater_request_t> heaterRequest =
|
||||||
lp_var_t<DeviceHandlerIF::dh_heater_request_t>(heaterRequestPoolId, sid.objectId, this);
|
lp_var_t<DeviceHandlerIF::dh_heater_request_t>(sid.objectId, heaterRequestPoolId, this);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERTHERMALSET_H_ */
|
#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERTHERMALSET_H_ */
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
#include "fsfw/action/HasActionsIF.h"
|
#include "fsfw/action/HasActionsIF.h"
|
||||||
#include "fsfw/objectmanager/SystemObjectIF.h"
|
#include "fsfw/objectmanager/SystemObjectIF.h"
|
||||||
#include "fsfw/serialize/SerializeIF.h"
|
#include "fsfw/serialize/SerializeIF.h"
|
||||||
#include "fsfw/util/dataWrapper.h"
|
|
||||||
|
|
||||||
class DeviceTmReportingWrapper : public SerializeIF {
|
class DeviceTmReportingWrapper : public SerializeIF {
|
||||||
public:
|
public:
|
||||||
|
@ -15,15 +15,16 @@ const LocalPool::LocalPoolConfig EventManager::poolConfig = {
|
|||||||
{fsfwconfig::FSFW_EVENTMGMT_EVENTIDMATCHERS, sizeof(EventIdRangeMatcher)},
|
{fsfwconfig::FSFW_EVENTMGMT_EVENTIDMATCHERS, sizeof(EventIdRangeMatcher)},
|
||||||
{fsfwconfig::FSFW_EVENTMGMR_RANGEMATCHERS, sizeof(ReporterRangeMatcher)}};
|
{fsfwconfig::FSFW_EVENTMGMR_RANGEMATCHERS, sizeof(ReporterRangeMatcher)}};
|
||||||
|
|
||||||
EventManager::EventManager(object_id_t setObjectId)
|
EventManager::EventManager(object_id_t setObjectId, uint32_t eventQueueDepth)
|
||||||
: SystemObject(setObjectId), factoryBackend(0, poolConfig, false, true) {
|
: SystemObject(setObjectId), factoryBackend(0, poolConfig, false, true) {
|
||||||
mutex = MutexFactory::instance()->createMutex();
|
mutex = MutexFactory::instance()->createMutex();
|
||||||
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
|
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
|
||||||
eventReportQueue = QueueFactory::instance()->createMessageQueue(
|
eventReportQueue = QueueFactory::instance()->createMessageQueue(
|
||||||
MAX_EVENTS_PER_CYCLE, EventMessage::EVENT_MESSAGE_SIZE, &mqArgs);
|
eventQueueDepth, EventMessage::EVENT_MESSAGE_SIZE, &mqArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
EventManager::~EventManager() {
|
EventManager::~EventManager() {
|
||||||
|
listenerList.clear();
|
||||||
QueueFactory::instance()->deleteMessageQueue(eventReportQueue);
|
QueueFactory::instance()->deleteMessageQueue(eventReportQueue);
|
||||||
MutexFactory::instance()->deleteMutex(mutex);
|
MutexFactory::instance()->deleteMutex(mutex);
|
||||||
}
|
}
|
||||||
@ -73,9 +74,14 @@ ReturnValue_t EventManager::registerListener(MessageQueueId_t listener,
|
|||||||
if (!result.second) {
|
if (!result.second) {
|
||||||
return returnvalue::FAILED;
|
return returnvalue::FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReturnValue_t EventManager::unregisterListener(MessageQueueId_t listener) {
|
||||||
|
return listenerList.erase(listener) == 1 ? returnvalue::OK : returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
ReturnValue_t EventManager::subscribeToEvent(MessageQueueId_t listener, EventId_t event) {
|
ReturnValue_t EventManager::subscribeToEvent(MessageQueueId_t listener, EventId_t event) {
|
||||||
return subscribeToEventRange(listener, event);
|
return subscribeToEventRange(listener, event);
|
||||||
}
|
}
|
||||||
|
@ -21,9 +21,9 @@ extern const char* translateEvents(Event event);
|
|||||||
|
|
||||||
class EventManager : public EventManagerIF, public ExecutableObjectIF, public SystemObject {
|
class EventManager : public EventManagerIF, public ExecutableObjectIF, public SystemObject {
|
||||||
public:
|
public:
|
||||||
static const uint16_t MAX_EVENTS_PER_CYCLE = 80;
|
static const uint16_t DEFAULT_MAX_EVENTS_PER_CYCLE = 80;
|
||||||
|
|
||||||
EventManager(object_id_t setObjectId);
|
EventManager(object_id_t setObjectId, uint32_t eventQueueDepth);
|
||||||
virtual ~EventManager();
|
virtual ~EventManager();
|
||||||
|
|
||||||
void setMutexTimeout(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs);
|
void setMutexTimeout(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs);
|
||||||
@ -31,6 +31,7 @@ class EventManager : public EventManagerIF, public ExecutableObjectIF, public Sy
|
|||||||
MessageQueueId_t getEventReportQueue();
|
MessageQueueId_t getEventReportQueue();
|
||||||
|
|
||||||
ReturnValue_t registerListener(MessageQueueId_t listener, bool forwardAllButSelected = false);
|
ReturnValue_t registerListener(MessageQueueId_t listener, bool forwardAllButSelected = false);
|
||||||
|
ReturnValue_t unregisterListener(MessageQueueId_t listener) override;
|
||||||
ReturnValue_t subscribeToEvent(MessageQueueId_t listener, EventId_t event);
|
ReturnValue_t subscribeToEvent(MessageQueueId_t listener, EventId_t event);
|
||||||
ReturnValue_t subscribeToAllEventsFrom(MessageQueueId_t listener, object_id_t object);
|
ReturnValue_t subscribeToAllEventsFrom(MessageQueueId_t listener, object_id_t object);
|
||||||
ReturnValue_t subscribeToEventRange(MessageQueueId_t listener, EventId_t idFrom = 0,
|
ReturnValue_t subscribeToEventRange(MessageQueueId_t listener, EventId_t idFrom = 0,
|
||||||
|
@ -18,6 +18,7 @@ class EventManagerIF {
|
|||||||
|
|
||||||
virtual ReturnValue_t registerListener(MessageQueueId_t listener,
|
virtual ReturnValue_t registerListener(MessageQueueId_t listener,
|
||||||
bool forwardAllButSelected = false) = 0;
|
bool forwardAllButSelected = false) = 0;
|
||||||
|
virtual ReturnValue_t unregisterListener(MessageQueueId_t listener) = 0;
|
||||||
virtual ReturnValue_t subscribeToEvent(MessageQueueId_t listener, EventId_t event) = 0;
|
virtual ReturnValue_t subscribeToEvent(MessageQueueId_t listener, EventId_t event) = 0;
|
||||||
virtual ReturnValue_t subscribeToAllEventsFrom(MessageQueueId_t listener, object_id_t object) = 0;
|
virtual ReturnValue_t subscribeToAllEventsFrom(MessageQueueId_t listener, object_id_t object) = 0;
|
||||||
virtual ReturnValue_t unsubscribeFromAllEvents(MessageQueueId_t listener, object_id_t object) = 0;
|
virtual ReturnValue_t unsubscribeFromAllEvents(MessageQueueId_t listener, object_id_t object) = 0;
|
||||||
|
@ -24,7 +24,7 @@ FailureIsolationBase::~FailureIsolationBase() {
|
|||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
manager->unsubscribeFromAllEvents(eventQueue->getId(), ownerId);
|
manager->unregisterListener(eventQueue->getId());
|
||||||
QueueFactory::instance()->deleteMessageQueue(eventQueue);
|
QueueFactory::instance()->deleteMessageQueue(eventQueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ ReturnValue_t FaultCounter::getParameter(uint8_t domainId, uint8_t uniqueId,
|
|||||||
parameterWrapper->set(faultCount);
|
parameterWrapper->set(faultCount);
|
||||||
break;
|
break;
|
||||||
case ParameterIds::TIMEOUT:
|
case ParameterIds::TIMEOUT:
|
||||||
parameterWrapper->set(timer.timeout);
|
parameterWrapper->set(timer.getTimeoutMs());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return INVALID_IDENTIFIER_ID;
|
return INVALID_IDENTIFIER_ID;
|
||||||
|
@ -74,6 +74,12 @@ class HasFileSystemIF {
|
|||||||
return MessageQueueIF::NO_QUEUE;
|
return MessageQueueIF::NO_QUEUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the base filename without the full directory path
|
||||||
|
virtual ReturnValue_t getBaseFilename(FilesystemParams params, char* nameBuf, size_t maxLen,
|
||||||
|
size_t& baseNameLen) = 0;
|
||||||
|
|
||||||
|
virtual bool isDirectory(const char* path) = 0;
|
||||||
|
|
||||||
virtual bool fileExists(FilesystemParams params) = 0;
|
virtual bool fileExists(FilesystemParams params) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -24,7 +24,7 @@ class MatchTree : public SerializeableMatcherIF<T>, public BinaryTree<Serializea
|
|||||||
MatchTree(iterator root, uint8_t maxDepth = -1)
|
MatchTree(iterator root, uint8_t maxDepth = -1)
|
||||||
: BinaryTree<SerializeableMatcherIF<T>>(root.element), maxDepth(maxDepth) {}
|
: BinaryTree<SerializeableMatcherIF<T>>(root.element), maxDepth(maxDepth) {}
|
||||||
MatchTree() : BinaryTree<SerializeableMatcherIF<T>>(), maxDepth(-1) {}
|
MatchTree() : BinaryTree<SerializeableMatcherIF<T>>(), maxDepth(-1) {}
|
||||||
virtual ~MatchTree() {}
|
virtual ~MatchTree() { clear(); }
|
||||||
virtual bool match(T number) override { return matchesTree(number); }
|
virtual bool match(T number) override { return matchesTree(number); }
|
||||||
bool matchesTree(T number) {
|
bool matchesTree(T number) {
|
||||||
iterator iter = this->begin();
|
iterator iter = this->begin();
|
||||||
@ -176,6 +176,45 @@ class MatchTree : public SerializeableMatcherIF<T>, public BinaryTree<Serializea
|
|||||||
return cleanUpElement(position);
|
return cleanUpElement(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void clear() {
|
||||||
|
Node* localRoot = BinaryTree<SerializeableMatcherIF<T>>::rootNode;
|
||||||
|
|
||||||
|
if (localRoot == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* node = localRoot->left;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (node->left != nullptr) {
|
||||||
|
node = node->left;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (node->right != nullptr) {
|
||||||
|
node = node->right;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (node->parent == nullptr) {
|
||||||
|
// this is the root node with no children
|
||||||
|
if (node->value != nullptr) {
|
||||||
|
cleanUpElement(iterator(node));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// leaf
|
||||||
|
{
|
||||||
|
Node* parent = node->parent;
|
||||||
|
if (parent->left == node) {
|
||||||
|
parent->left = nullptr;
|
||||||
|
} else {
|
||||||
|
parent->right = nullptr;
|
||||||
|
}
|
||||||
|
cleanUpElement(iterator(node));
|
||||||
|
node = parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
virtual ReturnValue_t cleanUpElement(iterator position) { return returnvalue::OK; }
|
virtual ReturnValue_t cleanUpElement(iterator position) { return returnvalue::OK; }
|
||||||
|
|
||||||
bool matchSubtree(iterator iter, T number) {
|
bool matchSubtree(iterator iter, T number) {
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#include "fsfw/globalfunctions/timevalOperations.h"
|
#include "fsfw/globalfunctions/timevalOperations.h"
|
||||||
|
|
||||||
timeval& operator+=(timeval& lhs, const timeval& rhs) {
|
timeval& operator+=(timeval& lhs, const timeval& rhs) {
|
||||||
int64_t sum = lhs.tv_sec * 1000000. + lhs.tv_usec;
|
int64_t sum = static_cast<int64_t>(lhs.tv_sec) * 1000000. + lhs.tv_usec;
|
||||||
sum += rhs.tv_sec * 1000000. + rhs.tv_usec;
|
sum += static_cast<int64_t>(rhs.tv_sec) * 1000000. + rhs.tv_usec;
|
||||||
lhs.tv_sec = sum / 1000000;
|
lhs.tv_sec = sum / 1000000;
|
||||||
lhs.tv_usec = sum - lhs.tv_sec * 1000000;
|
lhs.tv_usec = sum - lhs.tv_sec * 1000000;
|
||||||
return lhs;
|
return lhs;
|
||||||
|
@ -5,7 +5,11 @@
|
|||||||
HealthHelper::HealthHelper(HasHealthIF* owner, object_id_t objectId)
|
HealthHelper::HealthHelper(HasHealthIF* owner, object_id_t objectId)
|
||||||
: objectId(objectId), owner(owner) {}
|
: objectId(objectId), owner(owner) {}
|
||||||
|
|
||||||
HealthHelper::~HealthHelper() { healthTable->removeObject(objectId); }
|
HealthHelper::~HealthHelper() {
|
||||||
|
if (healthTable != nullptr) {
|
||||||
|
healthTable->removeObject(objectId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ReturnValue_t HealthHelper::handleHealthCommand(CommandMessage* message) {
|
ReturnValue_t HealthHelper::handleHealthCommand(CommandMessage* message) {
|
||||||
switch (message->getCommand()) {
|
switch (message->getCommand()) {
|
||||||
|
@ -6,8 +6,6 @@
|
|||||||
|
|
||||||
HealthTable::HealthTable(object_id_t objectid) : SystemObject(objectid) {
|
HealthTable::HealthTable(object_id_t objectid) : SystemObject(objectid) {
|
||||||
mutex = MutexFactory::instance()->createMutex();
|
mutex = MutexFactory::instance()->createMutex();
|
||||||
;
|
|
||||||
|
|
||||||
mapIterator = healthMap.begin();
|
mapIterator = healthMap.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
#include "HealthTableIF.h"
|
#include "HealthTableIF.h"
|
||||||
|
|
||||||
class HealthTable : public HealthTableIF, public SystemObject {
|
class HealthTable : public HealthTableIF, public SystemObject {
|
||||||
|
friend class CServiceHealthCommanding;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit HealthTable(object_id_t objectid);
|
explicit HealthTable(object_id_t objectid);
|
||||||
~HealthTable() override;
|
~HealthTable() override;
|
||||||
|
@ -10,13 +10,17 @@ InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, uint32_t m
|
|||||||
poolManager(this, commandQueue),
|
poolManager(this, commandQueue),
|
||||||
internalErrorSid(setObjectId, InternalErrorDataset::ERROR_SET_ID),
|
internalErrorSid(setObjectId, InternalErrorDataset::ERROR_SET_ID),
|
||||||
internalErrorDataset(this) {
|
internalErrorDataset(this) {
|
||||||
|
commandQueue = QueueFactory::instance()->createMessageQueue(messageQueueDepth);
|
||||||
mutex = MutexFactory::instance()->createMutex();
|
mutex = MutexFactory::instance()->createMutex();
|
||||||
auto mqArgs = MqArgs(setObjectId, static_cast<void *>(this));
|
auto mqArgs = MqArgs(setObjectId, static_cast<void *>(this));
|
||||||
commandQueue = QueueFactory::instance()->createMessageQueue(
|
commandQueue = QueueFactory::instance()->createMessageQueue(
|
||||||
messageQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
messageQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
InternalErrorReporter::~InternalErrorReporter() { MutexFactory::instance()->deleteMutex(mutex); }
|
InternalErrorReporter::~InternalErrorReporter() {
|
||||||
|
MutexFactory::instance()->deleteMutex(mutex);
|
||||||
|
QueueFactory::instance()->deleteMessageQueue(commandQueue);
|
||||||
|
}
|
||||||
|
|
||||||
void InternalErrorReporter::setDiagnosticPrintout(bool enable) {
|
void InternalErrorReporter::setDiagnosticPrintout(bool enable) {
|
||||||
this->diagnosticPrintout = enable;
|
this->diagnosticPrintout = enable;
|
||||||
|
@ -7,14 +7,17 @@
|
|||||||
class MutexGuard {
|
class MutexGuard {
|
||||||
public:
|
public:
|
||||||
MutexGuard(MutexIF* mutex, MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::BLOCKING,
|
MutexGuard(MutexIF* mutex, MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::BLOCKING,
|
||||||
uint32_t timeoutMs = 0)
|
uint32_t timeoutMs = 0, const char* context = nullptr)
|
||||||
: internalMutex(mutex) {
|
: internalMutex(mutex) {
|
||||||
|
if (context == nullptr) {
|
||||||
|
context = "unknown";
|
||||||
|
}
|
||||||
if (mutex == nullptr) {
|
if (mutex == nullptr) {
|
||||||
#if FSFW_VERBOSE_LEVEL >= 1
|
#if FSFW_VERBOSE_LEVEL >= 1
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "MutexGuard: Passed mutex is invalid!" << std::endl;
|
sif::error << "MutexGuard::" << context << ": Passed mutex is invalid!" << std::endl;
|
||||||
#else
|
#else
|
||||||
sif::printError("MutexGuard: Passed mutex is invalid!\n");
|
sif::printError("MutexGuard::%s: Passed mutex is invalid!\n", context);
|
||||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||||
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||||
return;
|
return;
|
||||||
@ -23,11 +26,11 @@ class MutexGuard {
|
|||||||
#if FSFW_VERBOSE_LEVEL >= 1
|
#if FSFW_VERBOSE_LEVEL >= 1
|
||||||
if (result == MutexIF::MUTEX_TIMEOUT) {
|
if (result == MutexIF::MUTEX_TIMEOUT) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "MutexGuard: Lock of mutex failed with timeout of " << timeoutMs
|
sif::error << "MutexGuard::" << context << ": Lock of mutex failed with timeout of "
|
||||||
<< " milliseconds!" << std::endl;
|
<< timeoutMs << " milliseconds!" << std::endl;
|
||||||
#else
|
#else
|
||||||
sif::printError("MutexGuard: Lock of mutex failed with timeout of %lu milliseconds\n",
|
sif::printError("MutexGuard::%s: Lock of mutex failed with timeout of %lu milliseconds\n",
|
||||||
timeoutMs);
|
context, timeoutMs);
|
||||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||||
|
|
||||||
} else if (result != returnvalue::OK) {
|
} else if (result != returnvalue::OK) {
|
||||||
|
@ -24,3 +24,19 @@ void ModeMessage::setCantReachMode(CommandMessage* message, ReturnValue_t reason
|
|||||||
message->setParameter(reason);
|
message->setParameter(reason);
|
||||||
message->setParameter2(0);
|
message->setParameter2(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ModeMessage::setModeAnnounceMessage(CommandMessage& message, bool recursive) {
|
||||||
|
Command_t cmd;
|
||||||
|
if (recursive) {
|
||||||
|
cmd = CMD_MODE_ANNOUNCE_RECURSIVELY;
|
||||||
|
} else {
|
||||||
|
cmd = CMD_MODE_ANNOUNCE;
|
||||||
|
}
|
||||||
|
message.setCommand(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModeMessage::setCmdModeMessage(CommandMessage& message, Mode_t mode, Submode_t submode) {
|
||||||
|
setModeMessage(&message, CMD_MODE_COMMAND, mode, submode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ModeMessage::setModeReadMessage(CommandMessage& message) { message.setCommand(CMD_MODE_READ); }
|
||||||
|
@ -1,43 +1,42 @@
|
|||||||
#ifndef FSFW_MODES_MODEMESSAGE_H_
|
#ifndef FSFW_MODES_MODEMESSAGE_H_
|
||||||
#define FSFW_MODES_MODEMESSAGE_H_
|
#define FSFW_MODES_MODEMESSAGE_H_
|
||||||
|
|
||||||
#include "../ipc/CommandMessage.h"
|
#include "fsfw/ipc/CommandMessage.h"
|
||||||
|
|
||||||
typedef uint32_t Mode_t;
|
typedef uint32_t Mode_t;
|
||||||
typedef uint8_t Submode_t;
|
typedef uint8_t Submode_t;
|
||||||
|
|
||||||
class ModeMessage {
|
class ModeMessage {
|
||||||
private:
|
|
||||||
ModeMessage();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const uint8_t MESSAGE_ID = messagetypes::MODE_COMMAND;
|
static const uint8_t MESSAGE_ID = messagetypes::MODE_COMMAND;
|
||||||
static const Command_t CMD_MODE_COMMAND =
|
//!> Command to set the specified Mode, replies are: REPLY_MODE_REPLY,
|
||||||
MAKE_COMMAND_ID(0x01); //!> Command to set the specified Mode, replies are: REPLY_MODE_REPLY,
|
//! REPLY_WRONG_MODE_REPLY, and REPLY_REJECTED; don't add any replies,
|
||||||
//! REPLY_WRONG_MODE_REPLY, and REPLY_REJECTED; don't add any replies,
|
//! as this will break the subsystem mode machine!!
|
||||||
//! as this will break the subsystem mode machine!!
|
static const Command_t CMD_MODE_COMMAND = MAKE_COMMAND_ID(0x01);
|
||||||
static const Command_t CMD_MODE_COMMAND_FORCED = MAKE_COMMAND_ID(
|
//!> Command to set the specified Mode, regardless of external control flag, replies
|
||||||
0xF1); //!> Command to set the specified Mode, regardless of external control flag, replies
|
//! are: REPLY_MODE_REPLY, REPLY_WRONG_MODE_REPLY, and REPLY_REJECTED; don't add any
|
||||||
//! are: REPLY_MODE_REPLY, REPLY_WRONG_MODE_REPLY, and REPLY_REJECTED; don't add any
|
//! replies, as this will break the subsystem mode machine!!
|
||||||
//! replies, as this will break the subsystem mode machine!!
|
static const Command_t CMD_MODE_COMMAND_FORCED = MAKE_COMMAND_ID(0xF1);
|
||||||
static const Command_t REPLY_MODE_REPLY =
|
//!> Reply to a CMD_MODE_COMMAND or CMD_MODE_READ
|
||||||
MAKE_COMMAND_ID(0x02); //!> Reply to a CMD_MODE_COMMAND or CMD_MODE_READ
|
static const Command_t REPLY_MODE_REPLY = MAKE_COMMAND_ID(0x02);
|
||||||
static const Command_t REPLY_MODE_INFO =
|
//!> Unrequested info about the current mode (used for composites to
|
||||||
MAKE_COMMAND_ID(0x03); //!> Unrequested info about the current mode (used for composites to
|
//! inform their container of a changed mode)
|
||||||
//! inform their container of a changed mode)
|
static const Command_t REPLY_MODE_INFO = MAKE_COMMAND_ID(0x03);
|
||||||
static const Command_t REPLY_CANT_REACH_MODE = MAKE_COMMAND_ID(
|
//!> Reply in case a mode command can't be executed. Par1: returnCode, Par2: 0
|
||||||
0x04); //!> Reply in case a mode command can't be executed. Par1: returnCode, Par2: 0
|
static const Command_t REPLY_CANT_REACH_MODE = MAKE_COMMAND_ID(0x04);
|
||||||
static const Command_t REPLY_WRONG_MODE_REPLY =
|
//!> Reply to a CMD_MODE_COMMAND, indicating that a mode was commanded
|
||||||
MAKE_COMMAND_ID(0x05); //!> Reply to a CMD_MODE_COMMAND, indicating that a mode was commanded
|
//! and a transition started but was aborted; the parameters contain
|
||||||
//! and a transition started but was aborted; the parameters contain
|
//! the mode that was reached
|
||||||
//! the mode that was reached
|
static const Command_t REPLY_WRONG_MODE_REPLY = MAKE_COMMAND_ID(0x05);
|
||||||
static const Command_t CMD_MODE_READ = MAKE_COMMAND_ID(
|
//!> Command to read the current mode and reply with a REPLY_MODE_REPLY
|
||||||
0x06); //!> Command to read the current mode and reply with a REPLY_MODE_REPLY
|
static const Command_t CMD_MODE_READ = MAKE_COMMAND_ID(0x06);
|
||||||
static const Command_t CMD_MODE_ANNOUNCE = MAKE_COMMAND_ID(
|
//!> Command to trigger an ModeInfo Event. This command does NOT have a reply.
|
||||||
0x07); //!> Command to trigger an ModeInfo Event. This command does NOT have a reply.
|
static const Command_t CMD_MODE_ANNOUNCE = MAKE_COMMAND_ID(0x07);
|
||||||
static const Command_t CMD_MODE_ANNOUNCE_RECURSIVELY =
|
//!> Command to trigger an ModeInfo Event and to send this command to
|
||||||
MAKE_COMMAND_ID(0x08); //!> Command to trigger an ModeInfo Event and to send this command to
|
//! every child. This command does NOT have a reply.
|
||||||
//! every child. This command does NOT have a reply.
|
static const Command_t CMD_MODE_ANNOUNCE_RECURSIVELY = MAKE_COMMAND_ID(0x08);
|
||||||
|
|
||||||
|
ModeMessage() = delete;
|
||||||
|
|
||||||
static Mode_t getMode(const CommandMessage* message);
|
static Mode_t getMode(const CommandMessage* message);
|
||||||
static Submode_t getSubmode(const CommandMessage* message);
|
static Submode_t getSubmode(const CommandMessage* message);
|
||||||
@ -45,6 +44,9 @@ class ModeMessage {
|
|||||||
|
|
||||||
static void setModeMessage(CommandMessage* message, Command_t command, Mode_t mode,
|
static void setModeMessage(CommandMessage* message, Command_t command, Mode_t mode,
|
||||||
Submode_t submode);
|
Submode_t submode);
|
||||||
|
static void setCmdModeMessage(CommandMessage& message, Mode_t mode, Submode_t submode);
|
||||||
|
static void setModeAnnounceMessage(CommandMessage& message, bool recursive);
|
||||||
|
static void setModeReadMessage(CommandMessage& message);
|
||||||
static void setCantReachMode(CommandMessage* message, ReturnValue_t reason);
|
static void setCantReachMode(CommandMessage* message, ReturnValue_t reason);
|
||||||
static void clear(CommandMessage* message);
|
static void clear(CommandMessage* message);
|
||||||
};
|
};
|
||||||
|
@ -23,9 +23,17 @@ void ObjectManager::setObjectFactoryFunction(produce_function_t objFactoryFunc,
|
|||||||
|
|
||||||
ObjectManager::ObjectManager() = default;
|
ObjectManager::ObjectManager() = default;
|
||||||
|
|
||||||
|
void ObjectManager::clear() {
|
||||||
|
if (objManagerInstance != nullptr) {
|
||||||
|
delete objManagerInstance;
|
||||||
|
objManagerInstance = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ObjectManager::~ObjectManager() {
|
ObjectManager::~ObjectManager() {
|
||||||
for (auto const& iter : objectList) {
|
teardown = true;
|
||||||
delete iter.second;
|
for (auto iter = objectList.begin(); iter != objectList.end(); iter = objectList.erase(iter)) {
|
||||||
|
delete iter->second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,6 +61,12 @@ ReturnValue_t ObjectManager::insert(object_id_t id, SystemObjectIF* object) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t ObjectManager::remove(object_id_t id) {
|
ReturnValue_t ObjectManager::remove(object_id_t id) {
|
||||||
|
// this function is called during destruction of System Objects
|
||||||
|
// disabeld for teardown to avoid iterator invalidation and
|
||||||
|
// double free
|
||||||
|
if (teardown) {
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
if (this->getSystemObject(id) != nullptr) {
|
if (this->getSystemObject(id) != nullptr) {
|
||||||
this->objectList.erase(id);
|
this->objectList.erase(id);
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
@ -24,12 +24,17 @@ class ObjectManager : public ObjectManagerIF {
|
|||||||
using produce_function_t = void (*)(void* args);
|
using produce_function_t = void (*)(void* args);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the single instance of TaskFactory.
|
* Returns the single instance of ObjectManager.
|
||||||
* The implementation of #instance is found in its subclasses.
|
* The implementation of #instance is found in its subclasses.
|
||||||
* Thus, we choose link-time variability of the instance.
|
* Thus, we choose link-time variability of the instance.
|
||||||
*/
|
*/
|
||||||
static ObjectManager* instance();
|
static ObjectManager* instance();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes the single instance of ObjectManager
|
||||||
|
*/
|
||||||
|
static void clear();
|
||||||
|
|
||||||
void setObjectFactoryFunction(produce_function_t prodFunc, void* args);
|
void setObjectFactoryFunction(produce_function_t prodFunc, void* args);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -66,6 +71,9 @@ class ObjectManager : public ObjectManagerIF {
|
|||||||
*/
|
*/
|
||||||
std::map<object_id_t, SystemObjectIF*> objectList;
|
std::map<object_id_t, SystemObjectIF*> objectList;
|
||||||
static ObjectManager* objManagerInstance;
|
static ObjectManager* objManagerInstance;
|
||||||
|
// used when the OM itself is deleted to modify behaviour of remove()
|
||||||
|
// to avoid iterator invalidation and double free
|
||||||
|
bool teardown = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Documentation can be found in the class method declaration above
|
// Documentation can be found in the class method declaration above
|
||||||
|
@ -15,6 +15,7 @@ enum framework_objects : object_id_t {
|
|||||||
PUS_SERVICE_8_FUNCTION_MGMT = 0x53000008,
|
PUS_SERVICE_8_FUNCTION_MGMT = 0x53000008,
|
||||||
PUS_SERVICE_9_TIME_MGMT = 0x53000009,
|
PUS_SERVICE_9_TIME_MGMT = 0x53000009,
|
||||||
PUS_SERVICE_11_TC_SCHEDULER = 0x53000011,
|
PUS_SERVICE_11_TC_SCHEDULER = 0x53000011,
|
||||||
|
PUS_SERVICE_15_TM_STORAGE = 0x53000015,
|
||||||
PUS_SERVICE_17_TEST = 0x53000017,
|
PUS_SERVICE_17_TEST = 0x53000017,
|
||||||
PUS_SERVICE_20_PARAMETERS = 0x53000020,
|
PUS_SERVICE_20_PARAMETERS = 0x53000020,
|
||||||
PUS_SERVICE_200_MODE_MGMT = 0x53000200,
|
PUS_SERVICE_200_MODE_MGMT = 0x53000200,
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
# Check the OS_FSFW variable
|
# Check the OS_FSFW variable
|
||||||
if(FSFW_OSAL MATCHES "freertos")
|
if(FSFW_OSAL MATCHES "freertos")
|
||||||
add_subdirectory(freertos)
|
add_subdirectory(freertos)
|
||||||
|
set(FSFW_OSAL_FREERTOS 1)
|
||||||
elseif(FSFW_OSAL MATCHES "rtems")
|
elseif(FSFW_OSAL MATCHES "rtems")
|
||||||
add_subdirectory(rtems)
|
add_subdirectory(rtems)
|
||||||
|
set(FSFW_OSAL_RTEMS 1)
|
||||||
elseif(FSFW_OSAL MATCHES "linux")
|
elseif(FSFW_OSAL MATCHES "linux")
|
||||||
add_subdirectory(linux)
|
add_subdirectory(linux)
|
||||||
|
set(FSFW_OSAL_LINUX 1)
|
||||||
elseif(FSFW_OSAL MATCHES "host")
|
elseif(FSFW_OSAL MATCHES "host")
|
||||||
add_subdirectory(host)
|
add_subdirectory(host)
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
@ -13,18 +16,20 @@ elseif(FSFW_OSAL MATCHES "host")
|
|||||||
# We still need to pull in some Linux specific sources
|
# We still need to pull in some Linux specific sources
|
||||||
target_sources(${LIB_FSFW_NAME} PUBLIC linux/tcpipHelpers.cpp)
|
target_sources(${LIB_FSFW_NAME} PUBLIC linux/tcpipHelpers.cpp)
|
||||||
endif()
|
endif()
|
||||||
|
set(FSFW_OSAL_HOST 1)
|
||||||
else()
|
else()
|
||||||
|
|
||||||
message(
|
message(
|
||||||
WARNING
|
WARNING
|
||||||
"${MSG_PREFIX} The FSFW_OSAL variable was not set. Assuming host OS..")
|
"${MSG_PREFIX} The FSFW_OSAL variable was not set. Assuming host OS..")
|
||||||
|
|
||||||
# Not set. Assumuing this is a host build, try to determine host OS
|
# Not set. Assumuing this is a host build, try to determine host OS
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
add_subdirectory(host)
|
add_subdirectory(host)
|
||||||
add_subdirectory(windows)
|
add_subdirectory(windows)
|
||||||
|
set(FSFW_OSAL_HOST 1)
|
||||||
elseif(UNIX)
|
elseif(UNIX)
|
||||||
add_subdirectory(linux)
|
add_subdirectory(linux)
|
||||||
|
set(FSFW_OSAL_LINUX 1)
|
||||||
else()
|
else()
|
||||||
# MacOS or other OSes have not been tested yet / are not supported.
|
# MacOS or other OSes have not been tested yet / are not supported.
|
||||||
message(FATAL_ERROR "The host OS could not be determined! Aborting.")
|
message(FATAL_ERROR "The host OS could not be determined! Aborting.")
|
||||||
@ -33,3 +38,5 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_subdirectory(common)
|
add_subdirectory(common)
|
||||||
|
|
||||||
|
configure_file(osal.h.in ${CMAKE_BINARY_DIR}/fsfw/osal/osal.h)
|
||||||
|
@ -41,6 +41,7 @@ int TcpIpBase::closeSocket(socket_t socket) {
|
|||||||
#elif defined(PLATFORM_UNIX)
|
#elif defined(PLATFORM_UNIX)
|
||||||
return close(socket);
|
return close(socket);
|
||||||
#endif
|
#endif
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int TcpIpBase::getLastSocketError() {
|
int TcpIpBase::getLastSocketError() {
|
||||||
@ -49,4 +50,5 @@ int TcpIpBase::getLastSocketError() {
|
|||||||
#elif defined(PLATFORM_UNIX)
|
#elif defined(PLATFORM_UNIX)
|
||||||
return errno;
|
return errno;
|
||||||
#endif
|
#endif
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -16,9 +16,9 @@
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TcpTmTcBridge::TcpTmTcBridge(object_id_t objectId, object_id_t tcDestination, object_id_t tmStoreId,
|
TcpTmTcBridge::TcpTmTcBridge(object_id_t objectId, object_id_t tcDestination,
|
||||||
object_id_t tcStoreId)
|
uint32_t msgQueueDepth, object_id_t tmStoreId, object_id_t tcStoreId)
|
||||||
: TmTcBridge("TCP TMTC Bridge", objectId, tcDestination, tmStoreId, tcStoreId) {
|
: TmTcBridge("TCP TMTC Bridge", objectId, tcDestination, msgQueueDepth, tmStoreId, tcStoreId) {
|
||||||
mutex = MutexFactory::instance()->createMutex();
|
mutex = MutexFactory::instance()->createMutex();
|
||||||
// Connection is always up, TM is requested by connecting to server and receiving packets
|
// Connection is always up, TM is requested by connecting to server and receiving packets
|
||||||
registerCommConnect();
|
registerCommConnect();
|
||||||
|
@ -38,7 +38,7 @@ class TcpTmTcBridge : public TmTcBridge {
|
|||||||
* @param tmStoreId TM store object ID. It is recommended to the default object ID
|
* @param tmStoreId TM store object ID. It is recommended to the default object ID
|
||||||
* @param tcStoreId TC store object ID. It is recommended to the default object ID
|
* @param tcStoreId TC store object ID. It is recommended to the default object ID
|
||||||
*/
|
*/
|
||||||
TcpTmTcBridge(object_id_t objectId, object_id_t tcDestination,
|
TcpTmTcBridge(object_id_t objectId, object_id_t tcDestination, uint32_t msgQueueDepth,
|
||||||
object_id_t tmStoreId = objects::TM_STORE,
|
object_id_t tmStoreId = objects::TM_STORE,
|
||||||
object_id_t tcStoreId = objects::TC_STORE);
|
object_id_t tcStoreId = objects::TC_STORE);
|
||||||
virtual ~TcpTmTcBridge();
|
virtual ~TcpTmTcBridge();
|
||||||
|
@ -26,12 +26,12 @@
|
|||||||
const std::string TcpTmTcServer::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT;
|
const std::string TcpTmTcServer::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT;
|
||||||
|
|
||||||
TcpTmTcServer::TcpTmTcServer(object_id_t objectId, object_id_t tmtcTcpBridge,
|
TcpTmTcServer::TcpTmTcServer(object_id_t objectId, object_id_t tmtcTcpBridge,
|
||||||
size_t receptionBufferSize, size_t ringBufferSize,
|
TcpTmTcServer::TcpConfig cfg, size_t receptionBufferSize,
|
||||||
std::string customTcpServerPort, ReceptionModes receptionMode)
|
size_t ringBufferSize, ReceptionModes receptionMode)
|
||||||
: SystemObject(objectId),
|
: SystemObject(objectId),
|
||||||
tmtcBridgeId(tmtcTcpBridge),
|
tmtcBridgeId(tmtcTcpBridge),
|
||||||
receptionMode(receptionMode),
|
receptionMode(receptionMode),
|
||||||
tcpConfig(std::move(customTcpServerPort)),
|
tcpConfig(cfg),
|
||||||
receptionBuffer(receptionBufferSize),
|
receptionBuffer(receptionBufferSize),
|
||||||
ringBuffer(ringBufferSize, true) {}
|
ringBuffer(ringBufferSize, true) {}
|
||||||
|
|
||||||
@ -91,6 +91,15 @@ ReturnValue_t TcpTmTcServer::initialize() {
|
|||||||
return returnvalue::FAILED;
|
return returnvalue::FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tcpConfig.reuseAddr) {
|
||||||
|
unsigned int enable = 1;
|
||||||
|
setsockopt(listenerTcpSocket, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable));
|
||||||
|
}
|
||||||
|
if (tcpConfig.reusePort) {
|
||||||
|
unsigned int enable = 1;
|
||||||
|
setsockopt(listenerTcpSocket, SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(enable));
|
||||||
|
}
|
||||||
|
|
||||||
// Bind to the address found by getaddrinfo
|
// Bind to the address found by getaddrinfo
|
||||||
retval = bind(listenerTcpSocket, addrResult->ai_addr, static_cast<int>(addrResult->ai_addrlen));
|
retval = bind(listenerTcpSocket, addrResult->ai_addr, static_cast<int>(addrResult->ai_addrlen));
|
||||||
if (retval == SOCKET_ERROR) {
|
if (retval == SOCKET_ERROR) {
|
||||||
@ -274,6 +283,8 @@ ReturnValue_t TcpTmTcServer::handleTmSending(socket_t connSocket, bool& tmSent)
|
|||||||
ConstStorageAccessor storeAccessor(storeId);
|
ConstStorageAccessor storeAccessor(storeId);
|
||||||
ReturnValue_t result = tmStore->getData(storeId, storeAccessor);
|
ReturnValue_t result = tmStore->getData(storeId, storeAccessor);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
|
// Invalid entry, pop FIFO
|
||||||
|
tmtcBridge->tmFifo->pop();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
if (wiretappingEnabled) {
|
if (wiretappingEnabled) {
|
||||||
|
@ -41,11 +41,11 @@ class SpacePacketParser;
|
|||||||
*/
|
*/
|
||||||
class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableObjectIF {
|
class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableObjectIF {
|
||||||
public:
|
public:
|
||||||
enum class ReceptionModes { SPACE_PACKETS };
|
|
||||||
|
|
||||||
struct TcpConfig {
|
struct TcpConfig {
|
||||||
public:
|
public:
|
||||||
explicit TcpConfig(std::string tcpPort) : tcpPort(std::move(tcpPort)) {}
|
TcpConfig(bool reuseAddr, bool reusePort) : reuseAddr(reuseAddr), reusePort(reusePort) {}
|
||||||
|
TcpConfig(std::string tcpPort, bool reuseAddr, bool reusePort)
|
||||||
|
: tcpPort(std::move(tcpPort)), reuseAddr(reuseAddr), reusePort(reusePort) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Passed to the recv call
|
* Passed to the recv call
|
||||||
@ -63,9 +63,25 @@ class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableOb
|
|||||||
*/
|
*/
|
||||||
int tcpTmFlags = 0;
|
int tcpTmFlags = 0;
|
||||||
|
|
||||||
const std::string tcpPort;
|
std::string tcpPort = DEFAULT_SERVER_PORT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the SO_REUSEADDR option on the socket. See
|
||||||
|
* https://man7.org/linux/man-pages/man7/socket.7.html for more details. This option is
|
||||||
|
* especially useful in a debugging and development environment where an OBSW image might be
|
||||||
|
* re-flashed oftentimes and where all incoming telecommands are received on a dedicated TCP
|
||||||
|
* port.
|
||||||
|
*/
|
||||||
|
bool reuseAddr = false;
|
||||||
|
/**
|
||||||
|
* Sets the SO_REUSEPORT option on the socket. See
|
||||||
|
* https://man7.org/linux/man-pages/man7/socket.7.html for more details.
|
||||||
|
*/
|
||||||
|
bool reusePort = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class ReceptionModes { SPACE_PACKETS };
|
||||||
|
|
||||||
static const std::string DEFAULT_SERVER_PORT;
|
static const std::string DEFAULT_SERVER_PORT;
|
||||||
|
|
||||||
static constexpr size_t ETHERNET_MTU_SIZE = 1500;
|
static constexpr size_t ETHERNET_MTU_SIZE = 1500;
|
||||||
@ -80,10 +96,9 @@ class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableOb
|
|||||||
* size will be the Ethernet MTU size
|
* size will be the Ethernet MTU size
|
||||||
* @param customTcpServerPort The user can specify another port than the default (7301) here.
|
* @param customTcpServerPort The user can specify another port than the default (7301) here.
|
||||||
*/
|
*/
|
||||||
TcpTmTcServer(object_id_t objectId, object_id_t tmtcTcpBridge,
|
TcpTmTcServer(object_id_t objectId, object_id_t tmtcTcpBridge, TcpTmTcServer::TcpConfig cfg,
|
||||||
size_t receptionBufferSize = RING_BUFFER_SIZE,
|
size_t receptionBufferSize = RING_BUFFER_SIZE,
|
||||||
size_t ringBufferSize = RING_BUFFER_SIZE,
|
size_t ringBufferSize = RING_BUFFER_SIZE,
|
||||||
std::string customTcpServerPort = DEFAULT_SERVER_PORT,
|
|
||||||
ReceptionModes receptionMode = ReceptionModes::SPACE_PACKETS);
|
ReceptionModes receptionMode = ReceptionModes::SPACE_PACKETS);
|
||||||
~TcpTmTcServer() override;
|
~TcpTmTcServer() override;
|
||||||
|
|
||||||
|
@ -20,9 +20,9 @@
|
|||||||
const std::string UdpTmTcBridge::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT;
|
const std::string UdpTmTcBridge::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT;
|
||||||
|
|
||||||
UdpTmTcBridge::UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination,
|
UdpTmTcBridge::UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination,
|
||||||
const std::string &udpServerPort_, object_id_t tmStoreId,
|
uint32_t msgQueueDepth, const std::string &udpServerPort_,
|
||||||
object_id_t tcStoreId)
|
object_id_t tmStoreId, object_id_t tcStoreId)
|
||||||
: TmTcBridge("UDP TMTC Bridge", objectId, tcDestination, tmStoreId, tcStoreId) {
|
: TmTcBridge("UDP TMTC Bridge", objectId, tcDestination, msgQueueDepth, tmStoreId, tcStoreId) {
|
||||||
if (udpServerPort_.empty()) {
|
if (udpServerPort_.empty()) {
|
||||||
udpServerPort = DEFAULT_SERVER_PORT;
|
udpServerPort = DEFAULT_SERVER_PORT;
|
||||||
} else {
|
} else {
|
||||||
@ -126,10 +126,7 @@ ReturnValue_t UdpTmTcBridge::sendTm(const uint8_t *data, size_t dataLen) {
|
|||||||
tcpip::handleError(tcpip::Protocol::UDP, tcpip::ErrorSources::SENDTO_CALL);
|
tcpip::handleError(tcpip::Protocol::UDP, tcpip::ErrorSources::SENDTO_CALL);
|
||||||
}
|
}
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_SEND_WIRETAPPING_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_SEND_WIRETAPPING_ENABLED == 1
|
||||||
sif::debug << "TmTcUdpBridge::sendTm: " << bytesSent
|
sif::debug << "TmTcUdpBridge::sendTm: " << bytesSent << " bytes were sent" << std::endl;
|
||||||
<< " bytes were"
|
|
||||||
" sent."
|
|
||||||
<< std::endl;
|
|
||||||
#endif
|
#endif
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ class UdpTmTcBridge : public TmTcBridge, public TcpIpBase {
|
|||||||
/* The ports chosen here should not be used by any other process. */
|
/* The ports chosen here should not be used by any other process. */
|
||||||
static const std::string DEFAULT_SERVER_PORT;
|
static const std::string DEFAULT_SERVER_PORT;
|
||||||
|
|
||||||
UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination,
|
UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination, uint32_t msgQueueDepth,
|
||||||
const std::string& udpServerPort = "", object_id_t tmStoreId = objects::TM_STORE,
|
const std::string& udpServerPort = "", object_id_t tmStoreId = objects::TM_STORE,
|
||||||
object_id_t tcStoreId = objects::TC_STORE);
|
object_id_t tcStoreId = objects::TC_STORE);
|
||||||
~UdpTmTcBridge() override;
|
~UdpTmTcBridge() override;
|
||||||
|
@ -47,7 +47,32 @@ ReturnValue_t Clock::setClock(const timeval* time) {
|
|||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t Clock::getClock_timeval(timeval* time) {
|
ReturnValue_t Clock::getClockMonotonic(timeval* time) {
|
||||||
|
#if defined(PLATFORM_WIN)
|
||||||
|
// TODO: Implement with std::chrono::steady_clock.. or in some other way. I am not even sure
|
||||||
|
// whether this is possible with steady_clock. The conversion we have to do here just to be
|
||||||
|
// generic is kind of awkward..
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
#elif defined(PLATFORM_UNIX)
|
||||||
|
timespec timeMonotonic;
|
||||||
|
int status = clock_gettime(CLOCK_MONOTONIC_RAW, &timeMonotonic);
|
||||||
|
if (status != 0) {
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
time->tv_sec = timeMonotonic.tv_sec;
|
||||||
|
time->tv_usec = timeMonotonic.tv_nsec / 1000.0;
|
||||||
|
return returnvalue::OK;
|
||||||
|
#else
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::warning << "Clock::getUptime: Not implemented for found OS!" << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printWarning("Clock::getUptime: Not implemented for found OS!\n");
|
||||||
|
#endif
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Clock::getClock(timeval* time) {
|
||||||
#if defined(PLATFORM_WIN)
|
#if defined(PLATFORM_WIN)
|
||||||
auto now = std::chrono::system_clock::now();
|
auto now = std::chrono::system_clock::now();
|
||||||
auto secondsChrono = std::chrono::time_point_cast<std::chrono::seconds>(now);
|
auto secondsChrono = std::chrono::time_point_cast<std::chrono::seconds>(now);
|
||||||
@ -75,6 +100,8 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Clock::getClock_timeval(timeval* time) { return Clock::getClock(time); }
|
||||||
|
|
||||||
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
|
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
|
||||||
if (time == nullptr) {
|
if (time == nullptr) {
|
||||||
return returnvalue::FAILED;
|
return returnvalue::FAILED;
|
||||||
|
@ -42,7 +42,7 @@ ReturnValue_t Clock::setClock(const timeval* time) {
|
|||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t Clock::getClock_timeval(timeval* time) {
|
ReturnValue_t Clock::getClock(timeval* time) {
|
||||||
timespec timeUnix{};
|
timespec timeUnix{};
|
||||||
int status = clock_gettime(CLOCK_REALTIME, &timeUnix);
|
int status = clock_gettime(CLOCK_REALTIME, &timeUnix);
|
||||||
if (status != 0) {
|
if (status != 0) {
|
||||||
@ -53,6 +53,8 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
|
|||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Clock::getClock_timeval(timeval* time) { return Clock::getClock(time); }
|
||||||
|
|
||||||
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
|
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
|
||||||
timeval timeVal{};
|
timeval timeVal{};
|
||||||
ReturnValue_t result = getClock_timeval(&timeVal);
|
ReturnValue_t result = getClock_timeval(&timeVal);
|
||||||
@ -64,6 +66,17 @@ ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
|
|||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Clock::getClockMonotonic(timeval* time) {
|
||||||
|
timespec timeMonotonic{};
|
||||||
|
int status = clock_gettime(CLOCK_MONOTONIC_RAW, &timeMonotonic);
|
||||||
|
if (status != 0) {
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
time->tv_sec = timeMonotonic.tv_sec;
|
||||||
|
time->tv_usec = timeMonotonic.tv_nsec / 1000.0;
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
|
||||||
timeval Clock::getUptime() {
|
timeval Clock::getUptime() {
|
||||||
timeval uptime{};
|
timeval uptime{};
|
||||||
auto result = getUptime(&uptime);
|
auto result = getUptime(&uptime);
|
||||||
@ -79,11 +92,16 @@ ReturnValue_t Clock::getUptime(timeval* uptime) {
|
|||||||
// TODO This is not posix compatible and delivers only seconds precision
|
// TODO This is not posix compatible and delivers only seconds precision
|
||||||
// Linux specific file read but more precise.
|
// Linux specific file read but more precise.
|
||||||
double uptimeSeconds;
|
double uptimeSeconds;
|
||||||
if (std::ifstream("/proc/uptime", std::ios::in) >> uptimeSeconds) {
|
std::ifstream ifile("/proc/uptime");
|
||||||
|
if (ifile.bad()) {
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
if (ifile >> uptimeSeconds) {
|
||||||
uptime->tv_sec = uptimeSeconds;
|
uptime->tv_sec = uptimeSeconds;
|
||||||
uptime->tv_usec = uptimeSeconds * (double)1e6 - (uptime->tv_sec * 1e6);
|
uptime->tv_usec = uptimeSeconds * (double)1e6 - (uptime->tv_sec * 1e6);
|
||||||
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
return returnvalue::OK;
|
return returnvalue::FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for new FSFW Clock function delivering seconds uptime.
|
// Wait for new FSFW Clock function delivering seconds uptime.
|
||||||
|
@ -21,7 +21,7 @@ MessageQueue::MessageQueue(uint32_t messageDepth, size_t maxMessageSize, MqArgs*
|
|||||||
attributes.mq_msgsize = maxMessageSize;
|
attributes.mq_msgsize = maxMessageSize;
|
||||||
attributes.mq_flags = 0; // Flags are ignored on Linux during mq_open
|
attributes.mq_flags = 0; // Flags are ignored on Linux during mq_open
|
||||||
// Set the name of the queue. The slash is mandatory!
|
// Set the name of the queue. The slash is mandatory!
|
||||||
sprintf(name, "/FSFW_MQ%u\n", queueCounter++);
|
sprintf(name, "/FSFW_MQ%u", queueCounter++);
|
||||||
|
|
||||||
// Create a nonblocking queue if the name is available (the queue is read
|
// Create a nonblocking queue if the name is available (the queue is read
|
||||||
// and writable for the owner as well as the group)
|
// and writable for the owner as well as the group)
|
||||||
|
36
src/fsfw/osal/osal.h.in
Normal file
36
src/fsfw/osal/osal.h.in
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace osal {
|
||||||
|
enum osalTarget{
|
||||||
|
HOST,
|
||||||
|
LINUX,
|
||||||
|
WINDOWS,
|
||||||
|
FREERTOS,
|
||||||
|
RTEMS,
|
||||||
|
};
|
||||||
|
|
||||||
|
#cmakedefine FSFW_OSAL_HOST
|
||||||
|
#cmakedefine FSFW_OSAL_LINUX
|
||||||
|
#cmakedefine FSFW_OSAL_WINDOWS
|
||||||
|
#cmakedefine FSFW_OSAL_FREERTOS
|
||||||
|
#cmakedefine FSFW_OSAL_RTEMS
|
||||||
|
|
||||||
|
|
||||||
|
constexpr osalTarget getTarget() {
|
||||||
|
#ifdef FSFW_OSAL_HOST
|
||||||
|
return HOST;
|
||||||
|
#endif
|
||||||
|
#ifdef FSFW_OSAL_LINUX
|
||||||
|
return LINUX;
|
||||||
|
#endif
|
||||||
|
#ifdef FSFW_OSAL_WINDOWS
|
||||||
|
return WINDOWS;
|
||||||
|
#endif
|
||||||
|
#ifdef FSFW_OSAL_FREERTOS
|
||||||
|
return FREERTOS;
|
||||||
|
#endif
|
||||||
|
#ifdef FSFW_OSAL_RTEMS
|
||||||
|
return RTEMS;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
};
|
@ -1,5 +1,7 @@
|
|||||||
#include "DummyPowerSwitcher.h"
|
#include "DummyPowerSwitcher.h"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
DummyPowerSwitcher::DummyPowerSwitcher(object_id_t objectId, size_t numberOfSwitches,
|
DummyPowerSwitcher::DummyPowerSwitcher(object_id_t objectId, size_t numberOfSwitches,
|
||||||
size_t numberOfFuses, bool registerGlobally,
|
size_t numberOfFuses, bool registerGlobally,
|
||||||
uint32_t switchDelayMs)
|
uint32_t switchDelayMs)
|
||||||
@ -9,11 +11,11 @@ DummyPowerSwitcher::DummyPowerSwitcher(object_id_t objectId, size_t numberOfSwit
|
|||||||
switchDelayMs(switchDelayMs) {}
|
switchDelayMs(switchDelayMs) {}
|
||||||
|
|
||||||
void DummyPowerSwitcher::setInitialSwitcherList(std::vector<ReturnValue_t> switcherList) {
|
void DummyPowerSwitcher::setInitialSwitcherList(std::vector<ReturnValue_t> switcherList) {
|
||||||
this->switcherList = switcherList;
|
this->switcherList = std::move(switcherList);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DummyPowerSwitcher::setInitialFusesList(std::vector<ReturnValue_t> fuseList) {
|
void DummyPowerSwitcher::setInitialFusesList(std::vector<ReturnValue_t> fuseList) {
|
||||||
this->fuseList = fuseList;
|
this->fuseList = std::move(fuseList);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t DummyPowerSwitcher::sendSwitchCommand(power::Switch_t switchNr, ReturnValue_t onOff) {
|
ReturnValue_t DummyPowerSwitcher::sendSwitchCommand(power::Switch_t switchNr, ReturnValue_t onOff) {
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#include <fsfw/ipc/QueueFactory.h>
|
#include <fsfw/ipc/QueueFactory.h>
|
||||||
#include <fsfw/power/PowerSwitchIF.h>
|
#include <fsfw/power/PowerSwitchIF.h>
|
||||||
|
|
||||||
PowerSwitcherComponent::PowerSwitcherComponent(object_id_t objectId, PowerSwitchIF *pwrSwitcher,
|
PowerSwitcherComponent::PowerSwitcherComponent(object_id_t objectId, PowerSwitchIF* pwrSwitcher,
|
||||||
power::Switch_t pwrSwitch)
|
power::Switch_t pwrSwitch)
|
||||||
: SystemObject(objectId),
|
: SystemObject(objectId),
|
||||||
switcher(pwrSwitcher, pwrSwitch),
|
switcher(pwrSwitcher, pwrSwitch),
|
||||||
@ -54,7 +54,7 @@ ReturnValue_t PowerSwitcherComponent::initialize() {
|
|||||||
|
|
||||||
MessageQueueId_t PowerSwitcherComponent::getCommandQueue() const { return queue->getId(); }
|
MessageQueueId_t PowerSwitcherComponent::getCommandQueue() const { return queue->getId(); }
|
||||||
|
|
||||||
void PowerSwitcherComponent::getMode(Mode_t *mode, Submode_t *submode) {
|
void PowerSwitcherComponent::getMode(Mode_t* mode, Submode_t* submode) {
|
||||||
*mode = this->mode;
|
*mode = this->mode;
|
||||||
*submode = this->submode;
|
*submode = this->submode;
|
||||||
}
|
}
|
||||||
@ -65,7 +65,7 @@ ReturnValue_t PowerSwitcherComponent::setHealth(HealthState health) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t PowerSwitcherComponent::checkModeCommand(Mode_t mode, Submode_t submode,
|
ReturnValue_t PowerSwitcherComponent::checkModeCommand(Mode_t mode, Submode_t submode,
|
||||||
uint32_t *msToReachTheMode) {
|
uint32_t* msToReachTheMode) {
|
||||||
*msToReachTheMode = 5000;
|
*msToReachTheMode = 5000;
|
||||||
if (mode != MODE_ON and mode != MODE_OFF) {
|
if (mode != MODE_ON and mode != MODE_OFF) {
|
||||||
return TRANS_NOT_ALLOWED;
|
return TRANS_NOT_ALLOWED;
|
||||||
@ -105,3 +105,15 @@ void PowerSwitcherComponent::setMode(Mode_t newMode, Submode_t newSubmode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
HasHealthIF::HealthState PowerSwitcherComponent::getHealth() { return healthHelper.getHealth(); }
|
HasHealthIF::HealthState PowerSwitcherComponent::getHealth() { return healthHelper.getHealth(); }
|
||||||
|
|
||||||
|
const HasHealthIF* PowerSwitcherComponent::getOptHealthIF() const { return this; }
|
||||||
|
|
||||||
|
const HasModesIF& PowerSwitcherComponent::getModeIF() const { return *this; }
|
||||||
|
|
||||||
|
ReturnValue_t PowerSwitcherComponent::connectModeTreeParent(HasModeTreeChildrenIF& parent) {
|
||||||
|
return parent.registerChild(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
object_id_t PowerSwitcherComponent::getObjectId() const { return SystemObject::getObjectId(); }
|
||||||
|
|
||||||
|
ModeTreeChildIF& PowerSwitcherComponent::getModeTreeChildIF() { return *this; }
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
#include <fsfw/objectmanager/SystemObject.h>
|
#include <fsfw/objectmanager/SystemObject.h>
|
||||||
#include <fsfw/power/PowerSwitcher.h>
|
#include <fsfw/power/PowerSwitcher.h>
|
||||||
#include <fsfw/power/definitions.h>
|
#include <fsfw/power/definitions.h>
|
||||||
|
#include <fsfw/subsystem/ModeTreeChildIF.h>
|
||||||
|
#include <fsfw/subsystem/ModeTreeConnectionIF.h>
|
||||||
#include <fsfw/tasks/ExecutableObjectIF.h>
|
#include <fsfw/tasks/ExecutableObjectIF.h>
|
||||||
|
|
||||||
class PowerSwitchIF;
|
class PowerSwitchIF;
|
||||||
@ -24,12 +26,17 @@ class PowerSwitchIF;
|
|||||||
*/
|
*/
|
||||||
class PowerSwitcherComponent : public SystemObject,
|
class PowerSwitcherComponent : public SystemObject,
|
||||||
public ExecutableObjectIF,
|
public ExecutableObjectIF,
|
||||||
|
public ModeTreeChildIF,
|
||||||
|
public ModeTreeConnectionIF,
|
||||||
public HasModesIF,
|
public HasModesIF,
|
||||||
public HasHealthIF {
|
public HasHealthIF {
|
||||||
public:
|
public:
|
||||||
PowerSwitcherComponent(object_id_t objectId, PowerSwitchIF *pwrSwitcher,
|
PowerSwitcherComponent(object_id_t objectId, PowerSwitchIF *pwrSwitcher,
|
||||||
power::Switch_t pwrSwitch);
|
power::Switch_t pwrSwitch);
|
||||||
|
|
||||||
|
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF &parent) override;
|
||||||
|
ModeTreeChildIF &getModeTreeChildIF() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MessageQueueIF *queue = nullptr;
|
MessageQueueIF *queue = nullptr;
|
||||||
PowerSwitcher switcher;
|
PowerSwitcher switcher;
|
||||||
@ -56,6 +63,10 @@ class PowerSwitcherComponent : public SystemObject,
|
|||||||
|
|
||||||
ReturnValue_t setHealth(HealthState health) override;
|
ReturnValue_t setHealth(HealthState health) override;
|
||||||
HasHealthIF::HealthState getHealth() override;
|
HasHealthIF::HealthState getHealth() override;
|
||||||
|
|
||||||
|
object_id_t getObjectId() const override;
|
||||||
|
const HasHealthIF *getOptHealthIF() const override;
|
||||||
|
const HasModesIF &getModeIF() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _FSFW_POWER_POWERSWITCHERCOMPONENT_H_ */
|
#endif /* _FSFW_POWER_POWERSWITCHERCOMPONENT_H_ */
|
||||||
|
@ -9,4 +9,4 @@ target_sources(
|
|||||||
Service17Test.cpp
|
Service17Test.cpp
|
||||||
Service20ParameterManagement.cpp
|
Service20ParameterManagement.cpp
|
||||||
CService200ModeCommanding.cpp
|
CService200ModeCommanding.cpp
|
||||||
CService201HealthCommanding.cpp)
|
CServiceHealthCommanding.cpp)
|
||||||
|
@ -19,7 +19,8 @@ ReturnValue_t CService200ModeCommanding::isValidSubservice(uint8_t subservice) {
|
|||||||
switch (subservice) {
|
switch (subservice) {
|
||||||
case (Subservice::COMMAND_MODE_COMMAND):
|
case (Subservice::COMMAND_MODE_COMMAND):
|
||||||
case (Subservice::COMMAND_MODE_READ):
|
case (Subservice::COMMAND_MODE_READ):
|
||||||
case (Subservice::COMMAND_MODE_ANNCOUNCE):
|
case (Subservice::COMMAND_MODE_ANNOUNCE):
|
||||||
|
case (Subservice::COMMAND_MODE_ANNOUNCE_RECURSIVELY):
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
default:
|
default:
|
||||||
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
|
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
|
||||||
@ -53,16 +54,32 @@ ReturnValue_t CService200ModeCommanding::checkInterfaceAndAcquireMessageQueue(
|
|||||||
ReturnValue_t CService200ModeCommanding::prepareCommand(CommandMessage *message, uint8_t subservice,
|
ReturnValue_t CService200ModeCommanding::prepareCommand(CommandMessage *message, uint8_t subservice,
|
||||||
const uint8_t *tcData, size_t tcDataLen,
|
const uint8_t *tcData, size_t tcDataLen,
|
||||||
uint32_t *state, object_id_t objectId) {
|
uint32_t *state, object_id_t objectId) {
|
||||||
ModePacket modeCommandPacket;
|
bool recursive = false;
|
||||||
ReturnValue_t result =
|
switch (subservice) {
|
||||||
modeCommandPacket.deSerialize(&tcData, &tcDataLen, SerializeIF::Endianness::BIG);
|
case (Subservice::COMMAND_MODE_COMMAND): {
|
||||||
if (result != returnvalue::OK) {
|
ModePacket modeCommandPacket;
|
||||||
return result;
|
ReturnValue_t result =
|
||||||
}
|
modeCommandPacket.deSerialize(&tcData, &tcDataLen, SerializeIF::Endianness::BIG);
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
ModeMessage::setModeMessage(message, ModeMessage::CMD_MODE_COMMAND, modeCommandPacket.getMode(),
|
ModeMessage::setModeMessage(message, ModeMessage::CMD_MODE_COMMAND,
|
||||||
modeCommandPacket.getSubmode());
|
modeCommandPacket.getMode(), modeCommandPacket.getSubmode());
|
||||||
return result;
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
case (Subservice::COMMAND_MODE_ANNOUNCE_RECURSIVELY):
|
||||||
|
recursive = true;
|
||||||
|
[[fallthrough]];
|
||||||
|
case (Subservice::COMMAND_MODE_ANNOUNCE):
|
||||||
|
ModeMessage::setModeAnnounceMessage(*message, recursive);
|
||||||
|
return EXECUTION_COMPLETE;
|
||||||
|
case (Subservice::COMMAND_MODE_READ):
|
||||||
|
ModeMessage::setModeReadMessage(*message);
|
||||||
|
return returnvalue::OK;
|
||||||
|
default:
|
||||||
|
return CommandingServiceBase::INVALID_SUBSERVICE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t CService200ModeCommanding::handleReply(const CommandMessage *reply,
|
ReturnValue_t CService200ModeCommanding::handleReply(const CommandMessage *reply,
|
||||||
@ -73,8 +90,10 @@ ReturnValue_t CService200ModeCommanding::handleReply(const CommandMessage *reply
|
|||||||
ReturnValue_t result = returnvalue::FAILED;
|
ReturnValue_t result = returnvalue::FAILED;
|
||||||
switch (replyId) {
|
switch (replyId) {
|
||||||
case (ModeMessage::REPLY_MODE_REPLY): {
|
case (ModeMessage::REPLY_MODE_REPLY): {
|
||||||
result = prepareModeReply(reply, objectId);
|
if (previousCommand != ModeMessage::CMD_MODE_COMMAND) {
|
||||||
break;
|
return prepareModeReply(reply, objectId);
|
||||||
|
}
|
||||||
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
case (ModeMessage::REPLY_WRONG_MODE_REPLY): {
|
case (ModeMessage::REPLY_WRONG_MODE_REPLY): {
|
||||||
result = prepareWrongModeReply(reply, objectId);
|
result = prepareWrongModeReply(reply, objectId);
|
||||||
|
@ -52,7 +52,7 @@ class CService200ModeCommanding : public CommandingServiceBase {
|
|||||||
COMMAND_MODE_READ = 3,
|
COMMAND_MODE_READ = 3,
|
||||||
//!< [EXPORT] : [COMMAND] Trigger an ModeInfo Event.
|
//!< [EXPORT] : [COMMAND] Trigger an ModeInfo Event.
|
||||||
//! This command does NOT have a reply
|
//! This command does NOT have a reply
|
||||||
COMMAND_MODE_ANNCOUNCE = 4,
|
COMMAND_MODE_ANNOUNCE = 4,
|
||||||
//!< [EXPORT] : [COMMAND] Trigger a ModeInfo Event and to send this
|
//!< [EXPORT] : [COMMAND] Trigger a ModeInfo Event and to send this
|
||||||
//! command to every child. This command does NOT have a reply.
|
//! command to every child. This command does NOT have a reply.
|
||||||
COMMAND_MODE_ANNOUNCE_RECURSIVELY = 5,
|
COMMAND_MODE_ANNOUNCE_RECURSIVELY = 5,
|
||||||
|
@ -1,106 +0,0 @@
|
|||||||
#include "fsfw/pus/CService201HealthCommanding.h"
|
|
||||||
|
|
||||||
#include "fsfw/health/HasHealthIF.h"
|
|
||||||
#include "fsfw/health/HealthMessage.h"
|
|
||||||
#include "fsfw/objectmanager/ObjectManager.h"
|
|
||||||
#include "fsfw/pus/servicepackets/Service201Packets.h"
|
|
||||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
|
||||||
|
|
||||||
CService201HealthCommanding::CService201HealthCommanding(object_id_t objectId, uint16_t apid,
|
|
||||||
uint8_t serviceId,
|
|
||||||
uint8_t numParallelCommands,
|
|
||||||
uint16_t commandTimeoutSeconds)
|
|
||||||
: CommandingServiceBase(objectId, apid, "PUS 201 Health MGMT", serviceId, numParallelCommands,
|
|
||||||
commandTimeoutSeconds) {}
|
|
||||||
|
|
||||||
ReturnValue_t CService201HealthCommanding::isValidSubservice(uint8_t subservice) {
|
|
||||||
switch (subservice) {
|
|
||||||
case (Subservice::COMMAND_SET_HEALTH):
|
|
||||||
case (Subservice::COMMAND_ANNOUNCE_HEALTH):
|
|
||||||
case (Subservice::COMMAND_ANNOUNCE_HEALTH_ALL):
|
|
||||||
return returnvalue::OK;
|
|
||||||
default:
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::error << "Invalid Subservice" << std::endl;
|
|
||||||
#endif
|
|
||||||
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t CService201HealthCommanding::getMessageQueueAndObject(uint8_t subservice,
|
|
||||||
const uint8_t *tcData,
|
|
||||||
size_t tcDataLen,
|
|
||||||
MessageQueueId_t *id,
|
|
||||||
object_id_t *objectId) {
|
|
||||||
if (tcDataLen < sizeof(object_id_t)) {
|
|
||||||
return CommandingServiceBase::INVALID_TC;
|
|
||||||
}
|
|
||||||
SerializeAdapter::deSerialize(objectId, &tcData, &tcDataLen, SerializeIF::Endianness::BIG);
|
|
||||||
|
|
||||||
return checkInterfaceAndAcquireMessageQueue(id, objectId);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t CService201HealthCommanding::checkInterfaceAndAcquireMessageQueue(
|
|
||||||
MessageQueueId_t *messageQueueToSet, const object_id_t *objectId) {
|
|
||||||
auto *destination = ObjectManager::instance()->get<HasHealthIF>(*objectId);
|
|
||||||
if (destination == nullptr) {
|
|
||||||
return CommandingServiceBase::INVALID_OBJECT;
|
|
||||||
}
|
|
||||||
|
|
||||||
*messageQueueToSet = destination->getCommandQueue();
|
|
||||||
return returnvalue::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t CService201HealthCommanding::prepareCommand(CommandMessage *message,
|
|
||||||
uint8_t subservice, const uint8_t *tcData,
|
|
||||||
size_t tcDataLen, uint32_t *state,
|
|
||||||
object_id_t objectId) {
|
|
||||||
ReturnValue_t result = returnvalue::OK;
|
|
||||||
switch (subservice) {
|
|
||||||
case (Subservice::COMMAND_SET_HEALTH): {
|
|
||||||
HealthSetCommand healthCommand;
|
|
||||||
result = healthCommand.deSerialize(&tcData, &tcDataLen, SerializeIF::Endianness::BIG);
|
|
||||||
if (result != returnvalue::OK) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_SET,
|
|
||||||
healthCommand.getHealth());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case (Subservice::COMMAND_ANNOUNCE_HEALTH): {
|
|
||||||
HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_ANNOUNCE);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case (Subservice::COMMAND_ANNOUNCE_HEALTH_ALL): {
|
|
||||||
HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_ANNOUNCE_ALL);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
// Should never happen, subservice was already checked
|
|
||||||
result = returnvalue::FAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t CService201HealthCommanding::handleReply(const CommandMessage *reply,
|
|
||||||
Command_t previousCommand, uint32_t *state,
|
|
||||||
CommandMessage *optionalNextCommand,
|
|
||||||
object_id_t objectId, bool *isStep) {
|
|
||||||
Command_t replyId = reply->getCommand();
|
|
||||||
if (replyId == HealthMessage::REPLY_HEALTH_SET) {
|
|
||||||
return EXECUTION_COMPLETE;
|
|
||||||
} else if (replyId == CommandMessageIF::REPLY_REJECTED) {
|
|
||||||
return reply->getReplyRejectedReason();
|
|
||||||
}
|
|
||||||
return CommandingServiceBase::INVALID_REPLY;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Not used for now, health state already reported by event
|
|
||||||
[[maybe_unused]] ReturnValue_t CService201HealthCommanding::prepareHealthSetReply(
|
|
||||||
const CommandMessage *reply) {
|
|
||||||
auto health = static_cast<uint8_t>(HealthMessage::getHealth(reply));
|
|
||||||
auto oldHealth = static_cast<uint8_t>(HealthMessage::getOldHealth(reply));
|
|
||||||
HealthSetReply healthSetReply(health, oldHealth);
|
|
||||||
return sendTmPacket(Subservice::REPLY_HEALTH_SET, healthSetReply);
|
|
||||||
}
|
|
155
src/fsfw/pus/CServiceHealthCommanding.cpp
Normal file
155
src/fsfw/pus/CServiceHealthCommanding.cpp
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
#include <fsfw/events/EventManagerIF.h>
|
||||||
|
#include <fsfw/pus/CServiceHealthCommanding.h>
|
||||||
|
|
||||||
|
#include "fsfw/health/HasHealthIF.h"
|
||||||
|
#include "fsfw/health/HealthMessage.h"
|
||||||
|
#include "fsfw/objectmanager/ObjectManager.h"
|
||||||
|
#include "fsfw/pus/servicepackets/Service201Packets.h"
|
||||||
|
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||||
|
|
||||||
|
CServiceHealthCommanding::CServiceHealthCommanding(HealthServiceCfg args)
|
||||||
|
: CommandingServiceBase(args.objectId, args.apid, "PUS 201 Health MGMT", args.service,
|
||||||
|
args.numParallelCommands, args.commandTimeoutSeconds),
|
||||||
|
healthTable(args.table),
|
||||||
|
maxNumHealthInfoPerCycle(args.maxNumHealthInfoPerCycle) {}
|
||||||
|
|
||||||
|
ReturnValue_t CServiceHealthCommanding::isValidSubservice(uint8_t subservice) {
|
||||||
|
switch (subservice) {
|
||||||
|
case (Subservice::COMMAND_SET_HEALTH):
|
||||||
|
case (Subservice::COMMAND_ANNOUNCE_HEALTH):
|
||||||
|
case (Subservice::COMMAND_ANNOUNCE_HEALTH_ALL):
|
||||||
|
return returnvalue::OK;
|
||||||
|
default:
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::error << "Invalid Subservice" << std::endl;
|
||||||
|
#endif
|
||||||
|
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t CServiceHealthCommanding::getMessageQueueAndObject(uint8_t subservice,
|
||||||
|
const uint8_t *tcData,
|
||||||
|
size_t tcDataLen,
|
||||||
|
MessageQueueId_t *id,
|
||||||
|
object_id_t *objectId) {
|
||||||
|
switch (subservice) {
|
||||||
|
case (Subservice::COMMAND_SET_HEALTH):
|
||||||
|
case (Subservice::COMMAND_ANNOUNCE_HEALTH): {
|
||||||
|
if (tcDataLen < sizeof(object_id_t)) {
|
||||||
|
return CommandingServiceBase::INVALID_TC;
|
||||||
|
}
|
||||||
|
SerializeAdapter::deSerialize(objectId, &tcData, &tcDataLen, SerializeIF::Endianness::BIG);
|
||||||
|
|
||||||
|
return checkInterfaceAndAcquireMessageQueue(id, objectId);
|
||||||
|
}
|
||||||
|
case (Subservice::COMMAND_ANNOUNCE_HEALTH_ALL): {
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t CServiceHealthCommanding::checkInterfaceAndAcquireMessageQueue(
|
||||||
|
MessageQueueId_t *messageQueueToSet, const object_id_t *objectId) {
|
||||||
|
auto *destination = ObjectManager::instance()->get<HasHealthIF>(*objectId);
|
||||||
|
if (destination == nullptr) {
|
||||||
|
return CommandingServiceBase::INVALID_OBJECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
*messageQueueToSet = destination->getCommandQueue();
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t CServiceHealthCommanding::prepareCommand(CommandMessage *message, uint8_t subservice,
|
||||||
|
const uint8_t *tcData, size_t tcDataLen,
|
||||||
|
uint32_t *state, object_id_t objectId) {
|
||||||
|
ReturnValue_t result = returnvalue::OK;
|
||||||
|
switch (subservice) {
|
||||||
|
case (Subservice::COMMAND_SET_HEALTH): {
|
||||||
|
if (tcDataLen != sizeof(object_id_t) + sizeof(HasHealthIF::HealthState)) {
|
||||||
|
return CommandingServiceBase::INVALID_TC;
|
||||||
|
}
|
||||||
|
HealthSetCommand healthCommand;
|
||||||
|
result = healthCommand.deSerialize(&tcData, &tcDataLen, SerializeIF::Endianness::BIG);
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_SET,
|
||||||
|
healthCommand.getHealth());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case (Subservice::COMMAND_ANNOUNCE_HEALTH): {
|
||||||
|
HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_ANNOUNCE);
|
||||||
|
return CommandingServiceBase::EXECUTION_COMPLETE;
|
||||||
|
}
|
||||||
|
case (Subservice::COMMAND_ANNOUNCE_HEALTH_ALL): {
|
||||||
|
ReturnValue_t result = iterateHealthTable(true);
|
||||||
|
if (result == returnvalue::OK) {
|
||||||
|
reportAllHealth = true;
|
||||||
|
return EXECUTION_COMPLETE;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
while (true) {
|
||||||
|
ReturnValue_t result = iterateHealthTable(false);
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
// Should never happen, subservice was already checked
|
||||||
|
result = returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t CServiceHealthCommanding::handleReply(const CommandMessage *reply,
|
||||||
|
Command_t previousCommand, uint32_t *state,
|
||||||
|
CommandMessage *optionalNextCommand,
|
||||||
|
object_id_t objectId, bool *isStep) {
|
||||||
|
Command_t replyId = reply->getCommand();
|
||||||
|
if (replyId == HealthMessage::REPLY_HEALTH_SET) {
|
||||||
|
return EXECUTION_COMPLETE;
|
||||||
|
} else if (replyId == CommandMessageIF::REPLY_REJECTED) {
|
||||||
|
return reply->getReplyRejectedReason();
|
||||||
|
}
|
||||||
|
return CommandingServiceBase::INVALID_REPLY;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CServiceHealthCommanding::doPeriodicOperation() {
|
||||||
|
if (reportAllHealth) {
|
||||||
|
for (uint8_t i = 0; i < maxNumHealthInfoPerCycle; i++) {
|
||||||
|
ReturnValue_t result = iterateHealthTable(false);
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
reportAllHealth = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not used for now, health state already reported by event
|
||||||
|
[[maybe_unused]] ReturnValue_t CServiceHealthCommanding::prepareHealthSetReply(
|
||||||
|
const CommandMessage *reply) {
|
||||||
|
auto health = static_cast<uint8_t>(HealthMessage::getHealth(reply));
|
||||||
|
auto oldHealth = static_cast<uint8_t>(HealthMessage::getOldHealth(reply));
|
||||||
|
HealthSetReply healthSetReply(health, oldHealth);
|
||||||
|
return sendTmPacket(Subservice::REPLY_HEALTH_SET, healthSetReply);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t CServiceHealthCommanding::iterateHealthTable(bool reset) {
|
||||||
|
std::pair<object_id_t, HasHealthIF::HealthState> pair;
|
||||||
|
|
||||||
|
ReturnValue_t result = healthTable.iterate(&pair, reset);
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
EventManagerIF::triggerEvent(pair.first, HasHealthIF::HEALTH_INFO, pair.second, pair.second);
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +1,26 @@
|
|||||||
#ifndef FSFW_PUS_CSERVICE201HEALTHCOMMANDING_H_
|
#ifndef FSFW_PUS_CSERVICE201HEALTHCOMMANDING_H_
|
||||||
#define FSFW_PUS_CSERVICE201HEALTHCOMMANDING_H_
|
#define FSFW_PUS_CSERVICE201HEALTHCOMMANDING_H_
|
||||||
|
|
||||||
|
#include <fsfw/health/HealthTable.h>
|
||||||
|
|
||||||
#include "fsfw/tmtcservices/CommandingServiceBase.h"
|
#include "fsfw/tmtcservices/CommandingServiceBase.h"
|
||||||
|
|
||||||
|
struct HealthServiceCfg {
|
||||||
|
HealthServiceCfg(object_id_t objectId, uint16_t apid, HealthTable &healthTable,
|
||||||
|
uint16_t maxNumHealthInfoPerCycle)
|
||||||
|
: objectId(objectId),
|
||||||
|
apid(apid),
|
||||||
|
table(healthTable),
|
||||||
|
maxNumHealthInfoPerCycle(maxNumHealthInfoPerCycle) {}
|
||||||
|
object_id_t objectId;
|
||||||
|
uint16_t apid;
|
||||||
|
HealthTable &table;
|
||||||
|
uint16_t maxNumHealthInfoPerCycle;
|
||||||
|
uint8_t service = 201;
|
||||||
|
uint8_t numParallelCommands = 4;
|
||||||
|
uint16_t commandTimeoutSeconds = 60;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Custom PUS service to set health of all objects
|
* @brief Custom PUS service to set health of all objects
|
||||||
* implementing hasHealthIF.
|
* implementing hasHealthIF.
|
||||||
@ -17,11 +35,10 @@
|
|||||||
* child class like this service
|
* child class like this service
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class CService201HealthCommanding : public CommandingServiceBase {
|
class CServiceHealthCommanding : public CommandingServiceBase {
|
||||||
public:
|
public:
|
||||||
CService201HealthCommanding(object_id_t objectId, uint16_t apid, uint8_t serviceId,
|
CServiceHealthCommanding(HealthServiceCfg args);
|
||||||
uint8_t numParallelCommands = 4, uint16_t commandTimeoutSeconds = 60);
|
~CServiceHealthCommanding() override = default;
|
||||||
~CService201HealthCommanding() override = default;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/* CSB abstract function implementations */
|
/* CSB abstract function implementations */
|
||||||
@ -37,7 +54,13 @@ class CService201HealthCommanding : public CommandingServiceBase {
|
|||||||
CommandMessage *optionalNextCommand, object_id_t objectId,
|
CommandMessage *optionalNextCommand, object_id_t objectId,
|
||||||
bool *isStep) override;
|
bool *isStep) override;
|
||||||
|
|
||||||
|
void doPeriodicOperation() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
HealthTable &healthTable;
|
||||||
|
uint16_t maxNumHealthInfoPerCycle = 0;
|
||||||
|
bool reportAllHealth = false;
|
||||||
|
ReturnValue_t iterateHealthTable(bool reset);
|
||||||
static ReturnValue_t checkInterfaceAndAcquireMessageQueue(MessageQueueId_t *MessageQueueToSet,
|
static ReturnValue_t checkInterfaceAndAcquireMessageQueue(MessageQueueId_t *MessageQueueToSet,
|
||||||
const object_id_t *objectId);
|
const object_id_t *objectId);
|
||||||
|
|
@ -41,6 +41,8 @@ class Service11TelecommandScheduling final : public PusServiceBase {
|
|||||||
static constexpr ReturnValue_t INVALID_TIME_WINDOW = returnvalue::makeCode(CLASS_ID, 2);
|
static constexpr ReturnValue_t INVALID_TIME_WINDOW = returnvalue::makeCode(CLASS_ID, 2);
|
||||||
static constexpr ReturnValue_t TIMESHIFTING_NOT_POSSIBLE = returnvalue::makeCode(CLASS_ID, 3);
|
static constexpr ReturnValue_t TIMESHIFTING_NOT_POSSIBLE = returnvalue::makeCode(CLASS_ID, 3);
|
||||||
static constexpr ReturnValue_t INVALID_RELATIVE_TIME = returnvalue::makeCode(CLASS_ID, 4);
|
static constexpr ReturnValue_t INVALID_RELATIVE_TIME = returnvalue::makeCode(CLASS_ID, 4);
|
||||||
|
static constexpr ReturnValue_t CONTAINED_TC_TOO_SMALL = returnvalue::makeCode(CLASS_ID, 5);
|
||||||
|
static constexpr ReturnValue_t CONTAINED_TC_CRC_MISSMATCH = returnvalue::makeCode(CLASS_ID, 6);
|
||||||
|
|
||||||
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PUS_SERVICE_11;
|
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PUS_SERVICE_11;
|
||||||
|
|
||||||
|
@ -2,9 +2,11 @@
|
|||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
|
#include "fsfw/globalfunctions/CRC.h"
|
||||||
#include "fsfw/objectmanager/ObjectManager.h"
|
#include "fsfw/objectmanager/ObjectManager.h"
|
||||||
#include "fsfw/serialize/SerializeAdapter.h"
|
#include "fsfw/serialize/SerializeAdapter.h"
|
||||||
#include "fsfw/serviceinterface.h"
|
#include "fsfw/serviceinterface.h"
|
||||||
|
#include "fsfw/tmtcpacket/pus/tc/PusTcIF.h"
|
||||||
#include "fsfw/tmtcservices/AcceptsTelecommandsIF.h"
|
#include "fsfw/tmtcservices/AcceptsTelecommandsIF.h"
|
||||||
|
|
||||||
static constexpr auto DEF_END = SerializeIF::Endianness::BIG;
|
static constexpr auto DEF_END = SerializeIF::Endianness::BIG;
|
||||||
@ -158,7 +160,7 @@ inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::doInsertActivi
|
|||||||
// (See requirement for Time margin)
|
// (See requirement for Time margin)
|
||||||
timeval tNow = {};
|
timeval tNow = {};
|
||||||
Clock::getClock_timeval(&tNow);
|
Clock::getClock_timeval(&tNow);
|
||||||
if (timestamp - tNow.tv_sec <= RELEASE_TIME_MARGIN_SECONDS) {
|
if (timestamp < static_cast<uint32_t>(tNow.tv_sec + RELEASE_TIME_MARGIN_SECONDS)) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "Service11TelecommandScheduling::doInsertActivity: Release time too close to "
|
sif::warning << "Service11TelecommandScheduling::doInsertActivity: Release time too close to "
|
||||||
"current time"
|
"current time"
|
||||||
@ -171,6 +173,14 @@ inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::doInsertActivi
|
|||||||
return returnvalue::FAILED;
|
return returnvalue::FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (size < PusTcIF::MIN_SIZE) {
|
||||||
|
return CONTAINED_TC_TOO_SMALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CRC::crc16ccitt(data, size) != 0) {
|
||||||
|
return CONTAINED_TC_CRC_MISSMATCH;
|
||||||
|
}
|
||||||
|
|
||||||
// store currentPacket and receive the store address
|
// store currentPacket and receive the store address
|
||||||
store_address_t addr{};
|
store_address_t addr{};
|
||||||
if (tcStore->addData(&addr, data, size) != returnvalue::OK ||
|
if (tcStore->addData(&addr, data, size) != returnvalue::OK ||
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "fsfw/pus/Service17Test.h"
|
#include "fsfw/pus/Service17Test.h"
|
||||||
|
|
||||||
|
#include <fsfw/serialize/SerializeElement.h>
|
||||||
|
|
||||||
#include "fsfw/FSFW.h"
|
#include "fsfw/FSFW.h"
|
||||||
#include "fsfw/objectmanager/ObjectManager.h"
|
#include "fsfw/objectmanager/ObjectManager.h"
|
||||||
#include "fsfw/objectmanager/SystemObject.h"
|
#include "fsfw/objectmanager/SystemObject.h"
|
||||||
@ -31,6 +33,15 @@ ReturnValue_t Service17Test::handleRequest(uint8_t subservice) {
|
|||||||
}
|
}
|
||||||
return tmHelper.storeAndSendTmPacket();
|
return tmHelper.storeAndSendTmPacket();
|
||||||
}
|
}
|
||||||
|
case Subservice::PING_WITH_DATA: {
|
||||||
|
SerializeElement<uint32_t> receivedDataLen = currentPacket.getUserDataLen();
|
||||||
|
ReturnValue_t result =
|
||||||
|
tmHelper.prepareTmPacket(Subservice::PING_WITH_DATA_REPORT_WITH_SIZE, receivedDataLen);
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return tmHelper.storeAndSendTmPacket();
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
|
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,9 @@ class Service17Test : public PusServiceBase {
|
|||||||
CONNECTION_TEST_REPORT = 2,
|
CONNECTION_TEST_REPORT = 2,
|
||||||
//! [EXPORT] : [COMMAND] Trigger test reply and test event
|
//! [EXPORT] : [COMMAND] Trigger test reply and test event
|
||||||
EVENT_TRIGGER_TEST = 128,
|
EVENT_TRIGGER_TEST = 128,
|
||||||
|
PING_WITH_DATA = 129,
|
||||||
|
//! [EXPORT] : [COMMAND] Report which reports the sent user data size
|
||||||
|
PING_WITH_DATA_REPORT_WITH_SIZE = 130
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit Service17Test(PsbParams params);
|
explicit Service17Test(PsbParams params);
|
||||||
|
@ -69,14 +69,14 @@ ReturnValue_t Service20ParameterManagement::checkInterfaceAndAcquireMessageQueue
|
|||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "Service20ParameterManagement::checkInterfaceAndAcquire"
|
sif::error << "Service20ParameterManagement::checkInterfaceAndAcquire"
|
||||||
<< "MessageQueue: Can't access object" << std::endl;
|
<< "MessageQueue: Can't access object" << std::endl;
|
||||||
sif::error << "Object ID: " << std::hex << objectId << std::dec << std::endl;
|
sif::error << "Object ID: 0x" << std::hex << *objectId << std::dec << std::endl;
|
||||||
sif::error << "Make sure it implements ReceivesParameterMessagesIF!" << std::endl;
|
sif::error << "Make sure it implements ReceivesParameterMessagesIF" << std::endl;
|
||||||
#else
|
#else
|
||||||
sif::printError(
|
sif::printError(
|
||||||
"Service20ParameterManagement::checkInterfaceAndAcquire"
|
"Service20ParameterManagement::checkInterfaceAndAcquire"
|
||||||
"MessageQueue: Can't access object\n");
|
"MessageQueue: Can't access object\n");
|
||||||
sif::printError("Object ID: 0x%08x\n", *objectId);
|
sif::printError("Object ID: 0x%08x\n", *objectId);
|
||||||
sif::printError("Make sure it implements ReceivesParameterMessagesIF!\n");
|
sif::printError("Make sure it implements ReceivesParameterMessagesIF\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return CommandingServiceBase::INVALID_OBJECT;
|
return CommandingServiceBase::INVALID_OBJECT;
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
class Service5EventReporting : public PusServiceBase {
|
class Service5EventReporting : public PusServiceBase {
|
||||||
public:
|
public:
|
||||||
Service5EventReporting(PsbParams params, size_t maxNumberReportsPerCycle = 10,
|
Service5EventReporting(PsbParams params, size_t maxNumberReportsPerCycle = 10,
|
||||||
uint32_t messageQueueDepth = 10);
|
uint32_t messageQueueDepth = 20);
|
||||||
~Service5EventReporting() override;
|
~Service5EventReporting() override;
|
||||||
|
|
||||||
/***
|
/***
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "fsfw/pus/Service9TimeManagement.h"
|
#include "fsfw/pus/Service9TimeManagement.h"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
#include "fsfw/events/EventManagerIF.h"
|
#include "fsfw/events/EventManagerIF.h"
|
||||||
#include "fsfw/pus/servicepackets/Service9Packets.h"
|
#include "fsfw/pus/servicepackets/Service9Packets.h"
|
||||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||||
@ -15,9 +17,17 @@ ReturnValue_t Service9TimeManagement::performService() { return returnvalue::OK;
|
|||||||
|
|
||||||
ReturnValue_t Service9TimeManagement::handleRequest(uint8_t subservice) {
|
ReturnValue_t Service9TimeManagement::handleRequest(uint8_t subservice) {
|
||||||
switch (subservice) {
|
switch (subservice) {
|
||||||
case SUBSERVICE::SET_TIME: {
|
case Subservice::SET_TIME: {
|
||||||
return setTime();
|
return setTime();
|
||||||
}
|
}
|
||||||
|
case Subservice::DUMP_TIME: {
|
||||||
|
timeval newTime;
|
||||||
|
Clock::getClock_timeval(&newTime);
|
||||||
|
uint32_t subsecondMs =
|
||||||
|
static_cast<uint32_t>(std::floor(static_cast<double>(newTime.tv_usec) / 1000.0));
|
||||||
|
triggerEvent(CLOCK_DUMP, newTime.tv_sec, subsecondMs);
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
|
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
|
||||||
}
|
}
|
||||||
@ -33,14 +43,14 @@ ReturnValue_t Service9TimeManagement::setTime() {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t formerUptime;
|
timeval time;
|
||||||
Clock::getUptime(&formerUptime);
|
Clock::getClock_timeval(&time);
|
||||||
result = Clock::setClock(&timeToSet);
|
result = Clock::setClock(&timeToSet);
|
||||||
|
|
||||||
if (result == returnvalue::OK) {
|
if (result == returnvalue::OK) {
|
||||||
uint32_t newUptime;
|
timeval newTime;
|
||||||
Clock::getUptime(&newUptime);
|
Clock::getClock_timeval(&newTime);
|
||||||
triggerEvent(CLOCK_SET, newUptime, formerUptime);
|
triggerEvent(CLOCK_SET, time.tv_sec, newTime.tv_sec);
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
} else {
|
} else {
|
||||||
triggerEvent(CLOCK_SET_FAILURE, result, 0);
|
triggerEvent(CLOCK_SET_FAILURE, result, 0);
|
||||||
|
@ -6,10 +6,13 @@
|
|||||||
class Service9TimeManagement : public PusServiceBase {
|
class Service9TimeManagement : public PusServiceBase {
|
||||||
public:
|
public:
|
||||||
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PUS_SERVICE_9;
|
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PUS_SERVICE_9;
|
||||||
//!< Clock has been set. P1: New Uptime. P2: Old Uptime
|
|
||||||
|
//!< Clock has been set. P1: old timeval seconds. P2: new timeval seconds.
|
||||||
static constexpr Event CLOCK_SET = MAKE_EVENT(0, severity::INFO);
|
static constexpr Event CLOCK_SET = MAKE_EVENT(0, severity::INFO);
|
||||||
|
//!< Clock dump event. P1: timeval seconds P2: timeval milliseconds.
|
||||||
|
static constexpr Event CLOCK_DUMP = MAKE_EVENT(1, severity::INFO);
|
||||||
//!< Clock could not be set. P1: Returncode.
|
//!< Clock could not be set. P1: Returncode.
|
||||||
static constexpr Event CLOCK_SET_FAILURE = MAKE_EVENT(1, severity::LOW);
|
static constexpr Event CLOCK_SET_FAILURE = MAKE_EVENT(2, severity::LOW);
|
||||||
|
|
||||||
static constexpr uint8_t CLASS_ID = CLASS_ID::PUS_SERVICE_9;
|
static constexpr uint8_t CLASS_ID = CLASS_ID::PUS_SERVICE_9;
|
||||||
|
|
||||||
@ -30,8 +33,9 @@ class Service9TimeManagement : public PusServiceBase {
|
|||||||
virtual ReturnValue_t setTime();
|
virtual ReturnValue_t setTime();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum SUBSERVICE {
|
enum Subservice {
|
||||||
SET_TIME = 128 //!< [EXPORT] : [COMMAND] Time command in ASCII, CUC or CDS format
|
SET_TIME = 128, //!< [EXPORT] : [COMMAND] Time command in ASCII, CUC or CDS format
|
||||||
|
DUMP_TIME = 129,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#ifndef FSFW_PUS_SERVICEPACKETS_SERVICE200PACKETS_H_
|
#ifndef FSFW_PUS_SERVICEPACKETS_SERVICE200PACKETS_H_
|
||||||
#define FSFW_PUS_SERVICEPACKETS_SERVICE200PACKETS_H_
|
#define FSFW_PUS_SERVICEPACKETS_SERVICE200PACKETS_H_
|
||||||
|
|
||||||
#include "../../modes/ModeMessage.h"
|
#include "fsfw/modes/ModeMessage.h"
|
||||||
#include "../../serialize/SerialLinkedListAdapter.h"
|
#include "fsfw/serialize/SerialLinkedListAdapter.h"
|
||||||
#include "../../serialize/SerializeIF.h"
|
#include "fsfw/serialize/SerializeIF.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Subservice 1, 2, 3, 4, 5
|
* @brief Subservice 1, 2, 3, 4, 5
|
||||||
|
@ -31,9 +31,8 @@ LocalPool::LocalPool(object_id_t setObjectId, const LocalPoolConfig& poolConfig,
|
|||||||
|
|
||||||
LocalPool::~LocalPool() = default;
|
LocalPool::~LocalPool() = default;
|
||||||
|
|
||||||
ReturnValue_t LocalPool::addData(store_address_t* storageId, const uint8_t* data, size_t size,
|
ReturnValue_t LocalPool::addData(store_address_t* storageId, const uint8_t* data, size_t size) {
|
||||||
bool ignoreFault) {
|
ReturnValue_t status = reserveSpace(size, storageId);
|
||||||
ReturnValue_t status = reserveSpace(size, storageId, ignoreFault);
|
|
||||||
if (status == returnvalue::OK) {
|
if (status == returnvalue::OK) {
|
||||||
write(*storageId, data, size);
|
write(*storageId, data, size);
|
||||||
}
|
}
|
||||||
@ -49,8 +48,8 @@ ReturnValue_t LocalPool::getData(store_address_t packetId, const uint8_t** packe
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t LocalPool::getFreeElement(store_address_t* storageId, const size_t size,
|
ReturnValue_t LocalPool::getFreeElement(store_address_t* storageId, const size_t size,
|
||||||
uint8_t** pData, bool ignoreFault) {
|
uint8_t** pData) {
|
||||||
ReturnValue_t status = reserveSpace(size, storageId, ignoreFault);
|
ReturnValue_t status = reserveSpace(size, storageId);
|
||||||
if (status == returnvalue::OK) {
|
if (status == returnvalue::OK) {
|
||||||
*pData = &store[storageId->poolIndex][getRawPosition(*storageId)];
|
*pData = &store[storageId->poolIndex][getRawPosition(*storageId)];
|
||||||
} else {
|
} else {
|
||||||
@ -167,7 +166,7 @@ void LocalPool::clearStore() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t LocalPool::reserveSpace(size_t size, store_address_t* storeId, bool ignoreFault) {
|
ReturnValue_t LocalPool::reserveSpace(size_t size, store_address_t* storeId) {
|
||||||
ReturnValue_t status = getSubPoolIndex(size, &storeId->poolIndex);
|
ReturnValue_t status = getSubPoolIndex(size, &storeId->poolIndex);
|
||||||
if (status != returnvalue::OK) {
|
if (status != returnvalue::OK) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
@ -318,27 +317,3 @@ bool LocalPool::hasDataAtId(store_address_t storeId) const {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t LocalPool::getFreeElement(store_address_t* storeId, size_t size, uint8_t** pData) {
|
|
||||||
return StorageManagerIF::getFreeElement(storeId, size, pData);
|
|
||||||
}
|
|
||||||
|
|
||||||
ConstAccessorPair LocalPool::getData(store_address_t storeId) {
|
|
||||||
return StorageManagerIF::getData(storeId);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t LocalPool::addData(store_address_t* storeId, const uint8_t* data, size_t size) {
|
|
||||||
return StorageManagerIF::addData(storeId, data, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t LocalPool::getData(store_address_t storeId, ConstStorageAccessor& accessor) {
|
|
||||||
return StorageManagerIF::getData(storeId, accessor);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t LocalPool::modifyData(store_address_t storeId, StorageAccessor& accessor) {
|
|
||||||
return StorageManagerIF::modifyData(storeId, accessor);
|
|
||||||
}
|
|
||||||
|
|
||||||
AccessorPair LocalPool::modifyData(store_address_t storeId) {
|
|
||||||
return StorageManagerIF::modifyData(storeId);
|
|
||||||
}
|
|
||||||
|
@ -86,21 +86,13 @@ class LocalPool : public SystemObject, public StorageManagerIF {
|
|||||||
/**
|
/**
|
||||||
* Documentation: See StorageManagerIF.h
|
* Documentation: See StorageManagerIF.h
|
||||||
*/
|
*/
|
||||||
ReturnValue_t addData(store_address_t* storeId, const uint8_t* data, size_t size,
|
|
||||||
bool ignoreFault) override;
|
|
||||||
ReturnValue_t addData(store_address_t* storeId, const uint8_t* data, size_t size) override;
|
ReturnValue_t addData(store_address_t* storeId, const uint8_t* data, size_t size) override;
|
||||||
|
|
||||||
ReturnValue_t getFreeElement(store_address_t* storeId, size_t size, uint8_t** pData) override;
|
ReturnValue_t getFreeElement(store_address_t* storeId, size_t size, uint8_t** pData) override;
|
||||||
ReturnValue_t getFreeElement(store_address_t* storeId, size_t size, uint8_t** pData,
|
|
||||||
bool ignoreFault) override;
|
|
||||||
|
|
||||||
ConstAccessorPair getData(store_address_t storeId) override;
|
|
||||||
ReturnValue_t getData(store_address_t storeId, ConstStorageAccessor& accessor) override;
|
|
||||||
ReturnValue_t getData(store_address_t storeId, const uint8_t** packet_ptr, size_t* size) override;
|
ReturnValue_t getData(store_address_t storeId, const uint8_t** packet_ptr, size_t* size) override;
|
||||||
|
|
||||||
AccessorPair modifyData(store_address_t storeId) override;
|
|
||||||
ReturnValue_t modifyData(store_address_t storeId, uint8_t** packet_ptr, size_t* size) override;
|
ReturnValue_t modifyData(store_address_t storeId, uint8_t** packet_ptr, size_t* size) override;
|
||||||
ReturnValue_t modifyData(store_address_t storeId, StorageAccessor& accessor) override;
|
|
||||||
|
|
||||||
ReturnValue_t deleteData(store_address_t storeId) override;
|
ReturnValue_t deleteData(store_address_t storeId) override;
|
||||||
ReturnValue_t deleteData(uint8_t* ptr, size_t size, store_address_t* storeId) override;
|
ReturnValue_t deleteData(uint8_t* ptr, size_t size, store_address_t* storeId) override;
|
||||||
@ -136,6 +128,12 @@ class LocalPool : public SystemObject, public StorageManagerIF {
|
|||||||
[[nodiscard]] max_subpools_t getNumberOfSubPools() const override;
|
[[nodiscard]] max_subpools_t getNumberOfSubPools() const override;
|
||||||
[[nodiscard]] bool hasDataAtId(store_address_t storeId) const override;
|
[[nodiscard]] bool hasDataAtId(store_address_t storeId) const override;
|
||||||
|
|
||||||
|
// Using functions provided by StorageManagerIF requires either a fully qualified path
|
||||||
|
// like for example localPool.StorageManagerIF::getFreeElement(...) or re-exporting
|
||||||
|
// the fully qualified path with the using directive.
|
||||||
|
using StorageManagerIF::getData;
|
||||||
|
using StorageManagerIF::modifyData;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* With this helper method, a free element of @c size is reserved.
|
* With this helper method, a free element of @c size is reserved.
|
||||||
@ -144,7 +142,7 @@ class LocalPool : public SystemObject, public StorageManagerIF {
|
|||||||
* @return - returnvalue::OK on success,
|
* @return - returnvalue::OK on success,
|
||||||
* - the return codes of #getPoolIndex or #findEmpty otherwise.
|
* - the return codes of #getPoolIndex or #findEmpty otherwise.
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t reserveSpace(size_t size, store_address_t* address, bool ignoreFault);
|
virtual ReturnValue_t reserveSpace(size_t size, store_address_t* address);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
@ -188,6 +186,8 @@ class LocalPool : public SystemObject, public StorageManagerIF {
|
|||||||
std::vector<std::vector<size_type>> sizeLists =
|
std::vector<std::vector<size_type>> sizeLists =
|
||||||
std::vector<std::vector<size_type>>(NUMBER_OF_SUBPOOLS);
|
std::vector<std::vector<size_type>>(NUMBER_OF_SUBPOOLS);
|
||||||
|
|
||||||
|
bool ignoreFault = false;
|
||||||
|
|
||||||
//! A variable to determine whether higher n pools are used if
|
//! A variable to determine whether higher n pools are used if
|
||||||
//! the store is full.
|
//! the store is full.
|
||||||
bool spillsToHigherPools = false;
|
bool spillsToHigherPools = false;
|
||||||
|
@ -9,10 +9,9 @@ PoolManager::PoolManager(object_id_t setObjectId, const LocalPoolConfig& localPo
|
|||||||
|
|
||||||
PoolManager::~PoolManager() { MutexFactory::instance()->deleteMutex(mutex); }
|
PoolManager::~PoolManager() { MutexFactory::instance()->deleteMutex(mutex); }
|
||||||
|
|
||||||
ReturnValue_t PoolManager::reserveSpace(const size_t size, store_address_t* address,
|
ReturnValue_t PoolManager::reserveSpace(const size_t size, store_address_t* address) {
|
||||||
bool ignoreFault) {
|
MutexGuard mutexHelper(mutex, MutexIF::TimeoutType::WAITING, mutexTimeoutMs, LOCK_CTX);
|
||||||
MutexGuard mutexHelper(mutex, MutexIF::TimeoutType::WAITING, mutexTimeoutMs);
|
ReturnValue_t status = LocalPool::reserveSpace(size, address);
|
||||||
ReturnValue_t status = LocalPool::reserveSpace(size, address, ignoreFault);
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,12 +22,12 @@ ReturnValue_t PoolManager::deleteData(store_address_t storeId) {
|
|||||||
<< storeId.poolIndex << ". id is " << storeId.packetIndex << std::endl;
|
<< storeId.poolIndex << ". id is " << storeId.packetIndex << std::endl;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
MutexGuard mutexHelper(mutex, MutexIF::TimeoutType::WAITING, mutexTimeoutMs);
|
MutexGuard mutexHelper(mutex, MutexIF::TimeoutType::WAITING, mutexTimeoutMs, LOCK_CTX);
|
||||||
return LocalPool::deleteData(storeId);
|
return LocalPool::deleteData(storeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t PoolManager::deleteData(uint8_t* buffer, size_t size, store_address_t* storeId) {
|
ReturnValue_t PoolManager::deleteData(uint8_t* buffer, size_t size, store_address_t* storeId) {
|
||||||
MutexGuard mutexHelper(mutex, MutexIF::TimeoutType::WAITING, 20);
|
MutexGuard mutexHelper(mutex, MutexIF::TimeoutType::WAITING, mutexTimeoutMs, LOCK_CTX);
|
||||||
ReturnValue_t status = LocalPool::deleteData(buffer, size, storeId);
|
ReturnValue_t status = LocalPool::deleteData(buffer, size, storeId);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -56,8 +56,9 @@ class PoolManager : public LocalPool {
|
|||||||
protected:
|
protected:
|
||||||
//! Default mutex timeout value to prevent permanent blocking.
|
//! Default mutex timeout value to prevent permanent blocking.
|
||||||
uint32_t mutexTimeoutMs = 20;
|
uint32_t mutexTimeoutMs = 20;
|
||||||
|
static constexpr char LOCK_CTX[] = "PoolManager";
|
||||||
|
|
||||||
ReturnValue_t reserveSpace(size_t size, store_address_t* address, bool ignoreFault) override;
|
ReturnValue_t reserveSpace(size_t size, store_address_t* address) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The mutex is created in the constructor and makes
|
* @brief The mutex is created in the constructor and makes
|
||||||
|
@ -55,7 +55,7 @@ class StorageManagerIF {
|
|||||||
/**
|
/**
|
||||||
* @brief This is the empty virtual destructor as required for C++ interfaces.
|
* @brief This is the empty virtual destructor as required for C++ interfaces.
|
||||||
*/
|
*/
|
||||||
~StorageManagerIF() = default;
|
virtual ~StorageManagerIF() = default;
|
||||||
/**
|
/**
|
||||||
* @brief With addData, a free storage position is allocated and data
|
* @brief With addData, a free storage position is allocated and data
|
||||||
* stored there.
|
* stored there.
|
||||||
@ -66,12 +66,7 @@ class StorageManagerIF {
|
|||||||
* @return Returns @returnvalue::OK if data was added.
|
* @return Returns @returnvalue::OK if data was added.
|
||||||
* @returnvalue::FAILED if data could not be added, storageId is unchanged then.
|
* @returnvalue::FAILED if data could not be added, storageId is unchanged then.
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t addData(store_address_t* storageId, const uint8_t* data, size_t size,
|
virtual ReturnValue_t addData(store_address_t* storageId, const uint8_t* data, size_t size) = 0;
|
||||||
bool ignoreFault) = 0;
|
|
||||||
|
|
||||||
virtual ReturnValue_t addData(store_address_t* storageId, const uint8_t* data, size_t size) {
|
|
||||||
return addData(storageId, data, size, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief With deleteData, the storageManager frees the memory region
|
* @brief With deleteData, the storageManager frees the memory region
|
||||||
@ -186,12 +181,8 @@ class StorageManagerIF {
|
|||||||
* @return Returns @returnvalue::OK if data was added.
|
* @return Returns @returnvalue::OK if data was added.
|
||||||
* @returnvalue::FAILED if data could not be added, storageId is unchanged then.
|
* @returnvalue::FAILED if data could not be added, storageId is unchanged then.
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t getFreeElement(store_address_t* storageId, size_t size, uint8_t** dataPtr,
|
virtual ReturnValue_t getFreeElement(store_address_t* storageId, size_t size,
|
||||||
bool ignoreFault) = 0;
|
uint8_t** dataPtr) = 0;
|
||||||
|
|
||||||
virtual ReturnValue_t getFreeElement(store_address_t* storageId, size_t size, uint8_t** dataPtr) {
|
|
||||||
return getFreeElement(storageId, size, dataPtr, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] virtual bool hasDataAtId(store_address_t storeId) const = 0;
|
[[nodiscard]] virtual bool hasDataAtId(store_address_t storeId) const = 0;
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
target_sources(${LIB_FSFW_NAME} PRIVATE Subsystem.cpp SubsystemBase.cpp)
|
target_sources(${LIB_FSFW_NAME} PRIVATE Subsystem.cpp SubsystemBase.cpp
|
||||||
|
helper.cpp)
|
||||||
|
|
||||||
add_subdirectory(modes)
|
add_subdirectory(modes)
|
||||||
|
13
src/fsfw/subsystem/HasModeTreeChildrenIF.h
Normal file
13
src/fsfw/subsystem/HasModeTreeChildrenIF.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#ifndef FSFW_SUBSYSTEM_HASMODETREECHILDRENIF_H_
|
||||||
|
#define FSFW_SUBSYSTEM_HASMODETREECHILDRENIF_H_
|
||||||
|
|
||||||
|
#include "ModeTreeChildIF.h"
|
||||||
|
|
||||||
|
class HasModeTreeChildrenIF {
|
||||||
|
public:
|
||||||
|
virtual ~HasModeTreeChildrenIF() = default;
|
||||||
|
virtual ReturnValue_t registerChild(const ModeTreeChildIF& child) = 0;
|
||||||
|
virtual MessageQueueId_t getCommandQueue() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // FSFW_SUBSYSTEM_HASMODETREECHILDRENIF_H_
|
15
src/fsfw/subsystem/ModeTreeChildIF.h
Normal file
15
src/fsfw/subsystem/ModeTreeChildIF.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#ifndef FSFW_SUBSYSTEM_MODETREECHILDIF_H_
|
||||||
|
#define FSFW_SUBSYSTEM_MODETREECHILDIF_H_
|
||||||
|
|
||||||
|
#include <fsfw/health/HasHealthIF.h>
|
||||||
|
#include <fsfw/modes/HasModesIF.h>
|
||||||
|
|
||||||
|
class ModeTreeChildIF {
|
||||||
|
public:
|
||||||
|
virtual ~ModeTreeChildIF() = default;
|
||||||
|
virtual object_id_t getObjectId() const = 0;
|
||||||
|
virtual const HasHealthIF* getOptHealthIF() const = 0;
|
||||||
|
virtual const HasModesIF& getModeIF() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* FSFW_SUBSYSTEM_MODETREECHILDIF_H_ */
|
13
src/fsfw/subsystem/ModeTreeConnectionIF.h
Normal file
13
src/fsfw/subsystem/ModeTreeConnectionIF.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#ifndef FSFW_SUBSYSTEM_MODES_MODETREECONNECTIONIF_H_
|
||||||
|
#define FSFW_SUBSYSTEM_MODES_MODETREECONNECTIONIF_H_
|
||||||
|
|
||||||
|
#include "fsfw/subsystem/HasModeTreeChildrenIF.h"
|
||||||
|
|
||||||
|
class ModeTreeConnectionIF {
|
||||||
|
public:
|
||||||
|
virtual ~ModeTreeConnectionIF() = default;
|
||||||
|
virtual ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF& parent) = 0;
|
||||||
|
virtual ModeTreeChildIF& getModeTreeChildIF() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* FSFW_SRC_FSFW_SUBSYSTEM_MODES_MODETREECONNECTIONIF_H_ */
|
@ -9,9 +9,9 @@
|
|||||||
#include "fsfw/serialize/SerialLinkedListAdapter.h"
|
#include "fsfw/serialize/SerialLinkedListAdapter.h"
|
||||||
#include "fsfw/serialize/SerializeElement.h"
|
#include "fsfw/serialize/SerializeElement.h"
|
||||||
|
|
||||||
Subsystem::Subsystem(object_id_t setObjectId, object_id_t parent, uint32_t maxNumberOfSequences,
|
Subsystem::Subsystem(object_id_t setObjectId, uint32_t maxNumberOfSequences,
|
||||||
uint32_t maxNumberOfTables)
|
uint32_t maxNumberOfTables)
|
||||||
: SubsystemBase(setObjectId, parent, 0),
|
: SubsystemBase(setObjectId, 0),
|
||||||
isInTransition(false),
|
isInTransition(false),
|
||||||
childrenChangedHealth(false),
|
childrenChangedHealth(false),
|
||||||
currentTargetTable(),
|
currentTargetTable(),
|
||||||
@ -36,6 +36,13 @@ ReturnValue_t Subsystem::checkSequence(HybridIterator<ModeListEntry> iter,
|
|||||||
|
|
||||||
for (; iter.value != nullptr; ++iter) {
|
for (; iter.value != nullptr; ++iter) {
|
||||||
if (!existsModeTable(iter->getTableId())) {
|
if (!existsModeTable(iter->getTableId())) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
using namespace std;
|
||||||
|
sif::warning << "Subsystem::checkSequence: "
|
||||||
|
<< "Object " << setfill('0') << hex << "0x" << setw(8) << getObjectId()
|
||||||
|
<< setw(0) << ": Mode table for mode ID "
|
||||||
|
<< "0x" << setw(8) << iter->getTableId() << " does not exist" << dec << endl;
|
||||||
|
#endif
|
||||||
return TABLE_DOES_NOT_EXIST;
|
return TABLE_DOES_NOT_EXIST;
|
||||||
} else {
|
} else {
|
||||||
ReturnValue_t result = checkTable(getTable(iter->getTableId()));
|
ReturnValue_t result = checkTable(getTable(iter->getTableId()));
|
||||||
|
@ -66,8 +66,7 @@ class Subsystem : public SubsystemBase, public HasModeSequenceIF {
|
|||||||
* @param maxNumberOfSequences
|
* @param maxNumberOfSequences
|
||||||
* @param maxNumberOfTables
|
* @param maxNumberOfTables
|
||||||
*/
|
*/
|
||||||
Subsystem(object_id_t setObjectId, object_id_t parent, uint32_t maxNumberOfSequences,
|
Subsystem(object_id_t setObjectId, uint32_t maxNumberOfSequences, uint32_t maxNumberOfTables);
|
||||||
uint32_t maxNumberOfTables);
|
|
||||||
virtual ~Subsystem();
|
virtual ~Subsystem();
|
||||||
|
|
||||||
ReturnValue_t addSequence(SequenceEntry sequence);
|
ReturnValue_t addSequence(SequenceEntry sequence);
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
#include "fsfw/subsystem/SubsystemBase.h"
|
#include "fsfw/subsystem/SubsystemBase.h"
|
||||||
|
|
||||||
|
#include "fsfw/FSFW.h"
|
||||||
#include "fsfw/ipc/QueueFactory.h"
|
#include "fsfw/ipc/QueueFactory.h"
|
||||||
#include "fsfw/objectmanager/ObjectManager.h"
|
#include "fsfw/objectmanager/ObjectManager.h"
|
||||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
#include "fsfw/serviceinterface.h"
|
||||||
|
#include "fsfw/subsystem/helper.h"
|
||||||
|
|
||||||
SubsystemBase::SubsystemBase(object_id_t setObjectId, object_id_t parent, Mode_t initialMode,
|
SubsystemBase::SubsystemBase(object_id_t setObjectId, Mode_t initialMode,
|
||||||
uint16_t commandQueueDepth)
|
uint16_t commandQueueDepth)
|
||||||
: SystemObject(setObjectId),
|
: SystemObject(setObjectId),
|
||||||
mode(initialMode),
|
mode(initialMode),
|
||||||
healthHelper(this, setObjectId),
|
healthHelper(this, setObjectId),
|
||||||
modeHelper(this),
|
modeHelper(this) {
|
||||||
parentId(parent) {
|
|
||||||
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
|
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
|
||||||
commandQueue = QueueFactory::instance()->createMessageQueue(
|
commandQueue = QueueFactory::instance()->createMessageQueue(
|
||||||
commandQueueDepth, CommandMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
commandQueueDepth, CommandMessage::MAX_MESSAGE_SIZE, &mqArgs);
|
||||||
@ -18,38 +19,9 @@ SubsystemBase::SubsystemBase(object_id_t setObjectId, object_id_t parent, Mode_t
|
|||||||
|
|
||||||
SubsystemBase::~SubsystemBase() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }
|
SubsystemBase::~SubsystemBase() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }
|
||||||
|
|
||||||
ReturnValue_t SubsystemBase::registerChild(object_id_t objectId) {
|
|
||||||
ChildInfo info;
|
|
||||||
|
|
||||||
HasModesIF* child = ObjectManager::instance()->get<HasModesIF>(objectId);
|
|
||||||
// This is a rather ugly hack to have the changedHealth info for all
|
|
||||||
// children available.
|
|
||||||
HasHealthIF* healthChild = ObjectManager::instance()->get<HasHealthIF>(objectId);
|
|
||||||
if (child == nullptr) {
|
|
||||||
if (healthChild == nullptr) {
|
|
||||||
return CHILD_DOESNT_HAVE_MODES;
|
|
||||||
} else {
|
|
||||||
info.commandQueue = healthChild->getCommandQueue();
|
|
||||||
info.mode = MODE_OFF;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// intentional to force an initial command during system startup
|
|
||||||
info.commandQueue = child->getCommandQueue();
|
|
||||||
info.mode = HasModesIF::MODE_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
info.submode = SUBMODE_NONE;
|
|
||||||
info.healthChanged = false;
|
|
||||||
|
|
||||||
auto resultPair = childrenMap.emplace(objectId, info);
|
|
||||||
if (not resultPair.second) {
|
|
||||||
return COULD_NOT_INSERT_CHILD;
|
|
||||||
}
|
|
||||||
return returnvalue::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t SubsystemBase::checkStateAgainstTable(HybridIterator<ModeListEntry> tableIter,
|
ReturnValue_t SubsystemBase::checkStateAgainstTable(HybridIterator<ModeListEntry> tableIter,
|
||||||
Submode_t targetSubmode) {
|
Submode_t targetSubmode) {
|
||||||
|
using namespace mode;
|
||||||
std::map<object_id_t, ChildInfo>::iterator childIter;
|
std::map<object_id_t, ChildInfo>::iterator childIter;
|
||||||
|
|
||||||
for (; tableIter.value != NULL; ++tableIter) {
|
for (; tableIter.value != NULL; ++tableIter) {
|
||||||
@ -63,13 +35,21 @@ ReturnValue_t SubsystemBase::checkStateAgainstTable(HybridIterator<ModeListEntry
|
|||||||
return returnvalue::FAILED;
|
return returnvalue::FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
Submode_t submodeToCheckAgainst = tableIter.value->getSubmode();
|
// Check submodes here.
|
||||||
|
uint8_t mask;
|
||||||
|
bool submodesAllowedMask = tableIter.value->submodesAllowed(&mask);
|
||||||
|
uint8_t submodeToCheckAgainst = tableIter.value->getSubmode();
|
||||||
if (tableIter.value->inheritSubmode()) {
|
if (tableIter.value->inheritSubmode()) {
|
||||||
submodeToCheckAgainst = targetSubmode;
|
submodeToCheckAgainst = targetSubmode;
|
||||||
}
|
}
|
||||||
|
if (submodesAllowedMask) {
|
||||||
if (childIter->second.submode != submodeToCheckAgainst) {
|
if ((childIter->second.submode | mask) != mask) {
|
||||||
return returnvalue::FAILED;
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (childIter->second.submode != submodeToCheckAgainst) {
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
@ -87,7 +67,8 @@ void SubsystemBase::executeTable(HybridIterator<ModeListEntry> tableIter, Submod
|
|||||||
if ((iter = childrenMap.find(object)) == childrenMap.end()) {
|
if ((iter = childrenMap.find(object)) == childrenMap.end()) {
|
||||||
// illegal table entry, should only happen due to misconfigured mode table
|
// illegal table entry, should only happen due to misconfigured mode table
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::debug << std::hex << getObjectId() << ": invalid mode table entry" << std::endl;
|
sif::debug << std::hex << SystemObject::getObjectId() << ": invalid mode table entry"
|
||||||
|
<< std::endl;
|
||||||
#endif
|
#endif
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -145,6 +126,20 @@ ReturnValue_t SubsystemBase::updateChildMode(MessageQueueId_t queue, Mode_t mode
|
|||||||
return CHILD_NOT_FOUND;
|
return CHILD_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReturnValue_t SubsystemBase::updateChildModeByObjId(object_id_t objectId, Mode_t mode,
|
||||||
|
Submode_t submode) {
|
||||||
|
std::map<object_id_t, ChildInfo>::iterator iter;
|
||||||
|
|
||||||
|
for (iter = childrenMap.begin(); iter != childrenMap.end(); iter++) {
|
||||||
|
if (iter->first == objectId) {
|
||||||
|
iter->second.mode = mode;
|
||||||
|
iter->second.submode = submode;
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CHILD_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
ReturnValue_t SubsystemBase::updateChildChangedHealth(MessageQueueId_t queue, bool changedHealth) {
|
ReturnValue_t SubsystemBase::updateChildChangedHealth(MessageQueueId_t queue, bool changedHealth) {
|
||||||
for (auto iter = childrenMap.begin(); iter != childrenMap.end(); iter++) {
|
for (auto iter = childrenMap.begin(); iter != childrenMap.end(); iter++) {
|
||||||
if (iter->second.commandQueue == queue) {
|
if (iter->second.commandQueue == queue) {
|
||||||
@ -158,36 +153,15 @@ ReturnValue_t SubsystemBase::updateChildChangedHealth(MessageQueueId_t queue, bo
|
|||||||
MessageQueueId_t SubsystemBase::getCommandQueue() const { return commandQueue->getId(); }
|
MessageQueueId_t SubsystemBase::getCommandQueue() const { return commandQueue->getId(); }
|
||||||
|
|
||||||
ReturnValue_t SubsystemBase::initialize() {
|
ReturnValue_t SubsystemBase::initialize() {
|
||||||
MessageQueueId_t parentQueue = MessageQueueIF::NO_QUEUE;
|
ReturnValue_t result = modeHelper.initialize();
|
||||||
ReturnValue_t result = SystemObject::initialize();
|
|
||||||
|
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
result = healthHelper.initialize();
|
||||||
if (parentId != objects::NO_OBJECT) {
|
|
||||||
SubsystemBase* parent = ObjectManager::instance()->get<SubsystemBase>(parentId);
|
|
||||||
if (parent == nullptr) {
|
|
||||||
return returnvalue::FAILED;
|
|
||||||
}
|
|
||||||
parentQueue = parent->getCommandQueue();
|
|
||||||
|
|
||||||
parent->registerChild(getObjectId());
|
|
||||||
}
|
|
||||||
|
|
||||||
result = healthHelper.initialize(parentQueue);
|
|
||||||
|
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
return SystemObject::initialize();
|
||||||
result = modeHelper.initialize(parentQueue);
|
|
||||||
|
|
||||||
if (result != returnvalue::OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
return returnvalue::OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t SubsystemBase::performOperation(uint8_t opCode) {
|
ReturnValue_t SubsystemBase::performOperation(uint8_t opCode) {
|
||||||
@ -240,8 +214,14 @@ ReturnValue_t SubsystemBase::handleModeReply(CommandMessage* message) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t SubsystemBase::checkTable(HybridIterator<ModeListEntry> tableIter) {
|
ReturnValue_t SubsystemBase::checkTable(HybridIterator<ModeListEntry> tableIter) {
|
||||||
for (; tableIter.value != NULL; ++tableIter) {
|
for (; tableIter.value != nullptr; ++tableIter) {
|
||||||
if (childrenMap.find(tableIter.value->getObject()) == childrenMap.end()) {
|
if (childrenMap.find(tableIter.value->getObject()) == childrenMap.end()) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
using namespace std;
|
||||||
|
sif::warning << "SubsystemBase::checkTable: Could not find object " << setfill('0') << hex
|
||||||
|
<< "0x" << setw(8) << tableIter.value->getObject() << " in object " << setw(8)
|
||||||
|
<< setw(0) << "0x" << setw(8) << SystemObject::getObjectId() << dec << std::endl;
|
||||||
|
#endif
|
||||||
return TABLE_CONTAINS_INVALID_OBJECT_ID;
|
return TABLE_CONTAINS_INVALID_OBJECT_ID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -326,4 +306,33 @@ ReturnValue_t SubsystemBase::setHealth(HealthState health) {
|
|||||||
|
|
||||||
HasHealthIF::HealthState SubsystemBase::getHealth() { return healthHelper.getHealth(); }
|
HasHealthIF::HealthState SubsystemBase::getHealth() { return healthHelper.getHealth(); }
|
||||||
|
|
||||||
|
ReturnValue_t SubsystemBase::connectModeTreeParent(HasModeTreeChildrenIF& parent) {
|
||||||
|
return modetree::connectModeTreeParent(parent, *this, &healthHelper, modeHelper);
|
||||||
|
}
|
||||||
|
|
||||||
|
object_id_t SubsystemBase::getObjectId() const { return SystemObject::getObjectId(); }
|
||||||
|
|
||||||
void SubsystemBase::modeChanged() {}
|
void SubsystemBase::modeChanged() {}
|
||||||
|
|
||||||
|
ReturnValue_t SubsystemBase::registerChild(const ModeTreeChildIF& child) {
|
||||||
|
ChildInfo info;
|
||||||
|
|
||||||
|
const HasModesIF& modeChild = child.getModeIF();
|
||||||
|
// intentional to force an initial command during system startup
|
||||||
|
info.commandQueue = modeChild.getCommandQueue();
|
||||||
|
info.mode = HasModesIF::MODE_UNDEFINED;
|
||||||
|
info.submode = SUBMODE_NONE;
|
||||||
|
info.healthChanged = false;
|
||||||
|
|
||||||
|
auto resultPair = childrenMap.emplace(child.getObjectId(), info);
|
||||||
|
if (not resultPair.second) {
|
||||||
|
return COULD_NOT_INSERT_CHILD;
|
||||||
|
}
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
const HasHealthIF* SubsystemBase::getOptHealthIF() const { return this; }
|
||||||
|
|
||||||
|
const HasModesIF& SubsystemBase::getModeIF() const { return *this; }
|
||||||
|
|
||||||
|
ModeTreeChildIF& SubsystemBase::getModeTreeChildIF() { return *this; }
|
||||||
|
@ -3,14 +3,16 @@
|
|||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include "../container/HybridIterator.h"
|
#include "fsfw/container/HybridIterator.h"
|
||||||
#include "../health/HasHealthIF.h"
|
#include "fsfw/health/HasHealthIF.h"
|
||||||
#include "../health/HealthHelper.h"
|
#include "fsfw/health/HealthHelper.h"
|
||||||
#include "../ipc/MessageQueueIF.h"
|
#include "fsfw/ipc/MessageQueueIF.h"
|
||||||
#include "../modes/HasModesIF.h"
|
#include "fsfw/modes/HasModesIF.h"
|
||||||
#include "../objectmanager/SystemObject.h"
|
#include "fsfw/objectmanager/SystemObject.h"
|
||||||
#include "../returnvalues/returnvalue.h"
|
#include "fsfw/returnvalues/returnvalue.h"
|
||||||
#include "../tasks/ExecutableObjectIF.h"
|
#include "fsfw/subsystem/HasModeTreeChildrenIF.h"
|
||||||
|
#include "fsfw/subsystem/ModeTreeConnectionIF.h"
|
||||||
|
#include "fsfw/tasks/ExecutableObjectIF.h"
|
||||||
#include "modes/HasModeSequenceIF.h"
|
#include "modes/HasModeSequenceIF.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -27,6 +29,9 @@
|
|||||||
class SubsystemBase : public SystemObject,
|
class SubsystemBase : public SystemObject,
|
||||||
public HasModesIF,
|
public HasModesIF,
|
||||||
public HasHealthIF,
|
public HasHealthIF,
|
||||||
|
public HasModeTreeChildrenIF,
|
||||||
|
public ModeTreeConnectionIF,
|
||||||
|
public ModeTreeChildIF,
|
||||||
public ExecutableObjectIF {
|
public ExecutableObjectIF {
|
||||||
public:
|
public:
|
||||||
static const uint8_t INTERFACE_ID = CLASS_ID::SUBSYSTEM_BASE;
|
static const uint8_t INTERFACE_ID = CLASS_ID::SUBSYSTEM_BASE;
|
||||||
@ -36,32 +41,34 @@ class SubsystemBase : public SystemObject,
|
|||||||
static const ReturnValue_t COULD_NOT_INSERT_CHILD = MAKE_RETURN_CODE(0x04);
|
static const ReturnValue_t COULD_NOT_INSERT_CHILD = MAKE_RETURN_CODE(0x04);
|
||||||
static const ReturnValue_t TABLE_CONTAINS_INVALID_OBJECT_ID = MAKE_RETURN_CODE(0x05);
|
static const ReturnValue_t TABLE_CONTAINS_INVALID_OBJECT_ID = MAKE_RETURN_CODE(0x05);
|
||||||
|
|
||||||
SubsystemBase(object_id_t setObjectId, object_id_t parent, Mode_t initialMode = 0,
|
SubsystemBase(object_id_t setObjectId, Mode_t initialMode = 0, uint16_t commandQueueDepth = 8);
|
||||||
uint16_t commandQueueDepth = 8);
|
|
||||||
virtual ~SubsystemBase();
|
virtual ~SubsystemBase();
|
||||||
|
|
||||||
virtual MessageQueueId_t getCommandQueue() const override;
|
virtual MessageQueueId_t getCommandQueue() const override;
|
||||||
|
|
||||||
|
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF &parent) override;
|
||||||
|
ModeTreeChildIF &getModeTreeChildIF() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function to register the child objects.
|
* Function to register the child objects.
|
||||||
* Performs a checks if the child does implement HasHealthIF and/or HasModesIF
|
* Performs a checks if the child does implement HasHealthIF and/or HasModesIF
|
||||||
*
|
*
|
||||||
* Also adds them to the internal childrenMap.
|
* Also adds them to the internal childrenMap.
|
||||||
*
|
*
|
||||||
* @param objectId
|
* @param objectId
|
||||||
* @return returnvalue::OK if successful
|
* @return returnvalue::OK if successful
|
||||||
* CHILD_DOESNT_HAVE_MODES if Child is no HasHealthIF and no HasModesIF
|
* CHILD_DOESNT_HAVE_MODES if Child is no HasHealthIF and no HasModesIF
|
||||||
* COULD_NOT_INSERT_CHILD If the Child could not be added to the ChildrenMap
|
* COULD_NOT_INSERT_CHILD If the Child could not be added to the ChildrenMap
|
||||||
*/
|
*/
|
||||||
ReturnValue_t registerChild(object_id_t objectId);
|
ReturnValue_t registerChild(const ModeTreeChildIF &child) override;
|
||||||
|
|
||||||
virtual ReturnValue_t initialize() override;
|
ReturnValue_t initialize() override;
|
||||||
|
|
||||||
virtual ReturnValue_t performOperation(uint8_t opCode) override;
|
ReturnValue_t performOperation(uint8_t opCode) override;
|
||||||
|
|
||||||
virtual ReturnValue_t setHealth(HealthState health) override;
|
ReturnValue_t setHealth(HealthState health) override;
|
||||||
|
|
||||||
virtual HasHealthIF::HealthState getHealth() override;
|
HasHealthIF::HealthState getHealth() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct ChildInfo {
|
struct ChildInfo {
|
||||||
@ -88,8 +95,6 @@ class SubsystemBase : public SystemObject,
|
|||||||
|
|
||||||
ModeHelper modeHelper;
|
ModeHelper modeHelper;
|
||||||
|
|
||||||
const object_id_t parentId;
|
|
||||||
|
|
||||||
typedef std::map<object_id_t, ChildInfo> ChildrenMap;
|
typedef std::map<object_id_t, ChildInfo> ChildrenMap;
|
||||||
ChildrenMap childrenMap;
|
ChildrenMap childrenMap;
|
||||||
|
|
||||||
@ -110,6 +115,7 @@ class SubsystemBase : public SystemObject,
|
|||||||
Submode_t targetSubmode = SUBMODE_NONE);
|
Submode_t targetSubmode = SUBMODE_NONE);
|
||||||
|
|
||||||
ReturnValue_t updateChildMode(MessageQueueId_t queue, Mode_t mode, Submode_t submode);
|
ReturnValue_t updateChildMode(MessageQueueId_t queue, Mode_t mode, Submode_t submode);
|
||||||
|
ReturnValue_t updateChildModeByObjId(object_id_t objectId, Mode_t mode, Submode_t submode);
|
||||||
|
|
||||||
ReturnValue_t updateChildChangedHealth(MessageQueueId_t queue, bool changedHealth = true);
|
ReturnValue_t updateChildChangedHealth(MessageQueueId_t queue, bool changedHealth = true);
|
||||||
|
|
||||||
@ -136,6 +142,10 @@ class SubsystemBase : public SystemObject,
|
|||||||
|
|
||||||
virtual void getMode(Mode_t *mode, Submode_t *submode) override;
|
virtual void getMode(Mode_t *mode, Submode_t *submode) override;
|
||||||
|
|
||||||
|
object_id_t getObjectId() const override;
|
||||||
|
const HasHealthIF *getOptHealthIF() const override;
|
||||||
|
const HasModesIF &getModeIF() const override;
|
||||||
|
|
||||||
virtual void setToExternalControl() override;
|
virtual void setToExternalControl() override;
|
||||||
|
|
||||||
virtual void announceMode(bool recursive) override;
|
virtual void announceMode(bool recursive) override;
|
||||||
|
15
src/fsfw/subsystem/helper.cpp
Normal file
15
src/fsfw/subsystem/helper.cpp
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#include "helper.h"
|
||||||
|
|
||||||
|
ReturnValue_t modetree::connectModeTreeParent(HasModeTreeChildrenIF& parent,
|
||||||
|
const ModeTreeChildIF& child,
|
||||||
|
HealthHelper* healthHelper, ModeHelper& modeHelper) {
|
||||||
|
ReturnValue_t result = parent.registerChild(child);
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (healthHelper != nullptr) {
|
||||||
|
healthHelper->setParentQueue(parent.getCommandQueue());
|
||||||
|
}
|
||||||
|
modeHelper.setParentQueue(parent.getCommandQueue());
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
14
src/fsfw/subsystem/helper.h
Normal file
14
src/fsfw/subsystem/helper.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#ifndef FSFW_SUBSYSTEM_HELPER_H_
|
||||||
|
#define FSFW_SUBSYSTEM_HELPER_H_
|
||||||
|
|
||||||
|
#include "HasModeTreeChildrenIF.h"
|
||||||
|
#include "fsfw/health/HealthHelper.h"
|
||||||
|
|
||||||
|
namespace modetree {
|
||||||
|
|
||||||
|
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF& parent, const ModeTreeChildIF& child,
|
||||||
|
HealthHelper* healthHelper, ModeHelper& modeHelper);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* FSFW_SRC_FSFW_SUBSYSTEM_HELPER_H_ */
|
@ -1,111 +1,126 @@
|
|||||||
#ifndef FSFW_SUBSYSTEM_MODES_MODEDEFINITIONS_H_
|
#ifndef FSFW_SUBSYSTEM_MODES_MODEDEFINITIONS_H_
|
||||||
#define FSFW_SUBSYSTEM_MODES_MODEDEFINITIONS_H_
|
#define FSFW_SUBSYSTEM_MODES_MODEDEFINITIONS_H_
|
||||||
|
|
||||||
#include "../../modes/HasModesIF.h"
|
#include "fsfw/modes/HasModesIF.h"
|
||||||
#include "../../objectmanager/SystemObjectIF.h"
|
#include "fsfw/objectmanager/SystemObjectIF.h"
|
||||||
#include "../../serialize/SerialLinkedListAdapter.h"
|
#include "fsfw/serialize/SerialLinkedListAdapter.h"
|
||||||
#include "../../serialize/SerializeIF.h"
|
#include "fsfw/serialize/SerializeIF.h"
|
||||||
|
|
||||||
class ModeListEntry : public SerializeIF, public LinkedElement<ModeListEntry> {
|
namespace mode {
|
||||||
|
enum SpecialSubmodeFlags : uint8_t { INHERIT = 1 << 0, ALLOWED_MASK = 1 << 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
class ModeListEntry : public SerialLinkedListAdapter<SerializeIF>,
|
||||||
|
public LinkedElement<ModeListEntry> {
|
||||||
public:
|
public:
|
||||||
ModeListEntry() : LinkedElement<ModeListEntry>(this) {}
|
static constexpr uint8_t ALL_SUBMODES_ALLOWED_MASK = 0xff;
|
||||||
|
|
||||||
uint32_t value1 = 0;
|
ModeListEntry() : SerialLinkedListAdapter(), LinkedElement<ModeListEntry>(this) { setLinks(); }
|
||||||
uint32_t value2 = 0;
|
|
||||||
uint8_t value3 = 0;
|
|
||||||
uint8_t value4 = 0;
|
|
||||||
|
|
||||||
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
SerializeElement<uint32_t> value1 = 0;
|
||||||
Endianness streamEndianness) const {
|
SerializeElement<uint32_t> value2 = 0;
|
||||||
ReturnValue_t result;
|
SerializeElement<uint8_t> value3 = 0;
|
||||||
|
SerializeElement<uint8_t> value4 = 0;
|
||||||
|
SerializeElement<uint8_t> value5 = 0;
|
||||||
|
|
||||||
result = SerializeAdapter::serialize(&value1, buffer, size, maxSize, streamEndianness);
|
ModeListEntry(const ModeListEntry& other)
|
||||||
|
: SerialLinkedListAdapter(), LinkedElement<ModeListEntry>(this) {
|
||||||
if (result != returnvalue::OK) {
|
value1.entry = other.value1.entry;
|
||||||
return result;
|
value2.entry = other.value2.entry;
|
||||||
}
|
value3.entry = other.value3.entry;
|
||||||
result = SerializeAdapter::serialize(&value2, buffer, size, maxSize, streamEndianness);
|
value4.entry = other.value4.entry;
|
||||||
|
value5.entry = other.value5.entry;
|
||||||
if (result != returnvalue::OK) {
|
setLinks();
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result = SerializeAdapter::serialize(&value3, buffer, size, maxSize, streamEndianness);
|
|
||||||
|
|
||||||
if (result != returnvalue::OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = SerializeAdapter::serialize(&value4, buffer, size, maxSize, streamEndianness);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual size_t getSerializedSize() const {
|
ModeListEntry& operator=(const ModeListEntry& other) {
|
||||||
return sizeof(value1) + sizeof(value2) + sizeof(value3) + sizeof(value4);
|
this->value1.entry = other.value1.entry;
|
||||||
|
this->value2.entry = other.value2.entry;
|
||||||
|
this->value3.entry = other.value3.entry;
|
||||||
|
this->value4.entry = other.value4.entry;
|
||||||
|
this->value5.entry = other.value5.entry;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
void setLinks() {
|
||||||
Endianness streamEndianness) {
|
setStart(&value1);
|
||||||
ReturnValue_t result;
|
value1.setNext(&value2);
|
||||||
|
value2.setNext(&value3);
|
||||||
result = SerializeAdapter::deSerialize(&value1, buffer, size, streamEndianness);
|
value3.setNext(&value4);
|
||||||
|
value4.setNext(&value5);
|
||||||
if (result != returnvalue::OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result = SerializeAdapter::deSerialize(&value2, buffer, size, streamEndianness);
|
|
||||||
|
|
||||||
if (result != returnvalue::OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result = SerializeAdapter::deSerialize(&value3, buffer, size, streamEndianness);
|
|
||||||
|
|
||||||
if (result != returnvalue::OK) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result = SerializeAdapter::deSerialize(&value4, buffer, size, streamEndianness);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// for Sequences
|
// for Sequences
|
||||||
Mode_t getTableId() const { return value1; }
|
Mode_t getTableId() const { return value1.entry; }
|
||||||
|
|
||||||
void setTableId(Mode_t tableId) { this->value1 = tableId; }
|
void setTableId(Mode_t tableId) { this->value1.entry = tableId; }
|
||||||
|
|
||||||
uint8_t getWaitSeconds() const { return value2; }
|
uint8_t getWaitSeconds() const { return value2.entry; }
|
||||||
|
|
||||||
void setWaitSeconds(uint8_t waitSeconds) { this->value2 = waitSeconds; }
|
void setWaitSeconds(uint8_t waitSeconds) { this->value2.entry = waitSeconds; }
|
||||||
|
|
||||||
bool checkSuccess() const { return value3 == 1; }
|
bool checkSuccess() const { return value3.entry == 1; }
|
||||||
|
|
||||||
void setCheckSuccess(bool checkSuccess) { this->value3 = checkSuccess; }
|
void setCheckSuccess(bool checkSuccess) { this->value3.entry = checkSuccess; }
|
||||||
|
|
||||||
// for Tables
|
// for Tables
|
||||||
object_id_t getObject() const { return value1; }
|
object_id_t getObject() const { return value1.entry; }
|
||||||
|
|
||||||
void setObject(object_id_t object) { this->value1 = object; }
|
void setObject(object_id_t object) { this->value1.entry = object; }
|
||||||
|
|
||||||
Mode_t getMode() const { return value2; }
|
Mode_t getMode() const { return value2.entry; }
|
||||||
|
|
||||||
void setMode(Mode_t mode) { this->value2 = mode; }
|
void setMode(Mode_t mode) { this->value2.entry = mode; }
|
||||||
|
|
||||||
Submode_t getSubmode() const { return value3; }
|
Submode_t getSubmode() const { return value3.entry; }
|
||||||
|
|
||||||
void setSubmode(Submode_t submode) { this->value3 = submode; }
|
void setSubmode(Submode_t submode) { this->value3.entry = submode; }
|
||||||
|
|
||||||
bool inheritSubmode() const { return value4 == 1; }
|
bool inheritSubmode() const {
|
||||||
|
return (value4.entry & mode::SpecialSubmodeFlags::INHERIT) ==
|
||||||
void setInheritSubmode(bool inherit) {
|
mode::SpecialSubmodeFlags::INHERIT;
|
||||||
if (inherit) {
|
}
|
||||||
value4 = 1;
|
bool submodesAllowed(uint8_t* mask) const {
|
||||||
} else {
|
bool submodesAllowed = (value4.entry & mode::SpecialSubmodeFlags::ALLOWED_MASK) ==
|
||||||
value4 = 0;
|
mode::SpecialSubmodeFlags::ALLOWED_MASK;
|
||||||
|
if (submodesAllowed and mask != nullptr) {
|
||||||
|
*mask = value5.entry;
|
||||||
}
|
}
|
||||||
|
return submodesAllowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(ModeListEntry other) {
|
/**
|
||||||
return ((value1 == other.value1) && (value2 == other.value2) && (value3 == other.value3));
|
* Enable the inheritance of submodes. This is relevant for both the execution
|
||||||
|
* of mode tables and for mode checking.
|
||||||
|
*/
|
||||||
|
void enableInheritSubmode() { value4.entry |= mode::SpecialSubmodeFlags::INHERIT; }
|
||||||
|
/**
|
||||||
|
* Disable the inheritance of submodes. This is relevant for both the execution
|
||||||
|
* of mode tables and for mode checking.
|
||||||
|
*/
|
||||||
|
void disableInheritSubmode() { value4.entry &= ~mode::SpecialSubmodeFlags::INHERIT; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specialization of @enableSubmodeAllowed which allows all submodes.
|
||||||
|
*/
|
||||||
|
void allowAllSubmodes() { enableSubmodeAllowed(ALL_SUBMODES_ALLOWED_MASK); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable an allowed submode mask for mode checks. Any submode which contains bits
|
||||||
|
* outside of the mask will be declined.
|
||||||
|
*
|
||||||
|
* For example, for a mask of 0b11, only the modes 0b00, 0b01 and 0b11 will be accepted.
|
||||||
|
*/
|
||||||
|
void enableSubmodeAllowed(uint8_t mask) {
|
||||||
|
value4.entry |= mode::SpecialSubmodeFlags::ALLOWED_MASK;
|
||||||
|
value5.entry = mask;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Enforce the equality of submodes for mode checks. This is the default.
|
||||||
|
*/
|
||||||
|
void disableSubmodeAllowed() {
|
||||||
|
value4.entry &= ~mode::SpecialSubmodeFlags::ALLOWED_MASK;
|
||||||
|
value5.entry = 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -15,10 +15,10 @@ ReturnValue_t FixedTimeslotTaskBase::addSlot(object_id_t execId, ExecutableObjec
|
|||||||
uint32_t slotTimeMs, int8_t executionStep) {
|
uint32_t slotTimeMs, int8_t executionStep) {
|
||||||
if (execObj == nullptr) {
|
if (execObj == nullptr) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "Component 0x" << std::hex << std::setw(8) << std::setfill('0') << execObj
|
sif::error << "Component 0x" << std::hex << std::setw(8) << std::setfill('0') << execId
|
||||||
<< std::setfill(' ') << " not found, not adding it to PST" << std::dec << std::endl;
|
<< std::setfill(' ') << " not found, not adding it to PST" << std::dec << std::endl;
|
||||||
#else
|
#else
|
||||||
sif::printError("Component 0x%08x not found, not adding it to PST\n");
|
sif::printError("Component 0x%08x not found, not adding it to PST\n", execId);
|
||||||
#endif
|
#endif
|
||||||
return returnvalue::FAILED;
|
return returnvalue::FAILED;
|
||||||
}
|
}
|
||||||
|
@ -283,7 +283,7 @@ ReturnValue_t Heater::getParameter(uint8_t domainId, uint8_t uniqueId,
|
|||||||
}
|
}
|
||||||
switch (uniqueId) {
|
switch (uniqueId) {
|
||||||
case 0:
|
case 0:
|
||||||
parameterWrapper->set(heaterOnCountdown.timeout);
|
parameterWrapper->set(heaterOnCountdown.getTimeoutMs());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return INVALID_IDENTIFIER_ID;
|
return INVALID_IDENTIFIER_ID;
|
||||||
|
@ -246,6 +246,20 @@ ReturnValue_t CCSDSTime::convertFromASCII(Clock::TimeOfDay_t* to, const uint8_t*
|
|||||||
return UNSUPPORTED_TIME_FORMAT;
|
return UNSUPPORTED_TIME_FORMAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReturnValue_t CCSDSTime::convertToAsciiWithSecs(int8_t* to, const Clock::TimeOfDay_t* from,
|
||||||
|
uint8_t length) {
|
||||||
|
if (from == nullptr or to == nullptr) {
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
int count = snprintf(reinterpret_cast<char*>(to), length,
|
||||||
|
"%4" SCNu32 "-%2" SCNu32 "-%2" SCNu32 "T%2" SCNu32 ":%2" SCNu32 ":%2" SCNu32,
|
||||||
|
from->year, from->month, from->day, from->hour, from->minute, from->second);
|
||||||
|
if (count >= length) {
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
|
||||||
ReturnValue_t CCSDSTime::checkCcs(const uint8_t* time, uint8_t length) {
|
ReturnValue_t CCSDSTime::checkCcs(const uint8_t* time, uint8_t length) {
|
||||||
const Ccs_mseconds* time_struct = reinterpret_cast<const Ccs_mseconds*>(time);
|
const Ccs_mseconds* time_struct = reinterpret_cast<const Ccs_mseconds*>(time);
|
||||||
|
|
||||||
|
@ -207,7 +207,8 @@ class CCSDSTime {
|
|||||||
|
|
||||||
static ReturnValue_t convertFromASCII(Clock::TimeOfDay_t *to, uint8_t const *from,
|
static ReturnValue_t convertFromASCII(Clock::TimeOfDay_t *to, uint8_t const *from,
|
||||||
uint8_t length);
|
uint8_t length);
|
||||||
|
static ReturnValue_t convertToAsciiWithSecs(int8_t *to, const Clock::TimeOfDay_t *from,
|
||||||
|
uint8_t length);
|
||||||
static uint32_t subsecondsToMicroseconds(uint16_t subseconds);
|
static uint32_t subsecondsToMicroseconds(uint16_t subseconds);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
#include "fsfw/timemanager/Clock.h"
|
#include "fsfw/timemanager/Clock.h"
|
||||||
|
|
||||||
|
CdsShortTimeStamper::CdsShortTimeStamper() : SystemObject(0, false) {}
|
||||||
|
|
||||||
CdsShortTimeStamper::CdsShortTimeStamper(object_id_t objectId) : SystemObject(objectId) {}
|
CdsShortTimeStamper::CdsShortTimeStamper(object_id_t objectId) : SystemObject(objectId) {}
|
||||||
|
|
||||||
ReturnValue_t CdsShortTimeStamper::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
ReturnValue_t CdsShortTimeStamper::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
class CdsShortTimeStamper : public TimeWriterIF, public TimeReaderIF, public SystemObject {
|
class CdsShortTimeStamper : public TimeWriterIF, public TimeReaderIF, public SystemObject {
|
||||||
public:
|
public:
|
||||||
static constexpr size_t TIMESTAMP_LEN = 7;
|
static constexpr size_t TIMESTAMP_LEN = 7;
|
||||||
|
CdsShortTimeStamper();
|
||||||
/**
|
/**
|
||||||
* @brief Default constructor which also registers the time stamper as a
|
* @brief Default constructor which also registers the time stamper as a
|
||||||
* system object so it can be found with the #objectManager.
|
* system object so it can be found with the #objectManager.
|
||||||
|
@ -49,6 +49,13 @@ class Clock {
|
|||||||
* @return -@c returnvalue::OK on success. Otherwise, the OS failure code is returned.
|
* @return -@c returnvalue::OK on success. Otherwise, the OS failure code is returned.
|
||||||
*/
|
*/
|
||||||
static ReturnValue_t setClock(const timeval *time);
|
static ReturnValue_t setClock(const timeval *time);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use getClock instead, which does the same.
|
||||||
|
* @param time
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
static ReturnValue_t getClock_timeval(timeval *time);
|
||||||
/**
|
/**
|
||||||
* This system call returns the current system clock in timeval format.
|
* This system call returns the current system clock in timeval format.
|
||||||
* The timval format has the fields @c tv_sec with seconds and @c tv_usec with
|
* The timval format has the fields @c tv_sec with seconds and @c tv_usec with
|
||||||
@ -56,7 +63,18 @@ class Clock {
|
|||||||
* @param time A pointer to a timeval struct where the current time is stored.
|
* @param time A pointer to a timeval struct where the current time is stored.
|
||||||
* @return @c returnvalue::OK on success. Otherwise, the OS failure code is returned.
|
* @return @c returnvalue::OK on success. Otherwise, the OS failure code is returned.
|
||||||
*/
|
*/
|
||||||
static ReturnValue_t getClock_timeval(timeval *time);
|
static ReturnValue_t getClock(timeval *time);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve a monotonic clock. This clock this is also more suited for measuring elapsed times
|
||||||
|
* between two time points, but less suited when the absolute time is required.
|
||||||
|
*
|
||||||
|
* Implementation example: A generic UNIX implementation can use CLOCK_MONOTONIC_RAW with
|
||||||
|
* `clock_gettime`.
|
||||||
|
* @param time
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
static ReturnValue_t getClockMonotonic(timeval *time);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the time since boot in a timeval struct
|
* Get the time since boot in a timeval struct
|
||||||
|
@ -1,49 +1,62 @@
|
|||||||
#include "fsfw/timemanager/Countdown.h"
|
#include "fsfw/timemanager/Countdown.h"
|
||||||
|
|
||||||
Countdown::Countdown(uint32_t initialTimeout, bool startImmediately) : timeout(initialTimeout) {
|
#include "fsfw/globalfunctions/timevalOperations.h"
|
||||||
|
|
||||||
|
Countdown::Countdown(uint32_t initialTimeout, bool startImmediately) {
|
||||||
if (startImmediately) {
|
if (startImmediately) {
|
||||||
setTimeout(initialTimeout);
|
setTimeout(initialTimeout);
|
||||||
} else {
|
} else {
|
||||||
timeout = initialTimeout;
|
timeout.tv_sec = initialTimeout / 1000;
|
||||||
|
timeout.tv_usec = (initialTimeout % 1000) * 1000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Countdown::~Countdown() {}
|
Countdown::~Countdown() = default;
|
||||||
|
|
||||||
ReturnValue_t Countdown::setTimeout(uint32_t milliseconds) {
|
ReturnValue_t Countdown::setTimeout(uint32_t milliseconds) {
|
||||||
ReturnValue_t returnValue = Clock::getUptime(&startTime);
|
timeout.tv_sec = milliseconds / 1000;
|
||||||
timeout = milliseconds;
|
timeout.tv_usec = (milliseconds % 1000) * 1000;
|
||||||
return returnValue;
|
return Clock::getClockMonotonic(&startTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Countdown::hasTimedOut() const {
|
bool Countdown::hasTimedOut() const {
|
||||||
if (uint32_t(this->getCurrentTime() - startTime) >= timeout) {
|
// Account for system clock going back in time.
|
||||||
|
if (getCurrentTime() < startTime) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
if (getCurrentTime() - startTime >= timeout) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Countdown::isBusy() const { return !hasTimedOut(); }
|
bool Countdown::isBusy() const { return !hasTimedOut(); }
|
||||||
|
|
||||||
ReturnValue_t Countdown::resetTimer() { return setTimeout(timeout); }
|
ReturnValue_t Countdown::resetTimer() { return setTimeoutTv(timeout); }
|
||||||
|
|
||||||
void Countdown::timeOut() { startTime = this->getCurrentTime() - timeout; }
|
void Countdown::timeOut() { startTime = this->getCurrentTime() - timeout; }
|
||||||
|
|
||||||
uint32_t Countdown::getRemainingMillis() const {
|
uint32_t Countdown::getRemainingMillis() const {
|
||||||
// We fetch the time before the if-statement
|
|
||||||
// to be sure that the return is in
|
|
||||||
// range 0 <= number <= timeout
|
|
||||||
uint32_t currentTime = this->getCurrentTime();
|
|
||||||
if (this->hasTimedOut()) {
|
if (this->hasTimedOut()) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
|
||||||
return (startTime + timeout) - currentTime;
|
|
||||||
}
|
}
|
||||||
|
timeval remainingMillisTv = (startTime + timeout) - this->getCurrentTime();
|
||||||
|
return remainingMillisTv.tv_sec * 1000 + remainingMillisTv.tv_usec / 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Countdown::getCurrentTime() const {
|
uint32_t Countdown::timevalToMs(timeval &tv) { return tv.tv_sec * 1000 + tv.tv_usec / 1000; }
|
||||||
uint32_t currentTime;
|
|
||||||
Clock::getUptime(¤tTime);
|
ReturnValue_t Countdown::setTimeoutTv(timeval tv) {
|
||||||
|
timeout = tv;
|
||||||
|
return Clock::getClockMonotonic(&startTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t Countdown::getTimeoutMs() const { return timeout.tv_sec * 1000 + timeout.tv_usec / 1000; }
|
||||||
|
|
||||||
|
timeval Countdown::getTimeout() const { return timeout; }
|
||||||
|
|
||||||
|
timeval Countdown::getCurrentTime() const {
|
||||||
|
timeval currentTime{};
|
||||||
|
Clock::getClockMonotonic(¤tTime);
|
||||||
return currentTime;
|
return currentTime;
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,10 @@
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Countdown keeps track of a timespan.
|
* Countdown keeps track of a timespan.
|
||||||
|
* This class uses the system clock internally to achieve
|
||||||
|
* a high resolution. This means that the API is only partially
|
||||||
|
* resistant against time jumps. The user must take care to account
|
||||||
|
* for time jumps in some from if this relevant.
|
||||||
*
|
*
|
||||||
* Countdown::resetTimer restarts the timer.
|
* Countdown::resetTimer restarts the timer.
|
||||||
* Countdown::setTimeout sets a new countdown duration and resets.
|
* Countdown::setTimeout sets a new countdown duration and resets.
|
||||||
@ -39,6 +43,8 @@ class Countdown {
|
|||||||
* @return Returnvalue from Clock::getUptime
|
* @return Returnvalue from Clock::getUptime
|
||||||
*/
|
*/
|
||||||
ReturnValue_t setTimeout(uint32_t milliseconds);
|
ReturnValue_t setTimeout(uint32_t milliseconds);
|
||||||
|
ReturnValue_t setTimeoutTv(timeval tv);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the countdown duration has passed.
|
* Returns true if the countdown duration has passed.
|
||||||
*
|
*
|
||||||
@ -61,22 +67,31 @@ class Countdown {
|
|||||||
* Returns the remaining milliseconds (0 if timeout)
|
* Returns the remaining milliseconds (0 if timeout)
|
||||||
*/
|
*/
|
||||||
uint32_t getRemainingMillis() const;
|
uint32_t getRemainingMillis() const;
|
||||||
|
|
||||||
|
uint32_t getTimeoutMs() const;
|
||||||
|
|
||||||
|
timeval getTimeout() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes hasTimedOut() return true
|
* Makes hasTimedOut() return true
|
||||||
*/
|
*/
|
||||||
void timeOut();
|
void timeOut();
|
||||||
/**
|
|
||||||
* Internal countdown duration in milliseconds
|
static inline uint32_t timevalToMs(timeval& tv);
|
||||||
*/
|
|
||||||
uint32_t timeout;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* Last time the timer was started (uptime)
|
* Start time of the countdown.
|
||||||
*/
|
*/
|
||||||
uint32_t startTime = 0;
|
timeval startTime{};
|
||||||
|
|
||||||
uint32_t getCurrentTime() const;
|
/**
|
||||||
|
* Timeout as timeval type. The countdown has timed out when the
|
||||||
|
* current time exceeds the start time plus the timeout.
|
||||||
|
*/
|
||||||
|
timeval timeout{};
|
||||||
|
|
||||||
|
timeval getCurrentTime() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_TIMEMANAGER_COUNTDOWN_H_ */
|
#endif /* FSFW_TIMEMANAGER_COUNTDOWN_H_ */
|
||||||
|
@ -9,10 +9,10 @@
|
|||||||
Stopwatch::Stopwatch(bool displayOnDestruction, StopwatchDisplayMode displayMode)
|
Stopwatch::Stopwatch(bool displayOnDestruction, StopwatchDisplayMode displayMode)
|
||||||
: displayOnDestruction(displayOnDestruction), displayMode(displayMode) {
|
: displayOnDestruction(displayOnDestruction), displayMode(displayMode) {
|
||||||
// Measures start time on initialization.
|
// Measures start time on initialization.
|
||||||
Clock::getUptime(&startTime);
|
Clock::getClockMonotonic(&startTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Stopwatch::start() { Clock::getUptime(&startTime); }
|
void Stopwatch::start() { Clock::getClockMonotonic(&startTime); }
|
||||||
|
|
||||||
dur_millis_t Stopwatch::stop(bool display) {
|
dur_millis_t Stopwatch::stop(bool display) {
|
||||||
stopInternal();
|
stopInternal();
|
||||||
@ -63,6 +63,6 @@ StopwatchDisplayMode Stopwatch::getDisplayMode() const { return displayMode; }
|
|||||||
|
|
||||||
void Stopwatch::stopInternal() {
|
void Stopwatch::stopInternal() {
|
||||||
timeval endTime;
|
timeval endTime;
|
||||||
Clock::getUptime(&endTime);
|
Clock::getClockMonotonic(&endTime);
|
||||||
elapsedTime = endTime - startTime;
|
elapsedTime = endTime - startTime;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#ifndef FSFW_TIMEMANAGER_TIMEREADERIF_H
|
#ifndef FSFW_TIMEMANAGER_TIMEREADERIF_H
|
||||||
#define FSFW_TIMEMANAGER_TIMEREADERIF_H
|
#define FSFW_TIMEMANAGER_TIMEREADERIF_H
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
#include "fsfw/platform.h"
|
#include "fsfw/platform.h"
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user