From 758bc6e0e60dade1990e79383c5cb3a55bce0327 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 17 Apr 2024 13:10:32 +0200 Subject: [PATCH] re-work transition handling --- linux/payload/FreshMpsocHandler.cpp | 119 ++++++++++++++++++++-------- linux/payload/FreshMpsocHandler.h | 11 +-- linux/payload/plocMpsocHelpers.cpp | 40 +++++----- linux/payload/plocMpsocHelpers.h | 33 +++++--- tmtc | 2 +- 5 files changed, 138 insertions(+), 67 deletions(-) diff --git a/linux/payload/FreshMpsocHandler.cpp b/linux/payload/FreshMpsocHandler.cpp index c9a6f2ab..d6ab2fd3 100644 --- a/linux/payload/FreshMpsocHandler.cpp +++ b/linux/payload/FreshMpsocHandler.cpp @@ -30,7 +30,7 @@ FreshMpsocHandler::FreshMpsocHandler(DhbConfig cfg, MpsocCommunication& comInter } void FreshMpsocHandler::performDeviceOperation(uint8_t opCode) { - if (not transitionActive and (mode == MODE_OFF or mode == MODE_UNDEFINED)) { + if (transitionState == TransitionState::NONE and (mode == MODE_OFF or mode == MODE_UNDEFINED)) { // Nothing to do for now. return; } @@ -55,23 +55,24 @@ void FreshMpsocHandler::performDeviceOperation(uint8_t opCode) { void FreshMpsocHandler::performDefaultDeviceOperation() { handleQueue(); - if (transitionActive) { - // TODO: Timeout handling for transitions. - if (targetMode == MODE_ON or targetMode == MODE_NORMAL) { - handleTransitionToOn(); - } else if (targetMode == MODE_OFF) { - handleTransitionToOff(); - } else { - // This should never happen. - sif::error << "FreshMpsocHandler: Invalid transition mode: " << targetMode << std::endl; - targetMode = MODE_OFF; - targetSubmode = 0; - handleTransitionToOff(); + if (transitionState == TransitionState::TO_ON) { + handleTransitionToOn(); + } else if (transitionState == TransitionState::TO_OFF) { + handleTransitionToOff(); + } else if (transitionState == TransitionState::SUBMODE) { + if (!activeCmdInfo.pending) { + commandSubmodeTransition(); } } else { - if (mode == MODE_NORMAL and not activeCmdInfo.pending) { - // TODO: Take care of regular periodic commanding here. - } + // This should never happen. + sif::error << "FreshMpsocHandler: Invalid transition mode: " << targetMode << std::endl; + targetMode = MODE_OFF; + targetSubmode = 0; + handleTransitionToOff(); + } + + if (mode == MODE_NORMAL and not activeCmdInfo.pending) { + // TODO: Take care of regular periodic commanding here. } if (activeCmdInfo.pending and activeCmdInfo.cmdCountdown.hasTimedOut()) { @@ -206,6 +207,18 @@ ReturnValue_t FreshMpsocHandler::initializeLocalDataPool(localpool::DataPool& lo // Mode abstract functions ReturnValue_t FreshMpsocHandler::checkModeCommand(Mode_t mode, Submode_t submode, uint32_t* msToReachTheMode) { + if (this->mode == MODE_OFF or this->mode == MODE_UNDEFINED) { + // Device needs to be commanded to ON or NORMAL first before commanding submode. + if (submode != mpsoc::Submode::IDLE_OR_NONE) { + return HasModesIF::INVALID_SUBMODE; + } + } + if (mode == MODE_ON or mode == MODE_NORMAL) { + if (submode != mpsoc::Submode::IDLE_OR_NONE && submode != mpsoc::Submode::REPLAY && + submode != mpsoc::Submode::SNAPSHOT) { + return HasModesIF::INVALID_SUBMODE; + } + } return returnvalue::OK; } @@ -267,7 +280,7 @@ ReturnValue_t FreshMpsocHandler::executeAction(ActionId_t actionId, MessageQueue specialComHelperExecuting = true; return EXECUTION_FINISHED; } - case (mpsoc::OBSW_RESET_SEQ_COUNT): { + case (mpsoc::OBSW_RESET_SEQ_COUNT_LEGACY): { commandSequenceCount = 0; return EXECUTION_FINISHED; } @@ -286,18 +299,39 @@ ReturnValue_t FreshMpsocHandler::executeAction(ActionId_t actionId, MessageQueue */ void FreshMpsocHandler::startTransition(Mode_t newMode, Submode_t submode) { // OFF commands are always accepted. Otherwise, ignore transition requests. - if (transitionActive && newMode != HasModesIF::MODE_OFF) { + if (transitionState != TransitionState::NONE && newMode != HasModesIF::MODE_OFF) { return; } + // We are already on and only a submode change is commanded. + if ((mode == MODE_ON or mode == MODE_NORMAL) && (newMode == MODE_ON or newMode == MODE_NORMAL)) { + transitionState = TransitionState::SUBMODE; + } + if (newMode == MODE_ON && ((mode == MODE_OFF) or (mode == MODE_UNDEFINED))) { + transitionState = TransitionState::TO_ON; + } + if (newMode == MODE_OFF) { + transitionState = TransitionState::TO_OFF; + } targetMode = newMode; targetSubmode = submode; - transitionActive = true; } ReturnValue_t FreshMpsocHandler::performDeviceOperationPreQueueHandling(uint8_t opCode) { return returnvalue::OK; } +void FreshMpsocHandler::commandSubmodeTransition() { + if (targetSubmode != mpsoc::Submode::IDLE_OR_NONE) { + if (targetSubmode == mpsoc::Submode::SNAPSHOT) { + commandTcModeSnapshot(); + } else if (targetSubmode == mpsoc::Submode::REPLAY) { + commandTcModeReplay(); + } else { + sif::error << "FreshMpsocHandler::handleTransitionToOn: Invalid submode" << std::endl; + } + } +} + void FreshMpsocHandler::handleTransitionToOn() { if (startupState == StartupState::IDLE) { startupState = StartupState::HW_INIT; @@ -309,7 +343,7 @@ void FreshMpsocHandler::handleTransitionToOn() { } if (startupState == StartupState::DONE) { setMode(targetMode, targetSubmode); - transitionActive = false; + transitionState = TransitionState::NONE; hkReport.setReportingEnabled(true); powerState = PowerState::IDLE; startupState = StartupState::IDLE; @@ -320,9 +354,8 @@ void FreshMpsocHandler::handleTransitionToOff() { if (handleHwShutdown()) { hkReport.setReportingEnabled(false); setMode(MODE_OFF); - transitionActive = false; - // commandIsPending = false; - // sequenceCount = 0; + transitionState = TransitionState::NONE; + activeCmdInfo.reset(); powerState = PowerState::IDLE; startupState = StartupState::IDLE; } @@ -458,12 +491,12 @@ ReturnValue_t FreshMpsocHandler::executeRegularCmd(ActionId_t actionId, result = prepareTcGetDirContent(commandData, commandDataLen); break; } - case (mpsoc::TC_MODE_REPLAY): { - result = prepareTcModeReplay(); + case (mpsoc::TC_MODE_REPLAY_LEGACY): { + result = commandTcModeReplay(); break; } - case (mpsoc::TC_MODE_IDLE): { - result = prepareTcModeIdle(); + case (mpsoc::TC_MODE_IDLE_LEGACY): { + result = commandTcModeIdle(); break; } case (mpsoc::TC_CAM_CMD_SEND): { @@ -482,8 +515,8 @@ ReturnValue_t FreshMpsocHandler::executeRegularCmd(ActionId_t actionId, result = prepareTcDownlinkDataModulate(commandData, commandDataLen); break; } - case (mpsoc::TC_MODE_SNAPSHOT): { - result = prepareTcModeSnapshot(); + case (mpsoc::TC_MODE_SNAPSHOT_LEGACY): { + result = commandTcModeSnapshot(); break; } default: @@ -598,13 +631,13 @@ ReturnValue_t FreshMpsocHandler::prepareTcReplayWriteSequence(const uint8_t* com return returnvalue::OK; } -ReturnValue_t FreshMpsocHandler::prepareTcModeReplay() { +ReturnValue_t FreshMpsocHandler::commandTcModeReplay() { mpsoc::TcModeReplay tcModeReplay(spParams, commandSequenceCount); finishAndSendTc(tcModeReplay); return returnvalue::OK; } -ReturnValue_t FreshMpsocHandler::prepareTcModeIdle() { +ReturnValue_t FreshMpsocHandler::commandTcModeIdle() { mpsoc::TcModeIdle tcModeIdle(spParams, commandSequenceCount); finishAndSendTc(tcModeIdle); return returnvalue::OK; @@ -665,7 +698,7 @@ ReturnValue_t FreshMpsocHandler::prepareTcDownlinkDataModulate(const uint8_t* co return returnvalue::OK; } -ReturnValue_t FreshMpsocHandler::prepareTcModeSnapshot() { +ReturnValue_t FreshMpsocHandler::commandTcModeSnapshot() { mpsoc::TcModeSnapshot tcModeSnapshot(spParams, commandSequenceCount); finishAndSendTc(tcModeSnapshot); return returnvalue::OK; @@ -703,6 +736,15 @@ void FreshMpsocHandler::handleEvent(EventMessage* eventMessage) { } void FreshMpsocHandler::cmdDoneHandler(bool success, ReturnValue_t result) { + if (transitionState == TransitionState::SUBMODE) { + if (success) { + setMode(targetMode, targetSubmode); + } else { + // Keep the old submode. + setMode(targetMode); + } + transitionState = TransitionState::NONE; + } if (activeCmdInfo.commandedBy != MessageQueueIF::NO_QUEUE) { actionHelper.finish(success, activeCmdInfo.commandedBy, activeCmdInfo.pendingCmd, result); } @@ -779,6 +821,19 @@ ReturnValue_t FreshMpsocHandler::handleExecutionReport() { } case (mpsoc::apid::EXE_FAILURE): { DeviceCommandId_t commandId = activeCmdInfo.pendingCmd; + // Ensure idempotency: If the device is already in the mode, the command was successful. + if (mpsoc::getStatusFromRawData(replyReader.getFullData()) == + mpsoc::statusCode::TC_NOT_ALLOWED_IN_MODE) { + if ((activeCmdInfo.pendingCmdMpsocApid == mpsoc::apid::TC_MODE_SNAPSHOT && + submode == mpsoc::Submode::SNAPSHOT) or + (activeCmdInfo.pendingCmdMpsocApid == mpsoc::apid::TC_MODE_IDLE && + submode == mpsoc::Submode::IDLE_OR_NONE) or + (activeCmdInfo.pendingCmdMpsocApid == mpsoc::apid::TC_MODE_REPLAY && + submode == mpsoc::Submode::REPLAY)) { + cmdDoneHandler(true, returnvalue::OK); + return result; + } + } if (commandId == DeviceHandlerIF::NO_COMMAND_ID) { sif::debug << "PlocMPSoCHandler::handleExecutionReport: Unknown command id" << std::endl; } diff --git a/linux/payload/FreshMpsocHandler.h b/linux/payload/FreshMpsocHandler.h index b930f1ad..cab4e789 100644 --- a/linux/payload/FreshMpsocHandler.h +++ b/linux/payload/FreshMpsocHandler.h @@ -1,4 +1,3 @@ -#include "eive/resultClassIds.h" #include "fsfw/action/CommandsActionsIF.h" #include "fsfw/devicehandlers/DeviceHandlerIF.h" #include "fsfw/devicehandlers/FreshDeviceHandlerBase.h" @@ -10,6 +9,7 @@ #include "fsfw_hal/linux/gpio/Gpio.h" #include "linux/payload/MpsocCommunication.h" #include "linux/payload/PlocMpsocSpecialComHelper.h" +#include "linux/payload/plocMpsocHelpers.h" static constexpr bool MPSOC_TX_WIRETAPPING = true; static constexpr bool MPSOC_RX_WIRETAPPING = true; @@ -43,7 +43,7 @@ class FreshMpsocHandler : public FreshDeviceHandlerBase, public CommandsActionsI enum class StartupState { IDLE, HW_INIT, DONE } startupState = StartupState::IDLE; enum class PowerState { IDLE, PENDING_STARTUP, PENDING_SHUTDOWN, SUPV_FAILED, DONE }; - bool transitionActive = false; + enum TransitionState { NONE, TO_ON, TO_OFF, SUBMODE } transitionState; MpsocCommunication& comInterface; PlocMpsocSpecialComHelper& specialComHelper; MessageQueueIF* eventQueue = nullptr; @@ -168,7 +168,7 @@ class FreshMpsocHandler : public FreshDeviceHandlerBase, public CommandsActionsI void handleTransitionToOn(); void handleTransitionToOff(); - ReturnValue_t prepareTcModeReplay(); + ReturnValue_t commandTcModeReplay(); ReturnValue_t prepareTcMemWrite(const uint8_t* commandData, size_t commandDataLen); ReturnValue_t prepareTcMemRead(const uint8_t* commandData, size_t commandDataLen); ReturnValue_t prepareTcFlashDelete(const uint8_t* commandData, size_t commandDataLen); @@ -180,11 +180,11 @@ class FreshMpsocHandler : public FreshDeviceHandlerBase, public CommandsActionsI ReturnValue_t prepareTcGetDirContent(const uint8_t* commandData, size_t commandDataLen); ReturnValue_t prepareTcReplayWriteSequence(const uint8_t* commandData, size_t commandDataLen); ReturnValue_t prepareTcCamCmdSend(const uint8_t* commandData, size_t commandDataLen); - ReturnValue_t prepareTcModeIdle(); + ReturnValue_t commandTcModeIdle(); ReturnValue_t prepareTcCamTakePic(const uint8_t* commandData, size_t commandDataLen); ReturnValue_t prepareTcSimplexSendFile(const uint8_t* commandData, size_t commandDataLen); ReturnValue_t prepareTcDownlinkDataModulate(const uint8_t* commandData, size_t commandDataLen); - ReturnValue_t prepareTcModeSnapshot(); + ReturnValue_t commandTcModeSnapshot(); ReturnValue_t finishAndSendTc(mpsoc::TcBase& tcBase); void handleEvent(EventMessage* eventMessage); @@ -199,4 +199,5 @@ class FreshMpsocHandler : public FreshDeviceHandlerBase, public CommandsActionsI bool handleHwShutdown(); void stopSpecialComHelper(); + void commandSubmodeTransition(); }; diff --git a/linux/payload/plocMpsocHelpers.cpp b/linux/payload/plocMpsocHelpers.cpp index 9e5b11c9..538d2cd9 100644 --- a/linux/payload/plocMpsocHelpers.cpp +++ b/linux/payload/plocMpsocHelpers.cpp @@ -5,83 +5,83 @@ uint16_t mpsoc::getStatusFromRawData(const uint8_t* data) { } std::string mpsoc::getStatusString(uint16_t status) { switch (status) { - case (mpsoc::status_code::UNKNOWN_APID): { + case (mpsoc::statusCode::UNKNOWN_APID): { return "Unknown APID"; break; } - case (mpsoc::status_code::INCORRECT_LENGTH): { + case (mpsoc::statusCode::INCORRECT_LENGTH): { return "Incorrect length"; break; } - case (mpsoc::status_code::INCORRECT_CRC): { + case (mpsoc::statusCode::INCORRECT_CRC): { return "Incorrect crc"; break; } - case (mpsoc::status_code::INCORRECT_PKT_SEQ_CNT): { + case (mpsoc::statusCode::INCORRECT_PKT_SEQ_CNT): { return "Incorrect packet sequence count"; break; } - case (mpsoc::status_code::TC_NOT_ALLOWED_IN_MODE): { + case (mpsoc::statusCode::TC_NOT_ALLOWED_IN_MODE): { return "TC not allowed in this mode"; break; } - case (mpsoc::status_code::TC_EXEUTION_DISABLED): { + case (mpsoc::statusCode::TC_EXEUTION_DISABLED): { return "TC execution disabled"; break; } - case (mpsoc::status_code::FLASH_MOUNT_FAILED): { + case (mpsoc::statusCode::FLASH_MOUNT_FAILED): { return "Flash mount failed"; break; } - case (mpsoc::status_code::FLASH_FILE_ALREADY_OPEN): { + case (mpsoc::statusCode::FLASH_FILE_ALREADY_OPEN): { return "Flash file already open"; break; } - case (mpsoc::status_code::FLASH_FILE_ALREADY_CLOSED): { + case (mpsoc::statusCode::FLASH_FILE_ALREADY_CLOSED): { return "Flash file already closed"; break; } - case (mpsoc::status_code::FLASH_FILE_OPEN_FAILED): { + case (mpsoc::statusCode::FLASH_FILE_OPEN_FAILED): { return "Flash file open failed"; break; } - case (mpsoc::status_code::FLASH_FILE_NOT_OPEN): { + case (mpsoc::statusCode::FLASH_FILE_NOT_OPEN): { return "Flash file not open"; break; } - case (mpsoc::status_code::FLASH_UNMOUNT_FAILED): { + case (mpsoc::statusCode::FLASH_UNMOUNT_FAILED): { return "Flash unmount failed"; break; } - case (mpsoc::status_code::HEAP_ALLOCATION_FAILED): { + case (mpsoc::statusCode::HEAP_ALLOCATION_FAILED): { return "Heap allocation failed"; break; } - case (mpsoc::status_code::INVALID_PARAMETER): { + case (mpsoc::statusCode::INVALID_PARAMETER): { return "Invalid parameter"; break; } - case (mpsoc::status_code::NOT_INITIALIZED): { + case (mpsoc::statusCode::NOT_INITIALIZED): { return "Not initialized"; break; } - case (mpsoc::status_code::REBOOT_IMMINENT): { + case (mpsoc::statusCode::REBOOT_IMMINENT): { return "Reboot imminent"; break; } - case (mpsoc::status_code::CORRUPT_DATA): { + case (mpsoc::statusCode::CORRUPT_DATA): { return "Corrupt data"; break; } - case (mpsoc::status_code::FLASH_CORRECTABLE_MISMATCH): { + case (mpsoc::statusCode::FLASH_CORRECTABLE_MISMATCH): { return "Flash correctable mismatch"; break; } - case (mpsoc::status_code::FLASH_UNCORRECTABLE_MISMATCH): { + case (mpsoc::statusCode::FLASH_UNCORRECTABLE_MISMATCH): { return "Flash uncorrectable mismatch"; break; } - case (mpsoc::status_code::DEFAULT_ERROR_CODE): { + case (mpsoc::statusCode::DEFAULT_ERROR_CODE): { return "Default error code"; break; } diff --git a/linux/payload/plocMpsocHelpers.h b/linux/payload/plocMpsocHelpers.h index a0af2813..344851f3 100644 --- a/linux/payload/plocMpsocHelpers.h +++ b/linux/payload/plocMpsocHelpers.h @@ -6,6 +6,7 @@ #include #include "eive/definitions.h" +#include "fsfw/modes/HasModesIF.h" #include "fsfw/returnvalues/returnvalue.h" #include "fsfw/serialize/SerializeAdapter.h" #include "fsfw/serialize/SerializeIF.h" @@ -134,31 +135,45 @@ static const DeviceCommandId_t TC_REPLAY_STOP = 12; static const DeviceCommandId_t TC_REPLAY_WRITE_SEQUENCE = 13; static const DeviceCommandId_t TC_DOWNLINK_PWR_ON = 14; static const DeviceCommandId_t TC_DOWNLINK_PWR_OFF = 15; -static const DeviceCommandId_t TC_MODE_REPLAY = 16; static const DeviceCommandId_t TC_CAM_CMD_SEND = 17; -static const DeviceCommandId_t TC_MODE_IDLE = 18; static const DeviceCommandId_t TM_CAM_CMD_RPT = 19; static const DeviceCommandId_t SET_UART_TX_TRISTATE = 20; static const DeviceCommandId_t RELEASE_UART_TX = 21; static const DeviceCommandId_t TC_CAM_TAKE_PIC = 22; static const DeviceCommandId_t TC_SIMPLEX_SEND_FILE = 23; static const DeviceCommandId_t TC_DOWNLINK_DATA_MODULATE = 24; -static const DeviceCommandId_t TC_MODE_SNAPSHOT = 25; static const DeviceCommandId_t TC_GET_HK_REPORT = 26; static const DeviceCommandId_t TM_GET_HK_REPORT = 27; static const DeviceCommandId_t TC_FLASH_GET_DIRECTORY_CONTENT = 28; static const DeviceCommandId_t TM_FLASH_DIRECTORY_CONTENT = 29; static constexpr DeviceCommandId_t TC_FLASH_READ_FULL_FILE = 30; -// Will reset the sequence count of the OBSW -static const DeviceCommandId_t OBSW_RESET_SEQ_COUNT = 50; +// Do not use those, use submode instead. +static const DeviceCommandId_t TC_MODE_REPLAY_LEGACY = 16; +static const DeviceCommandId_t TC_MODE_IDLE_LEGACY = 18; +static const DeviceCommandId_t TC_MODE_SNAPSHOT_LEGACY = 25; + +// Will reset the sequence count of the OBSW. Not required anymore after MPSoC update. +static const DeviceCommandId_t OBSW_RESET_SEQ_COUNT_LEGACY = 50; static const uint16_t SIZE_ACK_REPORT = 14; static const uint16_t SIZE_EXE_REPORT = 14; -static const uint16_t SIZE_TM_MEM_READ_REPORT = 18; -static const uint16_t SIZE_TM_CAM_CMD_RPT = 18; +// static const uint16_t SIZE_TM_MEM_READ_REPORT = 18; +// static const uint16_t SIZE_TM_CAM_CMD_RPT = 18; static constexpr size_t SIZE_TM_HK_REPORT = 369; +enum Submode : uint8_t { IDLE_OR_NONE = 0, REPLAY = 1, SNAPSHOT = 2 }; + +// Setting the internal mode value to the actual telecommand ID +/* +enum InternalMode { + OFF = HasModesIF::MODE_OFF, + IDLE = , + REPLAY = TC_MODE_REPLAY, + SNAPSHOT = TC_MODE_SNAPSHOT +}; +*/ + /** * SpacePacket apids of PLOC telecommands and telemetry. */ @@ -250,7 +265,7 @@ static const uint16_t TC_DOWNLINK_PWR_ON_EXECUTION_DELAY = 8; static const uint16_t TC_CAM_TAKE_PIC_EXECUTION_DELAY = 20; static const uint16_t TC_SIMPLEX_SEND_FILE_DELAY = 80; -namespace status_code { +namespace statusCode { static const uint16_t DEFAULT_ERROR_CODE = 0x1; static const uint16_t UNKNOWN_APID = 0x5DD; static const uint16_t INCORRECT_LENGTH = 0x5DE; @@ -276,7 +291,7 @@ static const uint16_t RESERVED_1 = 0x5F1; static const uint16_t RESERVED_2 = 0x5F2; static const uint16_t RESERVED_3 = 0x5F3; static const uint16_t RESERVED_4 = 0x5F4; -} // namespace status_code +} // namespace statusCode /** * @brief Abstract base class for TC space packet of MPSoC. diff --git a/tmtc b/tmtc index d5bb6fe6..fc5fb0ee 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit d5bb6fe6c5e9f3ea2cc703128bf7ed0560ca41de +Subproject commit fc5fb0eed333a46407c59e40cc9ca018ab3e217c