bugfix and simplifications for SDC state machine

This commit is contained in:
Robin Müller 2023-04-08 13:24:21 +02:00
parent 310f8f5f3c
commit 10f552f56a
No known key found for this signature in database
GPG Key ID: 11D4952C8CCEF814
5 changed files with 89 additions and 96 deletions

View File

@ -54,7 +54,6 @@ CoreController::CoreController(object_id_t objectId, bool enableHkSet)
// Set up state of SD card manager and own initial state. // Set up state of SD card manager and own initial state.
// Stopwatch watch; // Stopwatch watch;
sdcMan->updateSdCardStateFile(); sdcMan->updateSdCardStateFile();
sdcMan->updateSdStatePair();
SdCardManager::SdStatePair sdStates; SdCardManager::SdStatePair sdStates;
sdcMan->getSdCardsStatus(sdStates); sdcMan->getSdCardsStatus(sdStates);
auto sdCard = sdcMan->getPreferredSdCard(); auto sdCard = sdcMan->getPreferredSdCard();
@ -368,7 +367,7 @@ ReturnValue_t CoreController::initSdCardBlocking() {
} }
if (sdInfo.cfgMode == SdCfgMode::COLD_REDUNDANT) { if (sdInfo.cfgMode == SdCfgMode::COLD_REDUNDANT) {
updateSdInfoOther(); updateInternalSdInfo();
sif::info << "Cold redundant SD card configuration, preferred SD card: " sif::info << "Cold redundant SD card configuration, preferred SD card: "
<< static_cast<int>(sdInfo.active) << std::endl; << static_cast<int>(sdInfo.active) << std::endl;
result = sdColdRedundantBlockingInit(); result = sdColdRedundantBlockingInit();
@ -404,23 +403,23 @@ ReturnValue_t CoreController::sdStateMachine() {
} else { } else {
// Still update SD state file // Still update SD state file
if (sdInfo.cfgMode == SdCfgMode::PASSIVE) { if (sdInfo.cfgMode == SdCfgMode::PASSIVE) {
sdFsmState = SdStates::UPDATE_INFO; sdFsmState = SdStates::UPDATE_SD_INFO_END;
} else { } else {
sdInfo.cycleCount = 0; sdInfo.cycleCount = 0;
sdInfo.commandExecuted = false; sdInfo.commandPending = false;
sdFsmState = SdStates::GET_INFO; sdFsmState = SdStates::UPDATE_SD_INFO_START;
} }
} }
} }
// This lambda checks the non-blocking operation and assigns the new state on success. // This lambda checks the non-blocking operation of the SD card manager and assigns the new
// It returns true for an operation success and false otherwise // state on success. It returns true for an operation success and false otherwise
auto nonBlockingOpChecking = [&](SdStates newStateOnSuccess, uint16_t maxCycleCount, auto nonBlockingSdcOpChecking = [&](SdStates newStateOnSuccess, uint16_t maxCycleCount,
std::string opPrintout) { std::string opPrintout) {
SdCardManager::OpStatus status = sdcMan->checkCurrentOp(operation); SdCardManager::OpStatus status = sdcMan->checkCurrentOp(operation);
if (status == SdCardManager::OpStatus::SUCCESS) { if (status == SdCardManager::OpStatus::SUCCESS) {
sdFsmState = newStateOnSuccess; sdFsmState = newStateOnSuccess;
sdInfo.commandExecuted = false; sdInfo.commandPending = false;
sdInfo.cycleCount = 0; sdInfo.cycleCount = 0;
return true; return true;
} else if (sdInfo.cycleCount > 4) { } else if (sdInfo.cycleCount > 4) {
@ -431,26 +430,16 @@ ReturnValue_t CoreController::sdStateMachine() {
return false; return false;
}; };
if (sdFsmState == SdStates::GET_INFO) { if (sdFsmState == SdStates::UPDATE_SD_INFO_START) {
if (not sdInfo.commandExecuted) { if (not sdInfo.commandPending) {
// Create updated status file // Create updated status file
result = sdcMan->updateSdCardStateFile(); result = sdcMan->updateSdCardStateFile();
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
sif::warning << "CoreController::sdStateMachine: Updating SD card state file failed" sif::warning << "CoreController::sdStateMachine: Updating SD card state file failed"
<< std::endl; << 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); result = sdcMan->getSdCardsStatus(sdInfo.currentState);
updateSdInfoOther(); updateInternalSdInfo();
if (sdInfo.active != sd::SdCard::SLOT_0 and sdInfo.active != sd::SdCard::SLOT_1) { 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; sif::warning << "Preferred SD card invalid. Setting to card 0.." << std::endl;
sdInfo.active = sd::SdCard::SLOT_0; sdInfo.active = sd::SdCard::SLOT_0;
@ -478,12 +467,12 @@ ReturnValue_t CoreController::sdStateMachine() {
sdFsmState = SdStates::DETERMINE_OTHER; sdFsmState = SdStates::DETERMINE_OTHER;
} else if (sdInfo.activeState == sd::SdState::OFF) { } else if (sdInfo.activeState == sd::SdState::OFF) {
sdCardSetup(sdInfo.active, sd::SdState::ON, sdInfo.activeChar, false); sdCardSetup(sdInfo.active, sd::SdState::ON, sdInfo.activeChar, false);
sdInfo.commandExecuted = true; sdInfo.commandPending = true;
} else if (sdInfo.activeState == sd::SdState::ON) { } else if (sdInfo.activeState == sd::SdState::ON) {
sdFsmState = SdStates::MOUNT_SELF; sdFsmState = SdStates::MOUNT_SELF;
} }
} else { } else {
if (nonBlockingOpChecking(SdStates::MOUNT_SELF, 10, "Setting SDC state")) { if (nonBlockingSdcOpChecking(SdStates::MOUNT_SELF, 10, "Setting SDC state")) {
sdInfo.activeState = sd::SdState::ON; sdInfo.activeState = sd::SdState::ON;
currentStateSetter(sdInfo.active, sd::SdState::ON); currentStateSetter(sdInfo.active, sd::SdState::ON);
} }
@ -491,11 +480,11 @@ ReturnValue_t CoreController::sdStateMachine() {
} }
if (sdFsmState == SdStates::MOUNT_SELF) { if (sdFsmState == SdStates::MOUNT_SELF) {
if (not sdInfo.commandExecuted) { if (not sdInfo.commandPending) {
result = sdCardSetup(sdInfo.active, sd::SdState::MOUNTED, sdInfo.activeChar); result = sdCardSetup(sdInfo.active, sd::SdState::MOUNTED, sdInfo.activeChar);
sdInfo.commandExecuted = true; sdInfo.commandPending = true;
} else { } else {
if (nonBlockingOpChecking(SdStates::DETERMINE_OTHER, 5, "Mounting SD card")) { if (nonBlockingSdcOpChecking(SdStates::DETERMINE_OTHER, 5, "Mounting SD card")) {
sdcMan->setActiveSdCard(sdInfo.active); sdcMan->setActiveSdCard(sdInfo.active);
currMntPrefix = sdcMan->getCurrentMountPrefix(); currMntPrefix = sdcMan->getCurrentMountPrefix();
sdInfo.activeState = sd::SdState::MOUNTED; sdInfo.activeState = sd::SdState::MOUNTED;
@ -532,23 +521,23 @@ ReturnValue_t CoreController::sdStateMachine() {
if (sdFsmState == SdStates::SET_STATE_OTHER) { if (sdFsmState == SdStates::SET_STATE_OTHER) {
// Set state of other SD card to ON or OFF, depending on redundancy mode // Set state of other SD card to ON or OFF, depending on redundancy mode
if (sdInfo.cfgMode == SdCfgMode::COLD_REDUNDANT) { if (sdInfo.cfgMode == SdCfgMode::COLD_REDUNDANT) {
if (not sdInfo.commandExecuted) { if (not sdInfo.commandPending) {
result = sdCardSetup(sdInfo.other, sd::SdState::OFF, sdInfo.otherChar, false); result = sdCardSetup(sdInfo.other, sd::SdState::OFF, sdInfo.otherChar, false);
sdInfo.commandExecuted = true; sdInfo.commandPending = true;
} else { } else {
if (nonBlockingOpChecking(SdStates::SKIP_CYCLE_BEFORE_INFO_UPDATE, 10, if (nonBlockingSdcOpChecking(SdStates::SKIP_CYCLE_BEFORE_INFO_UPDATE, 10,
"Switching off other SD card")) { "Switching off other SD card")) {
sdInfo.otherState = sd::SdState::OFF; sdInfo.otherState = sd::SdState::OFF;
currentStateSetter(sdInfo.other, sd::SdState::OFF); currentStateSetter(sdInfo.other, sd::SdState::OFF);
} }
} }
} else if (sdInfo.cfgMode == SdCfgMode::HOT_REDUNDANT) { } 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); result = sdCardSetup(sdInfo.other, sd::SdState::ON, sdInfo.otherChar, false);
sdInfo.commandExecuted = true; sdInfo.commandPending = true;
} else { } else {
if (nonBlockingOpChecking(SdStates::MOUNT_UNMOUNT_OTHER, 10, if (nonBlockingSdcOpChecking(SdStates::MOUNT_UNMOUNT_OTHER, 10,
"Switching on other SD card")) { "Switching on other SD card")) {
sdInfo.otherState = sd::SdState::ON; sdInfo.otherState = sd::SdState::ON;
currentStateSetter(sdInfo.other, sd::SdState::ON); currentStateSetter(sdInfo.other, sd::SdState::ON);
} }
@ -559,21 +548,25 @@ ReturnValue_t CoreController::sdStateMachine() {
if (sdFsmState == SdStates::MOUNT_UNMOUNT_OTHER) { if (sdFsmState == SdStates::MOUNT_UNMOUNT_OTHER) {
// Mount or unmount other SD card, depending on redundancy mode // Mount or unmount other SD card, depending on redundancy mode
if (sdInfo.cfgMode == SdCfgMode::COLD_REDUNDANT) { if (sdInfo.cfgMode == SdCfgMode::COLD_REDUNDANT) {
if (not sdInfo.commandExecuted) { if (not sdInfo.commandPending) {
result = sdCardSetup(sdInfo.other, sd::SdState::ON, sdInfo.otherChar); result = sdCardSetup(sdInfo.other, sd::SdState::ON, sdInfo.otherChar);
sdInfo.commandExecuted = true; sdInfo.commandPending = true;
} else { } 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; sdInfo.otherState = sd::SdState::ON;
currentStateSetter(sdInfo.other, 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) { } else if (sdInfo.cfgMode == SdCfgMode::HOT_REDUNDANT) {
if (not sdInfo.commandExecuted) { if (not sdInfo.commandPending) {
result = sdCardSetup(sdInfo.other, sd::SdState::MOUNTED, sdInfo.otherChar); result = sdCardSetup(sdInfo.other, sd::SdState::MOUNTED, sdInfo.otherChar);
sdInfo.commandExecuted = true; sdInfo.commandPending = true;
} else { } 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; sdInfo.otherState = sd::SdState::MOUNTED;
currentStateSetter(sdInfo.other, 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) { if (sdFsmState == SdStates::SKIP_CYCLE_BEFORE_INFO_UPDATE) {
sdFsmState = SdStates::UPDATE_INFO; sdFsmState = SdStates::UPDATE_SD_INFO_END;
} else if (sdFsmState == SdStates::UPDATE_INFO) { } else if (sdFsmState == SdStates::UPDATE_SD_INFO_END) {
// Update status file // Update status file
result = sdcMan->updateSdCardStateFile(); result = sdcMan->updateSdCardStateFile();
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
sif::warning << "CoreController: Updating SD card state file failed" << std::endl; sif::warning << "CoreController: Updating SD card state file failed" << std::endl;
} }
sdInfo.commandExecuted = false; updateInternalSdInfo();
sdInfo.commandPending = false;
sdFsmState = SdStates::IDLE; sdFsmState = SdStates::IDLE;
sdInfo.cycleCount = 0; sdInfo.cycleCount = 0;
sdcMan->setBlocking(false); sdcMan->setBlocking(false);
@ -599,9 +593,16 @@ ReturnValue_t CoreController::sdStateMachine() {
actionHelper.finish(true, sdCommandingInfo.commander, sdCommandingInfo.actionId, actionHelper.finish(true, sdCommandingInfo.commander, sdCommandingInfo.actionId,
returnvalue::OK); 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) { if (not sdInfo.initFinished) {
updateSdInfoOther(); updateInternalSdInfo();
sdInfo.initFinished = true; sdInfo.initFinished = true;
sif::info << "SD card initialization finished" << std::endl; sif::info << "SD card initialization finished" << std::endl;
} }
@ -978,7 +979,7 @@ ReturnValue_t CoreController::gracefulShutdownTasks(xsc::Chip chip, xsc::Copy co
return result; return result;
} }
void CoreController::updateSdInfoOther() { void CoreController::updateInternalSdInfo() {
if (sdInfo.active == sd::SdCard::SLOT_0) { if (sdInfo.active == sd::SdCard::SLOT_0) {
sdInfo.activeChar = "0"; sdInfo.activeChar = "0";
sdInfo.otherChar = "1"; sdInfo.otherChar = "1";

View File

@ -129,8 +129,7 @@ class CoreController : public ExtendedControllerBase {
enum class SdStates { enum class SdStates {
NONE, NONE,
START, START,
GET_INFO, UPDATE_SD_INFO_START,
SET_STATE_SELF,
MOUNT_SELF, MOUNT_SELF,
// Determine operations for other SD card, depending on redundancy configuration // Determine operations for other SD card, depending on redundancy configuration
DETERMINE_OTHER, DETERMINE_OTHER,
@ -140,7 +139,7 @@ class CoreController : public ExtendedControllerBase {
// Skip period because the shell command used to generate the info file sometimes is // Skip period because the shell command used to generate the info file sometimes is
// missing the last performed operation if executed too early // missing the last performed operation if executed too early
SKIP_CYCLE_BEFORE_INFO_UPDATE, SKIP_CYCLE_BEFORE_INFO_UPDATE,
UPDATE_INFO, UPDATE_SD_INFO_END,
// SD initialization done // SD initialization done
IDLE IDLE
}; };
@ -159,13 +158,12 @@ class CoreController : public ExtendedControllerBase {
SdCfgMode cfgMode = SdCfgMode::COLD_REDUNDANT; SdCfgMode cfgMode = SdCfgMode::COLD_REDUNDANT;
sd::SdCard active = sd::SdCard::NONE; sd::SdCard active = sd::SdCard::NONE;
sd::SdCard other = 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 activeChar = "0";
std::string otherChar = "1"; std::string otherChar = "1";
sd::SdState activeState = sd::SdState::OFF;
sd::SdState otherState = sd::SdState::OFF;
std::pair<bool, bool> mountSwitch = {true, true}; std::pair<bool, bool> mountSwitch = {true, true};
// Used to track whether a command was executed bool commandPending = true;
bool commandExecuted = true;
bool initFinished = false; bool initFinished = false;
SdCardManager::SdStatePair currentState; SdCardManager::SdStatePair currentState;
uint16_t cycleCount = 0; uint16_t cycleCount = 0;
@ -232,7 +230,7 @@ class CoreController : public ExtendedControllerBase {
void initPrint(); void initPrint();
ReturnValue_t sdStateMachine(); ReturnValue_t sdStateMachine();
void updateSdInfoOther(); void updateInternalSdInfo();
ReturnValue_t sdCardSetup(sd::SdCard sdCard, sd::SdState targetState, std::string sdChar, ReturnValue_t sdCardSetup(sd::SdCard sdCard, sd::SdState targetState, std::string sdChar,
bool printOutput = true); bool printOutput = true);
ReturnValue_t executeSwUpdate(SwUpdateSources sourceDir, const uint8_t* data, size_t size); ReturnValue_t executeSwUpdate(SwUpdateSources sourceDir, const uint8_t* data, size_t size);

View File

@ -309,32 +309,6 @@ void SdCardManager::resetState() {
currentOp = Operations::IDLE; 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) { void SdCardManager::processSdStatusLine(std::string& line, uint8_t& idx, sd::SdCard& currentSd) {
using namespace std; using namespace std;
istringstream iss(line); istringstream iss(line);
@ -407,6 +381,7 @@ ReturnValue_t SdCardManager::setPreferredSdCard(sd::SdCard sdCard) {
} }
ReturnValue_t SdCardManager::updateSdCardStateFile() { ReturnValue_t SdCardManager::updateSdCardStateFile() {
using namespace std;
if (cmdExecutor.getCurrentState() == CommandExecutor::States::PENDING) { if (cmdExecutor.getCurrentState() == CommandExecutor::States::PENDING) {
return CommandExecutor::COMMAND_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); std::string updateCmd = "q7hw sd info all > " + std::string(SD_STATE_FILE);
cmdExecutor.load(updateCmd, true, printCmdOutput); cmdExecutor.load(updateCmd, true, printCmdOutput);
ReturnValue_t result = cmdExecutor.execute(); ReturnValue_t result = cmdExecutor.execute();
if (blocking and result != returnvalue::OK) { if (result != returnvalue::OK) {
utility::handleSystemError(cmdExecutor.getLastError(), "SdCardManager::mountSdCard"); 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 { const char* SdCardManager::getCurrentMountPrefix() const {

View File

@ -117,16 +117,6 @@ class SdCardManager : public SystemObject, public SdCardMountedIF {
ReturnValue_t switchOffSdCard(sd::SdCard sdCard, bool doUnmountSdCard = true, ReturnValue_t switchOffSdCard(sd::SdCard sdCard, bool doUnmountSdCard = true,
SdStatePair* statusPair = nullptr); 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 * 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 * 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(); 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); ReturnValue_t setSdCardState(sd::SdCard sdCard, bool on);

2
tmtc

@ -1 +1 @@
Subproject commit 92ce64cd39fb5d74af1358a436113322d9711dfb Subproject commit 43b530cdb7dfe6774962bf4b8a880e1c9a6e6580