Compare commits

...

87 Commits

Author SHA1 Message Date
bd208038dd printout fixes 2023-02-22 15:45:39 +01:00
2efff4d2c5 missing include 2023-02-21 02:59:13 +01:00
c327985222 printout tweak 2023-02-20 15:02:00 +01:00
c8469ca647 a lot of bug potential here 2023-02-18 14:03:19 +01:00
2d6622b8b8 wtf is this interface 2023-02-18 13:51:24 +01:00
5f9eb01d94 better naming 2023-02-18 13:46:51 +01:00
3568bdbecf lets see if this fixes the issue 2023-02-18 13:45:49 +01:00
fcd84b59ae how the hell does this break anything 2023-02-18 13:37:39 +01:00
e3c968096b i2c small improvements 2023-02-18 13:07:38 +01:00
be015b4c66 service 11: cast to fix warning 2023-02-17 12:07:50 +01:00
a6d707a7db SubsystemBase: Add function to update child modes 2023-02-17 02:04:17 +01:00
fe41d73895 remove obsolete mode 2023-02-16 17:57:03 +01:00
9de6c4b3aa printout corrections 2023-02-14 14:33:02 +01:00
d256ede8c1 fix cppcheck lint 2023-02-14 10:33:22 +01:00
f0b8457ba2 bugfix for SPI
- Set transfer length to 0 for failed transfers
2023-02-13 13:51:52 +01:00
dac2d210b5 updates for thermal module in DHB 2023-02-13 00:36:54 +01:00
8b4f73a97b better error msg 2023-02-12 21:07:11 +01:00
7fae6cbd6d added missing CS unlock 2023-02-12 20:06:32 +01:00
d302ba7185 afmt 2023-02-10 13:51:16 +01:00
14a92b3d89 typo 2023-02-09 18:28:16 +01:00
e4fd424d66 Merge branch 'possible_tc_sched_fixes' into develop 2023-02-09 18:25:44 +01:00
341a66c265 changelog 2023-02-09 18:22:00 +01:00
b9b076aa4c logic error 2023-02-09 18:18:25 +01:00
d93486a340 that time margin check is possible broken 2023-02-09 18:18:05 +01:00
820a7f059c logic error 2023-02-09 18:13:58 +01:00
f4d188c36f that time margin check is possible broken 2023-02-09 18:12:43 +01:00
1841f92944 important bugfix for thermal set 2023-02-09 17:17:42 +01:00
b279985859 refactor DHB: Bugfix for thermal module 2023-02-09 16:42:38 +01:00
fa7675897d Merge pull request 'Mode Service Bugfixes' (#736) from eive/fsfw:mode_service_fixes into development
Reviewed-on: fsfw/fsfw#736
2023-02-09 15:56:26 +01:00
3a2393885f more style 2023-02-09 15:44:39 +01:00
c752b6d143 Merge pull request 'Generic TMTC Bridge Update' (#734) from eive/fsfw:tmtcbridge_tweaks into development
Reviewed-on: fsfw/fsfw#734
2023-02-09 15:37:35 +01:00
b676040c7c Merge pull request 'CMakeLists file updates' (#731) from eive/fsfw:cmakelists_update into development
Reviewed-on: fsfw/fsfw#731
2023-02-09 15:29:46 +01:00
010509efb4 removed unneeded find_package parameter for etl 2023-02-09 13:50:16 +01:00
dfb1633f00 Merge branch 'development' into mode_service_fixes 2023-02-09 13:46:19 +01:00
5f7172e130 Merge pull request 'TCP/IP TMTC bridge memory leak fixes' (#737) from eive/fsfw:possible_tcpip_bridge_fixes into development
Reviewed-on: fsfw/fsfw#737
2023-02-09 12:15:45 +01:00
0c6465cd95 Merge pull request 'time stamper empty ctor' (#730) from eive/fsfw:empty_cds_short_ctor into development
Reviewed-on: fsfw/fsfw#730
2023-02-09 11:45:49 +01:00
f94987c46d Merge pull request 'RM3100 important bugfix' (#733) from eive/fsfw:rm3100_fixes into development
Reviewed-on: fsfw/fsfw#733
2023-02-09 11:41:53 +01:00
1809ce359b Merge pull request 'comment tweak to event parser can read everything' (#732) from eive/fsfw:health_if_update into development
Reviewed-on: fsfw/fsfw#732
2023-02-09 11:39:53 +01:00
8c712441ab Making fetch Catch2 quiet as well. 2023-02-09 11:34:58 +01:00
6ce80ea6c5 Merge branch 'possible_tcpip_bridge_fixes' into develop 2023-02-08 21:27:26 +01:00
f1b0ca7cff add PR link 2023-02-08 21:26:37 +01:00
000df85556 bump changelog 2023-02-08 21:24:00 +01:00
1fffcc2229 possiible leak fixes 2023-02-08 21:23:21 +01:00
6f05d6b7b0 possiible leak fixes 2023-02-08 20:38:32 +01:00
a419806a05 Merge remote-tracking branch 'upstream/development' into mode_service_fixes 2023-02-08 09:33:13 +01:00
84bbef0167 make it consistent 2023-02-08 09:27:14 +01:00
88b2b0e005 Merge branch 'mode_service_fixes' into develop 2023-02-08 09:26:38 +01:00
6445debfa1 bump changelog 2023-02-08 09:24:55 +01:00
8014e4adf9 mode service fixes 2023-02-08 09:23:48 +01:00
84dc7ac0ce bump changelog 2023-02-08 01:31:32 +01:00
ec12ab5daa mode service fixes 2023-02-08 01:20:28 +01:00
134d908f26 that stuff is not in upstream yet.. 2023-02-07 12:52:18 +01:00
40a9e12416 1000 is a bit much 2023-02-07 12:47:40 +01:00
f39054edd4 introduce warning switch 2023-02-07 12:45:29 +01:00
5adf89b911 changelog update 2023-02-07 12:41:42 +01:00
c2e6a22dec important bugfix for RM3100 2023-02-07 12:39:43 +01:00
c8e065a713 comment tweak to event parser can read everything 2023-02-07 12:36:42 +01:00
69c94645df add back HAL section 2023-02-07 12:36:01 +01:00
37e850c5a7 use upstream changelog 2023-02-07 12:31:19 +01:00
3ed49dbae3 Merge remote-tracking branch 'upstream/development' into empty_cds_short_ctor 2023-02-07 12:24:02 +01:00
4cf52d5dfe Merge pull request 'Time Service 9 update' (#726) from eive/fsfw:updates_fixes_pus_time_service into development
Reviewed-on: fsfw/fsfw#726
2023-02-07 12:19:45 +01:00
2646707d3f Merge branch 'cmakelists_update' into develop 2023-02-07 12:18:49 +01:00
539d7aac9e suppress error if ETL is not found 2023-02-07 12:17:03 +01:00
0a23f2c85a correction for printout, add prefix 2023-02-07 12:15:44 +01:00
06e30684fe Merge remote-tracking branch 'upstream/development' into develop 2023-02-07 12:14:31 +01:00
46230e6c6d Merge remote-tracking branch 'upstream/development' into updates_fixes_pus_time_service 2023-02-07 12:11:29 +01:00
b22d439300 bump changelog 2023-02-07 12:10:11 +01:00
7e7b3bbbc9 time stamper empty ctor 2023-02-07 12:07:41 +01:00
e2b66df72e Merge pull request 'various fixes related to linux Unittests and memory leaks' (#715) from eive/fsfw:unittest_fix_semaphore into development
Reviewed-on: fsfw/fsfw#715
2023-02-06 16:30:37 +01:00
7b828f233a Merge pull request 'I2C Linux: remove duplicate printout' (#718) from eive/fsfw:i2c_remove_duplicate_printout into development
Reviewed-on: fsfw/fsfw#718
2023-02-06 14:54:58 +01:00
c3d1000cd5 Merge branch 'development' into unittest_fix_semaphore 2023-02-06 14:46:45 +01:00
8e0e57714d Merge pull request 'allow using SO_REUSEADDR and SO_REUSEPORT on TCP server' (#722) from eive/fsfw:tcp_server_reuseaddr_reusesocket into development
Reviewed-on: fsfw/fsfw#722
2023-02-06 14:45:40 +01:00
cc9e54ea6b Merge pull request 'improve srv20 error messages' (#723) from eive/fsfw:srv20_error_msgs into development
Reviewed-on: fsfw/fsfw#723
2023-02-06 14:37:26 +01:00
31465a4e0f Merge pull request 'MGM: small tweak, gain factor was always them same' (#724) from eive/fsfw:mgm_handler_small_fix into development
Reviewed-on: fsfw/fsfw#724
2023-02-06 14:36:34 +01:00
c0e5d1eb99 Merge branch 'development' into tcp_server_reuseaddr_reusesocket 2023-02-06 14:34:52 +01:00
3bc5d4a2e0 Merge remote-tracking branch 'upstream/development' into mgm_handler_small_fix 2023-02-06 14:25:33 +01:00
b1e9dd9e4a Merge remote-tracking branch 'upstream/development' into updates_fixes_pus_time_service 2023-02-06 14:24:38 +01:00
ab86599db3 Merge pull request 'Bugfix DHB setNormalDatapoolEntriesInvalid' (#728) from eive/fsfw:bugfix_dhb_set_datapool_entries_invalid into development
Reviewed-on: fsfw/fsfw#728
2023-02-06 14:20:34 +01:00
034eb34c2e small tweak 2023-02-03 16:05:50 +01:00
9b05e8f274 re-order fields in TcpConfig 2023-01-30 14:24:48 +01:00
eb223dae88 bump changelog 2023-01-30 14:20:28 +01:00
3656662d88 small tweak, gain factory was always them same 2023-01-30 14:18:03 +01:00
fe71978467 improve srv20 error messages 2023-01-30 14:15:37 +01:00
b646717a76 bump changelog 2023-01-30 14:11:00 +01:00
99d8c845f2 allow using SO_REUSEADDR and SO_REUSEPORT on TCP server 2023-01-30 14:07:41 +01:00
ba62c28b64 adding linux ci and fixing problems 2023-01-12 15:40:52 +01:00
7adb47aecb remove duplicate printout 2023-01-11 08:45:37 +01:00
46 changed files with 428 additions and 228 deletions

View File

@@ -12,15 +12,26 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## Fixes
- 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.
- `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
- 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.
@@ -34,12 +45,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- `TcpTmTcServer.cpp`: The server was actually not able to handle
CCSDS packets which were clumped together. This has been fixed now.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/673
- `CServiceHealthCommanding`: Add announce all health info implementation
PR: https://egit.irs.uni-stuttgart.de/eive/fsfw/pulls/122
## Added
- `CServiceHealthCommanding`: Add announce all health info implementation
PR: https://egit.irs.uni-stuttgart.de/eive/fsfw/pulls/122
- Empty constructor for `CdsShortTimeStamper` which does not do an object manager registration.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/730
- `Service9TimeManagement`: Add `DUMP_TIME` (129) subservice.
- `TcpTmTcServer`: Allow setting the `SO_REUSEADDR` and `SO_REUSEPORT`
option on the TCP server. CTOR prototype has changed and expects an explicit
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.
@@ -117,6 +134,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
implementation without an extra component
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
## Changes
@@ -250,6 +277,7 @@ https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/593
- https://gitlab.kitware.com/cmake/cmake/-/issues/21696
Easiest solution for now: Keep this option OFF by default.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/616
- Linux HAL: Add wiretapping option for I2C. Enabled with `FSFW_HAL_I2C_WIRETAPPING` defined to 1
- Dedicated Version class and constant `fsfw::FSFW_VERSION` containing version information
inside `fsfw/version.h`
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/559
@@ -264,17 +292,6 @@ https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/593
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/590
- `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
- TCP TMTC Server: `MutexGuard` was not created properly in

View File

@@ -153,12 +153,12 @@ if(FSFW_BUILD_TESTS)
"${MSG_PREFIX} Building the FSFW unittests in addition to the static library"
)
# 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
if(NOT Catch2_FOUND)
message(
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)
@@ -196,13 +196,13 @@ message(
)
# 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
if(NOT ${FSFW_ETL_LIB_NAME}_FOUND)
message(
STATUS
"${MSG_PREFIX} No ETL installation was found with find_package. Installing and providing "
"etl with FindPackage")
"${MSG_PREFIX} ETL installation not found. Downloading ETL with FetchContent."
)
include(FetchContent)
FetchContent_Declare(

View File

@@ -1,45 +1,87 @@
pipeline {
environment {
BUILDDIR = 'cmake-build-tests'
BUILDDIR_HOST = 'cmake-build-tests-host'
BUILDDIR_LINUX = 'cmake-build-tests-linux'
DOCDDIR = 'cmake-build-documentation'
}
agent {
docker {
image 'fsfw-ci:d6'
args '--network host'
args '--network host --sysctl fs.mqueue.msg_max=100'
}
}
stages {
stage('Clean') {
steps {
sh 'rm -rf $BUILDDIR'
}
}
stage('Configure') {
steps {
dir(BUILDDIR) {
sh 'cmake -DFSFW_OSAL=host -DFSFW_BUILD_TESTS=ON -DFSFW_CICD_BUILD=ON ..'
stage('Host') {
stages{
stage('Clean') {
steps {
sh 'rm -rf $BUILDDIR_HOST'
}
}
stage('Configure') {
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') {
steps {
dir(BUILDDIR) {
sh 'cmake --build . -j4'
stage('Linux') {
stages{
stage('Clean') {
steps {
sh 'rm -rf $BUILDDIR_LINUX'
}
}
}
}
stage('Unittests') {
steps {
dir(BUILDDIR) {
sh 'cmake --build . -- fsfw-tests_coverage -j4'
stage('Configure') {
steps {
dir(BUILDDIR_LINUX) {
sh 'cmake -DFSFW_OSAL=linux -DFSFW_BUILD_TESTS=ON -DFSFW_CICD_BUILD=ON ..'
}
}
}
}
}
stage('Valgrind') {
steps {
dir(BUILDDIR) {
sh 'valgrind --leak-check=full --error-exitcode=1 ./fsfw-tests'
stage('Build') {
steps {
dir(BUILDDIR_LINUX) {
sh 'cmake --build . -j4'
}
}
}
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'
}
}
}
}
}

View File

@@ -58,12 +58,7 @@ void DeviceHandlerBase::setHkDestination(object_id_t hkDestination) {
this->hkDestination = hkDestination;
}
void DeviceHandlerBase::setThermalStateRequestPoolIds(lp_id_t thermalStatePoolId,
lp_id_t heaterRequestPoolId,
uint32_t thermalSetId) {
thermalSet =
new DeviceHandlerThermalSet(this, thermalSetId, thermalStatePoolId, heaterRequestPoolId);
}
void DeviceHandlerBase::enableThermalModule(ThermalStateCfg cfg) { this->thermalStateCfg = cfg; }
DeviceHandlerBase::~DeviceHandlerBase() {
if (comCookie != nullptr) {
@@ -227,12 +222,11 @@ ReturnValue_t DeviceHandlerBase::initialize() {
fillCommandAndReplyMap();
if (thermalSet != nullptr) {
PoolReadGuard pg(thermalSet);
// Set temperature target state to NON_OP.
result = thermalSet->read();
if (result == returnvalue::OK) {
if (pg.getReadResult() == returnvalue::OK) {
thermalSet->heaterRequest.value = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL;
thermalSet->heaterRequest.setValid(true);
thermalSet->commit();
}
}
@@ -382,7 +376,7 @@ void DeviceHandlerBase::doStateMachine() {
}
ReturnValue_t switchState = getStateOfSwitches();
if ((switchState == PowerSwitchIF::SWITCH_OFF) || (switchState == NO_SWITCH)) {
setMode(_MODE_SWITCH_IS_OFF);
setMode(MODE_OFF, SUBMODE_NONE);
}
} break;
case MODE_OFF:
@@ -395,9 +389,6 @@ void DeviceHandlerBase::doStateMachine() {
case MODE_NORMAL:
case MODE_ERROR_ON:
break;
case _MODE_SWITCH_IS_OFF:
setMode(MODE_OFF, SUBMODE_NONE);
break;
default:
triggerEvent(OBJECT_IN_INVALID_MODE, mode, submode);
setMode(_MODE_POWER_DOWN, 0);
@@ -594,12 +585,12 @@ void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) {
Clock::getUptime(&timeoutStart);
if (mode == MODE_OFF and thermalSet != nullptr) {
ReturnValue_t result = thermalSet->read();
if (result == returnvalue::OK) {
PoolReadGuard pg(thermalSet);
if (pg.getReadResult() == returnvalue::OK) {
if (thermalSet->heaterRequest.value != ThermalComponentIF::STATE_REQUEST_IGNORE) {
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 */
@@ -1088,8 +1079,8 @@ ReturnValue_t DeviceHandlerBase::checkModeCommand(Mode_t commandedMode, Submode_
// Do not check thermal state for MODE_RAW
if ((mode == MODE_OFF) and ((commandedMode == MODE_ON) or (commandedMode == MODE_NORMAL)) and
(thermalSet != nullptr)) {
ReturnValue_t result = thermalSet->read();
if (result == returnvalue::OK) {
PoolReadGuard pg(thermalSet);
if (pg.getReadResult() == returnvalue::OK) {
if ((thermalSet->heaterRequest.value != ThermalComponentIF::STATE_REQUEST_IGNORE) and
(not ThermalComponentIF::isOperational(thermalSet->thermalState.value))) {
triggerEvent(ThermalComponentIF::TEMP_NOT_IN_OP_RANGE, thermalSet->thermalState.value);
@@ -1150,11 +1141,10 @@ void DeviceHandlerBase::handleTransitionToOnMode(Mode_t commandedMode, Submode_t
childTransitionDelay = getTransitionDelayMs(_MODE_START_UP, MODE_ON);
triggerEvent(CHANGING_MODE, commandedMode, commandedSubmode);
if (thermalSet != nullptr) {
ReturnValue_t result = thermalSet->read();
if (result == returnvalue::OK) {
PoolReadGuard pg(thermalSet);
if (pg.getReadResult() == returnvalue::OK) {
if (thermalSet->heaterRequest != ThermalComponentIF::STATE_REQUEST_IGNORE) {
thermalSet->heaterRequest = ThermalComponentIF::STATE_REQUEST_OPERATIONAL;
thermalSet->commit();
}
}
}
@@ -1477,11 +1467,11 @@ void DeviceHandlerBase::performOperationHook() {}
ReturnValue_t DeviceHandlerBase::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) {
if (thermalSet != nullptr) {
localDataPoolMap.emplace(thermalSet->thermalStatePoolId,
new PoolEntry<DeviceHandlerIF::dh_thermal_state_t>);
localDataPoolMap.emplace(thermalSet->heaterRequestPoolId,
new PoolEntry<DeviceHandlerIF::dh_heater_request_t>);
if (thermalStateCfg.has_value()) {
localDataPoolMap.emplace(thermalStateCfg.value().thermalStatePoolId,
new PoolEntry<DeviceHandlerIF::dh_thermal_state_t>());
localDataPoolMap.emplace(thermalStateCfg.value().thermalRequestPoolId,
new PoolEntry<DeviceHandlerIF::dh_heater_request_t>());
}
return returnvalue::OK;
}
@@ -1494,6 +1484,10 @@ ReturnValue_t DeviceHandlerBase::initializeAfterTaskCreation() {
}
this->poolManager.initializeAfterTaskCreation();
if (thermalStateCfg.has_value()) {
ThermalStateCfg& cfg = thermalStateCfg.value();
thermalSet = new DeviceHandlerThermalSet(this, cfg);
}
if (setStartupImmediately) {
startTransition(MODE_ON, getInitialSubmode());
}

View File

@@ -2,6 +2,7 @@
#define FSFW_DEVICEHANDLERS_DEVICEHANDLERBASE_H_
#include <map>
#include <optional>
#include "DeviceCommunicationIF.h"
#include "DeviceHandlerFailureIsolation.h"
@@ -149,11 +150,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
//! 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.
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);
@@ -163,13 +159,8 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* The device handler will then take care of creating local pool entries
* for the device thermal state and device heating request.
* Custom local pool IDs can be assigned as well.
* @param thermalStatePoolId
* @param thermalRequestPoolId
*/
void setThermalStateRequestPoolIds(
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);
void enableThermalModule(ThermalStateCfg cfg);
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF &parent) override;
ModeTreeChildIF &getModeTreeChildIF() override;
@@ -931,6 +922,8 @@ class DeviceHandlerBase : public DeviceHandlerIF,
//! Object which may be the root cause of an identified fault.
static object_id_t defaultFdirParentId;
std::optional<ThermalStateCfg> thermalStateCfg;
/**
* @brief Send a reply to a received device handler command.
*

View File

@@ -136,4 +136,10 @@ class DeviceHandlerIF {
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_ */

View File

@@ -7,27 +7,21 @@
class DeviceHandlerThermalSet : public StaticLocalDataSet<2> {
public:
DeviceHandlerThermalSet(
HasLocalDataPoolIF* hkOwner, uint32_t setId = DeviceHandlerIF::DEFAULT_THERMAL_SET_ID,
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(HasLocalDataPoolIF* hkOwner, ThermalStateCfg cfg)
: DeviceHandlerThermalSet(hkOwner->getObjectId(), cfg) {}
DeviceHandlerThermalSet(
object_id_t deviceHandler, uint32_t setId = DeviceHandlerIF::DEFAULT_THERMAL_SET_ID,
lp_id_t thermalStateId = DeviceHandlerIF::DEFAULT_THERMAL_STATE_POOL_ID,
lp_id_t thermalStateRequestId = DeviceHandlerIF::DEFAULT_THERMAL_HEATING_REQUEST_POOL_ID)
: StaticLocalDataSet(sid_t(deviceHandler, setId)),
thermalStatePoolId(thermalStateId),
heaterRequestPoolId(thermalStateRequestId) {}
DeviceHandlerThermalSet(object_id_t deviceHandler, ThermalStateCfg cfg)
: StaticLocalDataSet(sid_t(deviceHandler, cfg.thermalSetId)),
thermalStatePoolId(cfg.thermalStatePoolId),
heaterRequestPoolId(cfg.thermalRequestPoolId) {}
const lp_id_t thermalStatePoolId;
const lp_id_t heaterRequestPoolId;
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>(heaterRequestPoolId, sid.objectId, this);
lp_var_t<DeviceHandlerIF::dh_heater_request_t>(sid.objectId, heaterRequestPoolId, this);
};
#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERTHERMALSET_H_ */

View File

@@ -24,6 +24,7 @@ EventManager::EventManager(object_id_t setObjectId)
}
EventManager::~EventManager() {
listenerList.clear();
QueueFactory::instance()->deleteMessageQueue(eventReportQueue);
MutexFactory::instance()->deleteMutex(mutex);
}
@@ -73,9 +74,14 @@ ReturnValue_t EventManager::registerListener(MessageQueueId_t listener,
if (!result.second) {
return returnvalue::FAILED;
}
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) {
return subscribeToEventRange(listener, event);
}

View File

@@ -31,6 +31,7 @@ class EventManager : public EventManagerIF, public ExecutableObjectIF, public Sy
MessageQueueId_t getEventReportQueue();
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 subscribeToAllEventsFrom(MessageQueueId_t listener, object_id_t object);
ReturnValue_t subscribeToEventRange(MessageQueueId_t listener, EventId_t idFrom = 0,

View File

@@ -18,6 +18,7 @@ class EventManagerIF {
virtual ReturnValue_t registerListener(MessageQueueId_t listener,
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 subscribeToAllEventsFrom(MessageQueueId_t listener, object_id_t object) = 0;
virtual ReturnValue_t unsubscribeFromAllEvents(MessageQueueId_t listener, object_id_t object) = 0;

View File

@@ -24,7 +24,7 @@ FailureIsolationBase::~FailureIsolationBase() {
#endif
return;
}
manager->unsubscribeFromAllEvents(eventQueue->getId(), ownerId);
manager->unregisterListener(eventQueue->getId());
QueueFactory::instance()->deleteMessageQueue(eventQueue);
}

View File

@@ -24,7 +24,7 @@ class MatchTree : public SerializeableMatcherIF<T>, public BinaryTree<Serializea
MatchTree(iterator root, uint8_t maxDepth = -1)
: BinaryTree<SerializeableMatcherIF<T>>(root.element), maxDepth(maxDepth) {}
MatchTree() : BinaryTree<SerializeableMatcherIF<T>>(), maxDepth(-1) {}
virtual ~MatchTree() {}
virtual ~MatchTree() { clear(); }
virtual bool match(T number) override { return matchesTree(number); }
bool matchesTree(T number) {
iterator iter = this->begin();
@@ -176,6 +176,45 @@ class MatchTree : public SerializeableMatcherIF<T>, public BinaryTree<Serializea
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; }
bool matchSubtree(iterator iter, T number) {

View File

@@ -6,8 +6,6 @@
HealthTable::HealthTable(object_id_t objectid) : SystemObject(objectid) {
mutex = MutexFactory::instance()->createMutex();
;
mapIterator = healthMap.begin();
}

View File

@@ -10,13 +10,17 @@ InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, uint32_t m
poolManager(this, commandQueue),
internalErrorSid(setObjectId, InternalErrorDataset::ERROR_SET_ID),
internalErrorDataset(this) {
commandQueue = QueueFactory::instance()->createMessageQueue(messageQueueDepth);
mutex = MutexFactory::instance()->createMutex();
auto mqArgs = MqArgs(setObjectId, static_cast<void *>(this));
commandQueue = QueueFactory::instance()->createMessageQueue(
messageQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
}
InternalErrorReporter::~InternalErrorReporter() { MutexFactory::instance()->deleteMutex(mutex); }
InternalErrorReporter::~InternalErrorReporter() {
MutexFactory::instance()->deleteMutex(mutex);
QueueFactory::instance()->deleteMessageQueue(commandQueue);
}
void InternalErrorReporter::setDiagnosticPrintout(bool enable) {
this->diagnosticPrintout = enable;

View File

@@ -35,6 +35,8 @@ void ModeMessage::setModeAnnounceMessage(CommandMessage& message, bool recursive
message.setCommand(cmd);
}
void ModeMessage::setCmdModeModeMessage(CommandMessage& message, Mode_t mode, Submode_t submode) {
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); }

View File

@@ -38,14 +38,15 @@ class ModeMessage {
ModeMessage() = delete;
static void setModeMessage(CommandMessage* message, Command_t command, Mode_t mode,
Submode_t submode);
static Mode_t getMode(const CommandMessage* message);
static Submode_t getSubmode(const CommandMessage* message);
static ReturnValue_t getCantReachModeReason(const CommandMessage* message);
static void setCmdModeModeMessage(CommandMessage& message, Mode_t mode, Submode_t submode);
static void setModeMessage(CommandMessage* message, Command_t command, Mode_t mode,
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 clear(CommandMessage* message);
};

View File

@@ -23,9 +23,17 @@ void ObjectManager::setObjectFactoryFunction(produce_function_t objFactoryFunc,
ObjectManager::ObjectManager() = default;
void ObjectManager::clear() {
if (objManagerInstance != nullptr) {
delete objManagerInstance;
objManagerInstance = nullptr;
}
}
ObjectManager::~ObjectManager() {
for (auto const& iter : objectList) {
delete iter.second;
teardown = true;
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) {
// 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) {
this->objectList.erase(id);
#if FSFW_CPP_OSTREAM_ENABLED == 1

View File

@@ -24,12 +24,17 @@ class ObjectManager : public ObjectManagerIF {
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.
* Thus, we choose link-time variability of the instance.
*/
static ObjectManager* instance();
/**
* Deletes the single instance of ObjectManager
*/
static void clear();
void setObjectFactoryFunction(produce_function_t prodFunc, void* args);
template <typename T>
@@ -66,6 +71,9 @@ class ObjectManager : public ObjectManagerIF {
*/
std::map<object_id_t, SystemObjectIF*> objectList;
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

View File

@@ -1,10 +1,13 @@
# Check the OS_FSFW variable
if(FSFW_OSAL MATCHES "freertos")
add_subdirectory(freertos)
set(FSFW_OSAL_FREERTOS 1)
elseif(FSFW_OSAL MATCHES "rtems")
add_subdirectory(rtems)
set(FSFW_OSAL_RTEMS 1)
elseif(FSFW_OSAL MATCHES "linux")
add_subdirectory(linux)
set(FSFW_OSAL_LINUX 1)
elseif(FSFW_OSAL MATCHES "host")
add_subdirectory(host)
if(WIN32)
@@ -13,18 +16,20 @@ elseif(FSFW_OSAL MATCHES "host")
# We still need to pull in some Linux specific sources
target_sources(${LIB_FSFW_NAME} PUBLIC linux/tcpipHelpers.cpp)
endif()
set(FSFW_OSAL_HOST 1)
else()
message(
WARNING
"${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
if(WIN32)
add_subdirectory(host)
add_subdirectory(windows)
set(FSFW_OSAL_HOST 1)
elseif(UNIX)
add_subdirectory(linux)
set(FSFW_OSAL_LINUX 1)
else()
# MacOS or other OSes have not been tested yet / are not supported.
message(FATAL_ERROR "The host OS could not be determined! Aborting.")
@@ -33,3 +38,5 @@ else()
endif()
add_subdirectory(common)
configure_file(osal.h.in ${CMAKE_BINARY_DIR}/fsfw/osal/osal.h)

View File

@@ -41,6 +41,7 @@ int TcpIpBase::closeSocket(socket_t socket) {
#elif defined(PLATFORM_UNIX)
return close(socket);
#endif
return -1;
}
int TcpIpBase::getLastSocketError() {
@@ -49,4 +50,5 @@ int TcpIpBase::getLastSocketError() {
#elif defined(PLATFORM_UNIX)
return errno;
#endif
return 0;
}

View File

@@ -79,6 +79,7 @@ class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableOb
*/
bool reusePort = false;
};
enum class ReceptionModes { SPACE_PACKETS };
static const std::string DEFAULT_SERVER_PORT;

View File

@@ -126,10 +126,7 @@ ReturnValue_t UdpTmTcBridge::sendTm(const uint8_t *data, size_t dataLen) {
tcpip::handleError(tcpip::Protocol::UDP, tcpip::ErrorSources::SENDTO_CALL);
}
#if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_SEND_WIRETAPPING_ENABLED == 1
sif::debug << "TmTcUdpBridge::sendTm: " << bytesSent
<< " bytes were"
" sent."
<< std::endl;
sif::debug << "TmTcUdpBridge::sendTm: " << bytesSent << " bytes were sent" << std::endl;
#endif
return returnvalue::OK;
}

View File

@@ -21,7 +21,7 @@ MessageQueue::MessageQueue(uint32_t messageDepth, size_t maxMessageSize, MqArgs*
attributes.mq_msgsize = maxMessageSize;
attributes.mq_flags = 0; // Flags are ignored on Linux during mq_open
// 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
// and writable for the owner as well as the group)

36
src/fsfw/osal/osal.h.in Normal file
View 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
}
};

View File

@@ -19,7 +19,7 @@ ReturnValue_t CService200ModeCommanding::isValidSubservice(uint8_t subservice) {
switch (subservice) {
case (Subservice::COMMAND_MODE_COMMAND):
case (Subservice::COMMAND_MODE_READ):
case (Subservice::COMMAND_MODE_ANNCOUNCE):
case (Subservice::COMMAND_MODE_ANNOUNCE):
case (Subservice::COMMAND_MODE_ANNOUNCE_RECURSIVELY):
return returnvalue::OK;
default:
@@ -54,27 +54,32 @@ ReturnValue_t CService200ModeCommanding::checkInterfaceAndAcquireMessageQueue(
ReturnValue_t CService200ModeCommanding::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;
if (subservice == Subservice::COMMAND_MODE_ANNCOUNCE or
subservice == Subservice::COMMAND_MODE_ANNOUNCE_RECURSIVELY) {
bool recursive = true;
if (subservice == Subservice::COMMAND_MODE_ANNCOUNCE) {
recursive = false;
}
ModeMessage::setModeAnnounceMessage(*message, recursive);
} else {
ModePacket modeCommandPacket;
ReturnValue_t result =
modeCommandPacket.deSerialize(&tcData, &tcDataLen, SerializeIF::Endianness::BIG);
if (result != returnvalue::OK) {
return result;
}
bool recursive = false;
switch (subservice) {
case (Subservice::COMMAND_MODE_COMMAND): {
ModePacket modeCommandPacket;
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(),
modeCommandPacket.getSubmode());
ModeMessage::setModeMessage(message, ModeMessage::CMD_MODE_COMMAND,
modeCommandPacket.getMode(), modeCommandPacket.getSubmode());
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;
}
return result;
}
ReturnValue_t CService200ModeCommanding::handleReply(const CommandMessage *reply,
@@ -85,8 +90,10 @@ ReturnValue_t CService200ModeCommanding::handleReply(const CommandMessage *reply
ReturnValue_t result = returnvalue::FAILED;
switch (replyId) {
case (ModeMessage::REPLY_MODE_REPLY): {
result = prepareModeReply(reply, objectId);
break;
if (previousCommand != ModeMessage::CMD_MODE_COMMAND) {
return prepareModeReply(reply, objectId);
}
return returnvalue::OK;
}
case (ModeMessage::REPLY_WRONG_MODE_REPLY): {
result = prepareWrongModeReply(reply, objectId);

View File

@@ -52,7 +52,7 @@ class CService200ModeCommanding : public CommandingServiceBase {
COMMAND_MODE_READ = 3,
//!< [EXPORT] : [COMMAND] Trigger an ModeInfo Event.
//! 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
//! command to every child. This command does NOT have a reply.
COMMAND_MODE_ANNOUNCE_RECURSIVELY = 5,

View File

@@ -160,7 +160,7 @@ inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::doInsertActivi
// (See requirement for Time margin)
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
sif::warning << "Service11TelecommandScheduling::doInsertActivity: Release time too close to "
"current time"

View File

@@ -117,6 +117,20 @@ ReturnValue_t SubsystemBase::updateChildMode(MessageQueueId_t queue, Mode_t mode
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) {
for (auto iter = childrenMap.begin(); iter != childrenMap.end(); iter++) {
if (iter->second.commandQueue == queue) {

View File

@@ -115,6 +115,7 @@ class SubsystemBase : public SystemObject,
Submode_t targetSubmode = SUBMODE_NONE);
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);

View File

@@ -15,10 +15,10 @@ ReturnValue_t FixedTimeslotTaskBase::addSlot(object_id_t execId, ExecutableObjec
uint32_t slotTimeMs, int8_t executionStep) {
if (execObj == nullptr) {
#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;
#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
return returnvalue::FAILED;
}

View File

@@ -4,6 +4,8 @@
#include "fsfw/timemanager/Clock.h"
CdsShortTimeStamper::CdsShortTimeStamper() : SystemObject(0, false) {}
CdsShortTimeStamper::CdsShortTimeStamper(object_id_t objectId) : SystemObject(objectId) {}
ReturnValue_t CdsShortTimeStamper::serialize(uint8_t **buffer, size_t *size, size_t maxSize,

View File

@@ -18,6 +18,7 @@
class CdsShortTimeStamper : public TimeWriterIF, public TimeReaderIF, public SystemObject {
public:
static constexpr size_t TIMESTAMP_LEN = 7;
CdsShortTimeStamper();
/**
* @brief Default constructor which also registers the time stamper as a
* system object so it can be found with the #objectManager.

View File

@@ -145,13 +145,17 @@ ReturnValue_t TmTcBridge::handleTmQueue() {
#endif /* FSFW_VERBOSE_LEVEL >= 3 */
if (communicationLinkUp == false or packetSentCounter >= sentPacketsPerCycle) {
storeDownlinkData(&message);
ReturnValue_t result = storeDownlinkData(&message);
if (result != returnvalue::OK) {
tmStore->deleteData(message.getStorageId());
}
continue;
}
result = tmStore->getData(message.getStorageId(), &data, &size);
if (result != returnvalue::OK) {
status = result;
tmStore->deleteData(message.getStorageId());
continue;
}
@@ -159,9 +163,9 @@ ReturnValue_t TmTcBridge::handleTmQueue() {
if (result != returnvalue::OK) {
status = result;
} else {
tmStore->deleteData(message.getStorageId());
packetSentCounter++;
}
tmStore->deleteData(message.getStorageId());
}
return status;
}

View File

@@ -17,7 +17,7 @@ class TmTcBridge : public AcceptsTelemetryIF,
public:
static constexpr uint8_t TMTC_RECEPTION_QUEUE_DEPTH = 20;
static constexpr uint8_t LIMIT_STORED_DATA_SENT_PER_CYCLE = 15;
static constexpr unsigned int LIMIT_DOWNLINK_PACKETS_STORED = 1000;
static constexpr unsigned int LIMIT_DOWNLINK_PACKETS_STORED = 500;
static constexpr uint8_t DEFAULT_STORED_DATA_SENT_PER_CYCLE = 5;
static constexpr uint8_t DEFAULT_DOWNLINK_PACKETS_STORED = 10;

View File

@@ -1,6 +1,7 @@
#include "version.h"
#include <cstdio>
#include <cstring>
#include "fsfw/FSFWVersion.h"
@@ -20,7 +21,7 @@ fsfw::Version::Version(int major, int minor, int revision, const char* addInfo)
void fsfw::Version::getVersion(char* str, size_t maxLen) const {
size_t len = snprintf(str, maxLen, "%d.%d.%d", major, minor, revision);
if (addInfo != nullptr) {
if (addInfo != nullptr and std::strcmp(addInfo, "") != 0) {
snprintf(str + len, maxLen - len, "-%s", addInfo);
}
}
@@ -30,7 +31,7 @@ namespace fsfw {
#if FSFW_CPP_OSTREAM_ENABLED == 1
std::ostream& operator<<(std::ostream& os, const Version& v) {
os << v.major << "." << v.minor << "." << v.revision;
if (v.addInfo != nullptr) {
if (v.addInfo != nullptr and std::strcmp(v.addInfo, "") != 0) {
os << "-" << v.addInfo;
}
return os;

View File

@@ -6,14 +6,11 @@
#include "fsfw/FSFW.h"
#include "fsfw/serviceinterface.h"
UnixFileGuard::UnixFileGuard(const std::string& device, int* fileDescriptor, int flags,
UnixFileGuard::UnixFileGuard(const std::string& device, int& fileDescriptor, int flags,
std::string diagnosticPrefix)
: fileDescriptor(fileDescriptor) {
if (fileDescriptor == nullptr) {
return;
}
*fileDescriptor = open(device.c_str(), flags);
if (*fileDescriptor < 0) {
: fdRef(fileDescriptor) {
fileDescriptor = open(device.c_str(), flags);
if (fileDescriptor < 0) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << diagnosticPrefix << ": Opening device failed with error code " << errno << ": "
@@ -27,10 +24,6 @@ UnixFileGuard::UnixFileGuard(const std::string& device, int* fileDescriptor, int
}
}
UnixFileGuard::~UnixFileGuard() {
if (fileDescriptor != nullptr) {
close(*fileDescriptor);
}
}
UnixFileGuard::~UnixFileGuard() { close(fdRef); }
ReturnValue_t UnixFileGuard::getOpenResult() const { return openStatus; }

View File

@@ -15,7 +15,15 @@ class UnixFileGuard {
static constexpr ReturnValue_t OPEN_FILE_FAILED = 1;
UnixFileGuard(const std::string& device, int* fileDescriptor, int flags,
/**
* Open a device and assign the given file descriptor variable
* @param device [in] Device name.
* @param fileDescriptor [in/out] Will be assigned by file guard and re-used to
* close the guard.
* @param flags
* @param diagnosticPrefix
*/
UnixFileGuard(const std::string& device, int& fileDescriptor, int flags,
std::string diagnosticPrefix = "");
virtual ~UnixFileGuard();
@@ -23,7 +31,7 @@ class UnixFileGuard {
ReturnValue_t getOpenResult() const;
private:
int* fileDescriptor = nullptr;
int& fdRef;
ReturnValue_t openStatus = returnvalue::OK;
};

View File

@@ -66,8 +66,7 @@ ReturnValue_t I2cComIF::initializeInterface(CookieIF* cookie) {
ReturnValue_t I2cComIF::sendMessage(CookieIF* cookie, const uint8_t* sendData, size_t sendLen) {
ReturnValue_t result;
int fd;
std::string deviceFile;
int fd = 0;
if (sendData == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
@@ -98,12 +97,12 @@ ReturnValue_t I2cComIF::sendMessage(CookieIF* cookie, const uint8_t* sendData, s
return returnvalue::FAILED;
}
deviceFile = i2cCookie->getDeviceFile();
UnixFileGuard fileHelper(deviceFile, &fd, O_RDWR, "I2cComIF::sendMessage");
const auto& deviceFile = i2cCookie->getDeviceFile();
UnixFileGuard fileHelper(deviceFile, fd, O_RDWR, "I2cComIF::sendMessage");
if (fileHelper.getOpenResult() != returnvalue::OK) {
return fileHelper.getOpenResult();
}
result = openDevice(deviceFile, i2cAddress, &fd);
result = openI2cSlave(deviceFile, i2cAddress, fd);
if (result != returnvalue::OK) {
return result;
}
@@ -131,8 +130,7 @@ ReturnValue_t I2cComIF::getSendSuccess(CookieIF* cookie) { return returnvalue::O
ReturnValue_t I2cComIF::requestReceiveMessage(CookieIF* cookie, size_t requestLen) {
ReturnValue_t result;
int fd;
std::string deviceFile;
int fd = 0;
if (requestLen == 0) {
return returnvalue::OK;
@@ -157,12 +155,12 @@ ReturnValue_t I2cComIF::requestReceiveMessage(CookieIF* cookie, size_t requestLe
}
i2cDeviceMapIter->second.replyLen = 0;
deviceFile = i2cCookie->getDeviceFile();
UnixFileGuard fileHelper(deviceFile, &fd, O_RDWR, "I2cComIF::requestReceiveMessage");
auto& deviceFile = i2cCookie->getDeviceFile();
UnixFileGuard fileHelper(deviceFile, fd, O_RDWR, "I2cComIF::requestReceiveMessage");
if (fileHelper.getOpenResult() != returnvalue::OK) {
return fileHelper.getOpenResult();
}
result = openDevice(deviceFile, i2cAddress, &fd);
result = openI2cSlave(deviceFile, i2cAddress, fd);
if (result != returnvalue::OK) {
return result;
}
@@ -220,9 +218,9 @@ ReturnValue_t I2cComIF::readReceivedMessage(CookieIF* cookie, uint8_t** buffer,
return returnvalue::OK;
}
ReturnValue_t I2cComIF::openDevice(std::string deviceFile, address_t i2cAddress,
int* fileDescriptor) {
if (ioctl(*fileDescriptor, I2C_SLAVE, i2cAddress) < 0) {
ReturnValue_t I2cComIF::openI2cSlave(const std::string& deviceFile, address_t i2cAddress,
int& fileDescriptor) {
if (ioctl(fileDescriptor, I2C_SLAVE, i2cAddress) < 0) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "I2cComIF: Specifying target device failed with error code " << errno << "."

View File

@@ -49,7 +49,8 @@ class I2cComIF : public DeviceCommunicationIF, public SystemObject {
* @param fileDescriptor Pointer to device descriptor.
* @return returnvalue::OK if successful, otherwise returnvalue::FAILED.
*/
ReturnValue_t openDevice(std::string deviceFile, address_t i2cAddress, int *fileDescriptor);
ReturnValue_t openI2cSlave(const std::string &deviceFile, address_t i2cAddress,
int &fileDescriptor);
};
#endif /* LINUX_I2C_I2COMIF_H_ */

View File

@@ -1,12 +1,12 @@
#include "fsfw_hal/linux/i2c/I2cCookie.h"
I2cCookie::I2cCookie(address_t i2cAddress_, size_t maxReplyLen_, std::string deviceFile_)
: i2cAddress(i2cAddress_), maxReplyLen(maxReplyLen_), deviceFile(deviceFile_) {}
: i2cAddress(i2cAddress_), maxReplyLen(maxReplyLen_), deviceFile(std::move(deviceFile_)) {}
address_t I2cCookie::getAddress() const { return i2cAddress; }
size_t I2cCookie::getMaxReplyLen() const { return maxReplyLen; }
std::string I2cCookie::getDeviceFile() const { return deviceFile; }
const std::string& I2cCookie::getDeviceFile() const { return deviceFile; }
I2cCookie::~I2cCookie() {}

View File

@@ -25,7 +25,7 @@ class I2cCookie : public CookieIF {
address_t getAddress() const;
size_t getMaxReplyLen() const;
std::string getDeviceFile() const;
const std::string& getDeviceFile() const;
uint8_t errorCounter = 0;

View File

@@ -1,5 +1,6 @@
#pragma once
#include <fsfw_hal/linux/spi/SpiCookie.h>
#include "fsfw/ipc/MutexIF.h"
#include "fsfw/returnvalues/returnvalue.h"
#include "fsfw_hal/common/gpio/GpioIF.h"

View File

@@ -75,7 +75,7 @@ ReturnValue_t SpiComIF::initializeInterface(CookieIF* cookie) {
spiCookie->getSpiParameters(spiMode, spiSpeed, &params);
int fileDescriptor = 0;
UnixFileGuard fileHelper(dev, &fileDescriptor, O_RDWR, "SpiComIF::initializeInterface");
UnixFileGuard fileHelper(dev, fileDescriptor, O_RDWR, "SpiComIF::initializeInterface");
if (fileHelper.getOpenResult() != returnvalue::OK) {
return fileHelper.getOpenResult();
}
@@ -171,7 +171,7 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const
int retval = 0;
/* Prepare transfer */
int fileDescriptor = 0;
UnixFileGuard fileHelper(dev, &fileDescriptor, O_RDWR, "SpiComIF::sendMessage");
UnixFileGuard fileHelper(dev, fileDescriptor, O_RDWR, "SpiComIF::sendMessage");
if (fileHelper.getOpenResult() != returnvalue::OK) {
return OPENING_FILE_FAILED;
}
@@ -179,12 +179,11 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const
uint32_t spiSpeed = 0;
spiCookie->getSpiParameters(spiMode, spiSpeed, nullptr);
setSpiSpeedAndMode(fileDescriptor, spiMode, spiSpeed);
spiCookie->assignWriteBuffer(sendData);
spiCookie->setTransferSize(sendLen);
bool fullDuplex = spiCookie->isFullDuplex();
gpioId_t gpioId = spiCookie->getChipSelectPin();
bool csLockManual = spiCookie->getCsLockManual();
spiCookie->setTransferSize(0);
MutexIF::TimeoutType csType;
dur_millis_t csTimeout = 0;
@@ -195,9 +194,13 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const
if (result != returnvalue::OK) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "SpiComIF::sendMessage: Failed to lock mutex with code "
<< "0x" << std::hex << std::setfill('0') << std::setw(4) << result << std::dec
<< std::endl;
if (result == MutexIF::MUTEX_TIMEOUT) {
sif::error << "SpiComIF::sendMessage: Lock timeout" << std::endl;
} else {
sif::error << "SpiComIF::sendMessage: Failed to lock mutex with code "
<< "0x" << std::hex << std::setfill('0') << std::setw(4) << result << std::dec
<< std::endl;
}
#else
sif::printError("SpiComIF::sendMessage: Failed to lock mutex with code %d\n", result);
#endif
@@ -214,17 +217,22 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const
sif::printWarning("SpiComIF::sendMessage: Pulling low CS pin failed");
#endif
#endif
csMutex->unlockMutex();
return result;
}
} else {
updateLinePolarity(fileDescriptor);
}
spiCookie->assignWriteBuffer(sendData);
spiCookie->setTransferSize(sendLen);
/* Execute transfer */
if (fullDuplex) {
/* Initiate a full duplex SPI transfer. */
retval = ioctl(fileDescriptor, SPI_IOC_MESSAGE(1), spiCookie->getTransferStructHandle());
if (retval < 0) {
spiCookie->setTransferSize(0);
utility::handleIoctlError("SpiComIF::sendMessage: ioctl error.");
result = FULL_DUPLEX_TRANSFER_FAILED;
}
@@ -234,6 +242,7 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const
} else {
/* We write with a blocking half-duplex transfer here */
if (write(fileDescriptor, sendData, sendLen) != static_cast<ssize_t>(sendLen)) {
spiCookie->setTransferSize(0);
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "SpiComIF::sendMessage: Half-Duplex write operation failed!" << std::endl;
@@ -276,7 +285,7 @@ ReturnValue_t SpiComIF::requestReceiveMessage(CookieIF* cookie, size_t requestLe
ReturnValue_t SpiComIF::performHalfDuplexReception(SpiCookie* spiCookie) {
ReturnValue_t result = returnvalue::OK;
int fileDescriptor = 0;
UnixFileGuard fileHelper(dev, &fileDescriptor, O_RDWR, "SpiComIF::requestReceiveMessage");
UnixFileGuard fileHelper(dev, fileDescriptor, O_RDWR, "SpiComIF::requestReceiveMessage");
if (fileHelper.getOpenResult() != returnvalue::OK) {
return OPENING_FILE_FAILED;
}

View File

@@ -31,4 +31,7 @@ int customSetup() {
return 0;
}
int customTeardown() { return 0; }
int customTeardown() {
ObjectManager::clear();
return 0;
}

View File

@@ -9,7 +9,9 @@ DeviceHandlerCommander::DeviceHandlerCommander(object_id_t objectId)
QUEUE_SIZE, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
}
DeviceHandlerCommander::~DeviceHandlerCommander() {}
DeviceHandlerCommander::~DeviceHandlerCommander() {
QueueFactory::instance()->deleteMessageQueue(commandQueue);
}
ReturnValue_t DeviceHandlerCommander::performOperation(uint8_t operationCode) {
readCommandQueue();

View File

@@ -1,46 +1,38 @@
#ifdef LINUX
/*
#include <fsfw/osal/osal.h>
#include <fsfw/tasks/SemaphoreFactory.h>
#include <fsfw/timemanager/Stopwatch.h>
#include "catch.hpp"
#include "core/CatchDefinitions.h"
#include <catch2/catch_test_macros.hpp>
TEST_CASE("Binary Semaphore Test" , "[BinSemaphore]") {
//perform set-up here
SemaphoreIF* binSemaph = SemaphoreFactory::instance()->
createBinarySemaphore();
REQUIRE(binSemaph != nullptr);
SECTION("Simple Test") {
// set-up is run for each section
REQUIRE(binSemaph->getSemaphoreCounter() == 1);
REQUIRE(binSemaph->release() ==
static_cast<int>(SemaphoreIF::SEMAPHORE_NOT_OWNED));
REQUIRE(binSemaph->acquire(SemaphoreIF::POLLING) ==
returnvalue::OK);
{
// not precise enough on linux.. should use clock instead..
//Stopwatch stopwatch(false);
//REQUIRE(binSemaph->acquire(SemaphoreIF::TimeoutType::WAITING, 5) ==
// SemaphoreIF::SEMAPHORE_TIMEOUT);
//dur_millis_t time = stopwatch.stop();
//CHECK(time == 5);
}
REQUIRE(binSemaph->getSemaphoreCounter() == 0);
REQUIRE(binSemaph->release() == returnvalue::OK);
}
SemaphoreFactory::instance()->deleteSemaphore(binSemaph);
// perform tear-down here
// binary semaphores currently only supported on linux
#ifdef FSFW_OSAL_LINUX
TEST_CASE("Binary Semaphore Test", "[BinSemaphore]") {
// perform set-up here
SemaphoreIF* binSemaph = SemaphoreFactory::instance()->createBinarySemaphore();
REQUIRE(binSemaph != nullptr);
SECTION("Simple Test") {
// set-up is run for each section
REQUIRE(binSemaph->getSemaphoreCounter() == 1);
REQUIRE(binSemaph->release() == static_cast<int>(SemaphoreIF::SEMAPHORE_NOT_OWNED));
REQUIRE(binSemaph->acquire(SemaphoreIF::POLLING) == returnvalue::OK);
{
// not precise enough on linux.. should use clock instead..
// Stopwatch stopwatch(false);
// REQUIRE(binSemaph->acquire(SemaphoreIF::TimeoutType::WAITING, 5) ==
// SemaphoreIF::SEMAPHORE_TIMEOUT);
// dur_millis_t time = stopwatch.stop();
// CHECK(time == 5);
}
REQUIRE(binSemaph->getSemaphoreCounter() == 0);
REQUIRE(binSemaph->release() == returnvalue::OK);
}
SemaphoreFactory::instance()->deleteSemaphore(binSemaph);
// perform tear-down here
}
TEST_CASE("Counting Semaphore Test" , "[CountingSemaph]") {
SECTION("Simple Test") {
}
TEST_CASE("Counting Semaphore Test", "[CountingSemaph]") {
SECTION("Simple Test") {}
}
*/
#endif
#endif