modes for VC/stores

This commit is contained in:
Robin Müller 2023-03-31 01:14:59 +02:00
parent f6f4db525c
commit 4b1221ab99
No known key found for this signature in database
GPG Key ID: 71B58F8A3CDFA9AC
24 changed files with 347 additions and 90 deletions

View File

@ -19,6 +19,10 @@ will consitute of a breaking change warranting a new major release:
## Changed ## Changed
- SCEX filename updates. Also use T as the file ID / date separator between date and time. - SCEX filename updates. Also use T as the file ID / date separator between date and time.
- COM TM store and dump handling: Introduce modes for all 4 TM VC/store tasks. The OFF mode can be
used to disable ongoing dumps or to prevent writes to the PTME VC. This allows cleaner reset
handling of the PTME. All 4 VC/store tasks were attached to the COM mode tree and are commanded
as part of the COM sequence as well to ensure consistent state with the CCSDS IP core handler.
## Fixed ## Fixed

View File

@ -20,15 +20,15 @@
#include <mission/acs/MgmRm3100CustomHandler.h> #include <mission/acs/MgmRm3100CustomHandler.h>
#include <mission/acs/str/StarTrackerHandler.h> #include <mission/acs/str/StarTrackerHandler.h>
#include <mission/acs/str/strHelpers.h> #include <mission/acs/str/strHelpers.h>
#include <mission/com/LiveTmTask.h>
#include <mission/com/PersistentLogTmStoreTask.h>
#include <mission/com/PersistentSingleTmStoreTask.h>
#include <mission/power/CspCookie.h> #include <mission/power/CspCookie.h>
#include <mission/system/acs/ImtqAssembly.h> #include <mission/system/acs/ImtqAssembly.h>
#include <mission/system/acs/StrAssembly.h> #include <mission/system/acs/StrAssembly.h>
#include <mission/system/fdir/StrFdir.h> #include <mission/system/fdir/StrFdir.h>
#include <mission/system/objects/CamSwitcher.h> #include <mission/system/objects/CamSwitcher.h>
#include <mission/system/objects/SyrlinksAssembly.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 "OBSWConfig.h"
#include "bsp_q7s/boardtest/Q7STestTask.h" #include "bsp_q7s/boardtest/Q7STestTask.h"
@ -81,6 +81,7 @@ using gpio::Levels;
#include <mission/acs/ImtqHandler.h> #include <mission/acs/ImtqHandler.h>
#include <mission/acs/rwHelpers.h> #include <mission/acs/rwHelpers.h>
#include <mission/com/SyrlinksHandler.h> #include <mission/com/SyrlinksHandler.h>
#include <mission/com/VirtualChannelWithQueue.h>
#include <mission/payload/PayloadPcduHandler.h> #include <mission/payload/PayloadPcduHandler.h>
#include <mission/payload/RadiationSensorHandler.h> #include <mission/payload/RadiationSensorHandler.h>
#include <mission/payload/payloadPcduDefinitions.h> #include <mission/payload/payloadPcduDefinitions.h>
@ -96,7 +97,6 @@ using gpio::Levels;
#include <mission/tcs/Max31865Definitions.h> #include <mission/tcs/Max31865Definitions.h>
#include <mission/tcs/Max31865PT1000Handler.h> #include <mission/tcs/Max31865PT1000Handler.h>
#include <mission/tcs/Tmp1075Handler.h> #include <mission/tcs/Tmp1075Handler.h>
#include <mission/tmtc/VirtualChannelWithQueue.h>
#include <sstream> #include <sstream>

View File

@ -4,11 +4,11 @@
#include <fsfw/returnvalues/returnvalue.h> #include <fsfw/returnvalues/returnvalue.h>
#include <fsfw_hal/linux/spi/SpiComIF.h> #include <fsfw_hal/linux/spi/SpiComIF.h>
#include <mission/com/CcsdsIpCoreHandler.h> #include <mission/com/CcsdsIpCoreHandler.h>
#include <mission/com/PersistentLogTmStoreTask.h>
#include <mission/genericFactory.h> #include <mission/genericFactory.h>
#include <mission/system/objects/Stack5VHandler.h> #include <mission/system/objects/Stack5VHandler.h>
#include <mission/tcs/HeaterHandler.h> #include <mission/tcs/HeaterHandler.h>
#include <mission/tmtc/CfdpTmFunnel.h> #include <mission/tmtc/CfdpTmFunnel.h>
#include <mission/tmtc/PersistentLogTmStoreTask.h>
#include <mission/tmtc/PusTmFunnel.h> #include <mission/tmtc/PusTmFunnel.h>
#include <atomic> #include <atomic>

View File

