diff --git a/bsp_q7s/core/CoreController.cpp b/bsp_q7s/core/CoreController.cpp index b1ca47d9..606646bf 100644 --- a/bsp_q7s/core/CoreController.cpp +++ b/bsp_q7s/core/CoreController.cpp @@ -4,7 +4,9 @@ #include "watchdogConf.h" #include "fsfw/FSFWVersion.h" +#include "fsfw/timemanager/Stopwatch.h" #include "fsfw/serviceinterface/ServiceInterface.h" +#include "fsfw/osal/linux/Timer.h" #if OBSW_USE_TMTC_TCP_BRIDGE == 0 #include "fsfw/osal/common/UdpTmTcBridge.h" #else @@ -23,8 +25,8 @@ CoreController::Chip CoreController::currentChip = Chip::NO_CHIP; CoreController::Copy CoreController::currentCopy = Copy::NO_COPY; CoreController::CoreController(object_id_t objectId): - ExtendedControllerBase(objectId, objects::NO_OBJECT, 5), - opDivider(5) { + ExtendedControllerBase(objectId, objects::NO_OBJECT, 5), + opDivider(5) { ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; try { result = initWatchdogFifo(); @@ -32,15 +34,20 @@ CoreController::CoreController(object_id_t objectId): sif::warning << "CoreController::CoreController: Watchdog FIFO init failed" << std::endl; } - result = initSdCard(); - if(result != HasReturnvaluesIF::RETURN_OK) { - sif::warning << "CoreController::CoreController: SD card init failed" << std::endl; + sdcMan = SdCardManager::instance(); + if(sdcMan == nullptr) { + sif::error << "CoreController::CoreController: SD card manager invalid!" << std::endl; } + + if(not BLOCKING_SD_INIT) { + sdcMan->setBlocking(false); + } + sdStateMachine(); + result = initBootCopy(); if(result != HasReturnvaluesIF::RETURN_OK) { sif::warning << "CoreController::CoreController: Boot copy init" << std::endl; } - } catch(const std::filesystem::filesystem_error& e) { sif::error << "CoreController::CoreController: Failed with exception " << @@ -54,6 +61,7 @@ ReturnValue_t CoreController::handleCommandMessage(CommandMessage *message) { void CoreController::performControlOperation() { performWatchdogControlOperation(); + sdStateMachine(); } ReturnValue_t CoreController::initializeLocalDataPool(localpool::DataPool &localDataPoolMap, @@ -74,6 +82,7 @@ ReturnValue_t CoreController::initialize() { "count failed" << std::endl; } + sdStateMachine(); return ExtendedControllerBase::initialize(); } @@ -82,35 +91,36 @@ ReturnValue_t CoreController::checkModeCommand(Mode_t mode, Submode_t submode, return HasReturnvaluesIF::RETURN_OK; } -ReturnValue_t CoreController::initSdCard() { -#if Q7S_SD_CARD_CONFIG == Q7S_SD_NONE - sif::info << "No SD card initialization will be performed" << std::endl; - return HasReturnvaluesIF::RETURN_OK; -#else - SdCardManager* sdcMan = SdCardManager::instance(); - if(sdcMan == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; - } +ReturnValue_t CoreController::initSdCardBlocking() { // Create update status file ReturnValue_t result = sdcMan->updateSdCardStateFile(); if(result != HasReturnvaluesIF::RETURN_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 HasReturnvaluesIF::RETURN_OK; +#else - auto statusPair = SdCardManager::SdStatusPair(sd::SdStatus::OFF, sd::SdStatus::OFF); - result = sdcMan->getSdCardActiveStatus(statusPair); + result = sdcMan->getSdCardActiveStatus(sdInfo.currentState); if(result != HasReturnvaluesIF::RETURN_OK) { sif::warning << "Getting SD card activity status failed" << std::endl; } #if Q7S_SD_CARD_CONFIG == Q7S_SD_COLD_REDUNDANT - return sdCardColdRedundantInit(sdcMan, statusPair); + determinePreferredSdCard(); + 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; - - setUpSdCard(sd::SdCard::SLOT_0, sdStatus.first, "0"); - setUpSdCard(sd::SdCard::SLOT_1, sdStatus.second, "1"); + 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 HasReturnvaluesIF::RETURN_OK; @@ -120,10 +130,332 @@ ReturnValue_t CoreController::initSdCard() { } -ReturnValue_t CoreController::sdCardSetup(SdCardManager& sdcMan, - SdCardManager::SdStatusPair& statusPair,sd::SdCard sdCard, sd::SdStatus status, - std::string sdString) { +ReturnValue_t CoreController::sdStateMachine() { + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + SdCardManager::Operations operation; + + if(sdInfo.state == SdStates::IDLE) { + // Nothing to do + return result; + } + + if(sdInfo.state == SdStates::START) { + // Init will be performed by separate function + if(BLOCKING_SD_INIT) { + sdInfo.state = 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 + } + } + + // 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) { + SdCardManager::OpStatus status = sdcMan->checkCurrentOp(operation); + if(status == SdCardManager::OpStatus::SUCCESS) { + sdInfo.state = newStateOnSuccess; + sdInfo.commandExecuted = false; + sdInfo.cycleCount = 0; + return true; + } + else if(sdInfo.cycleCount > 4) { + sif::warning << "CoreController::sdInitStateMachine: " << opPrintout << + " takes too long" << std::endl; + return false; + } + return false; + }; + + if(sdInfo.state == SdStates::GET_INFO) { + if(not sdInfo.commandExecuted) { + // Create update status file + result = sdcMan->updateSdCardStateFile(); + if(result != HasReturnvaluesIF::RETURN_OK) { + sif::warning << "CoreController::initialize: Updating SD card state file failed" + << std::endl; + } + sdInfo.commandExecuted = true; + } + else { + nonBlockingOpChecking(SdStates::SET_STATE_SELF, 4, "Updating SDC file"); + } + } + + if(sdInfo.state == SdStates::SET_STATE_SELF) { + if(not sdInfo.commandExecuted) { + result = sdcMan->getSdCardActiveStatus(sdInfo.currentState); + determinePreferredSdCard(); + updateSdInfoOther(); + if(result != HasReturnvaluesIF::RETURN_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 OBSW_VERBOSE_LEVEL >= 1 + std::string mountString; + if(sdInfo.pref == sd::SdCard::SLOT_0) { + mountString = SdCardManager::SD_0_MOUNT_POINT; + } + else { + mountString = SdCardManager::SD_1_MOUNT_POINT; + } + sif::info << "SD card " << sdInfo.prefChar << " 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); + sdInfo.commandExecuted = true; + } + else if(sdInfo.prefState == sd::SdState::ON) { + sdInfo.state = SdStates::MOUNT_SELF; + } + } + else { + if(nonBlockingOpChecking(SdStates::MOUNT_SELF, 10, "Setting SDC state")) { + sdInfo.prefState = sd::SdState::ON; + currentStateSetter(sdInfo.pref, sd::SdState::ON); + } + } + } + + if(sdInfo.state == SdStates::MOUNT_SELF) { + if(not sdInfo.commandExecuted) { + result = sdCardSetup(sdInfo.pref, sd::SdState::MOUNTED, sdInfo.prefChar); + sdInfo.commandExecuted = true; + } + else { + if(nonBlockingOpChecking(SdStates::DETERMINE_OTHER, 5, "Mounting SD card")) { + sdInfo.prefState = sd::SdState::MOUNTED; + currentStateSetter(sdInfo.pref, sd::SdState::MOUNTED); + } + } + } + + if(sdInfo.state == 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; + } +#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) { + // 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); + } + } +#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) { + // 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); + } + } +#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) { + // 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 + sdcMan->setBlocking(true); + // Update status file + result = sdcMan->updateSdCardStateFile(); + if(result != HasReturnvaluesIF::RETURN_OK) { + sif::warning << "CoreController::initialize: Updating SD card state file failed" + << std::endl; + } + sdInfo.commandExecuted = false; + sdInfo.state = SdStates::IDLE; + sdInfo.cycleCount = 0; + sdcMan->setBlocking(false); + sdcMan->getSdCardActiveStatus(sdInfo.currentState); + if(not sdInfo.initFinished) { + updateSdInfoOther(); + sdInfo.initFinished = true; + sif::info << "SD card initialization finished" << std::endl; + } + } + + if(sdInfo.state == SdStates::SET_STATE_FROM_COMMAND) { + if(not sdInfo.commandExecuted) { + executeNextExternalSdCommand(); + } + else { + checkExternalSdCommandStatus(); + } + } + + sdInfo.cycleCount++; + return HasReturnvaluesIF::RETURN_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; + } + else { + sdInfo.currentState.second = newState; + } +} + +ReturnValue_t CoreController::sdCardSetup(sd::SdCard sdCard, sd::SdState targetState, + std::string sdChar, bool printOutput) { std::string mountString; + sdcMan->setPrintCommandOutput(printOutput); if(sdCard == sd::SdCard::SLOT_0) { mountString = SdCardManager::SD_0_MOUNT_POINT; } @@ -131,27 +463,63 @@ ReturnValue_t CoreController::sdCardSetup(SdCardManager& sdcMan, mountString = SdCardManager::SD_1_MOUNT_POINT; } - if(status == sd::SdStatus::OFF) { - sif::info << "Switching on and mounting SD card " << sdString << " at " << - mountString << std::endl; - return sdcMan.switchOnSdCard(sdCard, true, &statusPair); - } - else if(status == sd::SdStatus::ON) { - sif::info << "Mounting SD card " << sdString << " at " << mountString << std::endl; - return sdcMan.mountSdCard(sdCard); + sd::SdState state = sd::SdState::OFF; + if(sdCard == sd::SdCard::SLOT_0) { + state = sdInfo.currentState.first; } else { - if(std::filesystem::exists(mountString)) { - sif::info << "SD card " << sdString << " already on and mounted at " << - mountString << std::endl; - return SdCardManager::ALREADY_MOUNTED; - } - sif::error << "SD card mounted but expected mount point " << mountString << " not found!" - << std::endl; - return SdCardManager::MOUNT_ERROR; + state = sdInfo.currentState.second; } + if(state == sd::SdState::MOUNTED) { + if(targetState == sd::SdState::OFF) { + sif::info << "Switching off SD card " << sdChar << std::endl; + return sdcMan->switchOffSdCard(sdCard, true, &sdInfo.currentState); + } + else if(targetState == sd::SdState::ON) { + sif::info << "Unmounting SD card " << sdChar << std::endl; + return sdcMan->unmountSdCard(sdCard); + } + else { + if(std::filesystem::exists(mountString)) { + sif::info << "SD card " << sdChar << " already on and mounted at " << + mountString << std::endl; + return SdCardManager::ALREADY_MOUNTED; + } + sif::error << "SD card mounted but expected mount point " << + mountString << " not found!" << std::endl; + return SdCardManager::MOUNT_ERROR; + } + } + + if(state == sd::SdState::OFF) { + if(targetState == sd::SdState::MOUNTED) { + sif::info << "Switching on and mounting SD card " << sdChar << " at " << + mountString << std::endl; + return sdcMan->switchOnSdCard(sdCard, true, &sdInfo.currentState); + } + else if(targetState == sd::SdState::ON) { + sif::info << "Switching on SD card " << sdChar << std::endl; + return sdcMan->switchOnSdCard(sdCard, false, &sdInfo.currentState); + } + } + + else if(state == sd::SdState::ON) { + if(targetState == sd::SdState::MOUNTED) { + sif::info << "Mounting SD card " << sdChar << " at " << mountString << std::endl; + return sdcMan->mountSdCard(sdCard); + } + else if(targetState == sd::SdState::OFF) { + sif::info << "Switching off SD card " << sdChar << std::endl; + return sdcMan->switchOffSdCard(sdCard, false, &sdInfo.currentState); + } + } + else { + sif::warning << "CoreController::sdCardSetup: Invalid state for this call" << std::endl; + } + return HasReturnvaluesIF::RETURN_OK; } + ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, const uint8_t *data, size_t size) { switch(actionId) { @@ -168,7 +536,15 @@ ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_ } ReturnValue_t CoreController::initializeAfterTaskCreation() { - ReturnValue_t result = initVersionFile(); + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + if(BLOCKING_SD_INIT) { + ReturnValue_t result = initSdCardBlocking(); + if(result != HasReturnvaluesIF::RETURN_OK and result != SdCardManager::ALREADY_MOUNTED) { + sif::warning << "CoreController::CoreController: SD card init failed" << std::endl; + } + } + sdStateMachine(); + result = initVersionFile(); if(result != HasReturnvaluesIF::RETURN_OK) { sif::warning << "CoreController::initialize: Version initialization failed" << std::endl; } @@ -176,69 +552,30 @@ ReturnValue_t CoreController::initializeAfterTaskCreation() { return result; } -ReturnValue_t CoreController::sdCardColdRedundantInit(SdCardManager* sdcMan, - SdCardManager::SdStatusPair& statusPair) { - sd::SdCard preferredSdCard = sd::SdCard::SLOT_0; - ReturnValue_t result = sdcMan->getPreferredSdCard(preferredSdCard); - if(result != HasReturnvaluesIF::RETURN_OK) { - if(result == scratch::KEY_NOT_FOUND) { - sif::warning << "CoreController::sdCardInit: " - "Preferred SD card not set. Setting to 0" << std::endl; - sdcMan->setPreferredSdCard(preferredSdCard); - } - else { - sif::warning << "CoreController::sdCardInit: Could not get preferred SD card" - "information from the scratch buffer" << std::endl; - } - } - std::string preferredString; - sd::SdStatus preferredStatus = sd::SdStatus::OFF; +ReturnValue_t CoreController::sdColdRedundantBlockingInit() { + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; - sd::SdStatus otherStatus = sd::SdStatus::OFF; - std::string otherString; - sd::SdCard otherSdc = sd::SdCard::SLOT_0; - - if(preferredSdCard == sd::SdCard::SLOT_0) { - preferredStatus = statusPair.first; - preferredString = "0"; - otherSdc = sd::SdCard::SLOT_1; - otherStatus = statusPair.second; - otherString = "1"; - } - else { - preferredString = "1"; - preferredStatus = statusPair.second; - otherStatus = statusPair.first; - otherSdc = sd::SdCard::SLOT_0; - otherString = "0"; - } - - sif::info << "Cold redundant SD card configuration, preferred SD card " << - preferredString << std::endl; - - result = sdCardSetup(*sdcMan, statusPair, preferredSdCard, preferredStatus, preferredString); + result = sdCardSetup(sdInfo.pref, sd::SdState::MOUNTED, sdInfo.prefChar); if(result != SdCardManager::ALREADY_MOUNTED and result != HasReturnvaluesIF::RETURN_OK) { - sif::warning << "Setting up preferred card " << otherString << + 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(*sdcMan, statusPair, preferredSdCard, preferredStatus, preferredString); + sdCardSetup(sdInfo.pref, sd::SdState::MOUNTED, sdInfo.prefChar); result = HasReturnvaluesIF::RETURN_FAILED; } - if(result != HasReturnvaluesIF::RETURN_FAILED and otherStatus != sd::SdStatus::OFF) { - sif::info << "Switching off secondary SD card " << otherString << std::endl; - // Switch off other SD card in cold redundant mode if setting up preferred one walked + if(result != HasReturnvaluesIF::RETURN_FAILED and sdInfo.otherState != sd::SdState::OFF) { + sif::info << "Switching off secondary SD card " << sdInfo.otherChar << std::endl; + // Switch off other SD card in cold redundant mode if setting up preferred one worked // without issues - result = sdcMan->switchOffSdCard(otherSdc, otherStatus, &statusPair); - if(result != HasReturnvaluesIF::RETURN_OK and result != SdCardManager::ALREADY_OFF) { - sif::warning << "Switching off secondary SD card " << otherString << + ReturnValue_t result2 = sdcMan->switchOffSdCard(sdInfo.other, + sdInfo.otherState, &sdInfo.currentState); + if(result2 != HasReturnvaluesIF::RETURN_OK and result2 != SdCardManager::ALREADY_OFF) { + sif::warning << "Switching off secondary SD card " << sdInfo.otherChar << " in cold redundant mode failed" << std::endl; } } - - // Update status file - sdcMan->updateSdCardStateFile(); - return HasReturnvaluesIF::RETURN_OK; + return result; } ReturnValue_t CoreController::incrementAllocationFailureCount() { @@ -379,6 +716,7 @@ ReturnValue_t CoreController::actionListDirectoryIntoFile(ActionId_t actionId, if(RFlag) { oss << "R"; } + oss << " " << repoName << " > " << targetFileName; int result = std::system(oss.str().c_str()); if(result != 0) { @@ -493,6 +831,48 @@ ReturnValue_t CoreController::actionPerformReboot(const uint8_t *data, size_t si return HasActionsIF::EXECUTION_FINISHED; } +CoreController::~CoreController() { +} + +void CoreController::determinePreferredSdCard() { + if(sdInfo.pref == sd::SdCard::NONE) { + ReturnValue_t result = sdcMan->getPreferredSdCard(sdInfo.pref); + if(result != HasReturnvaluesIF::RETURN_OK) { + if(result == scratch::KEY_NOT_FOUND) { + sif::warning << "CoreController::sdCardInit: " + "Preferred SD card not set. Setting to 0" << std::endl; + sdcMan->setPreferredSdCard(sdInfo.pref); + } + else { + sif::warning << "CoreController::sdCardInit: Could not get preferred SD card" + "information from the scratch buffer" << std::endl; + } + } + } +} + +void CoreController::updateSdInfoOther() { + if(sdInfo.pref == sd::SdCard::SLOT_0) { + sdInfo.prefChar = "0"; + sdInfo.otherChar = "1"; + sdInfo.otherState = sdInfo.currentState.second; + sdInfo.prefState = sdInfo.currentState.first; + sdInfo.other = sd::SdCard::SLOT_1; + + } + else { + sdInfo.prefChar = "1"; + sdInfo.otherChar = "0"; + sdInfo.otherState = sdInfo.currentState.first; + sdInfo.prefState = sdInfo.currentState.second; + sdInfo.other = sd::SdCard::SLOT_0; + } +} + +bool CoreController::sdInitFinished() const { + return sdInfo.initFinished; +} + void CoreController::performWatchdogControlOperation() { // Only perform each fifth iteration if(watchdogFifoFd != 0 and opDivider.checkAndIncrement()) { diff --git a/bsp_q7s/core/CoreController.h b/bsp_q7s/core/CoreController.h index 4a71e6e7..b26c99c5 100644 --- a/bsp_q7s/core/CoreController.h +++ b/bsp_q7s/core/CoreController.h @@ -8,6 +8,8 @@ #include "events/subsystemIdRanges.h" +class Timer; +class SdCardManager; class CoreController: public ExtendedControllerBase { public: @@ -32,6 +34,7 @@ public: CoreController(object_id_t objectId); + virtual~ CoreController(); ReturnValue_t initialize() override; @@ -45,6 +48,7 @@ public: static ReturnValue_t incrementAllocationFailureCount(); static void getCurrentBootCopy(Chip& chip, Copy& copy); + bool sdInitFinished() const; private: static Chip currentChip; @@ -56,11 +60,65 @@ private: ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, uint32_t *msToReachTheMode); - ReturnValue_t initSdCard(); - ReturnValue_t sdCardSetup(SdCardManager& sdcMan, SdCardManager::SdStatusPair& statusPair, - sd::SdCard sdCard, sd::SdStatus status, std::string sdString); - ReturnValue_t sdCardColdRedundantInit(SdCardManager* sdcMan, - SdCardManager::SdStatusPair& statusPair); + // States for SD state machine, which is used in non-blocking mode + enum class SdStates { + NONE, + START, + GET_INFO, + SET_STATE_SELF, + MOUNT_SELF, + // Determine operations for other SD card, depending on redundancy configuration + DETERMINE_OTHER, + SET_STATE_OTHER, + // Mount or unmount other + MOUNT_UNMOUNT_OTHER, + // 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, + // SD initialization done + IDLE, + // Used if SD switches or mount commands are issued via telecommand + SET_STATE_FROM_COMMAND, + }; + static constexpr bool BLOCKING_SD_INIT = false; + + SdCardManager* sdcMan = nullptr; + + ReturnValue_t initSdCardBlocking(); + ReturnValue_t sdStateMachine(); + + struct SdInfo { + sd::SdCard pref = sd::SdCard::NONE; + sd::SdState prefState = sd::SdState::OFF; + sd::SdCard other = sd::SdCard::NONE; + sd::SdState otherState = sd::SdState::OFF; + std::string prefChar = "0"; + std::string otherChar = "1"; + 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 sdInfo; + + void updateSdInfoOther(); + ReturnValue_t sdCardSetup(sd::SdCard sdCard, sd::SdState targetState, std::string sdChar, + bool printOutput = true); + ReturnValue_t sdColdRedundantBlockingInit(); + void currentStateSetter(sd::SdCard sdCard, sd::SdState newState); + void determinePreferredSdCard(); + void executeNextExternalSdCommand(); + void checkExternalSdCommandStatus(); ReturnValue_t initVersionFile(); ReturnValue_t initBootCopy(); diff --git a/bsp_q7s/memory/FileSystemHandler.cpp b/bsp_q7s/memory/FileSystemHandler.cpp index 5a7895da..ad8ec137 100644 --- a/bsp_q7s/memory/FileSystemHandler.cpp +++ b/bsp_q7s/memory/FileSystemHandler.cpp @@ -41,7 +41,9 @@ void FileSystemHandler::fileSystemHandlerLoop() { ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; while(true) { if(opCounter % 5 == 0) { - fileSystemCheckup(); + if(coreCtrl->sdInitFinished()) { + fileSystemCheckup(); + } } result = mq->receiveMessage(&filemsg); if(result == MessageQueueIF::EMPTY) { @@ -72,16 +74,16 @@ void FileSystemHandler::fileSystemHandlerLoop() { } void FileSystemHandler::fileSystemCheckup() { - SdCardManager::SdStatusPair statusPair; + SdCardManager::SdStatePair statusPair; sdcMan->getSdCardActiveStatus(statusPair); sd::SdCard preferredSdCard; sdcMan->getPreferredSdCard(preferredSdCard); if((preferredSdCard == sd::SdCard::SLOT_0) and - (statusPair.first == sd::SdStatus::MOUNTED)) { + (statusPair.first == sd::SdState::MOUNTED)) { currentMountPrefix = SdCardManager::SD_0_MOUNT_POINT; } else if((preferredSdCard == sd::SdCard::SLOT_1) and - (statusPair.second == sd::SdStatus::MOUNTED)) { + (statusPair.second == sd::SdState::MOUNTED)) { currentMountPrefix = SdCardManager::SD_1_MOUNT_POINT; } else { @@ -111,6 +113,11 @@ MessageQueueId_t FileSystemHandler::getCommandQueue() const { } ReturnValue_t FileSystemHandler::initialize() { + coreCtrl = ObjectManager::instance()->get(objects::CORE_CONTROLLER); + if(coreCtrl == nullptr) { + sif::error << "FileSystemHandler::initialize: Could not retrieve core controller handle" << + std::endl; + } sdcMan = SdCardManager::instance(); sd::SdCard preferredSdCard; ReturnValue_t result = sdcMan->getPreferredSdCard(preferredSdCard); diff --git a/bsp_q7s/memory/FileSystemHandler.h b/bsp_q7s/memory/FileSystemHandler.h index 22a7e7ae..1ff5d7c9 100644 --- a/bsp_q7s/memory/FileSystemHandler.h +++ b/bsp_q7s/memory/FileSystemHandler.h @@ -11,6 +11,8 @@ #include +class CoreController; + class FileSystemHandler: public SystemObject, public ExecutableObjectIF, public HasFileSystemIF { @@ -47,6 +49,7 @@ public: void* args = nullptr) override; private: + CoreController* coreCtrl = nullptr; MessageQueueIF* mq = nullptr; std::string currentMountPrefix = SdCardManager::SD_0_MOUNT_POINT; static constexpr uint32_t FS_MAX_QUEUE_SIZE = config::OBSW_FILESYSTEM_HANDLER_QUEUE_SIZE; diff --git a/bsp_q7s/memory/SdCardManager.cpp b/bsp_q7s/memory/SdCardManager.cpp index 3dfa0b10..873bb6a4 100644 --- a/bsp_q7s/memory/SdCardManager.cpp +++ b/bsp_q7s/memory/SdCardManager.cpp @@ -1,3 +1,4 @@ +#include #include "SdCardManager.h" #include "scratchApi.h" @@ -6,13 +7,16 @@ #include "fsfw/ipc/MutexFactory.h" #include "fsfw/serviceinterface/ServiceInterface.h" +#include + #include #include #include +#include SdCardManager* SdCardManager::factoryInstance = nullptr; -SdCardManager::SdCardManager() { +SdCardManager::SdCardManager(): cmdExecutor(256) { } SdCardManager::~SdCardManager() { @@ -30,11 +34,19 @@ SdCardManager* SdCardManager::instance() { } ReturnValue_t SdCardManager::switchOnSdCard(sd::SdCard sdCard, bool doMountSdCard, - SdStatusPair* statusPair) { + SdStatePair* statusPair) { ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; - std::unique_ptr sdStatusPtr; + if(doMountSdCard) { + if(not blocking) { + sif::warning << "SdCardManager::switchOnSdCard: Two-step command but manager is" + " not configured for blocking operation. " + "Forcing blocking mode.." << std::endl; + blocking = true; + } + } + std::unique_ptr sdStatusPtr; if(statusPair == nullptr) { - sdStatusPtr = std::make_unique(); + sdStatusPtr = std::make_unique(); statusPair = sdStatusPtr.get(); result = getSdCardActiveStatus(*statusPair); if(result != HasReturnvaluesIF::RETURN_OK) { @@ -49,39 +61,35 @@ ReturnValue_t SdCardManager::switchOnSdCard(sd::SdCard sdCard, bool doMountSdCar return HasReturnvaluesIF::RETURN_FAILED; } - sd::SdStatus targetStatus; + sd::SdState currentState; if(sdCard == sd::SdCard::SLOT_0) { - targetStatus = statusPair->first; + currentState = statusPair->first; } else if(sdCard == sd::SdCard::SLOT_1) { - targetStatus = statusPair->second; + currentState = statusPair->second; } else { // Should not happen - targetStatus = sd::SdStatus::OFF; + currentState = sd::SdState::OFF; } - auto switchCall = [&]() { - if(targetStatus == sd::SdStatus::ON) { - if(not doMountSdCard) { - return ALREADY_ON; - } - else { - return mountSdCard(sdCard); - } - } - else if(targetStatus == sd::SdStatus::MOUNTED) { - return ALREADY_MOUNTED; - } - else if(targetStatus == sd::SdStatus::OFF) { - return setSdCardState(sdCard, true); + if(currentState == sd::SdState::ON) { + if(not doMountSdCard) { + return ALREADY_ON; } else { - return HasReturnvaluesIF::RETURN_FAILED; + return mountSdCard(sdCard); } - }; - - result = switchCall(); + } + else if(currentState == sd::SdState::MOUNTED) { + result = ALREADY_MOUNTED; + } + else if(currentState == sd::SdState::OFF) { + result = setSdCardState(sdCard, true); + } + else { + result = HasReturnvaluesIF::RETURN_FAILED; + } if(result != HasReturnvaluesIF::RETURN_OK or not doMountSdCard) { return result; @@ -91,12 +99,19 @@ ReturnValue_t SdCardManager::switchOnSdCard(sd::SdCard sdCard, bool doMountSdCar } ReturnValue_t SdCardManager::switchOffSdCard(sd::SdCard sdCard, bool doUnmountSdCard, - SdStatusPair* statusPair) { - std::pair active; + SdStatePair* statusPair) { + std::pair active; ReturnValue_t result = getSdCardActiveStatus(active); if(result != HasReturnvaluesIF::RETURN_OK) { return result; } + if(doUnmountSdCard) { + if(not blocking) { + sif::warning << "SdCardManager::switchOffSdCard: Two-step command but manager is" + " not configured for blocking operation. Forcing blocking mode.." << std::endl; + blocking = true; + } + } // Not allowed, this function turns off one SD card if(sdCard == sd::SdCard::BOTH) { sif::warning << "SdCardManager::switchOffSdCard: API does not allow sd::SdStatus::BOTH" @@ -104,12 +119,12 @@ ReturnValue_t SdCardManager::switchOffSdCard(sd::SdCard sdCard, bool doUnmountSd return HasReturnvaluesIF::RETURN_FAILED; } if(sdCard == sd::SdCard::SLOT_0) { - if(active.first == sd::SdStatus::OFF) { + if(active.first == sd::SdState::OFF) { return ALREADY_OFF; } } else if(sdCard == sd::SdCard::SLOT_1) { - if(active.second == sd::SdStatus::OFF) { + if(active.second == sd::SdState::OFF) { return ALREADY_OFF; } } @@ -126,6 +141,9 @@ ReturnValue_t SdCardManager::switchOffSdCard(sd::SdCard sdCard, bool doUnmountSd ReturnValue_t SdCardManager::setSdCardState(sd::SdCard sdCard, bool on) { using namespace std; + if(cmdExecutor.getCurrentState() == CommandExecutor::States::PENDING) { + return CommandExecutor::COMMAND_PENDING; + } string sdstring = ""; string statestring = ""; if(sdCard == sd::SdCard::SLOT_0) { @@ -135,23 +153,24 @@ ReturnValue_t SdCardManager::setSdCardState(sd::SdCard sdCard, bool on) { sdstring = "1"; } if(on) { + currentOp = Operations::SWITCHING_ON; statestring = "on"; } else { + currentOp = Operations::SWITCHING_OFF; statestring = "off"; } ostringstream command; command << "q7hw sd set " << sdstring << " " << statestring; - int result = system(command.str().c_str()); - if(result == 0) { - return HasReturnvaluesIF::RETURN_OK; + cmdExecutor.load(command.str(), blocking, printCmdOutput); + ReturnValue_t result = cmdExecutor.execute(); + if(blocking and result != HasReturnvaluesIF::RETURN_OK) { + utility::handleSystemError(cmdExecutor.getLastError(), "SdCardManager::setSdCardState"); } - sif::warning << "SdCardManager::setSdCardState: system call failed with code " << - result << std::endl; - return SYSTEM_CALL_ERROR; + return result; } -ReturnValue_t SdCardManager::getSdCardActiveStatus(SdStatusPair& active) { +ReturnValue_t SdCardManager::getSdCardActiveStatus(SdStatePair& active) { using namespace std; if(not filesystem::exists(SD_STATE_FILE)) { return STATUS_FILE_NEXISTS; @@ -174,6 +193,9 @@ ReturnValue_t SdCardManager::getSdCardActiveStatus(SdStatusPair& active) { ReturnValue_t SdCardManager::mountSdCard(sd::SdCard sdCard) { using namespace std; + if(cmdExecutor.getCurrentState() == CommandExecutor::States::PENDING) { + return CommandExecutor::COMMAND_PENDING; + } if(sdCard == sd::SdCard::BOTH) { sif::warning << "SdCardManager::mountSdCard: API does not allow sd::SdStatus::BOTH" << std::endl; @@ -195,16 +217,22 @@ ReturnValue_t SdCardManager::mountSdCard(sd::SdCard sdCard) { return MOUNT_ERROR; } - string sdMountCommand = "mount " + mountDev + " " + mountPoint; - int result = system(sdMountCommand.c_str()); - if (result != 0) { - utility::handleSystemError(result, "SdCardManager::mountSdCard"); - return SYSTEM_CALL_ERROR; + if(not blocking) { + currentOp = Operations::MOUNTING; } - return HasReturnvaluesIF::RETURN_OK; + string sdMountCommand = "mount " + mountDev + " " + mountPoint; + cmdExecutor.load(sdMountCommand, blocking, printCmdOutput); + ReturnValue_t result = cmdExecutor.execute(); + if(blocking and result != HasReturnvaluesIF::RETURN_OK) { + utility::handleSystemError(cmdExecutor.getLastError(), "SdCardManager::mountSdCard"); + } + return result; } ReturnValue_t SdCardManager::unmountSdCard(sd::SdCard sdCard) { + if(cmdExecutor.getCurrentState() == CommandExecutor::States::PENDING) { + return CommandExecutor::COMMAND_PENDING; + } using namespace std; if(sdCard == sd::SdCard::BOTH) { sif::warning << "SdCardManager::unmountSdCard: API does not allow sd::SdStatus::BOTH" @@ -229,34 +257,53 @@ ReturnValue_t SdCardManager::unmountSdCard(sd::SdCard sdCard) { sif::warning << "SdCardManager::unmountSdCard: Mount point is empty!" << std::endl; } string sdUnmountCommand = "umount " + mountPoint; - int result = system(sdUnmountCommand.c_str()); - if (result != 0) { - utility::handleSystemError(result, "SdCardManager::unmountSdCard"); - return SYSTEM_CALL_ERROR; + if(not blocking) { + currentOp = Operations::UNMOUNTING; } - return HasReturnvaluesIF::RETURN_OK; + cmdExecutor.load(sdUnmountCommand, blocking, printCmdOutput); + ReturnValue_t result = cmdExecutor.execute(); + if(blocking and result != HasReturnvaluesIF::RETURN_OK) { + utility::handleSystemError(cmdExecutor.getLastError(), "SdCardManager::unmountSdCard"); + } + return result; } -ReturnValue_t SdCardManager::sanitizeState(SdStatusPair* statusPair, sd::SdCard prefSdCard) { - std::unique_ptr sdStatusPtr; +ReturnValue_t SdCardManager::sanitizeState(SdStatePair* statusPair, sd::SdCard prefSdCard) { + std::unique_ptr sdStatusPtr; + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + // Enforce blocking operation for now. Be careful to reset it when returning prematurely! + bool resetNonBlockingState = false; + if(not this->blocking) { + blocking = true; + resetNonBlockingState = true; + } if(prefSdCard == sd::SdCard::NONE) { - ReturnValue_t result = getPreferredSdCard(prefSdCard); + result = getPreferredSdCard(prefSdCard); if(result != HasReturnvaluesIF::RETURN_OK) {} } if(statusPair == nullptr) { - sdStatusPtr = std::make_unique(); + sdStatusPtr = std::make_unique(); statusPair = sdStatusPtr.get(); getSdCardActiveStatus(*statusPair); } - if(statusPair->first == sd::SdStatus::ON) { - return mountSdCard(prefSdCard); + if(statusPair->first == sd::SdState::ON) { + result = mountSdCard(prefSdCard); } - return switchOnSdCard(prefSdCard, true, statusPair); + result = switchOnSdCard(prefSdCard, true, statusPair); + if(resetNonBlockingState) { + blocking = false; + } + return result; } -void SdCardManager::processSdStatusLine(std::pair &active, +void SdCardManager::resetState() { + cmdExecutor.reset(); + currentOp = Operations::IDLE; +} + +void SdCardManager::processSdStatusLine(std::pair &active, std::string& line, uint8_t& idx, sd::SdCard& currentSd) { using namespace std; istringstream iss(line); @@ -278,28 +325,28 @@ void SdCardManager::processSdStatusLine(std::pair &a if(word == "on") { if(currentSd == sd::SdCard::SLOT_0) { - active.first = sd::SdStatus::ON; + active.first = sd::SdState::ON; } else { - active.second = sd::SdStatus::ON; + active.second = sd::SdState::ON; } } else if (word == "off") { if(currentSd == sd::SdCard::SLOT_0) { - active.first = sd::SdStatus::OFF; + active.first = sd::SdState::OFF; } else { - active.second = sd::SdStatus::OFF; + active.second = sd::SdState::OFF; } } } if(mountLine) { if(currentSd == sd::SdCard::SLOT_0) { - active.first = sd::SdStatus::MOUNTED; + active.first = sd::SdState::MOUNTED; } else { - active.second = sd::SdStatus::MOUNTED; + active.second = sd::SdState::MOUNTED; } } @@ -329,15 +376,17 @@ ReturnValue_t SdCardManager::setPreferredSdCard(sd::SdCard sdCard) { } ReturnValue_t SdCardManager::updateSdCardStateFile() { + if(cmdExecutor.getCurrentState() == CommandExecutor::States::PENDING) { + return CommandExecutor::COMMAND_PENDING; + } // Use q7hw utility and pipe the command output into the state file std::string updateCmd = "q7hw sd info all > " + std::string(SD_STATE_FILE); - int result = std::system(updateCmd.c_str()); - if(result == 0) { - return HasReturnvaluesIF::RETURN_OK; + cmdExecutor.load(updateCmd, blocking, printCmdOutput); + ReturnValue_t result = cmdExecutor.execute(); + if(blocking and result != HasReturnvaluesIF::RETURN_OK) { + utility::handleSystemError(cmdExecutor.getLastError(), "SdCardManager::mountSdCard"); } - sif::warning << "SdCardManager::updateSdCardStateFile: system call failed with code " << - result << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; + return result; } std::string SdCardManager::getCurrentMountPrefix(sd::SdCard prefSdCard) { @@ -354,3 +403,56 @@ std::string SdCardManager::getCurrentMountPrefix(sd::SdCard prefSdCard) { return SD_1_MOUNT_POINT; } } + +SdCardManager::OpStatus SdCardManager::checkCurrentOp(Operations ¤tOp) { + CommandExecutor::States state = cmdExecutor.getCurrentState(); + if(state == CommandExecutor::States::IDLE or state == CommandExecutor::States::COMMAND_LOADED) { + return OpStatus::IDLE; + } + currentOp = this->currentOp; + bool bytesRead = false; + +#if OBSW_ENABLE_TIMERS == 1 + Timer timer; + timer.setTimer(100); + uint32_t remainingTimeMs = 0; +#endif + while(true) { + ReturnValue_t result = cmdExecutor.check(bytesRead); + // This timer can prevent deadlocks due to missconfigurations +#if OBSW_ENABLE_TIMERS == 1 + timer.getTimer(&remainingTimeMs); + if(remainingTimeMs == 0) { + sif::error << "SdCardManager::checkCurrentOp: Timeout!" << std::endl; + return OpStatus::FAIL; + } +#endif + switch(result) { + case(CommandExecutor::BYTES_READ): { + continue; + } + case(CommandExecutor::EXECUTION_FINISHED): { + return OpStatus::SUCCESS; + } + case(HasReturnvaluesIF::RETURN_OK): { + return OpStatus::ONGOING; + } + case(HasReturnvaluesIF::RETURN_FAILED): { + return OpStatus::FAIL; + } + default: { + sif::warning << "SdCardManager::checkCurrentOp: Unhandled case" << std::endl; + } + } + } +} + +void SdCardManager::setBlocking(bool blocking) { + this->blocking = blocking; +} + +void SdCardManager::setPrintCommandOutput(bool print) { + this->printCmdOutput = print; + +} + diff --git a/bsp_q7s/memory/SdCardManager.h b/bsp_q7s/memory/SdCardManager.h index d882aa8e..1a86f711 100644 --- a/bsp_q7s/memory/SdCardManager.h +++ b/bsp_q7s/memory/SdCardManager.h @@ -1,6 +1,7 @@ #ifndef BSP_Q7S_MEMORY_SDCARDACCESSMANAGER_H_ #define BSP_Q7S_MEMORY_SDCARDACCESSMANAGER_H_ +#include #include "definitions.h" #include "returnvalues/classIds.h" #include "events/subsystemIdRanges.h" @@ -8,10 +9,13 @@ #include "fsfw/events/Event.h" #include "fsfw/returnvalues/HasReturnvaluesIF.h" +#include + #include #include #include #include +#include class MutexIF; @@ -22,16 +26,34 @@ class MutexIF; class SdCardManager { friend class SdCardAccess; public: - using SdStatusPair = std::pair; + enum class Operations { + SWITCHING_ON, + SWITCHING_OFF, + MOUNTING, + UNMOUNTING, + IDLE + }; + + enum class OpStatus { + IDLE, + TIMEOUT, + ONGOING, + SUCCESS, + FAIL + }; + + using SdStatePair = std::pair; static constexpr uint8_t INTERFACE_ID = CLASS_ID::SD_CARD_MANAGER; - static constexpr ReturnValue_t ALREADY_ON = + static constexpr ReturnValue_t OP_ONGOING = HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 0); - static constexpr ReturnValue_t ALREADY_MOUNTED = + static constexpr ReturnValue_t ALREADY_ON = HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 1); - static constexpr ReturnValue_t ALREADY_OFF = + static constexpr ReturnValue_t ALREADY_MOUNTED = HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 2); + static constexpr ReturnValue_t ALREADY_OFF = + HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 3); static constexpr ReturnValue_t STATUS_FILE_NEXISTS = HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 10); static constexpr ReturnValue_t STATUS_FILE_FORMAT_INVALID = @@ -42,6 +64,8 @@ public: HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 13); static constexpr ReturnValue_t SYSTEM_CALL_ERROR = HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 14); + static constexpr ReturnValue_t POPEN_CALL_ERROR = + HasReturnvaluesIF::makeReturnCode(INTERFACE_ID, 15); static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::FILE_SYSTEM; @@ -90,7 +114,7 @@ public: * SYSTEM_CALL_ERROR on system error */ ReturnValue_t switchOnSdCard(sd::SdCard sdCard, bool doMountSdCard = true, - SdStatusPair* statusPair = nullptr); + SdStatePair* statusPair = nullptr); /** * Switch off the specified SD card. @@ -102,13 +126,15 @@ public: * SYSTEM_CALL_ERROR on system error */ ReturnValue_t switchOffSdCard(sd::SdCard sdCard, bool doUnmountSdCard = true, - SdStatusPair* 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 - RETURN_OK if the state file was updated successfully - * - SYSTEM_CALL_ERROR if the call to create the status file failed + * @return + * - RETURN_OK if the state file was updated successfully + * - CommandExecutor::COMMAND_PENDING: Non-blocking command is pending + * - RETURN_FAILED: blocking command failed */ ReturnValue_t updateSdCardStateFile(); @@ -123,7 +149,7 @@ public: * should call #updateSdCardStateFile again in that case * - STATUS_FILE_NEXISTS if the status file does not exist */ - ReturnValue_t getSdCardActiveStatus(SdStatusPair& active); + ReturnValue_t getSdCardActiveStatus(SdStatePair& active); /** * Mount the specified SD card. This is necessary to use it. @@ -143,13 +169,13 @@ public: * In case that there is a discrepancy between the preferred SD card and the currently * mounted one, this function will sanitize the state by attempting to mount the * currently preferred SD card. If the caller already has state information, it can be - * passed into the function. + * passed into the function. For now, this operation will be enforced in blocking mode. * @param statusPair Current SD card status capture with #getSdCardActiveStatus * @param prefSdCard Preferred SD card captured with #getPreferredSdCard * @throws std::bad_alloc if one of the two arguments was a nullptr and an allocation failed * @return */ - ReturnValue_t sanitizeState(SdStatusPair* statusPair = nullptr, + ReturnValue_t sanitizeState(SdStatePair* statusPair = nullptr, sd::SdCard prefSdCard = sd::SdCard::NONE); /** @@ -159,12 +185,27 @@ public: * @return */ std::string getCurrentMountPrefix(sd::SdCard prefSdCardPtr = sd::SdCard::NONE); + + OpStatus checkCurrentOp(Operations& currentOp); + + /** + * If there are issues with the state machine, it can be reset with this function + */ + void resetState(); + + void setBlocking(bool blocking); + void setPrintCommandOutput(bool print); private: + CommandExecutor cmdExecutor; + Operations currentOp = Operations::IDLE; + bool blocking = false; + bool printCmdOutput = true; + SdCardManager(); ReturnValue_t setSdCardState(sd::SdCard sdCard, bool on); - void processSdStatusLine(SdStatusPair& active, std::string& line, uint8_t& idx, + void processSdStatusLine(SdStatePair& active, std::string& line, uint8_t& idx, sd::SdCard& currentSd); std::string currentPrefix; diff --git a/bsp_q7s/memory/definitions.h b/bsp_q7s/memory/definitions.h index 9fcbee08..9e0bca65 100644 --- a/bsp_q7s/memory/definitions.h +++ b/bsp_q7s/memory/definitions.h @@ -5,7 +5,7 @@ namespace sd { -enum SdStatus: uint8_t { +enum SdState: uint8_t { OFF = 0, ON = 1, // A mounted SD card is on as well diff --git a/fsfw b/fsfw index 133820f4..22e29144 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit 133820f463645164c203e72f0acd078eb002e159 +Subproject commit 22e29144b6783a824b310204c76fa413eb94f331 diff --git a/linux/fsfwconfig/OBSWConfig.h.in b/linux/fsfwconfig/OBSWConfig.h.in index 6a83a874..36d1e638 100644 --- a/linux/fsfwconfig/OBSWConfig.h.in +++ b/linux/fsfwconfig/OBSWConfig.h.in @@ -22,6 +22,10 @@ debugging. */ #define OBSW_VERBOSE_LEVEL 1 +//! Timers can mess up the code when debugging +//! TODO: Enable for mission code, disable for debug code +#define OBSW_ENABLE_TIMERS 0 + #define OBSW_PRINT_MISSED_DEADLINES 1 #define OBSW_ADD_TEST_CODE 1 #define OBSW_ADD_TEST_PST 1 diff --git a/mission/devices/PlocUpdater.cpp b/mission/devices/PlocUpdater.cpp index bb09a1c6..f890c239 100644 --- a/mission/devices/PlocUpdater.cpp +++ b/mission/devices/PlocUpdater.cpp @@ -174,7 +174,7 @@ ReturnValue_t PlocUpdater::getImageLocation(const uint8_t* data, size_t size) { } bool PlocUpdater::isSdCardMounted(sd::SdCard sdCard) { - SdCardManager::SdStatusPair active; + SdCardManager::SdStatePair active; ReturnValue_t result = sdcMan->getSdCardActiveStatus(active); if (result != RETURN_OK) { sif::debug << "PlocUpdater::isSdCardMounted: Failed to get SD card active state"; diff --git a/tmtc b/tmtc index 547b4b21..3e8626bf 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 547b4b213704a72a884c2871debeea0461c7704f +Subproject commit 3e8626bfafa561510323bf8fe3963bc2860950ed