diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ab39c23..7c22cb43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,14 @@ will consitute of a breaking change warranting a new major release: # [unreleased] +## Changed + +- Refactored TM pipeline to optimize usage of the PTME and communication downlink bandwidth. + This was done by moving the dumping of TMs to the VCs into separate threads with permanent loops. + These threads are then able to process high TM loads on demand. The PUS TM funnel will route + PUS packets to the approrpiate persisten TM stores and then demultiplex the TM to all registered + TM destinations are before. + # [v1.36.0] 2023-03-08 eive-tmtc: v2.17.2 diff --git a/bsp_q7s/core/ObjectFactory.cpp b/bsp_q7s/core/ObjectFactory.cpp index 62aecde4..a3045e62 100644 --- a/bsp_q7s/core/ObjectFactory.cpp +++ b/bsp_q7s/core/ObjectFactory.cpp @@ -12,6 +12,9 @@ #include #include #include +#include +#include +#include #include "OBSWConfig.h" #include "bsp_q7s/boardtest/Q7STestTask.h" @@ -716,9 +719,7 @@ void ObjectFactory::createReactionWheelComponents(LinuxLibgpioIF* gpioComIF, #endif /* OBSW_ADD_RW == 1 */ } -ReturnValue_t ObjectFactory::createCcsdsComponents(LinuxLibgpioIF* gpioComIF, - PusTmFunnel& pusFunnel, - CcsdsIpCoreHandler** ipCoreHandler) { +ReturnValue_t ObjectFactory::createCcsdsComponents(CcsdsComponentArgs& args) { using namespace gpio; // GPIO definitions of signals connected to the virtual channel interfaces of the PTME IP Core GpioCookie* gpioCookiePtmeIp = new GpioCookie; @@ -739,20 +740,20 @@ ReturnValue_t ObjectFactory::createCcsdsComponents(LinuxLibgpioIF* gpioComIF, gpioCookiePtmeIp->addGpio(gpioIds::VC3_PAPB_BUSY, gpio); gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_EMPTY_SIGNAL_VC3, "PAPB VC3"); gpioCookiePtmeIp->addGpio(gpioIds::VC3_PAPB_EMPTY, gpio); - gpioChecker(gpioComIF->addGpios(gpioCookiePtmeIp), "PTME PAPB VCs"); + gpioChecker(args.gpioComIF.addGpios(gpioCookiePtmeIp), "PTME PAPB VCs"); // Creating virtual channel interfaces VirtualChannelIF* vc0 = - new PapbVcInterface(gpioComIF, gpioIds::VC0_PAPB_BUSY, gpioIds::VC0_PAPB_EMPTY, q7s::UIO_PTME, - q7s::uiomapids::PTME_VC0); + new PapbVcInterface(&args.gpioComIF, gpioIds::VC0_PAPB_BUSY, gpioIds::VC0_PAPB_EMPTY, + q7s::UIO_PTME, q7s::uiomapids::PTME_VC0); VirtualChannelIF* vc1 = - new PapbVcInterface(gpioComIF, gpioIds::VC1_PAPB_BUSY, gpioIds::VC1_PAPB_EMPTY, q7s::UIO_PTME, - q7s::uiomapids::PTME_VC1); + new PapbVcInterface(&args.gpioComIF, gpioIds::VC1_PAPB_BUSY, gpioIds::VC1_PAPB_EMPTY, + q7s::UIO_PTME, q7s::uiomapids::PTME_VC1); VirtualChannelIF* vc2 = - new PapbVcInterface(gpioComIF, gpioIds::VC2_PAPB_BUSY, gpioIds::VC2_PAPB_EMPTY, q7s::UIO_PTME, - q7s::uiomapids::PTME_VC2); + new PapbVcInterface(&args.gpioComIF, gpioIds::VC2_PAPB_BUSY, gpioIds::VC2_PAPB_EMPTY, + q7s::UIO_PTME, q7s::uiomapids::PTME_VC2); VirtualChannelIF* vc3 = - new PapbVcInterface(gpioComIF, gpioIds::VC3_PAPB_BUSY, gpioIds::VC3_PAPB_EMPTY, q7s::UIO_PTME, - q7s::uiomapids::PTME_VC3); + new PapbVcInterface(&args.gpioComIF, gpioIds::VC3_PAPB_BUSY, gpioIds::VC3_PAPB_EMPTY, + q7s::UIO_PTME, q7s::uiomapids::PTME_VC3); // Creating ptme object and adding virtual channel interfaces Ptme* ptme = new Ptme(objects::PTME); ptme->addVcInterface(ccsds::VC0, vc0); @@ -763,29 +764,33 @@ ReturnValue_t ObjectFactory::createCcsdsComponents(LinuxLibgpioIF* gpioComIF, new AxiPtmeConfig(objects::AXI_PTME_CONFIG, q7s::UIO_PTME, q7s::uiomapids::PTME_CONFIG); PtmeConfig* ptmeConfig = new PtmeConfig(objects::PTME_CONFIG, axiPtmeConfig); - *ipCoreHandler = new CcsdsIpCoreHandler(objects::CCSDS_HANDLER, objects::CCSDS_PACKET_DISTRIBUTOR, - *ptmeConfig, LINK_STATE, gpioComIF, - gpioIds::RS485_EN_TX_CLOCK, gpioIds::RS485_EN_TX_DATA); - VirtualChannel* vc = new VirtualChannel(objects::PTME_VC0_LIVE_TM, ccsds::VC0, "PTME VC0 LIVE TM", - *ptme, LINK_STATE); - //(*ipCoreHandler)->addVirtualChannel(ccsds::VC0, vc); - vc = new VirtualChannel(objects::PTME_VC1_LOG_TM, ccsds::VC1, "PTME VC1 LOG TM", *ptme, - LINK_STATE); + *args.ipCoreHandler = new CcsdsIpCoreHandler( + objects::CCSDS_HANDLER, objects::CCSDS_PACKET_DISTRIBUTOR, *ptmeConfig, LINK_STATE, + &args.gpioComIF, gpioIds::RS485_EN_TX_CLOCK, gpioIds::RS485_EN_TX_DATA); + // This VC will receive all live TM + auto* vcWithQueue = + new VirtualChannelWithQueue(objects::PTME_VC0_LIVE_TM, ccsds::VC0, "PTME VC0 LIVE TM", *ptme, + LINK_STATE, args.tmStore, 500); + new LiveTmTask(objects::LIVE_TM_TASK, *vcWithQueue); + + // Set up log store. + auto* vc = new VirtualChannel(objects::PTME_VC1_LOG_TM, ccsds::VC1, "PTME VC1 LOG TM", *ptme, + LINK_STATE); + LogStores logStores(args.stores); + // Core task which handles the LOG store and takes care of dumping it as TM using a VC directly + new PersistentLogTmStoreTask(objects::LOG_STORE_TASK, args.ipcStore, logStores, *vc); - // pusFunnel.addPersistentTmStoreRouting(filters::okFilter(), vc->getReportReceptionQueue()); - // pusFunnel.addPersistentTmStoreRouting(filters::notOkFilter(), vc->getReportReceptionQueue()); - // pusFunnel.addPersistentTmStoreRouting(filters::miscFilter(), vc->getReportReceptionQueue()); - //(*ipCoreHandler)->addVirtualChannel(ccsds::VC1, vc); vc = new VirtualChannel(objects::PTME_VC2_HK_TM, ccsds::VC2, "PTME VC2 HK TM", *ptme, LINK_STATE); - // auto hkTmStoreTask = new PersistentSingleTmStoreTask(); - // pusFunnel.addPersistentTmStoreRouting(filters::hkFilter(), vc->getReportReceptionQueue()); - //(*ipCoreHandler)->addVirtualChannel(ccsds::VC2, vc); + // Core task which handles the HK store and takes care of dumping it as TM using a VC directly + new PersistentSingleTmStoreTask(objects::HK_STORE_TASK, args.ipcStore, *args.stores.hkStore, *vc); + vc = new VirtualChannel(objects::PTME_VC3_CFDP_TM, ccsds::VC3, "PTME VC3 CFDP TM", *ptme, LINK_STATE); - // TODO: Set VC destination in CFDP funnel. - //(*ipCoreHandler)->addVirtualChannel(ccsds::VC3, vc); + // Core task which handles the CFDP store and takes care of dumping it as TM using a VC directly + new PersistentSingleTmStoreTask(objects::CFDP_STORE_TASK, args.ipcStore, *args.stores.cfdpStore, + *vc); - ReturnValue_t result = (*ipCoreHandler)->connectModeTreeParent(satsystem::com::SUBSYSTEM); + ReturnValue_t result = (*args.ipCoreHandler)->connectModeTreeParent(satsystem::com::SUBSYSTEM); if (result != returnvalue::OK) { sif::error << "ObjectFactory::createCcsdsComponents: Connecting COM subsystem to CCSDS handler failed" @@ -797,14 +802,14 @@ ReturnValue_t ObjectFactory::createCcsdsComponents(LinuxLibgpioIF* gpioComIF, gpio = new GpiodRegularByLineName(q7s::gpioNames::PDEC_RESET, "PDEC Handler", Direction::OUT, Levels::LOW); gpioCookiePdec->addGpio(gpioIds::PDEC_RESET, gpio); - gpioChecker(gpioComIF->addGpios(gpioCookiePdec), "PDEC"); + gpioChecker(args.gpioComIF.addGpios(gpioCookiePdec), "PDEC"); struct UioNames uioNames {}; uioNames.configMemory = q7s::UIO_PDEC_CONFIG_MEMORY; uioNames.ramMemory = q7s::UIO_PDEC_RAM; uioNames.registers = q7s::UIO_PDEC_REGISTERS; uioNames.irq = q7s::UIO_PDEC_IRQ; - new PdecHandler(objects::PDEC_HANDLER, objects::CCSDS_HANDLER, gpioComIF, gpioIds::PDEC_RESET, - uioNames); + new PdecHandler(objects::PDEC_HANDLER, objects::CCSDS_HANDLER, &args.gpioComIF, + gpioIds::PDEC_RESET, uioNames); GpioCookie* gpioRS485Chip = new GpioCookie; gpio = new GpiodRegularByLineName(q7s::gpioNames::RS485_EN_TX_CLOCK, "RS485 Transceiver", Direction::OUT, Levels::LOW); @@ -819,7 +824,7 @@ ReturnValue_t ObjectFactory::createCcsdsComponents(LinuxLibgpioIF* gpioComIF, gpio = new GpiodRegularByLineName(q7s::gpioNames::RS485_EN_RX_DATA, "RS485 Transceiver", Direction::OUT, Levels::LOW); gpioRS485Chip->addGpio(gpioIds::RS485_EN_RX_DATA, gpio); - gpioChecker(gpioComIF->addGpios(gpioRS485Chip), "RS485 Transceiver"); + gpioChecker(args.gpioComIF.addGpios(gpioRS485Chip), "RS485 Transceiver"); return returnvalue::OK; } diff --git a/bsp_q7s/core/ObjectFactory.h b/bsp_q7s/core/ObjectFactory.h index d71ed359..c13f9c68 100644 --- a/bsp_q7s/core/ObjectFactory.h +++ b/bsp_q7s/core/ObjectFactory.h @@ -3,10 +3,12 @@ #include #include +#include #include #include #include #include +#include #include #include @@ -22,6 +24,24 @@ class GpioIF; namespace ObjectFactory { +struct CcsdsComponentArgs { + CcsdsComponentArgs(LinuxLibgpioIF& gpioIF, PusTmFunnel& funnel, StorageManagerIF& ipcStore, + StorageManagerIF& tmStore, PersistentTmStores& stores, + CcsdsIpCoreHandler** ipCoreHandler) + : gpioComIF(gpioIF), + pusFunnel(funnel), + ipcStore(ipcStore), + tmStore(tmStore), + stores(stores), + ipCoreHandler(ipCoreHandler) {} + LinuxLibgpioIF& gpioComIF; + PusTmFunnel& pusFunnel; + StorageManagerIF& ipcStore; + StorageManagerIF& tmStore; + PersistentTmStores& stores; + CcsdsIpCoreHandler** ipCoreHandler; +}; + void setStatics(); void produce(void* args); @@ -43,8 +63,7 @@ void createSolarArrayDeploymentComponents(PowerSwitchIF& pwrSwitcher, GpioIF& gp void createSyrlinksComponents(PowerSwitchIF* pwrSwitcher); void createPayloadComponents(LinuxLibgpioIF* gpioComIF, PowerSwitchIF& pwrSwitcher); void createReactionWheelComponents(LinuxLibgpioIF* gpioComIF, PowerSwitchIF* pwrSwitcher); -ReturnValue_t createCcsdsComponents(LinuxLibgpioIF* gpioComIF, PusTmFunnel& pusFunnel, - CcsdsIpCoreHandler** ipCoreHandler); +ReturnValue_t createCcsdsComponents(CcsdsComponentArgs& args); void createMiscComponents(); void createTestComponents(LinuxLibgpioIF* gpioComIF); diff --git a/bsp_q7s/fmObjectFactory.cpp b/bsp_q7s/fmObjectFactory.cpp index c8760478..0fecf58b 100644 --- a/bsp_q7s/fmObjectFactory.cpp +++ b/bsp_q7s/fmObjectFactory.cpp @@ -19,9 +19,12 @@ void ObjectFactory::produce(void* args) { HealthTableIF* healthTable = nullptr; PusTmFunnel* pusFunnel = nullptr; CfdpTmFunnel* cfdpFunnel = nullptr; + StorageManagerIF* ipcStore = nullptr; + StorageManagerIF* tmStore = nullptr; + PersistentTmStores stores; ObjectFactory::produceGenericObjects(&healthTable, &pusFunnel, &cfdpFunnel, - *SdCardManager::instance()); + *SdCardManager::instance(), &ipcStore, &tmStore, stores); LinuxLibgpioIF* gpioComIF = nullptr; SerialComIF* uartComIF = nullptr; @@ -74,7 +77,8 @@ void ObjectFactory::produce(void* args) { #endif /* OBSW_ADD_STAR_TRACKER == 1 */ #if OBSW_ADD_CCSDS_IP_CORES == 1 CcsdsIpCoreHandler* ipCoreHandler = nullptr; - createCcsdsComponents(gpioComIF, *pusFunnel, &ipCoreHandler); + CcsdsComponentArgs ccsdsArgs(*gpioComIF, *pusFunnel, *ipcStore, *tmStore, stores, &ipCoreHandler); + createCcsdsComponents(ccsdsArgs); #if OBSW_TM_TO_PTME == 1 // TODO: Remove this if not needed anymore // addTmtcIpCoresToFunnels(*ipCoreHandler, *pusFunnel, *cfdpFunnel); diff --git a/common/config/eive/objects.h b/common/config/eive/objects.h index bbab8a0a..d5a59791 100644 --- a/common/config/eive/objects.h +++ b/common/config/eive/objects.h @@ -168,6 +168,11 @@ enum commonObjects : uint32_t { HK_TM_STORE = 0x73020004, CFDP_TM_STORE = 0x73030000, + LIVE_TM_TASK = 0x73040000, + LOG_STORE_TASK = 0x73040001, + HK_STORE_TASK = 0x73040002, + CFDP_STORE_TASK = 0x73040003, + // Other stuff THERMAL_TEMP_INSERTER = 0x90000003, }; diff --git a/mission/core/GenericFactory.cpp b/mission/core/GenericFactory.cpp index e2e5c0c7..c7048cbc 100644 --- a/mission/core/GenericFactory.cpp +++ b/mission/core/GenericFactory.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -47,6 +48,7 @@ #include "mission/system/objects/RwAssembly.h" #include "mission/system/tree/acsModeTree.h" #include "mission/system/tree/tcsModeTree.h" +#include "mission/tmtc/tmFilters.h" #include "objects/systemObjectList.h" #include "tmtc/pusIds.h" @@ -87,7 +89,9 @@ EiveFaultHandler EIVE_FAULT_HANDLER; } // namespace cfdp void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFunnel** pusFunnel, - CfdpTmFunnel** cfdpFunnel, SdCardMountedIF& sdcMan) { + CfdpTmFunnel** cfdpFunnel, SdCardMountedIF& sdcMan, + StorageManagerIF** ipcStore, StorageManagerIF** tmStore, + PersistentTmStores& stores) { // Framework objects new EventManager(objects::EVENT_MANAGER); auto healthTable = new HealthTable(objects::HEALTH_TABLE); @@ -98,8 +102,6 @@ void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFun new VerificationReporter(); auto* timeStamper = new CdsShortTimeStamper(objects::TIME_STAMPER); StorageManagerIF* tcStore; - StorageManagerIF* tmStore; - StorageManagerIF* ipcStore; { PoolManager::LocalPoolConfig poolCfg = {{250, 16}, {250, 32}, {250, 64}, {150, 128}, {120, 1024}, {120, 2048}}; @@ -109,13 +111,13 @@ void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFun { PoolManager::LocalPoolConfig poolCfg = {{400, 32}, {400, 64}, {250, 128}, {150, 512}, {150, 1024}, {150, 2048}}; - tmStore = new PoolManager(objects::TM_STORE, poolCfg); + *tmStore = new PoolManager(objects::TM_STORE, poolCfg); } { PoolManager::LocalPoolConfig poolCfg = {{300, 16}, {200, 32}, {150, 64}, {150, 128}, {100, 256}, {50, 512}, {50, 1024}, {10, 2048}}; - ipcStore = new PoolManager(objects::IPC_STORE, poolCfg); + *ipcStore = new PoolManager(objects::IPC_STORE, poolCfg); } #if OBSW_ADD_TCPIP_SERVERS == 1 @@ -144,20 +146,71 @@ void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFun new CcsdsDistributor(config::EIVE_PUS_APID, objects::CCSDS_PACKET_DISTRIBUTOR); new PusDistributor(config::EIVE_PUS_APID, objects::PUS_PACKET_DISTRIBUTOR, ccsdsDistrib); - PusTmFunnel::FunnelCfg cfdpFunnelCfg(objects::CFDP_TM_FUNNEL, "CfdpTmFunnel", *tmStore, *ipcStore, - 50); + PusTmFunnel::FunnelCfg cfdpFunnelCfg(objects::CFDP_TM_FUNNEL, "CfdpTmFunnel", **tmStore, + **ipcStore, 50); *cfdpFunnel = new CfdpTmFunnel(cfdpFunnelCfg, config::EIVE_CFDP_APID); - auto* miscStore = new PersistentTmStore(objects::MISC_TM_STORE, "tm", "misc", - RolloverInterval::HOURLY, 2, *tmStore, sdcMan); - auto* okStore = new PersistentTmStore(objects::OK_TM_STORE, "tm", "ok", - RolloverInterval::MINUTELY, 30, *tmStore, sdcMan); - auto* notOkStore = new PersistentTmStore(objects::NOT_OK_TM_STORE, "tm", "nok", - RolloverInterval::MINUTELY, 30, *tmStore, sdcMan); - auto* hkStore = new PersistentTmStore(objects::HK_TM_STORE, "tm", "hk", - RolloverInterval::MINUTELY, 15, *tmStore, sdcMan); - PusTmFunnel::FunnelCfg pusFunnelCfg(objects::PUS_TM_FUNNEL, "PusTmFunnel", *tmStore, *ipcStore, + PusTmFunnel::FunnelCfg pusFunnelCfg(objects::PUS_TM_FUNNEL, "PusTmFunnel", **tmStore, **ipcStore, config::MAX_PUS_FUNNEL_QUEUE_DEPTH); + // The PUS funnel routes all live TM to the live destinations and to the TM stores. *pusFunnel = new PusTmFunnel(pusFunnelCfg, *timeStamper, sdcMan); + + // MISC store and PUS funnel to MISC store routing + // TODO: Make queue depth configurable + { + PersistentTmStoreArgs storeArgs(objects::MISC_TM_STORE, "tm", "misc", + + RolloverInterval::HOURLY, 2, **tmStore, sdcMan); + stores.miscStore = new PersistentTmStoreWithTmQueue(storeArgs, "MISC STORE", 500); + (*pusFunnel) + ->addPersistentTmStoreRouting(filters::miscFilter(), + stores.miscStore->getReportReceptionQueue(0)); + } + + // OK store and PUS Funnel to OK store routing + // TODO: Make queue depth configurable + { + PersistentTmStoreArgs storeArgs(objects::OK_TM_STORE, "tm", "ok", RolloverInterval::MINUTELY, + 30, **tmStore, sdcMan); + stores.okStore = new PersistentTmStoreWithTmQueue(storeArgs, "OK STORE", 500); + (*pusFunnel) + ->addPersistentTmStoreRouting(filters::okFilter(), + stores.okStore->getReportReceptionQueue(0)); + } + + // NOT OK store and PUS funnel to NOT OK store routing + // TODO: Make queue depth configurable + { + PersistentTmStoreArgs storeArgs(objects::NOT_OK_TM_STORE, "tm", "nok", + RolloverInterval::MINUTELY, 30, **tmStore, sdcMan); + stores.notOkStore = new PersistentTmStoreWithTmQueue(storeArgs, "NOT OK STORE", 500); + (*pusFunnel) + ->addPersistentTmStoreRouting(filters::notOkFilter(), + stores.notOkStore->getReportReceptionQueue(0)); + } + + // HK store and PUS funnel to HK store routing + // TODO: Make queue depth configurable + { + PersistentTmStoreArgs storeArgs(objects::HK_TM_STORE, "tm", "hk", RolloverInterval::MINUTELY, + 15, **tmStore, sdcMan); + stores.hkStore = new PersistentTmStoreWithTmQueue(storeArgs, "HK STORE", 500); + (*pusFunnel) + ->addPersistentTmStoreRouting(filters::hkFilter(), + stores.hkStore->getReportReceptionQueue(0)); + } + + // CFDP store and PUS funnel to CFDP store routing + // TODO: Make queue depth configurable + { + PersistentTmStoreArgs storeArgs(objects::CFDP_TM_STORE, "tm", "cfdp", + RolloverInterval::MINUTELY, 30, **tmStore, sdcMan); + stores.cfdpStore = new PersistentTmStoreWithTmQueue(storeArgs, "CFDP STORE", 500); + + (*pusFunnel) + ->addPersistentTmStoreRouting(filters::cfdpFilter(), + stores.cfdpStore->getReportReceptionQueue(0)); + } + #if OBSW_ADD_TCPIP_SERVERS == 1 #if OBSW_ADD_TMTC_UDP_SERVER == 1 (*cfdpFunnel)->addLiveDestination("UDP Server", *udpBridge, 0); @@ -208,7 +261,7 @@ void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFun new CfdpDistributor(distribCfg); auto* msgQueue = QueueFactory::instance()->createMessageQueue(32); - FsfwHandlerParams params(objects::CFDP_HANDLER, HOST_FS, **cfdpFunnel, *tcStore, *tmStore, + FsfwHandlerParams params(objects::CFDP_HANDLER, HOST_FS, **cfdpFunnel, *tcStore, **tmStore, *msgQueue); cfdp::IndicationCfg indicationCfg; UnsignedByteField apid(config::EIVE_LOCAL_CFDP_ENTITY_ID); diff --git a/mission/core/GenericFactory.h b/mission/core/GenericFactory.h index 5902ff7b..6fb5d73d 100644 --- a/mission/core/GenericFactory.h +++ b/mission/core/GenericFactory.h @@ -3,6 +3,7 @@ #include #include +#include #include "fsfw/objectmanager/SystemObjectIF.h" #include "fsfw/power/PowerSwitchIF.h" @@ -35,10 +36,20 @@ const std::array, EiveMax31855::NUM_RTDS> RT {objects::RTD_15_IC18_IMTQ, "RTD_15_IMTQ"}, }}; +struct PersistentTmStores { + PersistentTmStoreWithTmQueue* okStore; + PersistentTmStoreWithTmQueue* notOkStore; + PersistentTmStoreWithTmQueue* miscStore; + PersistentTmStoreWithTmQueue* hkStore; + PersistentTmStoreWithTmQueue* cfdpStore; +}; + namespace ObjectFactory { void produceGenericObjects(HealthTableIF** healthTable, PusTmFunnel** pusFunnel, - CfdpTmFunnel** cfdpFunnel, SdCardMountedIF& sdcMan); + CfdpTmFunnel** cfdpFunnel, SdCardMountedIF& sdcMan, + StorageManagerIF** ipcStore, StorageManagerIF** tmStore, + PersistentTmStores& stores); void createGenericHeaterComponents(GpioIF& gpioIF, PowerSwitchIF& pwrSwitcher, HeaterHandler*& heaterHandler); diff --git a/mission/tmtc/CMakeLists.txt b/mission/tmtc/CMakeLists.txt index ab5cf85d..b155e02e 100644 --- a/mission/tmtc/CMakeLists.txt +++ b/mission/tmtc/CMakeLists.txt @@ -12,6 +12,7 @@ target_sources( PusLiveDemux.cpp PersistentSingleTmStoreTask.cpp PersistentLogTmStoreTask.cpp + TmStoreTaskBase.cpp PusPacketFilter.cpp PusTmRouteByFilterHelper.cpp Service15TmStorage.cpp diff --git a/mission/tmtc/PersistentLogTmStoreTask.cpp b/mission/tmtc/PersistentLogTmStoreTask.cpp index 2102bcb7..0410893d 100644 --- a/mission/tmtc/PersistentLogTmStoreTask.cpp +++ b/mission/tmtc/PersistentLogTmStoreTask.cpp @@ -1 +1,28 @@ #include "PersistentLogTmStoreTask.h" + +#include + +PersistentLogTmStoreTask::PersistentLogTmStoreTask(object_id_t objectId, StorageManagerIF& ipcStore, + LogStores stores, VirtualChannel& channel) + : TmStoreTaskBase(objectId, ipcStore, channel), stores(stores) {} + +ReturnValue_t PersistentLogTmStoreTask::performOperation(uint8_t opCode) { + while (true) { + bool someonesBusy = false; + bool busy = handleOneStore(stores.okStore); + if (busy) { + someonesBusy = true; + } + busy = handleOneStore(stores.okStore); + if (busy) { + someonesBusy = true; + } + busy = handleOneStore(stores.miscStore); + if (busy) { + someonesBusy = true; + } + if (not someonesBusy) { + TaskFactory::delayTask(5); + } + } +} diff --git a/mission/tmtc/PersistentLogTmStoreTask.h b/mission/tmtc/PersistentLogTmStoreTask.h index d119fd33..a360c35c 100644 --- a/mission/tmtc/PersistentLogTmStoreTask.h +++ b/mission/tmtc/PersistentLogTmStoreTask.h @@ -5,22 +5,29 @@ #include #include #include +#include #include #include +#include #include struct LogStores { + LogStores(PersistentTmStores& stores) + : okStore(*stores.okStore), notOkStore(*stores.notOkStore), miscStore(*stores.miscStore) {} PersistentTmStoreWithTmQueue& okStore; PersistentTmStoreWithTmQueue& notOkStore; PersistentTmStoreWithTmQueue& miscStore; }; -class PersistentLogTmStoreTask : public SystemObject, public ExecutableObjectIF { +class PersistentLogTmStoreTask : public TmStoreTaskBase, public ExecutableObjectIF { public: PersistentLogTmStoreTask(object_id_t objectId, StorageManagerIF& ipcStore, LogStores tmStore, - VirtualChannelWithQueue& channel); + VirtualChannel& channel); + + ReturnValue_t performOperation(uint8_t opCode) override; private: + LogStores stores; }; #endif /* MISSION_TMTC_PERSISTENTLOGTMSTORETASK_H_ */ diff --git a/mission/tmtc/PersistentSingleTmStoreTask.cpp b/mission/tmtc/PersistentSingleTmStoreTask.cpp index 3b7f919c..e3bd018b 100644 --- a/mission/tmtc/PersistentSingleTmStoreTask.cpp +++ b/mission/tmtc/PersistentSingleTmStoreTask.cpp @@ -5,32 +5,12 @@ PersistentSingleTmStoreTask::PersistentSingleTmStoreTask(object_id_t objectId, StorageManagerIF& ipcStore, PersistentTmStoreWithTmQueue& tmStore, VirtualChannel& channel) - : SystemObject(objectId), ipcStore(ipcStore), storeWithQueue(tmStore), channel(channel) {} + : TmStoreTaskBase(objectId, ipcStore, channel), storeWithQueue(tmStore) {} ReturnValue_t PersistentSingleTmStoreTask::performOperation(uint8_t opCode) { - ReturnValue_t result; - auto& store = storeWithQueue.getTmStore(); - bool noTmToStoreReceived = false; - bool noTcRequestReceived = false; while (true) { - // Store TM persistently - result = storeWithQueue.handleNextTm(); - if (result == MessageQueueIF::NO_QUEUE) { - noTmToStoreReceived = true; - } - // Handle TC requests, for example deletion or retrieval requests. - result = store.handleCommandQueue(ipcStore); - if (result == MessageQueueIF::NO_QUEUE) { - noTcRequestReceived = true; - } - // Dump TMs when applicable - if (store.getState() == PersistentTmStore::State::DUMPING) { - size_t dumpedLen; - // TODO: Maybe do a bit of a delay every 100-200 packets? - // TODO: handle returnvalue? - store.dumpNextPacket(channel, dumpedLen); - } else if (noTcRequestReceived and noTmToStoreReceived) { - // Nothng to do, so sleep for a bit. + bool busy = handleOneStore(storeWithQueue); + if (not busy) { TaskFactory::delayTask(5); } } diff --git a/mission/tmtc/PersistentSingleTmStoreTask.h b/mission/tmtc/PersistentSingleTmStoreTask.h index 4ec9f03f..7776134a 100644 --- a/mission/tmtc/PersistentSingleTmStoreTask.h +++ b/mission/tmtc/PersistentSingleTmStoreTask.h @@ -4,9 +4,10 @@ #include #include #include +#include #include -class PersistentSingleTmStoreTask : public SystemObject, public ExecutableObjectIF { +class PersistentSingleTmStoreTask : public TmStoreTaskBase, public ExecutableObjectIF { public: PersistentSingleTmStoreTask(object_id_t objectId, StorageManagerIF& ipcStore, PersistentTmStoreWithTmQueue& storeWithQueue, @@ -15,9 +16,7 @@ class PersistentSingleTmStoreTask : public SystemObject, public ExecutableObject ReturnValue_t performOperation(uint8_t opCode) override; private: - StorageManagerIF& ipcStore; PersistentTmStoreWithTmQueue& storeWithQueue; - VirtualChannel& channel; }; #endif /* MISSION_TMTC_PERSISTENTSINGLETMSTORETASK_H_ */ diff --git a/mission/tmtc/PersistentTmStore.cpp b/mission/tmtc/PersistentTmStore.cpp index 8bcf59bd..0fe96c65 100644 --- a/mission/tmtc/PersistentTmStore.cpp +++ b/mission/tmtc/PersistentTmStore.cpp @@ -15,17 +15,14 @@ using namespace returnvalue; -PersistentTmStore::PersistentTmStore(object_id_t objectId, const char* baseDir, - std::string baseName, RolloverInterval intervalUnit, - uint32_t intervalCount, StorageManagerIF& tmStore, - SdCardMountedIF& sdcMan) - : SystemObject(objectId), - baseDir(baseDir), - baseName(std::move(baseName)), - sdcMan(sdcMan), - tmStore(tmStore) { +PersistentTmStore::PersistentTmStore(PersistentTmStoreArgs args) + : SystemObject(args.objectId), + tmStore(args.tmStore), + baseDir(args.baseDir), + baseName(std::move(args.baseName)), + sdcMan(args.sdcMan) { tcQueue = QueueFactory::instance()->createMessageQueue(); - calcDiffSeconds(intervalUnit, intervalCount); + calcDiffSeconds(args.intervalUnit, args.intervalCount); } ReturnValue_t PersistentTmStore::assignAndOrCreateMostRecentFile() { diff --git a/mission/tmtc/PersistentTmStore.h b/mission/tmtc/PersistentTmStore.h index 795c1fcd..34ad0ba0 100644 --- a/mission/tmtc/PersistentTmStore.h +++ b/mission/tmtc/PersistentTmStore.h @@ -17,6 +17,27 @@ enum class RolloverInterval { MINUTELY, HOURLY, DAILY }; +struct PersistentTmStoreArgs { + PersistentTmStoreArgs(object_id_t objectId, const char* baseDir, std::string baseName, + RolloverInterval intervalUnit, uint32_t intervalCount, + StorageManagerIF& tmStore, SdCardMountedIF& sdcMan) + : objectId(objectId), + baseDir(baseDir), + baseName(baseName), + intervalUnit(intervalUnit), + intervalCount(intervalCount), + tmStore(tmStore), + sdcMan(sdcMan) {} + + object_id_t objectId; + const char* baseDir; + std::string baseName; + RolloverInterval intervalUnit; + uint32_t intervalCount; + StorageManagerIF& tmStore; + SdCardMountedIF& sdcMan; +}; + class PersistentTmStore : public TmStoreFrontendSimpleIF, public SystemObject { public: enum class State { IDLE, DUMPING }; @@ -36,9 +57,7 @@ class PersistentTmStore : public TmStoreFrontendSimpleIF, public SystemObject { static constexpr Event FILE_TOO_LARGE = event::makeEvent(SUBSYSTEM_ID, 1, severity::LOW); static constexpr Event BUSY_DUMPING_EVENT = event::makeEvent(SUBSYSTEM_ID, 2, severity::INFO); - PersistentTmStore(object_id_t objectId, const char* baseDir, std::string baseName, - RolloverInterval intervalUnit, uint32_t intervalCount, - StorageManagerIF& tmStore, SdCardMountedIF& sdcMan); + PersistentTmStore(PersistentTmStoreArgs args); ReturnValue_t initializeTmStore(); State getState() const; @@ -52,6 +71,9 @@ class PersistentTmStore : public TmStoreFrontendSimpleIF, public SystemObject { // ReturnValue_t passPacket(PusTmReader& reader); ReturnValue_t storePacket(PusTmReader& reader); + protected: + StorageManagerIF& tmStore; + private: static constexpr uint8_t MAX_FILES_IN_ONE_SECOND = 10; static constexpr size_t MAX_FILESIZE = 8192; @@ -87,7 +109,6 @@ class PersistentTmStore : public TmStoreFrontendSimpleIF, public SystemObject { ActiveDumpParams dumpParams; std::optional activeFile; SdCardMountedIF& sdcMan; - StorageManagerIF& tmStore; /** * To get the queue where commands shall be sent. diff --git a/mission/tmtc/PersistentTmStoreWithTmQueue.cpp b/mission/tmtc/PersistentTmStoreWithTmQueue.cpp index b8d40adf..df4960d3 100644 --- a/mission/tmtc/PersistentTmStoreWithTmQueue.cpp +++ b/mission/tmtc/PersistentTmStoreWithTmQueue.cpp @@ -3,10 +3,10 @@ #include #include -PersistentTmStoreWithTmQueue::PersistentTmStoreWithTmQueue(StorageManagerIF& tmStore, - PersistentTmStore& persistentTmStore, +PersistentTmStoreWithTmQueue::PersistentTmStoreWithTmQueue(PersistentTmStoreArgs args, + const char* storeName, uint32_t tmQueueDepth) - : tmStore(tmStore), persistentTmStore(persistentTmStore) { + : PersistentTmStore(args), storeName(storeName) { tmQueue = QueueFactory::instance()->createMessageQueue(tmQueueDepth); } @@ -21,8 +21,13 @@ ReturnValue_t PersistentTmStoreWithTmQueue::handleNextTm() { return result; } PusTmReader reader(accessor.second.data(), accessor.second.size()); - persistentTmStore.storePacket(reader); + storePacket(reader); return returnvalue::OK; } -PersistentTmStore& PersistentTmStoreWithTmQueue::getTmStore() { return persistentTmStore; } +const char* PersistentTmStoreWithTmQueue::getName() const { return storeName; } + +MessageQueueId_t PersistentTmStoreWithTmQueue::getReportReceptionQueue( + uint8_t virtualChannel) const { + return tmQueue->getId(); +} diff --git a/mission/tmtc/PersistentTmStoreWithTmQueue.h b/mission/tmtc/PersistentTmStoreWithTmQueue.h index 05cc4d2d..be1026f8 100644 --- a/mission/tmtc/PersistentTmStoreWithTmQueue.h +++ b/mission/tmtc/PersistentTmStoreWithTmQueue.h @@ -2,18 +2,19 @@ #define MISSION_TMTC_PERSISTENTTMSTOREWITHTMQUEUE_H_ #include -class PersistentTmStoreWithTmQueue : public AcceptsTelemetryIF { +class PersistentTmStoreWithTmQueue : public PersistentTmStore, public AcceptsTelemetryIF { public: - PersistentTmStoreWithTmQueue(StorageManagerIF& tmStore, PersistentTmStore& persistentTmStore, + PersistentTmStoreWithTmQueue(PersistentTmStoreArgs args, const char* storeName, uint32_t tmQueueDepth); ReturnValue_t handleNextTm(); - PersistentTmStore& getTmStore(); + + [[nodiscard]] const char* getName() const override; + [[nodiscard]] MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel) const override; private: - StorageManagerIF& tmStore; + const char* storeName; MessageQueueIF* tmQueue; - PersistentTmStore& persistentTmStore; }; #endif /* MISSION_TMTC_PERSISTENTTMSTOREWITHTMQUEUE_H_ */ diff --git a/mission/tmtc/TmStoreTaskBase.cpp b/mission/tmtc/TmStoreTaskBase.cpp new file mode 100644 index 00000000..839cb754 --- /dev/null +++ b/mission/tmtc/TmStoreTaskBase.cpp @@ -0,0 +1,35 @@ +#include "TmStoreTaskBase.h" + +TmStoreTaskBase::TmStoreTaskBase(object_id_t objectId, StorageManagerIF& ipcStore, + VirtualChannel& channel) + : SystemObject(objectId), ipcStore(ipcStore), channel(channel) {} + +bool TmStoreTaskBase::handleOneStore(PersistentTmStoreWithTmQueue& store) { + bool tmToStoreReceived = true; + bool tcRequestReceived = true; + bool dumpsPerformed = false; + // Store TM persistently + ReturnValue_t result = store.handleNextTm(); + if (result == MessageQueueIF::NO_QUEUE) { + tmToStoreReceived = false; + } + // Handle TC requests, for example deletion or retrieval requests. + result = store.handleCommandQueue(ipcStore); + if (result == MessageQueueIF::NO_QUEUE) { + tcRequestReceived = false; + } + // Dump TMs when applicable + if (store.getState() == PersistentTmStore::State::DUMPING) { + size_t dumpedLen; + // TODO: Maybe do a bit of a delay every 100-200 packets? + // TODO: handle returnvalue? + result = store.dumpNextPacket(channel, dumpedLen); + if (result == returnvalue::OK) { + dumpsPerformed = true; + } + } + if (tcRequestReceived or tmToStoreReceived or dumpsPerformed) { + return true; + } + return false; +} diff --git a/mission/tmtc/TmStoreTaskBase.h b/mission/tmtc/TmStoreTaskBase.h new file mode 100644 index 00000000..b2f1f323 --- /dev/null +++ b/mission/tmtc/TmStoreTaskBase.h @@ -0,0 +1,22 @@ +#ifndef MISSION_TMTC_TMSTORETASKBASE_H_ +#define MISSION_TMTC_TMSTORETASKBASE_H_ + +#include +#include + +class TmStoreTaskBase : public SystemObject { + public: + TmStoreTaskBase(object_id_t objectId, StorageManagerIF& ipcStore, VirtualChannel& channel); + /** + * Handling for one store. Returns if anything was done. + * @param store + * @return + */ + bool handleOneStore(PersistentTmStoreWithTmQueue& store); + + private: + StorageManagerIF& ipcStore; + VirtualChannel& channel; +}; + +#endif /* MISSION_TMTC_TMSTORETASKBASE_H_ */ diff --git a/mission/tmtc/VirtualChannel.cpp b/mission/tmtc/VirtualChannel.cpp index fba64049..0c41ad86 100644 --- a/mission/tmtc/VirtualChannel.cpp +++ b/mission/tmtc/VirtualChannel.cpp @@ -3,9 +3,9 @@ VirtualChannel::VirtualChannel(object_id_t objectId, uint8_t vcId, const char* vcName, PtmeIF& ptme, const std::atomic_bool& linkStateProvider) : SystemObject(objectId), + ptme(ptme), vcId(vcId), vcName(vcName), - ptme(ptme), linkStateProvider(linkStateProvider) {} ReturnValue_t VirtualChannel::initialize() { return returnvalue::OK; } diff --git a/mission/tmtc/VirtualChannelWithQueue.cpp b/mission/tmtc/VirtualChannelWithQueue.cpp index 62557973..630552cb 100644 --- a/mission/tmtc/VirtualChannelWithQueue.cpp +++ b/mission/tmtc/VirtualChannelWithQueue.cpp @@ -7,15 +7,18 @@ #include "fsfw/serviceinterface/ServiceInterfaceStream.h" #include "fsfw/tmtcservices/TmTcMessage.h" -VirtualChannelWithQueue::VirtualChannelWithQueue(VirtualChannel& channel, StorageManagerIF& tmStore, - uint32_t tmQueueDepth, - const std::atomic_bool& linkStateProvider) - : channel(channel) { - auto mqArgs = MqArgs(channel.getObjectId(), reinterpret_cast(channel.getVcid())); +VirtualChannelWithQueue::VirtualChannelWithQueue(object_id_t objectId, uint8_t vcId, + const char* vcName, PtmeIF& ptme, + const std::atomic_bool& linkStateProvider, + StorageManagerIF& tmStore, uint32_t tmQueueDepth) + : VirtualChannel(objectId, vcId, vcName, ptme, linkStateProvider) { + auto mqArgs = MqArgs(getObjectId(), reinterpret_cast(getVcid())); tmQueue = QueueFactory::instance()->createMessageQueue( tmQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs); } +const char* VirtualChannelWithQueue::getName() const { return VirtualChannel::getName(); } + ReturnValue_t VirtualChannelWithQueue::sendNextTm() { TmTcMessage message; ReturnValue_t result = tmQueue->receiveMessage(&message); @@ -33,7 +36,7 @@ ReturnValue_t VirtualChannelWithQueue::sendNextTm() { return result; } - channel.write(data, size); + write(data, size); tmStore->deleteData(storeId); if (result != returnvalue::OK) { return result; @@ -44,5 +47,3 @@ ReturnValue_t VirtualChannelWithQueue::sendNextTm() { MessageQueueId_t VirtualChannelWithQueue::getReportReceptionQueue(uint8_t virtualChannel) const { return tmQueue->getId(); } - -VirtualChannel& VirtualChannelWithQueue::vc() { return channel; } diff --git a/mission/tmtc/VirtualChannelWithQueue.h b/mission/tmtc/VirtualChannelWithQueue.h index f7a2bef9..fdd0fca4 100644 --- a/mission/tmtc/VirtualChannelWithQueue.h +++ b/mission/tmtc/VirtualChannelWithQueue.h @@ -20,7 +20,7 @@ class StorageManagerIF; * * @author J. Meier */ -class VirtualChannelWithQueue : public AcceptsTelemetryIF { +class VirtualChannelWithQueue : public VirtualChannel, public AcceptsTelemetryIF { public: /** * @brief Constructor @@ -28,18 +28,15 @@ class VirtualChannelWithQueue : public AcceptsTelemetryIF { * @param vcId The virtual channel id assigned to this object * @param tmQueueDepth Queue depth of queue receiving telemetry from other objects */ - VirtualChannelWithQueue(VirtualChannel& channel, StorageManagerIF& tmStore, uint32_t tmQueueDepth, - const std::atomic_bool& linkStateProvider); + VirtualChannelWithQueue(object_id_t objectId, uint8_t vcId, const char* vcName, PtmeIF& ptme, + const std::atomic_bool& linkStateProvider, StorageManagerIF& tmStore, + uint32_t tmQueueDepth); MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel = 0) const override; + [[nodiscard]] const char* getName() const override; ReturnValue_t sendNextTm(); - VirtualChannel& vc(); - - const char* getName() const override; - private: - VirtualChannel& channel; MessageQueueIF* tmQueue = nullptr; StorageManagerIF* tmStore = nullptr; }; diff --git a/mission/tmtc/tmFilters.cpp b/mission/tmtc/tmFilters.cpp index 540df3de..944cd3be 100644 --- a/mission/tmtc/tmFilters.cpp +++ b/mission/tmtc/tmFilters.cpp @@ -49,3 +49,9 @@ PusPacketFilter filters::notOkFilter() { notOkFilter.addServiceSubservice(pus::PUS_SERVICE_1, 8); return notOkFilter; } + +PusPacketFilter filters::cfdpFilter() { + PusPacketFilter cfdpFilter; + cfdpFilter.addApid(config::EIVE_CFDP_APID); + return cfdpFilter; +} diff --git a/mission/tmtc/tmFilters.h b/mission/tmtc/tmFilters.h index fc5318f9..a358c8f0 100644 --- a/mission/tmtc/tmFilters.h +++ b/mission/tmtc/tmFilters.h @@ -4,6 +4,7 @@ namespace filters { +PusPacketFilter cfdpFilter(); PusPacketFilter hkFilter(); PusPacketFilter miscFilter(); PusPacketFilter okFilter();