Merge remote-tracking branch 'origin/develop' into mueller/pus-15-tm-storage

This commit is contained in:
Robin Müller 2023-02-14 17:33:59 +01:00
commit 70b785984c
14 changed files with 87 additions and 71 deletions

View File

@ -12,15 +12,22 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## Fixes ## 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 - `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 on mode announcements, duplicate mode reply generated on announce commands, and the mode read
subservice not working properly. 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 - `Service9TimeManagement`: Fix the time dump at the `SET_TIME` subservice: Include clock timeval
seconds instead of uptime. seconds instead of uptime.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/726 PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/726
- HAL MGM3100 Handler: Use axis specific gain/scaling factors. Previously, - HAL MGM3100 Handler: Use axis specific gain/scaling factors. Previously,
only the X scaling factor was used. only the X scaling factor was used.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/724 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 - DHB `setNormalDatapoolEntriesInvalid`: The default implementation did not set the validity
to false correctly because the `read` and `write` calls were missing. to false correctly because the `read` and `write` calls were missing.
- PUS TMTC creator module: Sequence flags were set to continuation segment (0b00) instead - PUS TMTC creator module: Sequence flags were set to continuation segment (0b00) instead
@ -43,6 +50,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- `CServiceHealthCommanding`: Add announce all health info implementation - `CServiceHealthCommanding`: Add announce all health info implementation
PR: https://egit.irs.uni-stuttgart.de/eive/fsfw/pulls/122 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. - `Service9TimeManagement`: Add `DUMP_TIME` (129) subservice.
- `TcpTmTcServer`: Allow setting the `SO_REUSEADDR` and `SO_REUSEPORT` - `TcpTmTcServer`: Allow setting the `SO_REUSEADDR` and `SO_REUSEPORT`
option on the TCP server. CTOR prototype has changed and expects an explicit option on the TCP server. CTOR prototype has changed and expects an explicit

View File

@ -153,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)
@ -196,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(

View File

@ -58,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) {
@ -227,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();
} }
} }
@ -594,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 */
@ -1088,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);
@ -1150,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();
} }
} }
} }
@ -1477,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;
} }
@ -1494,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());
} }

View File

@ -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"
@ -163,13 +164,8 @@ 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,
uint32_t thermalSetId = DeviceHandlerIF::DEFAULT_THERMAL_SET_ID);
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF &parent) override; ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF &parent) override;
ModeTreeChildIF &getModeTreeChildIF() override; ModeTreeChildIF &getModeTreeChildIF() override;
@ -931,6 +927,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.
* *

View File

@ -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_ */

View File

@ -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_ */

View File

@ -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;
} }

View File

@ -19,7 +19,7 @@ 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): case (Subservice::COMMAND_MODE_ANNOUNCE_RECURSIVELY):
return returnvalue::OK; return returnvalue::OK;
default: default:
@ -54,6 +54,7 @@ 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) {
bool recursive = false;
switch (subservice) { switch (subservice) {
case (Subservice::COMMAND_MODE_COMMAND): { case (Subservice::COMMAND_MODE_COMMAND): {
ModePacket modeCommandPacket; ModePacket modeCommandPacket;
@ -67,22 +68,17 @@ ReturnValue_t CService200ModeCommanding::prepareCommand(CommandMessage *message,
modeCommandPacket.getMode(), modeCommandPacket.getSubmode()); modeCommandPacket.getMode(), modeCommandPacket.getSubmode());
return returnvalue::OK; return returnvalue::OK;
} }
case (Subservice::COMMAND_MODE_ANNCOUNCE): case (Subservice::COMMAND_MODE_ANNOUNCE_RECURSIVELY):
case (Subservice::COMMAND_MODE_ANNOUNCE_RECURSIVELY): { recursive = true;
bool recursive = true; [[fallthrough]];
if (subservice == Subservice::COMMAND_MODE_ANNCOUNCE) { case (Subservice::COMMAND_MODE_ANNOUNCE):
recursive = false;
}
ModeMessage::setModeAnnounceMessage(*message, recursive); ModeMessage::setModeAnnounceMessage(*message, recursive);
return EXECUTION_COMPLETE; return EXECUTION_COMPLETE;
} case (Subservice::COMMAND_MODE_READ):
case (Subservice::COMMAND_MODE_READ): {
ModeMessage::setModeReadMessage(*message); ModeMessage::setModeReadMessage(*message);
return returnvalue::OK; return returnvalue::OK;
} default:
default: {
return CommandingServiceBase::INVALID_SUBSERVICE; return CommandingServiceBase::INVALID_SUBSERVICE;
}
} }
} }

View File

@ -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,

View File

@ -160,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 < 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"

View File

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

View File

@ -17,7 +17,7 @@ class TmTcBridge : public AcceptsTelemetryIF,
public: public:
static constexpr uint8_t TMTC_RECEPTION_QUEUE_DEPTH = 20; static constexpr uint8_t TMTC_RECEPTION_QUEUE_DEPTH = 20;
static constexpr uint8_t LIMIT_STORED_DATA_SENT_PER_CYCLE = 15; 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_STORED_DATA_SENT_PER_CYCLE = 5;
static constexpr uint8_t DEFAULT_DOWNLINK_PACKETS_STORED = 10; static constexpr uint8_t DEFAULT_DOWNLINK_PACKETS_STORED = 10;

View File

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

View File

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