PTME rework reset handling #542
@ -19,6 +19,10 @@ will consitute of a breaking change warranting a new major release:
|
||||
## Changed
|
||||
|
||||
- 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
|
||||
|
||||
|
@ -20,15 +20,15 @@
|
||||
#include <mission/acs/MgmRm3100CustomHandler.h>
|
||||
#include <mission/acs/str/StarTrackerHandler.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/system/acs/ImtqAssembly.h>
|
||||
#include <mission/system/acs/StrAssembly.h>
|
||||
#include <mission/system/fdir/StrFdir.h>
|
||||
#include <mission/system/objects/CamSwitcher.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"
|
||||
@ -81,6 +81,7 @@ using gpio::Levels;
|
||||
#include <mission/acs/ImtqHandler.h>
|
||||
#include <mission/acs/rwHelpers.h>
|
||||
#include <mission/com/SyrlinksHandler.h>
|
||||
#include <mission/com/VirtualChannelWithQueue.h>
|
||||
#include <mission/payload/PayloadPcduHandler.h>
|
||||
#include <mission/payload/RadiationSensorHandler.h>
|
||||
#include <mission/payload/payloadPcduDefinitions.h>
|
||||
@ -96,7 +97,6 @@ using gpio::Levels;
|
||||
#include <mission/tcs/Max31865Definitions.h>
|
||||
#include <mission/tcs/Max31865PT1000Handler.h>
|
||||
#include <mission/tcs/Tmp1075Handler.h>
|
||||
#include <mission/tmtc/VirtualChannelWithQueue.h>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
|
@ -4,11 +4,11 @@
|
||||
#include <fsfw/returnvalues/returnvalue.h>
|
||||
#include <fsfw_hal/linux/spi/SpiComIF.h>
|
||||
#include <mission/com/CcsdsIpCoreHandler.h>
|
||||
#include <mission/com/PersistentLogTmStoreTask.h>
|
||||
#include <mission/genericFactory.h>
|
||||
#include <mission/system/objects/Stack5VHandler.h>
|
||||
#include <mission/tcs/HeaterHandler.h>
|
||||
#include <mission/tmtc/CfdpTmFunnel.h>
|
||||
#include <mission/tmtc/PersistentLogTmStoreTask.h>
|
||||
#include <mission/tmtc/PusTmFunnel.h>
|
||||
|
||||
#include <atomic>
|
||||
|
@ -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
|
||||
// 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.
|
||||
nanosleep(&BETWEEN_POLL_DELAY, &remDelay);
|
||||
// nanosleep(&BETWEEN_POLL_DELAY, &remDelay);
|
||||
if (pollPapbBusySignal(2) == returnvalue::OK) {
|
||||
*(vcBaseReg + DATA_REG_OFFSET) = static_cast<uint32_t>(data[idx]);
|
||||
} else {
|
||||
@ -46,7 +46,7 @@ ReturnValue_t PapbVcInterface::write(const uint8_t* data, size_t size) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
}
|
||||
nanosleep(&BETWEEN_POLL_DELAY, &remDelay);
|
||||
// nanosleep(&BETWEEN_POLL_DELAY, &remDelay);
|
||||
if (pollPapbBusySignal(2) == returnvalue::OK) {
|
||||
completePacketTransfer();
|
||||
} else {
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include <fsfw_hal/linux/gpio/LinuxLibgpioIF.h>
|
||||
#include <linux/ipcore/VirtualChannelIF.h>
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "fsfw/returnvalues/returnvalue.h"
|
||||
|
||||
|
@ -1,2 +1,11 @@
|
||||
target_sources(${LIB_EIVE_MISSION} PRIVATE SyrlinksHandler.cpp
|
||||
CcsdsIpCoreHandler.cpp)
|
||||
target_sources(
|
||||
${LIB_EIVE_MISSION}
|
||||
PRIVATE SyrlinksHandler.cpp
|
||||
CcsdsIpCoreHandler.cpp
|
||||
LiveTmTask.cpp
|
||||
PersistentLogTmStoreTask.cpp
|
||||
TmStoreTaskBase.cpp
|
||||
VirtualChannel.cpp
|
||||
VirtualChannelWithQueue.cpp
|
||||
PersistentSingleTmStoreTask.cpp
|
||||
LiveTmTask.cpp)
|
||||
|
@ -2,7 +2,7 @@
|
||||
#define CCSDSHANDLER_H_
|
||||
|
||||
#include <fsfw/modes/HasModesIF.h>
|
||||
#include <mission/tmtc/VirtualChannelWithQueue.h>
|
||||
#include <mission/com/VirtualChannelWithQueue.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <unordered_map>
|
||||
|
101
mission/com/LiveTmTask.cpp
Normal file
101
mission/com/LiveTmTask.cpp
Normal 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
55
mission/com/LiveTmTask.h
Normal 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_ */
|
@ -27,6 +27,8 @@ ReturnValue_t PersistentLogTmStoreTask::performOperation(uint8_t opCode) {
|
||||
}
|
||||
};
|
||||
while (true) {
|
||||
readCommandQueue();
|
||||
|
||||
if (not cyclicStoreCheck()) {
|
||||
continue;
|
||||
}
|
||||
@ -54,3 +56,17 @@ bool PersistentLogTmStoreTask::initStoresIfPossible() {
|
||||
}
|
||||
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);
|
||||
}
|
@ -5,11 +5,11 @@
|
||||
#include <fsfw/storagemanager/StorageManagerIF.h>
|
||||
#include <fsfw/tasks/ExecutableObjectIF.h>
|
||||
#include <fsfw/tmtcservices/AcceptsTelemetryIF.h>
|
||||
#include <mission/com/TmStoreTaskBase.h>
|
||||
#include <mission/com/VirtualChannelWithQueue.h>
|
||||
#include <mission/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)
|
||||
@ -36,6 +36,7 @@ class PersistentLogTmStoreTask : public TmStoreTaskBase, public ExecutableObject
|
||||
bool someFileWasSwapped = false;
|
||||
|
||||
bool initStoresIfPossible() override;
|
||||
void startTransition(Mode_t mode, Submode_t submode) override;
|
||||
};
|
||||
|
||||
#endif /* MISSION_TMTC_PERSISTENTLOGTMSTORETASK_H_ */
|
@ -1,17 +1,21 @@
|
||||
#include "PersistentSingleTmStoreTask.h"
|
||||
|
||||
#include <fsfw/tasks/TaskFactory.h>
|
||||
#include <fsfw/timemanager/Stopwatch.h>
|
||||
#include <mission/tmtc/PersistentSingleTmStoreTask.h>
|
||||
#include <unistd.h>
|
||||
|
||||
PersistentSingleTmStoreTask::PersistentSingleTmStoreTask(
|
||||
object_id_t objectId, StorageManagerIF& ipcStore, PersistentTmStoreWithTmQueue& tmStore,
|
||||
VirtualChannel& channel, Event eventIfDumpDone, Event eventIfCancelled, SdCardMountedIF& sdcMan)
|
||||
: TmStoreTaskBase(objectId, ipcStore, channel, sdcMan),
|
||||
modeHelper(this),
|
||||
storeWithQueue(tmStore),
|
||||
dumpContext(eventIfDumpDone, eventIfCancelled) {}
|
||||
|
||||
ReturnValue_t PersistentSingleTmStoreTask::performOperation(uint8_t opCode) {
|
||||
while (true) {
|
||||
readCommandQueue();
|
||||
|
||||
// Delay done by the check
|
||||
if (not cyclicStoreCheck()) {
|
||||
continue;
|
||||
@ -33,3 +37,14 @@ bool PersistentSingleTmStoreTask::initStoresIfPossible() {
|
||||
}
|
||||
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);
|
||||
}
|
@ -3,9 +3,9 @@
|
||||
|
||||
#include <fsfw/objectmanager/SystemObject.h>
|
||||
#include <fsfw/tasks/ExecutableObjectIF.h>
|
||||
#include <mission/com/TmStoreTaskBase.h>
|
||||
#include <mission/com/VirtualChannel.h>
|
||||
#include <mission/tmtc/PersistentTmStoreWithTmQueue.h>
|
||||
#include <mission/tmtc/TmStoreTaskBase.h>
|
||||
#include <mission/tmtc/VirtualChannel.h>
|
||||
|
||||
class PersistentSingleTmStoreTask : public TmStoreTaskBase, public ExecutableObjectIF {
|
||||
public:
|
||||
@ -17,12 +17,15 @@ class PersistentSingleTmStoreTask : public TmStoreTaskBase, public ExecutableObj
|
||||
ReturnValue_t performOperation(uint8_t opCode) override;
|
||||
|
||||
private:
|
||||
ModeHelper modeHelper;
|
||||
PersistentTmStoreWithTmQueue& storeWithQueue;
|
||||
DumpContext dumpContext;
|
||||
Countdown tcHandlingCd = Countdown(400);
|
||||
Countdown graceDelayDuringDumping = Countdown(100);
|
||||
|
||||
bool initStoresIfPossible() override;
|
||||
|
||||
void startTransition(Mode_t mode, Submode_t submode) override;
|
||||
};
|
||||
|
||||
#endif /* MISSION_TMTC_PERSISTENTSINGLETMSTORETASK_H_ */
|
@ -1,6 +1,8 @@
|
||||
#include "TmStoreTaskBase.h"
|
||||
|
||||
#include <fsfw/ipc/CommandMessageIF.h>
|
||||
#include <fsfw/ipc/QueueFactory.h>
|
||||
#include <fsfw/subsystem/helper.h>
|
||||
#include <fsfw/tasks/TaskFactory.h>
|
||||
#include <fsfw/timemanager/Stopwatch.h>
|
||||
#include <fsfw/tmstorage/TmStoreMessage.h>
|
||||
@ -9,7 +11,13 @@
|
||||
|
||||
TmStoreTaskBase::TmStoreTaskBase(object_id_t objectId, StorageManagerIF& ipcStore,
|
||||
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,
|
||||
DumpContext& dumpContext) {
|
||||
@ -26,8 +34,8 @@ bool TmStoreTaskBase::handleOneStore(PersistentTmStoreWithTmQueue& store,
|
||||
if (result == returnvalue::OK) {
|
||||
tmToStoreReceived = true;
|
||||
}
|
||||
// Dump TMs when applicable
|
||||
if (store.getState() == PersistentTmStore::State::DUMPING) {
|
||||
// Dump TMs when applicable and allowed (mode is on)
|
||||
if (mode == MODE_ON and store.getState() == PersistentTmStore::State::DUMPING) {
|
||||
if (handleOneDump(store, dumpContext, dumpPerformed) != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
@ -129,3 +137,57 @@ ReturnValue_t TmStoreTaskBase::handleOneDump(PersistentTmStoreWithTmQueue& store
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
@ -1,15 +1,21 @@
|
||||
#ifndef 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 <mission/com/VirtualChannel.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
|
||||
* the TM store into the virtual channel directly.
|
||||
*/
|
||||
class TmStoreTaskBase : public SystemObject {
|
||||
class TmStoreTaskBase : public SystemObject,
|
||||
public HasModesIF,
|
||||
public ModeTreeChildIF,
|
||||
public ModeTreeConnectionIF {
|
||||
public:
|
||||
struct DumpContext {
|
||||
DumpContext(Event eventIfDone, Event eventIfCancelled)
|
||||
@ -35,8 +41,13 @@ class TmStoreTaskBase : public SystemObject {
|
||||
TmStoreTaskBase(object_id_t objectId, StorageManagerIF& ipcStore, VirtualChannel& channel,
|
||||
SdCardMountedIF& sdcMan);
|
||||
|
||||
ReturnValue_t initialize() override;
|
||||
|
||||
protected:
|
||||
MessageQueueIF* requestQueue;
|
||||
ModeHelper modeHelper;
|
||||
StorageManagerIF& ipcStore;
|
||||
Mode_t mode = HasModesIF::MODE_OFF;
|
||||
Countdown sdCardCheckCd = Countdown(800);
|
||||
// 20 minutes are allowed as maximum dump time.
|
||||
Countdown cancelDumpCd = Countdown(60 * 20 * 1000);
|
||||
@ -47,6 +58,11 @@ class TmStoreTaskBase : public SystemObject {
|
||||
bool fileHasSwapped = false;
|
||||
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);
|
||||
/**
|
||||
*
|
||||
@ -65,7 +81,18 @@ class TmStoreTaskBase : public SystemObject {
|
||||
*/
|
||||
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_ */
|
@ -1,4 +1,4 @@
|
||||
#include <mission/tmtc/VirtualChannelWithQueue.h>
|
||||
#include "VirtualChannelWithQueue.h"
|
||||
|
||||
#include "OBSWConfig.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(); }
|
||||
|
||||
ReturnValue_t VirtualChannelWithQueue::sendNextTm() {
|
||||
ReturnValue_t VirtualChannelWithQueue::handleNextTm(bool performWriteOp) {
|
||||
TmTcMessage message;
|
||||
ReturnValue_t result = tmQueue->receiveMessage(&message);
|
||||
if (result == MessageQueueIF::EMPTY) {
|
||||
@ -36,7 +36,9 @@ ReturnValue_t VirtualChannelWithQueue::sendNextTm() {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (performWriteOp) {
|
||||
result = write(data, size);
|
||||
}
|
||||
// Try delete in any case, ignore failures (which should not happen), it is more important to
|
||||
// propagate write errors.
|
||||
tmStore.deleteData(storeId);
|
@ -4,7 +4,7 @@
|
||||
#include <fsfw/objectmanager/SystemObject.h>
|
||||
#include <fsfw/tasks/ExecutableObjectIF.h>
|
||||
#include <linux/ipcore/PtmeIF.h>
|
||||
#include <mission/tmtc/VirtualChannel.h>
|
||||
#include <mission/com/VirtualChannel.h>
|
||||
|
||||
#include <atomic>
|
||||
|
||||
@ -34,7 +34,7 @@ class VirtualChannelWithQueue : public VirtualChannel, public AcceptsTelemetryIF
|
||||
|
||||
MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel = 0) const override;
|
||||
[[nodiscard]] const char* getName() const override;
|
||||
ReturnValue_t sendNextTm();
|
||||
ReturnValue_t handleNextTm(bool performWriteOp);
|
||||
|
||||
private:
|
||||
MessageQueueIF* tmQueue = nullptr;
|
@ -3,6 +3,8 @@
|
||||
#include <fsfw/ipc/MutexFactory.h>
|
||||
#include <fsfw/ipc/MutexGuard.h>
|
||||
|
||||
#include <atomic>
|
||||
|
||||
com::Datarate DATARATE_CFG_RAW = com::Datarate::LOW_RATE_MODULATION_BPSK;
|
||||
MutexIF* DATARATE_LOCK = nullptr;
|
||||
|
||||
|
@ -22,7 +22,7 @@ auto COM_SEQUENCE_RX_ONLY =
|
||||
auto COM_TABLE_RX_ONLY_TGT = std::make_pair(
|
||||
static_cast<uint32_t>(::com::Submode::RX_ONLY << 24) | 1, FixedArrayList<ModeListEntry, 3>());
|
||||
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(
|
||||
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>());
|
||||
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,
|
||||
FixedArrayList<ModeListEntry, 3>());
|
||||
FixedArrayList<ModeListEntry, 6>());
|
||||
|
||||
auto COM_SEQUENCE_RX_AND_TX_HIGH_RATE =
|
||||
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>());
|
||||
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,
|
||||
FixedArrayList<ModeListEntry, 3>());
|
||||
FixedArrayList<ModeListEntry, 6>());
|
||||
|
||||
auto COM_SEQUENCE_RX_AND_TX_DEFAULT_RATE =
|
||||
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>());
|
||||
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,
|
||||
FixedArrayList<ModeListEntry, 3>());
|
||||
FixedArrayList<ModeListEntry, 6>());
|
||||
|
||||
namespace {
|
||||
|
||||
@ -110,6 +110,10 @@ void buildRxOnlySequence(Subsystem& ss, ModeListEntry& eh) {
|
||||
|
||||
// Build RX Only transition 0
|
||||
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)),
|
||||
ctxc);
|
||||
|
||||
@ -165,6 +169,10 @@ void buildTxAndRxLowRateSequence(Subsystem& ss, ModeListEntry& eh) {
|
||||
// Build TX and RX low transition 1
|
||||
iht(objects::SYRLINKS_ASSY, NML, ::com::Submode::RX_AND_TX_LOW_DATARATE,
|
||||
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,
|
||||
&COM_TABLE_RX_AND_TX_LOW_RATE_TRANS_1.second)),
|
||||
ctxc);
|
||||
@ -217,6 +225,10 @@ void buildTxAndRxHighRateSequence(Subsystem& ss, ModeListEntry& eh) {
|
||||
// Build TX and RX high transition 1
|
||||
iht(objects::SYRLINKS_ASSY, NML, ::com::Submode::RX_AND_TX_HIGH_DATARATE,
|
||||
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,
|
||||
&COM_TABLE_RX_AND_TX_HIGH_RATE_TRANS_1.second)),
|
||||
ctxc);
|
||||
@ -271,6 +283,10 @@ void buildTxAndRxDefaultRateSequence(Subsystem& ss, ModeListEntry& eh) {
|
||||
// Build TX and RX default transition 1
|
||||
iht(objects::SYRLINKS_ASSY, NML, ::com::Submode::RX_AND_TX_DEFAULT_DATARATE,
|
||||
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,
|
||||
&COM_TABLE_RX_AND_TX_DEFAULT_RATE_TRANS_1.second)),
|
||||
ctxc);
|
||||
|
@ -1,17 +1,11 @@
|
||||
target_sources(
|
||||
${LIB_EIVE_MISSION}
|
||||
PRIVATE VirtualChannelWithQueue.cpp
|
||||
PersistentTmStoreWithTmQueue.cpp
|
||||
LiveTmTask.cpp
|
||||
VirtualChannel.cpp
|
||||
PRIVATE PersistentTmStoreWithTmQueue.cpp
|
||||
TmFunnelHandler.cpp
|
||||
TmFunnelBase.cpp
|
||||
CfdpTmFunnel.cpp
|
||||
tmFilters.cpp
|
||||
PusLiveDemux.cpp
|
||||
PersistentSingleTmStoreTask.cpp
|
||||
PersistentLogTmStoreTask.cpp
|
||||
TmStoreTaskBase.cpp
|
||||
PusPacketFilter.cpp
|
||||
PusTmRouteByFilterHelper.cpp
|
||||
Service15TmStorage.cpp
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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_ */
|
Loading…
Reference in New Issue
Block a user