From 10f552f56a21e3f0bd7b27f61c855cd6780b4908 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sat, 8 Apr 2023 13:24:21 +0200 Subject: [PATCH] bugfix and simplifications for SDC state machine --- bsp_q7s/core/CoreController.cpp | 97 +++++++++++++++++---------------- bsp_q7s/core/CoreController.h | 14 ++--- bsp_q7s/fs/SdCardManager.cpp | 52 ++++++++---------- bsp_q7s/fs/SdCardManager.h | 20 +++---- tmtc | 2 +- 5 files changed, 89 insertions(+), 96 deletions(-) diff --git a/bsp_q7s/core/CoreController.cpp b/bsp_q7s/core/CoreController.cpp index 015a37d2..08135b7b 100644 --- a/bsp_q7s/core/CoreController.cpp +++ b/bsp_q7s/core/CoreController.cpp @@ -54,7 +54,6 @@ CoreController::CoreController(object_id_t objectId, bool enableHkSet) // Set up state of SD card manager and own initial state. // Stopwatch watch; sdcMan->updateSdCardStateFile(); - sdcMan->updateSdStatePair(); SdCardManager::SdStatePair sdStates; sdcMan->getSdCardsStatus(sdStates); auto sdCard = sdcMan->getPreferredSdCard(); @@ -368,7 +367,7 @@ ReturnValue_t CoreController::initSdCardBlocking() { } if (sdInfo.cfgMode == SdCfgMode::COLD_REDUNDANT) { - updateSdInfoOther(); + updateInternalSdInfo(); sif::info << "Cold redundant SD card configuration, preferred SD card: " << static_cast(sdInfo.active) << std::endl; result = sdColdRedundantBlockingInit(); @@ -404,23 +403,23 @@ ReturnValue_t CoreController::sdStateMachine() { } else { // Still update SD state file if (sdInfo.cfgMode == SdCfgMode::PASSIVE) { - sdFsmState = SdStates::UPDATE_INFO; + sdFsmState = SdStates::UPDATE_SD_INFO_END; } else { sdInfo.cycleCount = 0; - sdInfo.commandExecuted = false; - sdFsmState = SdStates::GET_INFO; + sdInfo.commandPending = false; + sdFsmState = SdStates::UPDATE_SD_INFO_START; } } } - // This lambda checks the non-blocking operation and assigns the new state on success. - // It returns true for an operation success and false otherwise - auto nonBlockingOpChecking = [&](SdStates newStateOnSuccess, uint16_t maxCycleCount, - std::string opPrintout) { + // This lambda checks the non-blocking operation of the SD card manager and assigns the new + // state on success. It returns true for an operation success and false otherwise + auto nonBlockingSdcOpChecking = [&](SdStates newStateOnSuccess, uint16_t maxCycleCount, + std::string opPrintout) { SdCardManager::OpStatus status = sdcMan->checkCurrentOp(operation); if (status == SdCardManager::OpStatus::SUCCESS) { sdFsmState = newStateOnSuccess; - sdInfo.commandExecuted = false; + sdInfo.commandPending = false; sdInfo.cycleCount = 0; return true; } else if (sdInfo.cycleCount > 4) { @@ -431,26 +430,16 @@ ReturnValue_t CoreController::sdStateMachine() { return false; }; - if (sdFsmState == SdStates::GET_INFO) { - if (not sdInfo.commandExecuted) { + if (sdFsmState == SdStates::UPDATE_SD_INFO_START) { + if (not sdInfo.commandPending) { // Create updated status file result = sdcMan->updateSdCardStateFile(); if (result != returnvalue::OK) { sif::warning << "CoreController::sdStateMachine: Updating SD card state file failed" << std::endl; } - sdFsmState = SdStates::SET_STATE_SELF; - sdInfo.commandExecuted = false; - sdInfo.cycleCount = 0; - } else { - nonBlockingOpChecking(SdStates::SET_STATE_SELF, 4, "Updating SDC file"); - } - } - - if (sdFsmState == SdStates::SET_STATE_SELF) { - if (not sdInfo.commandExecuted) { result = sdcMan->getSdCardsStatus(sdInfo.currentState); - updateSdInfoOther(); + updateInternalSdInfo(); if (sdInfo.active != sd::SdCard::SLOT_0 and sdInfo.active != sd::SdCard::SLOT_1) { sif::warning << "Preferred SD card invalid. Setting to card 0.." << std::endl; sdInfo.active = sd::SdCard::SLOT_0; @@ -478,12 +467,12 @@ ReturnValue_t CoreController::sdStateMachine() { sdFsmState = SdStates::DETERMINE_OTHER; } else if (sdInfo.activeState == sd::SdState::OFF) { sdCardSetup(sdInfo.active, sd::SdState::ON, sdInfo.activeChar, false); - sdInfo.commandExecuted = true; + sdInfo.commandPending = true; } else if (sdInfo.activeState == sd::SdState::ON) { sdFsmState = SdStates::MOUNT_SELF; } } else { - if (nonBlockingOpChecking(SdStates::MOUNT_SELF, 10, "Setting SDC state")) { + if (nonBlockingSdcOpChecking(SdStates::MOUNT_SELF, 10, "Setting SDC state")) { sdInfo.activeState = sd::SdState::ON; currentStateSetter(sdInfo.active, sd::SdState::ON); } @@ -491,11 +480,11 @@ ReturnValue_t CoreController::sdStateMachine() { } if (sdFsmState == SdStates::MOUNT_SELF) { - if (not sdInfo.commandExecuted) { + if (not sdInfo.commandPending) { result = sdCardSetup(sdInfo.active, sd::SdState::MOUNTED, sdInfo.activeChar); - sdInfo.commandExecuted = true; + sdInfo.commandPending = true; } else { - if (nonBlockingOpChecking(SdStates::DETERMINE_OTHER, 5, "Mounting SD card")) { + if (nonBlockingSdcOpChecking(SdStates::DETERMINE_OTHER, 5, "Mounting SD card")) { sdcMan->setActiveSdCard(sdInfo.active); currMntPrefix = sdcMan->getCurrentMountPrefix(); sdInfo.activeState = sd::SdState::MOUNTED; @@ -532,23 +521,23 @@ ReturnValue_t CoreController::sdStateMachine() { if (sdFsmState == SdStates::SET_STATE_OTHER) { // Set state of other SD card to ON or OFF, depending on redundancy mode if (sdInfo.cfgMode == SdCfgMode::COLD_REDUNDANT) { - if (not sdInfo.commandExecuted) { + if (not sdInfo.commandPending) { result = sdCardSetup(sdInfo.other, sd::SdState::OFF, sdInfo.otherChar, false); - sdInfo.commandExecuted = true; + sdInfo.commandPending = true; } else { - if (nonBlockingOpChecking(SdStates::SKIP_CYCLE_BEFORE_INFO_UPDATE, 10, - "Switching off other SD card")) { + if (nonBlockingSdcOpChecking(SdStates::SKIP_CYCLE_BEFORE_INFO_UPDATE, 10, + "Switching off other SD card")) { sdInfo.otherState = sd::SdState::OFF; currentStateSetter(sdInfo.other, sd::SdState::OFF); } } } else if (sdInfo.cfgMode == SdCfgMode::HOT_REDUNDANT) { - if (not sdInfo.commandExecuted) { + if (not sdInfo.commandPending) { result = sdCardSetup(sdInfo.other, sd::SdState::ON, sdInfo.otherChar, false); - sdInfo.commandExecuted = true; + sdInfo.commandPending = true; } else { - if (nonBlockingOpChecking(SdStates::MOUNT_UNMOUNT_OTHER, 10, - "Switching on other SD card")) { + if (nonBlockingSdcOpChecking(SdStates::MOUNT_UNMOUNT_OTHER, 10, + "Switching on other SD card")) { sdInfo.otherState = sd::SdState::ON; currentStateSetter(sdInfo.other, sd::SdState::ON); } @@ -559,21 +548,25 @@ ReturnValue_t CoreController::sdStateMachine() { if (sdFsmState == SdStates::MOUNT_UNMOUNT_OTHER) { // Mount or unmount other SD card, depending on redundancy mode if (sdInfo.cfgMode == SdCfgMode::COLD_REDUNDANT) { - if (not sdInfo.commandExecuted) { + if (not sdInfo.commandPending) { result = sdCardSetup(sdInfo.other, sd::SdState::ON, sdInfo.otherChar); - sdInfo.commandExecuted = true; + sdInfo.commandPending = true; } else { - if (nonBlockingOpChecking(SdStates::SET_STATE_OTHER, 10, "Unmounting other SD card")) { + if (nonBlockingSdcOpChecking(SdStates::SET_STATE_OTHER, 10, "Unmounting other SD card")) { sdInfo.otherState = sd::SdState::ON; currentStateSetter(sdInfo.other, sd::SdState::ON); + } else { + sdInfo.otherState = sd::SdState::ON; + currentStateSetter(sdInfo.other, sd::SdState::ON); + sdFsmState = SdStates::SET_STATE_OTHER; } } } else if (sdInfo.cfgMode == SdCfgMode::HOT_REDUNDANT) { - if (not sdInfo.commandExecuted) { + if (not sdInfo.commandPending) { result = sdCardSetup(sdInfo.other, sd::SdState::MOUNTED, sdInfo.otherChar); - sdInfo.commandExecuted = true; + sdInfo.commandPending = true; } else { - if (nonBlockingOpChecking(SdStates::UPDATE_INFO, 4, "Mounting other SD card")) { + if (nonBlockingSdcOpChecking(SdStates::UPDATE_SD_INFO_END, 4, "Mounting other SD card")) { sdInfo.otherState = sd::SdState::MOUNTED; currentStateSetter(sdInfo.other, sd::SdState::MOUNTED); } @@ -582,14 +575,15 @@ ReturnValue_t CoreController::sdStateMachine() { } if (sdFsmState == SdStates::SKIP_CYCLE_BEFORE_INFO_UPDATE) { - sdFsmState = SdStates::UPDATE_INFO; - } else if (sdFsmState == SdStates::UPDATE_INFO) { + sdFsmState = SdStates::UPDATE_SD_INFO_END; + } else if (sdFsmState == SdStates::UPDATE_SD_INFO_END) { // Update status file result = sdcMan->updateSdCardStateFile(); if (result != returnvalue::OK) { sif::warning << "CoreController: Updating SD card state file failed" << std::endl; } - sdInfo.commandExecuted = false; + updateInternalSdInfo(); + sdInfo.commandPending = false; sdFsmState = SdStates::IDLE; sdInfo.cycleCount = 0; sdcMan->setBlocking(false); @@ -599,9 +593,16 @@ ReturnValue_t CoreController::sdStateMachine() { actionHelper.finish(true, sdCommandingInfo.commander, sdCommandingInfo.actionId, returnvalue::OK); } - sif::info << "SD card update finished" << std::endl; + const char *modeStr = "UNKNOWN"; + if (sdInfo.cfgMode == SdCfgMode::COLD_REDUNDANT) { + modeStr = "COLD REDUNDANT"; + } else if (sdInfo.cfgMode == SdCfgMode::HOT_REDUNDANT) { + modeStr = "HOT REDUNDANT"; + } + sif::info << "SD card update into " << modeStr + << " mode finished. Active SD: " << sdInfo.activeChar << std::endl; if (not sdInfo.initFinished) { - updateSdInfoOther(); + updateInternalSdInfo(); sdInfo.initFinished = true; sif::info << "SD card initialization finished" << std::endl; } @@ -978,7 +979,7 @@ ReturnValue_t CoreController::gracefulShutdownTasks(xsc::Chip chip, xsc::Copy co return result; } -void CoreController::updateSdInfoOther() { +void CoreController::updateInternalSdInfo() { if (sdInfo.active == sd::SdCard::SLOT_0) { sdInfo.activeChar = "0"; sdInfo.otherChar = "1"; diff --git a/bsp_q7s/core/CoreController.h b/bsp_q7s/core/CoreController.h index 53a96cc3..8d6e802c 100644 --- a/bsp_q7s/core/CoreController.h +++ b/bsp_q7s/core/CoreController.h @@ -129,8 +129,7 @@ class CoreController : public ExtendedControllerBase { enum class SdStates { NONE, START, - GET_INFO, - SET_STATE_SELF, + UPDATE_SD_INFO_START, MOUNT_SELF, // Determine operations for other SD card, depending on redundancy configuration DETERMINE_OTHER, @@ -140,7 +139,7 @@ class CoreController : public ExtendedControllerBase { // Skip period because the shell command used to generate the info file sometimes is // missing the last performed operation if executed too early SKIP_CYCLE_BEFORE_INFO_UPDATE, - UPDATE_INFO, + UPDATE_SD_INFO_END, // SD initialization done IDLE }; @@ -159,13 +158,12 @@ class CoreController : public ExtendedControllerBase { SdCfgMode cfgMode = SdCfgMode::COLD_REDUNDANT; sd::SdCard active = sd::SdCard::NONE; sd::SdCard other = sd::SdCard::NONE; - sd::SdState activeState = sd::SdState::OFF; - sd::SdState otherState = sd::SdState::OFF; std::string activeChar = "0"; std::string otherChar = "1"; + sd::SdState activeState = sd::SdState::OFF; + sd::SdState otherState = sd::SdState::OFF; std::pair mountSwitch = {true, true}; - // Used to track whether a command was executed - bool commandExecuted = true; + bool commandPending = true; bool initFinished = false; SdCardManager::SdStatePair currentState; uint16_t cycleCount = 0; @@ -232,7 +230,7 @@ class CoreController : public ExtendedControllerBase { void initPrint(); ReturnValue_t sdStateMachine(); - void updateSdInfoOther(); + void updateInternalSdInfo(); ReturnValue_t sdCardSetup(sd::SdCard sdCard, sd::SdState targetState, std::string sdChar, bool printOutput = true); ReturnValue_t executeSwUpdate(SwUpdateSources sourceDir, const uint8_t* data, size_t size); diff --git a/bsp_q7s/fs/SdCardManager.cpp b/bsp_q7s/fs/SdCardManager.cpp index 89d3aaff..0375a71d 100644 --- a/bsp_q7s/fs/SdCardManager.cpp +++ b/bsp_q7s/fs/SdCardManager.cpp @@ -309,32 +309,6 @@ void SdCardManager::resetState() { currentOp = Operations::IDLE; } -ReturnValue_t SdCardManager::updateSdStatePair() { - using namespace std; - - std::error_code e; - if (not filesystem::exists(SD_STATE_FILE, e)) { - return STATUS_FILE_NEXISTS; - } - - // Now the file should exist in any case. Still check whether it exists. - fstream sdStatus(SD_STATE_FILE); - if (not sdStatus.good()) { - return STATUS_FILE_NEXISTS; - } - string line; - uint8_t idx = 0; - sd::SdCard currentSd = sd::SdCard::SLOT_0; - // Process status file line by line - while (std::getline(sdStatus, line)) { - processSdStatusLine(line, idx, currentSd); - } - if (sdStates.first != sd::SdState::MOUNTED && sdStates.second != sd::SdState::MOUNTED) { - sdCardActive = false; - } - return returnvalue::OK; -} - void SdCardManager::processSdStatusLine(std::string& line, uint8_t& idx, sd::SdCard& currentSd) { using namespace std; istringstream iss(line); @@ -407,6 +381,7 @@ ReturnValue_t SdCardManager::setPreferredSdCard(sd::SdCard sdCard) { } ReturnValue_t SdCardManager::updateSdCardStateFile() { + using namespace std; if (cmdExecutor.getCurrentState() == CommandExecutor::States::PENDING) { return CommandExecutor::COMMAND_PENDING; } @@ -414,10 +389,31 @@ ReturnValue_t SdCardManager::updateSdCardStateFile() { std::string updateCmd = "q7hw sd info all > " + std::string(SD_STATE_FILE); cmdExecutor.load(updateCmd, true, printCmdOutput); ReturnValue_t result = cmdExecutor.execute(); - if (blocking and result != returnvalue::OK) { + if (result != returnvalue::OK) { utility::handleSystemError(cmdExecutor.getLastError(), "SdCardManager::mountSdCard"); } - return result; + + std::error_code e; + if (not filesystem::exists(SD_STATE_FILE, e)) { + return STATUS_FILE_NEXISTS; + } + + // Now the file should exist in any case. Still check whether it exists. + fstream sdStatus(SD_STATE_FILE); + if (not sdStatus.good()) { + return STATUS_FILE_NEXISTS; + } + string line; + uint8_t idx = 0; + sd::SdCard currentSd = sd::SdCard::SLOT_0; + // Process status file line by line + while (std::getline(sdStatus, line)) { + processSdStatusLine(line, idx, currentSd); + } + if (sdStates.first != sd::SdState::MOUNTED && sdStates.second != sd::SdState::MOUNTED) { + sdCardActive = false; + } + return returnvalue::OK; } const char* SdCardManager::getCurrentMountPrefix() const { diff --git a/bsp_q7s/fs/SdCardManager.h b/bsp_q7s/fs/SdCardManager.h index b7e2a09f..74bf6e4b 100644 --- a/bsp_q7s/fs/SdCardManager.h +++ b/bsp_q7s/fs/SdCardManager.h @@ -117,16 +117,6 @@ class SdCardManager : public SystemObject, public SdCardMountedIF { ReturnValue_t switchOffSdCard(sd::SdCard sdCard, bool doUnmountSdCard = true, SdStatePair* statusPair = nullptr); - /** - * Update the state file or creates one if it does not exist. You need to call this - * function before calling #sdCardActive - * @return - * - returnvalue::OK if the state file was updated successfully - * - CommandExecutor::COMMAND_PENDING: Non-blocking command is pending - * - returnvalue::FAILED: blocking command failed - */ - ReturnValue_t updateSdCardStateFile(); - /** * Get the state of the SD cards. If the state file does not exist, this function will * take care of updating it. If it does not, the function will use the state file to get @@ -234,7 +224,15 @@ class SdCardManager : public SystemObject, public SdCardMountedIF { SdCardManager(); - ReturnValue_t updateSdStatePair(); + /** + * Update the state file or creates one if it does not exist. You need to call this + * function before calling #sdCardActive + * @return + * - returnvalue::OK if the state file was updated successfully + * - CommandExecutor::COMMAND_PENDING: Non-blocking command is pending + * - returnvalue::FAILED: blocking command failed + */ + ReturnValue_t updateSdCardStateFile(); ReturnValue_t setSdCardState(sd::SdCard sdCard, bool on); diff --git a/tmtc b/tmtc index 92ce64cd..43b530cd 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 92ce64cd39fb5d74af1358a436113322d9711dfb +Subproject commit 43b530cdb7dfe6774962bf4b8a880e1c9a6e6580