diff --git a/.idea/cmake.xml b/.idea/cmake.xml new file mode 100644 index 00000000..b0a4921a --- /dev/null +++ b/.idea/cmake.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index d3e03c4f..9f5bb9bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,40 @@ and this project adheres to [Semantic Versioning](http://semver.org/). # [unreleased] +## Fixes + +- The `PusTmCreator` API only accepted 255 bytes of source data. It can now accept source + data with a size limited only by the size of `size_t`. +- Important bugfix in CFDP PDU header format: The entity length field and the transaction sequence + number fields stored the actual length of the field instead of the length minus 1 like specified + in the CFDP standard. +- PUS Health Service: Size check for set health command. + Perform operation completion for announce health command. + https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/746 +- Linux OSAL `getUptime` fix: Check validity of `/proc/uptime` file before reading uptime. + https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/745 +- Small tweak for version getter + https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/744 + +## Added + +- add CFDP subsystem ID + https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/742 +- `PusTmZcWriter` now exposes API to set message counter field. + +## Changed + +- HK generation is now countdown based. +- Bump ETL version to 20.35.14 + https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/748 +- Renamed `PCDU_2` subsystem ID to `POWER_SWITCH_IF`. + https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/743 +- Add new `PowerSwitchIF::SWITCH_UNKNOWN` returnvalue. + https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/743 +- Assert that `FixedArrayList` is larger than 0 at compile time. + https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/740 +- Health functions are virtual now. + # [v6.0.0] 2023-02-10 ## Fixes diff --git a/CMakeLists.txt b/CMakeLists.txt index 5eddde7f..5d35e6ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,7 +72,7 @@ set(FSFW_ETL_LIB_MAJOR_VERSION 20 CACHE STRING "ETL library major version requirement") set(FSFW_ETL_LIB_VERSION - ${FSFW_ETL_LIB_MAJOR_VERSION}.28.0 + ${FSFW_ETL_LIB_MAJOR_VERSION}.35.14 CACHE STRING "ETL library exact version requirement") set(FSFW_ETL_LINK_TARGET etl::etl) diff --git a/src/fsfw/action/ActionHelper.cpp b/src/fsfw/action/ActionHelper.cpp index fd6c8afb..81a1a727 100644 --- a/src/fsfw/action/ActionHelper.cpp +++ b/src/fsfw/action/ActionHelper.cpp @@ -59,17 +59,24 @@ void ActionHelper::setQueueToUse(MessageQueueIF* queue) { queueToUse = queue; } void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId, store_address_t dataAddress) { + bool hasAdditionalData = false; const uint8_t* dataPtr = nullptr; size_t size = 0; - ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size); - if (result != returnvalue::OK) { - CommandMessage reply; - ActionMessage::setStepReply(&reply, actionId, 0, result); - queueToUse->sendMessage(commandedBy, &reply); - return; + ReturnValue_t result; + if (dataAddress != store_address_t::invalid()) { + hasAdditionalData = true; + ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size); + if (result != returnvalue::OK) { + CommandMessage reply; + ActionMessage::setStepReply(&reply, actionId, 0, result); + queueToUse->sendMessage(commandedBy, &reply); + return; + } } result = owner->executeAction(actionId, commandedBy, dataPtr, size); - ipcStore->deleteData(dataAddress); + if (hasAdditionalData) { + ipcStore->deleteData(dataAddress); + } if (result == HasActionsIF::EXECUTION_FINISHED) { CommandMessage reply; ActionMessage::setCompletionReply(&reply, actionId, true, result); diff --git a/src/fsfw/cfdp.h b/src/fsfw/cfdp.h index f6c01ad0..b2645978 100644 --- a/src/fsfw/cfdp.h +++ b/src/fsfw/cfdp.h @@ -2,7 +2,6 @@ #define FSFW_CFDP_H #include "cfdp/definitions.h" -#include "cfdp/handler/CfdpHandler.h" #include "cfdp/handler/DestHandler.h" #include "cfdp/handler/FaultHandlerBase.h" #include "cfdp/helpers.h" diff --git a/src/fsfw/cfdp/handler/CMakeLists.txt b/src/fsfw/cfdp/handler/CMakeLists.txt index d96ce91c..7ad995c0 100644 --- a/src/fsfw/cfdp/handler/CMakeLists.txt +++ b/src/fsfw/cfdp/handler/CMakeLists.txt @@ -1,3 +1,2 @@ -target_sources( - ${LIB_FSFW_NAME} PRIVATE SourceHandler.cpp DestHandler.cpp - FaultHandlerBase.cpp UserBase.cpp CfdpHandler.cpp) +target_sources(${LIB_FSFW_NAME} PRIVATE SourceHandler.cpp DestHandler.cpp + FaultHandlerBase.cpp UserBase.cpp) diff --git a/src/fsfw/cfdp/handler/CfdpHandler.cpp b/src/fsfw/cfdp/handler/CfdpHandler.cpp deleted file mode 100644 index 902097b6..00000000 --- a/src/fsfw/cfdp/handler/CfdpHandler.cpp +++ /dev/null @@ -1,134 +0,0 @@ -#include "CfdpHandler.h" - -#include "fsfw/cfdp/pdu/AckPduReader.h" -#include "fsfw/cfdp/pdu/PduHeaderReader.h" -#include "fsfw/globalfunctions/arrayprinter.h" -#include "fsfw/ipc/QueueFactory.h" -#include "fsfw/tmtcservices/TmTcMessage.h" - -using namespace returnvalue; -using namespace cfdp; - -CfdpHandler::CfdpHandler(const FsfwHandlerParams& fsfwParams, const CfdpHandlerCfg& cfdpCfg) - : SystemObject(fsfwParams.objectId), - msgQueue(fsfwParams.msgQueue), - destHandler( - DestHandlerParams(LocalEntityCfg(cfdpCfg.id, cfdpCfg.indicCfg, cfdpCfg.faultHandler), - cfdpCfg.userHandler, cfdpCfg.remoteCfgProvider, cfdpCfg.packetInfoList, - cfdpCfg.lostSegmentsList), - FsfwParams(fsfwParams.packetDest, nullptr, this, fsfwParams.tcStore, - fsfwParams.tmStore)) { - destHandler.setMsgQueue(msgQueue); -} - -[[nodiscard]] const char* CfdpHandler::getName() const { return "CFDP Handler"; } - -[[nodiscard]] uint32_t CfdpHandler::getIdentifier() const { - return destHandler.getDestHandlerParams().cfg.localId.getValue(); -} - -[[nodiscard]] MessageQueueId_t CfdpHandler::getRequestQueue() const { return msgQueue.getId(); } - -ReturnValue_t CfdpHandler::initialize() { - ReturnValue_t result = destHandler.initialize(); - if (result != OK) { - return result; - } - tcStore = destHandler.getTcStore(); - tmStore = destHandler.getTmStore(); - - return SystemObject::initialize(); -} - -ReturnValue_t CfdpHandler::performOperation(uint8_t operationCode) { - // TODO: Receive TC packets and route them to source and dest handler, depending on which is - // correct or more appropriate - ReturnValue_t status; - ReturnValue_t result = OK; - TmTcMessage tmtcMsg; - for (status = msgQueue.receiveMessage(&tmtcMsg); status == returnvalue::OK; - status = msgQueue.receiveMessage(&tmtcMsg)) { - result = handleCfdpPacket(tmtcMsg); - if (result != OK) { - status = result; - } - } - auto& fsmRes = destHandler.performStateMachine(); - // TODO: Error handling? - while (fsmRes.callStatus == CallStatus::CALL_AGAIN) { - destHandler.performStateMachine(); - // TODO: Error handling? - } - return status; -} - -ReturnValue_t CfdpHandler::handleCfdpPacket(TmTcMessage& msg) { - auto accessorPair = tcStore->getData(msg.getStorageId()); - if (accessorPair.first != OK) { - return accessorPair.first; - } - PduHeaderReader reader(accessorPair.second.data(), accessorPair.second.size()); - ReturnValue_t result = reader.parseData(); - if (result != returnvalue::OK) { - return INVALID_PDU_FORMAT; - } - // The CFDP distributor should have taken care of ensuring the destination ID is correct - PduType type = reader.getPduType(); - // Only the destination handler can process these PDUs - if (type == PduType::FILE_DATA) { - // Disable auto-deletion of packet - accessorPair.second.release(); - PacketInfo info(type, msg.getStorageId()); - result = destHandler.passPacket(info); - } else { - // Route depending on PDU type and directive type if applicable. It retrieves directive type - // from the raw stream for better performance (with sanity and directive code check). - // The routing is based on section 4.5 of the CFDP standard which specifies the PDU forwarding - // procedure. - - // PDU header only. Invalid supplied data. A directive packet should have a valid data field - // with at least one byte being the directive code - const uint8_t* pduDataField = reader.getPduDataField(); - if (pduDataField == nullptr) { - return INVALID_PDU_FORMAT; - } - if (not FileDirectiveReader::checkFileDirective(pduDataField[0])) { - return INVALID_DIRECTIVE_FIELD; - } - auto directive = static_cast(pduDataField[0]); - - auto passToDestHandler = [&]() { - accessorPair.second.release(); - PacketInfo info(type, msg.getStorageId(), directive); - result = destHandler.passPacket(info); - }; - auto passToSourceHandler = [&]() { - - }; - if (directive == FileDirective::METADATA or directive == FileDirective::EOF_DIRECTIVE or - directive == FileDirective::PROMPT) { - // Section b) of 4.5.3: These PDUs should always be targeted towards the file receiver a.k.a. - // the destination handler - passToDestHandler(); - } else if (directive == FileDirective::FINISH or directive == FileDirective::NAK or - directive == FileDirective::KEEP_ALIVE) { - // Section c) of 4.5.3: These PDUs should always be targeted towards the file sender a.k.a. - // the source handler - passToSourceHandler(); - } else if (directive == FileDirective::ACK) { - // Section a): Recipient depends of the type of PDU that is being acknowledged. We can simply - // extract the PDU type from the raw stream. If it is an EOF PDU, this packet is passed to - // the source handler, for a Finished PDU, it is passed to the destination handler. - FileDirective ackedDirective; - if (not AckPduReader::checkAckedDirectiveField(pduDataField[1], ackedDirective)) { - return INVALID_ACK_DIRECTIVE_FIELDS; - } - if (ackedDirective == FileDirective::EOF_DIRECTIVE) { - passToSourceHandler(); - } else if (ackedDirective == FileDirective::FINISH) { - passToDestHandler(); - } - } - } - return result; -} diff --git a/src/fsfw/cfdp/handler/CfdpHandler.h b/src/fsfw/cfdp/handler/CfdpHandler.h deleted file mode 100644 index 2de9f7dd..00000000 --- a/src/fsfw/cfdp/handler/CfdpHandler.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef FSFW_EXAMPLE_HOSTED_CFDPHANDLER_H -#define FSFW_EXAMPLE_HOSTED_CFDPHANDLER_H - -#include - -#include "fsfw/cfdp/handler/DestHandler.h" -#include "fsfw/objectmanager/SystemObject.h" -#include "fsfw/tasks/ExecutableObjectIF.h" -#include "fsfw/tmtcservices/AcceptsTelecommandsIF.h" -#include "fsfw/tmtcservices/TmTcMessage.h" - -struct FsfwHandlerParams { - FsfwHandlerParams(object_id_t objectId, HasFileSystemIF& vfs, AcceptsTelemetryIF& packetDest, - StorageManagerIF& tcStore, StorageManagerIF& tmStore, MessageQueueIF& msgQueue) - : objectId(objectId), - vfs(vfs), - packetDest(packetDest), - tcStore(tcStore), - tmStore(tmStore), - msgQueue(msgQueue) {} - object_id_t objectId{}; - HasFileSystemIF& vfs; - AcceptsTelemetryIF& packetDest; - StorageManagerIF& tcStore; - StorageManagerIF& tmStore; - MessageQueueIF& msgQueue; -}; - -struct CfdpHandlerCfg { - CfdpHandlerCfg(cfdp::EntityId localId, cfdp::IndicationCfg indicationCfg, - cfdp::UserBase& userHandler, cfdp::FaultHandlerBase& userFaultHandler, - cfdp::PacketInfoListBase& packetInfo, cfdp::LostSegmentsListBase& lostSegmentsList, - cfdp::RemoteConfigTableIF& remoteCfgProvider) - : id(std::move(localId)), - indicCfg(indicationCfg), - packetInfoList(packetInfo), - lostSegmentsList(lostSegmentsList), - remoteCfgProvider(remoteCfgProvider), - userHandler(userHandler), - faultHandler(userFaultHandler) {} - - cfdp::EntityId id; - cfdp::IndicationCfg indicCfg; - cfdp::PacketInfoListBase& packetInfoList; - cfdp::LostSegmentsListBase& lostSegmentsList; - cfdp::RemoteConfigTableIF& remoteCfgProvider; - cfdp::UserBase& userHandler; - cfdp::FaultHandlerBase& faultHandler; -}; - -class CfdpHandler : public SystemObject, public ExecutableObjectIF, public AcceptsTelecommandsIF { - public: - explicit CfdpHandler(const FsfwHandlerParams& fsfwParams, const CfdpHandlerCfg& cfdpCfg); - - [[nodiscard]] const char* getName() const override; - [[nodiscard]] uint32_t getIdentifier() const override; - [[nodiscard]] MessageQueueId_t getRequestQueue() const override; - - ReturnValue_t initialize() override; - ReturnValue_t performOperation(uint8_t operationCode) override; - - private: - MessageQueueIF& msgQueue; - cfdp::DestHandler destHandler; - StorageManagerIF* tcStore = nullptr; - StorageManagerIF* tmStore = nullptr; - - ReturnValue_t handleCfdpPacket(TmTcMessage& msg); -}; - -#endif // FSFW_EXAMPLE_HOSTED_CFDPHANDLER_H diff --git a/src/fsfw/cfdp/pdu/HeaderCreator.cpp b/src/fsfw/cfdp/pdu/HeaderCreator.cpp index 29688575..2db3953c 100644 --- a/src/fsfw/cfdp/pdu/HeaderCreator.cpp +++ b/src/fsfw/cfdp/pdu/HeaderCreator.cpp @@ -24,8 +24,8 @@ ReturnValue_t HeaderCreator::serialize(uint8_t **buffer, size_t *size, size_t ma *buffer += 1; **buffer = pduDataFieldLen & 0x00ff; *buffer += 1; - **buffer = segmentationCtrl << 7 | pduConf.sourceId.getWidth() << 4 | segmentMetadataFlag << 3 | - pduConf.seqNum.getWidth(); + **buffer = segmentationCtrl << 7 | ((pduConf.sourceId.getWidth() - 1) << 4) | + segmentMetadataFlag << 3 | (pduConf.seqNum.getWidth() - 1); *buffer += 1; *size += 4; ReturnValue_t result = pduConf.sourceId.serialize(buffer, size, maxSize, streamEndianness); diff --git a/src/fsfw/cfdp/pdu/HeaderReader.cpp b/src/fsfw/cfdp/pdu/HeaderReader.cpp index 9edf2394..de3d2906 100644 --- a/src/fsfw/cfdp/pdu/HeaderReader.cpp +++ b/src/fsfw/cfdp/pdu/HeaderReader.cpp @@ -78,11 +78,11 @@ cfdp::SegmentationControl PduHeaderReader::getSegmentationControl() const { } cfdp::WidthInBytes PduHeaderReader::getLenEntityIds() const { - return static_cast((pointers.fixedHeader->fourthByte >> 4) & 0x07); + return static_cast(((pointers.fixedHeader->fourthByte >> 4) & 0b111) + 1); } cfdp::WidthInBytes PduHeaderReader::getLenSeqNum() const { - return static_cast(pointers.fixedHeader->fourthByte & 0x07); + return static_cast((pointers.fixedHeader->fourthByte & 0b111) + 1); } cfdp::SegmentMetadataFlag PduHeaderReader::getSegmentMetadataFlag() const { diff --git a/src/fsfw/controller/ControllerBase.cpp b/src/fsfw/controller/ControllerBase.cpp index c41c4121..2c151f5a 100644 --- a/src/fsfw/controller/ControllerBase.cpp +++ b/src/fsfw/controller/ControllerBase.cpp @@ -58,7 +58,7 @@ void ControllerBase::handleQueue() { void ControllerBase::startTransition(Mode_t mode_, Submode_t submode_) { changeHK(this->mode, this->submode, false); - triggerEvent(CHANGING_MODE, mode, submode); + triggerEvent(CHANGING_MODE, mode_, submode_); mode = mode_; submode = submode_; modeHelper.modeChanged(mode, submode); diff --git a/src/fsfw/coordinates/Sgp4Propagator.cpp b/src/fsfw/coordinates/Sgp4Propagator.cpp index e79ffef5..62c2670e 100644 --- a/src/fsfw/coordinates/Sgp4Propagator.cpp +++ b/src/fsfw/coordinates/Sgp4Propagator.cpp @@ -166,9 +166,9 @@ ReturnValue_t Sgp4Propagator::propagate(double* position, double* velocity, time timeval timeSinceEpoch = time - epoch; double minutesSinceEpoch = timeSinceEpoch.tv_sec / 60. + timeSinceEpoch.tv_usec / 60000000.; - double yearsSinceEpoch = minutesSinceEpoch / 60 / 24 / 365; + double monthsSinceEpoch = minutesSinceEpoch / 60 / 24 / 30; - if ((yearsSinceEpoch > 1) || (yearsSinceEpoch < -1)) { + if ((monthsSinceEpoch > 1) || (monthsSinceEpoch < -1)) { return TLE_TOO_OLD; } diff --git a/src/fsfw/datapoollocal/LocalDataPoolManager.cpp b/src/fsfw/datapoollocal/LocalDataPoolManager.cpp index f66a328c..32de8e6b 100644 --- a/src/fsfw/datapoollocal/LocalDataPoolManager.cpp +++ b/src/fsfw/datapoollocal/LocalDataPoolManager.cpp @@ -505,9 +505,9 @@ ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage(CommandMessage* me float newCollIntvl = 0; HousekeepingMessage::getCollectionIntervalModificationCommand(message, &newCollIntvl); if (command == HousekeepingMessage::MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL) { - result = changeCollectionInterval(sid, newCollIntvl, true); + result = changeCollectionInterval(sid, newCollIntvl); } else { - result = changeCollectionInterval(sid, newCollIntvl, false); + result = changeCollectionInterval(sid, newCollIntvl); } break; } @@ -720,8 +720,8 @@ ReturnValue_t LocalDataPoolManager::togglePeriodicGeneration(sid_t sid, bool ena return returnvalue::OK; } -ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid, float newCollectionInterval, - bool isDiagnostics) { +ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid, + float newCollectionInterval) { LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid); if (dataSet == nullptr) { printWarningOrError(sif::OutputTypes::OUT_WARNING, "changeCollectionInterval", @@ -729,11 +729,6 @@ ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid, float ne return DATASET_NOT_FOUND; } - bool targetIsDiagnostics = LocalPoolDataSetAttorney::isDiagnostics(*dataSet); - if ((targetIsDiagnostics and not isDiagnostics) or (not targetIsDiagnostics and isDiagnostics)) { - return WRONG_HK_PACKET_TYPE; - } - PeriodicHousekeepingHelper* periodicHelper = LocalPoolDataSetAttorney::getPeriodicHelper(*dataSet); diff --git a/src/fsfw/datapoollocal/LocalDataPoolManager.h b/src/fsfw/datapoollocal/LocalDataPoolManager.h index 65d58d59..cd0d4f62 100644 --- a/src/fsfw/datapoollocal/LocalDataPoolManager.h +++ b/src/fsfw/datapoollocal/LocalDataPoolManager.h @@ -174,6 +174,7 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces ReturnValue_t generateHousekeepingPacket(sid_t sid, LocalPoolDataSetBase* dataSet, bool forDownlink, MessageQueueId_t destination = MessageQueueIF::NO_QUEUE); + ReturnValue_t changeCollectionInterval(sid_t sid, float newCollectionInterval); HasLocalDataPoolIF* getOwner(); @@ -337,8 +338,6 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces void performPeriodicHkGeneration(HkReceiver& hkReceiver); ReturnValue_t togglePeriodicGeneration(sid_t sid, bool enable, bool isDiagnostics); - ReturnValue_t changeCollectionInterval(sid_t sid, float newCollectionInterval, - bool isDiagnostics); ReturnValue_t generateSetStructurePacket(sid_t sid, bool isDiagnostics); void handleHkUpdateResetListInsertion(DataType dataType, DataId dataId); diff --git a/src/fsfw/devicehandlers/DeviceCommunicationIF.h b/src/fsfw/devicehandlers/DeviceCommunicationIF.h index a5546a36..cf827240 100644 --- a/src/fsfw/devicehandlers/DeviceCommunicationIF.h +++ b/src/fsfw/devicehandlers/DeviceCommunicationIF.h @@ -49,6 +49,7 @@ class DeviceCommunicationIF { // is this needed if there is no open/close call? static const ReturnValue_t NOT_ACTIVE = MAKE_RETURN_CODE(0x05); static const ReturnValue_t TOO_MUCH_DATA = MAKE_RETURN_CODE(0x06); + static constexpr ReturnValue_t BUSY = MAKE_RETURN_CODE(0x07); virtual ~DeviceCommunicationIF() {} diff --git a/src/fsfw/devicehandlers/DeviceHandlerBase.cpp b/src/fsfw/devicehandlers/DeviceHandlerBase.cpp index 99b7496c..00d6c451 100644 --- a/src/fsfw/devicehandlers/DeviceHandlerBase.cpp +++ b/src/fsfw/devicehandlers/DeviceHandlerBase.cpp @@ -567,7 +567,7 @@ void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) { continueToNormal = false; // TODO: Check whether the following two lines are okay to do so. transitionSourceMode = MODE_ON; - transitionSourceSubMode = submode; + transitionSourceSubMode = newSubmode; mode = _MODE_TO_NORMAL; return; } diff --git a/src/fsfw/devicehandlers/DeviceHandlerBase.h b/src/fsfw/devicehandlers/DeviceHandlerBase.h index 57e9d982..08298bdc 100644 --- a/src/fsfw/devicehandlers/DeviceHandlerBase.h +++ b/src/fsfw/devicehandlers/DeviceHandlerBase.h @@ -257,8 +257,8 @@ class DeviceHandlerBase : public DeviceHandlerIF, Mode_t getTransitionSourceMode() const; Submode_t getTransitionSourceSubMode() const; virtual void getMode(Mode_t *mode, Submode_t *submode); - HealthState getHealth(); - ReturnValue_t setHealth(HealthState health); + virtual HealthState getHealth() override; + virtual ReturnValue_t setHealth(HealthState health) override; virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId, ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues, diff --git a/src/fsfw/devicehandlers/DeviceHandlerFailureIsolation.cpp b/src/fsfw/devicehandlers/DeviceHandlerFailureIsolation.cpp index 20e141c3..d3e5753f 100644 --- a/src/fsfw/devicehandlers/DeviceHandlerFailureIsolation.cpp +++ b/src/fsfw/devicehandlers/DeviceHandlerFailureIsolation.cpp @@ -10,8 +10,9 @@ object_id_t DeviceHandlerFailureIsolation::powerConfirmationId = objects::NO_OBJECT; -DeviceHandlerFailureIsolation::DeviceHandlerFailureIsolation(object_id_t owner, object_id_t parent) - : FailureIsolationBase(owner, parent), +DeviceHandlerFailureIsolation::DeviceHandlerFailureIsolation(object_id_t owner, object_id_t parent, + uint8_t eventQueueDepth) + : FailureIsolationBase(owner, parent, eventQueueDepth), strangeReplyCount(DEFAULT_MAX_STRANGE_REPLIES, DEFAULT_STRANGE_REPLIES_TIME_MS, parameterDomainBase++), missedReplyCount(DEFAULT_MAX_MISSED_REPLY_COUNT, DEFAULT_MISSED_REPLY_TIME_MS, diff --git a/src/fsfw/devicehandlers/DeviceHandlerFailureIsolation.h b/src/fsfw/devicehandlers/DeviceHandlerFailureIsolation.h index 6007ceb8..4835af99 100644 --- a/src/fsfw/devicehandlers/DeviceHandlerFailureIsolation.h +++ b/src/fsfw/devicehandlers/DeviceHandlerFailureIsolation.h @@ -13,7 +13,8 @@ class DeviceHandlerFailureIsolation : public FailureIsolationBase { friend class Heater; public: - DeviceHandlerFailureIsolation(object_id_t owner, object_id_t parent); + DeviceHandlerFailureIsolation(object_id_t owner, object_id_t parent, + uint8_t eventQueueDepth = 10); ~DeviceHandlerFailureIsolation(); ReturnValue_t initialize(); void triggerEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0); diff --git a/src/fsfw/devicehandlers/HealthDevice.cpp b/src/fsfw/devicehandlers/HealthDevice.cpp index 717fadd1..d3a70c77 100644 --- a/src/fsfw/devicehandlers/HealthDevice.cpp +++ b/src/fsfw/devicehandlers/HealthDevice.cpp @@ -29,11 +29,10 @@ ReturnValue_t HealthDevice::initialize() { if (result != returnvalue::OK) { return result; } - if (parentQueue != 0) { + if (parentQueue != MessageQueueIF::NO_QUEUE) { return healthHelper.initialize(parentQueue); - } else { - return healthHelper.initialize(); } + return healthHelper.initialize(); } MessageQueueId_t HealthDevice::getCommandQueue() const { return commandQueue->getId(); } diff --git a/src/fsfw/devicehandlers/HealthDevice.h b/src/fsfw/devicehandlers/HealthDevice.h index f4c3520f..a5c28cf7 100644 --- a/src/fsfw/devicehandlers/HealthDevice.h +++ b/src/fsfw/devicehandlers/HealthDevice.h @@ -29,10 +29,8 @@ class HealthDevice : public SystemObject, public ExecutableObjectIF, public HasH protected: HealthState lastHealth; - MessageQueueId_t parentQueue; + MessageQueueId_t parentQueue = MessageQueueIF::NO_QUEUE; MessageQueueIF* commandQueue; - - public: HealthHelper healthHelper; }; diff --git a/src/fsfw/events/EventManager.cpp b/src/fsfw/events/EventManager.cpp index f2a099ed..f5cc99c6 100644 --- a/src/fsfw/events/EventManager.cpp +++ b/src/fsfw/events/EventManager.cpp @@ -55,8 +55,9 @@ void EventManager::notifyListeners(EventMessage* message) { if (result != returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << std::hex << "EventManager::notifyListeners: MSG to 0x" << std::setfill('0') - << std::setw(8) << listener.first << " failed with result 0x" << std::setw(4) - << result << std::setfill(' ') << std::endl; + << std::setw(8) << listener.first << " for event 0x" << std::setw(4) + << message->getEventId() << " failed with result 0x" << std::setw(4) << result + << std::setfill(' ') << std::endl; #else sif::printError("Sending message to listener 0x%08x failed with result %04x\n", listener.first, result); diff --git a/src/fsfw/globalfunctions/DleParser.h b/src/fsfw/globalfunctions/DleParser.h index 9802017a..48df0543 100644 --- a/src/fsfw/globalfunctions/DleParser.h +++ b/src/fsfw/globalfunctions/DleParser.h @@ -18,8 +18,11 @@ */ class DleParser { public: + //! [EXPORT] : [SKIP] static constexpr ReturnValue_t NO_PACKET_FOUND = returnvalue::makeCode(1, 1); + //! [EXPORT] : [SKIP] static constexpr ReturnValue_t POSSIBLE_PACKET_LOSS = returnvalue::makeCode(1, 2); + using BufPair = std::pair; enum class ContextType { NONE, PACKET_FOUND, ERROR }; diff --git a/src/fsfw/globalfunctions/math/VectorOperations.h b/src/fsfw/globalfunctions/math/VectorOperations.h index 197cd46a..b8f6b00f 100644 --- a/src/fsfw/globalfunctions/math/VectorOperations.h +++ b/src/fsfw/globalfunctions/math/VectorOperations.h @@ -53,8 +53,9 @@ class VectorOperations { mulScalar(vector, 1 / norm(vector, size), normalizedVector, size); } - static T maxAbsValue(const T *vector, uint8_t size, uint8_t *index = 0) { - T max = -1; + static T maxAbsValue(const T *vector, uint8_t size, uint8_t *index = nullptr) { + T max = vector[size - 1]; + uint8_t foundIndex = size - 1; for (; size > 0; size--) { T abs = vector[size - 1]; @@ -64,24 +65,35 @@ class VectorOperations { if (abs > max) { max = abs; if (index != 0) { - *index = size - 1; + foundIndex = size - 1; } } } + + if (index != nullptr) { + *index = foundIndex; + } + return max; } - static T maxValue(const T *vector, uint8_t size, uint8_t *index = 0) { - T max = -1; + static T maxValue(const T *vector, uint8_t size, uint8_t *index = nullptr) { + T max = vector[size - 1]; + uint8_t foundIndex = size - 1; for (; size > 0; size--) { if (vector[size - 1] > max) { max = vector[size - 1]; if (index != 0) { - *index = size - 1; + foundIndex = size - 1; } } } + + if (index != nullptr) { + *index = foundIndex; + } + return max; } diff --git a/src/fsfw/housekeeping/PeriodicHousekeepingHelper.cpp b/src/fsfw/housekeeping/PeriodicHousekeepingHelper.cpp index b39e45c3..ec34330a 100644 --- a/src/fsfw/housekeeping/PeriodicHousekeepingHelper.cpp +++ b/src/fsfw/housekeeping/PeriodicHousekeepingHelper.cpp @@ -3,6 +3,7 @@ #include #include "fsfw/datapoollocal/LocalPoolDataSetBase.h" +#include "fsfw/serviceinterface.h" PeriodicHousekeepingHelper::PeriodicHousekeepingHelper(LocalPoolDataSetBase* owner) : owner(owner) {} @@ -10,51 +11,29 @@ PeriodicHousekeepingHelper::PeriodicHousekeepingHelper(LocalPoolDataSetBase* own void PeriodicHousekeepingHelper::initialize(float collectionInterval, dur_millis_t minimumPeriodicInterval) { this->minimumPeriodicInterval = minimumPeriodicInterval; - collectionIntervalTicks = intervalSecondsToIntervalTicks(collectionInterval); - /* This will cause a checkOpNecessary call to be true immediately. I think it's okay - if a HK packet is generated immediately instead of waiting one generation cycle. */ - internalTickCounter = collectionIntervalTicks; + changeCollectionInterval(collectionInterval); } float PeriodicHousekeepingHelper::getCollectionIntervalInSeconds() const { - return intervalTicksToSeconds(collectionIntervalTicks); + return collectionInterval; } bool PeriodicHousekeepingHelper::checkOpNecessary() { - if (internalTickCounter >= collectionIntervalTicks) { - internalTickCounter = 1; + if (hkGenerationCd.hasTimedOut()) { + hkGenerationCd.resetTimer(); return true; } - internalTickCounter++; return false; } -uint32_t PeriodicHousekeepingHelper::intervalSecondsToIntervalTicks( - float collectionIntervalSeconds) { - if (owner == nullptr) { - return 0; - } - - /* Avoid division by zero */ - if (minimumPeriodicInterval == 0) { - /* Perform operation each cycle */ - return 1; - - } else { - dur_millis_t intervalInMs = collectionIntervalSeconds * 1000; - uint32_t divisor = minimumPeriodicInterval; - uint32_t ticks = std::ceil(static_cast(intervalInMs) / divisor); - - return ticks; - } -} - -float PeriodicHousekeepingHelper::intervalTicksToSeconds(uint32_t collectionInterval) const { - /* Number of ticks times the minimum interval is in milliseconds, so we divide by 1000 to get - the value in seconds */ - return static_cast(collectionInterval * minimumPeriodicInterval / 1000.0); -} - void PeriodicHousekeepingHelper::changeCollectionInterval(float newIntervalSeconds) { - collectionIntervalTicks = intervalSecondsToIntervalTicks(newIntervalSeconds); + uint32_t intervalMs = newIntervalSeconds * 1000; + if (newIntervalSeconds <= 0) { + intervalMs = minimumPeriodicInterval; + newIntervalSeconds = static_cast(minimumPeriodicInterval) / 1000.0; + } + collectionInterval = newIntervalSeconds; + hkGenerationCd.setTimeout(intervalMs); + // We want an immediate HK packet at the start, so time out the generation CD immediately. + hkGenerationCd.timeOut(); } diff --git a/src/fsfw/housekeeping/PeriodicHousekeepingHelper.h b/src/fsfw/housekeeping/PeriodicHousekeepingHelper.h index 1ec0febf..1586649c 100644 --- a/src/fsfw/housekeeping/PeriodicHousekeepingHelper.h +++ b/src/fsfw/housekeeping/PeriodicHousekeepingHelper.h @@ -4,6 +4,7 @@ #include #include "fsfw/timemanager/Clock.h" +#include "fsfw/timemanager/Countdown.h" class LocalPoolDataSetBase; @@ -19,13 +20,10 @@ class PeriodicHousekeepingHelper { private: LocalPoolDataSetBase* owner = nullptr; - - uint32_t intervalSecondsToIntervalTicks(float collectionIntervalSeconds); - float intervalTicksToSeconds(uint32_t collectionInterval) const; + Countdown hkGenerationCd; + float collectionInterval = 0.0; dur_millis_t minimumPeriodicInterval = 0; - uint32_t internalTickCounter = 1; - uint32_t collectionIntervalTicks = 0; }; #endif /* FSFW_HOUSEKEEPING_PERIODICHOUSEKEEPINGHELPER_H_ */ diff --git a/src/fsfw/internalerror/InternalErrorReporter.cpp b/src/fsfw/internalerror/InternalErrorReporter.cpp index 69faacdd..44910801 100644 --- a/src/fsfw/internalerror/InternalErrorReporter.cpp +++ b/src/fsfw/internalerror/InternalErrorReporter.cpp @@ -5,9 +5,12 @@ #include "fsfw/ipc/QueueFactory.h" #include "fsfw/serviceinterface/ServiceInterface.h" -InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth) +InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth, + bool enableSetByDefault, float generationFrequency) : SystemObject(setObjectId), poolManager(this, commandQueue), + enableSetByDefault(enableSetByDefault), + generationFrequency(generationFrequency), internalErrorSid(setObjectId, InternalErrorDataset::ERROR_SET_ID), internalErrorDataset(this) { commandQueue = QueueFactory::instance()->createMessageQueue(messageQueueDepth); @@ -134,9 +137,8 @@ ReturnValue_t InternalErrorReporter::initializeLocalDataPool(localpool::DataPool localDataPoolMap.emplace(errorPoolIds::TM_HITS, &tmHitsEntry); localDataPoolMap.emplace(errorPoolIds::QUEUE_HITS, &queueHitsEntry); localDataPoolMap.emplace(errorPoolIds::STORE_HITS, &storeHitsEntry); - poolManager.subscribeForDiagPeriodicPacket(subdp::DiagnosticsHkPeriodicParams( - internalErrorSid, false, - static_cast(getPeriodicOperationFrequency()) / static_cast(1000.0))); + poolManager.subscribeForRegularPeriodicPacket( + subdp::RegularHkPeriodicParams(internalErrorSid, enableSetByDefault, generationFrequency)); internalErrorDataset.setValidity(true, true); return returnvalue::OK; } diff --git a/src/fsfw/internalerror/InternalErrorReporter.h b/src/fsfw/internalerror/InternalErrorReporter.h index ca82d1a4..f845410b 100644 --- a/src/fsfw/internalerror/InternalErrorReporter.h +++ b/src/fsfw/internalerror/InternalErrorReporter.h @@ -21,7 +21,8 @@ class InternalErrorReporter : public SystemObject, public InternalErrorReporterIF, public HasLocalDataPoolIF { public: - InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth = 5); + InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth, + bool enableSetByDefault, float generationFrequency); /** * Enable diagnostic printout. Please note that this feature will @@ -63,6 +64,8 @@ class InternalErrorReporter : public SystemObject, MutexIF* mutex = nullptr; MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING; uint32_t timeoutMs = 20; + bool enableSetByDefault; + float generationFrequency; sid_t internalErrorSid; InternalErrorDataset internalErrorDataset; diff --git a/src/fsfw/osal/host/TaskFactory.cpp b/src/fsfw/osal/host/TaskFactory.cpp index 0a27241b..d9552923 100644 --- a/src/fsfw/osal/host/TaskFactory.cpp +++ b/src/fsfw/osal/host/TaskFactory.cpp @@ -20,16 +20,18 @@ TaskFactory::~TaskFactory() = default; TaskFactory* TaskFactory::instance() { return TaskFactory::factoryInstance; } -PeriodicTaskIF* TaskFactory::createPeriodicTask( - TaskName name_, TaskPriority taskPriority_, TaskStackSize stackSize_, - TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_) { +PeriodicTaskIF* TaskFactory::createPeriodicTask(TaskName name_, TaskPriority taskPriority_, + TaskStackSize stackSize_, + TaskPeriod periodInSeconds_, + TaskDeadlineMissedFunction deadLineMissedFunction_, + void* args) { return new PeriodicTask(name_, taskPriority_, stackSize_, periodInSeconds_, deadLineMissedFunction_); } FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask( TaskName name_, TaskPriority taskPriority_, TaskStackSize stackSize_, - TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_) { + TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_, void* args) { return new FixedTimeslotTask(name_, taskPriority_, stackSize_, periodInSeconds_, deadLineMissedFunction_); } diff --git a/src/fsfw/osal/linux/Clock.cpp b/src/fsfw/osal/linux/Clock.cpp index fd861da2..209dba56 100644 --- a/src/fsfw/osal/linux/Clock.cpp +++ b/src/fsfw/osal/linux/Clock.cpp @@ -89,8 +89,6 @@ timeval Clock::getUptime() { } ReturnValue_t Clock::getUptime(timeval* uptime) { - // TODO This is not posix compatible and delivers only seconds precision - // Linux specific file read but more precise. double uptimeSeconds; std::ifstream ifile("/proc/uptime"); if (ifile.bad()) { diff --git a/src/fsfw/osal/linux/FixedTimeslotTask.cpp b/src/fsfw/osal/linux/FixedTimeslotTask.cpp index 34729c22..0709f52f 100644 --- a/src/fsfw/osal/linux/FixedTimeslotTask.cpp +++ b/src/fsfw/osal/linux/FixedTimeslotTask.cpp @@ -7,10 +7,15 @@ const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = PTHREAD_STACK_MIN; FixedTimeslotTask::FixedTimeslotTask(const char* name_, TaskPriority priority_, size_t stackSize_, - TaskPeriod periodSeconds_, TaskDeadlineMissedFunction dlmFunc_) + TaskPeriod periodSeconds_, TaskDeadlineMissedFunction dlmFunc_, + PosixThreadArgs* args) : FixedTimeslotTaskBase(periodSeconds_, dlmFunc_), - posixThread(name_, priority_, stackSize_), - started(false) {} + posixThread(name_, SchedulingPolicy::REGULAR, priority_, stackSize_), + started(false) { + if (args != nullptr) { + posixThread.setSchedPolicy(args->policy); + } +} void* FixedTimeslotTask::taskEntryPoint(void* arg) { // The argument is re-interpreted as PollingTask. diff --git a/src/fsfw/osal/linux/FixedTimeslotTask.h b/src/fsfw/osal/linux/FixedTimeslotTask.h index 1f5766a2..0957bedc 100644 --- a/src/fsfw/osal/linux/FixedTimeslotTask.h +++ b/src/fsfw/osal/linux/FixedTimeslotTask.h @@ -23,7 +23,8 @@ class FixedTimeslotTask : public FixedTimeslotTaskBase { * @param deadlineMissedFunc_ */ FixedTimeslotTask(const char* name_, TaskPriority priority_, size_t stackSize_, - TaskPeriod periodSeconds_, TaskDeadlineMissedFunction dlmFunc_); + TaskPeriod periodSeconds_, TaskDeadlineMissedFunction dlmFunc_, + PosixThreadArgs* args); ~FixedTimeslotTask() override = default; ReturnValue_t startTask() override; diff --git a/src/fsfw/osal/linux/PeriodicPosixTask.cpp b/src/fsfw/osal/linux/PeriodicPosixTask.cpp index 556a0367..5f1256d7 100644 --- a/src/fsfw/osal/linux/PeriodicPosixTask.cpp +++ b/src/fsfw/osal/linux/PeriodicPosixTask.cpp @@ -4,10 +4,15 @@ #include "fsfw/tasks/ExecutableObjectIF.h" PeriodicPosixTask::PeriodicPosixTask(const char* name_, int priority_, size_t stackSize_, - TaskPeriod period_, TaskDeadlineMissedFunction dlmFunc_) + TaskPeriod period_, TaskDeadlineMissedFunction dlmFunc_, + PosixThreadArgs* args) : PeriodicTaskBase(period_, dlmFunc_), - posixThread(name_, priority_, stackSize_), - started(false) {} + posixThread(name_, SchedulingPolicy::REGULAR, priority_, stackSize_), + started(false) { + if (args != nullptr) { + posixThread.setSchedPolicy(args->policy); + } +} void* PeriodicPosixTask::taskEntryPoint(void* arg) { // The argument is re-interpreted as PollingTask. diff --git a/src/fsfw/osal/linux/PeriodicPosixTask.h b/src/fsfw/osal/linux/PeriodicPosixTask.h index 085c10b9..eac14f0c 100644 --- a/src/fsfw/osal/linux/PeriodicPosixTask.h +++ b/src/fsfw/osal/linux/PeriodicPosixTask.h @@ -24,7 +24,7 @@ class PeriodicPosixTask : public PeriodicTaskBase { * @param deadlineMissedFunc_ */ PeriodicPosixTask(const char* name_, int priority_, size_t stackSize_, TaskPeriod period_, - TaskDeadlineMissedFunction dlmFunc_); + TaskDeadlineMissedFunction dlmFunc_, PosixThreadArgs* args); ~PeriodicPosixTask() override = default; /** diff --git a/src/fsfw/osal/linux/PosixThread.cpp b/src/fsfw/osal/linux/PosixThread.cpp index 811d58e2..f420b326 100644 --- a/src/fsfw/osal/linux/PosixThread.cpp +++ b/src/fsfw/osal/linux/PosixThread.cpp @@ -7,8 +7,9 @@ #include "fsfw/osal/linux/unixUtility.h" #include "fsfw/serviceinterface/ServiceInterface.h" -PosixThread::PosixThread(const char* name_, int priority_, size_t stackSize_) - : thread(0), priority(priority_), stackSize(stackSize_) { +PosixThread::PosixThread(const char* name_, SchedulingPolicy schedPolciy, int priority_, + size_t stackSize_) + : thread(0), schedPolicy(schedPolciy), priority(priority_), stackSize(stackSize_) { name[0] = '\0'; std::strncat(name, name_, PTHREAD_MAX_NAMELEN - 1); } @@ -178,20 +179,30 @@ void PosixThread::createTask(void* (*fnc_)(void*), void* arg_) { #ifndef FSFW_USE_REALTIME_FOR_LINUX #error "Please define FSFW_USE_REALTIME_FOR_LINUX with either 0 or 1" #endif + if (schedPolicy == SchedulingPolicy::RR) { + // RR -> This needs root privileges for the process #if FSFW_USE_REALTIME_FOR_LINUX == 1 - // FIFO -> This needs root privileges for the process - status = pthread_attr_setschedpolicy(&attributes, SCHED_FIFO); - if (status != 0) { - utility::printUnixErrorGeneric(CLASS_NAME, "createTask", "pthread_attr_setschedpolicy"); + status = pthread_attr_setschedpolicy(&attributes, SCHED_RR); + if (status != 0) { + utility::printUnixErrorGeneric(CLASS_NAME, "createTask", "pthread_attr_setschedpolicy"); + } + sched_param scheduleParams; + scheduleParams.sched_priority = priority; + status = pthread_attr_setschedparam(&attributes, &scheduleParams); + if (status != 0) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "PosixThread: Setting priority failed" << std::endl; +#endif + } +#else +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning + << "Real time priorities are only allowed if FSFW_USE_REALTIME_FOR_LINUX is set to 1" + << std::endl; +#endif +#endif } - sched_param scheduleParams; - scheduleParams.__sched_priority = priority; - status = pthread_attr_setschedparam(&attributes, &scheduleParams); - if (status != 0) { - utility::printUnixErrorGeneric(CLASS_NAME, "createTask", "pthread_attr_setschedparam"); - } -#endif // Set Signal Mask for suspend until startTask is called sigset_t waitSignal; sigemptyset(&waitSignal); @@ -243,3 +254,5 @@ void PosixThread::createTask(void* (*fnc_)(void*), void* arg_) { utility::printUnixErrorGeneric(CLASS_NAME, "createTask", "pthread_attr_destroy"); } } + +void PosixThread::setSchedPolicy(SchedulingPolicy policy) { this->schedPolicy = policy; } diff --git a/src/fsfw/osal/linux/PosixThread.h b/src/fsfw/osal/linux/PosixThread.h index add41bf6..133a9884 100644 --- a/src/fsfw/osal/linux/PosixThread.h +++ b/src/fsfw/osal/linux/PosixThread.h @@ -9,10 +9,15 @@ #include "../../returnvalues/returnvalue.h" +enum SchedulingPolicy { REGULAR, RR }; +struct PosixThreadArgs { + SchedulingPolicy policy = SchedulingPolicy::REGULAR; +}; + class PosixThread { public: static constexpr uint8_t PTHREAD_MAX_NAMELEN = 16; - PosixThread(const char* name_, int priority_, size_t stackSize_); + PosixThread(const char* name_, SchedulingPolicy schedPolicy, int priority_, size_t stackSize_); virtual ~PosixThread(); /** * Set the Thread to sleep state @@ -20,6 +25,9 @@ class PosixThread { * @return Returns Failed if sleep fails */ static ReturnValue_t sleep(uint64_t ns); + + void setSchedPolicy(SchedulingPolicy policy); + /** * @brief Function to suspend the task until SIGUSR1 was received * @@ -72,6 +80,7 @@ class PosixThread { private: char name[PTHREAD_MAX_NAMELEN]; + SchedulingPolicy schedPolicy; int priority; size_t stackSize = 0; diff --git a/src/fsfw/osal/linux/TaskFactory.cpp b/src/fsfw/osal/linux/TaskFactory.cpp index bacc4311..c93f3fde 100644 --- a/src/fsfw/osal/linux/TaskFactory.cpp +++ b/src/fsfw/osal/linux/TaskFactory.cpp @@ -12,18 +12,20 @@ TaskFactory::~TaskFactory() = default; TaskFactory* TaskFactory::instance() { return TaskFactory::factoryInstance; } -PeriodicTaskIF* TaskFactory::createPeriodicTask( - TaskName name_, TaskPriority taskPriority_, TaskStackSize stackSize_, - TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_) { +PeriodicTaskIF* TaskFactory::createPeriodicTask(TaskName name_, TaskPriority taskPriority_, + TaskStackSize stackSize_, + TaskPeriod periodInSeconds_, + TaskDeadlineMissedFunction deadLineMissedFunction_, + void* args) { return new PeriodicPosixTask(name_, taskPriority_, stackSize_, periodInSeconds_, - deadLineMissedFunction_); + deadLineMissedFunction_, reinterpret_cast(args)); } FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask( TaskName name_, TaskPriority taskPriority_, TaskStackSize stackSize_, - TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_) { + TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_, void* args) { return new FixedTimeslotTask(name_, taskPriority_, stackSize_, periodInSeconds_, - deadLineMissedFunction_); + deadLineMissedFunction_, reinterpret_cast(args)); } ReturnValue_t TaskFactory::deleteTask(PeriodicTaskIF* task) { diff --git a/src/fsfw/power/DummyPowerSwitcher.cpp b/src/fsfw/power/DummyPowerSwitcher.cpp index 952a5a57..80b4cc4a 100644 --- a/src/fsfw/power/DummyPowerSwitcher.cpp +++ b/src/fsfw/power/DummyPowerSwitcher.cpp @@ -6,7 +6,11 @@ DummyPowerSwitcher::DummyPowerSwitcher(object_id_t objectId, size_t numberOfSwit : SystemObject(objectId, registerGlobally), switcherList(numberOfSwitches), fuseList(numberOfFuses), - switchDelayMs(switchDelayMs) {} + switchDelayMs(switchDelayMs) { + for (auto &switchState : switcherList) { + switchState = PowerSwitchIF::SWITCH_UNKNOWN; + } +} void DummyPowerSwitcher::setInitialSwitcherList(std::vector switcherList) { this->switcherList = switcherList; diff --git a/src/fsfw/power/PowerSwitcherComponent.h b/src/fsfw/power/PowerSwitcherComponent.h index d6fc06cd..8c74e76f 100644 --- a/src/fsfw/power/PowerSwitcherComponent.h +++ b/src/fsfw/power/PowerSwitcherComponent.h @@ -42,7 +42,7 @@ class PowerSwitcherComponent : public SystemObject, private: MessageQueueIF *queue = nullptr; - Mode_t mode = MODE_OFF; + Mode_t mode = MODE_UNDEFINED; Submode_t submode = 0; ModeHelper modeHelper; diff --git a/src/fsfw/pus/Service3Housekeeping.cpp b/src/fsfw/pus/Service3Housekeeping.cpp index 0a51aa4b..c6fac20c 100644 --- a/src/fsfw/pus/Service3Housekeeping.cpp +++ b/src/fsfw/pus/Service3Housekeeping.cpp @@ -4,9 +4,10 @@ #include "fsfw/objectmanager/ObjectManager.h" #include "fsfw/pus/servicepackets/Service3Packets.h" -Service3Housekeeping::Service3Housekeeping(object_id_t objectId, uint16_t apid, uint8_t serviceId) - : CommandingServiceBase(objectId, apid, "PUS 3 HK", serviceId, NUM_OF_PARALLEL_COMMANDS, - COMMAND_TIMEOUT_SECONDS) {} +Service3Housekeeping::Service3Housekeeping(object_id_t objectId, uint16_t apid, uint8_t serviceId, + uint32_t queueDepth, uint8_t numParallelCommands) + : CommandingServiceBase(objectId, apid, "PUS 3 HK", serviceId, numParallelCommands, + COMMAND_TIMEOUT_SECONDS, queueDepth) {} Service3Housekeeping::~Service3Housekeeping() {} diff --git a/src/fsfw/pus/Service3Housekeeping.h b/src/fsfw/pus/Service3Housekeeping.h index 70f15762..10004bc6 100644 --- a/src/fsfw/pus/Service3Housekeeping.h +++ b/src/fsfw/pus/Service3Housekeeping.h @@ -28,7 +28,8 @@ class Service3Housekeeping : public CommandingServiceBase, public AcceptsHkPacke static constexpr uint8_t NUM_OF_PARALLEL_COMMANDS = 4; static constexpr uint16_t COMMAND_TIMEOUT_SECONDS = 60; - Service3Housekeeping(object_id_t objectId, uint16_t apid, uint8_t serviceId); + Service3Housekeeping(object_id_t objectId, uint16_t apid, uint8_t serviceId, uint32_t queueDepth, + uint8_t numParallelCommands); virtual ~Service3Housekeeping(); protected: diff --git a/src/fsfw/pus/Service8FunctionManagement.cpp b/src/fsfw/pus/Service8FunctionManagement.cpp index 8b7c6972..2607adca 100644 --- a/src/fsfw/pus/Service8FunctionManagement.cpp +++ b/src/fsfw/pus/Service8FunctionManagement.cpp @@ -9,11 +9,11 @@ #include "fsfw/serviceinterface/ServiceInterface.h" Service8FunctionManagement::Service8FunctionManagement(object_id_t objectId, uint16_t apid, - uint8_t serviceId, + uint8_t serviceId, size_t queueDepth, uint8_t numParallelCommands, uint16_t commandTimeoutSeconds) : CommandingServiceBase(objectId, apid, "PUS 8 Functional Commanding", serviceId, - numParallelCommands, commandTimeoutSeconds) {} + numParallelCommands, commandTimeoutSeconds, queueDepth) {} Service8FunctionManagement::~Service8FunctionManagement() {} diff --git a/src/fsfw/pus/Service8FunctionManagement.h b/src/fsfw/pus/Service8FunctionManagement.h index 38aaf4f4..0ec715b8 100644 --- a/src/fsfw/pus/Service8FunctionManagement.h +++ b/src/fsfw/pus/Service8FunctionManagement.h @@ -31,7 +31,8 @@ class Service8FunctionManagement : public CommandingServiceBase { public: Service8FunctionManagement(object_id_t objectId, uint16_t apid, uint8_t serviceId, - uint8_t numParallelCommands = 4, uint16_t commandTimeoutSeconds = 60); + size_t queueDepth, uint8_t numParallelCommands = 4, + uint16_t commandTimeoutSeconds = 60); ~Service8FunctionManagement() override; protected: diff --git a/src/fsfw/subsystem/SubsystemBase.cpp b/src/fsfw/subsystem/SubsystemBase.cpp index eccd447c..4f62a889 100644 --- a/src/fsfw/subsystem/SubsystemBase.cpp +++ b/src/fsfw/subsystem/SubsystemBase.cpp @@ -315,20 +315,7 @@ object_id_t SubsystemBase::getObjectId() const { return SystemObject::getObjectI 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; + return registerChild(child.getObjectId(), child.getModeIF().getCommandQueue()); } const HasHealthIF* SubsystemBase::getOptHealthIF() const { return this; } @@ -336,3 +323,19 @@ const HasHealthIF* SubsystemBase::getOptHealthIF() const { return this; } const HasModesIF& SubsystemBase::getModeIF() const { return *this; } ModeTreeChildIF& SubsystemBase::getModeTreeChildIF() { return *this; } + +ReturnValue_t SubsystemBase::registerChild(object_id_t childObjectId, MessageQueueId_t childQueue) { + ChildInfo info; + + // intentional to force an initial command during system startup + info.commandQueue = childQueue; + info.mode = HasModesIF::MODE_UNDEFINED; + info.submode = SUBMODE_NONE; + info.healthChanged = false; + + auto resultPair = childrenMap.emplace(childObjectId, info); + if (not resultPair.second) { + return COULD_NOT_INSERT_CHILD; + } + return returnvalue::OK; +} diff --git a/src/fsfw/subsystem/SubsystemBase.h b/src/fsfw/subsystem/SubsystemBase.h index c3886d61..072b4ca4 100644 --- a/src/fsfw/subsystem/SubsystemBase.h +++ b/src/fsfw/subsystem/SubsystemBase.h @@ -61,6 +61,8 @@ class SubsystemBase : public SystemObject, * COULD_NOT_INSERT_CHILD If the Child could not be added to the ChildrenMap */ ReturnValue_t registerChild(const ModeTreeChildIF &child) override; + // TODO: Add this to HasModeTreeChildrenIF. + ReturnValue_t registerChild(object_id_t childObjectId, MessageQueueId_t childQueue); ReturnValue_t initialize() override; diff --git a/src/fsfw/tasks/TaskFactory.h b/src/fsfw/tasks/TaskFactory.h index 828c533e..e9b96a77 100644 --- a/src/fsfw/tasks/TaskFactory.h +++ b/src/fsfw/tasks/TaskFactory.h @@ -47,7 +47,8 @@ class TaskFactory { */ PeriodicTaskIF* createPeriodicTask(TaskName name_, TaskPriority taskPriority_, TaskStackSize stackSize_, TaskPeriod periodInSeconds_, - TaskDeadlineMissedFunction deadLineMissedFunction_); + TaskDeadlineMissedFunction deadLineMissedFunction_, + void* args = nullptr); /** * The meaning for the variables for fixed timeslot tasks is the same as for periodic tasks. @@ -62,7 +63,8 @@ class TaskFactory { FixedTimeslotTaskIF* createFixedTimeslotTask(TaskName name_, TaskPriority taskPriority_, TaskStackSize stackSize_, TaskPeriod periodInSeconds_, - TaskDeadlineMissedFunction deadLineMissedFunction_); + TaskDeadlineMissedFunction deadLineMissedFunction_, + void* args = nullptr); /** * Function to be called to delete a task diff --git a/src/fsfw/tmtcpacket/pus/tm/PusTmCreator.h b/src/fsfw/tmtcpacket/pus/tm/PusTmCreator.h index 626d873e..19922b2f 100644 --- a/src/fsfw/tmtcpacket/pus/tm/PusTmCreator.h +++ b/src/fsfw/tmtcpacket/pus/tm/PusTmCreator.h @@ -40,7 +40,7 @@ struct PusTmParams { size_t dataLen) : secHeader(service, subservice, timeStamper), adapter(data, dataLen), sourceData(&adapter) {} PusTmSecHeader secHeader; - SerialBufferAdapter adapter; + SerialBufferAdapter adapter; const SerializeIF* sourceData = nullptr; }; diff --git a/src/fsfw/tmtcpacket/pus/tm/PusTmZcWriter.cpp b/src/fsfw/tmtcpacket/pus/tm/PusTmZcWriter.cpp index 6a9f6235..d897aff9 100644 --- a/src/fsfw/tmtcpacket/pus/tm/PusTmZcWriter.cpp +++ b/src/fsfw/tmtcpacket/pus/tm/PusTmZcWriter.cpp @@ -24,3 +24,9 @@ void PusTmZeroCopyWriter::updateErrorControl() { crcStart[0] = (crc16 >> 8) & 0xff; crcStart[1] = crc16 & 0xff; } + +void PusTmZeroCopyWriter::setMessageCount(uint16_t msgCount) { + size_t serSize = 0; + SerializeAdapter::serialize(&msgCount, const_cast(pointers.secHeaderStart + 3), + &serSize, 2, SerializeIF::Endianness::NETWORK); +} diff --git a/src/fsfw/tmtcpacket/pus/tm/PusTmZcWriter.h b/src/fsfw/tmtcpacket/pus/tm/PusTmZcWriter.h index 36c43f51..66ef1405 100644 --- a/src/fsfw/tmtcpacket/pus/tm/PusTmZcWriter.h +++ b/src/fsfw/tmtcpacket/pus/tm/PusTmZcWriter.h @@ -14,6 +14,7 @@ class PusTmZeroCopyWriter : public PusTmReader { PusTmZeroCopyWriter(TimeReaderIF& timeReader, uint8_t* data, size_t size); void setSequenceCount(uint16_t seqCount); + void setMessageCount(uint16_t msgCount); void updateErrorControl(); private: diff --git a/src/fsfw_hal/common/spi/spiCommon.h b/src/fsfw_hal/common/spi/spiCommon.h index bee86823..072363a5 100644 --- a/src/fsfw_hal/common/spi/spiCommon.h +++ b/src/fsfw_hal/common/spi/spiCommon.h @@ -5,8 +5,18 @@ namespace spi { +static constexpr uint8_t CLASS_ID = CLASS_ID::HAL_SPI; +static constexpr ReturnValue_t OPENING_FILE_FAILED = returnvalue::makeCode(CLASS_ID, 0); +/* Full duplex (ioctl) transfer failure */ +static constexpr ReturnValue_t FULL_DUPLEX_TRANSFER_FAILED = returnvalue::makeCode(CLASS_ID, 1); +/* Half duplex (read/write) transfer failure */ +static constexpr ReturnValue_t HALF_DUPLEX_TRANSFER_FAILED = returnvalue::makeCode(CLASS_ID, 2); +static constexpr ReturnValue_t TIMEOUT = returnvalue::makeCode(CLASS_ID, 3); +static constexpr ReturnValue_t BUSY = returnvalue::makeCode(CLASS_ID, 4); +static constexpr ReturnValue_t GENERIC_ERROR = returnvalue::makeCode(CLASS_ID, 5); + enum SpiModes : uint8_t { MODE_0, MODE_1, MODE_2, MODE_3 }; -} +} // namespace spi #endif /* FSFW_HAL_COMMON_SPI_SPICOMMON_H_ */ diff --git a/src/fsfw_hal/devicehandlers/devicedefinitions/gyroL3gHelpers.h b/src/fsfw_hal/devicehandlers/devicedefinitions/gyroL3gHelpers.h index 4aef6811..0135a04c 100644 --- a/src/fsfw_hal/devicehandlers/devicedefinitions/gyroL3gHelpers.h +++ b/src/fsfw_hal/devicehandlers/devicedefinitions/gyroL3gHelpers.h @@ -73,8 +73,10 @@ static constexpr uint8_t CTRL_REG_4_VAL = SET_BLE; /* Register 5 */ static constexpr uint8_t SET_REBOOT_MEM = 1 << 7; static constexpr uint8_t SET_FIFO_ENB = 1 << 6; +static constexpr uint8_t SET_OUT_SEL_1 = 1 << 1; +static constexpr uint8_t SET_OUT_SEL_0 = 1 << 0; -static constexpr uint8_t CTRL_REG_5_VAL = 0b00000000; +static constexpr uint8_t CTRL_REG_5_VAL = SET_OUT_SEL_1 | SET_OUT_SEL_0; /* Possible range values in degrees per second (DPS). */ static constexpr uint16_t RANGE_DPS_00 = 245; diff --git a/src/fsfw_hal/host/HostFilesystem.cpp b/src/fsfw_hal/host/HostFilesystem.cpp index 315ba422..20984f77 100644 --- a/src/fsfw_hal/host/HostFilesystem.cpp +++ b/src/fsfw_hal/host/HostFilesystem.cpp @@ -165,7 +165,8 @@ ReturnValue_t HostFilesystem::truncateFile(FilesystemParams params) { if (not filesystem::exists(path, e)) { return FILE_DOES_NOT_EXIST; } - ofstream of(path); + // Specify truncation flug explicitely. + ofstream of(path, std::ios::out | std::ios::trunc); return returnvalue::OK; } diff --git a/src/fsfw_hal/linux/serial/SerialComIF.cpp b/src/fsfw_hal/linux/serial/SerialComIF.cpp index 177d74e4..f272e787 100644 --- a/src/fsfw_hal/linux/serial/SerialComIF.cpp +++ b/src/fsfw_hal/linux/serial/SerialComIF.cpp @@ -88,11 +88,11 @@ int SerialComIF::configureUartPort(SerialCookie* uartCookie) { return fd; } - uart::setParity(options, uartCookie->getParity()); + serial::setParity(options, uartCookie->getParity()); setStopBitOptions(&options, uartCookie); setDatasizeOptions(&options, uartCookie); setFixedOptions(&options); - uart::setMode(options, uartCookie->getUartMode()); + serial::setMode(options, uartCookie->getUartMode()); if (uartCookie->getInputShouldBeFlushed()) { tcflush(fd, TCIFLUSH); } @@ -101,7 +101,7 @@ int SerialComIF::configureUartPort(SerialCookie* uartCookie) { options.c_cc[VTIME] = 0; options.c_cc[VMIN] = 0; - uart::setBaudrate(options, uartCookie->getBaudrate()); + serial::setBaudrate(options, uartCookie->getBaudrate()); /* Save option settings */ if (tcsetattr(fd, TCSANOW, &options) != 0) { diff --git a/src/fsfw_hal/linux/serial/helper.cpp b/src/fsfw_hal/linux/serial/helper.cpp index ba975f2f..c58689c0 100644 --- a/src/fsfw_hal/linux/serial/helper.cpp +++ b/src/fsfw_hal/linux/serial/helper.cpp @@ -3,7 +3,7 @@ #include "fsfw/serviceinterface.h" -void uart::setMode(struct termios& options, UartModes mode) { +void serial::setMode(struct termios& options, UartModes mode) { if (mode == UartModes::NON_CANONICAL) { /* Disable canonical mode */ options.c_lflag &= ~ICANON; @@ -12,7 +12,7 @@ void uart::setMode(struct termios& options, UartModes mode) { } } -void uart::setBaudrate(struct termios& options, UartBaudRate baud) { +void serial::setBaudrate(struct termios& options, UartBaudRate baud) { switch (baud) { case UartBaudRate::RATE_50: cfsetspeed(&options, B50); @@ -114,7 +114,7 @@ void uart::setBaudrate(struct termios& options, UartBaudRate baud) { } } -void uart::setBitsPerWord(struct termios& options, BitsPerWord bits) { +void serial::setBitsPerWord(struct termios& options, BitsPerWord bits) { options.c_cflag &= ~CSIZE; // Clear all the size bits if (bits == BitsPerWord::BITS_5) { options.c_cflag |= CS5; @@ -127,11 +127,11 @@ void uart::setBitsPerWord(struct termios& options, BitsPerWord bits) { } } -void uart::enableRead(struct termios& options) { options.c_cflag |= CREAD; } +void serial::enableRead(struct termios& options) { options.c_cflag |= CREAD; } -void uart::ignoreCtrlLines(struct termios& options) { options.c_cflag |= CLOCAL; } +void serial::ignoreCtrlLines(struct termios& options) { options.c_cflag |= CLOCAL; } -void uart::setParity(struct termios& options, Parity parity) { +void serial::setParity(struct termios& options, Parity parity) { /* Clear parity bit */ options.c_cflag &= ~PARENB; switch (parity) { @@ -148,11 +148,11 @@ void uart::setParity(struct termios& options, Parity parity) { } } -int uart::readCountersAndErrors(int serialPort, serial_icounter_struct& icounter) { +int serial::readCountersAndErrors(int serialPort, serial_icounter_struct& icounter) { return ioctl(serialPort, TIOCGICOUNT, &icounter); } -void uart::setStopbits(struct termios& options, StopBits bits) { +void serial::setStopbits(struct termios& options, StopBits bits) { if (bits == StopBits::TWO_STOP_BITS) { // Use two stop bits options.c_cflag |= CSTOPB; @@ -161,3 +161,7 @@ void uart::setStopbits(struct termios& options, StopBits bits) { options.c_cflag &= ~CSTOPB; } } + +void serial::flushRxBuf(int fd) { tcflush(fd, TCIFLUSH); } + +void serial::flushTxRxBuf(int fd) { tcflush(fd, TCIOFLUSH); } diff --git a/src/fsfw_hal/linux/serial/helper.h b/src/fsfw_hal/linux/serial/helper.h index 7f067d00..623612ad 100644 --- a/src/fsfw_hal/linux/serial/helper.h +++ b/src/fsfw_hal/linux/serial/helper.h @@ -45,7 +45,7 @@ enum class UartBaudRate { RATE_4000000 }; -namespace uart { +namespace serial { void setMode(struct termios& options, UartModes mode); /** @@ -64,8 +64,11 @@ void setParity(struct termios& options, Parity parity); void ignoreCtrlLines(struct termios& options); +void flushRxBuf(int fd); +void flushTxRxBuf(int fd); + int readCountersAndErrors(int serialPort, serial_icounter_struct& icounter); -} // namespace uart +} // namespace serial #endif /* FSFW_HAL_LINUX_UART_HELPER_H_ */ diff --git a/src/fsfw_hal/linux/spi/SpiComIF.cpp b/src/fsfw_hal/linux/spi/SpiComIF.cpp index d285b120..f227c685 100644 --- a/src/fsfw_hal/linux/spi/SpiComIF.cpp +++ b/src/fsfw_hal/linux/spi/SpiComIF.cpp @@ -173,7 +173,7 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const int fileDescriptor = 0; UnixFileGuard fileHelper(dev, fileDescriptor, O_RDWR, "SpiComIF::sendMessage"); if (fileHelper.getOpenResult() != returnvalue::OK) { - return OPENING_FILE_FAILED; + return spi::OPENING_FILE_FAILED; } spi::SpiModes spiMode = spi::SpiModes::MODE_0; uint32_t spiSpeed = 0; @@ -234,7 +234,7 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const if (retval < 0) { spiCookie->setTransferSize(0); utility::handleIoctlError("SpiComIF::sendMessage: ioctl error."); - result = FULL_DUPLEX_TRANSFER_FAILED; + result = spi::FULL_DUPLEX_TRANSFER_FAILED; } #if FSFW_HAL_SPI_WIRETAPPING == 1 performSpiWiretapping(spiCookie); @@ -250,7 +250,7 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const sif::printWarning("SpiComIF::sendMessage: Half-Duplex write operation failed!\n"); #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ #endif /* FSFW_VERBOSE_LEVEL >= 1 */ - result = HALF_DUPLEX_TRANSFER_FAILED; + result = spi::HALF_DUPLEX_TRANSFER_FAILED; } } @@ -287,7 +287,7 @@ ReturnValue_t SpiComIF::performHalfDuplexReception(SpiCookie* spiCookie) { int fileDescriptor = 0; UnixFileGuard fileHelper(dev, fileDescriptor, O_RDWR, "SpiComIF::requestReceiveMessage"); if (fileHelper.getOpenResult() != returnvalue::OK) { - return OPENING_FILE_FAILED; + return spi::OPENING_FILE_FAILED; } uint8_t* rxBuf = nullptr; @@ -327,7 +327,7 @@ ReturnValue_t SpiComIF::performHalfDuplexReception(SpiCookie* spiCookie) { sif::printWarning("SpiComIF::sendMessage: Half-Duplex read operation failed!\n"); #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ #endif /* FSFW_VERBOSE_LEVEL >= 1 */ - result = HALF_DUPLEX_TRANSFER_FAILED; + result = spi::HALF_DUPLEX_TRANSFER_FAILED; } if (gpioId != gpio::NO_GPIO and not csLockManual) { diff --git a/src/fsfw_hal/linux/spi/SpiComIF.h b/src/fsfw_hal/linux/spi/SpiComIF.h index 14a3355a..3b72a59d 100644 --- a/src/fsfw_hal/linux/spi/SpiComIF.h +++ b/src/fsfw_hal/linux/spi/SpiComIF.h @@ -22,15 +22,6 @@ class SpiCookie; */ class SpiComIF : public DeviceCommunicationIF, public SystemObject { public: - static constexpr uint8_t spiRetvalId = CLASS_ID::HAL_SPI; - static constexpr ReturnValue_t OPENING_FILE_FAILED = returnvalue::makeCode(spiRetvalId, 0); - /* Full duplex (ioctl) transfer failure */ - static constexpr ReturnValue_t FULL_DUPLEX_TRANSFER_FAILED = - returnvalue::makeCode(spiRetvalId, 1); - /* Half duplex (read/write) transfer failure */ - static constexpr ReturnValue_t HALF_DUPLEX_TRANSFER_FAILED = - returnvalue::makeCode(spiRetvalId, 2); - SpiComIF(object_id_t objectId, std::string devname, GpioIF& gpioComIF); ReturnValue_t initializeInterface(CookieIF* cookie) override; diff --git a/src/fsfw_hal/linux/uio/UioMapper.cpp b/src/fsfw_hal/linux/uio/UioMapper.cpp index 33e4fd97..c6da5488 100644 --- a/src/fsfw_hal/linux/uio/UioMapper.cpp +++ b/src/fsfw_hal/linux/uio/UioMapper.cpp @@ -36,7 +36,7 @@ UioMapper::~UioMapper() {} ReturnValue_t UioMapper::getMappedAdress(uint32_t** address, Permissions permissions) { ReturnValue_t result = returnvalue::OK; - int fd = open(uioFile.c_str(), O_RDWR); + int fd = open(uioFile.c_str(), O_RDWR | O_SYNC); if (fd < 1) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::error << "UioMapper::getMappedAdress: Invalid UIO device file " << uioFile << std::endl; diff --git a/src/fsfw_hal/stm32h7/spi/SpiComIF.cpp b/src/fsfw_hal/stm32h7/spi/SpiComIF.cpp index 724917bd..4d688bd5 100644 --- a/src/fsfw_hal/stm32h7/spi/SpiComIF.cpp +++ b/src/fsfw_hal/stm32h7/spi/SpiComIF.cpp @@ -357,13 +357,13 @@ ReturnValue_t SpiComIF::halErrorHandler(HAL_StatusTypeDef status, spi::TransferM sif::printWarning("SpiComIF::handle%sSendOperation: HAL error %d occured\n", modeString, status); switch (status) { case (HAL_BUSY): { - return spi::HAL_BUSY_RETVAL; + return spi::BUSY; } case (HAL_ERROR): { - return spi::HAL_ERROR_RETVAL; + return spi::GENERIC_ERROR; } case (HAL_TIMEOUT): { - return spi::HAL_TIMEOUT_RETVAL; + return spi::TIMEOUT; } default: { return returnvalue::FAILED; diff --git a/unittests/CatchFactory.cpp b/unittests/CatchFactory.cpp index 0d855cb3..589e6887 100644 --- a/unittests/CatchFactory.cpp +++ b/unittests/CatchFactory.cpp @@ -30,9 +30,9 @@ */ void Factory::produceFrameworkObjects(void* args) { setStaticFrameworkObjectIds(); - new EventManager(objects::EVENT_MANAGER); + new EventManager(objects::EVENT_MANAGER, 120); new HealthTable(objects::HEALTH_TABLE); - new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER); + new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER, 20, false, 1.0); { PoolManager::LocalPoolConfig poolCfg = {{100, 16}, {50, 32}, {25, 64}, {15, 128}, {5, 1024}}; diff --git a/unittests/action/TestActionHelper.cpp b/unittests/action/TestActionHelper.cpp index d99700d7..de021bb8 100644 --- a/unittests/action/TestActionHelper.cpp +++ b/unittests/action/TestActionHelper.cpp @@ -27,12 +27,7 @@ TEST_CASE("Action Helper", "[action]") { CHECK(not testDhMock.executeActionCalled); REQUIRE(actionHelper.handleActionMessage(&actionMessage) == returnvalue::OK); CHECK(testDhMock.executeActionCalled); - // No message is sent if everything is alright. CHECK(not testMqMock.wasMessageSent()); - store_address_t invalidAddress; - ActionMessage::setCommand(&actionMessage, testActionId, invalidAddress); - actionHelper.handleActionMessage(&actionMessage); - CHECK(testMqMock.wasMessageSent()); const uint8_t* ptr = nullptr; size_t size = 0; REQUIRE(ipcStore->getData(paramAddress, &ptr, &size) == @@ -44,6 +39,10 @@ TEST_CASE("Action Helper", "[action]") { for (uint8_t i = 0; i < 3; i++) { REQUIRE(ptr[i] == (i + 1)); } + // Action message without application data is also valid + store_address_t invalidAddress; + ActionMessage::setCommand(&actionMessage, testActionId, invalidAddress); + actionHelper.handleActionMessage(&actionMessage); testDhMock.clearBuffer(); } @@ -95,17 +94,5 @@ TEST_CASE("Action Helper", "[action]") { REQUIRE(ActionMessage::getActionId(&testMessage) == testActionId); } - SECTION("Missing IPC Data") { - ActionMessage::setCommand(&actionMessage, testActionId, store_address_t::invalid()); - CHECK(not testDhMock.executeActionCalled); - REQUIRE(actionHelper.handleActionMessage(&actionMessage) == returnvalue::OK); - CommandMessage testMessage; - REQUIRE(testMqMock.getNextSentMessage(testMessage) == returnvalue::OK); - REQUIRE(testMessage.getCommand() == static_cast(ActionMessage::STEP_FAILED)); - REQUIRE(ActionMessage::getReturnCode(&testMessage) == - static_cast(StorageManagerIF::ILLEGAL_STORAGE_ID)); - REQUIRE(ActionMessage::getStep(&testMessage) == 0); - } - SECTION("Data Reply") {} } diff --git a/unittests/cfdp/pdu/testCfdpHeader.cpp b/unittests/cfdp/pdu/testCfdpHeader.cpp index 5f81bec9..1fc7dfd4 100644 --- a/unittests/cfdp/pdu/testCfdpHeader.cpp +++ b/unittests/cfdp/pdu/testCfdpHeader.cpp @@ -97,7 +97,7 @@ TEST_CASE("CFDP Header", "[cfdp]") { REQUIRE(creator.serialize(&serTarget, &serSize, serBuf.size(), SerializeIF::Endianness::BIG) == returnvalue::OK); CHECK(serBuf[0] == 0x3f); - CHECK(serBuf[3] == 0x99); + CHECK(serBuf[3] == 0x88); REQUIRE(creator.getCrcFlag() == true); REQUIRE(creator.getDirection() == cfdp::Direction::TOWARDS_SENDER); REQUIRE(creator.getLargeFileFlag() == true); @@ -127,7 +127,7 @@ TEST_CASE("CFDP Header", "[cfdp]") { REQUIRE(creator.getTransmissionMode() == cfdp::TransmissionMode::UNACKNOWLEDGED); REQUIRE(creator.getSegmentationControl() == true); // Last three bits are 2 now (length of seq number) and bit 1 to bit 3 is 4 (len entity IDs) - REQUIRE(serBuf[3] == 0b11001010); + REQUIRE(serBuf[3] == 0b10111001); uint32_t entityId = 0; size_t deSerSize = 0; SerializeAdapter::deSerialize(&entityId, serBuf.data() + 4, &deSerSize, @@ -175,7 +175,7 @@ TEST_CASE("CFDP Header", "[cfdp]") { REQUIRE(serBuf[1] == 0); REQUIRE(serBuf[2] == 0); // Entity and Transaction Sequence number are 1 byte large - REQUIRE(serBuf[3] == 0b00010001); + REQUIRE(serBuf[3] == 0b00000000); // Source ID REQUIRE(serBuf[4] == 0); // Transaction Seq Number @@ -220,7 +220,7 @@ TEST_CASE("CFDP Header", "[cfdp]") { REQUIRE(serBuf[1] == 0); REQUIRE(serBuf[2] == 0); // Entity and Transaction Sequence number are 1 byte large - REQUIRE(serBuf[3] == 0b00010001); + REQUIRE(serBuf[3] == 0b00000000); REQUIRE(serSize == 7); // Deser call not strictly necessary auto reader = PduHeaderReader(serBuf.data(), serBuf.size()); @@ -270,7 +270,7 @@ TEST_CASE("CFDP Header", "[cfdp]") { REQUIRE(reader.parseData() == returnvalue::OK); // Everything except version bit flipped to one now REQUIRE(serBuf[0] == 0x3f); - REQUIRE(serBuf[3] == 0b11001010); + REQUIRE(serBuf[3] == 0b10111001); REQUIRE(reader.getWholePduSize() == 14); REQUIRE(reader.getCrcFlag() == true); diff --git a/unittests/cfdp/pdu/testFileData.cpp b/unittests/cfdp/pdu/testFileData.cpp index 258ef9c1..39139378 100644 --- a/unittests/cfdp/pdu/testFileData.cpp +++ b/unittests/cfdp/pdu/testFileData.cpp @@ -68,7 +68,7 @@ TEST_CASE("File Data PDU", "[cfdp][pdu]") { // Bits 1 to 3 length of enitity IDs is 2 // Bit 4: Segment metadata flag is set // Bit 5 to seven: length of transaction seq num is 2 - REQUIRE(fileDataBuffer[3] == 0b10101010); + REQUIRE(fileDataBuffer[3] == 0b10011001); REQUIRE((fileDataBuffer[10] >> 6) & 0b11 == cfdp::RecordContinuationState::CONTAINS_START_AND_END); // Segment metadata length diff --git a/unittests/cfdp/pdu/testFileDirective.cpp b/unittests/cfdp/pdu/testFileDirective.cpp index e1158a1a..17e0d699 100644 --- a/unittests/cfdp/pdu/testFileDirective.cpp +++ b/unittests/cfdp/pdu/testFileDirective.cpp @@ -30,7 +30,7 @@ TEST_CASE("CFDP File Directive", "[cfdp][pdu]") { REQUIRE(serBuf[1] == 0); REQUIRE(serBuf[2] == 5); // Entity and Transaction Sequence number are 1 byte large - REQUIRE(serBuf[3] == 0b00010001); + REQUIRE(serBuf[3] == 0b00000000); // Source ID REQUIRE(serBuf[4] == 0); // Transaction Seq Number @@ -82,4 +82,4 @@ TEST_CASE("CFDP File Directive", "[cfdp][pdu]") { // Invalid file directive REQUIRE(fdDeser.parseData() == cfdp::INVALID_DIRECTIVE_FIELD); } -} \ No newline at end of file +} diff --git a/unittests/cfdp/testCfdp.cpp b/unittests/cfdp/testCfdp.cpp index eacc83de..467b5b2d 100644 --- a/unittests/cfdp/testCfdp.cpp +++ b/unittests/cfdp/testCfdp.cpp @@ -33,8 +33,8 @@ TEST_CASE("CFDP Base", "[cfdp]") { // PDU data field length is 5 (4 + Directive code octet) REQUIRE(serBuf[1] == 0); REQUIRE(serBuf[2] == 5); - // Entity and Transaction Sequence number are 1 byte large - REQUIRE(serBuf[3] == 0b00010001); + // Entity and Transaction Sequence number are 1 byte large, value minus one is stored + REQUIRE(serBuf[3] == 0b00000000); // Source ID REQUIRE(serBuf[4] == 0); // Transaction Seq Number diff --git a/unittests/datapoollocal/testLocalPoolManager.cpp b/unittests/datapoollocal/testLocalPoolManager.cpp index 91cd011d..e463a123 100644 --- a/unittests/datapoollocal/testLocalPoolManager.cpp +++ b/unittests/datapoollocal/testLocalPoolManager.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include "CatchDefinitions.h" @@ -309,9 +310,7 @@ TEST_CASE("Local Pool Manager Tests", "[LocManTest]") { HousekeepingMessage::setCollectionIntervalModificationCommand(&hkCmd, lpool::testSid, 0.4, false); CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == returnvalue::OK); - /* For non-diagnostics and a specified minimum frequency of 0.2 seconds, the - resulting collection interval should be 1.0 second */ - CHECK(poolOwner.dataset.getCollectionInterval() == 1.0); + CHECK_THAT(poolOwner.dataset.getCollectionInterval(), Catch::Matchers::WithinAbs(0.4, 0.01)); REQUIRE(poolOwnerMock.wasMessageSent()); REQUIRE(poolOwnerMock.numberOfSentMessages() == 1); CHECK(poolOwnerMock.clearLastSentMessage() == returnvalue::OK); @@ -348,14 +347,6 @@ TEST_CASE("Local Pool Manager Tests", "[LocManTest]") { REQUIRE(poolOwnerMock.numberOfSentMessages() == 1); CHECK(poolOwnerMock.clearLastSentMessage() == returnvalue::OK); - HousekeepingMessage::setCollectionIntervalModificationCommand(&hkCmd, lpool::testSid, 0.4, - false); - CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == - static_cast(LocalDataPoolManager::WRONG_HK_PACKET_TYPE)); - REQUIRE(poolOwnerMock.wasMessageSent()); - REQUIRE(poolOwnerMock.numberOfSentMessages() == 1); - CHECK(poolOwnerMock.clearLastSentMessage() == returnvalue::OK); - HousekeepingMessage::setStructureReportingCommand(&hkCmd, lpool::testSid, false); CHECK(poolOwner.poolManager.handleHousekeepingMessage(&hkCmd) == static_cast(LocalDataPoolManager::WRONG_HK_PACKET_TYPE));