Refactor TM handling #450

Merged
muellerr merged 47 commits from refactor_tm_handling into develop 2023-03-11 15:05:22 +01:00
23 changed files with 330 additions and 125 deletions
Showing only changes of commit b2fd2f5d83 - Show all commits

View File

@ -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

View File

@ -12,6 +12,9 @@
#include <mission/system/objects/ImtqAssembly.h>
#include <mission/system/objects/StrAssembly.h>
#include <mission/system/objects/SyrlinksAssembly.h>
#include <mission/tmtc/LiveTmTask.h>
#include <mission/tmtc/PersistentLogTmStoreTask.h>
#include <mission/tmtc/PersistentSingleTmStoreTask.h>
#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;
}

View File

@ -3,10 +3,12 @@
#include <fsfw/returnvalues/returnvalue.h>
#include <fsfw_hal/linux/spi/SpiComIF.h>
#include <mission/core/GenericFactory.h>
#include <mission/devices/HeaterHandler.h>
#include <mission/system/objects/Stack5VHandler.h>
#include <mission/tmtc/CcsdsIpCoreHandler.h>
#include <mission/tmtc/CfdpTmFunnel.h>
#include <mission/tmtc/PersistentLogTmStoreTask.h>
#include <mission/tmtc/PusTmFunnel.h>
#include <string>
@ -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);

View File

@ -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);

View File

@ -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,
};

View File

@ -34,6 +34,7 @@
#include <mission/system/objects/TcsBoardAssembly.h>
#include <mission/tmtc/CfdpTmFunnel.h>
#include <mission/tmtc/PersistentTmStore.h>
#include <mission/tmtc/PersistentTmStoreWithTmQueue.h>
#include <mission/tmtc/PusPacketFilter.h>
#include <mission/tmtc/PusTmFunnel.h>
#include <mission/tmtc/PusTmRouteByFilterHelper.h>
@ -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<uint16_t> apid(config::EIVE_LOCAL_CFDP_ENTITY_ID);

View File

@ -3,6 +3,7 @@
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
#include <mission/memory/SdCardMountedIF.h>
#include <mission/tmtc/PersistentTmStoreWithTmQueue.h>
#include "fsfw/objectmanager/SystemObjectIF.h"
#include "fsfw/power/PowerSwitchIF.h"
@ -35,10 +36,20 @@ const std::array<std::pair<object_id_t, std::string>, 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);

View File

@ -12,6 +12,7 @@ target_sources(
PusLiveDemux.cpp
PersistentSingleTmStoreTask.cpp
PersistentLogTmStoreTask.cpp
TmStoreTaskBase.cpp
PusPacketFilter.cpp
PusTmRouteByFilterHelper.cpp
Service15TmStorage.cpp

View File

@ -1 +1,28 @@
#include "PersistentLogTmStoreTask.h"
#include <fsfw/tasks/TaskFactory.h>
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);
}
}
}

View File

@ -5,22 +5,29 @@
#include <fsfw/storagemanager/StorageManagerIF.h>
#include <fsfw/tasks/ExecutableObjectIF.h>
#include <fsfw/tmtcservices/AcceptsTelemetryIF.h>
#include <mission/core/GenericFactory.h>
#include <mission/tmtc/PersistentTmStore.h>
#include <mission/tmtc/PersistentTmStoreWithTmQueue.h>
#include <mission/tmtc/TmStoreTaskBase.h>
#include <mission/tmtc/VirtualChannelWithQueue.h>
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_ */

View File

@ -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);
}
}

View File

@ -4,9 +4,10 @@
#include <fsfw/objectmanager/SystemObject.h>
#include <fsfw/tasks/ExecutableObjectIF.h>
#include <mission/tmtc/PersistentTmStoreWithTmQueue.h>
#include <mission/tmtc/TmStoreTaskBase.h>
#include <mission/tmtc/VirtualChannel.h>
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_ */

View File

@ -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() {

View File

@ -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<std::filesystem::path> activeFile;
SdCardMountedIF& sdcMan;
StorageManagerIF& tmStore;
/**
* To get the queue where commands shall be sent.

View File

@ -3,10 +3,10 @@
#include <fsfw/ipc/QueueFactory.h>
#include <fsfw/tmtcservices/TmTcMessage.h>
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();
}

View File

@ -2,18 +2,19 @@
#define MISSION_TMTC_PERSISTENTTMSTOREWITHTMQUEUE_H_
#include <mission/tmtc/PersistentTmStore.h>
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_ */

View File

@ -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;
}

View File

@ -0,0 +1,22 @@
#ifndef MISSION_TMTC_TMSTORETASKBASE_H_
#define MISSION_TMTC_TMSTORETASKBASE_H_
#include <mission/tmtc/PersistentTmStoreWithTmQueue.h>
#include <mission/tmtc/VirtualChannel.h>
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_ */

View File

@ -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; }

View File

@ -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<void*>(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<void*>(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; }

View File

@ -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;
};

View File

@ -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;
}

View File

@ -4,6 +4,7 @@
namespace filters {
PusPacketFilter cfdpFilter();
PusPacketFilter hkFilter();
PusPacketFilter miscFilter();
PusPacketFilter okFilter();