From 90962c9f8e9538a03b487514343cf96fb936d755 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 27 Sep 2022 10:51:07 +0200 Subject: [PATCH] rudimentary SD commanding interface --- bsp_q7s/boardconfig/q7sConfig.h.in | 10 - bsp_q7s/core/CoreController.cpp | 387 +++++++++----------- bsp_q7s/core/CoreController.h | 35 +- bsp_q7s/fs/FilesystemHelper.cpp | 4 +- bsp_q7s/fs/SdCardManager.cpp | 9 +- bsp_q7s/fs/SdCardManager.h | 3 +- linux/devices/startracker/StrHelper.cpp | 4 +- mission/devices/PayloadPcduHandler.cpp | 2 +- mission/memory/SdCardMountedIF.h | 2 +- unittest/rebootLogic/src/CoreController.cpp | 12 +- unittest/rebootLogic/src/CoreController.h | 6 +- 11 files changed, 226 insertions(+), 248 deletions(-) diff --git a/bsp_q7s/boardconfig/q7sConfig.h.in b/bsp_q7s/boardconfig/q7sConfig.h.in index a678764a..ee9cd863 100644 --- a/bsp_q7s/boardconfig/q7sConfig.h.in +++ b/bsp_q7s/boardconfig/q7sConfig.h.in @@ -16,16 +16,6 @@ /** Other flags */ /*******************************************************************/ -#define Q7S_SD_NONE 0 -#define Q7S_SD_COLD_REDUNDANT 1 -#define Q7S_SD_HOT_REDUNDANT 2 -// The OBSW will perform different actions to set up the SD cards depending on the flag set here -// Set to Q7S_SD_NONE: Don't do anything -// Set to Q7S_COLD_REDUNDANT: On startup, get the prefered SD card, turn it on and mount it, and -// turn off the second SD card if it is on -// Set to Q7S_HOT_REDUNDANT: On startup, turn on both SD cards and mount them -#define Q7S_SD_CARD_CONFIG Q7S_SD_COLD_REDUNDANT - // Probably better if this is disabled for mission code. Convenient for development #define Q7S_CHECK_FOR_ALREADY_RUNNING_IMG 1 diff --git a/bsp_q7s/core/CoreController.cpp b/bsp_q7s/core/CoreController.cpp index 210e1a20..6e66c655 100644 --- a/bsp_q7s/core/CoreController.cpp +++ b/bsp_q7s/core/CoreController.cpp @@ -62,6 +62,8 @@ CoreController::CoreController(object_id_t objectId) eventQueue = QueueFactory::instance()->createMessageQueue(5, EventMessage::MAX_MESSAGE_SIZE); } +CoreController::~CoreController() {} + ReturnValue_t CoreController::handleCommandMessage(CommandMessage *message) { return ExtendedControllerBase::handleCommandMessage(message); } @@ -141,8 +143,8 @@ ReturnValue_t CoreController::initialize() { ReturnValue_t CoreController::initializeAfterTaskCreation() { ReturnValue_t result = returnvalue::OK; - sdInfo.pref = sdcMan->getPreferredSdCard(); - sdcMan->setActiveSdCard(sdInfo.pref); + sdInfo.active = sdcMan->getPreferredSdCard(); + sdcMan->setActiveSdCard(sdInfo.active); currMntPrefix = sdcMan->getCurrentMountPrefix(); if (BLOCKING_SD_INIT) { ReturnValue_t result = initSdCardBlocking(); @@ -209,6 +211,33 @@ ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_ case (OBSW_UPDATE_FROM_TMP): { return executeSwUpdate(SwUpdateSources::TMP_DIR, data, size); } + case (SWITCH_TO_SD_0): { + if (not startSdStateMachine(sd::SdCard::SLOT_0, SdCfgMode::COLD_REDUNDANT)) { + return HasActionsIF::IS_BUSY; + } + return returnvalue::OK; + } + case (SWITCH_TO_SD_1): { + if (not startSdStateMachine(sd::SdCard::SLOT_1, SdCfgMode::COLD_REDUNDANT)) { + return HasActionsIF::IS_BUSY; + } + return returnvalue::OK; + } + case (SWITCH_TO_BOTH_SD_CARDS): { + // An active SD still needs to be specified because the system needs to know which SD + // card to use for regular operations like telemetry storage. + if (size != 1) { + return HasActionsIF::INVALID_PARAMETERS; + } + if (data[0] != 0 and data[1] != 1) { + return HasActionsIF::INVALID_PARAMETERS; + } + auto active = static_cast(data[0]); + if (not startSdStateMachine(active, SdCfgMode::HOT_REDUNDANT)) { + return HasActionsIF::IS_BUSY; + } + return returnvalue::OK; + } case (SWITCH_IMG_LOCK): { if (size != 3) { return HasActionsIF::INVALID_PARAMETERS; @@ -256,60 +285,59 @@ ReturnValue_t CoreController::initSdCardBlocking() { if (result != returnvalue::OK) { sif::warning << "CoreController::initialize: Updating SD card state file failed" << std::endl; } -#if Q7S_SD_CARD_CONFIG == Q7S_SD_NONE - sif::info << "No SD card initialization will be performed" << std::endl; - return returnvalue::OK; -#else + if (sdInfo.cfgMode == SdCfgMode::PASSIVE) { + sif::info << "No SD card initialization will be performed" << std::endl; + return returnvalue::OK; + } result = sdcMan->getSdCardsStatus(sdInfo.currentState); if (result != returnvalue::OK) { sif::warning << "Getting SD card activity status failed" << std::endl; } -#if Q7S_SD_CARD_CONFIG == Q7S_SD_COLD_REDUNDANT - updateSdInfoOther(); - sif::info << "Cold redundant SD card configuration, preferred SD card: " - << static_cast(sdInfo.pref) << std::endl; - result = sdColdRedundantBlockingInit(); - // Update status file - sdcMan->updateSdCardStateFile(); - return result; -#elif Q7S_SD_CARD_CONFIG == Q7S_SD_HOT_REDUNDANT - sif::info << "Hot redundant SD card configuration" << std::endl; - sdCardSetup(sd::SdCard::SLOT_0, sd::SdState::MOUNTED, "0", false); - sdCardSetup(sd::SdCard::SLOT_1, sd::SdState::MOUNTED, "1", false); - // Update status file - sdcMan->updateSdCardStateFile(); + if (sdInfo.cfgMode == SdCfgMode::COLD_REDUNDANT) { + updateSdInfoOther(); + sif::info << "Cold redundant SD card configuration, preferred SD card: " + << static_cast(sdInfo.active) << std::endl; + result = sdColdRedundantBlockingInit(); + // Update status file + sdcMan->updateSdCardStateFile(); + return result; + } + if (sdInfo.cfgMode == SdCfgMode::HOT_REDUNDANT) { + sif::info << "Hot redundant SD card configuration" << std::endl; + sdCardSetup(sd::SdCard::SLOT_0, sd::SdState::MOUNTED, "0", false); + sdCardSetup(sd::SdCard::SLOT_1, sd::SdState::MOUNTED, "1", false); + // Update status file + sdcMan->updateSdCardStateFile(); + } return returnvalue::OK; -#endif - -#endif /* Q7S_SD_CARD_CONFIG != Q7S_SD_NONE */ } ReturnValue_t CoreController::sdStateMachine() { ReturnValue_t result = returnvalue::OK; SdCardManager::Operations operation; - if (sdInfo.state == SdStates::IDLE) { + if (sdFsmState == SdStates::IDLE) { // Nothing to do return result; } - if (sdInfo.state == SdStates::START) { + if (sdFsmState == SdStates::START) { // Init will be performed by separate function if (BLOCKING_SD_INIT) { - sdInfo.state = SdStates::IDLE; + sdFsmState = SdStates::IDLE; sdInfo.initFinished = true; return result; } else { // Still update SD state file -#if Q7S_SD_CARD_CONFIG == Q7S_SD_NONE - sdInfo.state = SdStates::UPDATE_INFO; -#else - sdInfo.cycleCount = 0; - sdInfo.commandExecuted = false; - sdInfo.state = SdStates::GET_INFO; -#endif + if (sdInfo.cfgMode == SdCfgMode::PASSIVE) { + sdFsmState = SdStates::UPDATE_INFO; + } else { + sdInfo.cycleCount = 0; + sdInfo.commandExecuted = false; + sdFsmState = SdStates::GET_INFO; + } } } @@ -319,7 +347,7 @@ ReturnValue_t CoreController::sdStateMachine() { std::string opPrintout) { SdCardManager::OpStatus status = sdcMan->checkCurrentOp(operation); if (status == SdCardManager::OpStatus::SUCCESS) { - sdInfo.state = newStateOnSuccess; + sdFsmState = newStateOnSuccess; sdInfo.commandExecuted = false; sdInfo.cycleCount = 0; return true; @@ -331,9 +359,9 @@ ReturnValue_t CoreController::sdStateMachine() { return false; }; - if (sdInfo.state == SdStates::GET_INFO) { + if (sdFsmState == SdStates::GET_INFO) { if (not sdInfo.commandExecuted) { - // Create update status file + // Create updated status file result = sdcMan->updateSdCardStateFile(); if (result != returnvalue::OK) { sif::warning << "CoreController::initialize: Updating SD card state file failed" @@ -345,139 +373,141 @@ ReturnValue_t CoreController::sdStateMachine() { } } - if (sdInfo.state == SdStates::SET_STATE_SELF) { + if (sdFsmState == SdStates::SET_STATE_SELF) { if (not sdInfo.commandExecuted) { result = sdcMan->getSdCardsStatus(sdInfo.currentState); - sdInfo.pref = sdcMan->getPreferredSdCard(); updateSdInfoOther(); - if (sdInfo.pref != sd::SdCard::SLOT_0 and sdInfo.pref != 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; - sdInfo.pref = sd::SdCard::SLOT_0; + sdInfo.active = sd::SdCard::SLOT_0; } if (result != returnvalue::OK) { sif::warning << "Getting SD card activity status failed" << std::endl; } -#if Q7S_SD_CARD_CONFIG == Q7S_SD_COLD_REDUNDANT - sif::info << "Cold redundant SD card configuration, preferred SD card: " - << static_cast(sdInfo.pref) << std::endl; -#endif - if (sdInfo.prefState == sd::SdState::MOUNTED) { + if (sdInfo.cfgMode == SdCfgMode::COLD_REDUNDANT) { + sif::info << "Cold redundant SD card configuration, preferred SD card: " + << static_cast(sdInfo.active) << std::endl; + } + if (sdInfo.activeState == sd::SdState::MOUNTED) { #if OBSW_VERBOSE_LEVEL >= 1 std::string mountString; - if (sdInfo.pref == sd::SdCard::SLOT_0) { + if (sdInfo.active == sd::SdCard::SLOT_0) { mountString = config::SD_0_MOUNT_POINT; } else { mountString = config::SD_1_MOUNT_POINT; } - sif::info << "SD card " << sdInfo.prefChar << " already on and mounted at " << mountString + sif::info << "SD card " << sdInfo.activeChar << " already on and mounted at " << mountString << std::endl; #endif - sdInfo.state = SdStates::DETERMINE_OTHER; - } else if (sdInfo.prefState == sd::SdState::OFF) { - sdCardSetup(sdInfo.pref, sd::SdState::ON, sdInfo.prefChar, false); + sdcMan->setActiveSdCard(sdInfo.active); + sdFsmState = SdStates::DETERMINE_OTHER; + } else if (sdInfo.activeState == sd::SdState::OFF) { + sdCardSetup(sdInfo.active, sd::SdState::ON, sdInfo.activeChar, false); sdInfo.commandExecuted = true; - } else if (sdInfo.prefState == sd::SdState::ON) { - sdInfo.state = SdStates::MOUNT_SELF; + } else if (sdInfo.activeState == sd::SdState::ON) { + sdFsmState = SdStates::MOUNT_SELF; } } else { if (nonBlockingOpChecking(SdStates::MOUNT_SELF, 10, "Setting SDC state")) { - sdInfo.prefState = sd::SdState::ON; - currentStateSetter(sdInfo.pref, sd::SdState::ON); + sdInfo.activeState = sd::SdState::ON; + currentStateSetter(sdInfo.active, sd::SdState::ON); } } } - if (sdInfo.state == SdStates::MOUNT_SELF) { + if (sdFsmState == SdStates::MOUNT_SELF) { if (not sdInfo.commandExecuted) { - result = sdCardSetup(sdInfo.pref, sd::SdState::MOUNTED, sdInfo.prefChar); + result = sdCardSetup(sdInfo.active, sd::SdState::MOUNTED, sdInfo.activeChar); sdInfo.commandExecuted = true; } else { if (nonBlockingOpChecking(SdStates::DETERMINE_OTHER, 5, "Mounting SD card")) { - sdInfo.prefState = sd::SdState::MOUNTED; - currentStateSetter(sdInfo.pref, sd::SdState::MOUNTED); + sdcMan->setActiveSdCard(sdInfo.active); + sdInfo.activeState = sd::SdState::MOUNTED; + currentStateSetter(sdInfo.active, sd::SdState::MOUNTED); } } } - if (sdInfo.state == SdStates::DETERMINE_OTHER) { + if (sdFsmState == SdStates::DETERMINE_OTHER) { // Determine whether any additional operations have to be done for the other SD card // 1. Cold redundant case: Other SD card needs to be unmounted and switched off // 2. Hot redundant case: Other SD card needs to be mounted and switched on -#if Q7S_SD_CARD_CONFIG == Q7S_SD_COLD_REDUNDANT - if (sdInfo.otherState == sd::SdState::ON) { - sdInfo.state = SdStates::SET_STATE_OTHER; - } else if (sdInfo.otherState == sd::SdState::MOUNTED) { - sdInfo.state = SdStates::MOUNT_UNMOUNT_OTHER; - } else { - // Is already off, update info, but with a small delay - sdInfo.state = SdStates::SKIP_CYCLE_BEFORE_INFO_UPDATE; + if (sdInfo.cfgMode == SdCfgMode::COLD_REDUNDANT) { + if (sdInfo.otherState == sd::SdState::ON) { + sdFsmState = SdStates::SET_STATE_OTHER; + } else if (sdInfo.otherState == sd::SdState::MOUNTED) { + sdFsmState = SdStates::MOUNT_UNMOUNT_OTHER; + } else { + // Is already off, update info, but with a small delay + sdFsmState = SdStates::SKIP_CYCLE_BEFORE_INFO_UPDATE; + } + } else if (sdInfo.cfgMode == SdCfgMode::HOT_REDUNDANT) { + if (sdInfo.otherState == sd::SdState::OFF) { + sdFsmState = SdStates::SET_STATE_OTHER; + } else if (sdInfo.otherState == sd::SdState::ON) { + sdFsmState = SdStates::MOUNT_UNMOUNT_OTHER; + } else { + // Is already on and mounted, update info + sdFsmState = SdStates::SKIP_CYCLE_BEFORE_INFO_UPDATE; + } } -#elif Q7S_SD_CARD_CONFIG == Q7S_SD_HOT_REDUNDANT - if (sdInfo.otherState == sd::SdState::OFF) { - sdInfo.state = SdStates::SET_STATE_OTHER; - } else if (sdInfo.otherState == sd::SdState::ON) { - sdInfo.state = SdStates::MOUNT_UNMOUNT_OTHER; - } else { - // Is already on and mounted, update info - sdInfo.state = SdStates::SKIP_CYCLE_BEFORE_INFO_UPDATE; - } -#endif } - if (sdInfo.state == SdStates::SET_STATE_OTHER) { + if (sdFsmState == SdStates::SET_STATE_OTHER) { // Set state of other SD card to ON or OFF, depending on redundancy mode -#if Q7S_SD_CARD_CONFIG == Q7S_SD_COLD_REDUNDANT - if (not sdInfo.commandExecuted) { - result = sdCardSetup(sdInfo.other, sd::SdState::OFF, sdInfo.otherChar, false); - sdInfo.commandExecuted = true; - } else { - if (nonBlockingOpChecking(SdStates::SKIP_CYCLE_BEFORE_INFO_UPDATE, 10, - "Switching off other SD card")) { - sdInfo.otherState = sd::SdState::OFF; - currentStateSetter(sdInfo.other, sd::SdState::OFF); + if (sdInfo.cfgMode == SdCfgMode::COLD_REDUNDANT) { + if (not sdInfo.commandExecuted) { + result = sdCardSetup(sdInfo.other, sd::SdState::OFF, sdInfo.otherChar, false); + sdInfo.commandExecuted = true; + } else { + if (nonBlockingOpChecking(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) { + result = sdCardSetup(sdInfo.other, sd::SdState::ON, sdInfo.otherChar, false); + sdInfo.commandExecuted = true; + } else { + if (nonBlockingOpChecking(SdStates::MOUNT_UNMOUNT_OTHER, 10, + "Switching on other SD card")) { + sdInfo.otherState = sd::SdState::ON; + currentStateSetter(sdInfo.other, sd::SdState::ON); + } } } -#elif Q7S_SD_CARD_CONFIG == Q7S_SD_HOT_REDUNDANT - if (not sdInfo.commandExecuted) { - result = sdCardSetup(sdInfo.other, sd::SdState::ON, sdInfo.otherChar, false); - sdInfo.commandExecuted = true; - } else { - if (nonBlockingOpChecking(SdStates::MOUNT_UNMOUNT_OTHER, 10, "Switching on other SD card")) { - sdInfo.otherState = sd::SdState::ON; - currentStateSetter(sdInfo.other, sd::SdState::ON); - } - } -#endif } - if (sdInfo.state == SdStates::MOUNT_UNMOUNT_OTHER) { + if (sdFsmState == SdStates::MOUNT_UNMOUNT_OTHER) { // Mount or unmount other SD card, depending on redundancy mode -#if Q7S_SD_CARD_CONFIG == Q7S_SD_COLD_REDUNDANT - if (not sdInfo.commandExecuted) { - result = sdCardSetup(sdInfo.other, sd::SdState::ON, sdInfo.otherChar); - sdInfo.commandExecuted = true; - } else { - if (nonBlockingOpChecking(SdStates::SET_STATE_OTHER, 10, "Unmounting other SD card")) { - sdInfo.otherState = sd::SdState::ON; - currentStateSetter(sdInfo.other, sd::SdState::ON); + if (sdInfo.cfgMode == SdCfgMode::COLD_REDUNDANT) { + if (not sdInfo.commandExecuted) { + result = sdCardSetup(sdInfo.other, sd::SdState::ON, sdInfo.otherChar); + sdInfo.commandExecuted = true; + } else { + if (nonBlockingOpChecking(SdStates::SET_STATE_OTHER, 10, "Unmounting other SD card")) { + sdInfo.otherState = sd::SdState::ON; + currentStateSetter(sdInfo.other, sd::SdState::ON); + } + } + } else if (sdInfo.cfgMode == SdCfgMode::HOT_REDUNDANT) { + if (not sdInfo.commandExecuted) { + result = sdCardSetup(sdInfo.other, sd::SdState::MOUNTED, sdInfo.otherChar); + sdInfo.commandExecuted = true; + } else { + if (nonBlockingOpChecking(SdStates::UPDATE_INFO, 4, "Mounting other SD card")) { + sdInfo.otherState = sd::SdState::MOUNTED; + currentStateSetter(sdInfo.other, sd::SdState::MOUNTED); + } } } -#elif Q7S_SD_CARD_CONFIG == Q7S_SD_HOT_REDUNDANT - if (not sdInfo.commandExecuted) { - result = sdCardSetup(sdInfo.other, sd::SdState::MOUNTED, sdInfo.otherChar); - sdInfo.commandExecuted = true; - } else { - if (nonBlockingOpChecking(SdStates::UPDATE_INFO, 4, "Mounting other SD card")) { - sdInfo.otherState = sd::SdState::MOUNTED; - currentStateSetter(sdInfo.other, sd::SdState::MOUNTED); - } - } -#endif } - if (sdInfo.state == SdStates::SKIP_CYCLE_BEFORE_INFO_UPDATE) { - sdInfo.state = SdStates::UPDATE_INFO; - } else if (sdInfo.state == SdStates::UPDATE_INFO) { + if (sdFsmState == SdStates::SKIP_CYCLE_BEFORE_INFO_UPDATE) { + sdFsmState = SdStates::UPDATE_INFO; + } else if (sdFsmState == SdStates::UPDATE_INFO) { // It is assumed that all tasks are running by the point this section is reached. // Therefore, perform this operation in blocking mode because it does not take long // and the ready state of the SD card is available sooner @@ -488,10 +518,15 @@ ReturnValue_t CoreController::sdStateMachine() { sif::warning << "CoreController::initialize: Updating SD card state file failed" << std::endl; } sdInfo.commandExecuted = false; - sdInfo.state = SdStates::IDLE; + sdFsmState = SdStates::IDLE; sdInfo.cycleCount = 0; sdcMan->setBlocking(false); sdcMan->getSdCardsStatus(sdInfo.currentState); + if (sdCommandingInfo.cmdPending) { + sdCommandingInfo.cmdPending = false; + actionHelper.finish(true, sdCommandingInfo.commander, sdCommandingInfo.actionId, + returnvalue::OK); + } if (not sdInfo.initFinished) { updateSdInfoOther(); sdInfo.initFinished = true; @@ -499,81 +534,10 @@ ReturnValue_t CoreController::sdStateMachine() { } } - if (sdInfo.state == SdStates::SET_STATE_FROM_COMMAND) { - if (not sdInfo.commandExecuted) { - executeNextExternalSdCommand(); - } else { - checkExternalSdCommandStatus(); - } - } - sdInfo.cycleCount++; return returnvalue::OK; } -void CoreController::executeNextExternalSdCommand() { - std::string sdChar; - sd::SdState currentStateOfCard = sd::SdState::OFF; - if (sdInfo.commandedCard == sd::SdCard::SLOT_0) { - sdChar = "0"; - currentStateOfCard = sdInfo.currentState.first; - } else { - sdChar = "1"; - currentStateOfCard = sdInfo.currentState.second; - } - if (currentStateOfCard == sd::SdState::OFF) { - if (sdInfo.commandedState == sd::SdState::ON) { - sdInfo.currentlyCommandedState = sdInfo.commandedState; - } else if (sdInfo.commandedState == sd::SdState::MOUNTED) { - sdInfo.currentlyCommandedState = sd::SdState::ON; - } else { - // SD card is already on target state - sdInfo.commandFinished = true; - sdInfo.state = SdStates::IDLE; - } - } else if (currentStateOfCard == sd::SdState::ON) { - if (sdInfo.commandedState == sd::SdState::OFF or - sdInfo.commandedState == sd::SdState::MOUNTED) { - sdInfo.currentlyCommandedState = sdInfo.commandedState; - } else { - // Already on target state - sdInfo.commandFinished = true; - sdInfo.state = SdStates::IDLE; - } - } else if (currentStateOfCard == sd::SdState::MOUNTED) { - if (sdInfo.commandedState == sd::SdState::ON) { - sdInfo.currentlyCommandedState = sdInfo.commandedState; - } else if (sdInfo.commandedState == sd::SdState::OFF) { - // This causes an unmount in sdCardSetup - sdInfo.currentlyCommandedState = sd::SdState::ON; - } else { - sdInfo.commandFinished = true; - } - } - sdCardSetup(sdInfo.commandedCard, sdInfo.commandedState, sdChar); - sdInfo.commandExecuted = true; -} - -void CoreController::checkExternalSdCommandStatus() { - SdCardManager::Operations operation; - SdCardManager::OpStatus status = sdcMan->checkCurrentOp(operation); - if (status == SdCardManager::OpStatus::SUCCESS) { - if (sdInfo.currentlyCommandedState == sdInfo.commandedState) { - sdInfo.state = SdStates::SKIP_CYCLE_BEFORE_INFO_UPDATE; - sdInfo.commandFinished = true; - } else { - // stay on same state machine state because the target state was not reached yet. - sdInfo.cycleCount = 0; - } - currentStateSetter(sdInfo.commandedCard, sdInfo.currentlyCommandedState); - sdInfo.commandExecuted = false; - } else if (sdInfo.cycleCount > 4) { - sif::warning << "CoreController::sdStateMachine: Commanding SD state " - "takes too long" - << std::endl; - } -} - void CoreController::currentStateSetter(sd::SdCard sdCard, sd::SdState newState) { if (sdCard == sd::SdCard::SLOT_0) { sdInfo.currentState.first = newState; @@ -645,12 +609,12 @@ ReturnValue_t CoreController::sdCardSetup(sd::SdCard sdCard, sd::SdState targetS ReturnValue_t CoreController::sdColdRedundantBlockingInit() { ReturnValue_t result = returnvalue::OK; - result = sdCardSetup(sdInfo.pref, sd::SdState::MOUNTED, sdInfo.prefChar); + result = sdCardSetup(sdInfo.active, sd::SdState::MOUNTED, sdInfo.activeChar); if (result != SdCardManager::ALREADY_MOUNTED and result != returnvalue::OK) { sif::warning << "Setting up preferred card " << sdInfo.otherChar << " in cold redundant mode failed" << std::endl; // Try other SD card and mark set up operation as failed - sdCardSetup(sdInfo.pref, sd::SdState::MOUNTED, sdInfo.prefChar); + sdCardSetup(sdInfo.active, sd::SdState::MOUNTED, sdInfo.activeChar); result = returnvalue::FAILED; } @@ -967,21 +931,19 @@ ReturnValue_t CoreController::gracefulShutdownTasks(xsc::Chip chip, xsc::Copy co return result; } -CoreController::~CoreController() {} - void CoreController::updateSdInfoOther() { - if (sdInfo.pref == sd::SdCard::SLOT_0) { - sdInfo.prefChar = "0"; + if (sdInfo.active == sd::SdCard::SLOT_0) { + sdInfo.activeChar = "0"; sdInfo.otherChar = "1"; sdInfo.otherState = sdInfo.currentState.second; - sdInfo.prefState = sdInfo.currentState.first; + sdInfo.activeState = sdInfo.currentState.first; sdInfo.other = sd::SdCard::SLOT_1; - } else if (sdInfo.pref == sd::SdCard::SLOT_1) { - sdInfo.prefChar = "1"; + } else if (sdInfo.active == sd::SdCard::SLOT_1) { + sdInfo.activeChar = "1"; sdInfo.otherChar = "0"; sdInfo.otherState = sdInfo.currentState.first; - sdInfo.prefState = sdInfo.currentState.second; + sdInfo.activeState = sdInfo.currentState.second; sdInfo.other = sd::SdCard::SLOT_0; } else { sif::warning << "CoreController::updateSdInfoOther: Invalid SD card passed" << std::endl; @@ -1254,7 +1216,7 @@ void CoreController::performWatchdogControlOperation() { void CoreController::performMountedSdCardOperations() { auto mountedSdCardOp = [&](bool &mntSwitch, sd::SdCard sdCard, std::string mntPoint) { if (mntSwitch) { - bool sdCardMounted = sdcMan->isSdCardMounted(sdCard); + bool sdCardMounted = sdcMan->isSdCardUsable(sdCard); if (sdCardMounted and not performOneShotSdCardOpsSwitch) { std::ostringstream path; path << mntPoint << "/" << CONF_FOLDER; @@ -1269,7 +1231,7 @@ void CoreController::performMountedSdCardOperations() { mntSwitch = false; } }; - if (sdInfo.pref == sd::SdCard::SLOT_1) { + if (sdInfo.active == sd::SdCard::SLOT_1) { mountedSdCardOp(sdInfo.mountSwitch.second, sd::SdCard::SLOT_1, config::SD_1_MOUNT_POINT); mountedSdCardOp(sdInfo.mountSwitch.first, sd::SdCard::SLOT_0, config::SD_0_MOUNT_POINT); } else { @@ -1283,13 +1245,15 @@ ReturnValue_t CoreController::performSdCardCheck() { bool mountedReadOnly = false; SdCardManager::SdStatePair active; sdcMan->getSdCardsStatus(active); + if (sdFsmState != SdStates::IDLE) { + return returnvalue::OK; + } auto sdCardCheck = [&](sd::SdCard sdCard) { ReturnValue_t result = sdcMan->isSdCardMountedReadOnly(sdCard, mountedReadOnly); if (result != returnvalue::OK) { sif::error << "CoreController::performSdCardCheck: Could not check " "read-only mount state" << std::endl; - mountedReadOnly = true; } if (mountedReadOnly) { int linuxErrno = 0; @@ -1986,6 +1950,17 @@ ReturnValue_t CoreController::executeSwUpdate(SwUpdateSources sourceDir, const u return HasActionsIF::EXECUTION_FINISHED; } +bool CoreController::startSdStateMachine(sd::SdCard targetActiveSd, SdCfgMode mode) { + if (sdFsmState != SdStates::IDLE or sdCommandingInfo.cmdPending) { + return false; + } + sdFsmState = SdStates::START; + sdInfo.active = targetActiveSd; + sdInfo.cfgMode = mode; + sdCommandingInfo.cmdPending = true; + return true; +} + bool CoreController::isNumber(const std::string &s) { return !s.empty() && std::find_if(s.begin(), s.end(), [](unsigned char c) { return !std::isdigit(c); }) == s.end(); diff --git a/bsp_q7s/core/CoreController.h b/bsp_q7s/core/CoreController.h index e49411a4..2f96e033 100644 --- a/bsp_q7s/core/CoreController.h +++ b/bsp_q7s/core/CoreController.h @@ -79,6 +79,10 @@ class CoreController : public ExtendedControllerBase { static constexpr ActionId_t OBSW_UPDATE_FROM_SD_1 = 11; static constexpr ActionId_t OBSW_UPDATE_FROM_TMP = 12; + static constexpr ActionId_t SWITCH_TO_SD_0 = 16; + static constexpr ActionId_t SWITCH_TO_SD_1 = 17; + static constexpr ActionId_t SWITCH_TO_BOTH_SD_CARDS = 18; + //! Reboot using the xsc_boot_copy command static constexpr ActionId_t XSC_REBOOT_OBC = 32; static constexpr ActionId_t MOUNT_OTHER_COPY = 33; @@ -164,9 +168,7 @@ class CoreController : public ExtendedControllerBase { SKIP_CYCLE_BEFORE_INFO_UPDATE, UPDATE_INFO, // SD initialization done - IDLE, - // Used if SD switches or mount commands are issued via telecommand - SET_STATE_FROM_COMMAND, + IDLE }; enum class SwUpdateSources { SD_0, SD_1, TMP_DIR }; @@ -176,27 +178,31 @@ class CoreController : public ExtendedControllerBase { SdCardManager* sdcMan = nullptr; MessageQueueIF* eventQueue = nullptr; - struct SdInfo { - sd::SdCard pref = sd::SdCard::NONE; + SdStates sdFsmState = SdStates::START; + enum SdCfgMode { PASSIVE, COLD_REDUNDANT, HOT_REDUNDANT }; + + struct SdFsmParams { + SdCfgMode cfgMode = SdCfgMode::COLD_REDUNDANT; + sd::SdCard active = sd::SdCard::NONE; sd::SdCard other = sd::SdCard::NONE; - sd::SdState prefState = sd::SdState::OFF; + sd::SdState activeState = sd::SdState::OFF; sd::SdState otherState = sd::SdState::OFF; - std::string prefChar = "0"; + std::string activeChar = "0"; std::string otherChar = "1"; std::pair mountSwitch = {true, true}; - SdStates state = SdStates::START; // Used to track whether a command was executed bool commandExecuted = true; bool initFinished = false; SdCardManager::SdStatePair currentState; uint16_t cycleCount = 0; - // These two flags are related to external commanding - bool commandIssued = false; - bool commandFinished = false; - sd::SdState currentlyCommandedState = sd::SdState::OFF; - sd::SdCard commandedCard = sd::SdCard::NONE; - sd::SdState commandedState = sd::SdState::OFF; } sdInfo; + + struct SdCommanding { + bool cmdPending = false; + MessageQueueId_t commander = MessageQueueIF::NO_QUEUE; + DeviceCommandId_t actionId; + } sdCommandingInfo; + RebootFile rebootFile = {}; std::string currMntPrefix; bool performOneShotSdCardOpsSwitch = true; @@ -227,6 +233,7 @@ class CoreController : public ExtendedControllerBase { ReturnValue_t initBootCopy(); ReturnValue_t initWatchdogFifo(); ReturnValue_t initSdCardBlocking(); + bool startSdStateMachine(sd::SdCard targetActiveSd, SdCfgMode mode); void initPrint(); ReturnValue_t sdStateMachine(); diff --git a/bsp_q7s/fs/FilesystemHelper.cpp b/bsp_q7s/fs/FilesystemHelper.cpp index 68bf2178..bc435d1c 100644 --- a/bsp_q7s/fs/FilesystemHelper.cpp +++ b/bsp_q7s/fs/FilesystemHelper.cpp @@ -16,13 +16,13 @@ ReturnValue_t FilesystemHelper::checkPath(std::string path) { return returnvalue::FAILED; } if (path.substr(0, sizeof(config::SD_0_MOUNT_POINT)) == std::string(config::SD_0_MOUNT_POINT)) { - if (!sdcMan->isSdCardMounted(sd::SLOT_0)) { + if (!sdcMan->isSdCardUsable(sd::SLOT_0)) { sif::warning << "FilesystemHelper::checkPath: SD card 0 not mounted" << std::endl; return SD_NOT_MOUNTED; } } else if (path.substr(0, sizeof(config::SD_1_MOUNT_POINT)) == std::string(config::SD_1_MOUNT_POINT)) { - if (!sdcMan->isSdCardMounted(sd::SLOT_0)) { + if (!sdcMan->isSdCardUsable(sd::SLOT_0)) { sif::warning << "FilesystemHelper::checkPath: SD card 1 not mounted" << std::endl; return SD_NOT_MOUNTED; } diff --git a/bsp_q7s/fs/SdCardManager.cpp b/bsp_q7s/fs/SdCardManager.cpp index 68155a20..ea238225 100644 --- a/bsp_q7s/fs/SdCardManager.cpp +++ b/bsp_q7s/fs/SdCardManager.cpp @@ -213,6 +213,9 @@ ReturnValue_t SdCardManager::getSdCardsStatus(SdStatePair& active) { while (std::getline(sdStatus, line)) { processSdStatusLine(active, line, idx, currentSd); } + if (active.first != sd::SdState::MOUNTED && active.second != sd::SdState::MOUNTED) { + sdCardActive = false; + } return returnvalue::OK; } @@ -466,7 +469,7 @@ void SdCardManager::setBlocking(bool blocking) { this->blocking = blocking; } void SdCardManager::setPrintCommandOutput(bool print) { this->printCmdOutput = print; } -bool SdCardManager::isSdCardMounted(sd::SdCard sdCard) { +bool SdCardManager::isSdCardUsable(sd::SdCard sdCard) { SdCardManager::SdStatePair active; ReturnValue_t result = this->getSdCardsStatus(active); @@ -496,8 +499,10 @@ ReturnValue_t SdCardManager::isSdCardMountedReadOnly(sd::SdCard sdcard, bool& re std::ostringstream command; if (sdcard == sd::SdCard::SLOT_0) { command << "grep -q '" << config::SD_0_MOUNT_POINT << " vfat ro,' /proc/mounts"; - } else { + } else if (sdcard == sd::SdCard::SLOT_1) { command << "grep -q '" << config::SD_1_MOUNT_POINT << " vfat ro,' /proc/mounts"; + } else { + return returnvalue::FAILED; } ReturnValue_t result = cmdExecutor.load(command.str(), true, false); if (result != returnvalue::OK) { diff --git a/bsp_q7s/fs/SdCardManager.h b/bsp_q7s/fs/SdCardManager.h index 28886ffe..ad222687 100644 --- a/bsp_q7s/fs/SdCardManager.h +++ b/bsp_q7s/fs/SdCardManager.h @@ -206,7 +206,7 @@ class SdCardManager : public SystemObject, public SdCardMountedIF { * * @return true if mounted, otherwise false */ - bool isSdCardMounted(sd::SdCard sdCard) override; + bool isSdCardUsable(sd::SdCard sdCard) override; ReturnValue_t isSdCardMountedReadOnly(sd::SdCard sdcard, bool& readOnly); @@ -218,6 +218,7 @@ class SdCardManager : public SystemObject, public SdCardMountedIF { CommandExecutor cmdExecutor; Operations currentOp = Operations::IDLE; bool blocking = false; + bool sdCardActive = true; bool printCmdOutput = true; MutexIF* mutex = nullptr; diff --git a/linux/devices/startracker/StrHelper.cpp b/linux/devices/startracker/StrHelper.cpp index fa3971af..685cf3b3 100644 --- a/linux/devices/startracker/StrHelper.cpp +++ b/linux/devices/startracker/StrHelper.cpp @@ -543,13 +543,13 @@ ReturnValue_t StrHelper::checkReplyPosition(uint32_t expectedPosition) { #ifdef XIPHOS_Q7S ReturnValue_t StrHelper::checkPath(std::string name) { if (name.substr(0, sizeof(config::SD_0_MOUNT_POINT)) == std::string(config::SD_0_MOUNT_POINT)) { - if (!sdcMan->isSdCardMounted(sd::SLOT_0)) { + if (!sdcMan->isSdCardUsable(sd::SLOT_0)) { sif::warning << "StrHelper::checkPath: SD card 0 not mounted" << std::endl; return SD_NOT_MOUNTED; } } else if (name.substr(0, sizeof(config::SD_1_MOUNT_POINT)) == std::string(config::SD_1_MOUNT_POINT)) { - if (!sdcMan->isSdCardMounted(sd::SLOT_0)) { + if (!sdcMan->isSdCardUsable(sd::SLOT_0)) { sif::warning << "StrHelper::checkPath: SD card 1 not mounted" << std::endl; return SD_NOT_MOUNTED; } diff --git a/mission/devices/PayloadPcduHandler.cpp b/mission/devices/PayloadPcduHandler.cpp index e643a945..3a027b9a 100644 --- a/mission/devices/PayloadPcduHandler.cpp +++ b/mission/devices/PayloadPcduHandler.cpp @@ -492,7 +492,7 @@ void PayloadPcduHandler::checkAdcValues() { void PayloadPcduHandler::checkJsonFileInit() { if (not jsonFileInitComplete) { sd::SdCard activeSd = sdcMan->getActiveSdCard(); - if (sdcMan->isSdCardMounted(activeSd)) { + if (sdcMan->isSdCardUsable(activeSd)) { params.initialize(sdcMan->getCurrentMountPrefix()); jsonFileInitComplete = true; } diff --git a/mission/memory/SdCardMountedIF.h b/mission/memory/SdCardMountedIF.h index 853c7e8d..453a44d7 100644 --- a/mission/memory/SdCardMountedIF.h +++ b/mission/memory/SdCardMountedIF.h @@ -9,7 +9,7 @@ class SdCardMountedIF { public: virtual ~SdCardMountedIF(){}; virtual std::string getCurrentMountPrefix() const = 0; - virtual bool isSdCardMounted(sd::SdCard sdCard) = 0; + virtual bool isSdCardUsable(sd::SdCard sdCard) = 0; virtual sd::SdCard getPreferredSdCard() const = 0; virtual void setActiveSdCard(sd::SdCard sdCard) = 0; virtual sd::SdCard getActiveSdCard() const = 0; diff --git a/unittest/rebootLogic/src/CoreController.cpp b/unittest/rebootLogic/src/CoreController.cpp index 87268b45..2bc8bbef 100644 --- a/unittest/rebootLogic/src/CoreController.cpp +++ b/unittest/rebootLogic/src/CoreController.cpp @@ -21,7 +21,7 @@ CoreController::CoreController() { void CoreController::performRebootFileHandling(bool recreateFile) { using namespace std; - std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE; + std::string path = sdcMan->getCurrentMountPrefix(sdInfo.active) + REBOOT_FILE; if (not std::filesystem::exists(path) or recreateFile) { #if OBSW_VERBOSE_LEVEL >= 1 sif::info << "CoreController::performRebootFileHandling: Recreating reboot file" << std::endl; @@ -400,7 +400,7 @@ bool CoreController::parseRebootFile(std::string path, RebootFile &rf) { } void CoreController::resetRebootCount(xsc::Chip tgtChip, xsc::Copy tgtCopy) { - std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE; + std::string path = sdcMan->getCurrentMountPrefix(sdInfo.active) + REBOOT_FILE; // Disable the reboot file mechanism parseRebootFile(path, rebootFile); if (tgtChip == xsc::ALL_CHIP and tgtCopy == xsc::ALL_COPY) { @@ -427,7 +427,7 @@ void CoreController::resetRebootCount(xsc::Chip tgtChip, xsc::Copy tgtCopy) { } void CoreController::rewriteRebootFile(RebootFile file) { - std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE; + std::string path = sdcMan->getCurrentMountPrefix(sdInfo.active) + REBOOT_FILE; std::ofstream rebootFile(path); if (rebootFile.is_open()) { // Initiate reboot file first. Reboot handling will be on on initialization @@ -450,7 +450,7 @@ ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_ if (size < 1) { return HasActionsIF::INVALID_PARAMETERS; } - std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE; + std::string path = sdcMan->getCurrentMountPrefix(sdInfo.active) + REBOOT_FILE; // Disable the reboot file mechanism parseRebootFile(path, rebootFile); if (data[0] == 0) { @@ -490,7 +490,7 @@ ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_ if (size < 1) { return HasActionsIF::INVALID_PARAMETERS; } - std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE; + std::string path = sdcMan->getCurrentMountPrefix(sdInfo.active) + REBOOT_FILE; // Disable the reboot file mechanism parseRebootFile(path, rebootFile); rebootFile.maxCount = data[0]; @@ -504,7 +504,7 @@ ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_ } void CoreController::setRebootMechanismLock(bool lock, xsc::Chip tgtChip, xsc::Copy tgtCopy) { - std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE; + std::string path = sdcMan->getCurrentMountPrefix(sdInfo.active) + REBOOT_FILE; // Disable the reboot file mechanism parseRebootFile(path, rebootFile); if (tgtChip == xsc::CHIP_0) { diff --git a/unittest/rebootLogic/src/CoreController.h b/unittest/rebootLogic/src/CoreController.h index c79a4ccd..1846c27f 100644 --- a/unittest/rebootLogic/src/CoreController.h +++ b/unittest/rebootLogic/src/CoreController.h @@ -66,9 +66,9 @@ class CoreController { void rewriteRebootFile(RebootFile file); private: - struct SdInfo { - sd::SdCard pref = sd::SdCard::NONE; - sd::SdState prefState = sd::SdState::OFF; + struct SdFsmParams { + sd::SdCard active = sd::SdCard::NONE; + sd::SdState activeState = sd::SdState::OFF; sd::SdCard other = sd::SdCard::NONE; sd::SdState otherState = sd::SdState::OFF; } sdInfo;