From 873316d012bec41c10a46d5c2b51c511235dd187 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 25 Jun 2023 12:41:20 +0200 Subject: [PATCH 1/7] sequence counter isn ow persistent, msg type count support --- CHANGELOG.md | 5 ++++ common/config/eive/definitions.h | 2 ++ fsfw | 2 +- mission/genericFactory.cpp | 12 ++++++--- mission/sysDefs.h | 3 +++ mission/tmtc/CfdpTmFunnel.cpp | 10 +++++++- mission/tmtc/CfdpTmFunnel.h | 2 +- mission/tmtc/PusTmFunnel.cpp | 24 +++++++++++++++-- mission/tmtc/PusTmFunnel.h | 7 ++--- mission/tmtc/TmFunnelBase.cpp | 44 +++++++++++++++++++++++++++++++- mission/tmtc/TmFunnelBase.h | 20 +++++++++++++-- 11 files changed, 117 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fb62b8fc..bc07719d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,11 @@ will consitute of a breaking change warranting a new major release: # [unreleased] +## Added + +- Sequence counters for PUS and CFDP packets are now stored persistently across graceful reboots. +- The PUS packet message type counter will now be increment properly. + # [v4.0.1] 2023-06-24 ## Fixed diff --git a/common/config/eive/definitions.h b/common/config/eive/definitions.h index 2083962a..b369f512 100644 --- a/common/config/eive/definitions.h +++ b/common/config/eive/definitions.h @@ -11,6 +11,8 @@ static constexpr char SD_1_MOUNT_POINT[] = "/mnt/sd1"; static constexpr char OBSW_UPDATE_ARCHIVE_FILE_NAME[] = "eive-sw-update.tar.xz"; static constexpr char STRIPPED_OBSW_BINARY_FILE_NAME[] = "eive-obsw-stripped"; static constexpr char OBSW_VERSION_FILE_NAME[] = "obsw_version.txt"; +static constexpr char PUS_SEQUENCE_COUNT_FILE[] = "pus-sequence-count.txt"; +static constexpr char CFDP_SEQUENCE_COUNT_FILE[] = "cfdp-sequence-count.txt"; static constexpr char OBSW_PATH[] = "/usr/bin/eive-obsw"; static constexpr char OBSW_VERSION_FILE_PATH[] = "/usr/share/eive-obsw/obsw_version.txt"; diff --git a/fsfw b/fsfw index 0f76cdb3..c3572e31 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit 0f76cdb3ba54f5e90a8eee4316c49cf0f581f996 +Subproject commit c3572e31a8d6845442cf8e54802d94477b2db64e diff --git a/mission/genericFactory.cpp b/mission/genericFactory.cpp index cbe78c7f..7101ab3d 100644 --- a/mission/genericFactory.cpp +++ b/mission/genericFactory.cpp @@ -91,6 +91,8 @@ EiveFaultHandler EIVE_FAULT_HANDLER; } // namespace cfdp std::atomic_bool tcs::TCS_BOARD_SHORTLY_UNAVAILABLE = false; +std::atomic_bool core::SAVE_PUS_SEQUENCE_COUNT = false; +std::atomic_bool core::SAVE_CFDP_SEQUENCE_COUNT = false; void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFunnel** pusFunnel, CfdpTmFunnel** cfdpFunnel, SdCardMountedIF& sdcMan, @@ -155,9 +157,11 @@ void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFun new PusDistributor(config::EIVE_PUS_APID, objects::PUS_PACKET_DISTRIBUTOR, ccsdsDistrib); PusTmFunnel::FunnelCfg pusFunnelCfg(objects::PUS_TM_FUNNEL, "PusTmFunnel", **tmStore, **ipcStore, - config::MAX_PUS_FUNNEL_QUEUE_DEPTH); + config::MAX_PUS_FUNNEL_QUEUE_DEPTH, sdcMan, + config::PUS_SEQUENCE_COUNT_FILE, + core::SAVE_PUS_SEQUENCE_COUNT); // The PUS funnel routes all live TM to the live destinations and to the TM stores. - *pusFunnel = new PusTmFunnel(pusFunnelCfg, *ramToFileStore, *timeStamper, sdcMan); + *pusFunnel = new PusTmFunnel(pusFunnelCfg, *ramToFileStore, *timeStamper); // MISC store and PUS funnel to MISC store routing { @@ -216,7 +220,9 @@ void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFun stores.cfdpStore->getReportReceptionQueue(0)); } PusTmFunnel::FunnelCfg cfdpFunnelCfg(objects::CFDP_TM_FUNNEL, "CfdpTmFunnel", **tmStore, - **ipcStore, config::MAX_CFDP_FUNNEL_QUEUE_DEPTH); + **ipcStore, config::MAX_CFDP_FUNNEL_QUEUE_DEPTH, sdcMan, + config::CFDP_SEQUENCE_COUNT_FILE, + core::SAVE_CFDP_SEQUENCE_COUNT); *cfdpFunnel = new CfdpTmFunnel(cfdpFunnelCfg, stores.cfdpStore->getReportReceptionQueue(0), *ramToFileStore, config::EIVE_CFDP_APID); diff --git a/mission/sysDefs.h b/mission/sysDefs.h index 32ce9642..1184a8a8 100644 --- a/mission/sysDefs.h +++ b/mission/sysDefs.h @@ -34,6 +34,9 @@ enum Copy : int { COPY_0, COPY_1, NO_COPY, SELF_COPY, ALL_COPY }; namespace core { +extern std::atomic_bool SAVE_PUS_SEQUENCE_COUNT; +extern std::atomic_bool SAVE_CFDP_SEQUENCE_COUNT; + // TODO: Support for status? Or maybe some command to quickly get information whether a unit // is running. enum SystemctlCmd : uint8_t { START = 0, STOP = 1, RESTART = 2, NUM_CMDS = 3 }; diff --git a/mission/tmtc/CfdpTmFunnel.cpp b/mission/tmtc/CfdpTmFunnel.cpp index 46915b82..93c294a4 100644 --- a/mission/tmtc/CfdpTmFunnel.cpp +++ b/mission/tmtc/CfdpTmFunnel.cpp @@ -15,8 +15,16 @@ const char* CfdpTmFunnel::getName() const { return "CFDP TM Funnel"; } ReturnValue_t CfdpTmFunnel::performOperation(uint8_t) { TmTcMessage currentMessage; + ReturnValue_t status; unsigned int count = 0; - ReturnValue_t status = tmQueue->receiveMessage(¤tMessage); + if (saveSequenceCount) { + status = saveSequenceCountToFile(); + if (status != returnvalue::OK) { + sif::error << "CfdpTmFunnel: Storing sequence count to file has failed" << std::endl; + } + saveSequenceCount = false; + } + status = tmQueue->receiveMessage(¤tMessage); while (status == returnvalue::OK) { status = handlePacket(currentMessage); if (status != returnvalue::OK) { diff --git a/mission/tmtc/CfdpTmFunnel.h b/mission/tmtc/CfdpTmFunnel.h index a4d1bc70..7b9efd34 100644 --- a/mission/tmtc/CfdpTmFunnel.h +++ b/mission/tmtc/CfdpTmFunnel.h @@ -3,6 +3,7 @@ #include +#include #include #include "fsfw/objectmanager/SystemObject.h" @@ -23,7 +24,6 @@ class CfdpTmFunnel : public TmFunnelBase { MessageQueueId_t fileStoreDest; StorageManagerIF& ramToFileStore; - uint16_t sourceSequenceCount = 0; uint16_t cfdpInCcsdsApid; }; #endif // FSFW_EXAMPLE_COMMON_CFDPTMFUNNEL_H diff --git a/mission/tmtc/PusTmFunnel.cpp b/mission/tmtc/PusTmFunnel.cpp index dbc8f1c4..b49d19d3 100644 --- a/mission/tmtc/PusTmFunnel.cpp +++ b/mission/tmtc/PusTmFunnel.cpp @@ -1,5 +1,7 @@ #include "PusTmFunnel.h" +#include + #include "eive/definitions.h" #include "eive/objects.h" #include "fsfw/ipc/CommandMessage.h" @@ -11,8 +13,8 @@ #include "tmtc/pusIds.h" PusTmFunnel::PusTmFunnel(TmFunnelBase::FunnelCfg cfg, StorageManagerIF &ramToFileStore, - TimeReaderIF &timeReader, SdCardMountedIF &sdcMan) - : TmFunnelBase(cfg), ramToFileStore(ramToFileStore), timeReader(timeReader), sdcMan(sdcMan) {} + TimeReaderIF &timeReader) + : TmFunnelBase(cfg), ramToFileStore(ramToFileStore), timeReader(timeReader) {} PusTmFunnel::~PusTmFunnel() = default; @@ -21,6 +23,13 @@ ReturnValue_t PusTmFunnel::performOperation(uint8_t) { ReturnValue_t result; TmTcMessage currentMessage; unsigned int count = 0; + if (saveSequenceCount) { + result = saveSequenceCountToFile(); + if (result != returnvalue::OK) { + sif::error << "PusTmFunnel: Storing sequence count to file has failed" << std::endl; + } + saveSequenceCount = false; + } result = tmQueue->receiveMessage(¤tMessage); while (result == returnvalue::OK) { result = handleTmPacket(currentMessage); @@ -61,6 +70,17 @@ ReturnValue_t PusTmFunnel::handleTmPacket(TmTcMessage &message) { packet.setSequenceCount(sourceSequenceCount++); sourceSequenceCount = sourceSequenceCount % ccsds::LIMIT_SEQUENCE_COUNT; packet.updateErrorControl(); + uint8_t service = packet.getMessageTypeCounter(); + auto mapIter = msgCounterMap.find(service); + if (mapIter == msgCounterMap.end()) { + msgCounterMap.emplace(service, 0); + } + if (mapIter->second == std::numeric_limits::max()) { + mapIter->second = 0; + } else { + mapIter->second++; + } + packet.setMessageCount(mapIter->second); // Send to persistent TM store if the packet matches some filter. MessageQueueId_t destination; diff --git a/mission/tmtc/PusTmFunnel.h b/mission/tmtc/PusTmFunnel.h index ba6e8d3e..3696fdcc 100644 --- a/mission/tmtc/PusTmFunnel.h +++ b/mission/tmtc/PusTmFunnel.h @@ -9,6 +9,8 @@ #include #include +#include +#include #include #include "PersistentTmStore.h" @@ -25,7 +27,7 @@ class PusTmFunnel : public TmFunnelBase { public: PusTmFunnel(TmFunnelBase::FunnelCfg cfg, StorageManagerIF &ramToFileStore, - TimeReaderIF &timeReader, SdCardMountedIF &sdcMan); + TimeReaderIF &timeReader); [[nodiscard]] const char *getName() const override; ~PusTmFunnel() override; @@ -36,11 +38,10 @@ class PusTmFunnel : public TmFunnelBase { // Update TV stamp every 5 minutes static constexpr dur_millis_t TV_UPDATE_INTERVAL_SECS = 60 * 5; - uint16_t sourceSequenceCount = 0; + std::map msgCounterMap; StorageManagerIF &ramToFileStore; TimeReaderIF &timeReader; bool storesInitialized = false; - SdCardMountedIF &sdcMan; PusTmRouteByFilterHelper persistentTmMap; ReturnValue_t handleTmPacket(TmTcMessage &message); diff --git a/mission/tmtc/TmFunnelBase.cpp b/mission/tmtc/TmFunnelBase.cpp index eb480b03..16e4d3bb 100644 --- a/mission/tmtc/TmFunnelBase.cpp +++ b/mission/tmtc/TmFunnelBase.cpp @@ -2,6 +2,10 @@ #include +#include +#include +#include + #include "fsfw/ipc/QueueFactory.h" TmFunnelBase::TmFunnelBase(FunnelCfg cfg) @@ -10,7 +14,10 @@ TmFunnelBase::TmFunnelBase(FunnelCfg cfg) tmStore(cfg.tmStore), ipcStore(cfg.ipcStore), tmQueue(QueueFactory::instance()->createMessageQueue(cfg.tmMsgDepth)), - liveDemux(*tmQueue) {} + liveDemux(*tmQueue), + sdcMan(cfg.sdcMan), + sequenceCounterFilename(cfg.sequenceCounterFilename), + saveSequenceCount(cfg.saveSequenceCount) {} ReturnValue_t TmFunnelBase::demultiplexLivePackets(store_address_t origStoreId, const uint8_t *tmData, size_t tmSize) { @@ -27,3 +34,38 @@ void TmFunnelBase::addLiveDestination(const char *name, const AcceptsTelemetryIF &downlinkDestination, uint8_t vcid) { liveDemux.addDestination(name, downlinkDestination, vcid); } + +ReturnValue_t TmFunnelBase::initialize() { + using namespace std::filesystem; + // The filesystem should always be available at the start.. Let's assume it always is, otherwise + // we just live with a regular 0 initialization. It simplifies a lot. + std::error_code e; + path filePath = + path(sdcMan.getCurrentMountPrefix() / std::string("conf") / sequenceCounterFilename); + if (exists(filePath, e)) { + std::ifstream ifile(filePath); + if (ifile.bad()) { + sif::error << "TmFunnelBase::initialize: Faulty file open for sequence counter initialization" + << std::endl; + return returnvalue::OK; + } + if (not(ifile >> sourceSequenceCount)) { + // Initialize to 0 in any case if reading a number failed. + sourceSequenceCount = 0; + } + } + return returnvalue::OK; +} + +ReturnValue_t TmFunnelBase::saveSequenceCountToFile() { + using namespace std::filesystem; + std::error_code e; + path filePath = + path(sdcMan.getCurrentMountPrefix() / std::string("conf") / sequenceCounterFilename); + std::ofstream ofile(filePath); + if (ofile.bad()) { + return returnvalue::FAILED; + } + ofile << sourceSequenceCount << "\n"; + return returnvalue::OK; +} diff --git a/mission/tmtc/TmFunnelBase.h b/mission/tmtc/TmFunnelBase.h index 51d16626..72d91103 100644 --- a/mission/tmtc/TmFunnelBase.h +++ b/mission/tmtc/TmFunnelBase.h @@ -6,25 +6,34 @@ #include #include #include +#include #include +#include #include class TmFunnelBase : public AcceptsTelemetryIF, public SystemObject { public: struct FunnelCfg { FunnelCfg(object_id_t objId, const char* name, StorageManagerIF& tmStore, - StorageManagerIF& ipcStore, uint32_t tmMsgDepth) + StorageManagerIF& ipcStore, uint32_t tmMsgDepth, SdCardMountedIF& sdcMan, + const char* sequenceCounterFilename, std::atomic_bool& saveSequenceCount) : objectId(objId), name(name), tmStore(tmStore), ipcStore(ipcStore), - tmMsgDepth(tmMsgDepth) {} + tmMsgDepth(tmMsgDepth), + sdcMan(sdcMan), + sequenceCounterFilename(sequenceCounterFilename), + saveSequenceCount(saveSequenceCount) {} object_id_t objectId; const char* name; StorageManagerIF& tmStore; StorageManagerIF& ipcStore; uint32_t tmMsgDepth; + SdCardMountedIF& sdcMan; + const char* sequenceCounterFilename; + std::atomic_bool& saveSequenceCount; }; explicit TmFunnelBase(FunnelCfg cfg); [[nodiscard]] MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel) const override; @@ -32,6 +41,9 @@ class TmFunnelBase : public AcceptsTelemetryIF, public SystemObject { uint8_t vcid = 0); ReturnValue_t demultiplexLivePackets(store_address_t origStoreId, const uint8_t* tmData, size_t tmSize); + ReturnValue_t initialize() override; + + ReturnValue_t saveSequenceCountToFile(); ~TmFunnelBase() override; @@ -41,6 +53,10 @@ class TmFunnelBase : public AcceptsTelemetryIF, public SystemObject { StorageManagerIF& ipcStore; MessageQueueIF* tmQueue = nullptr; PusLiveDemux liveDemux; + SdCardMountedIF& sdcMan; + const char* sequenceCounterFilename; + std::atomic_bool& saveSequenceCount; + uint16_t sourceSequenceCount = 0; }; #endif /* MISSION_TMTC_TMFUNNELBASE_H_ */ From e036ed2bff981daa040f7e793568ce73a69695b7 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 25 Jun 2023 12:47:28 +0200 Subject: [PATCH 2/7] now its complete --- bsp_q7s/core/CoreController.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bsp_q7s/core/CoreController.cpp b/bsp_q7s/core/CoreController.cpp index f9242da3..ca207719 100644 --- a/bsp_q7s/core/CoreController.cpp +++ b/bsp_q7s/core/CoreController.cpp @@ -1222,6 +1222,10 @@ ReturnValue_t CoreController::actionReboot(const uint8_t *data, size_t size) { ReturnValue_t CoreController::gracefulShutdownTasks(xsc::Chip chip, xsc::Copy copy, bool &protOpPerformed) { + // Store both sequence counters persistently. + core::SAVE_CFDP_SEQUENCE_COUNT = true; + core::SAVE_PUS_SEQUENCE_COUNT = true; + sdcMan->setBlocking(true); sdcMan->markUnusable(); // Wait two seconds to ensure no one uses the SD cards From 5a15d39a1d5c38af793c52d215d4737ad9529b17 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 25 Jun 2023 12:49:51 +0200 Subject: [PATCH 3/7] important order bugfix --- mission/tmtc/PusTmFunnel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mission/tmtc/PusTmFunnel.cpp b/mission/tmtc/PusTmFunnel.cpp index b49d19d3..e5285ba5 100644 --- a/mission/tmtc/PusTmFunnel.cpp +++ b/mission/tmtc/PusTmFunnel.cpp @@ -69,7 +69,6 @@ ReturnValue_t PusTmFunnel::handleTmPacket(TmTcMessage &message) { } packet.setSequenceCount(sourceSequenceCount++); sourceSequenceCount = sourceSequenceCount % ccsds::LIMIT_SEQUENCE_COUNT; - packet.updateErrorControl(); uint8_t service = packet.getMessageTypeCounter(); auto mapIter = msgCounterMap.find(service); if (mapIter == msgCounterMap.end()) { @@ -81,6 +80,7 @@ ReturnValue_t PusTmFunnel::handleTmPacket(TmTcMessage &message) { mapIter->second++; } packet.setMessageCount(mapIter->second); + packet.updateErrorControl(); // Send to persistent TM store if the packet matches some filter. MessageQueueId_t destination; From 80160e829166c48957b1747df69c98ad649c2a51 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 25 Jun 2023 13:07:31 +0200 Subject: [PATCH 4/7] that was hopefully the last set of fixes --- mission/tmtc/PusTmFunnel.cpp | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/mission/tmtc/PusTmFunnel.cpp b/mission/tmtc/PusTmFunnel.cpp index e5285ba5..87648e55 100644 --- a/mission/tmtc/PusTmFunnel.cpp +++ b/mission/tmtc/PusTmFunnel.cpp @@ -68,18 +68,33 @@ ReturnValue_t PusTmFunnel::handleTmPacket(TmTcMessage &message) { return result; } packet.setSequenceCount(sourceSequenceCount++); + // NOTE: This only works because the limit value bit width is below 16 bits! sourceSequenceCount = sourceSequenceCount % ccsds::LIMIT_SEQUENCE_COUNT; - uint8_t service = packet.getMessageTypeCounter(); + + // Message type counter handling. + uint8_t service = packet.getService(); + bool insertionFailed = false; auto mapIter = msgCounterMap.find(service); if (mapIter == msgCounterMap.end()) { - msgCounterMap.emplace(service, 0); + auto iterPair = msgCounterMap.emplace(service, 0); + if (iterPair.second) { + mapIter = iterPair.first; + } else { + // Should really never never happen but you never know.. + insertionFailed = true; + } } - if (mapIter->second == std::numeric_limits::max()) { - mapIter->second = 0; - } else { - mapIter->second++; + if (not insertionFailed) { + packet.setMessageCount(mapIter->second); + // Sane overflow handling. + if (mapIter->second == std::numeric_limits::max()) { + mapIter->second = 0; + } else { + mapIter->second++; + } } - packet.setMessageCount(mapIter->second); + + // Re-calculate CRC after changing the fields. This operation HAS to come last! packet.updateErrorControl(); // Send to persistent TM store if the packet matches some filter. From 93fb2070320f7482f10e6a15d6448c8f2e86f91b Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 25 Jun 2023 13:12:39 +0200 Subject: [PATCH 5/7] C++ insanity.. --- mission/tmtc/TmFunnelBase.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mission/tmtc/TmFunnelBase.cpp b/mission/tmtc/TmFunnelBase.cpp index 16e4d3bb..06bdd15f 100644 --- a/mission/tmtc/TmFunnelBase.cpp +++ b/mission/tmtc/TmFunnelBase.cpp @@ -40,8 +40,8 @@ ReturnValue_t TmFunnelBase::initialize() { // The filesystem should always be available at the start.. Let's assume it always is, otherwise // we just live with a regular 0 initialization. It simplifies a lot. std::error_code e; - path filePath = - path(sdcMan.getCurrentMountPrefix() / std::string("conf") / sequenceCounterFilename); + path filePath = path(std::string(sdcMan.getCurrentMountPrefix()) / std::string("conf") / + std::string(sequenceCounterFilename)); if (exists(filePath, e)) { std::ifstream ifile(filePath); if (ifile.bad()) { @@ -60,8 +60,8 @@ ReturnValue_t TmFunnelBase::initialize() { ReturnValue_t TmFunnelBase::saveSequenceCountToFile() { using namespace std::filesystem; std::error_code e; - path filePath = - path(sdcMan.getCurrentMountPrefix() / std::string("conf") / sequenceCounterFilename); + path filePath = path(std::string(sdcMan.getCurrentMountPrefix()) / std::string("conf") / + std::string(sequenceCounterFilename)); std::ofstream ofile(filePath); if (ofile.bad()) { return returnvalue::FAILED; From c806aa81f07560c9d06b56116225835c72e845b8 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 26 Jun 2023 11:14:11 +0200 Subject: [PATCH 6/7] what does the new compiler want? --- mission/tmtc/TmFunnelBase.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mission/tmtc/TmFunnelBase.cpp b/mission/tmtc/TmFunnelBase.cpp index 06bdd15f..fc2e4b76 100644 --- a/mission/tmtc/TmFunnelBase.cpp +++ b/mission/tmtc/TmFunnelBase.cpp @@ -40,8 +40,8 @@ ReturnValue_t TmFunnelBase::initialize() { // The filesystem should always be available at the start.. Let's assume it always is, otherwise // we just live with a regular 0 initialization. It simplifies a lot. std::error_code e; - path filePath = path(std::string(sdcMan.getCurrentMountPrefix()) / std::string("conf") / - std::string(sequenceCounterFilename)); + path filePath = + path(path(sdcMan.getCurrentMountPrefix()) / path("conf") / path(sequenceCounterFilename)); if (exists(filePath, e)) { std::ifstream ifile(filePath); if (ifile.bad()) { @@ -60,8 +60,8 @@ ReturnValue_t TmFunnelBase::initialize() { ReturnValue_t TmFunnelBase::saveSequenceCountToFile() { using namespace std::filesystem; std::error_code e; - path filePath = path(std::string(sdcMan.getCurrentMountPrefix()) / std::string("conf") / - std::string(sequenceCounterFilename)); + path filePath = + path(path(sdcMan.getCurrentMountPrefix()) / path("conf") / path(sequenceCounterFilename)); std::ofstream ofile(filePath); if (ofile.bad()) { return returnvalue::FAILED; From 52fedb94e806bb7173cf65d70304c05e1f96bc78 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 28 Jun 2023 13:20:50 +0200 Subject: [PATCH 7/7] bump fsfw and tmtc --- fsfw | 2 +- tmtc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fsfw b/fsfw index 7e8845f2..8da89eba 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit 7e8845f2c2565b1486ff37be0519d3e15b4e1a13 +Subproject commit 8da89eba80f73cb05e5c38fc012456f1d9569af5 diff --git a/tmtc b/tmtc index ec0ebc36..8caa408c 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit ec0ebc365308198046addc94909b1bca8678aa5a +Subproject commit 8caa408cbdf7eebdd441cff580063283ab81ffe1