From 159da20ef2a485f6f1924a55a9e0fd9aa77c6328 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 20 Mar 2023 14:31:10 +0100 Subject: [PATCH 01/22] some tweaks for busy handling --- linux/ipcore/PapbVcInterface.cpp | 25 ++++++++++------ mission/tmtc/LiveTmTask.cpp | 3 ++ mission/tmtc/TmStoreTaskBase.cpp | 37 +++++++++++++----------- mission/tmtc/VirtualChannelWithQueue.cpp | 5 +++- 4 files changed, 43 insertions(+), 27 deletions(-) diff --git a/linux/ipcore/PapbVcInterface.cpp b/linux/ipcore/PapbVcInterface.cpp index 51afc15d..2f875d04 100644 --- a/linux/ipcore/PapbVcInterface.cpp +++ b/linux/ipcore/PapbVcInterface.cpp @@ -44,16 +44,23 @@ void PapbVcInterface::endPacketTransfer() { *vcBaseReg = CONFIG_END; } ReturnValue_t PapbVcInterface::pollPapbBusySignal() const { gpio::Levels papbBusyState = gpio::Levels::LOW; ReturnValue_t result = returnvalue::OK; + uint32_t busyIdx = 0; - /** Check if PAPB interface is ready to receive data */ - result = gpioComIF->readGpio(papbBusyId, papbBusyState); - if (result != returnvalue::OK) { - sif::warning << "PapbVcInterface::pollPapbBusySignal: Failed to read papb busy signal" - << std::endl; - return returnvalue::FAILED; - } - if (papbBusyState == gpio::Levels::LOW) { - return PAPB_BUSY; + while (true) { + /** Check if PAPB interface is ready to receive data */ + result = gpioComIF->readGpio(papbBusyId, papbBusyState); + if (result != returnvalue::OK) { + sif::warning << "PapbVcInterface::pollPapbBusySignal: Failed to read papb busy signal" + << std::endl; + return returnvalue::FAILED; + } + if (papbBusyState == gpio::Levels::HIGH) { + return returnvalue::OK; + } + if (busyIdx == 100) { + return PAPB_BUSY; + } + busyIdx++; } return returnvalue::OK; diff --git a/mission/tmtc/LiveTmTask.cpp b/mission/tmtc/LiveTmTask.cpp index 53a9f04a..7e6d3de6 100644 --- a/mission/tmtc/LiveTmTask.cpp +++ b/mission/tmtc/LiveTmTask.cpp @@ -11,6 +11,9 @@ ReturnValue_t LiveTmTask::performOperation(uint8_t opCode) { while (true) { // The funnel tasks are scheduled here directly as well. ReturnValue_t result = channel.sendNextTm(); + if (result == DirectTmSinkIF::IS_BUSY) { + sif::error << "Lost live TM, PAPB busy" << std::endl; + } if (result == MessageQueueIF::EMPTY) { if (tmFunnelCd.hasTimedOut()) { pusFunnel.performOperation(0); diff --git a/mission/tmtc/TmStoreTaskBase.cpp b/mission/tmtc/TmStoreTaskBase.cpp index d8b6bdcb..8328c65e 100644 --- a/mission/tmtc/TmStoreTaskBase.cpp +++ b/mission/tmtc/TmStoreTaskBase.cpp @@ -26,24 +26,27 @@ bool TmStoreTaskBase::handleOneStore(PersistentTmStoreWithTmQueue& store, if (store.getState() == PersistentTmStore::State::DUMPING) { size_t dumpedLen = 0; bool fileHasSwapped; - if (not channel.isBusy()) { - tmSinkBusyCd.resetTimer(); - result = store.dumpNextPacket(channel, dumpedLen, fileHasSwapped); - if ((result == PersistentTmStore::DUMP_DONE or result == returnvalue::OK) and dumpedLen > 0) { - dumpContext.dumpedBytes += dumpedLen; - dumpContext.numberOfDumpedPackets += 1; - } - if (result == PersistentTmStore::DUMP_DONE) { - uint32_t startTime; - uint32_t endTime; - store.getStartAndEndTimeCurrentOrLastDump(startTime, endTime); - triggerEvent(dumpContext.eventIfDone, dumpContext.numberOfDumpedPackets, - dumpContext.dumpedBytes); - dumpsPerformed = true; - } else if (result == returnvalue::OK) { - dumpsPerformed = true; - } + // if (not channel.isBusy()) { + tmSinkBusyCd.resetTimer(); + result = store.dumpNextPacket(channel, dumpedLen, fileHasSwapped); + if (result == DirectTmSinkIF::IS_BUSY) { + sif::warning << "PersistentTmStore: PAPB was too busy for dump" << std::endl; } + if ((result == PersistentTmStore::DUMP_DONE or result == returnvalue::OK) and dumpedLen > 0) { + dumpContext.dumpedBytes += dumpedLen; + dumpContext.numberOfDumpedPackets += 1; + } + if (result == PersistentTmStore::DUMP_DONE) { + uint32_t startTime; + uint32_t endTime; + store.getStartAndEndTimeCurrentOrLastDump(startTime, endTime); + triggerEvent(dumpContext.eventIfDone, dumpContext.numberOfDumpedPackets, + dumpContext.dumpedBytes); + dumpsPerformed = true; + } else if (result == returnvalue::OK) { + dumpsPerformed = true; + } + //} if (cancelDumpCd.hasTimedOut() or tmSinkBusyCd.hasTimedOut()) { triggerEvent(persTmStore::DUMP_WAS_CANCELLED, store.getObjectId()); store.cancelDump(); diff --git a/mission/tmtc/VirtualChannelWithQueue.cpp b/mission/tmtc/VirtualChannelWithQueue.cpp index 884dbf89..ef93687e 100644 --- a/mission/tmtc/VirtualChannelWithQueue.cpp +++ b/mission/tmtc/VirtualChannelWithQueue.cpp @@ -36,7 +36,10 @@ ReturnValue_t VirtualChannelWithQueue::sendNextTm() { return result; } - write(data, size); + ReturnValue_t result = write(data, size); + if (result != returnvalue::OK) { + return result; + } tmStore.deleteData(storeId); if (result != returnvalue::OK) { return result; -- 2.43.0 From 394f0498c56bbc4b0951d5a3282c92c72d8a1114 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 20 Mar 2023 17:58:23 +0100 Subject: [PATCH 02/22] small compile error --- mission/tmtc/VirtualChannelWithQueue.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mission/tmtc/VirtualChannelWithQueue.cpp b/mission/tmtc/VirtualChannelWithQueue.cpp index ef93687e..c00ccd9c 100644 --- a/mission/tmtc/VirtualChannelWithQueue.cpp +++ b/mission/tmtc/VirtualChannelWithQueue.cpp @@ -36,7 +36,7 @@ ReturnValue_t VirtualChannelWithQueue::sendNextTm() { return result; } - ReturnValue_t result = write(data, size); + result = write(data, size); if (result != returnvalue::OK) { return result; } -- 2.43.0 From 68e68afdd6fd6640a717af933ad755042351f2ea Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 20 Mar 2023 17:59:46 +0100 Subject: [PATCH 03/22] changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3727efef..b30044a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,10 @@ will consitute of a breaking change warranting a new major release: - Fixed transition for dual power lane assemblies: When going from dual side submode to single side submode, perform logical commanding first, similarly to when going to OFF mode. +- PAPB busy polling now implemented properly with an upper bound of how often the PAPB is allowed + to be busy before returning the BUSY returnvalue. Also propagate and check for that case properly. + Ideally, this will never be an issue and the PAPB VC interface should never block for a longer + period. ## Changed -- 2.43.0 From 9c22e4cab2b1b2fcb24f3021ecf47df7a3e86a4a Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 21 Mar 2023 12:58:28 +0100 Subject: [PATCH 04/22] small sched tweaks --- bsp_q7s/core/scheduling.cpp | 4 ++-- tmtc | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bsp_q7s/core/scheduling.cpp b/bsp_q7s/core/scheduling.cpp index bd9ee01c..f6727420 100644 --- a/bsp_q7s/core/scheduling.cpp +++ b/bsp_q7s/core/scheduling.cpp @@ -471,7 +471,7 @@ void scheduling::createPstTasks(TaskFactory& factory, TaskDeadlineMissedFunction /* Polling Sequence Table Default */ #if OBSW_ADD_SPI_TEST_CODE == 0 FixedTimeslotTaskIF* syrlinksPst = factory.createFixedTimeslotTask( - "SYRLINKS", 45, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 0.5, missedDeadlineFunc); + "SYRLINKS", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 0.5, missedDeadlineFunc); result = pst::pstSyrlinks(syrlinksPst); if (result != returnvalue::OK) { if (result == FixedTimeslotTaskIF::SLOT_LIST_EMPTY) { @@ -535,7 +535,7 @@ void scheduling::createPusTasks(TaskFactory& factory, TaskDeadlineMissedFunction taskVec.push_back(pusHighPrio); PeriodicTaskIF* pusMedPrio = factory.createPeriodicTask( - "PUS_MED_PRIO", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.8, missedDeadlineFunc); + "PUS_MED_PRIO", 45, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.8, missedDeadlineFunc); result = pusMedPrio->addComponent(objects::PUS_SERVICE_3_HOUSEKEEPING); if (result != returnvalue::OK) { scheduling::printAddObjectError("PUS_3", objects::PUS_SERVICE_3_HOUSEKEEPING); diff --git a/tmtc b/tmtc index e5a09e14..b32a9273 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit e5a09e148b45d0380dc6d9a1a88002bab4b0376c +Subproject commit b32a9273ae4186a440685ffde7618f017cfdb268 -- 2.43.0 From beb80e7a0b99c77e3c7d14a0310030f0c3883564 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 21 Mar 2023 14:09:59 +0100 Subject: [PATCH 05/22] transform tm stores into quasi background threads --- bsp_q7s/core/scheduling.cpp | 8 ++--- mission/tmtc/PersistentLogTmStoreTask.cpp | 31 +++++++++++--------- mission/tmtc/PersistentLogTmStoreTask.h | 2 ++ mission/tmtc/PersistentSingleTmStoreTask.cpp | 5 ++++ mission/tmtc/PersistentSingleTmStoreTask.h | 1 + mission/tmtc/TmStoreTaskBase.cpp | 1 - mission/tmtc/TmStoreTaskBase.h | 1 + 7 files changed, 30 insertions(+), 19 deletions(-) diff --git a/bsp_q7s/core/scheduling.cpp b/bsp_q7s/core/scheduling.cpp index f6727420..782a2666 100644 --- a/bsp_q7s/core/scheduling.cpp +++ b/bsp_q7s/core/scheduling.cpp @@ -186,19 +186,19 @@ void scheduling::initTasks() { scheduling::printAddObjectError("LIVE_TM", objects::LIVE_TM_TASK); } PeriodicTaskIF* logTmTask = factory->createPeriodicTask( - "LOG_STORE_AND_TM", 45, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr); + "LOG_STORE_AND_TM", 15, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr); result = logTmTask->addComponent(objects::LOG_STORE_AND_TM_TASK); if (result != returnvalue::OK) { scheduling::printAddObjectError("LOG_STORE_AND_TM", objects::LOG_STORE_AND_TM_TASK); } PeriodicTaskIF* hkTmTask = factory->createPeriodicTask( - "HK_STORE_AND_TM", 45, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr); + "HK_STORE_AND_TM", 15, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr); result = hkTmTask->addComponent(objects::HK_STORE_AND_TM_TASK); if (result != returnvalue::OK) { scheduling::printAddObjectError("HK_STORE_AND_TM", objects::HK_STORE_AND_TM_TASK); } PeriodicTaskIF* cfdpTmTask = factory->createPeriodicTask( - "CFDP_STORE_AND_TM", 45, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr); + "CFDP_STORE_AND_TM", 15, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr); result = cfdpTmTask->addComponent(objects::CFDP_STORE_AND_TM_TASK); if (result != returnvalue::OK) { scheduling::printAddObjectError("CFDP_STORE_AND_TM", objects::CFDP_STORE_AND_TM_TASK); @@ -326,7 +326,7 @@ void scheduling::initTasks() { #if OBSW_ADD_PLOC_SUPERVISOR == 1 PeriodicTaskIF* supvHelperTask = factory->createPeriodicTask( - "PLOC_SUPV_HELPER", 10, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, missedDeadlineFunc); + "PLOC_SUPV_HELPER", 20, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, missedDeadlineFunc); result = supvHelperTask->addComponent(objects::PLOC_SUPERVISOR_HELPER); if (result != returnvalue::OK) { scheduling::printAddObjectError("PLOC_SUPV_HELPER", objects::PLOC_SUPERVISOR_HELPER); diff --git a/mission/tmtc/PersistentLogTmStoreTask.cpp b/mission/tmtc/PersistentLogTmStoreTask.cpp index dc17ec58..41d90875 100644 --- a/mission/tmtc/PersistentLogTmStoreTask.cpp +++ b/mission/tmtc/PersistentLogTmStoreTask.cpp @@ -13,26 +13,29 @@ PersistentLogTmStoreTask::PersistentLogTmStoreTask(object_id_t objectId, Storage miscStoreContext(persTmStore::DUMP_MISC_STORE_DONE) {} ReturnValue_t PersistentLogTmStoreTask::performOperation(uint8_t opCode) { + bool someonesBusy = false; + auto stateHandlingForStore = [&](bool storeIsBusy) { + if (storeIsBusy) { + someonesBusy = true; + } + if (fileHasSwapped) { + someFileWasSwapped = fileHasSwapped; + } + }; while (true) { if (not cyclicStoreCheck()) { continue; } - bool someonesBusy = false; - bool busy = false; - busy = handleOneStore(stores.okStore, okStoreContext); - if (busy) { - someonesBusy = true; - } - busy = handleOneStore(stores.notOkStore, notOkStoreContext); - if (busy) { - someonesBusy = true; - } - busy = handleOneStore(stores.miscStore, miscStoreContext); - if (busy) { - someonesBusy = true; - } + someFileWasSwapped = false; + bool busy = handleOneStore(stores.okStore, okStoreContext); + stateHandlingForStore(busy); + stateHandlingForStore(handleOneStore(stores.notOkStore, notOkStoreContext)); + stateHandlingForStore(handleOneStore(stores.miscStore, miscStoreContext)); if (not someonesBusy) { TaskFactory::delayTask(40); + } else if (someFileWasSwapped and graceDelayDuringDumping.hasTimedOut()) { + TaskFactory::delayTask(2); + graceDelayDuringDumping.resetTimer(); } } } diff --git a/mission/tmtc/PersistentLogTmStoreTask.h b/mission/tmtc/PersistentLogTmStoreTask.h index 8cd74f20..99cb9118 100644 --- a/mission/tmtc/PersistentLogTmStoreTask.h +++ b/mission/tmtc/PersistentLogTmStoreTask.h @@ -32,6 +32,8 @@ class PersistentLogTmStoreTask : public TmStoreTaskBase, public ExecutableObject DumpContext notOkStoreContext; DumpContext miscStoreContext; Countdown tcHandlingCd = Countdown(400); + Countdown graceDelayDuringDumping = Countdown(200); + bool someFileWasSwapped = false; bool initStoresIfPossible(); }; diff --git a/mission/tmtc/PersistentSingleTmStoreTask.cpp b/mission/tmtc/PersistentSingleTmStoreTask.cpp index 3588b9fd..af394672 100644 --- a/mission/tmtc/PersistentSingleTmStoreTask.cpp +++ b/mission/tmtc/PersistentSingleTmStoreTask.cpp @@ -18,6 +18,11 @@ ReturnValue_t PersistentSingleTmStoreTask::performOperation(uint8_t opCode) { bool busy = handleOneStore(storeWithQueue, dumpContext); if (not busy) { TaskFactory::delayTask(40); + } else { + if (fileHasSwapped and graceDelayDuringDumping.hasTimedOut()) { + TaskFactory::delayTask(2); + graceDelayDuringDumping.resetTimer(); + } } } } diff --git a/mission/tmtc/PersistentSingleTmStoreTask.h b/mission/tmtc/PersistentSingleTmStoreTask.h index b21ddf1d..7a4dd7ca 100644 --- a/mission/tmtc/PersistentSingleTmStoreTask.h +++ b/mission/tmtc/PersistentSingleTmStoreTask.h @@ -19,6 +19,7 @@ class PersistentSingleTmStoreTask : public TmStoreTaskBase, public ExecutableObj PersistentTmStoreWithTmQueue& storeWithQueue; DumpContext dumpContext; Countdown tcHandlingCd = Countdown(400); + Countdown graceDelayDuringDumping = Countdown(100); bool initStoresIfPossible(); }; diff --git a/mission/tmtc/TmStoreTaskBase.cpp b/mission/tmtc/TmStoreTaskBase.cpp index 8328c65e..50ec63e4 100644 --- a/mission/tmtc/TmStoreTaskBase.cpp +++ b/mission/tmtc/TmStoreTaskBase.cpp @@ -25,7 +25,6 @@ bool TmStoreTaskBase::handleOneStore(PersistentTmStoreWithTmQueue& store, // Dump TMs when applicable if (store.getState() == PersistentTmStore::State::DUMPING) { size_t dumpedLen = 0; - bool fileHasSwapped; // if (not channel.isBusy()) { tmSinkBusyCd.resetTimer(); result = store.dumpNextPacket(channel, dumpedLen, fileHasSwapped); diff --git a/mission/tmtc/TmStoreTaskBase.h b/mission/tmtc/TmStoreTaskBase.h index 2d899be3..1f0834d6 100644 --- a/mission/tmtc/TmStoreTaskBase.h +++ b/mission/tmtc/TmStoreTaskBase.h @@ -45,6 +45,7 @@ class TmStoreTaskBase : public SystemObject { Countdown tmSinkBusyCd = Countdown(60 * 1000); VirtualChannel& channel; bool storesInitialized = false; + bool fileHasSwapped = false; SdCardMountedIF& sdcMan; }; -- 2.43.0 From 6a07471c3af7c9b93a1d65b9b559bead7c699455 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 21 Mar 2023 14:11:19 +0100 Subject: [PATCH 06/22] changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b30044a7..64dc2f07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,8 @@ will consitute of a breaking change warranting a new major release: Furthermore, the submode in the NORMAL mode now should be 0 instead of some ON mode submode. - Updated GYR bias values to newest measurements. This also corrects the ADIS values to always consit of just one digit. +- The persistent TM stores now have low priorities and behave like background thread now. This + should prevent them from blocking or slowing down the system even during dumps. # [v1.38.0] 2023-03-17 -- 2.43.0 From 8464dd1eaee32107a48e49775c167b8b29593f8e Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 21 Mar 2023 14:12:00 +0100 Subject: [PATCH 07/22] changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 64dc2f07..4e383436 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,7 +31,7 @@ will consitute of a breaking change warranting a new major release: Furthermore, the submode in the NORMAL mode now should be 0 instead of some ON mode submode. - Updated GYR bias values to newest measurements. This also corrects the ADIS values to always consit of just one digit. -- The persistent TM stores now have low priorities and behave like background thread now. This +- The persistent TM stores now have low priorities and behave like background threads now. This should prevent them from blocking or slowing down the system even during dumps. # [v1.38.0] 2023-03-17 -- 2.43.0 From 9003eea07bbd83b3a9ac39be03f17fb64beb5437 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 21 Mar 2023 14:16:35 +0100 Subject: [PATCH 08/22] task name adaptions --- bsp_q7s/core/scheduling.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/bsp_q7s/core/scheduling.cpp b/bsp_q7s/core/scheduling.cpp index 782a2666..491a8bd1 100644 --- a/bsp_q7s/core/scheduling.cpp +++ b/bsp_q7s/core/scheduling.cpp @@ -89,7 +89,7 @@ void scheduling::initTasks() { /* TMTC Distribution */ PeriodicTaskIF* tmTcDistributor = factory->createPeriodicTask( - "DIST", 45, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc); + "TC_DIST", 45, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc); #if OBSW_ADD_TCPIP_SERVERS == 1 #if OBSW_ADD_TMTC_UDP_SERVER == 1 result = tmTcDistributor->addComponent(objects::UDP_TMTC_SERVER); @@ -186,19 +186,19 @@ void scheduling::initTasks() { scheduling::printAddObjectError("LIVE_TM", objects::LIVE_TM_TASK); } PeriodicTaskIF* logTmTask = factory->createPeriodicTask( - "LOG_STORE_AND_TM", 15, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr); + "LOG_PSTORE", 15, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr); result = logTmTask->addComponent(objects::LOG_STORE_AND_TM_TASK); if (result != returnvalue::OK) { scheduling::printAddObjectError("LOG_STORE_AND_TM", objects::LOG_STORE_AND_TM_TASK); } PeriodicTaskIF* hkTmTask = factory->createPeriodicTask( - "HK_STORE_AND_TM", 15, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr); + "HK_PSTORE", 15, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr); result = hkTmTask->addComponent(objects::HK_STORE_AND_TM_TASK); if (result != returnvalue::OK) { scheduling::printAddObjectError("HK_STORE_AND_TM", objects::HK_STORE_AND_TM_TASK); } PeriodicTaskIF* cfdpTmTask = factory->createPeriodicTask( - "CFDP_STORE_AND_TM", 15, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr); + "CFDP_PSTORE", 15, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr); result = cfdpTmTask->addComponent(objects::CFDP_STORE_AND_TM_TASK); if (result != returnvalue::OK) { scheduling::printAddObjectError("CFDP_STORE_AND_TM", objects::CFDP_STORE_AND_TM_TASK); @@ -206,7 +206,7 @@ void scheduling::initTasks() { #if OBSW_ADD_CFDP_COMPONENTS == 1 PeriodicTaskIF* cfdpTask = factory->createPeriodicTask( - "CFDP Handler", 45, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.4, missedDeadlineFunc); + "CFDP_HANDLER", 45, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.4, missedDeadlineFunc); result = cfdpTask->addComponent(objects::CFDP_HANDLER); if (result != returnvalue::OK) { scheduling::printAddObjectError("CFDP Handler", objects::CFDP_HANDLER); @@ -486,7 +486,7 @@ void scheduling::createPstTasks(TaskFactory& factory, TaskDeadlineMissedFunction #if OBSW_ADD_I2C_TEST_CODE == 0 FixedTimeslotTaskIF* i2cPst = factory.createFixedTimeslotTask( - "I2C_PST", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 0.4, missedDeadlineFunc); + "I2C_PS_PST", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 0.4, missedDeadlineFunc); result = pst::pstI2cProcessingSystem(i2cPst); if (result != returnvalue::OK) { if (result == FixedTimeslotTaskIF::SLOT_LIST_EMPTY) { -- 2.43.0 From 884462e79338d2ee9a1c7f9f440a551a13178145 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 23 Mar 2023 12:03:53 +0100 Subject: [PATCH 09/22] changelog --- CHANGELOG.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6fd8daa6..2b1953c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,13 @@ will consitute of a breaking change warranting a new major release: # [unreleased] +## Fixed + +- PAPB busy polling now implemented properly with an upper bound of how often the PAPB is allowed + to be busy before returning the BUSY returnvalue. Also propagate and check for that case properly. + Ideally, this will never be an issue and the PAPB VC interface should never block for a longer + period. + ## Added - The persistent TM stores now have low priorities and behave like background threads now. This @@ -50,10 +57,6 @@ eive-tmtc: v2.19.3 - Fixed transition for dual power lane assemblies: When going from dual side submode to single side submode, perform logical commanding first, similarly to when going to OFF mode. -- PAPB busy polling now implemented properly with an upper bound of how often the PAPB is allowed - to be busy before returning the BUSY returnvalue. Also propagate and check for that case properly. - Ideally, this will never be an issue and the PAPB VC interface should never block for a longer - period. - GPS time is only set to valid if at least one satellite is in view. ## Changed -- 2.43.0 From f61c448a240db68f393993ec1de37c8dcbe3c64d Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 23 Mar 2023 11:32:46 +0100 Subject: [PATCH 10/22] important bugfix --- mission/tmtc/PersistentLogTmStoreTask.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mission/tmtc/PersistentLogTmStoreTask.cpp b/mission/tmtc/PersistentLogTmStoreTask.cpp index 41d90875..06256d73 100644 --- a/mission/tmtc/PersistentLogTmStoreTask.cpp +++ b/mission/tmtc/PersistentLogTmStoreTask.cpp @@ -26,9 +26,9 @@ ReturnValue_t PersistentLogTmStoreTask::performOperation(uint8_t opCode) { if (not cyclicStoreCheck()) { continue; } + someonesBusy = false; someFileWasSwapped = false; - bool busy = handleOneStore(stores.okStore, okStoreContext); - stateHandlingForStore(busy); + stateHandlingForStore(handleOneStore(stores.okStore, okStoreContext)); stateHandlingForStore(handleOneStore(stores.notOkStore, notOkStoreContext)); stateHandlingForStore(handleOneStore(stores.miscStore, miscStoreContext)); if (not someonesBusy) { -- 2.43.0 From dda8261fc3c6b7611d3363c1b77796f0dc650c71 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 23 Mar 2023 11:42:24 +0100 Subject: [PATCH 11/22] stry debug printout --- mission/tmtc/PersistentTmStore.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mission/tmtc/PersistentTmStore.cpp b/mission/tmtc/PersistentTmStore.cpp index 445eee9d..4b6ebbdc 100644 --- a/mission/tmtc/PersistentTmStore.cpp +++ b/mission/tmtc/PersistentTmStore.cpp @@ -216,7 +216,7 @@ ReturnValue_t PersistentTmStore::loadNextDumpFile() { sif::error << "PersistentTmStore: Could not retrieve file size: " << e.message() << std::endl; continue; } - sif::debug << "Path: " << dumpParams.dirEntry.path() << std::endl; + //sif::debug << "Path: " << dumpParams.dirEntry.path() << std::endl; // Can't even read CCSDS header. if (dumpParams.fileSize <= 6) { -- 2.43.0 From 493f89e0cbc05c1e78fa4c91b4ab63dd6fd86b3d Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 23 Mar 2023 15:43:14 +0100 Subject: [PATCH 12/22] this is tricky --- fsfw | 2 +- linux/ipcore/PapbVcInterface.cpp | 34 ++++++++++++----- linux/ipcore/PapbVcInterface.h | 17 ++++++--- mission/tmtc/CcsdsIpCoreHandler.cpp | 1 - mission/tmtc/CcsdsIpCoreHandler.h | 2 +- mission/tmtc/PersistentLogTmStoreTask.cpp | 7 +++- mission/tmtc/PersistentSingleTmStoreTask.cpp | 9 +++-- mission/tmtc/PersistentTmStore.cpp | 2 +- mission/tmtc/TmStoreTaskBase.cpp | 40 ++++++++++---------- 9 files changed, 70 insertions(+), 44 deletions(-) diff --git a/fsfw b/fsfw index 227524a2..33ac3950 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit 227524a21da755d125bcb1a5ff67bcbc452f8cf9 +Subproject commit 33ac395072f0145b6e80e12deae978a5e0432f08 diff --git a/linux/ipcore/PapbVcInterface.cpp b/linux/ipcore/PapbVcInterface.cpp index 2f875d04..cb563a65 100644 --- a/linux/ipcore/PapbVcInterface.cpp +++ b/linux/ipcore/PapbVcInterface.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "fsfw/serviceinterface/ServiceInterface.h" @@ -15,7 +16,13 @@ PapbVcInterface::~PapbVcInterface() {} ReturnValue_t PapbVcInterface::initialize() { UioMapper uioMapper(uioFile, mapNum); - return uioMapper.getMappedAdress(&vcBaseReg, UioMapper::Permissions::WRITE_ONLY); + uint32_t* baseReg; + ReturnValue_t result = uioMapper.getMappedAdress(&baseReg, UioMapper::Permissions::WRITE_ONLY); + if (result != returnvalue::OK) { + return result; + } + vcBaseReg = baseReg; + return returnvalue::OK; } ReturnValue_t PapbVcInterface::write(const uint8_t* data, size_t size) { @@ -24,27 +31,27 @@ ReturnValue_t PapbVcInterface::write(const uint8_t* data, size_t size) { } for (size_t idx = 0; idx < size; idx++) { if (pollPapbBusySignal() == returnvalue::OK) { - *(vcBaseReg + DATA_REG_OFFSET) = static_cast(*(data + idx)); + *(vcBaseReg + DATA_REG_OFFSET) = static_cast(data[idx]); } else { - sif::warning << "PapbVcInterface::write: Only written " << idx << " of " << size << " data" - << std::endl; - return returnvalue::FAILED; + abortPacketTransfer(); + return DirectTmSinkIF::IS_BUSY; } } if (pollPapbBusySignal() == returnvalue::OK) { - endPacketTransfer(); + completePacketTransfer(); } return returnvalue::OK; } void PapbVcInterface::startPacketTransfer() { *vcBaseReg = CONFIG_START; } -void PapbVcInterface::endPacketTransfer() { *vcBaseReg = CONFIG_END; } +void PapbVcInterface::completePacketTransfer() { *vcBaseReg = CONFIG_END; } ReturnValue_t PapbVcInterface::pollPapbBusySignal() const { gpio::Levels papbBusyState = gpio::Levels::LOW; - ReturnValue_t result = returnvalue::OK; + ReturnValue_t result; uint32_t busyIdx = 0; + uint32_t delayCount = 0; while (true) { /** Check if PAPB interface is ready to receive data */ @@ -57,12 +64,17 @@ ReturnValue_t PapbVcInterface::pollPapbBusySignal() const { if (papbBusyState == gpio::Levels::HIGH) { return returnvalue::OK; } - if (busyIdx == 100) { + if (busyIdx == 3) { + usleep(100); + busyIdx = 0; + delayCount += 1; + continue; + } + if (delayCount == 1000) { return PAPB_BUSY; } busyIdx++; } - return returnvalue::OK; } @@ -104,3 +116,5 @@ ReturnValue_t PapbVcInterface::sendTestFrame() { return returnvalue::OK; } + +void PapbVcInterface::abortPacketTransfer() { *vcBaseReg = CONFIG_ABORT; } diff --git a/linux/ipcore/PapbVcInterface.h b/linux/ipcore/PapbVcInterface.h index d4694a62..b517962c 100644 --- a/linux/ipcore/PapbVcInterface.h +++ b/linux/ipcore/PapbVcInterface.h @@ -51,16 +51,21 @@ class PapbVcInterface : public VirtualChannelIF { /** * Configuration bits: * bit[1:0]: Size of data (1,2,3 or 4 bytes). 1 Byte <=> b00 - * bit[2]: Set this bit to 1 to abort a transfered packet + * bit[2]: Set this bit to 1 to abort a transferred packet * bit[3]: Signals to VcInterface the start of a new telemetry packet */ - static const uint32_t CONFIG_START = 0x8; + static constexpr uint32_t CONFIG_START = 0b00001000; + + /** + * Abort a transferred packet. + */ + static constexpr uint32_t CONFIG_ABORT = 0b00000100; /** * Writing this word to the VcInterface base address signals to the virtual channel interface * that a complete tm packet has been transferred. */ - static const uint32_t CONFIG_END = 0x0; + static constexpr uint32_t CONFIG_END = 0x0; /** * Writing to this offset within the memory space of a virtual channel will insert data for @@ -79,7 +84,7 @@ class PapbVcInterface : public VirtualChannelIF { std::string uioFile; int mapNum = 0; - uint32_t* vcBaseReg = nullptr; + volatile uint32_t* vcBaseReg = nullptr; uint32_t vcOffset = 0; @@ -89,11 +94,13 @@ class PapbVcInterface : public VirtualChannelIF { */ void startPacketTransfer(); + void abortPacketTransfer(); + /** * @brief This function sends the config byte to the virtual channel interface of the PTME * IP Core to signal the end of a packet transfer. */ - void endPacketTransfer(); + void completePacketTransfer(); /** * @brief This function reads the papb busy signal indicating whether the virtual channel diff --git a/mission/tmtc/CcsdsIpCoreHandler.cpp b/mission/tmtc/CcsdsIpCoreHandler.cpp index c9493f47..39f17487 100644 --- a/mission/tmtc/CcsdsIpCoreHandler.cpp +++ b/mission/tmtc/CcsdsIpCoreHandler.cpp @@ -39,7 +39,6 @@ ReturnValue_t CcsdsIpCoreHandler::performOperation(uint8_t operationCode) { } ReturnValue_t CcsdsIpCoreHandler::initialize() { - AcceptsTelecommandsIF* tcDistributor = ObjectManager::instance()->get(tcDestination); if (tcDistributor == nullptr) { diff --git a/mission/tmtc/CcsdsIpCoreHandler.h b/mission/tmtc/CcsdsIpCoreHandler.h index 627f357d..8d203081 100644 --- a/mission/tmtc/CcsdsIpCoreHandler.h +++ b/mission/tmtc/CcsdsIpCoreHandler.h @@ -153,7 +153,7 @@ class CcsdsIpCoreHandler : public SystemObject, PtmeConfig& ptmeConfig; PtmeGpios ptmeGpios; // BAT priority bit on by default to enable priority selection mode for the PTME. - uint8_t batPriorityParam = 1; + uint8_t batPriorityParam = 0; bool updateBatPriorityOnTxOff = false; GpioIF* gpioIF = nullptr; diff --git a/mission/tmtc/PersistentLogTmStoreTask.cpp b/mission/tmtc/PersistentLogTmStoreTask.cpp index 06256d73..eea1e335 100644 --- a/mission/tmtc/PersistentLogTmStoreTask.cpp +++ b/mission/tmtc/PersistentLogTmStoreTask.cpp @@ -34,8 +34,11 @@ ReturnValue_t PersistentLogTmStoreTask::performOperation(uint8_t opCode) { if (not someonesBusy) { TaskFactory::delayTask(40); } else if (someFileWasSwapped and graceDelayDuringDumping.hasTimedOut()) { - TaskFactory::delayTask(2); - graceDelayDuringDumping.resetTimer(); + if (someFileWasSwapped) { + TaskFactory::delayTask(1); + } + // TaskFactory::delayTask(2); + // graceDelayDuringDumping.resetTimer(); } } } diff --git a/mission/tmtc/PersistentSingleTmStoreTask.cpp b/mission/tmtc/PersistentSingleTmStoreTask.cpp index af394672..ecf071f9 100644 --- a/mission/tmtc/PersistentSingleTmStoreTask.cpp +++ b/mission/tmtc/PersistentSingleTmStoreTask.cpp @@ -19,10 +19,13 @@ ReturnValue_t PersistentSingleTmStoreTask::performOperation(uint8_t opCode) { if (not busy) { TaskFactory::delayTask(40); } else { - if (fileHasSwapped and graceDelayDuringDumping.hasTimedOut()) { - TaskFactory::delayTask(2); - graceDelayDuringDumping.resetTimer(); + if (fileHasSwapped) { + TaskFactory::delayTask(1); } + // if (fileHasSwapped and graceDelayDuringDumping.hasTimedOut()) { + // TaskFactory::delayTask(2); + // graceDelayDuringDumping.resetTimer(); + // } } } } diff --git a/mission/tmtc/PersistentTmStore.cpp b/mission/tmtc/PersistentTmStore.cpp index 4b6ebbdc..5e17cfa1 100644 --- a/mission/tmtc/PersistentTmStore.cpp +++ b/mission/tmtc/PersistentTmStore.cpp @@ -216,7 +216,7 @@ ReturnValue_t PersistentTmStore::loadNextDumpFile() { sif::error << "PersistentTmStore: Could not retrieve file size: " << e.message() << std::endl; continue; } - //sif::debug << "Path: " << dumpParams.dirEntry.path() << std::endl; + // sif::debug << "Path: " << dumpParams.dirEntry.path() << std::endl; // Can't even read CCSDS header. if (dumpParams.fileSize <= 6) { diff --git a/mission/tmtc/TmStoreTaskBase.cpp b/mission/tmtc/TmStoreTaskBase.cpp index 50ec63e4..7728501d 100644 --- a/mission/tmtc/TmStoreTaskBase.cpp +++ b/mission/tmtc/TmStoreTaskBase.cpp @@ -25,27 +25,27 @@ bool TmStoreTaskBase::handleOneStore(PersistentTmStoreWithTmQueue& store, // Dump TMs when applicable if (store.getState() == PersistentTmStore::State::DUMPING) { size_t dumpedLen = 0; - // if (not channel.isBusy()) { - tmSinkBusyCd.resetTimer(); - result = store.dumpNextPacket(channel, dumpedLen, fileHasSwapped); - if (result == DirectTmSinkIF::IS_BUSY) { - sif::warning << "PersistentTmStore: PAPB was too busy for dump" << std::endl; + if (not channel.isBusy()) { + tmSinkBusyCd.resetTimer(); + result = store.dumpNextPacket(channel, dumpedLen, fileHasSwapped); + if (result == DirectTmSinkIF::IS_BUSY) { + sif::warning << "PersistentTmStore: PAPB was too busy for dump" << std::endl; + } + if ((result == PersistentTmStore::DUMP_DONE or result == returnvalue::OK) and dumpedLen > 0) { + dumpContext.dumpedBytes += dumpedLen; + dumpContext.numberOfDumpedPackets += 1; + } + if (result == PersistentTmStore::DUMP_DONE) { + uint32_t startTime; + uint32_t endTime; + store.getStartAndEndTimeCurrentOrLastDump(startTime, endTime); + triggerEvent(dumpContext.eventIfDone, dumpContext.numberOfDumpedPackets, + dumpContext.dumpedBytes); + dumpsPerformed = true; + } else if (result == returnvalue::OK) { + dumpsPerformed = true; + } } - if ((result == PersistentTmStore::DUMP_DONE or result == returnvalue::OK) and dumpedLen > 0) { - dumpContext.dumpedBytes += dumpedLen; - dumpContext.numberOfDumpedPackets += 1; - } - if (result == PersistentTmStore::DUMP_DONE) { - uint32_t startTime; - uint32_t endTime; - store.getStartAndEndTimeCurrentOrLastDump(startTime, endTime); - triggerEvent(dumpContext.eventIfDone, dumpContext.numberOfDumpedPackets, - dumpContext.dumpedBytes); - dumpsPerformed = true; - } else if (result == returnvalue::OK) { - dumpsPerformed = true; - } - //} if (cancelDumpCd.hasTimedOut() or tmSinkBusyCd.hasTimedOut()) { triggerEvent(persTmStore::DUMP_WAS_CANCELLED, store.getObjectId()); store.cancelDump(); -- 2.43.0 From 45054cc863c96ab761a7486df73ae3e6d3f58d97 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 23 Mar 2023 18:31:47 +0100 Subject: [PATCH 13/22] scaling up --- bsp_q7s/core/scheduling.cpp | 6 ++-- fsfw | 2 +- linux/ipcore/PapbVcInterface.cpp | 34 +++++++++++--------- linux/ipcore/PapbVcInterface.h | 4 ++- linux/ipcore/Ptme.cpp | 12 +++++-- linux/ipcore/Ptme.h | 1 + linux/ipcore/PtmeIF.h | 1 + linux/ipcore/VirtualChannelIF.h | 1 + mission/tmtc/CcsdsIpCoreHandler.cpp | 2 ++ mission/tmtc/PersistentLogTmStoreTask.cpp | 6 ++-- mission/tmtc/PersistentSingleTmStoreTask.cpp | 4 +-- mission/tmtc/PersistentTmStore.cpp | 2 +- mission/tmtc/TmStoreTaskBase.cpp | 9 +++++- mission/tmtc/TmStoreTaskBase.h | 1 + mission/tmtc/VirtualChannel.cpp | 10 +++++- mission/tmtc/VirtualChannel.h | 1 + 16 files changed, 65 insertions(+), 31 deletions(-) diff --git a/bsp_q7s/core/scheduling.cpp b/bsp_q7s/core/scheduling.cpp index 491a8bd1..d1065d4c 100644 --- a/bsp_q7s/core/scheduling.cpp +++ b/bsp_q7s/core/scheduling.cpp @@ -186,19 +186,19 @@ void scheduling::initTasks() { scheduling::printAddObjectError("LIVE_TM", objects::LIVE_TM_TASK); } PeriodicTaskIF* logTmTask = factory->createPeriodicTask( - "LOG_PSTORE", 15, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr); + "LOG_PSTORE", 120, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr); result = logTmTask->addComponent(objects::LOG_STORE_AND_TM_TASK); if (result != returnvalue::OK) { scheduling::printAddObjectError("LOG_STORE_AND_TM", objects::LOG_STORE_AND_TM_TASK); } PeriodicTaskIF* hkTmTask = factory->createPeriodicTask( - "HK_PSTORE", 15, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr); + "HK_PSTORE", 120, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr); result = hkTmTask->addComponent(objects::HK_STORE_AND_TM_TASK); if (result != returnvalue::OK) { scheduling::printAddObjectError("HK_STORE_AND_TM", objects::HK_STORE_AND_TM_TASK); } PeriodicTaskIF* cfdpTmTask = factory->createPeriodicTask( - "CFDP_PSTORE", 15, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr); + "CFDP_PSTORE", 120, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr); result = cfdpTmTask->addComponent(objects::CFDP_STORE_AND_TM_TASK); if (result != returnvalue::OK) { scheduling::printAddObjectError("CFDP_STORE_AND_TM", objects::CFDP_STORE_AND_TM_TASK); diff --git a/fsfw b/fsfw index 33ac3950..db4587bb 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit 33ac395072f0145b6e80e12deae978a5e0432f08 +Subproject commit db4587bb59603bdc83e6720193fd1782649a0678 diff --git a/linux/ipcore/PapbVcInterface.cpp b/linux/ipcore/PapbVcInterface.cpp index cb563a65..8c98df90 100644 --- a/linux/ipcore/PapbVcInterface.cpp +++ b/linux/ipcore/PapbVcInterface.cpp @@ -26,19 +26,24 @@ ReturnValue_t PapbVcInterface::initialize() { } ReturnValue_t PapbVcInterface::write(const uint8_t* data, size_t size) { - if (pollPapbBusySignal() == returnvalue::OK) { + if (pollPapbBusySignal(0, 0) == returnvalue::OK) { startPacketTransfer(); + } else { + return DirectTmSinkIF::IS_BUSY; } for (size_t idx = 0; idx < size; idx++) { - if (pollPapbBusySignal() == returnvalue::OK) { + if (pollPapbBusySignal(10, 10) == returnvalue::OK) { *(vcBaseReg + DATA_REG_OFFSET) = static_cast(data[idx]); } else { abortPacketTransfer(); - return DirectTmSinkIF::IS_BUSY; + return returnvalue::FAILED; } } - if (pollPapbBusySignal() == returnvalue::OK) { + if (pollPapbBusySignal(10, 10) == returnvalue::OK) { completePacketTransfer(); + } else { + abortPacketTransfer(); + return returnvalue::FAILED; } return returnvalue::OK; } @@ -47,11 +52,11 @@ void PapbVcInterface::startPacketTransfer() { *vcBaseReg = CONFIG_START; } void PapbVcInterface::completePacketTransfer() { *vcBaseReg = CONFIG_END; } -ReturnValue_t PapbVcInterface::pollPapbBusySignal() const { +ReturnValue_t PapbVcInterface::pollPapbBusySignal(uint32_t maxPollRetries, + uint32_t retryDelayUs) const { gpio::Levels papbBusyState = gpio::Levels::LOW; ReturnValue_t result; uint32_t busyIdx = 0; - uint32_t delayCount = 0; while (true) { /** Check if PAPB interface is ready to receive data */ @@ -64,16 +69,13 @@ ReturnValue_t PapbVcInterface::pollPapbBusySignal() const { if (papbBusyState == gpio::Levels::HIGH) { return returnvalue::OK; } - if (busyIdx == 3) { - usleep(100); - busyIdx = 0; - delayCount += 1; - continue; - } - if (delayCount == 1000) { + + busyIdx++; + if (busyIdx >= maxPollRetries) { return PAPB_BUSY; } - busyIdx++; + + usleep(retryDelayUs); } return returnvalue::OK; } @@ -98,7 +100,9 @@ void PapbVcInterface::isVcInterfaceBufferEmpty() { return; } -bool PapbVcInterface::isBusy() const { return pollPapbBusySignal() == PAPB_BUSY; } +bool PapbVcInterface::isBusy() const { return pollPapbBusySignal(0, 0) == PAPB_BUSY; } + +void PapbVcInterface::cancelTransfer() { abortPacketTransfer(); } ReturnValue_t PapbVcInterface::sendTestFrame() { /** Size of one complete transfer frame data field amounts to 1105 bytes */ diff --git a/linux/ipcore/PapbVcInterface.h b/linux/ipcore/PapbVcInterface.h index b517962c..7491398c 100644 --- a/linux/ipcore/PapbVcInterface.h +++ b/linux/ipcore/PapbVcInterface.h @@ -41,6 +41,8 @@ class PapbVcInterface : public VirtualChannelIF { */ ReturnValue_t write(const uint8_t* data, size_t size) override; + void cancelTransfer() override; + ReturnValue_t initialize() override; private: @@ -109,7 +111,7 @@ class PapbVcInterface : public VirtualChannelIF { * * @return returnvalue::OK when ready to receive data else PAPB_BUSY. */ - ReturnValue_t pollPapbBusySignal() const; + ReturnValue_t pollPapbBusySignal(uint32_t maxPollRetries, uint32_t retryDelayUs) const; /** * @brief This function can be used for debugging to check whether there are packets in diff --git a/linux/ipcore/Ptme.cpp b/linux/ipcore/Ptme.cpp index 69d772ff..f33c8725 100644 --- a/linux/ipcore/Ptme.cpp +++ b/linux/ipcore/Ptme.cpp @@ -20,7 +20,6 @@ ReturnValue_t Ptme::initialize() { } ReturnValue_t Ptme::writeToVc(uint8_t vcId, const uint8_t* data, size_t size) { - ReturnValue_t result = returnvalue::OK; VcInterfaceMapIter vcInterfaceMapIter = vcInterfaceMap.find(vcId); if (vcInterfaceMapIter == vcInterfaceMap.end()) { sif::warning << "Ptme::writeToVc: No virtual channel interface found for the virtual " @@ -28,8 +27,7 @@ ReturnValue_t Ptme::writeToVc(uint8_t vcId, const uint8_t* data, size_t size) { << static_cast(vcId) << std::endl; return UNKNOWN_VC_ID; } - result = vcInterfaceMapIter->second->write(data, size); - return result; + return vcInterfaceMapIter->second->write(data, size); } void Ptme::addVcInterface(VcId_t vcId, VirtualChannelIF* vc) { @@ -62,3 +60,11 @@ bool Ptme::isBusy(uint8_t vcId) const { } return vcInterfaceMapIter->second->isBusy(); } + +void Ptme::cancelTransfer(uint8_t vcId) { + VcInterfaceMapIter vcInterfaceMapIter = vcInterfaceMap.find(vcId); + if (vcInterfaceMapIter == vcInterfaceMap.end()) { + return; + } + return vcInterfaceMapIter->second->cancelTransfer(); +} diff --git a/linux/ipcore/Ptme.h b/linux/ipcore/Ptme.h index 3c076085..2607fc90 100644 --- a/linux/ipcore/Ptme.h +++ b/linux/ipcore/Ptme.h @@ -36,6 +36,7 @@ class Ptme : public PtmeIF, public SystemObject { 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; /** * @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 06b1cbe7..38804484 100644 --- a/linux/ipcore/PtmeIF.h +++ b/linux/ipcore/PtmeIF.h @@ -23,6 +23,7 @@ class PtmeIF { */ 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; }; #endif /* LINUX_OBC_PTMEIF_H_ */ diff --git a/linux/ipcore/VirtualChannelIF.h b/linux/ipcore/VirtualChannelIF.h index 266a56c3..a8a60a06 100644 --- a/linux/ipcore/VirtualChannelIF.h +++ b/linux/ipcore/VirtualChannelIF.h @@ -18,6 +18,7 @@ class VirtualChannelIF : public DirectTmSinkIF { virtual ~VirtualChannelIF(){}; virtual ReturnValue_t initialize() = 0; + virtual void cancelTransfer() = 0; }; #endif /* LINUX_OBC_VCINTERFACEIF_H_ */ diff --git a/mission/tmtc/CcsdsIpCoreHandler.cpp b/mission/tmtc/CcsdsIpCoreHandler.cpp index 39f17487..1cb3e894 100644 --- a/mission/tmtc/CcsdsIpCoreHandler.cpp +++ b/mission/tmtc/CcsdsIpCoreHandler.cpp @@ -206,6 +206,8 @@ ReturnValue_t CcsdsIpCoreHandler::executeAction(ActionId_t actionId, MessageQueu void CcsdsIpCoreHandler::updateLinkState() { linkState = LINK_UP; } void CcsdsIpCoreHandler::enableTransmit() { + // Reset PTME on each transmit enable. + updateBatPriorityFromParam(); #ifndef TE0720_1CFA gpioIF->pullHigh(ptmeGpios.enableTxClock); gpioIF->pullHigh(ptmeGpios.enableTxData); diff --git a/mission/tmtc/PersistentLogTmStoreTask.cpp b/mission/tmtc/PersistentLogTmStoreTask.cpp index eea1e335..ccabb16d 100644 --- a/mission/tmtc/PersistentLogTmStoreTask.cpp +++ b/mission/tmtc/PersistentLogTmStoreTask.cpp @@ -32,10 +32,10 @@ ReturnValue_t PersistentLogTmStoreTask::performOperation(uint8_t opCode) { stateHandlingForStore(handleOneStore(stores.notOkStore, notOkStoreContext)); stateHandlingForStore(handleOneStore(stores.miscStore, miscStoreContext)); if (not someonesBusy) { - TaskFactory::delayTask(40); - } else if (someFileWasSwapped and graceDelayDuringDumping.hasTimedOut()) { + TaskFactory::delayTask(100); + } else /* and graceDelayDuringDumping.hasTimedOut()*/ { if (someFileWasSwapped) { - TaskFactory::delayTask(1); + TaskFactory::delayTask(20); } // TaskFactory::delayTask(2); // graceDelayDuringDumping.resetTimer(); diff --git a/mission/tmtc/PersistentSingleTmStoreTask.cpp b/mission/tmtc/PersistentSingleTmStoreTask.cpp index ecf071f9..a814694e 100644 --- a/mission/tmtc/PersistentSingleTmStoreTask.cpp +++ b/mission/tmtc/PersistentSingleTmStoreTask.cpp @@ -17,10 +17,10 @@ ReturnValue_t PersistentSingleTmStoreTask::performOperation(uint8_t opCode) { } bool busy = handleOneStore(storeWithQueue, dumpContext); if (not busy) { - TaskFactory::delayTask(40); + TaskFactory::delayTask(100); } else { if (fileHasSwapped) { - TaskFactory::delayTask(1); + TaskFactory::delayTask(20); } // if (fileHasSwapped and graceDelayDuringDumping.hasTimedOut()) { // TaskFactory::delayTask(2); diff --git a/mission/tmtc/PersistentTmStore.cpp b/mission/tmtc/PersistentTmStore.cpp index 5e17cfa1..09d405c0 100644 --- a/mission/tmtc/PersistentTmStore.cpp +++ b/mission/tmtc/PersistentTmStore.cpp @@ -218,7 +218,7 @@ ReturnValue_t PersistentTmStore::loadNextDumpFile() { } // sif::debug << "Path: " << dumpParams.dirEntry.path() << std::endl; - // Can't even read CCSDS header. + // File empty or can't even read CCSDS header. if (dumpParams.fileSize <= 6) { continue; } diff --git a/mission/tmtc/TmStoreTaskBase.cpp b/mission/tmtc/TmStoreTaskBase.cpp index 7728501d..eefe9dc6 100644 --- a/mission/tmtc/TmStoreTaskBase.cpp +++ b/mission/tmtc/TmStoreTaskBase.cpp @@ -29,7 +29,7 @@ bool TmStoreTaskBase::handleOneStore(PersistentTmStoreWithTmQueue& store, tmSinkBusyCd.resetTimer(); result = store.dumpNextPacket(channel, dumpedLen, fileHasSwapped); if (result == DirectTmSinkIF::IS_BUSY) { - sif::warning << "PersistentTmStore: PAPB was too busy for dump" << std::endl; + sif::warning << "Unexpected PAPB busy" << std::endl; } if ((result == PersistentTmStore::DUMP_DONE or result == returnvalue::OK) and dumpedLen > 0) { dumpContext.dumpedBytes += dumpedLen; @@ -45,6 +45,13 @@ bool TmStoreTaskBase::handleOneStore(PersistentTmStoreWithTmQueue& store, } else if (result == returnvalue::OK) { dumpsPerformed = true; } + } else { + dumpContext.ptmeBusyCounter++; + if (dumpContext.ptmeBusyCounter == 50) { + sif::warning << "PTME busy for longer period. Dumped length so far: " + << dumpContext.dumpedBytes << std::endl; + dumpContext.ptmeBusyCounter = 0; + } } if (cancelDumpCd.hasTimedOut() or tmSinkBusyCd.hasTimedOut()) { triggerEvent(persTmStore::DUMP_WAS_CANCELLED, store.getObjectId()); diff --git a/mission/tmtc/TmStoreTaskBase.h b/mission/tmtc/TmStoreTaskBase.h index 1f0834d6..aa0efbb4 100644 --- a/mission/tmtc/TmStoreTaskBase.h +++ b/mission/tmtc/TmStoreTaskBase.h @@ -16,6 +16,7 @@ class TmStoreTaskBase : public SystemObject { const Event eventIfDone; uint32_t numberOfDumpedPackets = 0; uint32_t dumpedBytes = 0; + uint32_t ptmeBusyCounter = 0; }; TmStoreTaskBase(object_id_t objectId, StorageManagerIF& ipcStore, VirtualChannel& channel, diff --git a/mission/tmtc/VirtualChannel.cpp b/mission/tmtc/VirtualChannel.cpp index da6ce13f..4fed30b1 100644 --- a/mission/tmtc/VirtualChannel.cpp +++ b/mission/tmtc/VirtualChannel.cpp @@ -25,4 +25,12 @@ uint8_t VirtualChannel::getVcid() const { return vcId; } const char* VirtualChannel::getName() const { return vcName.c_str(); } -bool VirtualChannel::isBusy() const { return ptme.isBusy(vcId); } +bool VirtualChannel::isBusy() const { + // Data is discarded, so channel is not busy. + if (linkStateProvider.load()) { + return false; + } + return ptme.isBusy(vcId); +} + +void VirtualChannel::cancelTransfer() { ptme.cancelTransfer(vcId); } diff --git a/mission/tmtc/VirtualChannel.h b/mission/tmtc/VirtualChannel.h index 983fa448..4cad3305 100644 --- a/mission/tmtc/VirtualChannel.h +++ b/mission/tmtc/VirtualChannel.h @@ -28,6 +28,7 @@ class VirtualChannel : public SystemObject, public VirtualChannelIF { ReturnValue_t sendNextTm(const uint8_t* data, size_t size); bool isBusy() const override; ReturnValue_t write(const uint8_t* data, size_t size) override; + void cancelTransfer() override; uint8_t getVcid() const; const char* getName() const; -- 2.43.0 From 0bced7eca5c137339d9def31b9d4514bbbd0b1e8 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 23 Mar 2023 18:44:12 +0100 Subject: [PATCH 14/22] bump fsfw --- fsfw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fsfw b/fsfw index db4587bb..7ed75ea8 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit db4587bb59603bdc83e6720193fd1782649a0678 +Subproject commit 7ed75ea87b81ac071c1e2ec0f16633487b8300fd -- 2.43.0 From cc4ef09e9f03203ac18d907fa83b8bb2b2be225b Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 23 Mar 2023 19:12:57 +0100 Subject: [PATCH 15/22] i think this is a bug --- mission/tmtc/PersistentTmStore.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/mission/tmtc/PersistentTmStore.cpp b/mission/tmtc/PersistentTmStore.cpp index 09d405c0..bdc893ec 100644 --- a/mission/tmtc/PersistentTmStore.cpp +++ b/mission/tmtc/PersistentTmStore.cpp @@ -195,10 +195,6 @@ ReturnValue_t PersistentTmStore::startDumpFromUpTo(uint32_t fromUnixSeconds, dumpParams.fromUnixTime = fromUnixSeconds; dumpParams.untilUnixTime = upToUnixSeconds; state = State::DUMPING; - if (loadNextDumpFile() == DUMP_DONE) { - // State will be set inside the function loading the next file. - return DUMP_DONE; - } return returnvalue::OK; } @@ -216,7 +212,7 @@ ReturnValue_t PersistentTmStore::loadNextDumpFile() { sif::error << "PersistentTmStore: Could not retrieve file size: " << e.message() << std::endl; continue; } - // sif::debug << "Path: " << dumpParams.dirEntry.path() << std::endl; + sif::debug << "Path: " << dumpParams.dirEntry.path() << std::endl; // File empty or can't even read CCSDS header. if (dumpParams.fileSize <= 6) { -- 2.43.0 From fd61a3f2431e869c615a96aa59eca875af80540c Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 23 Mar 2023 19:22:14 +0100 Subject: [PATCH 16/22] we still need the first file load --- mission/tmtc/PersistentTmStore.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mission/tmtc/PersistentTmStore.cpp b/mission/tmtc/PersistentTmStore.cpp index bdc893ec..8905aff4 100644 --- a/mission/tmtc/PersistentTmStore.cpp +++ b/mission/tmtc/PersistentTmStore.cpp @@ -195,7 +195,7 @@ ReturnValue_t PersistentTmStore::startDumpFromUpTo(uint32_t fromUnixSeconds, dumpParams.fromUnixTime = fromUnixSeconds; dumpParams.untilUnixTime = upToUnixSeconds; state = State::DUMPING; - return returnvalue::OK; + return loadNextDumpFile(); } ReturnValue_t PersistentTmStore::loadNextDumpFile() { -- 2.43.0 From 175c0f9961084e291b8465094e8b0fb42caf77d8 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 23 Mar 2023 20:56:06 +0100 Subject: [PATCH 17/22] and another bug --- mission/tmtc/PersistentTmStore.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/mission/tmtc/PersistentTmStore.cpp b/mission/tmtc/PersistentTmStore.cpp index 8905aff4..6cbcac86 100644 --- a/mission/tmtc/PersistentTmStore.cpp +++ b/mission/tmtc/PersistentTmStore.cpp @@ -243,14 +243,12 @@ ReturnValue_t PersistentTmStore::loadNextDumpFile() { static_cast(dumpParams.fileSize)); // Increment iterator for next cycle. dumpParams.dirIter++; - break; + return returnvalue::OK; } } - if (dumpParams.dirIter == directory_iterator()) { - state = State::IDLE; - return DUMP_DONE; - } - return returnvalue::OK; + // Directory iterator was consumed and we are done. + state = State::IDLE; + return DUMP_DONE; } ReturnValue_t PersistentTmStore::dumpNextPacket(DirectTmSinkIF& tmSink, size_t& dumpedLen, -- 2.43.0 From d226726a27825ae2df6322bd6a2c828552b971e2 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 24 Mar 2023 11:58:45 +0100 Subject: [PATCH 18/22] this is going to be annyoing --- bsp_q7s/core/scheduling.cpp | 8 +++++--- fsfw | 2 +- linux/devices/startracker/StrComHandler.cpp | 4 +--- linux/scheduling.cpp | 5 +++-- linux/scheduling.h | 5 +++++ 5 files changed, 15 insertions(+), 9 deletions(-) diff --git a/bsp_q7s/core/scheduling.cpp b/bsp_q7s/core/scheduling.cpp index aee99b76..1ef14d41 100644 --- a/bsp_q7s/core/scheduling.cpp +++ b/bsp_q7s/core/scheduling.cpp @@ -68,12 +68,14 @@ void scheduling::initTasks() { #else void (*missedDeadlineFunc)(void) = nullptr; #endif + RR_SCHEDULING.policy = SchedulingPolicy::RR; #if OBSW_ADD_SA_DEPL == 1 // Could add this to the core controller but the core controller does so many thing that I would // prefer to have the solar array deployment in a seprate task. - PeriodicTaskIF* solarArrayDeplTask = factory->createPeriodicTask( - "SOLAR_ARRAY_DEPL", 65, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.4, missedDeadlineFunc); + PeriodicTaskIF* solarArrayDeplTask = + factory->createPeriodicTask("SOLAR_ARRAY_DEPL", 65, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.4, + missedDeadlineFunc, &RR_SCHEDULING); result = solarArrayDeplTask->addComponent(objects::SOLAR_ARRAY_DEPL_HANDLER); if (result != returnvalue::OK) { scheduling::printAddObjectError("SOLAR_ARRAY_DEPL", objects::SOLAR_ARRAY_DEPL_HANDLER); @@ -81,7 +83,7 @@ void scheduling::initTasks() { #endif PeriodicTaskIF* coreCtrlTask = factory->createPeriodicTask( - "CORE_CTRL", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.4, missedDeadlineFunc); + "CORE_CTRL", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.4, missedDeadlineFunc, &RR_SCHEDULING); result = coreCtrlTask->addComponent(objects::CORE_CONTROLLER); if (result != returnvalue::OK) { scheduling::printAddObjectError("CORE_CTRL", objects::CORE_CONTROLLER); diff --git a/fsfw b/fsfw index 7ed75ea8..e704295c 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit 7ed75ea87b81ac071c1e2ec0f16633487b8300fd +Subproject commit e704295cce76048d65bbb8893840b9ecedb05c94 diff --git a/linux/devices/startracker/StrComHandler.cpp b/linux/devices/startracker/StrComHandler.cpp index 85be7871..fb11be27 100644 --- a/linux/devices/startracker/StrComHandler.cpp +++ b/linux/devices/startracker/StrComHandler.cpp @@ -155,9 +155,7 @@ ReturnValue_t StrComHandler::startImageDownload(std::string path) { return returnvalue::OK; } -void StrComHandler::stopProcess() { - terminate = true; -} +void StrComHandler::stopProcess() { terminate = true; } void StrComHandler::setDownloadImageName(std::string filename) { downloadImage.filename = filename; diff --git a/linux/scheduling.cpp b/linux/scheduling.cpp index 85735729..d3b88661 100644 --- a/linux/scheduling.cpp +++ b/linux/scheduling.cpp @@ -18,8 +18,9 @@ void scheduling::scheduleScexReader(TaskFactory& factory, PeriodicTaskIF*& scexR #endif result = returnvalue::OK; - scexReaderTask = factory.createPeriodicTask( - "SCEX_UART_READER", 20, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc); + scexReaderTask = + factory.createPeriodicTask("SCEX_UART_READER", 20, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, + missedDeadlineFunc, &NORMAL_SCHEDULING); result = scexReaderTask->addComponent(objects::SCEX_UART_READER); if (result != returnvalue::OK) { printAddObjectError("SCEX_UART_READER", objects::SCEX_UART_READER); diff --git a/linux/scheduling.h b/linux/scheduling.h index b5ec8ef2..d6c5b1f1 100644 --- a/linux/scheduling.h +++ b/linux/scheduling.h @@ -1,8 +1,13 @@ #pragma once +#include #include namespace scheduling { + +extern PosixThreadArgs RR_SCHEDULING; +extern PosixThreadArgs NORMAL_SCHEDULING; + void scheduleScexDev(PeriodicTaskIF*& scexDevHandler); void scheduleScexReader(TaskFactory& factory, PeriodicTaskIF*& scexReaderTask); void addMpsocSupvHandlers(PeriodicTaskIF* task); -- 2.43.0 From 349332c1e1192760e878ad0737d0a7a7c0bc9f48 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 24 Mar 2023 13:26:27 +0100 Subject: [PATCH 19/22] adapt all priorities --- bsp_q7s/core/scheduling.cpp | 114 +++++++++++++++++++++--------------- fsfw | 2 +- linux/scheduling.cpp | 3 + 3 files changed, 70 insertions(+), 49 deletions(-) diff --git a/bsp_q7s/core/scheduling.cpp b/bsp_q7s/core/scheduling.cpp index 1ef14d41..e17c4daa 100644 --- a/bsp_q7s/core/scheduling.cpp +++ b/bsp_q7s/core/scheduling.cpp @@ -68,7 +68,6 @@ void scheduling::initTasks() { #else void (*missedDeadlineFunc)(void) = nullptr; #endif - RR_SCHEDULING.policy = SchedulingPolicy::RR; #if OBSW_ADD_SA_DEPL == 1 // Could add this to the core controller but the core controller does so many thing that I would @@ -91,7 +90,7 @@ void scheduling::initTasks() { /* TMTC Distribution */ PeriodicTaskIF* tmTcDistributor = factory->createPeriodicTask( - "TC_DIST", 45, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc); + "TC_DIST", 45, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc, &RR_SCHEDULING); #if OBSW_ADD_TCPIP_SERVERS == 1 #if OBSW_ADD_TMTC_UDP_SERVER == 1 result = tmTcDistributor->addComponent(objects::UDP_TMTC_SERVER); @@ -121,16 +120,18 @@ void scheduling::initTasks() { #if OBSW_ADD_TCPIP_SERVERS == 1 #if OBSW_ADD_TMTC_UDP_SERVER == 1 - PeriodicTaskIF* udpPollingTask = factory->createPeriodicTask( - "UDP_TMTC_POLLING", 65, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc); + PeriodicTaskIF* udpPollingTask = + factory->createPeriodicTask("UDP_TMTC_POLLING", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, + missedDeadlineFunc, &RR_SCHEDULING); result = udpPollingTask->addComponent(objects::UDP_TMTC_POLLING_TASK); if (result != returnvalue::OK) { scheduling::printAddObjectError("UDP_POLLING", objects::UDP_TMTC_POLLING_TASK); } #endif #if OBSW_ADD_TMTC_TCP_SERVER == 1 - PeriodicTaskIF* tcpPollingTask = factory->createPeriodicTask( - "TCP_TMTC_POLLING", 65, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc); + PeriodicTaskIF* tcpPollingTask = + factory->createPeriodicTask("TCP_TMTC_POLLING", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, + missedDeadlineFunc, &RR_SCHEDULING); result = tcpPollingTask->addComponent(objects::TCP_TMTC_POLLING_TASK); if (result != returnvalue::OK) { scheduling::printAddObjectError("UDP_POLLING", objects::TCP_TMTC_POLLING_TASK); @@ -138,8 +139,9 @@ void scheduling::initTasks() { #endif #endif - PeriodicTaskIF* genericSysTask = factory->createPeriodicTask( - "SYSTEM_TASK", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.5, missedDeadlineFunc); + PeriodicTaskIF* genericSysTask = + factory->createPeriodicTask("SYSTEM_TASK", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.5, + missedDeadlineFunc, &RR_SCHEDULING); result = genericSysTask->addComponent(objects::EIVE_SYSTEM); if (result != returnvalue::OK) { scheduling::printAddObjectError("EIVE_SYSTEM", objects::EIVE_SYSTEM); @@ -173,7 +175,7 @@ void scheduling::initTasks() { // Runs in IRQ mode, frequency does not really matter PeriodicTaskIF* pdecHandlerTask = factory->createPeriodicTask( - "PDEC_HANDLER", 75, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, missedDeadlineFunc); + "PDEC_HANDLER", 75, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr, &RR_SCHEDULING); result = pdecHandlerTask->addComponent(objects::PDEC_HANDLER); if (result != returnvalue::OK) { scheduling::printAddObjectError("PDEC Handler", objects::PDEC_HANDLER); @@ -181,50 +183,53 @@ void scheduling::initTasks() { #endif /* OBSW_ADD_CCSDS_IP_CORE == 1 */ // All the TM store tasks run in permanent loops, frequency does not matter - PeriodicTaskIF* liveTmTask = - factory->createPeriodicTask("LIVE_TM", 55, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr); + PeriodicTaskIF* liveTmTask = factory->createPeriodicTask( + "LIVE_TM", 55, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr, &RR_SCHEDULING); result = liveTmTask->addComponent(objects::LIVE_TM_TASK); if (result != returnvalue::OK) { scheduling::printAddObjectError("LIVE_TM", objects::LIVE_TM_TASK); } PeriodicTaskIF* logTmTask = factory->createPeriodicTask( - "LOG_PSTORE", 120, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr); + "LOG_PSTORE", -10, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr, &NORMAL_SCHEDULING); result = logTmTask->addComponent(objects::LOG_STORE_AND_TM_TASK); if (result != returnvalue::OK) { scheduling::printAddObjectError("LOG_STORE_AND_TM", objects::LOG_STORE_AND_TM_TASK); } PeriodicTaskIF* hkTmTask = factory->createPeriodicTask( - "HK_PSTORE", 120, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr); + "HK_PSTORE", -10, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr, &NORMAL_SCHEDULING); result = hkTmTask->addComponent(objects::HK_STORE_AND_TM_TASK); if (result != returnvalue::OK) { scheduling::printAddObjectError("HK_STORE_AND_TM", objects::HK_STORE_AND_TM_TASK); } PeriodicTaskIF* cfdpTmTask = factory->createPeriodicTask( - "CFDP_PSTORE", 120, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr); + "CFDP_PSTORE", -5, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr, &NORMAL_SCHEDULING); result = cfdpTmTask->addComponent(objects::CFDP_STORE_AND_TM_TASK); if (result != returnvalue::OK) { scheduling::printAddObjectError("CFDP_STORE_AND_TM", objects::CFDP_STORE_AND_TM_TASK); } #if OBSW_ADD_CFDP_COMPONENTS == 1 - PeriodicTaskIF* cfdpTask = factory->createPeriodicTask( - "CFDP_HANDLER", 45, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.4, missedDeadlineFunc); + PeriodicTaskIF* cfdpTask = + factory->createPeriodicTask("CFDP_HANDLER", 40, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.4, + missedDeadlineFunc, &RR_SCHEDULING); result = cfdpTask->addComponent(objects::CFDP_HANDLER); if (result != returnvalue::OK) { scheduling::printAddObjectError("CFDP Handler", objects::CFDP_HANDLER); } #endif - PeriodicTaskIF* gpsTask = factory->createPeriodicTask( - "GPS_TASK", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2, 0.4, missedDeadlineFunc); + PeriodicTaskIF* gpsTask = + factory->createPeriodicTask("GPS_TASK", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2, 0.4, + missedDeadlineFunc, &RR_SCHEDULING); result = gpsTask->addComponent(objects::GPS_CONTROLLER); if (result != returnvalue::OK) { scheduling::printAddObjectError("GPS_CTRL", objects::GPS_CONTROLLER); } #if OBSW_ADD_ACS_BOARD == 1 - PeriodicTaskIF* acsBrdPolling = factory->createPeriodicTask( - "ACS_BOARD_POLLING", 85, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2, 0.4, missedDeadlineFunc); + PeriodicTaskIF* acsBrdPolling = + factory->createPeriodicTask("ACS_BOARD_POLLING", 85, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2, + 0.4, missedDeadlineFunc, &RR_SCHEDULING); result = acsBrdPolling->addComponent(objects::ACS_BOARD_POLLING_TASK); if (result != returnvalue::OK) { scheduling::printAddObjectError("ACS_BOARD_POLLING", objects::ACS_BOARD_POLLING_TASK); @@ -232,16 +237,18 @@ void scheduling::initTasks() { #endif #if OBSW_ADD_RW == 1 - PeriodicTaskIF* rwPolling = factory->createPeriodicTask( - "RW_POLLING_TASK", 85, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2, 0.4, missedDeadlineFunc); + PeriodicTaskIF* rwPolling = + factory->createPeriodicTask("RW_POLLING_TASK", 85, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2, + 0.4, missedDeadlineFunc, &RR_SCHEDULING); result = rwPolling->addComponent(objects::RW_POLLING_TASK); if (result != returnvalue::OK) { scheduling::printAddObjectError("RW_POLLING_TASK", objects::RW_POLLING_TASK); } #endif #if OBSW_ADD_MGT == 1 - PeriodicTaskIF* imtqPolling = factory->createPeriodicTask( - "IMTQ_POLLING_TASK", 85, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2, 0.4, missedDeadlineFunc); + PeriodicTaskIF* imtqPolling = + factory->createPeriodicTask("IMTQ_POLLING_TASK", 85, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2, + 0.4, missedDeadlineFunc, &RR_SCHEDULING); result = imtqPolling->addComponent(objects::IMTQ_POLLING); if (result != returnvalue::OK) { scheduling::printAddObjectError("IMTQ_POLLING_TASK", objects::IMTQ_POLLING); @@ -249,16 +256,18 @@ void scheduling::initTasks() { #endif #if OBSW_ADD_SUN_SENSORS == 1 - PeriodicTaskIF* susPolling = factory->createPeriodicTask( - "SUS_POLLING_TASK", 85, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2, 0.4, missedDeadlineFunc); + PeriodicTaskIF* susPolling = + factory->createPeriodicTask("SUS_POLLING_TASK", 85, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2, + 0.4, missedDeadlineFunc, &RR_SCHEDULING); result = susPolling->addComponent(objects::SUS_POLLING_TASK); if (result != returnvalue::OK) { scheduling::printAddObjectError("SUS_POLLING_TASK", objects::SUS_POLLING_TASK); } #endif - PeriodicTaskIF* acsSysTask = factory->createPeriodicTask( - "ACS_SYS_TASK", 55, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2, 0.4, missedDeadlineFunc); + PeriodicTaskIF* acsSysTask = + factory->createPeriodicTask("ACS_SYS_TASK", 55, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2, 0.4, + missedDeadlineFunc, &RR_SCHEDULING); result = acsSysTask->addComponent(objects::ACS_SUBSYSTEM); if (result != returnvalue::OK) { scheduling::printAddObjectError("ACS_SUBSYSTEM", objects::ACS_SUBSYSTEM); @@ -285,7 +294,7 @@ void scheduling::initTasks() { } PeriodicTaskIF* tcsSystemTask = factory->createPeriodicTask( - "TCS_TASK", 55, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.5, missedDeadlineFunc); + "TCS_TASK", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.5, missedDeadlineFunc, &RR_SCHEDULING); scheduling::scheduleRtdSensors(tcsSystemTask); result = tcsSystemTask->addComponent(objects::TCS_SUBSYSTEM); if (result != returnvalue::OK) { @@ -310,8 +319,9 @@ void scheduling::initTasks() { #if OBSW_ADD_STAR_TRACKER == 1 // Relatively high priority to make sure STR COM works well. - PeriodicTaskIF* strHelperTask = factory->createPeriodicTask( - "STR_HELPER", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc); + PeriodicTaskIF* strHelperTask = + factory->createPeriodicTask("STR_HELPER", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, + missedDeadlineFunc, &RR_SCHEDULING); result = strHelperTask->addComponent(objects::STR_COM_IF); if (result != returnvalue::OK) { scheduling::printAddObjectError("STR_HELPER", objects::STR_COM_IF); @@ -319,8 +329,9 @@ void scheduling::initTasks() { #endif /* OBSW_ADD_STAR_TRACKER == 1 */ #if OBSW_ADD_PLOC_MPSOC == 1 - PeriodicTaskIF* mpsocHelperTask = factory->createPeriodicTask( - "PLOC_MPSOC_HELPER", 20, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc); + PeriodicTaskIF* mpsocHelperTask = + factory->createPeriodicTask("PLOC_MPSOC_HELPER", 0, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, + missedDeadlineFunc, &NORMAL_SCHEDULING); result = mpsocHelperTask->addComponent(objects::PLOC_MPSOC_HELPER); if (result != returnvalue::OK) { scheduling::printAddObjectError("PLOC_MPSOC_HELPER", objects::PLOC_MPSOC_HELPER); @@ -328,8 +339,9 @@ void scheduling::initTasks() { #endif /* OBSW_ADD_PLOC_MPSOC */ #if OBSW_ADD_PLOC_SUPERVISOR == 1 - PeriodicTaskIF* supvHelperTask = factory->createPeriodicTask( - "PLOC_SUPV_HELPER", 20, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, missedDeadlineFunc); + PeriodicTaskIF* supvHelperTask = + factory->createPeriodicTask("PLOC_SUPV_HELPER", 0, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, + missedDeadlineFunc, &NORMAL_SCHEDULING); result = supvHelperTask->addComponent(objects::PLOC_SUPERVISOR_HELPER); if (result != returnvalue::OK) { scheduling::printAddObjectError("PLOC_SUPV_HELPER", objects::PLOC_SUPERVISOR_HELPER); @@ -337,7 +349,7 @@ void scheduling::initTasks() { #endif /* OBSW_ADD_PLOC_SUPERVISOR */ PeriodicTaskIF* plTask = factory->createPeriodicTask( - "PL_TASK", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.8, missedDeadlineFunc); + "PL_TASK", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.8, missedDeadlineFunc, &RR_SCHEDULING); plTask->addComponent(objects::CAM_SWITCHER); scheduling::addMpsocSupvHandlers(plTask); scheduling::scheduleScexDev(plTask); @@ -458,8 +470,9 @@ void scheduling::createPstTasks(TaskFactory& factory, TaskDeadlineMissedFunction #else static constexpr float acsPstPeriod = 0.4; #endif - FixedTimeslotTaskIF* acsTcsPst = factory.createFixedTimeslotTask( - "ACS_TCS_PST", 80, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2, acsPstPeriod, missedDeadlineFunc); + FixedTimeslotTaskIF* acsTcsPst = + factory.createFixedTimeslotTask("ACS_TCS_PST", 85, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2, + acsPstPeriod, missedDeadlineFunc, &RR_SCHEDULING); result = pst::pstTcsAndAcs(acsTcsPst, cfg); if (result != returnvalue::OK) { if (result == FixedTimeslotTaskIF::SLOT_LIST_EMPTY) { @@ -473,8 +486,9 @@ void scheduling::createPstTasks(TaskFactory& factory, TaskDeadlineMissedFunction /* Polling Sequence Table Default */ #if OBSW_ADD_SPI_TEST_CODE == 0 - FixedTimeslotTaskIF* syrlinksPst = factory.createFixedTimeslotTask( - "SYRLINKS", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 0.5, missedDeadlineFunc); + FixedTimeslotTaskIF* syrlinksPst = + factory.createFixedTimeslotTask("SYRLINKS", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 0.5, + missedDeadlineFunc, &RR_SCHEDULING); result = pst::pstSyrlinks(syrlinksPst); if (result != returnvalue::OK) { if (result == FixedTimeslotTaskIF::SLOT_LIST_EMPTY) { @@ -488,8 +502,9 @@ void scheduling::createPstTasks(TaskFactory& factory, TaskDeadlineMissedFunction #endif #if OBSW_ADD_I2C_TEST_CODE == 0 - FixedTimeslotTaskIF* i2cPst = factory.createFixedTimeslotTask( - "I2C_PS_PST", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 0.4, missedDeadlineFunc); + FixedTimeslotTaskIF* i2cPst = + factory.createFixedTimeslotTask("I2C_PS_PST", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 0.6, + missedDeadlineFunc, &RR_SCHEDULING); result = pst::pstI2cProcessingSystem(i2cPst); if (result != returnvalue::OK) { if (result == FixedTimeslotTaskIF::SLOT_LIST_EMPTY) { @@ -502,8 +517,9 @@ void scheduling::createPstTasks(TaskFactory& factory, TaskDeadlineMissedFunction } #endif - FixedTimeslotTaskIF* gomSpacePstTask = factory.createFixedTimeslotTask( - "GS_PST_TASK", 65, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 0.5, missedDeadlineFunc); + FixedTimeslotTaskIF* gomSpacePstTask = + factory.createFixedTimeslotTask("GS_PST_TASK", 65, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, + 0.5, missedDeadlineFunc, &RR_SCHEDULING); result = pst::pstGompaceCan(gomSpacePstTask); if (result != returnvalue::OK) { if (result != FixedTimeslotTaskIF::SLOT_LIST_EMPTY) { @@ -517,8 +533,9 @@ void scheduling::createPusTasks(TaskFactory& factory, TaskDeadlineMissedFunction std::vector& taskVec) { ReturnValue_t result = returnvalue::OK; /* PUS Services */ - PeriodicTaskIF* pusHighPrio = factory.createPeriodicTask( - "PUS_HIGH_PRIO", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc); + PeriodicTaskIF* pusHighPrio = + factory.createPeriodicTask("PUS_HIGH_PRIO", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, + missedDeadlineFunc, &RR_SCHEDULING); result = pusHighPrio->addComponent(objects::PUS_SERVICE_1_VERIFICATION); if (result != returnvalue::OK) { scheduling::printAddObjectError("PUS_VERIF", objects::PUS_SERVICE_1_VERIFICATION); @@ -537,8 +554,9 @@ void scheduling::createPusTasks(TaskFactory& factory, TaskDeadlineMissedFunction } taskVec.push_back(pusHighPrio); - PeriodicTaskIF* pusMedPrio = factory.createPeriodicTask( - "PUS_MED_PRIO", 45, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.8, missedDeadlineFunc); + PeriodicTaskIF* pusMedPrio = + factory.createPeriodicTask("PUS_MED_PRIO", 45, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.8, + missedDeadlineFunc, &RR_SCHEDULING); result = pusMedPrio->addComponent(objects::PUS_SERVICE_3_HOUSEKEEPING); if (result != returnvalue::OK) { scheduling::printAddObjectError("PUS_3", objects::PUS_SERVICE_3_HOUSEKEEPING); diff --git a/fsfw b/fsfw index e704295c..4415dc24 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit e704295cce76048d65bbb8893840b9ecedb05c94 +Subproject commit 4415dc24e1bee0252e5282b583fcade7f37a97bf diff --git a/linux/scheduling.cpp b/linux/scheduling.cpp index d3b88661..d1b7853f 100644 --- a/linux/scheduling.cpp +++ b/linux/scheduling.cpp @@ -8,6 +8,9 @@ #include "ObjectFactory.h" #include "eive/objects.h" +PosixThreadArgs scheduling::RR_SCHEDULING = {.policy = SchedulingPolicy::RR}; +PosixThreadArgs scheduling::NORMAL_SCHEDULING; + void scheduling::scheduleScexReader(TaskFactory& factory, PeriodicTaskIF*& scexReaderTask) { using namespace scheduling; ReturnValue_t result = returnvalue::OK; -- 2.43.0 From 91b83d477b5a47eadfc6d79123337089c7b61f8c Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 24 Mar 2023 13:28:27 +0100 Subject: [PATCH 20/22] changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cdcf7bc3..06e949fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,8 @@ will consitute of a breaking change warranting a new major release: ## Changed +- Rework FSFW OSALs to properly support regular scheduling (NICE priorities) and real-time + scheduling. - STR: Move datalink layer to `StrComHandler` completely. DLL is now completely hidden from device handler. - STR: Is now scheduled twice in ACS PST. -- 2.43.0 From 012e17348705c1d54775c7249f325e9b35bf8721 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 24 Mar 2023 14:11:08 +0100 Subject: [PATCH 21/22] okay this should work --- bsp_q7s/core/scheduling.cpp | 10 +++++----- fsfw | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/bsp_q7s/core/scheduling.cpp b/bsp_q7s/core/scheduling.cpp index e17c4daa..0978f842 100644 --- a/bsp_q7s/core/scheduling.cpp +++ b/bsp_q7s/core/scheduling.cpp @@ -190,19 +190,19 @@ void scheduling::initTasks() { scheduling::printAddObjectError("LIVE_TM", objects::LIVE_TM_TASK); } PeriodicTaskIF* logTmTask = factory->createPeriodicTask( - "LOG_PSTORE", -10, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr, &NORMAL_SCHEDULING); + "LOG_PSTORE", 0, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr); result = logTmTask->addComponent(objects::LOG_STORE_AND_TM_TASK); if (result != returnvalue::OK) { scheduling::printAddObjectError("LOG_STORE_AND_TM", objects::LOG_STORE_AND_TM_TASK); } PeriodicTaskIF* hkTmTask = factory->createPeriodicTask( - "HK_PSTORE", -10, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr, &NORMAL_SCHEDULING); + "HK_PSTORE", 0, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr); result = hkTmTask->addComponent(objects::HK_STORE_AND_TM_TASK); if (result != returnvalue::OK) { scheduling::printAddObjectError("HK_STORE_AND_TM", objects::HK_STORE_AND_TM_TASK); } PeriodicTaskIF* cfdpTmTask = factory->createPeriodicTask( - "CFDP_PSTORE", -5, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr, &NORMAL_SCHEDULING); + "CFDP_PSTORE", 0, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, nullptr); result = cfdpTmTask->addComponent(objects::CFDP_STORE_AND_TM_TASK); if (result != returnvalue::OK) { scheduling::printAddObjectError("CFDP_STORE_AND_TM", objects::CFDP_STORE_AND_TM_TASK); @@ -331,7 +331,7 @@ void scheduling::initTasks() { #if OBSW_ADD_PLOC_MPSOC == 1 PeriodicTaskIF* mpsocHelperTask = factory->createPeriodicTask("PLOC_MPSOC_HELPER", 0, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, - missedDeadlineFunc, &NORMAL_SCHEDULING); + missedDeadlineFunc); result = mpsocHelperTask->addComponent(objects::PLOC_MPSOC_HELPER); if (result != returnvalue::OK) { scheduling::printAddObjectError("PLOC_MPSOC_HELPER", objects::PLOC_MPSOC_HELPER); @@ -341,7 +341,7 @@ void scheduling::initTasks() { #if OBSW_ADD_PLOC_SUPERVISOR == 1 PeriodicTaskIF* supvHelperTask = factory->createPeriodicTask("PLOC_SUPV_HELPER", 0, PeriodicTaskIF::MINIMUM_STACK_SIZE, 1.0, - missedDeadlineFunc, &NORMAL_SCHEDULING); + missedDeadlineFunc); result = supvHelperTask->addComponent(objects::PLOC_SUPERVISOR_HELPER); if (result != returnvalue::OK) { scheduling::printAddObjectError("PLOC_SUPV_HELPER", objects::PLOC_SUPERVISOR_HELPER); diff --git a/fsfw b/fsfw index 4415dc24..a937b457 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit 4415dc24e1bee0252e5282b583fcade7f37a97bf +Subproject commit a937b457f900a6a6b26bc0b42a5357f014840a67 -- 2.43.0 From 267f9005459f197c853df859ad4af72bbf613895 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 24 Mar 2023 14:15:01 +0100 Subject: [PATCH 22/22] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 06e949fb..e328052f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ will consitute of a breaking change warranting a new major release: - Rework FSFW OSALs to properly support regular scheduling (NICE priorities) and real-time scheduling. +- Tweak scheduling priorities. - STR: Move datalink layer to `StrComHandler` completely. DLL is now completely hidden from device handler. - STR: Is now scheduled twice in ACS PST. -- 2.43.0