@ -19,7 +19,7 @@ PapbVcInterface::~PapbVcInterface() {}
ReturnValue_t PapbVcInterface::initialize() { ReturnValue_t PapbVcInterface::initialize() {
UioMapper uioMapper(uioFile, mapNum); UioMapper uioMapper(uioFile, mapNum);
ReturnValue_t result = uioMapper.getMappedAdress(const_cast<uint32_t**>(&vcBaseReg), ReturnValue_t result = uioMapper.getMappedAdress(const_cast<uint32_t**>(&vcBaseReg),
UioMapper::Permissions::WRITE_ONLY); UioMapper::Permissions::WRITE_ONLY);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;
} }
@ -38,7 +38,7 @@ ReturnValue_t PapbVcInterface::write(const uint8_t* data, size_t size) {
// TODO: Maybe this should not be done like this. It would be better if there was a custom // TODO: Maybe this should not be done like this. It would be better if there was a custom
// FPGA module which can accept packets and then takes care of dumping that packet into // FPGA module which can accept packets and then takes care of dumping that packet into
// the PTME. DMA would be an ideal solution for this. // the PTME. DMA would be an ideal solution for this.
nanosleep(&BETWEEN_POLL_DELAY, &remDelay); // nanosleep(&BETWEEN_POLL_DELAY, &remDelay);
if (pollPapbBusySignal(2) == returnvalue::OK) { if (pollPapbBusySignal(2) == returnvalue::OK) {
*(vcBaseReg + DATA_REG_OFFSET) = static_cast<uint32_t>(data[idx]); *(vcBaseReg + DATA_REG_OFFSET) = static_cast<uint32_t>(data[idx]);
} else { } else {
@ -46,7 +46,7 @@ ReturnValue_t PapbVcInterface::write(const uint8_t* data, size_t size) {
return returnvalue::FAILED; return returnvalue::FAILED;
} }
} }
nanosleep(&BETWEEN_POLL_DELAY, &remDelay); // nanosleep(&BETWEEN_POLL_DELAY, &remDelay);
if (pollPapbBusySignal(2) == returnvalue::OK) { if (pollPapbBusySignal(2) == returnvalue::OK) {
completePacketTransfer(); completePacketTransfer();
} else { } else {

View File

@ -5,6 +5,8 @@
#include <fsfw_hal/linux/gpio/LinuxLibgpioIF.h> #include <fsfw_hal/linux/gpio/LinuxLibgpioIF.h>
#include <linux/ipcore/VirtualChannelIF.h> #include <linux/ipcore/VirtualChannelIF.h>
#include <atomic>
#include "OBSWConfig.h" #include "OBSWConfig.h"
#include "fsfw/returnvalues/returnvalue.h" #include "fsfw/returnvalues/returnvalue.h"

View File

@ -1,2 +1,11 @@
target_sources(${LIB_EIVE_MISSION} PRIVATE SyrlinksHandler.cpp target_sources(
CcsdsIpCoreHandler.cpp) ${LIB_EIVE_MISSION}
PRIVATE SyrlinksHandler.cpp
CcsdsIpCoreHandler.cpp
LiveTmTask.cpp
PersistentLogTmStoreTask.cpp
TmStoreTaskBase.cpp
VirtualChannel.cpp
VirtualChannelWithQueue.cpp
PersistentSingleTmStoreTask.cpp
LiveTmTask.cpp)

View File

@ -2,7 +2,7 @@
#define CCSDSHANDLER_H_ #define CCSDSHANDLER_H_
#include <fsfw/modes/HasModesIF.h> #include <fsfw/modes/HasModesIF.h>
#include <mission/tmtc/VirtualChannelWithQueue.h> #include <mission/com/VirtualChannelWithQueue.h>
#include <cstdint> #include <cstdint>
#include <unordered_map> #include <unordered_map>

101
mission/com/LiveTmTask.cpp Normal file
View File

@ -0,0 +1,101 @@
#include "LiveTmTask.h"
#include <fsfw/ipc/QueueFactory.h>
#include <fsfw/subsystem/helper.h>
#include <fsfw/tasks/TaskFactory.h>
#include <fsfw/timemanager/Stopwatch.h>
LiveTmTask::LiveTmTask(object_id_t objectId, PusTmFunnel& pusFunnel, CfdpTmFunnel& cfdpFunnel,
VirtualChannelWithQueue& channel)
: SystemObject(objectId),
modeHelper(this),
pusFunnel(pusFunnel),
cfdpFunnel(cfdpFunnel),
channel(channel) {
requestQueue = QueueFactory::instance()->createMessageQueue();
}
ReturnValue_t LiveTmTask::performOperation(uint8_t opCode) {
readCommandQueue();
while (true) {
bool performWriteOp = true;
if (mode == MODE_OFF) {
performWriteOp = false;
}
// The funnel tasks are scheduled here directly as well.
ReturnValue_t result = channel.handleNextTm(performWriteOp);
if (result == DirectTmSinkIF::IS_BUSY) {
sif::error << "Lost live TM, PAPB busy" << std::endl;
}
if (result == MessageQueueIF::EMPTY) {
if (tmFunnelCd.hasTimedOut()) {
pusFunnel.performOperation(0);
cfdpFunnel.performOperation(0);
tmFunnelCd.resetTimer();
}
// Read command queue during idle times.
readCommandQueue();
// 40 ms IDLE delay. Might tweak this in the future.
TaskFactory::delayTask(40);
} else {
packetCounter++;
}
}
}
MessageQueueId_t LiveTmTask::getCommandQueue() const { return requestQueue->getId(); }
void LiveTmTask::getMode(Mode_t* mode, Submode_t* submode) {
if (mode != nullptr) {
*mode = this->mode;
}
if (submode != nullptr) {
*submode = SUBMODE_NONE;
}
}
ReturnValue_t LiveTmTask::checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t* msToReachTheMode) {
if (mode == MODE_ON or mode == MODE_OFF) {
return returnvalue::OK;
}
return returnvalue::FAILED;
}
void LiveTmTask::startTransition(Mode_t mode, Submode_t submode) {
this->mode = mode;
modeHelper.modeChanged(mode, submode);
announceMode(false);
}
void LiveTmTask::announceMode(bool recursive) { triggerEvent(MODE_INFO, mode, SUBMODE_NONE); }
object_id_t LiveTmTask::getObjectId() const { return SystemObject::getObjectId(); }
const HasHealthIF* LiveTmTask::getOptHealthIF() const { return nullptr; }
const HasModesIF& LiveTmTask::getModeIF() const { return *this; }
ReturnValue_t LiveTmTask::connectModeTreeParent(HasModeTreeChildrenIF& parent) {
return modetree::connectModeTreeParent(parent, *this, nullptr, modeHelper);
}
void LiveTmTask::readCommandQueue(void) {
CommandMessage commandMessage;
ReturnValue_t result = returnvalue::FAILED;
result = requestQueue->receiveMessage(&commandMessage);
if (result == returnvalue::OK) {
result = modeHelper.handleModeCommand(&commandMessage);
if (result == returnvalue::OK) {
return;
}
CommandMessage reply;
reply.setReplyRejected(CommandMessage::UNKNOWN_COMMAND, commandMessage.getCommand());
requestQueue->reply(&reply);
return;
}
}
ModeTreeChildIF& LiveTmTask::getModeTreeChildIF() { return *this; }

55
mission/com/LiveTmTask.h Normal file
View File

@ -0,0 +1,55 @@
#ifndef MISSION_TMTC_LIVETMTASK_H_
#define MISSION_TMTC_LIVETMTASK_H_
#include <fsfw/modes/HasModesIF.h>
#include <fsfw/objectmanager/SystemObject.h>
#include <fsfw/subsystem/ModeTreeChildIF.h>
#include <fsfw/subsystem/ModeTreeConnectionIF.h>
#include <fsfw/tasks/ExecutableObjectIF.h>
#include <fsfw/timemanager/Countdown.h>
#include <mission/com/VirtualChannelWithQueue.h>
#include <mission/tmtc/CfdpTmFunnel.h>
#include <mission/tmtc/PusTmFunnel.h>
class LiveTmTask : public SystemObject,
public HasModesIF,
public ExecutableObjectIF,
public ModeTreeChildIF,
public ModeTreeConnectionIF {
public:
LiveTmTask(object_id_t objectId, PusTmFunnel& pusFunnel, CfdpTmFunnel& cfdpFunnel,
VirtualChannelWithQueue& channel);
ReturnValue_t performOperation(uint8_t opCode) override;
private:
MessageQueueIF* requestQueue;
ModeHelper modeHelper;
Mode_t mode = HasModesIF::MODE_OFF;
Countdown tmFunnelCd = Countdown(100);
PusTmFunnel& pusFunnel;
CfdpTmFunnel& cfdpFunnel;
VirtualChannelWithQueue& channel;
uint32_t packetCounter = 0;
void readCommandQueue(void);
MessageQueueId_t getCommandQueue() const override;
void getMode(Mode_t* mode, Submode_t* submode) override;
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t* msToReachTheMode) override;
void startTransition(Mode_t mode, Submode_t submode) override;
void announceMode(bool recursive) override;
object_id_t getObjectId() const override;
const HasHealthIF* getOptHealthIF() const override;
const HasModesIF& getModeIF() const override;
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF& parent) override;
ModeTreeChildIF& getModeTreeChildIF() override;
};
#endif /* MISSION_TMTC_LIVETMTASK_H_ */

