From 9c1eee075c53c9bca1cefe7d5faf7d6267b6f730 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 2 Oct 2023 14:15:50 +0200 Subject: [PATCH 01/24] well that was fast --- bsp_q7s/core/CMakeLists.txt | 3 ++- bsp_q7s/core/XiphosWdtHandler.cpp | 39 +++++++++++++++++++++++++++++++ bsp_q7s/core/XiphosWdtHandler.h | 22 +++++++++++++++++ bsp_q7s/em/emObjectFactory.cpp | 2 ++ bsp_q7s/fmObjectFactory.cpp | 2 ++ bsp_q7s/scheduling.cpp | 9 +++++++ common/config/eive/objects.h | 1 + tmtc | 2 +- 8 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 bsp_q7s/core/XiphosWdtHandler.cpp create mode 100644 bsp_q7s/core/XiphosWdtHandler.h diff --git a/bsp_q7s/core/CMakeLists.txt b/bsp_q7s/core/CMakeLists.txt index 33550144..530b53e9 100644 --- a/bsp_q7s/core/CMakeLists.txt +++ b/bsp_q7s/core/CMakeLists.txt @@ -1 +1,2 @@ -target_sources(${OBSW_NAME} PRIVATE CoreController.cpp WatchdogHandler.cpp) +target_sources(${OBSW_NAME} PRIVATE CoreController.cpp WatchdogHandler.cpp + XiphosWdtHandler.cpp) diff --git a/bsp_q7s/core/XiphosWdtHandler.cpp b/bsp_q7s/core/XiphosWdtHandler.cpp new file mode 100644 index 00000000..38d206db --- /dev/null +++ b/bsp_q7s/core/XiphosWdtHandler.cpp @@ -0,0 +1,39 @@ +#include "XiphosWdtHandler.h" + +XiphosWdtHandler::XiphosWdtHandler(object_id_t objectId) : SystemObject(objectId) {} + +ReturnValue_t XiphosWdtHandler::initialize() { + int result = xsc_watchdog_init(&wdtHandle); + if (result != 0) { + sif::error << "XiphosWdtHandler: Initiating watchdog failed with code " << result << ": " + << strerror(result) << std::endl; + return ObjectManagerIF::CHILD_INIT_FAILED; + } + if (wdtHandle == nullptr) { + sif::error << "XiphosWdtHandler: WDT handle is nullptr!" << std::endl; + return ObjectManagerIF::CHILD_INIT_FAILED; + } + result = xsc_watchdog_set_timeout(wdtHandle, timeoutSeconds); + if (result != 0) { + sif::error << "XiphosWdtHandler: Setting WDT timeout of " << timeoutSeconds + << " seconds failed with code " << result << ": " << strerror(result) << std::endl; + return ObjectManagerIF::CHILD_INIT_FAILED; + } + result = xsc_watchdog_enable(wdtHandle); + if (result != 0) { + sif::error << "XiphosWdtHandler: Enabling WDT failed with code " << result << ": " + << strerror(result) << std::endl; + return ObjectManagerIF::CHILD_INIT_FAILED; + } + return returnvalue::OK; +} + +ReturnValue_t XiphosWdtHandler::performOperation(uint8_t opCode) { + int result = xsc_watchdog_keepalive(wdtHandle); + if (result != 0) { + sif::warning << "XiphosWdtHandler: Feeding WDT failed with code " << result << ": " + << strerror(result) << std::endl; + return returnvalue::FAILED; + } + return returnvalue::OK; +} diff --git a/bsp_q7s/core/XiphosWdtHandler.h b/bsp_q7s/core/XiphosWdtHandler.h new file mode 100644 index 00000000..346c13ef --- /dev/null +++ b/bsp_q7s/core/XiphosWdtHandler.h @@ -0,0 +1,22 @@ +#ifndef BSP_Q7S_CORE_XIPHOSWDTHANDLER_H_ +#define BSP_Q7S_CORE_XIPHOSWDTHANDLER_H_ + +#include +#include +#include +#include + +class XiphosWdtHandler : public SystemObject, public ExecutableObjectIF { + public: + XiphosWdtHandler(object_id_t objectId); + ReturnValue_t performOperation(uint8_t opCode) override; + ReturnValue_t initialize() override; + + private: + // Timeout duration range specified by Xiphos: 0.001 seconds to 171 seconds. The libxiphos API + // expects an int, so I guess this translates to 1 to 171 seconds. + uint32_t timeoutSeconds = 60; + struct watchdog_s* wdtHandle = nullptr; +}; + +#endif /* BSP_Q7S_CORE_XIPHOSWDTHANDLER_H_ */ diff --git a/bsp_q7s/em/emObjectFactory.cpp b/bsp_q7s/em/emObjectFactory.cpp index 976602d4..06867a1c 100644 --- a/bsp_q7s/em/emObjectFactory.cpp +++ b/bsp_q7s/em/emObjectFactory.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -37,6 +38,7 @@ void ObjectFactory::produce(void* args) { PersistentTmStores stores; readFirmwareVersion(); + new XiphosWdtHandler(objects::XIPHOS_WDT); ObjectFactory::produceGenericObjects(&healthTable, &pusFunnel, &cfdpFunnel, *SdCardManager::instance(), &ipcStore, &tmStore, stores, 200, enableHkSets); diff --git a/bsp_q7s/fmObjectFactory.cpp b/bsp_q7s/fmObjectFactory.cpp index a3ab6bba..83e3d90b 100644 --- a/bsp_q7s/fmObjectFactory.cpp +++ b/bsp_q7s/fmObjectFactory.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -34,6 +35,7 @@ void ObjectFactory::produce(void* args) { PersistentTmStores stores; readFirmwareVersion(); + new XiphosWdtHandler(objects::XIPHOS_WDT); ObjectFactory::produceGenericObjects(&healthTable, &pusFunnel, &cfdpFunnel, *SdCardManager::instance(), &ipcStore, &tmStore, stores, 200, true); diff --git a/bsp_q7s/scheduling.cpp b/bsp_q7s/scheduling.cpp index d7c179ad..7a94c118 100644 --- a/bsp_q7s/scheduling.cpp +++ b/bsp_q7s/scheduling.cpp @@ -82,6 +82,14 @@ void scheduling::initTasks() { } #endif + PeriodicTaskIF* xiphosWdtTask = + factory->createPeriodicTask("XIPHOS_WDT", 90, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.4, + missedDeadlineFunc, &RR_SCHEDULING); + result = xiphosWdtTask->addComponent(objects::XIPHOS_WDT); + if (result != returnvalue::OK) { + scheduling::printAddObjectError("XIPHOS_WDT", objects::XIPHOS_WDT); + } + PeriodicTaskIF* coreCtrlTask = factory->createPeriodicTask( "CORE_CTRL", 55, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.4, missedDeadlineFunc, &RR_SCHEDULING); result = coreCtrlTask->addComponent(objects::CORE_CONTROLLER); @@ -410,6 +418,7 @@ void scheduling::initTasks() { }; sif::info << "Starting tasks.." << std::endl; + xiphosWdtTask->startTask(); tmTcDistributor->startTask(); #if OBSW_ADD_TCPIP_SERVERS == 1 diff --git a/common/config/eive/objects.h b/common/config/eive/objects.h index 0cc4b9d9..2118aa6d 100644 --- a/common/config/eive/objects.h +++ b/common/config/eive/objects.h @@ -26,6 +26,7 @@ enum commonObjects : uint32_t { THERMAL_CONTROLLER = 0x43400001, ACS_CONTROLLER = 0x43000002, CORE_CONTROLLER = 0x43000003, + XIPHOS_WDT = 0x43000004, GLOBAL_JSON_CFG = 0x43000006, /* 0x44 ('D') for device handlers */ diff --git a/tmtc b/tmtc index 22a42108..783bdd29 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 22a42108b431bafa707de2b3a24cad9de95b70d0 +Subproject commit 783bdd297a931a96c8b077ec2c2456a203b23ffc From 404a1009ed46a839da2a9a21c901427447e9a7a4 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 2 Oct 2023 14:47:41 +0200 Subject: [PATCH 02/24] that should get the job done --- CHANGELOG.md | 5 +++++ bsp_q7s/core/XiphosWdtHandler.cpp | 19 ++++++++++++++----- bsp_q7s/scheduling.cpp | 4 +++- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ae7901e..da8e84c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,11 @@ will consitute of a breaking change warranting a new major release: - Missing `nullptr` checks for PLOC Supervisor handler, which could lead to crashes. +## Added + +- Activate Xiphos WDT with a timeout period of 60 seconds using the `libxiphos` API. The WDT + calls are done by the new `XiphosWdtHandler` object. + # [v6.6.0] 2023-09-18 ## Changed diff --git a/bsp_q7s/core/XiphosWdtHandler.cpp b/bsp_q7s/core/XiphosWdtHandler.cpp index 38d206db..dbf1474a 100644 --- a/bsp_q7s/core/XiphosWdtHandler.cpp +++ b/bsp_q7s/core/XiphosWdtHandler.cpp @@ -19,11 +19,20 @@ ReturnValue_t XiphosWdtHandler::initialize() { << " seconds failed with code " << result << ": " << strerror(result) << std::endl; return ObjectManagerIF::CHILD_INIT_FAILED; } - result = xsc_watchdog_enable(wdtHandle); - if (result != 0) { - sif::error << "XiphosWdtHandler: Enabling WDT failed with code " << result << ": " - << strerror(result) << std::endl; - return ObjectManagerIF::CHILD_INIT_FAILED; + int nowayout = 0; + int status = 0; + result = xsc_watchdog_get_status(&nowayout, &status); + if (result == 0) { + if (status == 0) { + result = xsc_watchdog_enable(wdtHandle); + if (result != 0) { + sif::error << "XiphosWdtHandler: Enabling WDT failed with code " << result << ": " + << strerror(result) << std::endl; + return ObjectManagerIF::CHILD_INIT_FAILED; + } + } + } else { + sif::warning << "XiphosWdtHandler: Getting WDT status failed" << std::endl; } return returnvalue::OK; } diff --git a/bsp_q7s/scheduling.cpp b/bsp_q7s/scheduling.cpp index 7a94c118..e8208e65 100644 --- a/bsp_q7s/scheduling.cpp +++ b/bsp_q7s/scheduling.cpp @@ -82,8 +82,10 @@ void scheduling::initTasks() { } #endif + // Medium priority, higher than something like payload, but not the highest priority to also + // detect tasks which choke other tasks. PeriodicTaskIF* xiphosWdtTask = - factory->createPeriodicTask("XIPHOS_WDT", 90, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.4, + factory->createPeriodicTask("XIPHOS_WDT", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.4, missedDeadlineFunc, &RR_SCHEDULING); result = xiphosWdtTask->addComponent(objects::XIPHOS_WDT); if (result != returnvalue::OK) { From 34100e6c9505c02477d0ebaed1cc911c099cdd15 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 2 Oct 2023 14:49:29 +0200 Subject: [PATCH 03/24] small robustness tweak --- bsp_q7s/core/XiphosWdtHandler.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bsp_q7s/core/XiphosWdtHandler.cpp b/bsp_q7s/core/XiphosWdtHandler.cpp index dbf1474a..5d4da7b6 100644 --- a/bsp_q7s/core/XiphosWdtHandler.cpp +++ b/bsp_q7s/core/XiphosWdtHandler.cpp @@ -15,9 +15,9 @@ ReturnValue_t XiphosWdtHandler::initialize() { } result = xsc_watchdog_set_timeout(wdtHandle, timeoutSeconds); if (result != 0) { - sif::error << "XiphosWdtHandler: Setting WDT timeout of " << timeoutSeconds + // This propably means that the default timeout is used. Still continue with task init. + sif::warning << "XiphosWdtHandler: Setting WDT timeout of " << timeoutSeconds << " seconds failed with code " << result << ": " << strerror(result) << std::endl; - return ObjectManagerIF::CHILD_INIT_FAILED; } int nowayout = 0; int status = 0; From 8fc560f9de72acfd08e480e500dbeb82fd302499 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 10 Oct 2023 11:34:18 +0200 Subject: [PATCH 04/24] what is this? --- bsp_q7s/core/XiphosWdtHandler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bsp_q7s/core/XiphosWdtHandler.h b/bsp_q7s/core/XiphosWdtHandler.h index 346c13ef..271df1a0 100644 --- a/bsp_q7s/core/XiphosWdtHandler.h +++ b/bsp_q7s/core/XiphosWdtHandler.h @@ -15,7 +15,7 @@ class XiphosWdtHandler : public SystemObject, public ExecutableObjectIF { private: // Timeout duration range specified by Xiphos: 0.001 seconds to 171 seconds. The libxiphos API // expects an int, so I guess this translates to 1 to 171 seconds. - uint32_t timeoutSeconds = 60; + int timeoutSeconds = 120; struct watchdog_s* wdtHandle = nullptr; }; From 4b4c78c3faab3fe8db1f34ec5a0edf9461a42da6 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 10 Oct 2023 12:19:42 +0200 Subject: [PATCH 05/24] lets go back to 60 seconds --- bsp_q7s/core/XiphosWdtHandler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bsp_q7s/core/XiphosWdtHandler.h b/bsp_q7s/core/XiphosWdtHandler.h index 271df1a0..1f6f8c0d 100644 --- a/bsp_q7s/core/XiphosWdtHandler.h +++ b/bsp_q7s/core/XiphosWdtHandler.h @@ -15,7 +15,7 @@ class XiphosWdtHandler : public SystemObject, public ExecutableObjectIF { private: // Timeout duration range specified by Xiphos: 0.001 seconds to 171 seconds. The libxiphos API // expects an int, so I guess this translates to 1 to 171 seconds. - int timeoutSeconds = 120; + int timeoutSeconds = 60; struct watchdog_s* wdtHandle = nullptr; }; From a29805cb6840e71c67b4e5053dc3592ef801276b Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 10 Oct 2023 16:18:35 +0200 Subject: [PATCH 06/24] SCEX bugfix --- mission/payload/ScexDeviceHandler.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/mission/payload/ScexDeviceHandler.cpp b/mission/payload/ScexDeviceHandler.cpp index 12c62f7a..0db10561 100644 --- a/mission/payload/ScexDeviceHandler.cpp +++ b/mission/payload/ScexDeviceHandler.cpp @@ -38,9 +38,13 @@ void ScexDeviceHandler::doShutDown() { setMode(_MODE_POWER_DOWN); } -ReturnValue_t ScexDeviceHandler::buildNormalDeviceCommand(DeviceCommandId_t* id) { return OK; } +ReturnValue_t ScexDeviceHandler::buildNormalDeviceCommand(DeviceCommandId_t* id) { + return NOTHING_TO_SEND; +} -ReturnValue_t ScexDeviceHandler::buildTransitionDeviceCommand(DeviceCommandId_t* id) { return OK; } +ReturnValue_t ScexDeviceHandler::buildTransitionDeviceCommand(DeviceCommandId_t* id) { + return NOTHING_TO_SEND; +} ReturnValue_t ScexDeviceHandler::buildCommandFromCommand(DeviceCommandId_t deviceCommand, const uint8_t* commandData, From 7f82dd91e28dd1362d5ff9c7e36238d6d82a69ff Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 10 Oct 2023 16:20:51 +0200 Subject: [PATCH 07/24] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ae7901e..ed736ae4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ will consitute of a breaking change warranting a new major release: ## Fixed - Missing `nullptr` checks for PLOC Supervisor handler, which could lead to crashes. +- SCEX bugfix for normal and transition command. # [v6.6.0] 2023-09-18 From d1e0d7407241b745d7ad38e5ce5f45786e5a1b85 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 10 Oct 2023 18:44:13 +0200 Subject: [PATCH 08/24] robustness fix --- mission/payload/ScexDeviceHandler.cpp | 2 +- tmtc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mission/payload/ScexDeviceHandler.cpp b/mission/payload/ScexDeviceHandler.cpp index 0db10561..ac668cdf 100644 --- a/mission/payload/ScexDeviceHandler.cpp +++ b/mission/payload/ScexDeviceHandler.cpp @@ -273,7 +273,7 @@ ReturnValue_t ScexDeviceHandler::interpretDeviceReply(DeviceCommandId_t id, cons // Unknown DeviceCommand return DeviceHandlerIF::COMMAND_NOT_IMPLEMENTED; } - if (helper.getPacketCounter() == helper.getTotalPacketCounter()) { + if (helper.getPacketCounter() >= helper.getTotalPacketCounter()) { reader.finish(); commandActive = false; if (id != PING) { diff --git a/tmtc b/tmtc index 22a42108..9711dd92 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 22a42108b431bafa707de2b3a24cad9de95b70d0 +Subproject commit 9711dd9242340720e28d41eefda90666ec9af4bb From 9a283b0f98e6092b55e960944c2dd7e74275ea9f Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 10 Oct 2023 19:15:52 +0200 Subject: [PATCH 09/24] add action cmds --- bsp_q7s/core/XiphosWdtHandler.cpp | 124 +++++++++++++++++++++++------- bsp_q7s/core/XiphosWdtHandler.h | 12 ++- tmtc | 2 +- 3 files changed, 108 insertions(+), 30 deletions(-) diff --git a/bsp_q7s/core/XiphosWdtHandler.cpp b/bsp_q7s/core/XiphosWdtHandler.cpp index 5d4da7b6..be087648 100644 --- a/bsp_q7s/core/XiphosWdtHandler.cpp +++ b/bsp_q7s/core/XiphosWdtHandler.cpp @@ -1,48 +1,116 @@ #include "XiphosWdtHandler.h" -XiphosWdtHandler::XiphosWdtHandler(object_id_t objectId) : SystemObject(objectId) {} +#include "fsfw/ipc/QueueFactory.h" + +XiphosWdtHandler::XiphosWdtHandler(object_id_t objectId) + : SystemObject(objectId), + requestQueue(QueueFactory::instance()->createMessageQueue()), + actionHelper(this, requestQueue) {} ReturnValue_t XiphosWdtHandler::initialize() { - int result = xsc_watchdog_init(&wdtHandle); - if (result != 0) { - sif::error << "XiphosWdtHandler: Initiating watchdog failed with code " << result << ": " - << strerror(result) << std::endl; + ReturnValue_t result = actionHelper.initialize(); + if (result != returnvalue::OK) { + return result; + } + int retval = xsc_watchdog_init(&wdtHandle); + if (retval != 0) { + sif::error << "XiphosWdtHandler: Initiating watchdog failed with code " << retval << ": " + << strerror(retval) << std::endl; return ObjectManagerIF::CHILD_INIT_FAILED; } if (wdtHandle == nullptr) { sif::error << "XiphosWdtHandler: WDT handle is nullptr!" << std::endl; return ObjectManagerIF::CHILD_INIT_FAILED; } - result = xsc_watchdog_set_timeout(wdtHandle, timeoutSeconds); - if (result != 0) { + retval = xsc_watchdog_set_timeout(wdtHandle, timeoutSeconds); + if (retval != 0) { // This propably means that the default timeout is used. Still continue with task init. sif::warning << "XiphosWdtHandler: Setting WDT timeout of " << timeoutSeconds - << " seconds failed with code " << result << ": " << strerror(result) << std::endl; + << " seconds failed with code " << result << ": " << strerror(retval) << std::endl; } - int nowayout = 0; - int status = 0; - result = xsc_watchdog_get_status(&nowayout, &status); - if (result == 0) { - if (status == 0) { - result = xsc_watchdog_enable(wdtHandle); - if (result != 0) { - sif::error << "XiphosWdtHandler: Enabling WDT failed with code " << result << ": " - << strerror(result) << std::endl; - return ObjectManagerIF::CHILD_INIT_FAILED; - } - } - } else { - sif::warning << "XiphosWdtHandler: Getting WDT status failed" << std::endl; - } - return returnvalue::OK; + return enableWdt(); } ReturnValue_t XiphosWdtHandler::performOperation(uint8_t opCode) { - int result = xsc_watchdog_keepalive(wdtHandle); - if (result != 0) { - sif::warning << "XiphosWdtHandler: Feeding WDT failed with code " << result << ": " - << strerror(result) << std::endl; + CommandMessage command; + ReturnValue_t result; + for (result = requestQueue->receiveMessage(&command); result == returnvalue::OK; + result = requestQueue->receiveMessage(&command)) { + result = actionHelper.handleActionMessage(&command); + if (result == returnvalue::OK) { + continue; + } + sif::warning << "Can not handle message with message type " << command.getMessageType() + << std::endl; + } + int retval = xsc_watchdog_keepalive(wdtHandle); + if (retval != 0) { + sif::warning << "XiphosWdtHandler: Feeding WDT failed with code " << retval << ": " + << strerror(retval) << std::endl; return returnvalue::FAILED; } return returnvalue::OK; } + +ReturnValue_t XiphosWdtHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, + const uint8_t *data, size_t size) { + switch (actionId) { + case (ActionId::ENABLE): { + ReturnValue_t result = enableWdt(); + if (result != returnvalue::OK) { + return result; + } + return EXECUTION_FINISHED; + } + case (ActionId::DISABLE): { + ReturnValue_t result = disableWdt(); + if (result != returnvalue::OK) { + return result; + } + return EXECUTION_FINISHED; + } + } + return HasActionsIF::INVALID_ACTION_ID; +} + +ReturnValue_t XiphosWdtHandler::enableWdt() { + int nowayout = 0; + int status = 0; + int retval = xsc_watchdog_get_status(&nowayout, &status); + // If this fails for whatever reason, just try enabling in any case. + if (retval != 0) { + sif::warning << "XiphosWdtHandler: Getting WDT status failed" << std::endl; + } + // Of course the enable API will fail if the device is already on, just perfect, love me some + // good C API... :))) + if (retval != 0 or status == 0) { + int retval = xsc_watchdog_enable(wdtHandle); + if (retval != 0) { + sif::error << "XiphosWdtHandler: Enabling WDT failed with code " << retval << ": " + << strerror(retval) << std::endl; + return returnvalue::FAILED; + } + } + return returnvalue::OK; +} + +ReturnValue_t XiphosWdtHandler::disableWdt() { + int nowayout = 0; + int status = 0; + int retval = xsc_watchdog_get_status(&nowayout, &status); + // If this fails for whatever reason, just try disabling in any case. + if (retval != 0) { + sif::warning << "XiphosWdtHandler: Getting WDT status failed" << std::endl; + } + // Of course the disable API will fail if the device is already off, just perfect, love me some + // good C API... :))) + if (retval != 0 or status == 1) { + int retval = xsc_watchdog_disable(wdtHandle); + if (retval != 0) { + sif::error << "XiphosWdtHandler: Disabling WDT failed with code " << retval << ": " + << strerror(retval) << std::endl; + return returnvalue::FAILED; + } + } + return returnvalue::OK; +} diff --git a/bsp_q7s/core/XiphosWdtHandler.h b/bsp_q7s/core/XiphosWdtHandler.h index 1f6f8c0d..28e48429 100644 --- a/bsp_q7s/core/XiphosWdtHandler.h +++ b/bsp_q7s/core/XiphosWdtHandler.h @@ -6,17 +6,27 @@ #include #include -class XiphosWdtHandler : public SystemObject, public ExecutableObjectIF { +class XiphosWdtHandler : public SystemObject, public ExecutableObjectIF, public HasActionsIF { public: + enum ActionId { ENABLE = 0, DISABLE = 1 }; + XiphosWdtHandler(object_id_t objectId); ReturnValue_t performOperation(uint8_t opCode) override; ReturnValue_t initialize() override; + ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, + const uint8_t* data, size_t size) override; + private: + // Wrappers to ensure idempotency of trash C API. + ReturnValue_t enableWdt(); + ReturnValue_t disableWdt(); // Timeout duration range specified by Xiphos: 0.001 seconds to 171 seconds. The libxiphos API // expects an int, so I guess this translates to 1 to 171 seconds. int timeoutSeconds = 60; struct watchdog_s* wdtHandle = nullptr; + MessageQueueIF* requestQueue = nullptr; + ActionHelper actionHelper; }; #endif /* BSP_Q7S_CORE_XIPHOSWDTHANDLER_H_ */ diff --git a/tmtc b/tmtc index 783bdd29..d82cecbe 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 783bdd297a931a96c8b077ec2c2456a203b23ffc +Subproject commit d82cecbe6e51e76a5b3b974b1c0d32ea22693853 From c3cdcaf9f445cda72f9930aa71469d9acc4f7023 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 11 Oct 2023 10:58:25 +0200 Subject: [PATCH 10/24] bump tmtc and gens --- bsp_hosted/fsfwconfig/events/translateEvents.cpp | 2 +- bsp_hosted/fsfwconfig/objects/translateObjects.cpp | 7 +++++-- generators/bsp_hosted_objects.csv | 1 + generators/bsp_q7s_objects.csv | 1 + generators/events/translateEvents.cpp | 2 +- generators/objects/translateObjects.cpp | 7 +++++-- linux/fsfwconfig/events/translateEvents.cpp | 2 +- linux/fsfwconfig/objects/translateObjects.cpp | 7 +++++-- mission/controller/CMakeLists.txt | 6 +++--- mission/system/power/CMakeLists.txt | 3 ++- tmtc | 2 +- 11 files changed, 26 insertions(+), 14 deletions(-) diff --git a/bsp_hosted/fsfwconfig/events/translateEvents.cpp b/bsp_hosted/fsfwconfig/events/translateEvents.cpp index 77df8166..9bb03ff0 100644 --- a/bsp_hosted/fsfwconfig/events/translateEvents.cpp +++ b/bsp_hosted/fsfwconfig/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** * @brief Auto-generated event translation file. Contains 313 translations. * @details - * Generated on: 2023-10-10 13:50:27 + * Generated on: 2023-10-11 10:54:39 */ #include "translateEvents.h" diff --git a/bsp_hosted/fsfwconfig/objects/translateObjects.cpp b/bsp_hosted/fsfwconfig/objects/translateObjects.cpp index 8d80ca56..7e795093 100644 --- a/bsp_hosted/fsfwconfig/objects/translateObjects.cpp +++ b/bsp_hosted/fsfwconfig/objects/translateObjects.cpp @@ -1,8 +1,8 @@ /** * @brief Auto-generated object translation file. * @details - * Contains 173 translations. - * Generated on: 2023-10-10 13:50:27 + * Contains 174 translations. + * Generated on: 2023-10-11 10:54:39 */ #include "translateObjects.h" @@ -11,6 +11,7 @@ const char *ACS_CONTROLLER_STRING = "ACS_CONTROLLER"; const char *CORE_CONTROLLER_STRING = "CORE_CONTROLLER"; const char *POWER_CONTROLLER_STRING = "POWER_CONTROLLER"; const char *GLOBAL_JSON_CFG_STRING = "GLOBAL_JSON_CFG"; +const char *XIPHOS_WDT_STRING = "XIPHOS_WDT"; const char *THERMAL_CONTROLLER_STRING = "THERMAL_CONTROLLER"; const char *DUMMY_HANDLER_STRING = "DUMMY_HANDLER"; const char *MGM_0_LIS3_HANDLER_STRING = "MGM_0_LIS3_HANDLER"; @@ -192,6 +193,8 @@ const char *translateObject(object_id_t object) { return POWER_CONTROLLER_STRING; case 0x43000006: return GLOBAL_JSON_CFG_STRING; + case 0x43000007: + return XIPHOS_WDT_STRING; case 0x43400001: return THERMAL_CONTROLLER_STRING; case 0x44000001: diff --git a/generators/bsp_hosted_objects.csv b/generators/bsp_hosted_objects.csv index 4cb21f46..689a58f2 100644 --- a/generators/bsp_hosted_objects.csv +++ b/generators/bsp_hosted_objects.csv @@ -3,6 +3,7 @@ 0x43000003;CORE_CONTROLLER 0x43000004;POWER_CONTROLLER 0x43000006;GLOBAL_JSON_CFG +0x43000007;XIPHOS_WDT 0x43400001;THERMAL_CONTROLLER 0x44000001;DUMMY_HANDLER 0x44120006;MGM_0_LIS3_HANDLER diff --git a/generators/bsp_q7s_objects.csv b/generators/bsp_q7s_objects.csv index 914b7df6..10cfed26 100644 --- a/generators/bsp_q7s_objects.csv +++ b/generators/bsp_q7s_objects.csv @@ -3,6 +3,7 @@ 0x43000003;CORE_CONTROLLER 0x43000004;POWER_CONTROLLER 0x43000006;GLOBAL_JSON_CFG +0x43000007;XIPHOS_WDT 0x43400001;THERMAL_CONTROLLER 0x44120006;MGM_0_LIS3_HANDLER 0x44120010;GYRO_0_ADIS_HANDLER diff --git a/generators/events/translateEvents.cpp b/generators/events/translateEvents.cpp index 77df8166..9bb03ff0 100644 --- a/generators/events/translateEvents.cpp +++ b/generators/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** * @brief Auto-generated event translation file. Contains 313 translations. * @details - * Generated on: 2023-10-10 13:50:27 + * Generated on: 2023-10-11 10:54:39 */ #include "translateEvents.h" diff --git a/generators/objects/translateObjects.cpp b/generators/objects/translateObjects.cpp index aeb2b405..0599cc18 100644 --- a/generators/objects/translateObjects.cpp +++ b/generators/objects/translateObjects.cpp @@ -1,8 +1,8 @@ /** * @brief Auto-generated object translation file. * @details - * Contains 177 translations. - * Generated on: 2023-10-10 13:50:27 + * Contains 178 translations. + * Generated on: 2023-10-11 10:54:39 */ #include "translateObjects.h" @@ -11,6 +11,7 @@ const char *ACS_CONTROLLER_STRING = "ACS_CONTROLLER"; const char *CORE_CONTROLLER_STRING = "CORE_CONTROLLER"; const char *POWER_CONTROLLER_STRING = "POWER_CONTROLLER"; const char *GLOBAL_JSON_CFG_STRING = "GLOBAL_JSON_CFG"; +const char *XIPHOS_WDT_STRING = "XIPHOS_WDT"; const char *THERMAL_CONTROLLER_STRING = "THERMAL_CONTROLLER"; const char *MGM_0_LIS3_HANDLER_STRING = "MGM_0_LIS3_HANDLER"; const char *GYRO_0_ADIS_HANDLER_STRING = "GYRO_0_ADIS_HANDLER"; @@ -196,6 +197,8 @@ const char *translateObject(object_id_t object) { return POWER_CONTROLLER_STRING; case 0x43000006: return GLOBAL_JSON_CFG_STRING; + case 0x43000007: + return XIPHOS_WDT_STRING; case 0x43400001: return THERMAL_CONTROLLER_STRING; case 0x44120006: diff --git a/linux/fsfwconfig/events/translateEvents.cpp b/linux/fsfwconfig/events/translateEvents.cpp index 77df8166..9bb03ff0 100644 --- a/linux/fsfwconfig/events/translateEvents.cpp +++ b/linux/fsfwconfig/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** * @brief Auto-generated event translation file. Contains 313 translations. * @details - * Generated on: 2023-10-10 13:50:27 + * Generated on: 2023-10-11 10:54:39 */ #include "translateEvents.h" diff --git a/linux/fsfwconfig/objects/translateObjects.cpp b/linux/fsfwconfig/objects/translateObjects.cpp index aeb2b405..0599cc18 100644 --- a/linux/fsfwconfig/objects/translateObjects.cpp +++ b/linux/fsfwconfig/objects/translateObjects.cpp @@ -1,8 +1,8 @@ /** * @brief Auto-generated object translation file. * @details - * Contains 177 translations. - * Generated on: 2023-10-10 13:50:27 + * Contains 178 translations. + * Generated on: 2023-10-11 10:54:39 */ #include "translateObjects.h" @@ -11,6 +11,7 @@ const char *ACS_CONTROLLER_STRING = "ACS_CONTROLLER"; const char *CORE_CONTROLLER_STRING = "CORE_CONTROLLER"; const char *POWER_CONTROLLER_STRING = "POWER_CONTROLLER"; const char *GLOBAL_JSON_CFG_STRING = "GLOBAL_JSON_CFG"; +const char *XIPHOS_WDT_STRING = "XIPHOS_WDT"; const char *THERMAL_CONTROLLER_STRING = "THERMAL_CONTROLLER"; const char *MGM_0_LIS3_HANDLER_STRING = "MGM_0_LIS3_HANDLER"; const char *GYRO_0_ADIS_HANDLER_STRING = "GYRO_0_ADIS_HANDLER"; @@ -196,6 +197,8 @@ const char *translateObject(object_id_t object) { return POWER_CONTROLLER_STRING; case 0x43000006: return GLOBAL_JSON_CFG_STRING; + case 0x43000007: + return XIPHOS_WDT_STRING; case 0x43400001: return THERMAL_CONTROLLER_STRING; case 0x44120006: diff --git a/mission/controller/CMakeLists.txt b/mission/controller/CMakeLists.txt index 901decc0..690ede64 100644 --- a/mission/controller/CMakeLists.txt +++ b/mission/controller/CMakeLists.txt @@ -1,7 +1,7 @@ if(TGT_BSP MATCHES "arm/q7s" OR TGT_BSP MATCHES "") - target_sources(${LIB_EIVE_MISSION} PRIVATE ThermalController.cpp - AcsController.cpp - PowerController.cpp) + target_sources( + ${LIB_EIVE_MISSION} PRIVATE ThermalController.cpp AcsController.cpp + PowerController.cpp) endif() add_subdirectory(acs) diff --git a/mission/system/power/CMakeLists.txt b/mission/system/power/CMakeLists.txt index a7e91e05..2c720978 100644 --- a/mission/system/power/CMakeLists.txt +++ b/mission/system/power/CMakeLists.txt @@ -1 +1,2 @@ -target_sources(${LIB_EIVE_MISSION} PRIVATE epsModeTree.cpp EpsSubsystem.cpp GomspacePowerFdir.cpp) +target_sources(${LIB_EIVE_MISSION} PRIVATE epsModeTree.cpp EpsSubsystem.cpp + GomspacePowerFdir.cpp) diff --git a/tmtc b/tmtc index d82cecbe..ec8febf6 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit d82cecbe6e51e76a5b3b974b1c0d32ea22693853 +Subproject commit ec8febf623a651b83c518443c30e9acfa36461fd From fddae1bfc60fea86619058cab6cae01662b9cfc3 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 11 Oct 2023 13:56:05 +0200 Subject: [PATCH 11/24] compile fixes --- bsp_q7s/core/XiphosWdtHandler.cpp | 6 ++++-- bsp_q7s/core/XiphosWdtHandler.h | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/bsp_q7s/core/XiphosWdtHandler.cpp b/bsp_q7s/core/XiphosWdtHandler.cpp index be087648..6a1dc687 100644 --- a/bsp_q7s/core/XiphosWdtHandler.cpp +++ b/bsp_q7s/core/XiphosWdtHandler.cpp @@ -84,7 +84,7 @@ ReturnValue_t XiphosWdtHandler::enableWdt() { // Of course the enable API will fail if the device is already on, just perfect, love me some // good C API... :))) if (retval != 0 or status == 0) { - int retval = xsc_watchdog_enable(wdtHandle); + retval = xsc_watchdog_enable(wdtHandle); if (retval != 0) { sif::error << "XiphosWdtHandler: Enabling WDT failed with code " << retval << ": " << strerror(retval) << std::endl; @@ -105,7 +105,7 @@ ReturnValue_t XiphosWdtHandler::disableWdt() { // Of course the disable API will fail if the device is already off, just perfect, love me some // good C API... :))) if (retval != 0 or status == 1) { - int retval = xsc_watchdog_disable(wdtHandle); + retval = xsc_watchdog_disable(wdtHandle); if (retval != 0) { sif::error << "XiphosWdtHandler: Disabling WDT failed with code " << retval << ": " << strerror(retval) << std::endl; @@ -114,3 +114,5 @@ ReturnValue_t XiphosWdtHandler::disableWdt() { } return returnvalue::OK; } + +MessageQueueId_t XiphosWdtHandler::getCommandQueue() const { return requestQueue->getId(); } diff --git a/bsp_q7s/core/XiphosWdtHandler.h b/bsp_q7s/core/XiphosWdtHandler.h index 28e48429..5d073e76 100644 --- a/bsp_q7s/core/XiphosWdtHandler.h +++ b/bsp_q7s/core/XiphosWdtHandler.h @@ -16,6 +16,7 @@ class XiphosWdtHandler : public SystemObject, public ExecutableObjectIF, public ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, const uint8_t* data, size_t size) override; + [[nodiscard]] virtual MessageQueueId_t getCommandQueue() const override; private: // Wrappers to ensure idempotency of trash C API. From 528360744144a00b8dea423f980278dbfe37bf7a Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 11 Oct 2023 13:59:11 +0200 Subject: [PATCH 12/24] changelog update --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a119bca..700a9a49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,7 +34,7 @@ will consitute of a breaking change warranting a new major release: ## Fixed - Missing `nullptr` checks for PLOC Supervisor handler, which could lead to crashes. -- SCEX bugfix for normal and transition command. +- SCEX bugfix for normal and transition commanding. # [v6.6.0] 2023-09-18 From 8cb46610062d4f8609debba3903e07033a062310 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 11 Oct 2023 14:51:55 +0200 Subject: [PATCH 13/24] higher timeout (max value) --- bsp_q7s/core/XiphosWdtHandler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bsp_q7s/core/XiphosWdtHandler.h b/bsp_q7s/core/XiphosWdtHandler.h index 5d073e76..69fad067 100644 --- a/bsp_q7s/core/XiphosWdtHandler.h +++ b/bsp_q7s/core/XiphosWdtHandler.h @@ -24,7 +24,7 @@ class XiphosWdtHandler : public SystemObject, public ExecutableObjectIF, public ReturnValue_t disableWdt(); // Timeout duration range specified by Xiphos: 0.001 seconds to 171 seconds. The libxiphos API // expects an int, so I guess this translates to 1 to 171 seconds. - int timeoutSeconds = 60; + int timeoutSeconds = 80; struct watchdog_s* wdtHandle = nullptr; MessageQueueIF* requestQueue = nullptr; ActionHelper actionHelper; From eb1b9c837f1863a7ed602aa1346b29f73557b938 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 11 Oct 2023 14:53:10 +0200 Subject: [PATCH 14/24] comment --- bsp_q7s/core/XiphosWdtHandler.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bsp_q7s/core/XiphosWdtHandler.h b/bsp_q7s/core/XiphosWdtHandler.h index 69fad067..3f46cfd3 100644 --- a/bsp_q7s/core/XiphosWdtHandler.h +++ b/bsp_q7s/core/XiphosWdtHandler.h @@ -24,6 +24,8 @@ class XiphosWdtHandler : public SystemObject, public ExecutableObjectIF, public ReturnValue_t disableWdt(); // Timeout duration range specified by Xiphos: 0.001 seconds to 171 seconds. The libxiphos API // expects an int, so I guess this translates to 1 to 171 seconds. + // WARNING: DO NOT SET THIS HIGHER THAN 80 SECONDS! + // Possible bug in Xiphos/Xilinx kernel driver for watchdog, related to overflow. int timeoutSeconds = 80; struct watchdog_s* wdtHandle = nullptr; MessageQueueIF* requestQueue = nullptr; From 4e3229f0189319127de58436061b3ffc057c4aa3 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 11 Oct 2023 15:00:15 +0200 Subject: [PATCH 15/24] cache wdt state --- bsp_q7s/core/XiphosWdtHandler.cpp | 14 +++++++++----- bsp_q7s/core/XiphosWdtHandler.h | 1 + tmtc | 2 +- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/bsp_q7s/core/XiphosWdtHandler.cpp b/bsp_q7s/core/XiphosWdtHandler.cpp index 6a1dc687..8444b65f 100644 --- a/bsp_q7s/core/XiphosWdtHandler.cpp +++ b/bsp_q7s/core/XiphosWdtHandler.cpp @@ -43,11 +43,13 @@ ReturnValue_t XiphosWdtHandler::performOperation(uint8_t opCode) { sif::warning << "Can not handle message with message type " << command.getMessageType() << std::endl; } - int retval = xsc_watchdog_keepalive(wdtHandle); - if (retval != 0) { - sif::warning << "XiphosWdtHandler: Feeding WDT failed with code " << retval << ": " - << strerror(retval) << std::endl; - return returnvalue::FAILED; + if (enabled) { + int retval = xsc_watchdog_keepalive(wdtHandle); + if (retval != 0) { + sif::warning << "XiphosWdtHandler: Feeding WDT failed with code " << retval << ": " + << strerror(retval) << std::endl; + return returnvalue::FAILED; + } } return returnvalue::OK; } @@ -91,6 +93,7 @@ ReturnValue_t XiphosWdtHandler::enableWdt() { return returnvalue::FAILED; } } + enabled = true; return returnvalue::OK; } @@ -112,6 +115,7 @@ ReturnValue_t XiphosWdtHandler::disableWdt() { return returnvalue::FAILED; } } + enabled = false; return returnvalue::OK; } diff --git a/bsp_q7s/core/XiphosWdtHandler.h b/bsp_q7s/core/XiphosWdtHandler.h index 3f46cfd3..a8d73f48 100644 --- a/bsp_q7s/core/XiphosWdtHandler.h +++ b/bsp_q7s/core/XiphosWdtHandler.h @@ -27,6 +27,7 @@ class XiphosWdtHandler : public SystemObject, public ExecutableObjectIF, public // WARNING: DO NOT SET THIS HIGHER THAN 80 SECONDS! // Possible bug in Xiphos/Xilinx kernel driver for watchdog, related to overflow. int timeoutSeconds = 80; + bool enabled = false; struct watchdog_s* wdtHandle = nullptr; MessageQueueIF* requestQueue = nullptr; ActionHelper actionHelper; diff --git a/tmtc b/tmtc index aba369f1..dcae9308 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit aba369f11f928aefe570f18651bd72ce98953961 +Subproject commit dcae930895b3debca5a5b615fc20cded7c3d0e89 From 9265f27af91317982f93f9e00aabc8a128def018 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 11 Oct 2023 15:02:59 +0200 Subject: [PATCH 16/24] changelog --- CHANGELOG.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f9038140..f3c69d56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,8 @@ will consitute of a breaking change warranting a new major release: - EPS Subsystem has been added to EIVE System Tree - Power Controller for calculating the State of Charge and FDIR regarding low SoC has been introduced. +- Activate Xiphos WDT with a timeout period of 80 seconds using the `libxiphos` API. The WDT + calls are done by the new `XiphosWdtHandler` object. ## Changed @@ -36,11 +38,6 @@ will consitute of a breaking change warranting a new major release: - Missing `nullptr` checks for PLOC Supervisor handler, which could lead to crashes. - SCEX bugfix for normal and transition commanding. -## Added - -- Activate Xiphos WDT with a timeout period of 60 seconds using the `libxiphos` API. The WDT - calls are done by the new `XiphosWdtHandler` object. - # [v6.6.0] 2023-09-18 ## Changed From a381efc5d949370ab65a6a2b72f5592ffabad463 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 11 Oct 2023 18:16:36 +0200 Subject: [PATCH 17/24] prep next release --- CHANGELOG.md | 4 +++- CMakeLists.txt | 4 ++-- tmtc | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 700a9a49..b7143400 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,9 @@ will consitute of a breaking change warranting a new major release: # [unreleased] -- Bumped `eive-tmtc` to v5.7.0. +# [v7.0.0] 2023-10-11 + +- Bumped `eive-tmtc` to v5.7.1. - Bumped `eive-fsfw` ## Added diff --git a/CMakeLists.txt b/CMakeLists.txt index 65038b76..2b02cfdb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,8 +9,8 @@ # ############################################################################## cmake_minimum_required(VERSION 3.13) -set(OBSW_VERSION_MAJOR 6) -set(OBSW_VERSION_MINOR 6) +set(OBSW_VERSION_MAJOR 7) +set(OBSW_VERSION_MINOR 0) set(OBSW_VERSION_REVISION 0) # set(CMAKE_VERBOSE TRUE) diff --git a/tmtc b/tmtc index 9711dd92..39e6a048 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 9711dd9242340720e28d41eefda90666ec9af4bb +Subproject commit 39e6a0488922590900b862e5e70524be1d6ec5ba From 62305ec39b31ba0533b2358173c3d5fd4233ad7f Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 11 Oct 2023 19:38:03 +0200 Subject: [PATCH 18/24] bump tmtc --- tmtc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tmtc b/tmtc index dcae9308..e249f147 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit dcae930895b3debca5a5b615fc20cded7c3d0e89 +Subproject commit e249f147bc1738003d31290df8f2b525d91c3482 From bb4e495199f61d0d8257f3777dc3d83442e89a43 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 11 Oct 2023 19:40:16 +0200 Subject: [PATCH 19/24] changelog correcion --- CHANGELOG.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 14e7e392..a6d88025 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,12 @@ will consitute of a breaking change warranting a new major release: # [unreleased] +# [v7.1.0] 2023-10-11 + +- Bumped `eive-tmtc` to v5.8.0. +- Activate Xiphos WDT with a timeout period of 80 seconds using the `libxiphos` API. The WDT + calls are done by the new `XiphosWdtHandler` object. + # [v7.0.0] 2023-10-11 - Bumped `eive-tmtc` to v5.7.1. @@ -26,8 +32,6 @@ will consitute of a breaking change warranting a new major release: - EPS Subsystem has been added to EIVE System Tree - Power Controller for calculating the State of Charge and FDIR regarding low SoC has been introduced. -- Activate Xiphos WDT with a timeout period of 80 seconds using the `libxiphos` API. The WDT - calls are done by the new `XiphosWdtHandler` object. ## Changed From ebe67a38a96651e8295a7076bd0cb0cb4759b4b7 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 11 Oct 2023 19:49:24 +0200 Subject: [PATCH 20/24] bump minor version --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2b02cfdb..65e85d35 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ cmake_minimum_required(VERSION 3.13) set(OBSW_VERSION_MAJOR 7) -set(OBSW_VERSION_MINOR 0) +set(OBSW_VERSION_MINOR 1) set(OBSW_VERSION_REVISION 0) # set(CMAKE_VERBOSE TRUE) From ffe1281eb9454ac0de0263f44ae53294b3bb1920 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 13 Oct 2023 09:20:51 +0200 Subject: [PATCH 21/24] fix PTME --- .../fsfwconfig/events/translateEvents.cpp | 2 +- .../fsfwconfig/objects/translateObjects.cpp | 2 +- common/config/eive/resultClassIds.h | 1 + generators/bsp_hosted_returnvalues.csv | 2 + generators/bsp_q7s_returnvalues.csv | 4 +- generators/events/translateEvents.cpp | 2 +- generators/objects/translateObjects.cpp | 2 +- linux/fsfwconfig/events/translateEvents.cpp | 2 +- linux/fsfwconfig/objects/translateObjects.cpp | 2 +- linux/ipcore/PapbVcInterface.cpp | 53 +++++++++---------- linux/ipcore/PapbVcInterface.h | 12 ++--- linux/ipcore/Ptme.cpp | 34 ++++-------- linux/ipcore/Ptme.h | 5 +- linux/ipcore/PtmeIF.h | 14 ++--- mission/com/TmStoreTaskBase.cpp | 13 ++++- mission/com/VirtualChannel.cpp | 51 +++++++++++++++--- mission/com/VirtualChannel.h | 11 +++- mission/com/VirtualChannelWithQueue.cpp | 13 ++++- mission/tmtc/DirectTmSinkIF.h | 8 ++- tmtc | 2 +- 20 files changed, 141 insertions(+), 94 deletions(-) diff --git a/bsp_hosted/fsfwconfig/events/translateEvents.cpp b/bsp_hosted/fsfwconfig/events/translateEvents.cpp index 9bb03ff0..13b2f7d5 100644 --- a/bsp_hosted/fsfwconfig/events/translateEvents.cpp +++ b/bsp_hosted/fsfwconfig/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** * @brief Auto-generated event translation file. Contains 313 translations. * @details - * Generated on: 2023-10-11 10:54:39 + * Generated on: 2023-10-13 09:17:41 */ #include "translateEvents.h" diff --git a/bsp_hosted/fsfwconfig/objects/translateObjects.cpp b/bsp_hosted/fsfwconfig/objects/translateObjects.cpp index 7e795093..00170e41 100644 --- a/bsp_hosted/fsfwconfig/objects/translateObjects.cpp +++ b/bsp_hosted/fsfwconfig/objects/translateObjects.cpp @@ -2,7 +2,7 @@ * @brief Auto-generated object translation file. * @details * Contains 174 translations. - * Generated on: 2023-10-11 10:54:39 + * Generated on: 2023-10-13 09:17:41 */ #include "translateObjects.h" diff --git a/common/config/eive/resultClassIds.h b/common/config/eive/resultClassIds.h index 9e2a3f2f..35b2a419 100644 --- a/common/config/eive/resultClassIds.h +++ b/common/config/eive/resultClassIds.h @@ -41,6 +41,7 @@ enum commonClassIds : uint8_t { LOCAL_PARAM_HANDLER, // LPH PERSISTENT_TM_STORE, // PTM TM_SINK, // TMS + VIRTUAL_CHANNEL, // VCS COMMON_CLASS_ID_END // [EXPORT] : [END] }; } diff --git a/generators/bsp_hosted_returnvalues.csv b/generators/bsp_hosted_returnvalues.csv index 0dfc94c3..ea7717f8 100644 --- a/generators/bsp_hosted_returnvalues.csv +++ b/generators/bsp_hosted_returnvalues.csv @@ -513,3 +513,5 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path 0x6d00;PTM_DumpDone;No description;0;PERSISTENT_TM_STORE;mission/tmtc/PersistentTmStore.h 0x6d01;PTM_BusyDumping;No description;1;PERSISTENT_TM_STORE;mission/tmtc/PersistentTmStore.h 0x6e00;TMS_IsBusy;No description;0;TM_SINK;mission/tmtc/DirectTmSinkIF.h +0x6e01;TMS_PartiallyWritten;No description;1;TM_SINK;mission/tmtc/DirectTmSinkIF.h +0x6f00;VCS_ChannelDoesNotExist;No description;0;VIRTUAL_CHANNEL;mission/com/VirtualChannel.h diff --git a/generators/bsp_q7s_returnvalues.csv b/generators/bsp_q7s_returnvalues.csv index 0e804457..c47d15e1 100644 --- a/generators/bsp_q7s_returnvalues.csv +++ b/generators/bsp_q7s_returnvalues.csv @@ -608,4 +608,6 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path 0x6d00;PTM_DumpDone;No description;0;PERSISTENT_TM_STORE;mission/tmtc/PersistentTmStore.h 0x6d01;PTM_BusyDumping;No description;1;PERSISTENT_TM_STORE;mission/tmtc/PersistentTmStore.h 0x6e00;TMS_IsBusy;No description;0;TM_SINK;mission/tmtc/DirectTmSinkIF.h -0x7000;SCBU_KeyNotFound;No description;0;SCRATCH_BUFFER;bsp_q7s/memory/scratchApi.h +0x6e01;TMS_PartiallyWritten;No description;1;TM_SINK;mission/tmtc/DirectTmSinkIF.h +0x6f00;VCS_ChannelDoesNotExist;No description;0;VIRTUAL_CHANNEL;mission/com/VirtualChannel.h +0x7100;SCBU_KeyNotFound;No description;0;SCRATCH_BUFFER;bsp_q7s/memory/scratchApi.h diff --git a/generators/events/translateEvents.cpp b/generators/events/translateEvents.cpp index 9bb03ff0..13b2f7d5 100644 --- a/generators/events/translateEvents.cpp +++ b/generators/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** * @brief Auto-generated event translation file. Contains 313 translations. * @details - * Generated on: 2023-10-11 10:54:39 + * Generated on: 2023-10-13 09:17:41 */ #include "translateEvents.h" diff --git a/generators/objects/translateObjects.cpp b/generators/objects/translateObjects.cpp index 0599cc18..06da3f47 100644 --- a/generators/objects/translateObjects.cpp +++ b/generators/objects/translateObjects.cpp @@ -2,7 +2,7 @@ * @brief Auto-generated object translation file. * @details * Contains 178 translations. - * Generated on: 2023-10-11 10:54:39 + * Generated on: 2023-10-13 09:17:41 */ #include "translateObjects.h" diff --git a/linux/fsfwconfig/events/translateEvents.cpp b/linux/fsfwconfig/events/translateEvents.cpp index 9bb03ff0..13b2f7d5 100644 --- a/linux/fsfwconfig/events/translateEvents.cpp +++ b/linux/fsfwconfig/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** * @brief Auto-generated event translation file. Contains 313 translations. * @details - * Generated on: 2023-10-11 10:54:39 + * Generated on: 2023-10-13 09:17:41 */ #include "translateEvents.h" diff --git a/linux/fsfwconfig/objects/translateObjects.cpp b/linux/fsfwconfig/objects/translateObjects.cpp index 0599cc18..06da3f47 100644 --- a/linux/fsfwconfig/objects/translateObjects.cpp +++ b/linux/fsfwconfig/objects/translateObjects.cpp @@ -2,7 +2,7 @@ * @brief Auto-generated object translation file. * @details * Contains 178 translations. - * Generated on: 2023-10-11 10:54:39 + * Generated on: 2023-10-13 09:17:41 */ #include "translateObjects.h" diff --git a/linux/ipcore/PapbVcInterface.cpp b/linux/ipcore/PapbVcInterface.cpp index 5dcb4519..5e63aebc 100644 --- a/linux/ipcore/PapbVcInterface.cpp +++ b/linux/ipcore/PapbVcInterface.cpp @@ -23,7 +23,7 @@ ReturnValue_t PapbVcInterface::initialize() { return returnvalue::OK; } -ReturnValue_t PapbVcInterface::write(const uint8_t* data, size_t size) { +ReturnValue_t PapbVcInterface::write(const uint8_t* data, size_t size, size_t& writtenSize) { // There are no packets smaller than 4, this is considered a configuration error. if (size < 4) { return returnvalue::FAILED; @@ -37,19 +37,7 @@ ReturnValue_t PapbVcInterface::write(const uint8_t* data, size_t size) { abortPacketTransfer(); return returnvalue::FAILED; } - for (size_t idx = 0; idx < size; idx++) { - if (not pollReadyForOctet(MAX_BUSY_POLLS)) { - abortPacketTransfer(); - return returnvalue::FAILED; - } - *(vcBaseReg + DATA_REG_OFFSET) = static_cast(data[idx]); - } - if (not pollReadyForOctet(MAX_BUSY_POLLS)) { - abortPacketTransfer(); - return returnvalue::FAILED; - } - completePacketTransfer(); - return returnvalue::OK; + return finishWritePartialOpt(data, size, true); } void PapbVcInterface::startPacketTransfer(ByteWidthCfg initWidth) { @@ -65,6 +53,26 @@ bool PapbVcInterface::pollReadyForPacket() const { return (reg >> 6) & 0b1; } +ReturnValue_t PapbVcInterface::finishWritePartialOpt(const uint8_t* data, size_t remainingSize, + bool handlePartial) { + for (size_t idx = 0; idx < remainingSize; idx++) { + if (not pollReadyForOctet(MAX_BUSY_POLLS)) { + if (not pollReadyForPacket()) { + return PARTIALLY_WRITTEN; + } + abortPacketTransfer(); + return returnvalue::FAILED; + } + *(vcBaseReg + DATA_REG_OFFSET) = static_cast(data[idx]); + } + if (not pollReadyForOctet(MAX_BUSY_POLLS)) { + abortPacketTransfer(); + return returnvalue::FAILED; + } + completePacketTransfer(); + return returnvalue::OK; +} + bool PapbVcInterface::isVcInterfaceBufferEmpty() { ReturnValue_t result = returnvalue::OK; gpio::Levels papbEmptyState = gpio::Levels::HIGH; @@ -101,21 +109,8 @@ inline bool PapbVcInterface::pollReadyForOctet(uint32_t maxCycles) const { return false; } -ReturnValue_t PapbVcInterface::sendTestFrame() { - /** Size of one complete transfer frame data field amounts to 1105 bytes */ - uint8_t testPacket[1105]; - - /** Fill one test packet */ - for (int idx = 0; idx < 1105; idx++) { - testPacket[idx] = static_cast(idx & 0xFF); - } - - ReturnValue_t result = write(testPacket, 1105); - if (result != returnvalue::OK) { - return result; - } - - return returnvalue::OK; +ReturnValue_t PapbVcInterface::finishWrite(const uint8_t* data, size_t remainingSize) { + return finishWritePartialOpt(data, remainingSize, false); } void PapbVcInterface::abortPacketTransfer() { *vcBaseReg = CONFIG_ABORT; } diff --git a/linux/ipcore/PapbVcInterface.h b/linux/ipcore/PapbVcInterface.h index b5160748..72b9b9f3 100644 --- a/linux/ipcore/PapbVcInterface.h +++ b/linux/ipcore/PapbVcInterface.h @@ -40,7 +40,11 @@ class PapbVcInterface : public VirtualChannelIF { * @param size * @return returnvalue::OK on successfull write, PAPB_BUSY if PAPB is busy. */ - ReturnValue_t write(const uint8_t* data, size_t size) override; + ReturnValue_t write(const uint8_t* data, size_t size, size_t& writtenSize) override; + + ReturnValue_t finishWrite(const uint8_t* data, size_t remainingSize) override; + ReturnValue_t finishWritePartialOpt(const uint8_t* data, size_t remainingSize, + bool handlePartial); void cancelTransfer() override; @@ -126,12 +130,6 @@ class PapbVcInterface : public VirtualChannelIF { * the packet buffer of the virtual channel or not. */ bool isVcInterfaceBufferEmpty(); - - /** - * @brief This function sends a complete telemetry transfer frame data field (1105 bytes) - * to the papb interface of the PTME IP Core. Can be used to test the implementation. - */ - ReturnValue_t sendTestFrame(); }; #endif /* LINUX_OBC_PAPBVCINTERFACE_H_ */ diff --git a/linux/ipcore/Ptme.cpp b/linux/ipcore/Ptme.cpp index f33c8725..9b688d16 100644 --- a/linux/ipcore/Ptme.cpp +++ b/linux/ipcore/Ptme.cpp @@ -19,15 +19,12 @@ ReturnValue_t Ptme::initialize() { return returnvalue::OK; } -ReturnValue_t Ptme::writeToVc(uint8_t vcId, const uint8_t* data, size_t size) { - VcInterfaceMapIter vcInterfaceMapIter = vcInterfaceMap.find(vcId); - if (vcInterfaceMapIter == vcInterfaceMap.end()) { - sif::warning << "Ptme::writeToVc: No virtual channel interface found for the virtual " - "channel with id " - << static_cast(vcId) << std::endl; - return UNKNOWN_VC_ID; +bool Ptme::containsVc(uint8_t vcId) const { + auto channelIter = vcInterfaceMap.find(vcId); + if (channelIter == vcInterfaceMap.end()) { + return false; } - return vcInterfaceMapIter->second->write(data, size); + return true; } void Ptme::addVcInterface(VcId_t vcId, VirtualChannelIF* vc) { @@ -50,21 +47,10 @@ void Ptme::addVcInterface(VcId_t vcId, VirtualChannelIF* vc) { } } -bool Ptme::isBusy(uint8_t vcId) const { - const auto& vcInterfaceMapIter = vcInterfaceMap.find(vcId); - if (vcInterfaceMapIter == vcInterfaceMap.end()) { - sif::warning << "Ptme::writeToVc: No virtual channel interface found for the virtual " - "channel with id " - << static_cast(vcId) << std::endl; - return UNKNOWN_VC_ID; +VirtualChannelIF* Ptme::getVirtChannel(uint8_t vcId) { + auto channelIter = vcInterfaceMap.find(vcId); + if (channelIter == vcInterfaceMap.end()) { + return nullptr; } - return vcInterfaceMapIter->second->isBusy(); -} - -void Ptme::cancelTransfer(uint8_t vcId) { - VcInterfaceMapIter vcInterfaceMapIter = vcInterfaceMap.find(vcId); - if (vcInterfaceMapIter == vcInterfaceMap.end()) { - return; - } - return vcInterfaceMapIter->second->cancelTransfer(); + return channelIter->second; } diff --git a/linux/ipcore/Ptme.h b/linux/ipcore/Ptme.h index 2607fc90..d5e77024 100644 --- a/linux/ipcore/Ptme.h +++ b/linux/ipcore/Ptme.h @@ -34,9 +34,8 @@ class Ptme : public PtmeIF, public SystemObject { virtual ~Ptme(); ReturnValue_t initialize() override; - ReturnValue_t writeToVc(uint8_t vcId, const uint8_t* data, size_t size) override; - bool isBusy(uint8_t vcId) const override; - void cancelTransfer(uint8_t vcId) override; + bool containsVc(uint8_t vcId) const override; + VirtualChannelIF* getVirtChannel(uint8_t vcId) override; /** * @brief This function adds the reference to a virtual channel interface to the vcInterface diff --git a/linux/ipcore/PtmeIF.h b/linux/ipcore/PtmeIF.h index 38804484..a5ea0c95 100644 --- a/linux/ipcore/PtmeIF.h +++ b/linux/ipcore/PtmeIF.h @@ -1,6 +1,8 @@ #ifndef LINUX_OBC_PTMEIF_H_ #define LINUX_OBC_PTMEIF_H_ +#include + #include "fsfw/returnvalues/returnvalue.h" /** @@ -14,16 +16,8 @@ class PtmeIF { public: virtual ~PtmeIF(){}; - /** - * @brief Implements to function to write to a specific virtual channel. - * - * @param vcId Virtual channel to write to - * @param data Pointer to buffer holding the data to write - * @param size Number of bytes to write - */ - virtual ReturnValue_t writeToVc(uint8_t vcId, const uint8_t* data, size_t size) = 0; - virtual bool isBusy(uint8_t vcId) const = 0; - virtual void cancelTransfer(uint8_t vcId) = 0; + virtual bool containsVc(uint8_t vcId) const = 0; + virtual VirtualChannelIF* getVirtChannel(uint8_t vcId) = 0; }; #endif /* LINUX_OBC_PTMEIF_H_ */ diff --git a/mission/com/TmStoreTaskBase.cpp b/mission/com/TmStoreTaskBase.cpp index 80900975..8849b241 100644 --- a/mission/com/TmStoreTaskBase.cpp +++ b/mission/com/TmStoreTaskBase.cpp @@ -138,8 +138,17 @@ ReturnValue_t TmStoreTaskBase::performDump(PersistentTmStoreWithTmQueue& store, return result; } dumpedLen = tmReader.getFullPacketLen(); - result = channel.write(tmReader.getFullData(), dumpedLen); - if (result == DirectTmSinkIF::IS_BUSY) { + size_t partiallyWrittenSize = 0; + result = channel.write(tmReader.getFullData(), dumpedLen, partiallyWrittenSize); + if (result == VirtualChannelIF::PARTIALLY_WRITTEN) { + result = channel.handleLastWriteSynchronously(tmReader.getFullData(), partiallyWrittenSize, + dumpedLen - partiallyWrittenSize, 20); + if (result != returnvalue::OK) { + // TODO: Event? Might lead to dangerous spam though.. + sif::warning << "PersistentTmStore: Synchronous write of last segment failed with code 0x" + << std::setw(4) << std::hex << result << std::endl; + } + } else if (result == DirectTmSinkIF::IS_BUSY) { sif::warning << "PersistentTmStore: Unexpected VC channel busy" << std::endl; } else if (result != returnvalue::OK) { sif::warning << "PersistentTmStore: Unexpected VC channel write failure" << std::endl; diff --git a/mission/com/VirtualChannel.cpp b/mission/com/VirtualChannel.cpp index ff3749a9..b3201334 100644 --- a/mission/com/VirtualChannel.cpp +++ b/mission/com/VirtualChannel.cpp @@ -1,25 +1,64 @@ #include "VirtualChannel.h" +#include + VirtualChannel::VirtualChannel(object_id_t objectId, uint8_t vcId, const char* vcName, PtmeIF& ptme, const std::atomic_bool& txOn) : SystemObject(objectId), ptme(ptme), vcId(vcId), vcName(vcName), txOn(txOn) {} ReturnValue_t VirtualChannel::initialize() { return returnvalue::OK; } -ReturnValue_t VirtualChannel::sendNextTm(const uint8_t* data, size_t size) { - return write(data, size); +ReturnValue_t VirtualChannel::sendNextTm(const uint8_t* data, size_t size, size_t& writtenSize) { + return write(data, size, writtenSize); } -ReturnValue_t VirtualChannel::write(const uint8_t* data, size_t size) { - return ptme.writeToVc(vcId, data, size); +ReturnValue_t VirtualChannel::write(const uint8_t* data, size_t size, size_t& writtenSize) { + if (!ptme.containsVc(vcId)) { + return CHANNEL_DOES_NOT_EXIST; + } + return ptme.getVirtChannel(vcId)->write(data, size, writtenSize); } uint8_t VirtualChannel::getVcid() const { return vcId; } +ReturnValue_t VirtualChannel::finishWrite(const uint8_t* data, size_t remainingSize) { + if (!ptme.containsVc(vcId)) { + return CHANNEL_DOES_NOT_EXIST; + } + return ptme.getVirtChannel(vcId)->finishWrite(data, remainingSize); +} + const char* VirtualChannel::getName() const { return vcName.c_str(); } -bool VirtualChannel::isBusy() const { return ptme.isBusy(vcId); } +bool VirtualChannel::isBusy() const { + if (!ptme.containsVc(vcId)) { + return CHANNEL_DOES_NOT_EXIST; + } + return ptme.getVirtChannel(vcId)->isBusy(); +} -void VirtualChannel::cancelTransfer() { ptme.cancelTransfer(vcId); } +void VirtualChannel::cancelTransfer() { + if (!ptme.containsVc(vcId)) { + return; + } + ptme.getVirtChannel(vcId)->cancelTransfer(); +} bool VirtualChannel::isTxOn() const { return txOn; } + +ReturnValue_t VirtualChannel::handleLastWriteSynchronously(const uint8_t* data, size_t start, + size_t remLen, unsigned maxDelayMs) { + unsigned delayMs = 0; + while (true) { + if (isBusy()) { + if (delayMs >= maxDelayMs) { + break; + } + TaskFactory::delayTask(10); + delayMs += 10; + continue; + } + return finishWrite(data, start); + } + return returnvalue::FAILED; +} diff --git a/mission/com/VirtualChannel.h b/mission/com/VirtualChannel.h index 98aba903..9995772f 100644 --- a/mission/com/VirtualChannel.h +++ b/mission/com/VirtualChannel.h @@ -15,6 +15,10 @@ */ class VirtualChannel : public SystemObject, public VirtualChannelIF { public: + static constexpr uint8_t CLASS_ID = CLASS_ID::VIRTUAL_CHANNEL; + + static constexpr ReturnValue_t CHANNEL_DOES_NOT_EXIST = returnvalue::makeCode(CLASS_ID, 0); + /** * @brief Constructor * @@ -25,9 +29,12 @@ class VirtualChannel : public SystemObject, public VirtualChannelIF { const std::atomic_bool& linkStateProvider); ReturnValue_t initialize() override; - ReturnValue_t sendNextTm(const uint8_t* data, size_t size); + ReturnValue_t sendNextTm(const uint8_t* data, size_t size, size_t& writtenSize); bool isBusy() const override; - ReturnValue_t write(const uint8_t* data, size_t size) override; + ReturnValue_t write(const uint8_t* data, size_t size, size_t& writtenSize) override; + ReturnValue_t finishWrite(const uint8_t* data, size_t remainingSize) override; + ReturnValue_t handleLastWriteSynchronously(const uint8_t* data, size_t start, size_t remLen, + unsigned maxDelayMs); void cancelTransfer() override; uint8_t getVcid() const; bool isTxOn() const; diff --git a/mission/com/VirtualChannelWithQueue.cpp b/mission/com/VirtualChannelWithQueue.cpp index a90829ab..621a7268 100644 --- a/mission/com/VirtualChannelWithQueue.cpp +++ b/mission/com/VirtualChannelWithQueue.cpp @@ -36,8 +36,19 @@ ReturnValue_t VirtualChannelWithQueue::handleNextTm(bool performWriteOp) { return result; } + // TODO: Hnadle partial write handling + size_t partiallyWrittenSize = 0; if (performWriteOp) { - result = write(data, size); + result = write(data, size, partiallyWrittenSize); + if (result == PARTIALLY_WRITTEN) { + result = handleLastWriteSynchronously(data, size, partiallyWrittenSize, 20); + if (result != returnvalue::OK) { + // TODO: Event? Might lead to dangerous spam though.. + sif::warning + << "VirtualChannelWithQueue: Synchronous write of last segment failed with code 0x" + << std::setw(4) << std::hex << result << std::endl; + } + } } // Try delete in any case, ignore failures (which should not happen), it is more important to // propagate write errors. diff --git a/mission/tmtc/DirectTmSinkIF.h b/mission/tmtc/DirectTmSinkIF.h index 11a17c79..a5f3af42 100644 --- a/mission/tmtc/DirectTmSinkIF.h +++ b/mission/tmtc/DirectTmSinkIF.h @@ -13,6 +13,7 @@ class DirectTmSinkIF { static constexpr uint8_t CLASS_ID = CLASS_ID::TM_SINK; static constexpr ReturnValue_t IS_BUSY = returnvalue::makeCode(CLASS_ID, 0); + static constexpr ReturnValue_t PARTIALLY_WRITTEN = returnvalue::makeCode(CLASS_ID, 1); /** * @brief Implements the functionality to write to a TM sink directly @@ -20,9 +21,12 @@ class DirectTmSinkIF { * @param data Pointer to buffer holding the data to write * @param size Number of bytes to write * @return returnvalue::OK on success, returnvalue::FAILED on failure, IS_BUSY - * if the TM sink is busy. + * if the TM sink is busy, PARTIALLY_WRITTEN if only a portion of the bytes could be + * written. */ - virtual ReturnValue_t write(const uint8_t* data, size_t size) = 0; + virtual ReturnValue_t write(const uint8_t* data, size_t size, size_t& writtenSize) = 0; + + virtual ReturnValue_t finishWrite(const uint8_t* data, size_t remainingSize) = 0; virtual bool isBusy() const = 0; }; diff --git a/tmtc b/tmtc index e249f147..84df438e 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit e249f147bc1738003d31290df8f2b525d91c3482 +Subproject commit 84df438e9d74898cbb3c6319ba55193c0c8d0b0c From 99192606a26d80a2942f1fdefeb106bc298e7a81 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 13 Oct 2023 09:27:24 +0200 Subject: [PATCH 22/24] bugfixes for PAPB IF --- linux/ipcore/PapbVcInterface.cpp | 19 ++++++++++++------- linux/ipcore/PapbVcInterface.h | 3 +-- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/linux/ipcore/PapbVcInterface.cpp b/linux/ipcore/PapbVcInterface.cpp index 5e63aebc..2329a32e 100644 --- a/linux/ipcore/PapbVcInterface.cpp +++ b/linux/ipcore/PapbVcInterface.cpp @@ -37,7 +37,7 @@ ReturnValue_t PapbVcInterface::write(const uint8_t* data, size_t size, size_t& w abortPacketTransfer(); return returnvalue::FAILED; } - return finishWritePartialOpt(data, size, true); + return finishWriteInternal(data, size, writtenSize); } void PapbVcInterface::startPacketTransfer(ByteWidthCfg initWidth) { @@ -53,11 +53,20 @@ bool PapbVcInterface::pollReadyForPacket() const { return (reg >> 6) & 0b1; } -ReturnValue_t PapbVcInterface::finishWritePartialOpt(const uint8_t* data, size_t remainingSize, - bool handlePartial) { +ReturnValue_t PapbVcInterface::finishWrite(const uint8_t* data, size_t remainingSize) { + if (not pollReadyForPacket()) { + return returnvalue::FAILED; + } + size_t dummy = 0; + return finishWriteInternal(data, remainingSize, dummy); +} + +ReturnValue_t PapbVcInterface::finishWriteInternal(const uint8_t* data, size_t remainingSize, + size_t& writtenSize) { for (size_t idx = 0; idx < remainingSize; idx++) { if (not pollReadyForOctet(MAX_BUSY_POLLS)) { if (not pollReadyForPacket()) { + writtenSize = idx; return PARTIALLY_WRITTEN; } abortPacketTransfer(); @@ -109,8 +118,4 @@ inline bool PapbVcInterface::pollReadyForOctet(uint32_t maxCycles) const { return false; } -ReturnValue_t PapbVcInterface::finishWrite(const uint8_t* data, size_t remainingSize) { - return finishWritePartialOpt(data, remainingSize, false); -} - void PapbVcInterface::abortPacketTransfer() { *vcBaseReg = CONFIG_ABORT; } diff --git a/linux/ipcore/PapbVcInterface.h b/linux/ipcore/PapbVcInterface.h index 72b9b9f3..201580bc 100644 --- a/linux/ipcore/PapbVcInterface.h +++ b/linux/ipcore/PapbVcInterface.h @@ -43,8 +43,7 @@ class PapbVcInterface : public VirtualChannelIF { ReturnValue_t write(const uint8_t* data, size_t size, size_t& writtenSize) override; ReturnValue_t finishWrite(const uint8_t* data, size_t remainingSize) override; - ReturnValue_t finishWritePartialOpt(const uint8_t* data, size_t remainingSize, - bool handlePartial); + ReturnValue_t finishWriteInternal(const uint8_t* data, size_t remainingSize, size_t& writtenSize); void cancelTransfer() override; From 7c42e05c2374509d7a4ee14658d45ee4cee753c1 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 13 Oct 2023 09:29:57 +0200 Subject: [PATCH 23/24] wait duration fix --- mission/com/TmStoreTaskBase.cpp | 4 ++-- mission/com/VirtualChannelWithQueue.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mission/com/TmStoreTaskBase.cpp b/mission/com/TmStoreTaskBase.cpp index 8849b241..c51d6f9b 100644 --- a/mission/com/TmStoreTaskBase.cpp +++ b/mission/com/TmStoreTaskBase.cpp @@ -142,11 +142,11 @@ ReturnValue_t TmStoreTaskBase::performDump(PersistentTmStoreWithTmQueue& store, result = channel.write(tmReader.getFullData(), dumpedLen, partiallyWrittenSize); if (result == VirtualChannelIF::PARTIALLY_WRITTEN) { result = channel.handleLastWriteSynchronously(tmReader.getFullData(), partiallyWrittenSize, - dumpedLen - partiallyWrittenSize, 20); + dumpedLen - partiallyWrittenSize, 200); if (result != returnvalue::OK) { // TODO: Event? Might lead to dangerous spam though.. sif::warning << "PersistentTmStore: Synchronous write of last segment failed with code 0x" - << std::setw(4) << std::hex << result << std::endl; + << std::setw(4) << std::hex << result << std::dec << std::endl; } } else if (result == DirectTmSinkIF::IS_BUSY) { sif::warning << "PersistentTmStore: Unexpected VC channel busy" << std::endl; diff --git a/mission/com/VirtualChannelWithQueue.cpp b/mission/com/VirtualChannelWithQueue.cpp index 621a7268..53f2ee52 100644 --- a/mission/com/VirtualChannelWithQueue.cpp +++ b/mission/com/VirtualChannelWithQueue.cpp @@ -41,12 +41,12 @@ ReturnValue_t VirtualChannelWithQueue::handleNextTm(bool performWriteOp) { if (performWriteOp) { result = write(data, size, partiallyWrittenSize); if (result == PARTIALLY_WRITTEN) { - result = handleLastWriteSynchronously(data, size, partiallyWrittenSize, 20); + result = handleLastWriteSynchronously(data, size, partiallyWrittenSize, 200); if (result != returnvalue::OK) { // TODO: Event? Might lead to dangerous spam though.. sif::warning << "VirtualChannelWithQueue: Synchronous write of last segment failed with code 0x" - << std::setw(4) << std::hex << result << std::endl; + << std::setw(4) << std::hex << result << std::dec << std::endl; } } } From 8dbc5cad48d24a2bf9ce90c7715c237a79ede1a4 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 13 Oct 2023 09:39:50 +0200 Subject: [PATCH 24/24] more bugfixes --- CHANGELOG.md | 8 ++++++++ linux/ipcore/PapbVcInterface.cpp | 26 +++++++++++++++++++------- linux/ipcore/PapbVcInterface.h | 6 ++++-- mission/com/VirtualChannel.cpp | 6 +++--- mission/com/VirtualChannel.h | 2 +- mission/tmtc/DirectTmSinkIF.h | 3 ++- 6 files changed, 37 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a6d88025..b029d621 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,14 @@ will consitute of a breaking change warranting a new major release: # [unreleased] +## Fixed + +- If the PTME is driven in a way where it fills faster than it can be emptied, the interface + can become full during the process of a regular packet write. The interface of the PAPB VC + component was adapted to account for this partial success state. The caller must now check + for the `PARTIALLY_WRITTEN` state and must take care of finishing a write in some shape or + form before starting the next packet transfer. + # [v7.1.0] 2023-10-11 - Bumped `eive-tmtc` to v5.8.0. diff --git a/linux/ipcore/PapbVcInterface.cpp b/linux/ipcore/PapbVcInterface.cpp index 2329a32e..88684772 100644 --- a/linux/ipcore/PapbVcInterface.cpp +++ b/linux/ipcore/PapbVcInterface.cpp @@ -28,6 +28,10 @@ ReturnValue_t PapbVcInterface::write(const uint8_t* data, size_t size, size_t& w if (size < 4) { return returnvalue::FAILED; } + // The user must call finishWrite before starting a new packet transfer. + if (partialWriteActive) { + return INCOMPLETE_PARTIAL_WRITE; + } if (pollReadyForPacket()) { startPacketTransfer(ByteWidthCfg::ONE); } else { @@ -37,7 +41,7 @@ ReturnValue_t PapbVcInterface::write(const uint8_t* data, size_t size, size_t& w abortPacketTransfer(); return returnvalue::FAILED; } - return finishWriteInternal(data, size, writtenSize); + return finishWriteInternal(data, 0, size, writtenSize, false); } void PapbVcInterface::startPacketTransfer(ByteWidthCfg initWidth) { @@ -53,26 +57,34 @@ bool PapbVcInterface::pollReadyForPacket() const { return (reg >> 6) & 0b1; } -ReturnValue_t PapbVcInterface::finishWrite(const uint8_t* data, size_t remainingSize) { +ReturnValue_t PapbVcInterface::finishWrite(const uint8_t* data, size_t start, + size_t remainingSize) { if (not pollReadyForPacket()) { return returnvalue::FAILED; } size_t dummy = 0; - return finishWriteInternal(data, remainingSize, dummy); + return finishWriteInternal(data, start, remainingSize, dummy, true); } -ReturnValue_t PapbVcInterface::finishWriteInternal(const uint8_t* data, size_t remainingSize, - size_t& writtenSize) { +ReturnValue_t PapbVcInterface::finishWriteInternal(const uint8_t* data, size_t start, + size_t remainingSize, size_t& writtenSize, + bool abortOnPartialWrite) { for (size_t idx = 0; idx < remainingSize; idx++) { if (not pollReadyForOctet(MAX_BUSY_POLLS)) { if (not pollReadyForPacket()) { - writtenSize = idx; + writtenSize = start + idx; + partialWriteActive = true; + if (abortOnPartialWrite) { + abortPacketTransfer(); + partialWriteActive = false; + return returnvalue::FAILED; + } return PARTIALLY_WRITTEN; } abortPacketTransfer(); return returnvalue::FAILED; } - *(vcBaseReg + DATA_REG_OFFSET) = static_cast(data[idx]); + *(vcBaseReg + DATA_REG_OFFSET) = static_cast(data[start + idx]); } if (not pollReadyForOctet(MAX_BUSY_POLLS)) { abortPacketTransfer(); diff --git a/linux/ipcore/PapbVcInterface.h b/linux/ipcore/PapbVcInterface.h index 201580bc..35bd0439 100644 --- a/linux/ipcore/PapbVcInterface.h +++ b/linux/ipcore/PapbVcInterface.h @@ -42,8 +42,9 @@ class PapbVcInterface : public VirtualChannelIF { */ ReturnValue_t write(const uint8_t* data, size_t size, size_t& writtenSize) override; - ReturnValue_t finishWrite(const uint8_t* data, size_t remainingSize) override; - ReturnValue_t finishWriteInternal(const uint8_t* data, size_t remainingSize, size_t& writtenSize); + ReturnValue_t finishWrite(const uint8_t* data, size_t start, size_t remainingSize) override; + ReturnValue_t finishWriteInternal(const uint8_t* data, size_t start, size_t remainingSize, + size_t& writtenSize, bool abortOnPartialWrite); void cancelTransfer() override; @@ -91,6 +92,7 @@ class PapbVcInterface : public VirtualChannelIF { std::string uioFile; int mapNum = 0; + bool partialWriteActive = false; mutable struct timespec nextDelay = {.tv_sec = 0, .tv_nsec = 0}; const struct timespec BETWEEN_POLL_DELAY = {.tv_sec = 0, .tv_nsec = 10}; mutable struct timespec remDelay; diff --git a/mission/com/VirtualChannel.cpp b/mission/com/VirtualChannel.cpp index b3201334..140b23f6 100644 --- a/mission/com/VirtualChannel.cpp +++ b/mission/com/VirtualChannel.cpp @@ -21,11 +21,11 @@ ReturnValue_t VirtualChannel::write(const uint8_t* data, size_t size, size_t& wr uint8_t VirtualChannel::getVcid() const { return vcId; } -ReturnValue_t VirtualChannel::finishWrite(const uint8_t* data, size_t remainingSize) { +ReturnValue_t VirtualChannel::finishWrite(const uint8_t* data, size_t start, size_t remainingSize) { if (!ptme.containsVc(vcId)) { return CHANNEL_DOES_NOT_EXIST; } - return ptme.getVirtChannel(vcId)->finishWrite(data, remainingSize); + return ptme.getVirtChannel(vcId)->finishWrite(data, start, remainingSize); } const char* VirtualChannel::getName() const { return vcName.c_str(); } @@ -58,7 +58,7 @@ ReturnValue_t VirtualChannel::handleLastWriteSynchronously(const uint8_t* data, delayMs += 10; continue; } - return finishWrite(data, start); + return finishWrite(data, start, remLen); } return returnvalue::FAILED; } diff --git a/mission/com/VirtualChannel.h b/mission/com/VirtualChannel.h index 9995772f..3d61bd13 100644 --- a/mission/com/VirtualChannel.h +++ b/mission/com/VirtualChannel.h @@ -32,7 +32,7 @@ class VirtualChannel : public SystemObject, public VirtualChannelIF { ReturnValue_t sendNextTm(const uint8_t* data, size_t size, size_t& writtenSize); bool isBusy() const override; ReturnValue_t write(const uint8_t* data, size_t size, size_t& writtenSize) override; - ReturnValue_t finishWrite(const uint8_t* data, size_t remainingSize) override; + ReturnValue_t finishWrite(const uint8_t* data, size_t start, size_t remainingSize) override; ReturnValue_t handleLastWriteSynchronously(const uint8_t* data, size_t start, size_t remLen, unsigned maxDelayMs); void cancelTransfer() override; diff --git a/mission/tmtc/DirectTmSinkIF.h b/mission/tmtc/DirectTmSinkIF.h index a5f3af42..e1fcf54f 100644 --- a/mission/tmtc/DirectTmSinkIF.h +++ b/mission/tmtc/DirectTmSinkIF.h @@ -14,6 +14,7 @@ class DirectTmSinkIF { static constexpr ReturnValue_t IS_BUSY = returnvalue::makeCode(CLASS_ID, 0); static constexpr ReturnValue_t PARTIALLY_WRITTEN = returnvalue::makeCode(CLASS_ID, 1); + static constexpr ReturnValue_t INCOMPLETE_PARTIAL_WRITE = returnvalue::makeCode(CLASS_ID, 2); /** * @brief Implements the functionality to write to a TM sink directly @@ -26,7 +27,7 @@ class DirectTmSinkIF { */ virtual ReturnValue_t write(const uint8_t* data, size_t size, size_t& writtenSize) = 0; - virtual ReturnValue_t finishWrite(const uint8_t* data, size_t remainingSize) = 0; + virtual ReturnValue_t finishWrite(const uint8_t* data, size_t start, size_t remainingSize) = 0; virtual bool isBusy() const = 0; };