PTME_LOCK atomic boolean and related handling
All checks were successful
EIVE/eive-obsw/pipeline/pr-develop This commit looks good

This commit is contained in:
Robin Müller 2023-03-31 16:51:30 +02:00
parent caa7c20adf
commit 55a22c840c
No known key found for this signature in database
GPG Key ID: 11D4952C8CCEF814
14 changed files with 165 additions and 102 deletions

View File

@ -23,6 +23,9 @@ will consitute of a breaking change warranting a new major release:
used to disable ongoing dumps or to prevent writes to the PTME VC. This allows cleaner reset 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 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. as part of the COM sequence as well to ensure consistent state with the CCSDS IP core handler.
- Added `PTME_LOCKED` boolean lock which is used to lock the PTME so it is not used by the VC tasks
anymore. This lock will be controlled by the CCSDS IP core handler and is locked when the PTME
needs to be reset. Examples for this are datarate changes.
## Fixed ## Fixed

View File

@ -125,6 +125,7 @@ using gpio::Levels;
ResetArgs RESET_ARGS_GNSS; ResetArgs RESET_ARGS_GNSS;
std::atomic_bool LINK_STATE = CcsdsIpCoreHandler::LINK_DOWN; std::atomic_bool LINK_STATE = CcsdsIpCoreHandler::LINK_DOWN;
std::atomic_bool PTME_LOCKED = false;
std::atomic_uint16_t I2C_FATAL_ERRORS = 0; std::atomic_uint16_t I2C_FATAL_ERRORS = 0;
void Factory::setStaticFrameworkObjectIds() { void Factory::setStaticFrameworkObjectIds() {
@ -789,14 +790,14 @@ ReturnValue_t ObjectFactory::createCcsdsComponents(CcsdsComponentArgs& args) {
*args.ipCoreHandler = *args.ipCoreHandler =
new CcsdsIpCoreHandler(objects::CCSDS_HANDLER, objects::CCSDS_PACKET_DISTRIBUTOR, *ptmeConfig, new CcsdsIpCoreHandler(objects::CCSDS_HANDLER, objects::CCSDS_PACKET_DISTRIBUTOR, *ptmeConfig,
LINK_STATE, &args.gpioComIF, gpios); LINK_STATE, &args.gpioComIF, gpios, PTME_LOCKED);
// This VC will receive all live TM // This VC will receive all live TM
auto* vcWithQueue = auto* vcWithQueue =
new VirtualChannelWithQueue(objects::PTME_VC0_LIVE_TM, ccsds::VC0, "PTME VC0 LIVE TM", *ptme, new VirtualChannelWithQueue(objects::PTME_VC0_LIVE_TM, ccsds::VC0, "PTME VC0 LIVE TM", *ptme,
LINK_STATE, args.tmStore, 500); LINK_STATE, args.tmStore, 500);
args.liveDestination = vcWithQueue; args.liveDestination = vcWithQueue;
auto* liveTask = auto* liveTask = new LiveTmTask(objects::LIVE_TM_TASK, args.pusFunnel, args.cfdpFunnel,
new LiveTmTask(objects::LIVE_TM_TASK, args.pusFunnel, args.cfdpFunnel, *vcWithQueue); *vcWithQueue, PTME_LOCKED);
liveTask->connectModeTreeParent(satsystem::com::SUBSYSTEM); liveTask->connectModeTreeParent(satsystem::com::SUBSYSTEM);
// Set up log store. // Set up log store.
@ -804,15 +805,17 @@ ReturnValue_t ObjectFactory::createCcsdsComponents(CcsdsComponentArgs& args) {
LINK_STATE); LINK_STATE);
LogStores logStores(args.stores); LogStores logStores(args.stores);
// Core task which handles the LOG store and takes care of dumping it as TM using a VC directly // Core task which handles the LOG store and takes care of dumping it as TM using a VC directly
auto* logStore = new PersistentLogTmStoreTask(objects::LOG_STORE_AND_TM_TASK, args.ipcStore, auto* logStore =
logStores, *vc, *SdCardManager::instance()); new PersistentLogTmStoreTask(objects::LOG_STORE_AND_TM_TASK, args.ipcStore, logStores, *vc,
*SdCardManager::instance(), PTME_LOCKED);
logStore->connectModeTreeParent(satsystem::com::SUBSYSTEM); logStore->connectModeTreeParent(satsystem::com::SUBSYSTEM);
vc = new VirtualChannel(objects::PTME_VC2_HK_TM, ccsds::VC2, "PTME VC2 HK TM", *ptme, LINK_STATE); vc = new VirtualChannel(objects::PTME_VC2_HK_TM, ccsds::VC2, "PTME VC2 HK TM", *ptme, LINK_STATE);
// Core task which handles the HK store and takes care of dumping it as TM using a VC directly // Core task which handles the HK store and takes care of dumping it as TM using a VC directly
auto* hkStore = new PersistentSingleTmStoreTask( auto* hkStore = new PersistentSingleTmStoreTask(
objects::HK_STORE_AND_TM_TASK, args.ipcStore, *args.stores.hkStore, *vc, objects::HK_STORE_AND_TM_TASK, args.ipcStore, *args.stores.hkStore, *vc,
persTmStore::DUMP_HK_STORE_DONE, persTmStore::DUMP_HK_STORE_DONE, *SdCardManager::instance()); persTmStore::DUMP_HK_STORE_DONE, persTmStore::DUMP_HK_STORE_DONE, *SdCardManager::instance(),
PTME_LOCKED);
hkStore->connectModeTreeParent(satsystem::com::SUBSYSTEM); hkStore->connectModeTreeParent(satsystem::com::SUBSYSTEM);
vc = new VirtualChannel(objects::PTME_VC3_CFDP_TM, ccsds::VC3, "PTME VC3 CFDP TM", *ptme, vc = new VirtualChannel(objects::PTME_VC3_CFDP_TM, ccsds::VC3, "PTME VC3 CFDP TM", *ptme,
@ -821,7 +824,7 @@ ReturnValue_t ObjectFactory::createCcsdsComponents(CcsdsComponentArgs& args) {
auto* cfdpTask = new PersistentSingleTmStoreTask( auto* cfdpTask = new PersistentSingleTmStoreTask(
objects::CFDP_STORE_AND_TM_TASK, args.ipcStore, *args.stores.cfdpStore, *vc, objects::CFDP_STORE_AND_TM_TASK, args.ipcStore, *args.stores.cfdpStore, *vc,
persTmStore::DUMP_CFDP_STORE_DONE, persTmStore::DUMP_CFDP_CANCELLED, persTmStore::DUMP_CFDP_STORE_DONE, persTmStore::DUMP_CFDP_CANCELLED,
*SdCardManager::instance()); *SdCardManager::instance(), PTME_LOCKED);
cfdpTask->connectModeTreeParent(satsystem::com::SUBSYSTEM); cfdpTask->connectModeTreeParent(satsystem::com::SUBSYSTEM);
ReturnValue_t result = (*args.ipCoreHandler)->connectModeTreeParent(satsystem::com::SUBSYSTEM); ReturnValue_t result = (*args.ipCoreHandler)->connectModeTreeParent(satsystem::com::SUBSYSTEM);

View File

@ -24,6 +24,7 @@ class AcsBoardAssembly;
class GpioIF; class GpioIF;
extern std::atomic_uint16_t I2C_FATAL_ERRORS; extern std::atomic_uint16_t I2C_FATAL_ERRORS;
extern std::atomic_bool PTME_LOCKED;
namespace ObjectFactory { namespace ObjectFactory {

View File

@ -61,7 +61,7 @@ void PapbVcInterface::startPacketTransfer() { *vcBaseReg = CONFIG_START; }
void PapbVcInterface::completePacketTransfer() { *vcBaseReg = CONFIG_END; } void PapbVcInterface::completePacketTransfer() { *vcBaseReg = CONFIG_END; }
ReturnValue_t PapbVcInterface::pollInterfaceReadiness(uint32_t maxPollRetries, ReturnValue_t PapbVcInterface::pollInterfaceReadiness(uint32_t maxPollRetries,
bool checkReadyState) const { bool checkReadyState) const {
uint32_t busyIdx = 0; uint32_t busyIdx = 0;
nextDelay.tv_nsec = FIRST_NON_NULL_DELAY_NS; nextDelay.tv_nsec = FIRST_NON_NULL_DELAY_NS;
@ -74,7 +74,7 @@ ReturnValue_t PapbVcInterface::pollInterfaceReadiness(uint32_t maxPollRetries,
if (not busy) { if (not busy) {
return returnvalue::OK; return returnvalue::OK;
} }
if(checkReadyState and not ready) { if (checkReadyState and not ready) {
return PAPB_BUSY; return PAPB_BUSY;
} }

View File

@ -15,9 +15,11 @@
CcsdsIpCoreHandler::CcsdsIpCoreHandler(object_id_t objectId, object_id_t tcDestination, CcsdsIpCoreHandler::CcsdsIpCoreHandler(object_id_t objectId, object_id_t tcDestination,
PtmeConfig& ptmeConfig, std::atomic_bool& linkState, PtmeConfig& ptmeConfig, std::atomic_bool& linkState,
GpioIF* gpioIF, PtmeGpios gpioIds) GpioIF* gpioIF, PtmeGpios gpioIds,
std::atomic_bool& ptmeLocked)
: SystemObject(objectId), : SystemObject(objectId),
linkState(linkState), linkState(linkState),
ptmeLocked(ptmeLocked),
tcDestination(tcDestination), tcDestination(tcDestination),
parameterHelper(this), parameterHelper(this),
actionHelper(this, nullptr), actionHelper(this, nullptr),
@ -35,6 +37,7 @@ CcsdsIpCoreHandler::~CcsdsIpCoreHandler() = default;
ReturnValue_t CcsdsIpCoreHandler::performOperation(uint8_t operationCode) { ReturnValue_t CcsdsIpCoreHandler::performOperation(uint8_t operationCode) {
readCommandQueue(); readCommandQueue();
performPtmeUpdateWhenApplicable();
return returnvalue::OK; return returnvalue::OK;
} }
@ -127,10 +130,15 @@ ReturnValue_t CcsdsIpCoreHandler::getParameter(uint8_t domainId, uint8_t uniqueI
return HasParametersIF::INVALID_VALUE; return HasParametersIF::INVALID_VALUE;
} }
parameterWrapper->set(batPriorityParam); parameterWrapper->set(batPriorityParam);
if (mode == MODE_ON) { if (newVal != batPriorityParam) {
updateBatPriorityOnTxOff = true; // This ensures that the BAT priority is updated at some point when an update of the PTME is
} else if (mode == MODE_OFF) { // allowed
updateBatPriorityFromParam(); updateContext.updateBatPrio = true;
// If we are off, we can do the update after X cycles. Otherwise, wait until the transmitter
// goes off.
if (mode == MODE_OFF) {
initPtmeUpdateAfterXCycles();
}
} }
return returnvalue::OK; return returnvalue::OK;
} }
@ -148,36 +156,12 @@ ReturnValue_t CcsdsIpCoreHandler::executeAction(ActionId_t actionId, MessageQueu
const uint8_t* data, size_t size) { const uint8_t* data, size_t size) {
ReturnValue_t result = returnvalue::OK; ReturnValue_t result = returnvalue::OK;
switch (actionId) { switch (actionId) {
case SET_LOW_RATE: {
submode = static_cast<Submode_t>(com::CcsdsSubmode::DATARATE_LOW);
result = ptmeConfig.setRate(RATE_100KBPS);
break;
}
case SET_HIGH_RATE: {
submode = static_cast<Submode_t>(com::CcsdsSubmode::DATARATE_HIGH);
result = ptmeConfig.setRate(RATE_500KBPS);
break;
}
case ARBITRARY_RATE: { case ARBITRARY_RATE: {
uint32_t bitrate = 0; uint32_t bitrate = 0;
SerializeAdapter::deSerialize(&bitrate, &data, &size, SerializeIF::Endianness::BIG); SerializeAdapter::deSerialize(&bitrate, &data, &size, SerializeIF::Endianness::BIG);
result = ptmeConfig.setRate(bitrate); result = ptmeConfig.setRate(bitrate);
break; break;
} }
case EN_TRANSMITTER: {
enableTransmit();
if (mode == HasModesIF::MODE_OFF) {
mode = HasModesIF::MODE_ON;
}
return EXECUTION_FINISHED;
}
case DISABLE_TRANSMITTER: {
disableTransmit();
if (mode == HasModesIF::MODE_ON) {
mode = HasModesIF::MODE_OFF;
}
return EXECUTION_FINISHED;
}
case ENABLE_TX_CLK_MANIPULATOR: { case ENABLE_TX_CLK_MANIPULATOR: {
result = ptmeConfig.configTxManipulator(true); result = ptmeConfig.configTxManipulator(true);
break; break;
@ -206,12 +190,8 @@ ReturnValue_t CcsdsIpCoreHandler::executeAction(ActionId_t actionId, MessageQueu
void CcsdsIpCoreHandler::updateLinkState() { linkState = LINK_UP; } void CcsdsIpCoreHandler::updateLinkState() { linkState = LINK_UP; }
void CcsdsIpCoreHandler::enableTransmit() { void CcsdsIpCoreHandler::enableTransmit() {
// Reset PTME on each transmit enable.
updateBatPriorityFromParam();
#ifndef TE0720_1CFA
gpioIF->pullHigh(ptmeGpios.enableTxClock); gpioIF->pullHigh(ptmeGpios.enableTxClock);
gpioIF->pullHigh(ptmeGpios.enableTxData); gpioIF->pullHigh(ptmeGpios.enableTxData);
#endif
linkState = LINK_UP; linkState = LINK_UP;
} }
@ -236,34 +216,23 @@ ReturnValue_t CcsdsIpCoreHandler::checkModeCommand(Mode_t mode, Submode_t submod
} }
void CcsdsIpCoreHandler::startTransition(Mode_t mode, Submode_t submode) { void CcsdsIpCoreHandler::startTransition(Mode_t mode, Submode_t submode) {
auto rateSet = [&](uint32_t rate) { triggerEvent(CHANGING_MODE, mode, submode);
ReturnValue_t result = ptmeConfig.setRate(rate);
if (result == returnvalue::OK) {
this->mode = HasModesIF::MODE_ON;
}
};
if (mode == HasModesIF::MODE_ON) { if (mode == HasModesIF::MODE_ON) {
enableTransmit(); if (this->submode != submode) {
if (submode == static_cast<Submode_t>(com::CcsdsSubmode::DATARATE_DEFAULT)) { initPtmeUpdateAfterXCycles();
com::Datarate currentDatarate = com::getCurrentDatarate(); updateContext.enableTransmitAfterPtmeUpdate = true;
if (currentDatarate == com::Datarate::LOW_RATE_MODULATION_BPSK) { updateContext.updateClockRate = true;
rateSet(RATE_100KBPS); this->submode = submode;
} else if (currentDatarate == com::Datarate::HIGH_RATE_MODULATION_0QPSK) { this->mode = mode;
rateSet(RATE_500KBPS); updateContext.setModeAfterUpdate = true;
} return;
} else if (submode == static_cast<Submode_t>(com::CcsdsSubmode::DATARATE_HIGH)) {
rateSet(RATE_500KBPS);
} else if (submode == static_cast<Submode_t>(com::CcsdsSubmode::DATARATE_LOW)) {
rateSet(RATE_100KBPS);
} }
// No rate change, so enable transmitter right away.
enableTransmit();
} else if (mode == HasModesIF::MODE_OFF) { } else if (mode == HasModesIF::MODE_OFF) {
disableTransmit(); disableTransmit();
this->mode = HasModesIF::MODE_OFF;
} }
this->submode = submode; setMode(mode, submode);
modeHelper.modeChanged(mode, submode);
announceMode(false);
} }
void CcsdsIpCoreHandler::announceMode(bool recursive) { triggerEvent(MODE_INFO, mode, submode); } void CcsdsIpCoreHandler::announceMode(bool recursive) { triggerEvent(MODE_INFO, mode, submode); }
@ -274,9 +243,9 @@ void CcsdsIpCoreHandler::disableTransmit() {
gpioIF->pullLow(ptmeGpios.enableTxData); gpioIF->pullLow(ptmeGpios.enableTxData);
#endif #endif
linkState = LINK_DOWN; linkState = LINK_DOWN;
if (updateBatPriorityOnTxOff) { // Some parameters need update and transmitter is off now.
updateBatPriorityFromParam(); if (updateContext.updateBatPrio or updateContext.updateClockRate) {
updateBatPriorityOnTxOff = false; initPtmeUpdateAfterXCycles();
} }
} }
@ -294,21 +263,9 @@ ModeTreeChildIF& CcsdsIpCoreHandler::getModeTreeChildIF() { return *this; }
object_id_t CcsdsIpCoreHandler::getObjectId() const { return SystemObject::getObjectId(); } object_id_t CcsdsIpCoreHandler::getObjectId() const { return SystemObject::getObjectId(); }
void CcsdsIpCoreHandler::enablePrioritySelectMode() { void CcsdsIpCoreHandler::enablePrioritySelectMode() { ptmeConfig.enableBatPriorityBit(true); }
ptmeConfig.enableBatPriorityBit(true);
// Reset the PTME
gpioIF->pullLow(ptmeGpios.ptmeResetn);
usleep(10);
gpioIF->pullHigh(ptmeGpios.ptmeResetn);
}
void CcsdsIpCoreHandler::disablePrioritySelectMode() { void CcsdsIpCoreHandler::disablePrioritySelectMode() { ptmeConfig.enableBatPriorityBit(false); }
ptmeConfig.enableBatPriorityBit(false);
// Reset the PTME
gpioIF->pullLow(ptmeGpios.ptmeResetn);
usleep(10);
gpioIF->pullHigh(ptmeGpios.ptmeResetn);
}
void CcsdsIpCoreHandler::updateBatPriorityFromParam() { void CcsdsIpCoreHandler::updateBatPriorityFromParam() {
if (batPriorityParam == 0) { if (batPriorityParam == 0) {
@ -317,3 +274,78 @@ void CcsdsIpCoreHandler::updateBatPriorityFromParam() {
enablePrioritySelectMode(); enablePrioritySelectMode();
} }
} }
void CcsdsIpCoreHandler::setMode(Mode_t mode, Submode_t submode) {
this->submode = submode;
this->mode = mode;
modeHelper.modeChanged(mode, submode);
announceMode(false);
}
void CcsdsIpCoreHandler::performPtmeUpdateWhenApplicable() {
if (not updateContext.performPtmeUpdateAfterXCycles) {
return;
}
if (updateContext.ptmeUpdateCycleCount >= 2) {
if (updateContext.updateBatPrio) {
updateBatPriorityFromParam();
updateContext.updateBatPrio = false;
}
ReturnValue_t result;
if (updateContext.updateClockRate) {
if (submode == static_cast<Submode_t>(com::CcsdsSubmode::DATARATE_DEFAULT)) {
com::Datarate currentDatarate = com::getCurrentDatarate();
if (currentDatarate == com::Datarate::LOW_RATE_MODULATION_BPSK) {
result = ptmeConfig.setRate(RATE_100KBPS);
} else if (currentDatarate == com::Datarate::HIGH_RATE_MODULATION_0QPSK) {
result = ptmeConfig.setRate(RATE_500KBPS);
}
} else if (submode == static_cast<Submode_t>(com::CcsdsSubmode::DATARATE_HIGH)) {
result = ptmeConfig.setRate(RATE_500KBPS);
} else if (submode == static_cast<Submode_t>(com::CcsdsSubmode::DATARATE_LOW)) {
result = ptmeConfig.setRate(RATE_100KBPS);
}
if (result != returnvalue::OK) {
sif::error << "CcsdsIpCoreHandler: Setting datarate failed" << std::endl;
}
updateContext.updateClockRate = false;
}
bool doResetPtme = true;
if (not updateContext.updateBatPrio and not updateContext.updateClockRate) {
doResetPtme = false;
}
finishPtmeUpdateAfterXCycles(doResetPtme);
return;
}
updateContext.ptmeUpdateCycleCount++;
}
void CcsdsIpCoreHandler::resetPtme() {
gpioIF->pullLow(ptmeGpios.ptmeResetn);
usleep(10);
gpioIF->pullHigh(ptmeGpios.ptmeResetn);
}
void CcsdsIpCoreHandler::initPtmeUpdateAfterXCycles() {
if (not updateContext.performPtmeUpdateAfterXCycles) {
updateContext.performPtmeUpdateAfterXCycles = true;
updateContext.ptmeUpdateCycleCount = 0;
}
}
void CcsdsIpCoreHandler::finishPtmeUpdateAfterXCycles(bool doResetPtme) {
if (doResetPtme) {
resetPtme();
}
ptmeLocked = false;
updateContext.performPtmeUpdateAfterXCycles = false;
updateContext.ptmeUpdateCycleCount = 0;
if (updateContext.enableTransmitAfterPtmeUpdate) {
enableTransmit();
updateContext.enableTransmitAfterPtmeUpdate = false;
}
if (updateContext.setModeAfterUpdate) {
setMode(mode, submode);
updateContext.setModeAfterUpdate = false;
}
}

View File

@ -79,7 +79,8 @@ class CcsdsIpCoreHandler : public SystemObject,
* @param enTxData GPIO ID of RS485 tx data enable * @param enTxData GPIO ID of RS485 tx data enable
*/ */
CcsdsIpCoreHandler(object_id_t objectId, object_id_t tcDestination, PtmeConfig& ptmeConfig, CcsdsIpCoreHandler(object_id_t objectId, object_id_t tcDestination, PtmeConfig& ptmeConfig,
std::atomic_bool& linkState, GpioIF* gpioIF, PtmeGpios gpioIds); std::atomic_bool& linkState, GpioIF* gpioIF, PtmeGpios gpioIds,
std::atomic_bool& ptmeLocked);
~CcsdsIpCoreHandler(); ~CcsdsIpCoreHandler();
@ -137,9 +138,8 @@ class CcsdsIpCoreHandler : public SystemObject,
//! [EXPORT] : [COMMENT] Received action message with unknown action id //! [EXPORT] : [COMMENT] Received action message with unknown action id
static const ReturnValue_t COMMAND_NOT_IMPLEMENTED = MAKE_RETURN_CODE(0xA0); static const ReturnValue_t COMMAND_NOT_IMPLEMENTED = MAKE_RETURN_CODE(0xA0);
// using VirtualChannelMap = std::unordered_map<VcId_t, VirtualChannelWithQueue*>;
// VirtualChannelMap virtualChannelMap;
std::atomic_bool& linkState; std::atomic_bool& linkState;
std::atomic_bool& ptmeLocked;
object_id_t tcDestination; object_id_t tcDestination;
@ -158,7 +158,15 @@ class CcsdsIpCoreHandler : public SystemObject,
PtmeGpios ptmeGpios; PtmeGpios ptmeGpios;
// BAT priority bit on by default to enable priority selection mode for the PTME. // BAT priority bit on by default to enable priority selection mode for the PTME.
uint8_t batPriorityParam = 0; uint8_t batPriorityParam = 0;
bool updateBatPriorityOnTxOff = false;
struct UpdateContext {
bool updateBatPrio = false;
bool updateClockRate = false;
bool enableTransmitAfterPtmeUpdate = false;
uint8_t ptmeUpdateCycleCount = 0;
bool performPtmeUpdateAfterXCycles = false;
bool setModeAfterUpdate = false;
} updateContext{};
GpioIF* gpioIF = nullptr; GpioIF* gpioIF = nullptr;
@ -180,6 +188,8 @@ class CcsdsIpCoreHandler : public SystemObject,
*/ */
void disableTransmit(); void disableTransmit();
void performPtmeUpdateWhenApplicable();
/** /**
* The following set of functions configure the mode of the PTME bandwith allocation table (BAT) * The following set of functions configure the mode of the PTME bandwith allocation table (BAT)
* module. This consists of the following 2 steps: * module. This consists of the following 2 steps:
@ -189,6 +199,11 @@ class CcsdsIpCoreHandler : public SystemObject,
void enablePrioritySelectMode(); void enablePrioritySelectMode();
void disablePrioritySelectMode(); void disablePrioritySelectMode();
void updateBatPriorityFromParam(); void updateBatPriorityFromParam();
void setMode(Mode_t mode, Submode_t submode);
void resetPtme();
void initPtmeUpdateAfterXCycles();
void finishPtmeUpdateAfterXCycles(bool doResetPtme);
}; };
#endif /* CCSDSHANDLER_H_ */ #endif /* CCSDSHANDLER_H_ */

View File

@ -6,12 +6,13 @@
#include <fsfw/timemanager/Stopwatch.h> #include <fsfw/timemanager/Stopwatch.h>
LiveTmTask::LiveTmTask(object_id_t objectId, PusTmFunnel& pusFunnel, CfdpTmFunnel& cfdpFunnel, LiveTmTask::LiveTmTask(object_id_t objectId, PusTmFunnel& pusFunnel, CfdpTmFunnel& cfdpFunnel,
VirtualChannelWithQueue& channel) VirtualChannelWithQueue& channel, const std::atomic_bool& ptmeLocked)
: SystemObject(objectId), : SystemObject(objectId),
modeHelper(this), modeHelper(this),
pusFunnel(pusFunnel), pusFunnel(pusFunnel),
cfdpFunnel(cfdpFunnel), cfdpFunnel(cfdpFunnel),
channel(channel) { channel(channel),
ptmeLocked(ptmeLocked) {
requestQueue = QueueFactory::instance()->createMessageQueue(); requestQueue = QueueFactory::instance()->createMessageQueue();
} }
@ -19,7 +20,7 @@ ReturnValue_t LiveTmTask::performOperation(uint8_t opCode) {
readCommandQueue(); readCommandQueue();
while (true) { while (true) {
bool performWriteOp = true; bool performWriteOp = true;
if (mode == MODE_OFF) { if (mode == MODE_OFF or ptmeLocked) {
performWriteOp = false; performWriteOp = false;
} }

View File

@ -18,7 +18,7 @@ class LiveTmTask : public SystemObject,
public ModeTreeConnectionIF { public ModeTreeConnectionIF {
public: public:
LiveTmTask(object_id_t objectId, PusTmFunnel& pusFunnel, CfdpTmFunnel& cfdpFunnel, LiveTmTask(object_id_t objectId, PusTmFunnel& pusFunnel, CfdpTmFunnel& cfdpFunnel,
VirtualChannelWithQueue& channel); VirtualChannelWithQueue& channel, const std::atomic_bool& ptmeLocked);
ReturnValue_t performOperation(uint8_t opCode) override; ReturnValue_t performOperation(uint8_t opCode) override;
ReturnValue_t initialize() override; ReturnValue_t initialize() override;
@ -33,6 +33,7 @@ class LiveTmTask : public SystemObject,
CfdpTmFunnel& cfdpFunnel; CfdpTmFunnel& cfdpFunnel;
VirtualChannelWithQueue& channel; VirtualChannelWithQueue& channel;
uint32_t packetCounter = 0; uint32_t packetCounter = 0;
const std::atomic_bool& ptmeLocked;
void readCommandQueue(void); void readCommandQueue(void);

View File

@ -5,8 +5,9 @@
PersistentLogTmStoreTask::PersistentLogTmStoreTask(object_id_t objectId, StorageManagerIF& ipcStore, PersistentLogTmStoreTask::PersistentLogTmStoreTask(object_id_t objectId, StorageManagerIF& ipcStore,
LogStores stores, VirtualChannel& channel, LogStores stores, VirtualChannel& channel,
SdCardMountedIF& sdcMan) SdCardMountedIF& sdcMan,
: TmStoreTaskBase(objectId, ipcStore, channel, sdcMan), const std::atomic_bool& ptmeLocked)
: TmStoreTaskBase(objectId, ipcStore, channel, sdcMan, ptmeLocked),
stores(stores), stores(stores),
okStoreContext(persTmStore::DUMP_OK_STORE_DONE, persTmStore::DUMP_OK_CANCELLED), okStoreContext(persTmStore::DUMP_OK_STORE_DONE, persTmStore::DUMP_OK_CANCELLED),
notOkStoreContext(persTmStore::DUMP_NOK_STORE_DONE, persTmStore::DUMP_NOK_CANCELLED), notOkStoreContext(persTmStore::DUMP_NOK_STORE_DONE, persTmStore::DUMP_NOK_CANCELLED),

View File

@ -22,7 +22,8 @@ struct LogStores {
class PersistentLogTmStoreTask : public TmStoreTaskBase, public ExecutableObjectIF { class PersistentLogTmStoreTask : public TmStoreTaskBase, public ExecutableObjectIF {
public: public:
PersistentLogTmStoreTask(object_id_t objectId, StorageManagerIF& ipcStore, LogStores tmStore, PersistentLogTmStoreTask(object_id_t objectId, StorageManagerIF& ipcStore, LogStores tmStore,
VirtualChannel& channel, SdCardMountedIF& sdcMan); VirtualChannel& channel, SdCardMountedIF& sdcMan,
const std::atomic_bool& ptmeLocked);
ReturnValue_t performOperation(uint8_t opCode) override; ReturnValue_t performOperation(uint8_t opCode) override;

View File

@ -6,8 +6,9 @@
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), const std::atomic_bool& ptmeLocked)
: TmStoreTaskBase(objectId, ipcStore, channel, sdcMan, ptmeLocked),
storeWithQueue(tmStore), storeWithQueue(tmStore),
dumpContext(eventIfDumpDone, eventIfCancelled) {} dumpContext(eventIfDumpDone, eventIfCancelled) {}
@ -27,7 +28,7 @@ ReturnValue_t PersistentSingleTmStoreTask::performOperation(uint8_t opCode) {
TaskFactory::delayTask(10); TaskFactory::delayTask(10);
} else { } else {
// TODO: Would be best to remove this, but not delaying here can lead to evil issues. // TODO: Would be best to remove this, but not delaying here can lead to evil issues.
TaskFactory::delayTask(2); TaskFactory::delayTask(10);
} }
} }
} }

View File

@ -12,7 +12,7 @@ class PersistentSingleTmStoreTask : public TmStoreTaskBase, public ExecutableObj
PersistentSingleTmStoreTask(object_id_t objectId, StorageManagerIF& ipcStore, PersistentSingleTmStoreTask(object_id_t objectId, StorageManagerIF& ipcStore,
PersistentTmStoreWithTmQueue& storeWithQueue, VirtualChannel& channel, PersistentTmStoreWithTmQueue& storeWithQueue, VirtualChannel& channel,
Event eventIfDumpDone, Event eventIfCancelled, Event eventIfDumpDone, Event eventIfCancelled,
SdCardMountedIF& sdcMan); SdCardMountedIF& sdcMan, const std::atomic_bool& ptmeLocked);
ReturnValue_t performOperation(uint8_t opCode) override; ReturnValue_t performOperation(uint8_t opCode) override;

View File

@ -10,13 +10,15 @@
#include "mission/persistentTmStoreDefs.h" #include "mission/persistentTmStoreDefs.h"
TmStoreTaskBase::TmStoreTaskBase(object_id_t objectId, StorageManagerIF& ipcStore, TmStoreTaskBase::TmStoreTaskBase(object_id_t objectId, StorageManagerIF& ipcStore,
VirtualChannel& channel, SdCardMountedIF& sdcMan) VirtualChannel& channel, SdCardMountedIF& sdcMan,
const std::atomic_bool& ptmeLocked)
: SystemObject(objectId), : SystemObject(objectId),
modeHelper(this), modeHelper(this),
ipcStore(ipcStore), ipcStore(ipcStore),
tmReader(&timeReader), tmReader(&timeReader),
channel(channel), channel(channel),
sdcMan(sdcMan) { sdcMan(sdcMan),
ptmeLocked(ptmeLocked) {
requestQueue = QueueFactory::instance()->createMessageQueue(10); requestQueue = QueueFactory::instance()->createMessageQueue(10);
} }
@ -99,7 +101,8 @@ ReturnValue_t TmStoreTaskBase::handleOneDump(PersistentTmStoreWithTmQueue& store
cancelDump(dumpContext, store, false); cancelDump(dumpContext, store, false);
return returnvalue::FAILED; return returnvalue::FAILED;
} }
if (not channel.isBusy()) { // It is assumed that the PTME will only be locked for a short period (e.g. to change datarate).
if (not channel.isBusy() and not ptmeLocked) {
performDump(store, dumpContext, dumpPerformed); performDump(store, dumpContext, dumpPerformed);
} else { } else {
// The PTME might be at full load, so it might sense to delay for a bit to let it do // The PTME might be at full load, so it might sense to delay for a bit to let it do

View File

@ -40,7 +40,7 @@ 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, const std::atomic_bool& ptmeLocked);
ReturnValue_t initialize() override; ReturnValue_t initialize() override;
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF& parent) override; ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF& parent) override;
@ -52,6 +52,8 @@ class TmStoreTaskBase : public SystemObject,
PusTmReader tmReader; PusTmReader tmReader;
CdsShortTimeStamper timeReader; CdsShortTimeStamper timeReader;
VirtualChannel& channel; VirtualChannel& channel;
SdCardMountedIF& sdcMan;
const std::atomic_bool& ptmeLocked;
Mode_t mode = HasModesIF::MODE_OFF; Mode_t mode = HasModesIF::MODE_OFF;
Countdown sdCardCheckCd = Countdown(800); Countdown sdCardCheckCd = Countdown(800);
@ -62,7 +64,6 @@ class TmStoreTaskBase : public SystemObject,
bool storesInitialized = false; bool storesInitialized = false;
bool fileHasSwapped = false; bool fileHasSwapped = false;
SdCardMountedIF& sdcMan;
void readCommandQueue(void); void readCommandQueue(void);