View File

@ -27,6 +27,8 @@ ReturnValue_t PersistentLogTmStoreTask::performOperation(uint8_t opCode) {
} }
}; };
while (true) { while (true) {
readCommandQueue();
if (not cyclicStoreCheck()) { if (not cyclicStoreCheck()) {
continue; continue;
} }
@ -54,3 +56,17 @@ bool PersistentLogTmStoreTask::initStoresIfPossible() {
} }
return false; return false;
} }
void PersistentLogTmStoreTask::startTransition(Mode_t mode, Submode_t submode) {
if (mode == MODE_OFF) {
bool channelIsOn = channel.isTxOn();
cancelDump(okStoreContext, stores.okStore, channelIsOn);
cancelDump(notOkStoreContext, stores.notOkStore, channelIsOn);
cancelDump(miscStoreContext, stores.miscStore, channelIsOn);
this->mode = MODE_OFF;
} else if (mode == MODE_ON) {
this->mode = MODE_ON;
}
modeHelper.modeChanged(mode, submode);
announceMode(false);
}

View File

@ -5,11 +5,11 @@
#include <fsfw/storagemanager/StorageManagerIF.h> #include <fsfw/storagemanager/StorageManagerIF.h>
#include <fsfw/tasks/ExecutableObjectIF.h> #include <fsfw/tasks/ExecutableObjectIF.h>
#include <fsfw/tmtcservices/AcceptsTelemetryIF.h> #include <fsfw/tmtcservices/AcceptsTelemetryIF.h>
#include <mission/com/TmStoreTaskBase.h>
#include <mission/com/VirtualChannelWithQueue.h>
#include <mission/genericFactory.h> #include <mission/genericFactory.h>
#include <mission/tmtc/PersistentTmStore.h> #include <mission/tmtc/PersistentTmStore.h>
#include <mission/tmtc/PersistentTmStoreWithTmQueue.h> #include <mission/tmtc/PersistentTmStoreWithTmQueue.h>
#include <mission/tmtc/TmStoreTaskBase.h>
#include <mission/tmtc/VirtualChannelWithQueue.h>
struct LogStores { struct LogStores {
LogStores(PersistentTmStores& stores) LogStores(PersistentTmStores& stores)
@ -36,6 +36,7 @@ class PersistentLogTmStoreTask : public TmStoreTaskBase, public ExecutableObject
bool someFileWasSwapped = false; bool someFileWasSwapped = false;
bool initStoresIfPossible() override; bool initStoresIfPossible() override;
void startTransition(Mode_t mode, Submode_t submode) override;
}; };
#endif /* MISSION_TMTC_PERSISTENTLOGTMSTORETASK_H_ */ #endif /* MISSION_TMTC_PERSISTENTLOGTMSTORETASK_H_ */

View File

