re-work transition handling
EIVE/eive-obsw/pipeline/head There was a failure building this commit Details

This commit is contained in:
Robin Müller 2024-04-17 13:10:32 +02:00
parent 91fdd7e7ac
commit 758bc6e0e6
Signed by: muellerr
GPG Key ID: A649FB78196E3849
5 changed files with 138 additions and 67 deletions

View File

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

View File

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

View File

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

View File

@ -6,6 +6,7 @@
#include <mission/payload/plocSpBase.h>
#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.

2
tmtc

@ -1 +1 @@
Subproject commit d5bb6fe6c5e9f3ea2cc703128bf7ed0560ca41de
Subproject commit fc5fb0eed333a46407c59e40cc9ca018ab3e217c