From 00bd6e260a5cc4de768e17ec4b86b55a5a0d5b29 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 25 Feb 2022 11:32:08 +0100 Subject: [PATCH 1/5] fsfw and tmtc update --- fsfw | 2 +- tmtc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fsfw b/fsfw index 19f8e41c..123f2ff3 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit 19f8e41c7f2523d3684ebddd393e3a7700861328 +Subproject commit 123f2ff360e71228e1c0c786d80a4c93d7144a2e diff --git a/tmtc b/tmtc index 6a783112..7e245891 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 6a78311239bdf78040e43ef217035fcaa2ab9f3b +Subproject commit 7e24589184bb7bbd427c66ed55b3c29bbeba927f From 3a6c7e31839d4aa209b14489617f47a32dee9705 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 25 Feb 2022 11:34:42 +0100 Subject: [PATCH 2/5] separate branch for reboot file handling --- bsp_q7s/boardtest/Q7STestTask.cpp | 20 +- bsp_q7s/core/CoreController.cpp | 573 ++++++++++++++++++++++++---- bsp_q7s/core/CoreController.h | 68 +++- bsp_q7s/memory/SdCardManager.cpp | 3 +- bsp_q7s/memory/SdCardManager.h | 6 +- cmake/Q7SCrossCompileConfig.cmake | 15 +- common/config/commonSubsystemIds.h | 1 + unittest/rebootLogic/.gitignore | 1 + unittest/rebootLogic/CMakeLists.txt | 11 + unittest/rebootLogic/main.cpp | 5 + 10 files changed, 607 insertions(+), 96 deletions(-) create mode 100644 unittest/rebootLogic/.gitignore create mode 100644 unittest/rebootLogic/CMakeLists.txt create mode 100644 unittest/rebootLogic/main.cpp diff --git a/bsp_q7s/boardtest/Q7STestTask.cpp b/bsp_q7s/boardtest/Q7STestTask.cpp index 5d9042ac..bd9890a7 100644 --- a/bsp_q7s/boardtest/Q7STestTask.cpp +++ b/bsp_q7s/boardtest/Q7STestTask.cpp @@ -170,15 +170,15 @@ void Q7STestTask::testProtHandler() { bool opPerformed = false; ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; // If any chips are unlocked, lock them here - result = coreController->setBootCopyProtection( - CoreController::Chip::ALL_CHIP, CoreController::Copy::ALL_COPY, true, opPerformed, true); + result = coreController->setBootCopyProtection(xsc::Chip::ALL_CHIP, xsc::Copy::ALL_COPY, true, + opPerformed, true); if (result != HasReturnvaluesIF::RETURN_OK) { sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl; } // unlock own copy - result = coreController->setBootCopyProtection( - CoreController::Chip::SELF_CHIP, CoreController::Copy::SELF_COPY, false, opPerformed, true); + result = coreController->setBootCopyProtection(xsc::Chip::SELF_CHIP, xsc::Copy::SELF_COPY, false, + opPerformed, true); if (result != HasReturnvaluesIF::RETURN_OK) { sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl; } @@ -191,8 +191,8 @@ void Q7STestTask::testProtHandler() { } // lock own copy - result = coreController->setBootCopyProtection( - CoreController::Chip::SELF_CHIP, CoreController::Copy::SELF_COPY, true, opPerformed, true); + result = coreController->setBootCopyProtection(xsc::Chip::SELF_CHIP, xsc::Copy::SELF_COPY, true, + opPerformed, true); if (result != HasReturnvaluesIF::RETURN_OK) { sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl; } @@ -205,8 +205,8 @@ void Q7STestTask::testProtHandler() { } // unlock specific copy - result = coreController->setBootCopyProtection( - CoreController::Chip::CHIP_1, CoreController::Copy::COPY_1, false, opPerformed, true); + result = coreController->setBootCopyProtection(xsc::Chip::CHIP_1, xsc::Copy::COPY_1, false, + opPerformed, true); if (result != HasReturnvaluesIF::RETURN_OK) { sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl; } @@ -219,8 +219,8 @@ void Q7STestTask::testProtHandler() { } // lock specific copy - result = coreController->setBootCopyProtection( - CoreController::Chip::CHIP_1, CoreController::Copy::COPY_1, true, opPerformed, true); + result = coreController->setBootCopyProtection(xsc::Chip::CHIP_1, xsc::Copy::COPY_1, true, + opPerformed, true); if (result != HasReturnvaluesIF::RETURN_OK) { sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl; } diff --git a/bsp_q7s/core/CoreController.cpp b/bsp_q7s/core/CoreController.cpp index bdbd51cc..c106cd7e 100644 --- a/bsp_q7s/core/CoreController.cpp +++ b/bsp_q7s/core/CoreController.cpp @@ -1,5 +1,7 @@ #include "CoreController.h" +#include + #include "OBSWConfig.h" #include "OBSWVersion.h" #include "fsfw/FSFWVersion.h" @@ -20,8 +22,8 @@ #include "bsp_q7s/memory/SdCardManager.h" #include "bsp_q7s/memory/scratchApi.h" -CoreController::Chip CoreController::CURRENT_CHIP = Chip::NO_CHIP; -CoreController::Copy CoreController::CURRENT_COPY = Copy::NO_COPY; +xsc::Chip CoreController::CURRENT_CHIP = xsc::Chip::NO_CHIP; +xsc::Copy CoreController::CURRENT_COPY = xsc::Copy::NO_COPY; CoreController::CoreController(object_id_t objectId) : ExtendedControllerBase(objectId, objects::NO_OBJECT, 5), opDivider(5) { @@ -57,6 +59,7 @@ ReturnValue_t CoreController::handleCommandMessage(CommandMessage *message) { void CoreController::performControlOperation() { performWatchdogControlOperation(); sdStateMachine(); + performRebootFileHandling(false); } ReturnValue_t CoreController::initializeLocalDataPool(localpool::DataPool &localDataPoolMap, @@ -77,6 +80,8 @@ ReturnValue_t CoreController::initialize() { } sdStateMachine(); + + triggerEvent(REBOOT_SW, CURRENT_CHIP, CURRENT_COPY); return ExtendedControllerBase::initialize(); } @@ -102,6 +107,59 @@ ReturnValue_t CoreController::initializeAfterTaskCreation() { return result; } +ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, + const uint8_t *data, size_t size) { + switch (actionId) { + case (LIST_DIRECTORY_INTO_FILE): { + return actionListDirectoryIntoFile(actionId, commandedBy, data, size); + } + case (SWITCH_REBOOT_FILE_HANDLING): { + if (size < 1) { + return HasActionsIF::INVALID_PARAMETERS; + } + std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE; + // Disable the reboot file mechanism + parseRebootFile(path, rebootFile); + if (data[0] == 0) { + rebootFile.enabled = false; + rewriteRebootFile(rebootFile); + } else if (data[0] == 1) { + rebootFile.enabled = true; + rewriteRebootFile(rebootFile); + } else { + return HasActionsIF::INVALID_PARAMETERS; + } + return HasActionsIF::EXECUTION_FINISHED; + } + case (RESET_ALL_REBOOT_COUNTERS): { + resetRebootCount(xsc::ALL_CHIP, xsc::ALL_COPY); + return HasActionsIF::EXECUTION_FINISHED; + } + case (RESET_REBOOT_COUNTER_00): { + resetRebootCount(xsc::CHIP_0, xsc::COPY_0); + return HasActionsIF::EXECUTION_FINISHED; + } + case (RESET_REBOOT_COUNTER_01): { + resetRebootCount(xsc::CHIP_0, xsc::COPY_1); + return HasActionsIF::EXECUTION_FINISHED; + } + case (RESET_REBOOT_COUNTER_10): { + resetRebootCount(xsc::CHIP_1, xsc::COPY_0); + return HasActionsIF::EXECUTION_FINISHED; + } + case (RESET_REBOOT_COUNTER_11): { + resetRebootCount(xsc::CHIP_1, xsc::COPY_1); + return HasActionsIF::EXECUTION_FINISHED; + } + case (REBOOT_OBC): { + return actionPerformReboot(data, size); + } + default: { + return HasActionsIF::INVALID_ACTION_ID; + } + } +} + ReturnValue_t CoreController::checkModeCommand(Mode_t mode, Submode_t submode, uint32_t *msToReachTheMode) { return HasReturnvaluesIF::RETURN_OK; @@ -500,21 +558,6 @@ ReturnValue_t CoreController::sdCardSetup(sd::SdCard sdCard, sd::SdState targetS return HasReturnvaluesIF::RETURN_OK; } -ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, - const uint8_t *data, size_t size) { - switch (actionId) { - case (LIST_DIRECTORY_INTO_FILE): { - return actionListDirectoryIntoFile(actionId, commandedBy, data, size); - } - case (REBOOT_OBC): { - return actionPerformReboot(data, size); - } - default: { - return HasActionsIF::INVALID_ACTION_ID; - } - } -} - ReturnValue_t CoreController::sdColdRedundantBlockingInit() { ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; @@ -689,7 +732,7 @@ ReturnValue_t CoreController::actionListDirectoryIntoFile(ActionId_t actionId, ReturnValue_t CoreController::initBootCopy() { if (not std::filesystem::exists(CURR_COPY_FILE)) { - // Thils file is created by the systemd service eive-early-config so this should + // This file is created by the systemd service eive-early-config so this should // not happen normally std::string cmd = "xsc_boot_copy > " + std::string(CURR_COPY_FILE); int result = std::system(cmd.c_str()); @@ -697,22 +740,18 @@ ReturnValue_t CoreController::initBootCopy() { utility::handleSystemError(result, "CoreController::initBootCopy"); } } - std::ifstream file(CURR_COPY_FILE); - std::string line; - std::getline(file, line); - std::istringstream iss(line); - int value = 0; - iss >> value; - CURRENT_CHIP = static_cast(value); - iss >> value; - CURRENT_COPY = static_cast(value); + + getCurrentBootCopy(CURRENT_CHIP, CURRENT_COPY); return HasReturnvaluesIF::RETURN_OK; } -void CoreController::getCurrentBootCopy(Chip &chip, Copy ©) { +void CoreController::getCurrentBootCopy(xsc::Chip &chip, xsc::Copy ©) { + xsc_libnor_chip_t xscChip; + xsc_libnor_copy_t xscCopy; + xsc_boot_get_chip_copy(&xscChip, &xscCopy); // Not really thread-safe but it does not need to be - chip = CURRENT_CHIP; - copy = CURRENT_COPY; + chip = static_cast(xscChip); + copy = static_cast(xscCopy); } ReturnValue_t CoreController::initWatchdogFifo() { @@ -759,8 +798,8 @@ ReturnValue_t CoreController::actionPerformReboot(const uint8_t *data, size_t si SdCardManager::instance()->switchOffSdCard(sd::SdCard::SLOT_0); SdCardManager::instance()->switchOffSdCard(sd::SdCard::SLOT_1); // If any boot copies are unprotected - ReturnValue_t retval = - setBootCopyProtection(Chip::SELF_CHIP, Copy::SELF_COPY, true, protOpPerformed, false); + ReturnValue_t retval = setBootCopyProtection(xsc::Chip::SELF_CHIP, xsc::Copy::SELF_COPY, true, + protOpPerformed, false); if (retval == HasReturnvaluesIF::RETURN_OK and protOpPerformed) { sif::info << "Running slot was writeprotected before reboot" << std::endl; } @@ -771,7 +810,7 @@ ReturnValue_t CoreController::actionPerformReboot(const uint8_t *data, size_t si } return HasActionsIF::EXECUTION_FINISHED; } - if (size < 3) { + if (size < 3 or (data[1] > 1 or data[2] > 1)) { return HasActionsIF::INVALID_PARAMETERS; } #if OBSW_VERBOSE_LEVEL >= 1 @@ -782,21 +821,53 @@ ReturnValue_t CoreController::actionPerformReboot(const uint8_t *data, size_t si // Check that the target chip and copy is writeprotected first generateChipStateFile(); // If any boot copies are unprotected, protect them here - ReturnValue_t retval = setBootCopyProtection( - static_cast(data[1]), static_cast(data[2]), true, protOpPerformed, false); + auto tgtChip = static_cast(data[1]); + auto tgtCopy = static_cast(data[2]); + + ReturnValue_t retval = + setBootCopyProtection(static_cast(data[1]), static_cast(data[2]), true, + protOpPerformed, false); if (retval == HasReturnvaluesIF::RETURN_OK and protOpPerformed) { sif::info << "Target slot was writeprotected before reboot" << std::endl; } - // The second byte in data is the target chip, the third byte is the target copy - std::string cmdString = - "xsc_boot_copy " + std::to_string(data[1]) + " " + std::to_string(data[2]); - int result = std::system(cmdString.c_str()); - if (result != 0) { - utility::handleSystemError(result, "CoreController::executeAction"); - return HasReturnvaluesIF::RETURN_FAILED; + switch (tgtChip) { + case (xsc::Chip::CHIP_0): { + switch (tgtCopy) { + case (xsc::Copy::COPY_0): { + xsc_boot_copy(XSC_LIBNOR_CHIP_0, XSC_LIBNOR_COPY_NOMINAL); + break; + } + case (xsc::Copy::COPY_1): { + xsc_boot_copy(XSC_LIBNOR_CHIP_0, XSC_LIBNOR_COPY_GOLD); + break; + } + default: { + break; + } + } + break; + } + case (xsc::Chip::CHIP_1): { + switch (tgtCopy) { + case (xsc::Copy::COPY_0): { + xsc_boot_copy(XSC_LIBNOR_CHIP_1, XSC_LIBNOR_COPY_NOMINAL); + break; + } + case (xsc::Copy::COPY_1): { + xsc_boot_copy(XSC_LIBNOR_CHIP_1, XSC_LIBNOR_COPY_GOLD); + break; + } + default: { + break; + } + } + break; + } + default: + break; } - return HasActionsIF::EXECUTION_FINISHED; + return HasReturnvaluesIF::RETURN_FAILED; } CoreController::~CoreController() {} @@ -850,8 +921,8 @@ ReturnValue_t CoreController::generateChipStateFile() { return HasReturnvaluesIF::RETURN_OK; } -ReturnValue_t CoreController::setBootCopyProtection(Chip targetChip, Copy targetCopy, bool protect, - bool &protOperationPerformed, +ReturnValue_t CoreController::setBootCopyProtection(xsc::Chip targetChip, xsc::Copy targetCopy, + bool protect, bool &protOperationPerformed, bool updateProtFile) { bool allChips = false; bool allCopies = false; @@ -860,14 +931,14 @@ ReturnValue_t CoreController::setBootCopyProtection(Chip targetChip, Copy target protOperationPerformed = false; switch (targetChip) { - case (Chip::ALL_CHIP): { + case (xsc::Chip::ALL_CHIP): { allChips = true; break; } - case (Chip::NO_CHIP): { + case (xsc::Chip::NO_CHIP): { return HasReturnvaluesIF::RETURN_OK; } - case (Chip::SELF_CHIP): { + case (xsc::Chip::SELF_CHIP): { selfChip = true; targetChip = CURRENT_CHIP; break; @@ -877,14 +948,14 @@ ReturnValue_t CoreController::setBootCopyProtection(Chip targetChip, Copy target } } switch (targetCopy) { - case (Copy::ALL_COPY): { + case (xsc::Copy::ALL_COPY): { allCopies = true; break; } - case (Copy::NO_COPY): { + case (xsc::Copy::NO_COPY): { return HasReturnvaluesIF::RETURN_OK; } - case (Copy::SELF_COPY): { + case (xsc::Copy::SELF_COPY): { selfCopy = true; targetCopy = CURRENT_COPY; break; @@ -907,10 +978,10 @@ ReturnValue_t CoreController::setBootCopyProtection(Chip targetChip, Copy target return HasReturnvaluesIF::RETURN_OK; } -int CoreController::handleBootCopyProtAtIndex(Chip targetChip, Copy targetCopy, bool protect, - bool &protOperationPerformed, bool selfChip, - bool selfCopy, bool allChips, bool allCopies, - uint8_t arrIdx) { +int CoreController::handleBootCopyProtAtIndex(xsc::Chip targetChip, xsc::Copy targetCopy, + bool protect, bool &protOperationPerformed, + bool selfChip, bool selfCopy, bool allChips, + bool allCopies, uint8_t arrIdx) { bool currentProt = protArray[arrIdx]; std::ostringstream oss; bool performOp = false; @@ -923,22 +994,22 @@ int CoreController::handleBootCopyProtAtIndex(Chip targetChip, Copy targetCopy, return 1; } } - Chip currentChip; - Copy currentCopy; + xsc::Chip currentChip; + xsc::Copy currentCopy; oss << "writeprotect "; if (arrIdx == 0 or arrIdx == 1) { oss << "0 "; - currentChip = Chip::CHIP_0; + currentChip = xsc::Chip::CHIP_0; } else { oss << "1 "; - currentChip = Chip::CHIP_1; + currentChip = xsc::Chip::CHIP_1; } if (arrIdx == 0 or arrIdx == 2) { oss << "0 "; - currentCopy = Copy::COPY_0; + currentCopy = xsc::Copy::COPY_0; } else { oss << "1 "; - currentCopy = Copy::COPY_1; + currentCopy = xsc::Copy::COPY_1; } if (protect) { oss << "1"; @@ -1033,29 +1104,29 @@ ReturnValue_t CoreController::handleProtInfoUpdateLine(std::string nextLine) { uint8_t wordIdx = 0; uint8_t arrayIdx = 0; istringstream iss(nextLine); - Chip currentChip = Chip::CHIP_0; - Copy currentCopy = Copy::COPY_0; + xsc::Chip currentChip = xsc::Chip::CHIP_0; + xsc::Copy currentCopy = xsc::Copy::COPY_0; while (iss >> word) { if (wordIdx == 1) { - currentChip = static_cast(stoi(word)); + currentChip = static_cast(stoi(word)); } if (wordIdx == 3) { - currentCopy = static_cast(stoi(word)); + currentCopy = static_cast(stoi(word)); } if (wordIdx == 3) { - if (currentChip == Chip::CHIP_0) { - if (currentCopy == Copy::COPY_0) { + if (currentChip == xsc::Chip::CHIP_0) { + if (currentCopy == xsc::Copy::COPY_0) { arrayIdx = 0; - } else if (currentCopy == Copy::COPY_1) { + } else if (currentCopy == xsc::Copy::COPY_1) { arrayIdx = 1; } } - else if (currentChip == Chip::CHIP_1) { - if (currentCopy == Copy::COPY_0) { + else if (currentChip == xsc::Chip::CHIP_1) { + if (currentCopy == xsc::Copy::COPY_0) { arrayIdx = 2; - } else if (currentCopy == Copy::COPY_1) { + } else if (currentCopy == xsc::Copy::COPY_1) { arrayIdx = 3; } } @@ -1101,3 +1172,363 @@ void CoreController::performWatchdogControlOperation() { } } } + +void CoreController::performRebootFileHandling(bool recreateFile) { + bool sdCardMounted = false; + if (not recreateFile and doPerformRebootFileHandling) { + sdCardMounted = sdcMan->isSdCardMounted(sdInfo.pref); + } + if ((doPerformRebootFileHandling and sdCardMounted) or recreateFile) { + using namespace std; + if (recreateFile) { +#if OBSW_VERBOSE_LEVEL >= 1 + sif::info << "CoreController::performRebootFileHandling: Recreating reboot file" << std::endl; +#endif + } + std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE; + if (not std::filesystem::exists(path) or recreateFile) { + rebootFile.enabled = true; + rebootFile.img00Cnt = 0; + rebootFile.img01Cnt = 0; + rebootFile.img10Cnt = 0; + rebootFile.img11Cnt = 0; + rebootFile.lastChip = xsc::Chip::CHIP_0; + rebootFile.lastCopy = xsc::Copy::COPY_0; + rebootFile.bootFlag = false; + rewriteRebootFile(rebootFile); + } else { + if (not parseRebootFile(path, rebootFile)) { + performRebootFileHandling(true); + } + } + + if (rebootFile.bootFlag) { + // Trigger event to inform ground that a reboot was triggered + uint32_t p1 = rebootFile.lastChip << 16 | rebootFile.lastCopy; + uint32_t p2 = rebootFile.img00Cnt << 24 | rebootFile.img01Cnt << 16 | + rebootFile.img10Cnt << 8 | rebootFile.img11Cnt; + triggerEvent(REBOOT_MECHANISM_TRIGGERED, p1, p2); + // Clear the boot flag + rebootFile.bootFlag = false; + } + + switch (CURRENT_CHIP) { + case (xsc::CHIP_0): { + switch (CURRENT_COPY) { + case (xsc::COPY_0): { + rebootFile.img00Cnt++; + break; + } + case (xsc::COPY_1): { + rebootFile.img01Cnt++; + break; + } + default: { + break; + } + } + break; + } + case (xsc::CHIP_1): { + switch (CURRENT_COPY) { + case (xsc::COPY_0): { + rebootFile.img10Cnt++; + break; + } + case (xsc::COPY_1): { + rebootFile.img11Cnt++; + break; + } + default: { + break; + } + } + break; + } + default: { + break; + } + } + if (CURRENT_CHIP == xsc::CHIP_0 and CURRENT_COPY == xsc::COPY_0) { + } + if (rebootFile.relevantBootCnt > rebootFile.maxCount) { + // Reboot to other image + bool doReboot = false; + determineAndExecuteReboot(rebootFile, doReboot, rebootFile.lastChip, rebootFile.lastCopy); + if (doReboot) { + rebootFile.bootFlag = true; +#if OBSW_VERBOSE_LEVEL >= 1 + sif::info << "Boot counter for image " << CURRENT_CHIP << " " << CURRENT_COPY + << "too high. Rebooting to " << rebootFile.lastChip << " " << rebootFile.lastCopy + << std::endl; +#endif + rewriteRebootFile(rebootFile); + xsc_boot_copy(static_cast(rebootFile.lastChip), + static_cast(rebootFile.lastCopy)); + } + } else { + rewriteRebootFile(rebootFile); + } + doPerformRebootFileHandling = false; + } +} + +void CoreController::determineAndExecuteReboot(RebootFile &rf, bool &needsReboot, + xsc::Chip &tgtChip, xsc::Copy &tgtCopy) { + tgtChip = xsc::CHIP_0; + tgtCopy = xsc::COPY_0; + needsReboot = false; + if ((CURRENT_COPY == xsc::COPY_0) and (CURRENT_CHIP == xsc::CHIP_0) and + (rf.img00Cnt >= rf.maxCount)) { + needsReboot = true; + if (rf.img01Cnt >= rf.maxCount) { + if (rf.img10Cnt >= rf.maxCount) { + if (rf.img11Cnt >= rf.maxCount) { + // Can't really do much here. Stay on image + sif::warning << "All reboot counts too high, but already on fallback image" << std::endl; + return; + } else { + tgtChip = xsc::CHIP_1; + tgtCopy = xsc::COPY_1; + } + } else { + tgtChip = xsc::CHIP_0; + tgtCopy = xsc::COPY_1; + } + } else { + tgtCopy = xsc::COPY_1; + } + } + if ((CURRENT_COPY == xsc::COPY_0) and (CURRENT_CHIP == xsc::CHIP_1) and + (rf.img01Cnt >= rf.maxCount)) { + needsReboot = true; + if (rf.img00Cnt >= rf.maxCount) { + if (rf.img10Cnt >= rf.maxCount) { + if (rf.img11Cnt >= rf.maxCount) { + // Reboot to fallback image + } else { + tgtChip = xsc::CHIP_1; + tgtCopy = xsc::COPY_1; + } + } else { + tgtChip = xsc::CHIP_1; + tgtCopy = xsc::COPY_0; + } + } else { + // Reboot on fallback image + } + } + if ((CURRENT_COPY == xsc::COPY_1) and (CURRENT_CHIP == xsc::CHIP_0) and + (rf.img10Cnt >= rf.maxCount)) { + needsReboot = true; + if (rf.img11Cnt >= rf.maxCount) { + if (rf.img00Cnt >= rf.maxCount) { + if (rf.img01Cnt >= rf.maxCount) { + // Reboot to fallback image + } else { + tgtChip = xsc::CHIP_0; + tgtCopy = xsc::COPY_1; + } + } else { + tgtChip = xsc::CHIP_0; + tgtCopy = xsc::COPY_0; + } + } else { + tgtChip = xsc::CHIP_1; + tgtCopy = xsc::COPY_1; + } + } + if ((CURRENT_COPY == xsc::COPY_1) and (CURRENT_CHIP == xsc::CHIP_1) and + (rf.img11Cnt >= rf.maxCount)) { + needsReboot = true; + if (rf.img10Cnt >= rf.maxCount) { + if (rf.img00Cnt >= rf.maxCount) { + if (rf.img01Cnt >= rf.maxCount) { + // Reboot to fallback image + } else { + tgtChip = xsc::CHIP_0; + tgtCopy = xsc::COPY_1; + } + } else { + tgtChip = xsc::CHIP_0; + tgtCopy = xsc::COPY_0; + } + } else { + tgtChip = xsc::CHIP_1; + tgtCopy = xsc::COPY_0; + } + } +} + +bool CoreController::parseRebootFile(std::string path, RebootFile &rf) { + using namespace std; + std::string selfMatch; + if (CURRENT_CHIP == xsc::CHIP_0) { + if (CURRENT_COPY == xsc::COPY_0) { + selfMatch = "00"; + } else { + selfMatch = "01"; + } + } else { + if (CURRENT_COPY == xsc::COPY_0) { + selfMatch = "10"; + } else { + selfMatch = "11"; + } + } + ifstream file(path); + string word; + string line; + uint8_t lineIdx = 0; + while (std::getline(file, line)) { + istringstream iss(line); + switch (lineIdx) { + case 0: { + iss >> word; + if (word.find("on:") == string::npos) { + // invalid file + return false; + } + iss >> rf.enabled; + break; + } + case 1: { + iss >> word; + if (word.find("maxcnt:") == string::npos) { + return false; + } + iss >> rf.maxCount; + break; + } + case 2: { + iss >> word; + if (word.find("img00:") == string::npos) { + return false; + } + iss >> rf.img00Cnt; + if (word.find(selfMatch) != string::npos) { + rf.relevantBootCnt = rf.img00Cnt; + } + break; + } + case 3: { + iss >> word; + if (word.find("img01:") == string::npos) { + return false; + } + iss >> rf.img01Cnt; + if (word.find(selfMatch) != string::npos) { + rf.relevantBootCnt = rf.img01Cnt; + } + break; + } + case 4: { + iss >> word; + if (word.find("img10:") == string::npos) { + return false; + } + iss >> rf.img10Cnt; + if (word.find(selfMatch) != string::npos) { + rf.relevantBootCnt = rf.img10Cnt; + } + break; + } + case 5: { + iss >> word; + if (word.find("img11:") == string::npos) { + return false; + } + iss >> rf.img11Cnt; + if (word.find(selfMatch) != string::npos) { + rf.relevantBootCnt = rf.img11Cnt; + } + break; + } + case 6: { + iss >> word; + if (word.find("bootflag:") == string::npos) { + return false; + } + iss >> rf.bootFlag; + break; + } + case 7: { + iss >> word; + if (word.find("bootflag:") == string::npos) { + return false; + } + break; + } + case 8: { + iss >> word; + uint8_t copyRaw = 0; + uint8_t chipRaw = 0; + if (word.find("last:") == string::npos) { + return false; + } + iss >> chipRaw; + if (iss.fail()) { + return false; + } + iss >> copyRaw; + if (iss.fail()) { + return false; + } + + if (chipRaw > 1 or copyRaw > 1) { + return false; + } + rf.lastChip = static_cast(chipRaw); + rf.lastCopy = static_cast(copyRaw); + } + } + if (iss.fail()) { + return false; + } + lineIdx++; + } + if (lineIdx < 8) { + return false; + } + return true; +} + +void CoreController::resetRebootCount(xsc::Chip tgtChip, xsc::Copy tgtCopy) { + std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE; + // Disable the reboot file mechanism + parseRebootFile(path, rebootFile); + if (tgtChip == xsc::ALL_CHIP and tgtCopy == xsc::ALL_COPY) { + rebootFile.img00Cnt = 0; + rebootFile.img01Cnt = 0; + rebootFile.img10Cnt = 0; + rebootFile.img11Cnt = 0; + } else { + if (tgtChip == xsc::CHIP_0) { + if (tgtCopy == xsc::COPY_0) { + rebootFile.img00Cnt = 0; + } else { + rebootFile.img01Cnt = 0; + } + } else { + if (tgtCopy == xsc::COPY_0) { + rebootFile.img10Cnt = 0; + } else { + rebootFile.img11Cnt = 0; + } + } + } + rewriteRebootFile(rebootFile); +} + +void CoreController::rewriteRebootFile(RebootFile file) { + std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE; + std::ofstream rebootFile(path); + if (rebootFile.is_open()) { + // Initiate reboot file first. Reboot handling will be on on initialization + rebootFile << "on: " << file.enabled << "\nmaxcnt: " << file.maxCount + << "\nimg00: " << file.img00Cnt << "\nimg01: " << file.img01Cnt + << "\nimg10: " << file.img10Cnt << "\nimg11: " << file.img11Cnt + << "\nbootflag: " << file.bootFlag << "\nlast: " << file.lastChip << " " + << file.lastCopy << "\n"; + } +} diff --git a/bsp_q7s/core/CoreController.h b/bsp_q7s/core/CoreController.h index 5365000a..38efda23 100644 --- a/bsp_q7s/core/CoreController.h +++ b/bsp_q7s/core/CoreController.h @@ -2,6 +2,9 @@ #define BSP_Q7S_CORE_CORECONTROLLER_H_ #include +#include + +#include #include "bsp_q7s/memory/SdCardManager.h" #include "events/subsystemIdRanges.h" @@ -10,24 +13,64 @@ class Timer; class SdCardManager; +namespace xsc { + +enum Chip : uint8_t { CHIP_0, CHIP_1, NO_CHIP, SELF_CHIP, ALL_CHIP }; +enum Copy : uint8_t { COPY_0, COPY_1, NO_COPY, SELF_COPY, ALL_COPY }; + +} // namespace xsc + +struct RebootFile { + static constexpr uint8_t DEFAULT_MAX_BOOT_CNT = 10; + + bool enabled = false; + size_t maxCount = DEFAULT_MAX_BOOT_CNT; + uint8_t img00Cnt = 0; + uint8_t img01Cnt = 0; + uint8_t img10Cnt = 0; + uint8_t img11Cnt = 0; + uint8_t relevantBootCnt = 0; + bool bootFlag = false; + xsc::Chip lastChip = xsc::Chip::CHIP_0; + xsc::Copy lastCopy = xsc::Copy::COPY_0; +}; + class CoreController : public ExtendedControllerBase { public: - enum Chip : uint8_t { CHIP_0, CHIP_1, NO_CHIP, SELF_CHIP, ALL_CHIP }; - - enum Copy : uint8_t { COPY_0, COPY_1, NO_COPY, SELF_COPY, ALL_COPY }; + static xsc::Chip CURRENT_CHIP; + static xsc::Copy CURRENT_COPY; static constexpr char CHIP_PROT_SCRIPT[] = "/home/root/scripts/get-chip-prot-status.sh"; static constexpr char CHIP_STATE_FILE[] = "/tmp/chip_prot_status.txt"; static constexpr char CURR_COPY_FILE[] = "/tmp/curr_copy.txt"; - static constexpr char VERSION_FILE[] = "/conf/sd_status"; + static constexpr char VERSION_FILE[] = "/conf/version.txt"; + static constexpr char REBOOT_FILE[] = "/conf/reboot.txt"; static constexpr ActionId_t LIST_DIRECTORY_INTO_FILE = 0; + static constexpr ActionId_t SWITCH_REBOOT_FILE_HANDLING = 5; + static constexpr ActionId_t RESET_ALL_REBOOT_COUNTERS = 6; + static constexpr ActionId_t RESET_REBOOT_COUNTER_00 = 7; + static constexpr ActionId_t RESET_REBOOT_COUNTER_01 = 8; + static constexpr ActionId_t RESET_REBOOT_COUNTER_10 = 9; + static constexpr ActionId_t RESET_REBOOT_COUNTER_11 = 10; + static constexpr ActionId_t SET_MAX_REBOOT_CNT = 11; + static constexpr ActionId_t REBOOT_OBC = 32; static constexpr ActionId_t MOUNT_OTHER_COPY = 33; static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::CORE; static constexpr Event ALLOC_FAILURE = event::makeEvent(SUBSYSTEM_ID, 0, severity::MEDIUM); + //! [EXPORT] : [COMMENT] Software reboot occured. Can also be a systemd reboot. + //! P1: Current Chip, P2: Current Copy + static constexpr Event REBOOT_SW = event::makeEvent(SUBSYSTEM_ID, 1, severity::MEDIUM); + //! [EXPORT] : [COMMENT] The reboot mechanism was triggered. + //! P1: First 16 bits: Last Chip, Last 16 bits: Last Copy, + //! P2: Each byte is the respective reboot count for the slots + static constexpr Event REBOOT_MECHANISM_TRIGGERED = + event::makeEvent(SUBSYSTEM_ID, 2, severity::MEDIUM); + //! Trying to find a way how to determine that the reboot came from ProASIC3 or PCDU.. + static constexpr Event REBOOT_HW = event::makeEvent(SUBSYSTEM_ID, 3, severity::MEDIUM); CoreController(object_id_t objectId); virtual ~CoreController(); @@ -48,7 +91,7 @@ class CoreController : public ExtendedControllerBase { */ static ReturnValue_t generateChipStateFile(); static ReturnValue_t incrementAllocationFailureCount(); - static void getCurrentBootCopy(Chip& chip, Copy& copy); + static void getCurrentBootCopy(xsc::Chip& chip, xsc::Copy& copy); ReturnValue_t updateProtInfo(bool regenerateChipStateFile = true); @@ -63,15 +106,12 @@ class CoreController : public ExtendedControllerBase { * @param updateProtFile Specify whether the protection info file is updated * @return */ - ReturnValue_t setBootCopyProtection(Chip targetChip, Copy targetCopy, bool protect, + ReturnValue_t setBootCopyProtection(xsc::Chip targetChip, xsc::Copy targetCopy, bool protect, bool& protOperationPerformed, bool updateProtFile = true); bool sdInitFinished() const; private: - static Chip CURRENT_CHIP; - static Copy CURRENT_COPY; - // Designated value for rechecking FIFO open static constexpr int RETRY_FIFO_OPEN = -2; int watchdogFifoFd = 0; @@ -122,6 +162,8 @@ class CoreController : public ExtendedControllerBase { sd::SdState commandedState = sd::SdState::OFF; }; SdInfo sdInfo; + RebootFile rebootFile = {}; + bool doPerformRebootFileHandling = true; /** * Index 0: Chip 0 Copy 0 @@ -152,6 +194,7 @@ class CoreController : public ExtendedControllerBase { void determinePreferredSdCard(); void executeNextExternalSdCommand(); void checkExternalSdCommandStatus(); + void performRebootFileHandling(bool recreateFile); ReturnValue_t actionListDirectoryIntoFile(ActionId_t actionId, MessageQueueId_t commandedBy, const uint8_t* data, size_t size); @@ -160,9 +203,14 @@ class CoreController : public ExtendedControllerBase { void performWatchdogControlOperation(); ReturnValue_t handleProtInfoUpdateLine(std::string nextLine); - int handleBootCopyProtAtIndex(Chip targetChip, Copy targetCopy, bool protect, + int handleBootCopyProtAtIndex(xsc::Chip targetChip, xsc::Copy targetCopy, bool protect, bool& protOperationPerformed, bool selfChip, bool selfCopy, bool allChips, bool allCopies, uint8_t arrIdx); + void determineAndExecuteReboot(RebootFile& rf, bool& needsReboot, xsc::Chip& tgtChip, + xsc::Copy& tgtCopy); + void resetRebootCount(xsc::Chip tgtChip, xsc::Copy tgtCopy); + bool parseRebootFile(std::string path, RebootFile& file); + void rewriteRebootFile(RebootFile file); }; #endif /* BSP_Q7S_CORE_CORECONTROLLER_H_ */ diff --git a/bsp_q7s/memory/SdCardManager.cpp b/bsp_q7s/memory/SdCardManager.cpp index 3647ff7b..b9b89bb9 100644 --- a/bsp_q7s/memory/SdCardManager.cpp +++ b/bsp_q7s/memory/SdCardManager.cpp @@ -7,6 +7,7 @@ #include #include +#include "common/config/commonObjects.h" #include "fsfw/ipc/MutexFactory.h" #include "fsfw/serviceinterface/ServiceInterface.h" #include "linux/utility/utility.h" @@ -14,7 +15,7 @@ SdCardManager* SdCardManager::factoryInstance = nullptr; -SdCardManager::SdCardManager() : cmdExecutor(256) {} +SdCardManager::SdCardManager() : SystemObject(objects::SDC_MANAGER), cmdExecutor(256) {} SdCardManager::~SdCardManager() {} diff --git a/bsp_q7s/memory/SdCardManager.h b/bsp_q7s/memory/SdCardManager.h index 4446a102..51ea3425 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 #include @@ -22,7 +23,7 @@ class MutexIF; * @brief Manages handling of SD cards like switching them on or off or getting the current * state */ -class SdCardManager { +class SdCardManager : public SystemObject { friend class SdCardAccess; public: @@ -54,6 +55,7 @@ class SdCardManager { static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::FILE_SYSTEM; static constexpr Event SANITIZATION_FAILED = event::makeEvent(SUBSYSTEM_ID, 0, severity::LOW); + static constexpr Event MOUNTED_SD_CARD = event::makeEvent(SUBSYSTEM_ID, 1, severity::INFO); // C++17 does not support constexpr std::string yet static constexpr char SD_0_DEV_NAME[] = "/dev/mmcblk0p1"; @@ -183,7 +185,7 @@ class SdCardManager { /** * @brief Checks if an SD card is mounted * - * @param sdCard The SD crad to check + * @param sdCard The SD card to check * * @return true if mounted, otherwise false */ diff --git a/cmake/Q7SCrossCompileConfig.cmake b/cmake/Q7SCrossCompileConfig.cmake index d4d05f4e..db05c8f0 100644 --- a/cmake/Q7SCrossCompileConfig.cmake +++ b/cmake/Q7SCrossCompileConfig.cmake @@ -81,12 +81,23 @@ set(CMAKE_PREFIX_PATH # "${SYSROOT_PATH}/usr/lib/${CROSS_COMPILE}" ) +set(C_FLAGS + -mcpu=cortex-a9 + -mfpu=neon-vfpv3 + -mfloat-abi=hard + ${COMMON_FLAGS} + -lgpiod + -lxiphos +) + +string (REPLACE ";" " " C_FLAGS "${C_FLAGS}") + set(CMAKE_C_FLAGS - "-mcpu=cortex-a9 -mfpu=neon-vfpv3 -mfloat-abi=hard ${COMMON_FLAGS} -lgpiod" + ${C_FLAGS} CACHE STRING "C flags for Q7S" ) set(CMAKE_CXX_FLAGS - "${CMAKE_C_FLAGS}" + "${CMAKE_C_FLAGS}" CACHE STRING "CPP flags for Q7S" ) diff --git a/common/config/commonSubsystemIds.h b/common/config/commonSubsystemIds.h index 55a4bed4..9f293ec6 100644 --- a/common/config/commonSubsystemIds.h +++ b/common/config/commonSubsystemIds.h @@ -19,6 +19,7 @@ enum: uint8_t { PLOC_MEMORY_DUMPER = 118, PDEC_HANDLER = 119, STR_HELPER = 120, + PL_PCDU_HANDLER = 121, COMMON_SUBSYSTEM_ID_END }; } diff --git a/unittest/rebootLogic/.gitignore b/unittest/rebootLogic/.gitignore new file mode 100644 index 00000000..796b96d1 --- /dev/null +++ b/unittest/rebootLogic/.gitignore @@ -0,0 +1 @@ +/build diff --git a/unittest/rebootLogic/CMakeLists.txt b/unittest/rebootLogic/CMakeLists.txt new file mode 100644 index 00000000..74fdb423 --- /dev/null +++ b/unittest/rebootLogic/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 3.0.0) +project(reboot-logic VERSION 0.1.0) + +include(CTest) +enable_testing() + +add_executable(reboot-logic main.cpp) + +set(CPACK_PROJECT_NAME ${PROJECT_NAME}) +set(CPACK_PROJECT_VERSION ${PROJECT_VERSION}) +include(CPack) diff --git a/unittest/rebootLogic/main.cpp b/unittest/rebootLogic/main.cpp new file mode 100644 index 00000000..c4a394dc --- /dev/null +++ b/unittest/rebootLogic/main.cpp @@ -0,0 +1,5 @@ +#include + +int main(int, char**) { + std::cout << "Hello, world!\n"; +} From 55618e381cffc17b28b7b098794be3ce3930e517 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 25 Feb 2022 13:20:17 +0100 Subject: [PATCH 3/5] update README --- README.md | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8268ea24..262132fd 100644 --- a/README.md +++ b/README.md @@ -441,12 +441,24 @@ Beagle Bone Black for download here Download it and unzip it somewhere in the Xilinx installation folder. You can use the following command if `wget` can be used or for CI/CD: -``` -wget https://eive-cloud.irs.uni-stuttgart.de/index.php/s/agnJGYeRf6fw2ci/download/cortexa9hf-neon-xiphos-linux-gnueabi.tar.gz +```sh +wget https://eive-cloud.irs.uni-stuttgart.de/index.php/s/SyXpdBBQX32xPgE/download/cortexa9hf-neon-xiphos-linux-gnueabi.tar.gz ``` Then, create a new environmental variables `Q7S_SYSROOT` and set it to the local system root path. +### Updating system root for CI + +If the system root is updated, it needs to be manually updated on the buggy file server. +If access on `buggy.irs.uni-stuttgart.de` is possible with `ssh` and the rootfs in the cloud +[was updated](https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/EIVE_IRS/Software/rootfs&fileid=831849) +as well, you can update the rootfs like this: + +```sh +cd /var/www/eive/tools +wget https://eive-cloud.irs.uni-stuttgart.de/index.php/s/SyXpdBBQX32xPgE/download/cortexa9hf-neon-xiphos-linux-gnueabi.tar.gz +``` + ## Setting up UNIX environment for real-time functionalities Please note that on most UNIX environments (e.g. Ubuntu), the real time functionalities From dfaaae551214b40c2aae113520b90d5e3fb99923 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 25 Feb 2022 13:24:34 +0100 Subject: [PATCH 4/5] cleanDocker --- cleandocker.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 cleandocker.txt diff --git a/cleandocker.txt b/cleandocker.txt new file mode 100644 index 00000000..e69de29b From da78e57dd376357b86c3e3b6c13f672241e3f338 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 25 Feb 2022 13:24:44 +0100 Subject: [PATCH 5/5] cleanDocker --- cleandocker.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 cleandocker.txt diff --git a/cleandocker.txt b/cleandocker.txt deleted file mode 100644 index e69de29b..00000000