@ -1,17 +1,21 @@
#include "PersistentSingleTmStoreTask.h"
#include <fsfw/tasks/TaskFactory.h> #include <fsfw/tasks/TaskFactory.h>
#include <fsfw/timemanager/Stopwatch.h> #include <fsfw/timemanager/Stopwatch.h>
#include <mission/tmtc/PersistentSingleTmStoreTask.h>
#include <unistd.h> #include <unistd.h>
PersistentSingleTmStoreTask::PersistentSingleTmStoreTask( PersistentSingleTmStoreTask::PersistentSingleTmStoreTask(
object_id_t objectId, StorageManagerIF& ipcStore, PersistentTmStoreWithTmQueue& tmStore, object_id_t objectId, StorageManagerIF& ipcStore, PersistentTmStoreWithTmQueue& tmStore,
VirtualChannel& channel, Event eventIfDumpDone, Event eventIfCancelled, SdCardMountedIF& sdcMan) VirtualChannel& channel, Event eventIfDumpDone, Event eventIfCancelled, SdCardMountedIF& sdcMan)
: TmStoreTaskBase(objectId, ipcStore, channel, sdcMan), : TmStoreTaskBase(objectId, ipcStore, channel, sdcMan),
modeHelper(this),
storeWithQueue(tmStore), storeWithQueue(tmStore),
dumpContext(eventIfDumpDone, eventIfCancelled) {} dumpContext(eventIfDumpDone, eventIfCancelled) {}
ReturnValue_t PersistentSingleTmStoreTask::performOperation(uint8_t opCode) { ReturnValue_t PersistentSingleTmStoreTask::performOperation(uint8_t opCode) {
while (true) { while (true) {
readCommandQueue();
// Delay done by the check // Delay done by the check
if (not cyclicStoreCheck()) { if (not cyclicStoreCheck()) {
continue; continue;
@ -33,3 +37,14 @@ bool PersistentSingleTmStoreTask::initStoresIfPossible() {
} }
return false; return false;
} }
void PersistentSingleTmStoreTask::startTransition(Mode_t mode, Submode_t submode) {
if (mode == MODE_OFF) {
cancelDump(dumpContext, storeWithQueue, channel.isTxOn());
this->mode = MODE_OFF;
} else if (mode == MODE_ON) {
this->mode = MODE_ON;
}
modeHelper.modeChanged(mode, submode);
announceMode(false);
}

View File

@ -3,9 +3,9 @@
#include <fsfw/objectmanager/SystemObject.h> #include <fsfw/objectmanager/SystemObject.h>
#include <fsfw/tasks/ExecutableObjectIF.h> #include <fsfw/tasks/ExecutableObjectIF.h>
#include <mission/com/TmStoreTaskBase.h>
#include <mission/com/VirtualChannel.h>
#include <mission/tmtc/PersistentTmStoreWithTmQueue.h> #include <mission/tmtc/PersistentTmStoreWithTmQueue.h>
#include <mission/tmtc/TmStoreTaskBase.h>
#include <mission/tmtc/VirtualChannel.h>
class PersistentSingleTmStoreTask : public TmStoreTaskBase, public ExecutableObjectIF { class PersistentSingleTmStoreTask : public TmStoreTaskBase, public ExecutableObjectIF {
public: public:
@ -17,12 +17,15 @@ class PersistentSingleTmStoreTask : public TmStoreTaskBase, public ExecutableObj
ReturnValue_t performOperation(uint8_t opCode) override; ReturnValue_t performOperation(uint8_t opCode) override;
private: private:
ModeHelper modeHelper;
PersistentTmStoreWithTmQueue& storeWithQueue; PersistentTmStoreWithTmQueue& storeWithQueue;
DumpContext dumpContext; DumpContext dumpContext;
Countdown tcHandlingCd = Countdown(400); Countdown tcHandlingCd = Countdown(400);
Countdown graceDelayDuringDumping = Countdown(100); Countdown graceDelayDuringDumping = Countdown(100);
bool initStoresIfPossible() override; bool initStoresIfPossible() override;
void startTransition(Mode_t mode, Submode_t submode) override;
}; };
#endif /* MISSION_TMTC_PERSISTENTSINGLETMSTORETASK_H_ */ #endif /* MISSION_TMTC_PERSISTENTSINGLETMSTORETASK_H_ */

View File

@ -1,6 +1,8 @@
#include "TmStoreTaskBase.h" #include "TmStoreTaskBase.h"
#include <fsfw/ipc/CommandMessageIF.h> #include <fsfw/ipc/CommandMessageIF.h>
#include <fsfw/ipc/QueueFactory.h>
#include <fsfw/subsystem/helper.h>
#include <fsfw/tasks/TaskFactory.h> #include <fsfw/tasks/TaskFactory.h>
#include <fsfw/timemanager/Stopwatch.h> #include <fsfw/timemanager/Stopwatch.h>
#include <fsfw/tmstorage/TmStoreMessage.h> #include <fsfw/tmstorage/TmStoreMessage.h>
@ -9,7 +11,13 @@
TmStoreTaskBase::TmStoreTaskBase(object_id_t objectId, StorageManagerIF& ipcStore, TmStoreTaskBase::TmStoreTaskBase(object_id_t objectId, StorageManagerIF& ipcStore,
VirtualChannel& channel, SdCardMountedIF& sdcMan) VirtualChannel& channel, SdCardMountedIF& sdcMan)
: SystemObject(objectId), ipcStore(ipcStore), channel(channel), sdcMan(sdcMan) {} : SystemObject(objectId),
modeHelper(this),
ipcStore(ipcStore),
channel(channel),
sdcMan(sdcMan) {
requestQueue = QueueFactory::instance()->createMessageQueue(10);
}
bool TmStoreTaskBase::handleOneStore(PersistentTmStoreWithTmQueue& store, bool TmStoreTaskBase::handleOneStore(PersistentTmStoreWithTmQueue& store,
DumpContext& dumpContext) { DumpContext& dumpContext) {
@ -26,8 +34,8 @@ bool TmStoreTaskBase::handleOneStore(PersistentTmStoreWithTmQueue& store,
if (result == returnvalue::OK) { if (result == returnvalue::OK) {
tmToStoreReceived = true; tmToStoreReceived = true;
} }
// Dump TMs when applicable // Dump TMs when applicable and allowed (mode is on)
if (store.getState() == PersistentTmStore::State::DUMPING) { if (mode == MODE_ON and store.getState() == PersistentTmStore::State::DUMPING) {
if (handleOneDump(store, dumpContext, dumpPerformed) != returnvalue::OK) { if (handleOneDump(store, dumpContext, dumpPerformed) != returnvalue::OK) {
return result; return result;
} }
@ -129,3 +137,57 @@ ReturnValue_t TmStoreTaskBase::handleOneDump(PersistentTmStoreWithTmQueue& store
} }
return result; return result;
} }
ReturnValue_t TmStoreTaskBase::initialize() {
modeHelper.initialize();
return returnvalue::OK;
}
void TmStoreTaskBase::getMode(Mode_t* mode, Submode_t* submode) {
if (mode != nullptr) {
*mode = this->mode;
}
if (submode != nullptr) {
*submode = SUBMODE_NONE;
}
}
ReturnValue_t TmStoreTaskBase::checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t* msToReachTheMode) {
if (mode == MODE_ON or mode == MODE_OFF) {
return returnvalue::OK;
}
return returnvalue::FAILED;
}
MessageQueueId_t TmStoreTaskBase::getCommandQueue() const { return requestQueue->getId(); }
void TmStoreTaskBase::announceMode(bool recursive) { triggerEvent(MODE_INFO, mode, SUBMODE_NONE); }
object_id_t TmStoreTaskBase::getObjectId() const { return SystemObject::getObjectId(); }
const HasHealthIF* TmStoreTaskBase::getOptHealthIF() const { return nullptr; }
const HasModesIF& TmStoreTaskBase::getModeIF() const { return *this; }
ReturnValue_t TmStoreTaskBase::connectModeTreeParent(HasModeTreeChildrenIF& parent) {
return modetree::connectModeTreeParent(parent, *this, nullptr, modeHelper);
}
ModeTreeChildIF& TmStoreTaskBase::getModeTreeChildIF() { return *this; }
void TmStoreTaskBase::readCommandQueue(void) {
CommandMessage commandMessage;
ReturnValue_t result = returnvalue::FAILED;
result = requestQueue->receiveMessage(&commandMessage);
if (result == returnvalue::OK) {
result = modeHelper.handleModeCommand(&commandMessage);
if (result == returnvalue::OK) {
return;
}
CommandMessage reply;
reply.setReplyRejected(CommandMessage::UNKNOWN_COMMAND, commandMessage.getCommand());
requestQueue->reply(&reply);
return;
}
}

View File

@ -1,15 +1,21 @@
#ifndef MISSION_TMTC_TMSTORETASKBASE_H_ #ifndef MISSION_TMTC_TMSTORETASKBASE_H_
#define MISSION_TMTC_TMSTORETASKBASE_H_ #define MISSION_TMTC_TMSTORETASKBASE_H_
#include <fsfw/modes/HasModesIF.h>
#include <fsfw/subsystem/ModeTreeChildIF.h>
#include <fsfw/subsystem/ModeTreeConnectionIF.h>
#include <fsfw/timemanager/Countdown.h> #include <fsfw/timemanager/Countdown.h>
#include <mission/com/VirtualChannel.h>
#include <mission/tmtc/PersistentTmStoreWithTmQueue.h> #include <mission/tmtc/PersistentTmStoreWithTmQueue.h>
#include <mission/tmtc/VirtualChannel.h>
/** /**
* Generic class which composes a Virtual Channel and a persistent TM stores. This allows dumping * Generic class which composes a Virtual Channel and a persistent TM stores. This allows dumping
* the TM store into the virtual channel directly. * the TM store into the virtual channel directly.
*/ */
class TmStoreTaskBase : public SystemObject { class TmStoreTaskBase : public SystemObject,
public HasModesIF,
public ModeTreeChildIF,
public ModeTreeConnectionIF {
public: public:
struct DumpContext { struct DumpContext {
DumpContext(Event eventIfDone, Event eventIfCancelled) DumpContext(Event eventIfDone, Event eventIfCancelled)
@ -35,8 +41,13 @@ class TmStoreTaskBase : public SystemObject {
TmStoreTaskBase(object_id_t objectId, StorageManagerIF& ipcStore, VirtualChannel& channel, TmStoreTaskBase(object_id_t objectId, StorageManagerIF& ipcStore, VirtualChannel& channel,
SdCardMountedIF& sdcMan); SdCardMountedIF& sdcMan);
ReturnValue_t initialize() override;
protected: protected:
MessageQueueIF* requestQueue;
ModeHelper modeHelper;
StorageManagerIF& ipcStore; StorageManagerIF& ipcStore;
Mode_t mode = HasModesIF::MODE_OFF;
Countdown sdCardCheckCd = Countdown(800); Countdown sdCardCheckCd = Countdown(800);
// 20 minutes are allowed as maximum dump time. // 20 minutes are allowed as maximum dump time.
Countdown cancelDumpCd = Countdown(60 * 20 * 1000); Countdown cancelDumpCd = Countdown(60 * 20 * 1000);
@ -47,6 +58,11 @@ class TmStoreTaskBase : public SystemObject {
bool fileHasSwapped = false; bool fileHasSwapped = false;
SdCardMountedIF& sdcMan; SdCardMountedIF& sdcMan;
void readCommandQueue(void);
virtual bool initStoresIfPossible() = 0;
virtual void startTransition(Mode_t mode, Submode_t submode) = 0;
void cancelDump(DumpContext& ctx, PersistentTmStore& store, bool isTxOn); void cancelDump(DumpContext& ctx, PersistentTmStore& store, bool isTxOn);
/** /**
* *
@ -65,7 +81,18 @@ class TmStoreTaskBase : public SystemObject {
*/ */
bool cyclicStoreCheck(); bool cyclicStoreCheck();
virtual bool initStoresIfPossible() = 0; MessageQueueId_t getCommandQueue() const override;
void getMode(Mode_t* mode, Submode_t* submode) override;
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t* msToReachTheMode) override;
void announceMode(bool recursive) override;
object_id_t getObjectId() const override;
const HasHealthIF* getOptHealthIF() const override;
const HasModesIF& getModeIF() const override;
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF& parent) override;
ModeTreeChildIF& getModeTreeChildIF() override;
}; };
#endif /* MISSION_TMTC_TMSTORETASKBASE_H_ */ #endif /* MISSION_TMTC_TMSTORETASKBASE_H_ */

View File

@ -1,4 +1,4 @@
#include <mission/tmtc/VirtualChannelWithQueue.h> #include "VirtualChannelWithQueue.h"
#include "OBSWConfig.h" #include "OBSWConfig.h"
#include "fsfw/ipc/QueueFactory.h" #include "fsfw/ipc/QueueFactory.h"
@ -19,7 +19,7 @@ VirtualChannelWithQueue::VirtualChannelWithQueue(object_id_t objectId, uint8_t v
const char* VirtualChannelWithQueue::getName() const { return VirtualChannel::getName(); } const char* VirtualChannelWithQueue::getName() const { return VirtualChannel::getName(); }
ReturnValue_t VirtualChannelWithQueue::sendNextTm() { ReturnValue_t VirtualChannelWithQueue::handleNextTm(bool performWriteOp) {
TmTcMessage message; TmTcMessage message;
ReturnValue_t result = tmQueue->receiveMessage(&message); ReturnValue_t result = tmQueue->receiveMessage(&message);
if (result == MessageQueueIF::EMPTY) { if (result == MessageQueueIF::EMPTY) {
@ -36,7 +36,9 @@ ReturnValue_t VirtualChannelWithQueue::sendNextTm() {
return result; return result;
} }
result = write(data, size); if (performWriteOp) {
result = write(data, size);
}
// Try delete in any case, ignore failures (which should not happen), it is more important to // Try delete in any case, ignore failures (which should not happen), it is more important to
// propagate write errors. // propagate write errors.
tmStore.deleteData(storeId); tmStore.deleteData(storeId);

View File

@ -4,7 +4,7 @@
#include <fsfw/objectmanager/SystemObject.h> #include <fsfw/objectmanager/SystemObject.h>
#include <fsfw/tasks/ExecutableObjectIF.h> #include <fsfw/tasks/ExecutableObjectIF.h>
#include <linux/ipcore/PtmeIF.h> #include <linux/ipcore/PtmeIF.h>
#include <mission/tmtc/VirtualChannel.h> #include <mission/com/VirtualChannel.h>
#include <atomic> #include <atomic>
@ -34,7 +34,7 @@ class VirtualChannelWithQueue : public VirtualChannel, public AcceptsTelemetryIF
MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel = 0) const override; MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel = 0) const override;
[[nodiscard]] const char* getName() const override; [[nodiscard]] const char* getName() const override;
ReturnValue_t sendNextTm(); ReturnValue_t handleNextTm(bool performWriteOp);
private: private:
MessageQueueIF* tmQueue = nullptr; MessageQueueIF* tmQueue = nullptr;

View File

@ -3,6 +3,8 @@
#include <fsfw/ipc/MutexFactory.h> #include <fsfw/ipc/MutexFactory.h>
#include <fsfw/ipc/MutexGuard.h> #include <fsfw/ipc/MutexGuard.h>
#include <atomic>
com::Datarate DATARATE_CFG_RAW = com::Datarate::LOW_RATE_MODULATION_BPSK; com::Datarate DATARATE_CFG_RAW = com::Datarate::LOW_RATE_MODULATION_BPSK;
MutexIF* DATARATE_LOCK = nullptr; MutexIF* DATARATE_LOCK = nullptr;

View File

@ -22,7 +22,7 @@ auto COM_SEQUENCE_RX_ONLY =
auto COM_TABLE_RX_ONLY_TGT = std::make_pair( auto COM_TABLE_RX_ONLY_TGT = std::make_pair(
static_cast<uint32_t>(::com::Submode::RX_ONLY << 24) | 1, FixedArrayList<ModeListEntry, 3>()); static_cast<uint32_t>(::com::Submode::RX_ONLY << 24) | 1, FixedArrayList<ModeListEntry, 3>());
auto COM_TABLE_RX_ONLY_TRANS_0 = std::make_pair( auto COM_TABLE_RX_ONLY_TRANS_0 = std::make_pair(
static_cast<uint32_t>(::com::Submode::RX_ONLY << 24) | 2, FixedArrayList<ModeListEntry, 3>()); static_cast<uint32_t>(::com::Submode::RX_ONLY << 24) | 2, FixedArrayList<ModeListEntry, 6>());
auto COM_TABLE_RX_ONLY_TRANS_1 = std::make_pair( auto COM_TABLE_RX_ONLY_TRANS_1 = std::make_pair(
static_cast<uint32_t>(::com::Submode::RX_ONLY << 24) | 3, FixedArrayList<ModeListEntry, 3>()); static_cast<uint32_t>(::com::Submode::RX_ONLY << 24) | 3, FixedArrayList<ModeListEntry, 3>());
@ -36,7 +36,7 @@ auto COM_TABLE_RX_AND_TX_LOW_RATE_TRANS_0 =
FixedArrayList<ModeListEntry, 3>()); FixedArrayList<ModeListEntry, 3>());
auto COM_TABLE_RX_AND_TX_LOW_RATE_TRANS_1 = auto COM_TABLE_RX_AND_TX_LOW_RATE_TRANS_1 =
std::make_pair(static_cast<uint32_t>(::com::Submode::RX_AND_TX_LOW_DATARATE << 24) | 3, std::make_pair(static_cast<uint32_t>(::com::Submode::RX_AND_TX_LOW_DATARATE << 24) | 3,
FixedArrayList<ModeListEntry, 3>()); FixedArrayList<ModeListEntry, 6>());
auto COM_SEQUENCE_RX_AND_TX_HIGH_RATE = auto COM_SEQUENCE_RX_AND_TX_HIGH_RATE =
std::make_pair(::com::Submode::RX_AND_TX_HIGH_DATARATE, FixedArrayList<ModeListEntry, 3>()); std::make_pair(::com::Submode::RX_AND_TX_HIGH_DATARATE, FixedArrayList<ModeListEntry, 3>());
@ -48,7 +48,7 @@ auto COM_TABLE_RX_AND_TX_HIGH_RATE_TRANS_0 =
FixedArrayList<ModeListEntry, 3>()); FixedArrayList<ModeListEntry, 3>());
auto COM_TABLE_RX_AND_TX_HIGH_RATE_TRANS_1 = auto COM_TABLE_RX_AND_TX_HIGH_RATE_TRANS_1 =
std::make_pair(static_cast<uint32_t>(::com::Submode::RX_AND_TX_HIGH_DATARATE << 24) | 3, std::make_pair(static_cast<uint32_t>(::com::Submode::RX_AND_TX_HIGH_DATARATE << 24) | 3,
FixedArrayList<ModeListEntry, 3>()); FixedArrayList<ModeListEntry, 6>());
auto COM_SEQUENCE_RX_AND_TX_DEFAULT_RATE = auto COM_SEQUENCE_RX_AND_TX_DEFAULT_RATE =
std::make_pair(::com::Submode::RX_AND_TX_DEFAULT_DATARATE, FixedArrayList<ModeListEntry, 3>()); std::make_pair(::com::Submode::RX_AND_TX_DEFAULT_DATARATE, FixedArrayList<ModeListEntry, 3>());
@ -60,7 +60,7 @@ auto COM_TABLE_RX_AND_TX_DEFAULT_RATE_TRANS_0 =
FixedArrayList<ModeListEntry, 3>()); FixedArrayList<ModeListEntry, 3>());
auto COM_TABLE_RX_AND_TX_DEFAULT_RATE_TRANS_1 = auto COM_TABLE_RX_AND_TX_DEFAULT_RATE_TRANS_1 =
std::make_pair(static_cast<uint32_t>(::com::Submode::RX_AND_TX_DEFAULT_DATARATE << 24) | 3, std::make_pair(static_cast<uint32_t>(::com::Submode::RX_AND_TX_DEFAULT_DATARATE << 24) | 3,
FixedArrayList<ModeListEntry, 3>()); FixedArrayList<ModeListEntry, 6>());
namespace { namespace {
@ -110,6 +110,10 @@ void buildRxOnlySequence(Subsystem& ss, ModeListEntry& eh) {
// Build RX Only transition 0 // Build RX Only transition 0
iht(objects::SYRLINKS_ASSY, NML, ::com::Submode::RX_ONLY, COM_TABLE_RX_ONLY_TRANS_0.second); iht(objects::SYRLINKS_ASSY, NML, ::com::Submode::RX_ONLY, COM_TABLE_RX_ONLY_TRANS_0.second);
iht(objects::LOG_STORE_AND_TM_TASK, OFF, 0, COM_TABLE_RX_ONLY_TRANS_0.second);
iht(objects::HK_STORE_AND_TM_TASK, OFF, 0, COM_TABLE_RX_ONLY_TRANS_0.second);
iht(objects::CFDP_STORE_AND_TM_TASK, OFF, 0, COM_TABLE_RX_ONLY_TRANS_0.second);
iht(objects::LIVE_TM_TASK, OFF, 0, COM_TABLE_RX_ONLY_TRANS_0.second);
check(ss.addTable(TableEntry(COM_TABLE_RX_ONLY_TRANS_0.first, &COM_TABLE_RX_ONLY_TRANS_0.second)), check(ss.addTable(TableEntry(COM_TABLE_RX_ONLY_TRANS_0.first, &COM_TABLE_RX_ONLY_TRANS_0.second)),
ctxc); ctxc);
@ -165,6 +169,10 @@ void buildTxAndRxLowRateSequence(Subsystem& ss, ModeListEntry& eh) {
// Build TX and RX low transition 1 // Build TX and RX low transition 1
iht(objects::SYRLINKS_ASSY, NML, ::com::Submode::RX_AND_TX_LOW_DATARATE, iht(objects::SYRLINKS_ASSY, NML, ::com::Submode::RX_AND_TX_LOW_DATARATE,
COM_TABLE_RX_AND_TX_LOW_RATE_TRANS_1.second); COM_TABLE_RX_AND_TX_LOW_RATE_TRANS_1.second);
iht(objects::LOG_STORE_AND_TM_TASK, ON, 0, COM_TABLE_RX_AND_TX_LOW_RATE_TRANS_1.second);
iht(objects::HK_STORE_AND_TM_TASK, ON, 0, COM_TABLE_RX_AND_TX_LOW_RATE_TRANS_1.second);
iht(objects::CFDP_STORE_AND_TM_TASK, ON, 0, COM_TABLE_RX_AND_TX_LOW_RATE_TRANS_1.second);
iht(objects::LIVE_TM_TASK, ON, 0, COM_TABLE_RX_AND_TX_LOW_RATE_TRANS_1.second);
check(ss.addTable(TableEntry(COM_TABLE_RX_AND_TX_LOW_RATE_TRANS_1.first, check(ss.addTable(TableEntry(COM_TABLE_RX_AND_TX_LOW_RATE_TRANS_1.first,
&COM_TABLE_RX_AND_TX_LOW_RATE_TRANS_1.second)), &COM_TABLE_RX_AND_TX_LOW_RATE_TRANS_1.second)),
ctxc); ctxc);
@ -217,6 +225,10 @@ void buildTxAndRxHighRateSequence(Subsystem& ss, ModeListEntry& eh) {
// Build TX and RX high transition 1 // Build TX and RX high transition 1
iht(objects::SYRLINKS_ASSY, NML, ::com::Submode::RX_AND_TX_HIGH_DATARATE, iht(objects::SYRLINKS_ASSY, NML, ::com::Submode::RX_AND_TX_HIGH_DATARATE,
COM_TABLE_RX_AND_TX_HIGH_RATE_TRANS_1.second); COM_TABLE_RX_AND_TX_HIGH_RATE_TRANS_1.second);
iht(objects::LOG_STORE_AND_TM_TASK, ON, 0, COM_TABLE_RX_AND_TX_HIGH_RATE_TRANS_1.second);
iht(objects::HK_STORE_AND_TM_TASK, ON, 0, COM_TABLE_RX_AND_TX_HIGH_RATE_TRANS_1.second);
iht(objects::CFDP_STORE_AND_TM_TASK, ON, 0, COM_TABLE_RX_AND_TX_HIGH_RATE_TRANS_1.second);
iht(objects::LIVE_TM_TASK, ON, 0, COM_TABLE_RX_AND_TX_HIGH_RATE_TRANS_1.second);
check(ss.addTable(TableEntry(COM_TABLE_RX_AND_TX_HIGH_RATE_TRANS_1.first, check(ss.addTable(TableEntry(COM_TABLE_RX_AND_TX_HIGH_RATE_TRANS_1.first,
&COM_TABLE_RX_AND_TX_HIGH_RATE_TRANS_1.second)), &COM_TABLE_RX_AND_TX_HIGH_RATE_TRANS_1.second)),
ctxc); ctxc);
@ -271,6 +283,10 @@ void buildTxAndRxDefaultRateSequence(Subsystem& ss, ModeListEntry& eh) {
// Build TX and RX default transition 1 // Build TX and RX default transition 1
iht(objects::SYRLINKS_ASSY, NML, ::com::Submode::RX_AND_TX_DEFAULT_DATARATE, iht(objects::SYRLINKS_ASSY, NML, ::com::Submode::RX_AND_TX_DEFAULT_DATARATE,
COM_TABLE_RX_AND_TX_DEFAULT_RATE_TRANS_1.second); COM_TABLE_RX_AND_TX_DEFAULT_RATE_TRANS_1.second);
iht(objects::LOG_STORE_AND_TM_TASK, ON, 0, COM_TABLE_RX_AND_TX_DEFAULT_RATE_TRANS_1.second);
iht(objects::HK_STORE_AND_TM_TASK, ON, 0, COM_TABLE_RX_AND_TX_DEFAULT_RATE_TRANS_1.second);
iht(objects::CFDP_STORE_AND_TM_TASK, ON, 0, COM_TABLE_RX_AND_TX_DEFAULT_RATE_TRANS_1.second);
iht(objects::LIVE_TM_TASK, ON, 0, COM_TABLE_RX_AND_TX_DEFAULT_RATE_TRANS_1.second);
check(ss.addTable(TableEntry(COM_TABLE_RX_AND_TX_DEFAULT_RATE_TRANS_1.first, check(ss.addTable(TableEntry(COM_TABLE_RX_AND_TX_DEFAULT_RATE_TRANS_1.first,
&COM_TABLE_RX_AND_TX_DEFAULT_RATE_TRANS_1.second)), &COM_TABLE_RX_AND_TX_DEFAULT_RATE_TRANS_1.second)),
ctxc); ctxc);

View File

@ -1,17 +1,11 @@
target_sources( target_sources(
${LIB_EIVE_MISSION} ${LIB_EIVE_MISSION}
PRIVATE VirtualChannelWithQueue.cpp PRIVATE PersistentTmStoreWithTmQueue.cpp
PersistentTmStoreWithTmQueue.cpp
LiveTmTask.cpp
VirtualChannel.cpp
TmFunnelHandler.cpp TmFunnelHandler.cpp
TmFunnelBase.cpp TmFunnelBase.cpp
CfdpTmFunnel.cpp CfdpTmFunnel.cpp
tmFilters.cpp tmFilters.cpp
PusLiveDemux.cpp PusLiveDemux.cpp
PersistentSingleTmStoreTask.cpp
PersistentLogTmStoreTask.cpp
TmStoreTaskBase.cpp
PusPacketFilter.cpp PusPacketFilter.cpp
PusTmRouteByFilterHelper.cpp PusTmRouteByFilterHelper.cpp
Service15TmStorage.cpp Service15TmStorage.cpp

View File

@ -1,27 +0,0 @@
#include "LiveTmTask.h"
#include <fsfw/tasks/TaskFactory.h>
#include <fsfw/timemanager/Stopwatch.h>
LiveTmTask::LiveTmTask(object_id_t objectId, PusTmFunnel& pusFunnel, CfdpTmFunnel& cfdpFunnel,
VirtualChannelWithQueue& channel)
: SystemObject(objectId), pusFunnel(pusFunnel), cfdpFunnel(cfdpFunnel), channel(channel) {}
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);
cfdpFunnel.performOperation(0);
tmFunnelCd.resetTimer();
}
// 40 ms IDLE delay. Might tweak this in the future.
TaskFactory::delayTask(40);
}
}
}

View File

@ -1,25 +0,0 @@
#ifndef MISSION_TMTC_LIVETMTASK_H_
#define MISSION_TMTC_LIVETMTASK_H_
#include <fsfw/objectmanager/SystemObject.h>
#include <fsfw/tasks/ExecutableObjectIF.h>
#include <fsfw/timemanager/Countdown.h>
#include <mission/tmtc/CfdpTmFunnel.h>
#include <mission/tmtc/PusTmFunnel.h>
#include <mission/tmtc/VirtualChannelWithQueue.h>
class LiveTmTask : public SystemObject, public ExecutableObjectIF {
public:
LiveTmTask(object_id_t objectId, PusTmFunnel& pusFunnel, CfdpTmFunnel& cfdpFunnel,
VirtualChannelWithQueue& channel);
ReturnValue_t performOperation(uint8_t opCode) override;
private:
Countdown tmFunnelCd = Countdown(100);
PusTmFunnel& pusFunnel;
CfdpTmFunnel& cfdpFunnel;
VirtualChannelWithQueue& channel;
};
#endif /* MISSION_TMTC_LIVETMTASK_H_ */