From 00bd6e260a5cc4de768e17ec4b86b55a5a0d5b29 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 25 Feb 2022 11:32:08 +0100 Subject: [PATCH 01/25] 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 02/25] 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 03/25] 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 04/25] 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 05/25] 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 From 042acc1a23f96f52bb500ea9f307e700258e12bd Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 28 Feb 2022 14:13:31 +0100 Subject: [PATCH 06/25] reboot logic unittest init --- .gitignore | 2 +- bsp_q7s/core/CoreController.h | 3 +- unittest/rebootLogic/.vscode/settings.json | 3 + unittest/rebootLogic/CMakeLists.txt | 12 + unittest/rebootLogic/CoreController.cpp | 376 +++++++++++++++++++++ unittest/rebootLogic/CoreController.h | 59 ++++ unittest/rebootLogic/SdCardManager.cpp | 9 + unittest/rebootLogic/SdCardManager.h | 23 ++ unittest/rebootLogic/conf.h | 1 + unittest/rebootLogic/event.cpp | 3 + unittest/rebootLogic/event.h | 5 + unittest/rebootLogic/libxiphos.cpp | 5 + unittest/rebootLogic/libxiphos.h | 17 + unittest/rebootLogic/main.cpp | 2 + 14 files changed, 517 insertions(+), 3 deletions(-) create mode 100644 unittest/rebootLogic/.vscode/settings.json create mode 100644 unittest/rebootLogic/CoreController.cpp create mode 100644 unittest/rebootLogic/CoreController.h create mode 100644 unittest/rebootLogic/SdCardManager.cpp create mode 100644 unittest/rebootLogic/SdCardManager.h create mode 100644 unittest/rebootLogic/conf.h create mode 100644 unittest/rebootLogic/event.cpp create mode 100644 unittest/rebootLogic/event.h create mode 100644 unittest/rebootLogic/libxiphos.cpp create mode 100644 unittest/rebootLogic/libxiphos.h diff --git a/.gitignore b/.gitignore index 2f7acd11..c337ab89 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,7 @@ !misc/eclipse/**/.project #vscode -.vscode +/.vscode # Python __pycache__ diff --git a/bsp_q7s/core/CoreController.h b/bsp_q7s/core/CoreController.h index 38efda23..c7577e02 100644 --- a/bsp_q7s/core/CoreController.h +++ b/bsp_q7s/core/CoreController.h @@ -160,8 +160,7 @@ class CoreController : public ExtendedControllerBase { sd::SdState currentlyCommandedState = sd::SdState::OFF; sd::SdCard commandedCard = sd::SdCard::NONE; sd::SdState commandedState = sd::SdState::OFF; - }; - SdInfo sdInfo; + } sdInfo; RebootFile rebootFile = {}; bool doPerformRebootFileHandling = true; diff --git a/unittest/rebootLogic/.vscode/settings.json b/unittest/rebootLogic/.vscode/settings.json new file mode 100644 index 00000000..ff30c446 --- /dev/null +++ b/unittest/rebootLogic/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "editor.tabSize": 2 +} \ No newline at end of file diff --git a/unittest/rebootLogic/CMakeLists.txt b/unittest/rebootLogic/CMakeLists.txt index 74fdb423..4af51d08 100644 --- a/unittest/rebootLogic/CMakeLists.txt +++ b/unittest/rebootLogic/CMakeLists.txt @@ -6,6 +6,18 @@ enable_testing() add_executable(reboot-logic main.cpp) +target_sources(reboot-logic PRIVATE + main.cpp + CoreController.cpp + SdCardManager.cpp + event.cpp + libxiphos.cpp +) + +target_include_directories(reboot-logic PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} +) + set(CPACK_PROJECT_NAME ${PROJECT_NAME}) set(CPACK_PROJECT_VERSION ${PROJECT_VERSION}) include(CPack) diff --git a/unittest/rebootLogic/CoreController.cpp b/unittest/rebootLogic/CoreController.cpp new file mode 100644 index 00000000..127c4a92 --- /dev/null +++ b/unittest/rebootLogic/CoreController.cpp @@ -0,0 +1,376 @@ +#include "conf.h" +#include "CoreController.h" +#include "SdCardManager.h" +#include "event.h" +#include "libxiphos.h" + +#include +#include +#include + +xsc::Chip CoreController::CURRENT_CHIP = xsc::Chip::NO_CHIP; +xsc::Copy CoreController::CURRENT_COPY = xsc::Copy::NO_COPY; + +CoreController::CoreController() { + sdcMan = new SdCardManager(); +} + +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 + std::cout << "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 + std::cout << "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 + std::cout << "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/unittest/rebootLogic/CoreController.h b/unittest/rebootLogic/CoreController.h new file mode 100644 index 00000000..f3fec0e2 --- /dev/null +++ b/unittest/rebootLogic/CoreController.h @@ -0,0 +1,59 @@ +#pragma once + +#include "SdCardManager.h" + +#include +#include +#include + +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 SdCardManager; + +class CoreController { +public: + static constexpr char REBOOT_FILE[] = "/conf/reboot.txt"; + static constexpr uint32_t REBOOT_MECHANISM_TRIGGERED = 1; + static xsc::Chip CURRENT_CHIP; + static xsc::Copy CURRENT_COPY; + + CoreController(); + void performRebootFileHandling(bool recreateFile); + 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); +private: + 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; + } sdInfo; + + SdCardManager* sdcMan = nullptr; + RebootFile rebootFile = {}; + bool doPerformRebootFileHandling = true; +}; \ No newline at end of file diff --git a/unittest/rebootLogic/SdCardManager.cpp b/unittest/rebootLogic/SdCardManager.cpp new file mode 100644 index 00000000..19bfa183 --- /dev/null +++ b/unittest/rebootLogic/SdCardManager.cpp @@ -0,0 +1,9 @@ +#include "SdCardManager.h" + +std::string SdCardManager::getCurrentMountPrefix(sd::SdCard prefSdCard) { + return "/tmp"; +} + +bool SdCardManager::isSdCardMounted(sd::SdCard sdCard) { + return true; +} \ No newline at end of file diff --git a/unittest/rebootLogic/SdCardManager.h b/unittest/rebootLogic/SdCardManager.h new file mode 100644 index 00000000..aee31d79 --- /dev/null +++ b/unittest/rebootLogic/SdCardManager.h @@ -0,0 +1,23 @@ +#pragma once + +#include +#include + +namespace sd { + +enum SdState : uint8_t { + OFF = 0, + ON = 1, + // A mounted SD card is on as well + MOUNTED = 2 +}; + +enum SdCard : uint8_t { SLOT_0 = 0, SLOT_1 = 1, BOTH, NONE }; + +} // namespace sd + +class SdCardManager { +public: + std::string getCurrentMountPrefix(sd::SdCard prefSdCard); + bool isSdCardMounted(sd::SdCard sdCard); +}; diff --git a/unittest/rebootLogic/conf.h b/unittest/rebootLogic/conf.h new file mode 100644 index 00000000..e2779c4a --- /dev/null +++ b/unittest/rebootLogic/conf.h @@ -0,0 +1 @@ +#define OBSW_VERBOSE_LEVEL 1 \ No newline at end of file diff --git a/unittest/rebootLogic/event.cpp b/unittest/rebootLogic/event.cpp new file mode 100644 index 00000000..4d2d3302 --- /dev/null +++ b/unittest/rebootLogic/event.cpp @@ -0,0 +1,3 @@ +#include "event.h" + +void triggerEvent(uint32_t event, uint32_t p1, uint32_t p2) {} \ No newline at end of file diff --git a/unittest/rebootLogic/event.h b/unittest/rebootLogic/event.h new file mode 100644 index 00000000..c96b8bab --- /dev/null +++ b/unittest/rebootLogic/event.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +void triggerEvent(uint32_t event, uint32_t p1, uint32_t p2); \ No newline at end of file diff --git a/unittest/rebootLogic/libxiphos.cpp b/unittest/rebootLogic/libxiphos.cpp new file mode 100644 index 00000000..110b0994 --- /dev/null +++ b/unittest/rebootLogic/libxiphos.cpp @@ -0,0 +1,5 @@ +#include "libxiphos.h" + +void xsc_boot_copy(xsc_libnor_chip_t boot_chip, xsc_libnor_copy_t boot_copy) { + +} \ No newline at end of file diff --git a/unittest/rebootLogic/libxiphos.h b/unittest/rebootLogic/libxiphos.h new file mode 100644 index 00000000..a0f3f4d6 --- /dev/null +++ b/unittest/rebootLogic/libxiphos.h @@ -0,0 +1,17 @@ +#pragma once + +/** Type for identifying the nominal or the gold (redundant) flash copy */ +typedef enum { + XSC_LIBNOR_COPY_NOMINAL, + XSC_LIBNOR_COPY_GOLD, + XSC_LIBNOR_COPY_TOTAL_NUMBER +} xsc_libnor_copy_t; + +/** Type for identifying on of the two NOR flash chips */ +typedef enum { + XSC_LIBNOR_CHIP_0, /* First NOR flash chip */ + XSC_LIBNOR_CHIP_1, /* Second NOR flash chip */ + XSC_LIBNOR_CHIP_TOTAL_NUMBER +} xsc_libnor_chip_t; + +void xsc_boot_copy(xsc_libnor_chip_t boot_chip, xsc_libnor_copy_t boot_copy); \ No newline at end of file diff --git a/unittest/rebootLogic/main.cpp b/unittest/rebootLogic/main.cpp index c4a394dc..f3e8680e 100644 --- a/unittest/rebootLogic/main.cpp +++ b/unittest/rebootLogic/main.cpp @@ -1,5 +1,7 @@ +#include "CoreController.h" #include int main(int, char**) { + CoreController ctrl; std::cout << "Hello, world!\n"; } From ff35986a16faaa142b8d6776097137b385828396 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 28 Feb 2022 15:59:33 +0100 Subject: [PATCH 07/25] fsfw update --- fsfw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fsfw b/fsfw index 123f2ff3..2d9216ba 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit 123f2ff360e71228e1c0c786d80a4c93d7144a2e +Subproject commit 2d9216ba19f1931225daa5b6b6f244a48c09f1b9 From 8e6d8a6fa8663fc98d73ebe62636e429ba1b674f Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 28 Feb 2022 16:05:32 +0100 Subject: [PATCH 08/25] use catch2 main --- unittest/rebootLogic/CMakeLists.txt | 17 +++++++++++++++++ unittest/rebootLogic/main.cpp | 3 ++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/unittest/rebootLogic/CMakeLists.txt b/unittest/rebootLogic/CMakeLists.txt index 4af51d08..9377d45e 100644 --- a/unittest/rebootLogic/CMakeLists.txt +++ b/unittest/rebootLogic/CMakeLists.txt @@ -2,6 +2,21 @@ cmake_minimum_required(VERSION 3.0.0) project(reboot-logic VERSION 0.1.0) include(CTest) +find_package(Catch2 3) +if(NOT Catch2_FOUND) + include(FetchContent) + + FetchContent_Declare( + Catch2 + GIT_REPOSITORY https://github.com/catchorg/Catch2.git + GIT_TAG v3.0.0-preview4 + ) + + FetchContent_MakeAvailable(Catch2) + #fixes regression -preview4, to be confirmed in later releases + set_target_properties(Catch2 PROPERTIES DEBUG_POSTFIX "") +endif() + enable_testing() add_executable(reboot-logic main.cpp) @@ -14,6 +29,8 @@ target_sources(reboot-logic PRIVATE libxiphos.cpp ) +target_link_libraries(reboot-logic PRIVATE Catch2::Catch2WithMain) + target_include_directories(reboot-logic PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ) diff --git a/unittest/rebootLogic/main.cpp b/unittest/rebootLogic/main.cpp index f3e8680e..cd6117ab 100644 --- a/unittest/rebootLogic/main.cpp +++ b/unittest/rebootLogic/main.cpp @@ -1,7 +1,8 @@ #include "CoreController.h" +#include #include -int main(int, char**) { +TEST_CASE( "Core Controller Reboot File Handling", "[reboot-file]" ) { CoreController ctrl; std::cout << "Hello, world!\n"; } From a2bc72a7981bcd53e23e4f86c01c8b0421bbef55 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 28 Feb 2022 16:35:16 +0100 Subject: [PATCH 09/25] improved mount logic, create conf folder is missing --- bsp_q7s/core/CoreController.cpp | 177 ++++++++++++------------ bsp_q7s/core/CoreController.h | 12 +- fsfw | 2 +- unittest/rebootLogic/CoreController.cpp | 158 ++++++++++----------- unittest/rebootLogic/main.cpp | 2 +- 5 files changed, 177 insertions(+), 174 deletions(-) diff --git a/bsp_q7s/core/CoreController.cpp b/bsp_q7s/core/CoreController.cpp index c106cd7e..d9022b57 100644 --- a/bsp_q7s/core/CoreController.cpp +++ b/bsp_q7s/core/CoreController.cpp @@ -59,7 +59,7 @@ ReturnValue_t CoreController::handleCommandMessage(CommandMessage *message) { void CoreController::performControlOperation() { performWatchdogControlOperation(); sdStateMachine(); - performRebootFileHandling(false); + performMountedSdCardOperations(); } ReturnValue_t CoreController::initializeLocalDataPool(localpool::DataPool &localDataPoolMap, @@ -94,7 +94,7 @@ ReturnValue_t CoreController::initializeAfterTaskCreation() { } } sdStateMachine(); - result = initVersionFile(); + performMountedSdCardOperations(); if (result != HasReturnvaluesIF::RETURN_OK) { sif::warning << "CoreController::initialize: Version initialization failed" << std::endl; } @@ -1174,102 +1174,93 @@ void CoreController::performWatchdogControlOperation() { } void CoreController::performRebootFileHandling(bool recreateFile) { - bool sdCardMounted = false; - if (not recreateFile and doPerformRebootFileHandling) { - sdCardMounted = sdcMan->isSdCardMounted(sdInfo.pref); + using namespace std; + std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE; + if (not std::filesystem::exists(path) or recreateFile) { +#if OBSW_VERBOSE_LEVEL >= 1 + sif::info << "CoreController::performRebootFileHandling: Recreating reboot file" << std::endl; +#endif + 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 ((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; - } + 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; - } + switch (CURRENT_CHIP) { + case (xsc::CHIP_0): { + switch (CURRENT_COPY) { + case (xsc::COPY_0): { + rebootFile.img00Cnt++; + 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; - } + case (xsc::COPY_1): { + rebootFile.img01Cnt++; + break; + } + default: { + break; } - 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; } - if (CURRENT_CHIP == xsc::CHIP_0 and CURRENT_COPY == xsc::COPY_0) { + default: { + break; } - 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 (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; + 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); + xsc_boot_copy(static_cast(rebootFile.lastChip), + static_cast(rebootFile.lastCopy)); } - doPerformRebootFileHandling = false; + } else { + rewriteRebootFile(rebootFile); } } @@ -1520,6 +1511,22 @@ void CoreController::resetRebootCount(xsc::Chip tgtChip, xsc::Copy tgtCopy) { rewriteRebootFile(rebootFile); } +void CoreController::performMountedSdCardOperations() { + if(doPerformMountedSdCardOps) { + bool sdCardMounted = false; + sdCardMounted = sdcMan->isSdCardMounted(sdInfo.pref); + if(sdCardMounted) { + std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + "/" + CONF_FOLDER; + if(not std::filesystem::exists(path)) { + std::filesystem::create_directory(path); + } + initVersionFile(); + performRebootFileHandling(true); + doPerformMountedSdCardOps = false; + } + } +} + void CoreController::rewriteRebootFile(RebootFile file) { std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE; std::ofstream rebootFile(path); diff --git a/bsp_q7s/core/CoreController.h b/bsp_q7s/core/CoreController.h index c7577e02..6a8bb8cd 100644 --- a/bsp_q7s/core/CoreController.h +++ b/bsp_q7s/core/CoreController.h @@ -43,8 +43,11 @@ class CoreController : public ExtendedControllerBase { 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/version.txt"; - static constexpr char REBOOT_FILE[] = "/conf/reboot.txt"; + static constexpr char CONF_FOLDER[] = "conf"; + static constexpr char VERSION_FILE_NAME[] = "version.txt"; + static constexpr char REBOOT_FILE_NAME[] = "reboot.txt"; + const std::string VERSION_FILE = "/" + std::string(CONF_FOLDER) + "/" + std::string(VERSION_FILE_NAME); + const std::string REBOOT_FILE = "/" + std::string(CONF_FOLDER) + "/" + std::string(REBOOT_FILE_NAME); static constexpr ActionId_t LIST_DIRECTORY_INTO_FILE = 0; static constexpr ActionId_t SWITCH_REBOOT_FILE_HANDLING = 5; @@ -162,7 +165,7 @@ class CoreController : public ExtendedControllerBase { sd::SdState commandedState = sd::SdState::OFF; } sdInfo; RebootFile rebootFile = {}; - bool doPerformRebootFileHandling = true; + bool doPerformMountedSdCardOps = true; /** * Index 0: Chip 0 Copy 0 @@ -177,7 +180,7 @@ class CoreController : public ExtendedControllerBase { LocalDataPoolManager& poolManager) override; LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override; ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, uint32_t* msToReachTheMode); - + void performMountedSdCardOperations(); ReturnValue_t initVersionFile(); ReturnValue_t initBootCopy(); ReturnValue_t initWatchdogFifo(); @@ -189,6 +192,7 @@ class CoreController : public ExtendedControllerBase { 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(); diff --git a/fsfw b/fsfw index 2d9216ba..6e0b9069 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit 2d9216ba19f1931225daa5b6b6f244a48c09f1b9 +Subproject commit 6e0b90696da2dfd2ec4749dfdb73950be2283c25 diff --git a/unittest/rebootLogic/CoreController.cpp b/unittest/rebootLogic/CoreController.cpp index 127c4a92..d9269c06 100644 --- a/unittest/rebootLogic/CoreController.cpp +++ b/unittest/rebootLogic/CoreController.cpp @@ -16,105 +16,97 @@ CoreController::CoreController() { } void CoreController::performRebootFileHandling(bool recreateFile) { - bool sdCardMounted = false; - if (not recreateFile and doPerformRebootFileHandling) { - sdCardMounted = sdcMan->isSdCardMounted(sdInfo.pref); + using namespace std; + std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE; + if (not std::filesystem::exists(path) or recreateFile) { +#if OBSW_VERBOSE_LEVEL >= 1 + std::cout << "CoreController::performRebootFileHandling: Recreating reboot file" << std::endl; +#endif + 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 ((doPerformRebootFileHandling and sdCardMounted) or recreateFile) { - using namespace std; - if (recreateFile) { -#if OBSW_VERBOSE_LEVEL >= 1 - std::cout << "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; - } + 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; - } + switch (CURRENT_CHIP) { + case (xsc::CHIP_0): { + switch (CURRENT_COPY) { + case (xsc::COPY_0): { + rebootFile.img00Cnt++; + 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; - } + case (xsc::COPY_1): { + rebootFile.img01Cnt++; + break; + } + default: { + break; } - 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; } - if (CURRENT_CHIP == xsc::CHIP_0 and CURRENT_COPY == xsc::COPY_0) { + default: { + break; } - 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 (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 - std::cout << "Boot counter for image " << CURRENT_CHIP << " " << CURRENT_COPY - << "too high. Rebooting to " << rebootFile.lastChip << " " << rebootFile.lastCopy - << std::endl; + std::cout << "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); + xsc_boot_copy(static_cast(rebootFile.lastChip), + static_cast(rebootFile.lastCopy)); } - doPerformRebootFileHandling = false; + } else { + rewriteRebootFile(rebootFile); } } + void CoreController::determineAndExecuteReboot(RebootFile &rf, bool &needsReboot, xsc::Chip &tgtChip, xsc::Copy &tgtCopy) { tgtChip = xsc::CHIP_0; diff --git a/unittest/rebootLogic/main.cpp b/unittest/rebootLogic/main.cpp index cd6117ab..1a7748c9 100644 --- a/unittest/rebootLogic/main.cpp +++ b/unittest/rebootLogic/main.cpp @@ -4,5 +4,5 @@ TEST_CASE( "Core Controller Reboot File Handling", "[reboot-file]" ) { CoreController ctrl; - std::cout << "Hello, world!\n"; + ctrl.performRebootFileHandling(true); } From 8c2c402821297dc2d61f4ecad108193104a9318f Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 28 Feb 2022 16:47:36 +0100 Subject: [PATCH 10/25] continued tests, first fixes --- bsp_q7s/core/CoreController.cpp | 10 ++++---- bsp_q7s/core/CoreController.h | 16 +++++++------ bsp_q7s/core/InitMission.cpp | 2 +- unittest/rebootLogic/.vscode/settings.json | 5 +++- unittest/rebootLogic/CoreController.cpp | 4 ++-- unittest/rebootLogic/CoreController.h | 10 ++++---- unittest/rebootLogic/main.cpp | 27 ++++++++++++++++++++++ 7 files changed, 53 insertions(+), 21 deletions(-) diff --git a/bsp_q7s/core/CoreController.cpp b/bsp_q7s/core/CoreController.cpp index d9022b57..535d12ed 100644 --- a/bsp_q7s/core/CoreController.cpp +++ b/bsp_q7s/core/CoreController.cpp @@ -1198,8 +1198,8 @@ void CoreController::performRebootFileHandling(bool recreateFile) { 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; + 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; @@ -1512,12 +1512,12 @@ void CoreController::resetRebootCount(xsc::Chip tgtChip, xsc::Copy tgtCopy) { } void CoreController::performMountedSdCardOperations() { - if(doPerformMountedSdCardOps) { + if (doPerformMountedSdCardOps) { bool sdCardMounted = false; sdCardMounted = sdcMan->isSdCardMounted(sdInfo.pref); - if(sdCardMounted) { + if (sdCardMounted) { std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + "/" + CONF_FOLDER; - if(not std::filesystem::exists(path)) { + if (not std::filesystem::exists(path)) { std::filesystem::create_directory(path); } initVersionFile(); diff --git a/bsp_q7s/core/CoreController.h b/bsp_q7s/core/CoreController.h index 6a8bb8cd..29b7676b 100644 --- a/bsp_q7s/core/CoreController.h +++ b/bsp_q7s/core/CoreController.h @@ -25,11 +25,11 @@ struct RebootFile { 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; + uint32_t img00Cnt = 0; + uint32_t img01Cnt = 0; + uint32_t img10Cnt = 0; + uint32_t img11Cnt = 0; + uint32_t relevantBootCnt = 0; bool bootFlag = false; xsc::Chip lastChip = xsc::Chip::CHIP_0; xsc::Copy lastCopy = xsc::Copy::COPY_0; @@ -46,8 +46,10 @@ class CoreController : public ExtendedControllerBase { static constexpr char CONF_FOLDER[] = "conf"; static constexpr char VERSION_FILE_NAME[] = "version.txt"; static constexpr char REBOOT_FILE_NAME[] = "reboot.txt"; - const std::string VERSION_FILE = "/" + std::string(CONF_FOLDER) + "/" + std::string(VERSION_FILE_NAME); - const std::string REBOOT_FILE = "/" + std::string(CONF_FOLDER) + "/" + std::string(REBOOT_FILE_NAME); + const std::string VERSION_FILE = + "/" + std::string(CONF_FOLDER) + "/" + std::string(VERSION_FILE_NAME); + const std::string REBOOT_FILE = + "/" + std::string(CONF_FOLDER) + "/" + std::string(REBOOT_FILE_NAME); static constexpr ActionId_t LIST_DIRECTORY_INTO_FILE = 0; static constexpr ActionId_t SWITCH_REBOOT_FILE_HANDLING = 5; diff --git a/bsp_q7s/core/InitMission.cpp b/bsp_q7s/core/InitMission.cpp index 76807438..b265ce33 100644 --- a/bsp_q7s/core/InitMission.cpp +++ b/bsp_q7s/core/InitMission.cpp @@ -266,7 +266,7 @@ void initmission::createPstTasks(TaskFactory& factory, sif::error << "InitMission::initTasks: GomSpace PST initialization failed!" << std::endl; } taskVec.push_back(gomSpacePstTask); -#else /* BOARD_TE7020 == 0 */ +#else /* BOARD_TE7020 == 0 */ FixedTimeslotTaskIF* pollingSequenceTaskTE0720 = factory.createFixedTimeslotTask( "PST_TASK_TE0720", 30, PeriodicTaskIF::MINIMUM_STACK_SIZE * 8, 3.0, missedDeadlineFunc); result = pst::pollingSequenceTE0720(pollingSequenceTaskTE0720); diff --git a/unittest/rebootLogic/.vscode/settings.json b/unittest/rebootLogic/.vscode/settings.json index ff30c446..8fcc89db 100644 --- a/unittest/rebootLogic/.vscode/settings.json +++ b/unittest/rebootLogic/.vscode/settings.json @@ -1,3 +1,6 @@ { - "editor.tabSize": 2 + "editor.tabSize": 2, + "files.associations": { + "iosfwd": "cpp" + } } \ No newline at end of file diff --git a/unittest/rebootLogic/CoreController.cpp b/unittest/rebootLogic/CoreController.cpp index d9269c06..34133ccf 100644 --- a/unittest/rebootLogic/CoreController.cpp +++ b/unittest/rebootLogic/CoreController.cpp @@ -362,7 +362,7 @@ void CoreController::rewriteRebootFile(RebootFile file) { 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"; + << "\nbootflag: " << file.bootFlag << "\nlast: " << static_cast(file.lastChip) << " " + << static_cast(file.lastCopy) << "\n"; } } diff --git a/unittest/rebootLogic/CoreController.h b/unittest/rebootLogic/CoreController.h index f3fec0e2..209db0da 100644 --- a/unittest/rebootLogic/CoreController.h +++ b/unittest/rebootLogic/CoreController.h @@ -19,11 +19,11 @@ struct RebootFile { 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; + uint32_t img00Cnt = 0; + uint32_t img01Cnt = 0; + uint32_t img10Cnt = 0; + uint32_t img11Cnt = 0; + uint32_t relevantBootCnt = 0; bool bootFlag = false; xsc::Chip lastChip = xsc::Chip::CHIP_0; xsc::Copy lastCopy = xsc::Copy::COPY_0; diff --git a/unittest/rebootLogic/main.cpp b/unittest/rebootLogic/main.cpp index 1a7748c9..8686c0b3 100644 --- a/unittest/rebootLogic/main.cpp +++ b/unittest/rebootLogic/main.cpp @@ -1,8 +1,35 @@ #include "CoreController.h" #include #include +#include +#include + +static constexpr bool CAT_FILE_TO_CONSOLE = true; +const std::string CONF_PATH = "/tmp/conf"; +const std::string REBOOT_FILE = CONF_PATH + "/reboot.txt"; + +void catFileToConsole(); TEST_CASE( "Core Controller Reboot File Handling", "[reboot-file]" ) { + + if(not std::filesystem::exists(CONF_PATH)) { + std::filesystem::create_directory(CONF_PATH); + } CoreController ctrl; + RebootFile rf; ctrl.performRebootFileHandling(true); + catFileToConsole(); + ctrl.parseRebootFile(REBOOT_FILE, rf); + REQUIRE(rf.enabled == 1); + REQUIRE(rf.enabled == 1); + std::filesystem::remove_all(CONF_PATH); } + +void catFileToConsole() { + if(CAT_FILE_TO_CONSOLE) { + std::ifstream file(REBOOT_FILE); + if (file.is_open()) { + std::cout << file.rdbuf(); + } + } +} \ No newline at end of file From 8e8fe3d0c964240551b28af0f0b91d6307a29b19 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 28 Feb 2022 16:48:13 +0100 Subject: [PATCH 11/25] some more fixes --- bsp_q7s/core/CoreController.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bsp_q7s/core/CoreController.cpp b/bsp_q7s/core/CoreController.cpp index 535d12ed..7acbd9ff 100644 --- a/bsp_q7s/core/CoreController.cpp +++ b/bsp_q7s/core/CoreController.cpp @@ -1535,7 +1535,7 @@ void CoreController::rewriteRebootFile(RebootFile file) { 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"; + << "\nbootflag: " << file.bootFlag << "\nlast: " << static_cast(file.lastChip) + << " " << static_cast(file.lastCopy) << "\n"; } } From d4dcd8c03fa77587c03bada4d5ed85f565fadf5f Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 28 Feb 2022 16:55:49 +0100 Subject: [PATCH 12/25] added missing command --- bsp_q7s/core/CoreController.cpp | 11 +++++ unittest/rebootLogic/CoreController.cpp | 59 +++++++++++++++++++++++++ unittest/rebootLogic/CoreController.h | 12 +++++ unittest/rebootLogic/HasActionsIF.h | 9 ++++ unittest/rebootLogic/definitions.h | 5 +++ 5 files changed, 96 insertions(+) create mode 100644 unittest/rebootLogic/HasActionsIF.h create mode 100644 unittest/rebootLogic/definitions.h diff --git a/bsp_q7s/core/CoreController.cpp b/bsp_q7s/core/CoreController.cpp index 7acbd9ff..189fed8e 100644 --- a/bsp_q7s/core/CoreController.cpp +++ b/bsp_q7s/core/CoreController.cpp @@ -151,6 +151,17 @@ ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_ resetRebootCount(xsc::CHIP_1, xsc::COPY_1); return HasActionsIF::EXECUTION_FINISHED; } + case(SET_MAX_REBOOT_CNT): { + if(size < 1) { + return HasActionsIF::INVALID_PARAMETERS; + } + std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE; + // Disable the reboot file mechanism + parseRebootFile(path, rebootFile); + rebootFile.maxCount = data[0]; + rewriteRebootFile(rebootFile); + return HasActionsIF::EXECUTION_FINISHED; + } case (REBOOT_OBC): { return actionPerformReboot(data, size); } diff --git a/unittest/rebootLogic/CoreController.cpp b/unittest/rebootLogic/CoreController.cpp index 34133ccf..a4949601 100644 --- a/unittest/rebootLogic/CoreController.cpp +++ b/unittest/rebootLogic/CoreController.cpp @@ -1,4 +1,5 @@ #include "conf.h" +#include "HasActionsIF.h" #include "CoreController.h" #include "SdCardManager.h" #include "event.h" @@ -366,3 +367,61 @@ void CoreController::rewriteRebootFile(RebootFile file) { << static_cast(file.lastCopy) << "\n"; } } + +ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, + const uint8_t *data, size_t size) { +switch (actionId) { + 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(SET_MAX_REBOOT_CNT): { + if(size < 1) { + return HasActionsIF::INVALID_PARAMETERS; + } + std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE; + // Disable the reboot file mechanism + parseRebootFile(path, rebootFile); + rebootFile.maxCount = data[0]; + rewriteRebootFile(rebootFile); + return HasActionsIF::EXECUTION_FINISHED; + } + default: { + return HasActionsIF::INVALID_ACTION_ID; + } + } +} \ No newline at end of file diff --git a/unittest/rebootLogic/CoreController.h b/unittest/rebootLogic/CoreController.h index 209db0da..0fa4e0c7 100644 --- a/unittest/rebootLogic/CoreController.h +++ b/unittest/rebootLogic/CoreController.h @@ -1,5 +1,6 @@ #pragma once +#include "definitions.h" #include "SdCardManager.h" #include @@ -38,7 +39,18 @@ public: static xsc::Chip CURRENT_CHIP; static xsc::Copy CURRENT_COPY; + 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; + CoreController(); + + ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, + const uint8_t* data, size_t size); void performRebootFileHandling(bool recreateFile); void determineAndExecuteReboot(RebootFile& rf, bool& needsReboot, xsc::Chip& tgtChip, xsc::Copy& tgtCopy); diff --git a/unittest/rebootLogic/HasActionsIF.h b/unittest/rebootLogic/HasActionsIF.h new file mode 100644 index 00000000..773ad54f --- /dev/null +++ b/unittest/rebootLogic/HasActionsIF.h @@ -0,0 +1,9 @@ +#include "definitions.h" + +class HasActionsIF { +public: + static const ReturnValue_t IS_BUSY = 1; + static const ReturnValue_t INVALID_PARAMETERS = 2; + static const ReturnValue_t EXECUTION_FINISHED = 3; + static const ReturnValue_t INVALID_ACTION_ID = 4; +}; diff --git a/unittest/rebootLogic/definitions.h b/unittest/rebootLogic/definitions.h new file mode 100644 index 00000000..377d2e23 --- /dev/null +++ b/unittest/rebootLogic/definitions.h @@ -0,0 +1,5 @@ +#include + +using ActionId_t = uint32_t; +using MessageQueueId_t = uint32_t; +using ReturnValue_t = uint16_t; From 0d1ff8585c3890489774fd8e71d901c4af42b484 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 28 Feb 2022 19:52:43 +0100 Subject: [PATCH 13/25] various bugfixes from unittest --- bsp_q7s/core/CoreController.cpp | 73 ++++++++-------- bsp_q7s/core/CoreController.h | 6 +- unittest/rebootLogic/.vscode/settings.json | 47 ++++++++++- unittest/rebootLogic/CoreController.cpp | 72 ++++++++-------- unittest/rebootLogic/CoreController.h | 12 ++- unittest/rebootLogic/definitions.h | 1 + unittest/rebootLogic/event.cpp | 19 ++++- unittest/rebootLogic/event.h | 37 ++++++++- unittest/rebootLogic/libxiphos.cpp | 20 ++++- unittest/rebootLogic/libxiphos.h | 8 ++ unittest/rebootLogic/main.cpp | 96 ++++++++++++++++++++-- 11 files changed, 299 insertions(+), 92 deletions(-) diff --git a/bsp_q7s/core/CoreController.cpp b/bsp_q7s/core/CoreController.cpp index 189fed8e..03ec86ee 100644 --- a/bsp_q7s/core/CoreController.cpp +++ b/bsp_q7s/core/CoreController.cpp @@ -151,8 +151,8 @@ ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_ resetRebootCount(xsc::CHIP_1, xsc::COPY_1); return HasActionsIF::EXECUTION_FINISHED; } - case(SET_MAX_REBOOT_CNT): { - if(size < 1) { + case (SET_MAX_REBOOT_CNT): { + if (size < 1) { return HasActionsIF::INVALID_PARAMETERS; } std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE; @@ -1189,7 +1189,7 @@ void CoreController::performRebootFileHandling(bool recreateFile) { std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE; if (not std::filesystem::exists(path) or recreateFile) { #if OBSW_VERBOSE_LEVEL >= 1 - sif::info << "CoreController::performRebootFileHandling: Recreating reboot file" << std::endl; + std::cout << "CoreController::performRebootFileHandling: Recreating reboot file" << std::endl; #endif rebootFile.enabled = true; rebootFile.img00Cnt = 0; @@ -1206,16 +1206,6 @@ void CoreController::performRebootFileHandling(bool recreateFile) { } } - 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) { @@ -1253,22 +1243,34 @@ void CoreController::performRebootFileHandling(bool recreateFile) { break; } } - if (CURRENT_CHIP == xsc::CHIP_0 and CURRENT_COPY == xsc::COPY_0) { + + 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; } - if (rebootFile.relevantBootCnt > rebootFile.maxCount) { + + if (*rebootFile.relevantBootCnt >= rebootFile.maxCount) { // Reboot to other image bool doReboot = false; - determineAndExecuteReboot(rebootFile, doReboot, rebootFile.lastChip, rebootFile.lastCopy); + xsc::Chip tgtChip = xsc::NO_CHIP; + xsc::Copy tgtCopy = xsc::NO_COPY; + determineAndExecuteReboot(rebootFile, doReboot, tgtChip, tgtCopy); 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; + std::cout << "Boot counter for image " << CURRENT_CHIP << " " << CURRENT_COPY + << " too high. Rebooting to " << tgtChip << " " << tgtCopy << std::endl; #endif + rebootFile.lastChip = CURRENT_CHIP; + rebootFile.lastCopy = CURRENT_COPY; rewriteRebootFile(rebootFile); - xsc_boot_copy(static_cast(rebootFile.lastChip), - static_cast(rebootFile.lastCopy)); + xsc_boot_copy(static_cast(tgtChip), + static_cast(tgtCopy)); } } else { rewriteRebootFile(rebootFile); @@ -1280,14 +1282,14 @@ void CoreController::determineAndExecuteReboot(RebootFile &rf, bool &needsReboot tgtChip = xsc::CHIP_0; tgtCopy = xsc::COPY_0; needsReboot = false; - if ((CURRENT_COPY == xsc::COPY_0) and (CURRENT_CHIP == xsc::CHIP_0) and + if ((CURRENT_CHIP == xsc::CHIP_0) and (CURRENT_COPY == xsc::COPY_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; + std::cout << "All reboot counts too high, but already on fallback image" << std::endl; return; } else { tgtChip = xsc::CHIP_1; @@ -1301,7 +1303,7 @@ void CoreController::determineAndExecuteReboot(RebootFile &rf, bool &needsReboot tgtCopy = xsc::COPY_1; } } - if ((CURRENT_COPY == xsc::COPY_0) and (CURRENT_CHIP == xsc::CHIP_1) and + if ((CURRENT_CHIP == xsc::CHIP_0) and (CURRENT_COPY == xsc::COPY_1) and (rf.img01Cnt >= rf.maxCount)) { needsReboot = true; if (rf.img00Cnt >= rf.maxCount) { @@ -1320,7 +1322,7 @@ void CoreController::determineAndExecuteReboot(RebootFile &rf, bool &needsReboot // Reboot on fallback image } } - if ((CURRENT_COPY == xsc::COPY_1) and (CURRENT_CHIP == xsc::CHIP_0) and + if ((CURRENT_CHIP == xsc::CHIP_1) and (CURRENT_COPY == xsc::COPY_0) and (rf.img10Cnt >= rf.maxCount)) { needsReboot = true; if (rf.img11Cnt >= rf.maxCount) { @@ -1340,7 +1342,7 @@ void CoreController::determineAndExecuteReboot(RebootFile &rf, bool &needsReboot tgtCopy = xsc::COPY_1; } } - if ((CURRENT_COPY == xsc::COPY_1) and (CURRENT_CHIP == xsc::CHIP_1) and + if ((CURRENT_CHIP == xsc::CHIP_1) and (CURRENT_COPY == xsc::COPY_1) and (rf.img11Cnt >= rf.maxCount)) { needsReboot = true; if (rf.img10Cnt >= rf.maxCount) { @@ -1409,7 +1411,7 @@ bool CoreController::parseRebootFile(std::string path, RebootFile &rf) { } iss >> rf.img00Cnt; if (word.find(selfMatch) != string::npos) { - rf.relevantBootCnt = rf.img00Cnt; + rf.relevantBootCnt = &rf.img00Cnt; } break; } @@ -1420,7 +1422,7 @@ bool CoreController::parseRebootFile(std::string path, RebootFile &rf) { } iss >> rf.img01Cnt; if (word.find(selfMatch) != string::npos) { - rf.relevantBootCnt = rf.img01Cnt; + rf.relevantBootCnt = &rf.img01Cnt; } break; } @@ -1431,7 +1433,7 @@ bool CoreController::parseRebootFile(std::string path, RebootFile &rf) { } iss >> rf.img10Cnt; if (word.find(selfMatch) != string::npos) { - rf.relevantBootCnt = rf.img10Cnt; + rf.relevantBootCnt = &rf.img10Cnt; } break; } @@ -1442,7 +1444,7 @@ bool CoreController::parseRebootFile(std::string path, RebootFile &rf) { } iss >> rf.img11Cnt; if (word.find(selfMatch) != string::npos) { - rf.relevantBootCnt = rf.img11Cnt; + rf.relevantBootCnt = &rf.img11Cnt; } break; } @@ -1456,15 +1458,8 @@ bool CoreController::parseRebootFile(std::string path, RebootFile &rf) { } 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; + int copyRaw = 0; + int chipRaw = 0; if (word.find("last:") == string::npos) { return false; } diff --git a/bsp_q7s/core/CoreController.h b/bsp_q7s/core/CoreController.h index 29b7676b..0d034c0b 100644 --- a/bsp_q7s/core/CoreController.h +++ b/bsp_q7s/core/CoreController.h @@ -15,8 +15,8 @@ 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 }; +enum Chip : int { CHIP_0, CHIP_1, NO_CHIP, SELF_CHIP, ALL_CHIP }; +enum Copy : int { COPY_0, COPY_1, NO_COPY, SELF_COPY, ALL_COPY }; } // namespace xsc @@ -29,7 +29,7 @@ struct RebootFile { uint32_t img01Cnt = 0; uint32_t img10Cnt = 0; uint32_t img11Cnt = 0; - uint32_t relevantBootCnt = 0; + uint32_t* relevantBootCnt = &img00Cnt; bool bootFlag = false; xsc::Chip lastChip = xsc::Chip::CHIP_0; xsc::Copy lastCopy = xsc::Copy::COPY_0; diff --git a/unittest/rebootLogic/.vscode/settings.json b/unittest/rebootLogic/.vscode/settings.json index 8fcc89db..688dbbf6 100644 --- a/unittest/rebootLogic/.vscode/settings.json +++ b/unittest/rebootLogic/.vscode/settings.json @@ -1,6 +1,51 @@ { "editor.tabSize": 2, "files.associations": { - "iosfwd": "cpp" + "iosfwd": "cpp", + "array": "cpp", + "*.tcc": "cpp", + "cctype": "cpp", + "chrono": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "codecvt": "cpp", + "compare": "cpp", + "concepts": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "exception": "cpp", + "fstream": "cpp", + "functional": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "new": "cpp", + "numbers": "cpp", + "optional": "cpp", + "ostream": "cpp", + "ratio": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "string": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "type_traits": "cpp", + "tuple": "cpp", + "typeinfo": "cpp", + "utility": "cpp", + "variant": "cpp", + "filesystem": "cpp", + "queue": "cpp" } } \ No newline at end of file diff --git a/unittest/rebootLogic/CoreController.cpp b/unittest/rebootLogic/CoreController.cpp index a4949601..fd479fd6 100644 --- a/unittest/rebootLogic/CoreController.cpp +++ b/unittest/rebootLogic/CoreController.cpp @@ -14,6 +14,7 @@ xsc::Copy CoreController::CURRENT_COPY = xsc::Copy::NO_COPY; CoreController::CoreController() { sdcMan = new SdCardManager(); + setCurrentBootCopy(xsc::CHIP_0, xsc::COPY_0); } void CoreController::performRebootFileHandling(bool recreateFile) { @@ -38,16 +39,6 @@ void CoreController::performRebootFileHandling(bool recreateFile) { } } - 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) { @@ -85,22 +76,35 @@ void CoreController::performRebootFileHandling(bool recreateFile) { break; } } - if (CURRENT_CHIP == xsc::CHIP_0 and CURRENT_COPY == xsc::COPY_0) { + + 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; } - if (rebootFile.relevantBootCnt > rebootFile.maxCount) { + + if (*rebootFile.relevantBootCnt >= rebootFile.maxCount) { // Reboot to other image bool doReboot = false; - determineAndExecuteReboot(rebootFile, doReboot, rebootFile.lastChip, rebootFile.lastCopy); + xsc::Chip tgtChip = xsc::NO_CHIP; + xsc::Copy tgtCopy = xsc::NO_COPY; + determineAndExecuteReboot(rebootFile, doReboot, tgtChip, tgtCopy); if (doReboot) { rebootFile.bootFlag = true; #if OBSW_VERBOSE_LEVEL >= 1 std::cout << "Boot counter for image " << CURRENT_CHIP << " " << CURRENT_COPY - << "too high. Rebooting to " << rebootFile.lastChip << " " << rebootFile.lastCopy + << " too high. Rebooting to " << tgtChip << " " << tgtCopy << std::endl; #endif + rebootFile.lastChip = CURRENT_CHIP; + rebootFile.lastCopy = CURRENT_COPY; rewriteRebootFile(rebootFile); - xsc_boot_copy(static_cast(rebootFile.lastChip), - static_cast(rebootFile.lastCopy)); + xsc_boot_copy(static_cast(tgtChip), + static_cast(tgtCopy)); } } else { rewriteRebootFile(rebootFile); @@ -113,7 +117,7 @@ void CoreController::determineAndExecuteReboot(RebootFile &rf, bool &needsReboot tgtChip = xsc::CHIP_0; tgtCopy = xsc::COPY_0; needsReboot = false; - if ((CURRENT_COPY == xsc::COPY_0) and (CURRENT_CHIP == xsc::CHIP_0) and + if ((CURRENT_CHIP == xsc::CHIP_0) and (CURRENT_COPY == xsc::COPY_0) and (rf.img00Cnt >= rf.maxCount)) { needsReboot = true; if (rf.img01Cnt >= rf.maxCount) { @@ -134,7 +138,7 @@ void CoreController::determineAndExecuteReboot(RebootFile &rf, bool &needsReboot tgtCopy = xsc::COPY_1; } } - if ((CURRENT_COPY == xsc::COPY_0) and (CURRENT_CHIP == xsc::CHIP_1) and + if ((CURRENT_CHIP == xsc::CHIP_0) and (CURRENT_COPY == xsc::COPY_1) and (rf.img01Cnt >= rf.maxCount)) { needsReboot = true; if (rf.img00Cnt >= rf.maxCount) { @@ -153,7 +157,7 @@ void CoreController::determineAndExecuteReboot(RebootFile &rf, bool &needsReboot // Reboot on fallback image } } - if ((CURRENT_COPY == xsc::COPY_1) and (CURRENT_CHIP == xsc::CHIP_0) and + if ((CURRENT_CHIP == xsc::CHIP_1) and (CURRENT_COPY == xsc::COPY_0) and (rf.img10Cnt >= rf.maxCount)) { needsReboot = true; if (rf.img11Cnt >= rf.maxCount) { @@ -173,7 +177,7 @@ void CoreController::determineAndExecuteReboot(RebootFile &rf, bool &needsReboot tgtCopy = xsc::COPY_1; } } - if ((CURRENT_COPY == xsc::COPY_1) and (CURRENT_CHIP == xsc::CHIP_1) and + if ((CURRENT_CHIP == xsc::CHIP_1) and (CURRENT_COPY == xsc::COPY_1) and (rf.img11Cnt >= rf.maxCount)) { needsReboot = true; if (rf.img10Cnt >= rf.maxCount) { @@ -242,7 +246,7 @@ bool CoreController::parseRebootFile(std::string path, RebootFile &rf) { } iss >> rf.img00Cnt; if (word.find(selfMatch) != string::npos) { - rf.relevantBootCnt = rf.img00Cnt; + rf.relevantBootCnt = &rf.img00Cnt; } break; } @@ -253,7 +257,7 @@ bool CoreController::parseRebootFile(std::string path, RebootFile &rf) { } iss >> rf.img01Cnt; if (word.find(selfMatch) != string::npos) { - rf.relevantBootCnt = rf.img01Cnt; + rf.relevantBootCnt = &rf.img01Cnt; } break; } @@ -264,7 +268,7 @@ bool CoreController::parseRebootFile(std::string path, RebootFile &rf) { } iss >> rf.img10Cnt; if (word.find(selfMatch) != string::npos) { - rf.relevantBootCnt = rf.img10Cnt; + rf.relevantBootCnt = &rf.img10Cnt; } break; } @@ -275,7 +279,7 @@ bool CoreController::parseRebootFile(std::string path, RebootFile &rf) { } iss >> rf.img11Cnt; if (word.find(selfMatch) != string::npos) { - rf.relevantBootCnt = rf.img11Cnt; + rf.relevantBootCnt = &rf.img11Cnt; } break; } @@ -289,15 +293,8 @@ bool CoreController::parseRebootFile(std::string path, RebootFile &rf) { } 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; + int copyRaw = 0; + int chipRaw = 0; if (word.find("last:") == string::npos) { return false; } @@ -363,8 +360,8 @@ void CoreController::rewriteRebootFile(RebootFile file) { rebootFile << "on: " << file.enabled << "\nmaxcnt: " << file.maxCount << "\nimg00: " << file.img00Cnt << "\nimg01: " << file.img01Cnt << "\nimg10: " << file.img10Cnt << "\nimg11: " << file.img11Cnt - << "\nbootflag: " << file.bootFlag << "\nlast: " << static_cast(file.lastChip) << " " - << static_cast(file.lastCopy) << "\n"; + << "\nbootflag: " << file.bootFlag << "\nlast: " << static_cast(file.lastChip) + << " " << static_cast(file.lastCopy) << "\n"; } } @@ -424,4 +421,9 @@ switch (actionId) { return HasActionsIF::INVALID_ACTION_ID; } } +} + +void CoreController::setCurrentBootCopy(xsc::Chip chip, xsc::Copy copy) { + CURRENT_CHIP = chip; + CURRENT_COPY = copy; } \ No newline at end of file diff --git a/unittest/rebootLogic/CoreController.h b/unittest/rebootLogic/CoreController.h index 0fa4e0c7..d7d20433 100644 --- a/unittest/rebootLogic/CoreController.h +++ b/unittest/rebootLogic/CoreController.h @@ -9,8 +9,8 @@ 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 }; +enum Chip : int { CHIP_0, CHIP_1, NO_CHIP, SELF_CHIP, ALL_CHIP }; +enum Copy : int { COPY_0, COPY_1, NO_COPY, SELF_COPY, ALL_COPY }; } // namespace xsc @@ -24,7 +24,7 @@ struct RebootFile { uint32_t img01Cnt = 0; uint32_t img10Cnt = 0; uint32_t img11Cnt = 0; - uint32_t relevantBootCnt = 0; + uint32_t* relevantBootCnt = &img00Cnt; bool bootFlag = false; xsc::Chip lastChip = xsc::Chip::CHIP_0; xsc::Copy lastCopy = xsc::Copy::COPY_0; @@ -35,7 +35,10 @@ class SdCardManager; class CoreController { public: static constexpr char REBOOT_FILE[] = "/conf/reboot.txt"; - static constexpr uint32_t REBOOT_MECHANISM_TRIGGERED = 1; + //! [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 = 1; static xsc::Chip CURRENT_CHIP; static xsc::Copy CURRENT_COPY; @@ -49,6 +52,7 @@ public: CoreController(); + static void setCurrentBootCopy(xsc::Chip chip, xsc::Copy copy); ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, const uint8_t* data, size_t size); void performRebootFileHandling(bool recreateFile); diff --git a/unittest/rebootLogic/definitions.h b/unittest/rebootLogic/definitions.h index 377d2e23..0a52474c 100644 --- a/unittest/rebootLogic/definitions.h +++ b/unittest/rebootLogic/definitions.h @@ -1,5 +1,6 @@ #include +using Event = uint32_t; using ActionId_t = uint32_t; using MessageQueueId_t = uint32_t; using ReturnValue_t = uint16_t; diff --git a/unittest/rebootLogic/event.cpp b/unittest/rebootLogic/event.cpp index 4d2d3302..e6f6d8f8 100644 --- a/unittest/rebootLogic/event.cpp +++ b/unittest/rebootLogic/event.cpp @@ -1,3 +1,20 @@ #include "event.h" +#include -void triggerEvent(uint32_t event, uint32_t p1, uint32_t p2) {} \ No newline at end of file +std::queue EVENT_QUEUE = {}; + +void triggerEvent(Event event, uint32_t p1, uint32_t p2) { + EventInfo info = {}; + info.event = event; + info.p1 = p1; + info.p2 = p2; + EVENT_QUEUE.push(info); +} + +void eventWasCalled(EventInfo& eventInfo, uint32_t& numEvents) { + numEvents = EVENT_QUEUE.size(); + if(not EVENT_QUEUE.empty()) { + eventInfo = std::move(EVENT_QUEUE.back()); + EVENT_QUEUE.pop(); + } +} \ No newline at end of file diff --git a/unittest/rebootLogic/event.h b/unittest/rebootLogic/event.h index c96b8bab..449836cd 100644 --- a/unittest/rebootLogic/event.h +++ b/unittest/rebootLogic/event.h @@ -1,5 +1,40 @@ #pragma once +#include "definitions.h" #include +#include -void triggerEvent(uint32_t event, uint32_t p1, uint32_t p2); \ No newline at end of file +struct EventInfo { + // That was just for testing, follow rule of 0 + /* + EventInfo () {} + + EventInfo (const EventInfo& other): event(other.event), p1(other.p1), p2(other.p2) { + std::cout << "Event info copy ctor called" << std::endl; + } + + EventInfo &operator= (const EventInfo& other) { + std::cout << "Event info assignment ctor called" << std::endl; + this->event = other.event; + this->p1 = other.p1; + this->p2 = other.p2; + return *this; + } + + EventInfo &operator= (EventInfo&& other) { + std::cout << "Event info move ctor called" << std::endl; + this->event = other.event; + this->p1 = other.p1; + this->p2 = other.p2; + return *this; + } + */ + + uint32_t event = 0; + uint32_t p1 = 0; + uint32_t p2 = 0; +}; + +void triggerEvent(Event event, uint32_t p1, uint32_t p2); + +void eventWasCalled(EventInfo& eventInfo, uint32_t& numEvents); diff --git a/unittest/rebootLogic/libxiphos.cpp b/unittest/rebootLogic/libxiphos.cpp index 110b0994..00bbbae9 100644 --- a/unittest/rebootLogic/libxiphos.cpp +++ b/unittest/rebootLogic/libxiphos.cpp @@ -1,5 +1,23 @@ #include "libxiphos.h" +#include "CoreController.h" + +bool rebootWasCalled = false; +xsc_libnor_chip_t lastChip; +xsc_libnor_copy_t lastCopy; + +bool getRebootWasCalled(xsc_libnor_chip_t& tgtChip, xsc_libnor_copy_t& tgtCopy) { + tgtChip = lastChip; + tgtCopy = lastCopy; + bool tmp = rebootWasCalled; + if(rebootWasCalled) { + rebootWasCalled = false; + } + return tmp; +} void xsc_boot_copy(xsc_libnor_chip_t boot_chip, xsc_libnor_copy_t boot_copy) { - + rebootWasCalled = true; + lastChip = boot_chip; + lastCopy = boot_copy; + CoreController::setCurrentBootCopy(static_cast(boot_chip), static_cast(boot_copy)); } \ No newline at end of file diff --git a/unittest/rebootLogic/libxiphos.h b/unittest/rebootLogic/libxiphos.h index a0f3f4d6..e6a40e45 100644 --- a/unittest/rebootLogic/libxiphos.h +++ b/unittest/rebootLogic/libxiphos.h @@ -14,4 +14,12 @@ typedef enum { XSC_LIBNOR_CHIP_TOTAL_NUMBER } xsc_libnor_chip_t; +/** + * @brief Used to verify whether reboot function was called + * + * @param tgtChip + * @param tgtCopy + */ +bool getRebootWasCalled(xsc_libnor_chip_t& tgtChip, xsc_libnor_copy_t& tgtCopy); + void xsc_boot_copy(xsc_libnor_chip_t boot_chip, xsc_libnor_copy_t boot_copy); \ No newline at end of file diff --git a/unittest/rebootLogic/main.cpp b/unittest/rebootLogic/main.cpp index 8686c0b3..515b9750 100644 --- a/unittest/rebootLogic/main.cpp +++ b/unittest/rebootLogic/main.cpp @@ -1,28 +1,110 @@ #include "CoreController.h" +#include "libxiphos.h" +#include "HasActionsIF.h" +#include "event.h" + #include #include #include #include -static constexpr bool CAT_FILE_TO_CONSOLE = true; +static constexpr bool CAT_FILE_TO_CONSOLE = false; const std::string CONF_PATH = "/tmp/conf"; const std::string REBOOT_FILE = CONF_PATH + "/reboot.txt"; void catFileToConsole(); TEST_CASE( "Core Controller Reboot File Handling", "[reboot-file]" ) { + if(not std::filesystem::exists(CONF_PATH)) { + std::filesystem::create_directory(CONF_PATH); + } + CoreController ctrl; - if(not std::filesystem::exists(CONF_PATH)) { - std::filesystem::create_directory(CONF_PATH); - } - CoreController ctrl; - RebootFile rf; + + SECTION ("Primary") { + xsc_libnor_chip_t chip; + xsc_libnor_copy_t copy; + RebootFile rf = {}; + ctrl.rewriteRebootFile(rf); + REQUIRE(rf.enabled == 0); + REQUIRE(rf.maxCount == RebootFile::DEFAULT_MAX_BOOT_CNT); + REQUIRE(rf.img00Cnt == 0); + REQUIRE(rf.img01Cnt == 0); + REQUIRE(rf.img10Cnt == 0); + REQUIRE(rf.img11Cnt == 0); + REQUIRE(rf.bootFlag == 0); + REQUIRE(rf.lastChip == 0); + REQUIRE(rf.lastCopy == 0); + // This recreates the file but should also increment the boot counter of the current image + REQUIRE(ctrl.CURRENT_CHIP == xsc::CHIP_0); + REQUIRE(ctrl.CURRENT_COPY == xsc::COPY_0); ctrl.performRebootFileHandling(true); catFileToConsole(); ctrl.parseRebootFile(REBOOT_FILE, rf); REQUIRE(rf.enabled == 1); + REQUIRE(rf.maxCount == RebootFile::DEFAULT_MAX_BOOT_CNT); + REQUIRE(rf.img00Cnt == 1); + REQUIRE(rf.img01Cnt == 0); + REQUIRE(rf.img10Cnt == 0); + REQUIRE(rf.img11Cnt == 0); + REQUIRE(rf.bootFlag == 0); + REQUIRE(rf.lastChip == 0); + REQUIRE(rf.lastCopy == 0); + uint8_t newRebootCnt = 3; + CHECK(ctrl.executeAction(CoreController::SET_MAX_REBOOT_CNT, 0, &newRebootCnt, 1) == HasActionsIF::EXECUTION_FINISHED); + ctrl.parseRebootFile(REBOOT_FILE, rf); REQUIRE(rf.enabled == 1); - std::filesystem::remove_all(CONF_PATH); + REQUIRE(rf.maxCount == 3); + REQUIRE(not getRebootWasCalled(chip, copy)); + ctrl.performRebootFileHandling(false); + ctrl.performRebootFileHandling(false); + ctrl.parseRebootFile(REBOOT_FILE, rf); + REQUIRE(rf.enabled == 1); + REQUIRE(rf.img00Cnt == 3); + REQUIRE(rf.img01Cnt == 0); + REQUIRE(rf.img10Cnt == 0); + REQUIRE(rf.img11Cnt == 0); + REQUIRE(rf.bootFlag == true); + REQUIRE(rf.lastChip == xsc::CHIP_0); + REQUIRE(rf.lastCopy == xsc::COPY_0); + REQUIRE(getRebootWasCalled(chip, copy)); + REQUIRE(chip == XSC_LIBNOR_CHIP_0); + REQUIRE(copy == XSC_LIBNOR_COPY_GOLD); + EventInfo info = {}; + uint32_t numEvents = 0; + ctrl.performRebootFileHandling(false); + eventWasCalled(info, numEvents); + CHECK(numEvents == 1); + CHECK(info.event == CoreController::REBOOT_MECHANISM_TRIGGERED); + CHECK(static_cast((info.p1 >> 16) & 0xFFFF) == xsc::CHIP_0); + CHECK(static_cast(info.p1 & 0xFFFF) == xsc::COPY_0); + CHECK(((info.p2 >> 24) & 0xFF) == 3); + CHECK(((info.p2 >> 16) & 0xFF) == 1); + CHECK(((info.p2 >> 8) & 0xFF) == 0); + CHECK((info.p2 & 0xFF) == 0); + ctrl.parseRebootFile(REBOOT_FILE, rf); + REQUIRE(rf.enabled == 1); + REQUIRE(rf.img00Cnt == 3); + REQUIRE(rf.img01Cnt == 1); + REQUIRE(rf.img10Cnt == 0); + REQUIRE(rf.img11Cnt == 0); + // Flag was cleared when event was thrown + REQUIRE(rf.bootFlag == false); + REQUIRE(rf.lastChip == xsc::CHIP_0); + REQUIRE(rf.lastCopy == xsc::COPY_0); + ctrl.performRebootFileHandling(false); + ctrl.performRebootFileHandling(false); + ctrl.parseRebootFile(REBOOT_FILE, rf); + REQUIRE(rf.enabled == 1); + REQUIRE(rf.img00Cnt == 3); + REQUIRE(rf.img01Cnt == 3); + REQUIRE(rf.img10Cnt == 0); + REQUIRE(rf.img11Cnt == 0); + } + if(std::filesystem::exists(CONF_PATH)) { + std::uintmax_t n = std::filesystem::remove_all(CONF_PATH); + CHECK(n == 2); + } } void catFileToConsole() { From 165e6e829ed3262205a4014e46be221f7a2aa29e Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 28 Feb 2022 20:24:40 +0100 Subject: [PATCH 14/25] bugfix by inspection --- bsp_q7s/core/CoreController.cpp | 8 +- unittest/rebootLogic/CoreController.cpp | 8 +- unittest/rebootLogic/main.cpp | 132 ++++++++++++++++++++++++ 3 files changed, 142 insertions(+), 6 deletions(-) diff --git a/bsp_q7s/core/CoreController.cpp b/bsp_q7s/core/CoreController.cpp index 03ec86ee..098124ac 100644 --- a/bsp_q7s/core/CoreController.cpp +++ b/bsp_q7s/core/CoreController.cpp @@ -1254,7 +1254,9 @@ void CoreController::performRebootFileHandling(bool recreateFile) { rebootFile.bootFlag = false; } - if (*rebootFile.relevantBootCnt >= rebootFile.maxCount) { + // Only reboot if the reboot functionality is enabled. + // The handler will still increment the boot counts + if (rebootFile.enabled and (*rebootFile.relevantBootCnt >= rebootFile.maxCount)) { // Reboot to other image bool doReboot = false; xsc::Chip tgtChip = xsc::NO_CHIP; @@ -1296,8 +1298,8 @@ void CoreController::determineAndExecuteReboot(RebootFile &rf, bool &needsReboot tgtCopy = xsc::COPY_1; } } else { - tgtChip = xsc::CHIP_0; - tgtCopy = xsc::COPY_1; + tgtChip = xsc::CHIP_1; + tgtCopy = xsc::COPY_0; } } else { tgtCopy = xsc::COPY_1; diff --git a/unittest/rebootLogic/CoreController.cpp b/unittest/rebootLogic/CoreController.cpp index fd479fd6..3a6b2e52 100644 --- a/unittest/rebootLogic/CoreController.cpp +++ b/unittest/rebootLogic/CoreController.cpp @@ -87,7 +87,9 @@ void CoreController::performRebootFileHandling(bool recreateFile) { rebootFile.bootFlag = false; } - if (*rebootFile.relevantBootCnt >= rebootFile.maxCount) { + // Only reboot if the reboot functionality is enabled. + // The handler will still increment the boot counts + if (rebootFile.enabled and (*rebootFile.relevantBootCnt >= rebootFile.maxCount)) { // Reboot to other image bool doReboot = false; xsc::Chip tgtChip = xsc::NO_CHIP; @@ -131,8 +133,8 @@ void CoreController::determineAndExecuteReboot(RebootFile &rf, bool &needsReboot tgtCopy = xsc::COPY_1; } } else { - tgtChip = xsc::CHIP_0; - tgtCopy = xsc::COPY_1; + tgtChip = xsc::CHIP_1; + tgtCopy = xsc::COPY_0; } } else { tgtCopy = xsc::COPY_1; diff --git a/unittest/rebootLogic/main.cpp b/unittest/rebootLogic/main.cpp index 515b9750..817bffe6 100644 --- a/unittest/rebootLogic/main.cpp +++ b/unittest/rebootLogic/main.cpp @@ -72,6 +72,8 @@ TEST_CASE( "Core Controller Reboot File Handling", "[reboot-file]" ) { REQUIRE(copy == XSC_LIBNOR_COPY_GOLD); EventInfo info = {}; uint32_t numEvents = 0; + + // We are now on image 0 1 and an event will be triggered ctrl.performRebootFileHandling(false); eventWasCalled(info, numEvents); CHECK(numEvents == 1); @@ -100,6 +102,136 @@ TEST_CASE( "Core Controller Reboot File Handling", "[reboot-file]" ) { REQUIRE(rf.img01Cnt == 3); REQUIRE(rf.img10Cnt == 0); REQUIRE(rf.img11Cnt == 0); + + // We are now on image 1 0 and an event will be triggered + ctrl.performRebootFileHandling(false); + eventWasCalled(info, numEvents); + CHECK(numEvents == 1); + CHECK(info.event == CoreController::REBOOT_MECHANISM_TRIGGERED); + CHECK(static_cast((info.p1 >> 16) & 0xFFFF) == xsc::CHIP_0); + CHECK(static_cast(info.p1 & 0xFFFF) == xsc::COPY_1); + CHECK(((info.p2 >> 24) & 0xFF) == 3); + CHECK(((info.p2 >> 16) & 0xFF) == 3); + CHECK(((info.p2 >> 8) & 0xFF) == 1); + CHECK((info.p2 & 0xFF) == 0); + ctrl.parseRebootFile(REBOOT_FILE, rf); + REQUIRE(rf.enabled == 1); + REQUIRE(rf.img00Cnt == 3); + REQUIRE(rf.img01Cnt == 3); + REQUIRE(rf.img10Cnt == 1); + REQUIRE(rf.img11Cnt == 0); + ctrl.performRebootFileHandling(false); + ctrl.performRebootFileHandling(false); + ctrl.parseRebootFile(REBOOT_FILE, rf); + REQUIRE(rf.enabled == 1); + REQUIRE(rf.img00Cnt == 3); + REQUIRE(rf.img01Cnt == 3); + REQUIRE(rf.img10Cnt == 3); + REQUIRE(rf.img11Cnt == 0); + eventWasCalled(info, numEvents); + + // On image 1 1 now + ctrl.performRebootFileHandling(false); + eventWasCalled(info, numEvents); + CHECK(numEvents == 1); + CHECK(info.event == CoreController::REBOOT_MECHANISM_TRIGGERED); + CHECK(static_cast((info.p1 >> 16) & 0xFFFF) == xsc::CHIP_1); + CHECK(static_cast(info.p1 & 0xFFFF) == xsc::COPY_0); + CHECK(((info.p2 >> 24) & 0xFF) == 3); + CHECK(((info.p2 >> 16) & 0xFF) == 3); + CHECK(((info.p2 >> 8) & 0xFF) == 3); + CHECK((info.p2 & 0xFF) == 1); + + ctrl.performRebootFileHandling(false); + ctrl.performRebootFileHandling(false); + // Now it should fall back to 0 0 because all are invalid + ctrl.parseRebootFile(REBOOT_FILE, rf); + REQUIRE(rf.enabled == 1); + REQUIRE(rf.img00Cnt == 3); + REQUIRE(rf.img01Cnt == 3); + REQUIRE(rf.img10Cnt == 3); + REQUIRE(rf.img11Cnt == 3); + + // Should remain on image now + ctrl.performRebootFileHandling(false); + eventWasCalled(info, numEvents); + CHECK(numEvents == 1); + CHECK(info.event == CoreController::REBOOT_MECHANISM_TRIGGERED); + CHECK(static_cast((info.p1 >> 16) & 0xFFFF) == xsc::CHIP_1); + CHECK(static_cast(info.p1 & 0xFFFF) == xsc::COPY_1); + CHECK(((info.p2 >> 24) & 0xFF) == 4); + CHECK(((info.p2 >> 16) & 0xFF) == 3); + CHECK(((info.p2 >> 8) & 0xFF) == 3); + CHECK((info.p2 & 0xFF) == 3); + ctrl.parseRebootFile(REBOOT_FILE, rf); + REQUIRE(rf.img00Cnt == 4); + REQUIRE(rf.img01Cnt == 3); + REQUIRE(rf.img10Cnt == 3); + REQUIRE(rf.img11Cnt == 3); + + // Reset a specific reboot counter + ctrl.executeAction(CoreController::RESET_REBOOT_COUNTER_01, 0, nullptr, 0); + // Reboot to 0 0 again + ctrl.performRebootFileHandling(false); + ctrl.parseRebootFile(REBOOT_FILE, rf); + REQUIRE(rf.enabled == 1); + REQUIRE(rf.img00Cnt == 5); + REQUIRE(rf.img01Cnt == 0); + REQUIRE(rf.img10Cnt == 3); + REQUIRE(rf.img11Cnt == 3); + CHECK(CoreController::CURRENT_CHIP == xsc::CHIP_0); + CHECK(CoreController::CURRENT_COPY == xsc::COPY_1); + ctrl.executeAction(CoreController::RESET_ALL_REBOOT_COUNTERS, 0, nullptr, 0); + ctrl.parseRebootFile(REBOOT_FILE, rf); + REQUIRE(rf.enabled == 1); + REQUIRE(rf.img00Cnt == 0); + REQUIRE(rf.img01Cnt == 0); + REQUIRE(rf.img10Cnt == 0); + REQUIRE(rf.img11Cnt == 0); + uint8_t enable = 0; + ctrl.executeAction(CoreController::SWITCH_REBOOT_FILE_HANDLING, 0, &enable, 1); + ctrl.parseRebootFile(REBOOT_FILE, rf); + REQUIRE(rf.enabled == 0); + REQUIRE(rf.img00Cnt == 0); + REQUIRE(rf.img01Cnt == 0); + REQUIRE(rf.img10Cnt == 0); + REQUIRE(rf.img11Cnt == 0); + + // Reboot to 1 0 explicitely + CoreController::setCurrentBootCopy(xsc::CHIP_1, xsc::COPY_0); + // Reboot three times and verify that no reboot is performed + ctrl.performRebootFileHandling(false); + ctrl.performRebootFileHandling(false); + ctrl.performRebootFileHandling(false); + ctrl.performRebootFileHandling(false); + ctrl.parseRebootFile(REBOOT_FILE, rf); + REQUIRE(rf.enabled == 0); + REQUIRE(rf.img00Cnt == 0); + REQUIRE(rf.img01Cnt == 0); + REQUIRE(rf.img10Cnt == 4); + REQUIRE(rf.img11Cnt == 0); + // Now enable the functionality again and verify it reboots to 1 1 + enable = 1; + ctrl.executeAction(CoreController::SWITCH_REBOOT_FILE_HANDLING, 0, &enable, 1); + ctrl.performRebootFileHandling(false); + ctrl.parseRebootFile(REBOOT_FILE, rf); + REQUIRE(rf.enabled == 1); + REQUIRE(rf.img00Cnt == 0); + REQUIRE(rf.img01Cnt == 0); + REQUIRE(rf.img10Cnt == 5); + REQUIRE(rf.img11Cnt == 0); + ctrl.performRebootFileHandling(false); + ctrl.parseRebootFile(REBOOT_FILE, rf); + REQUIRE(rf.enabled == 1); + REQUIRE(rf.img00Cnt == 0); + REQUIRE(rf.img01Cnt == 0); + REQUIRE(rf.img10Cnt == 5); + REQUIRE(rf.img11Cnt == 1); + ctrl.performRebootFileHandling(false); + ctrl.performRebootFileHandling(false); + // Should be on 0 0 now + CHECK(CoreController::CURRENT_CHIP == xsc::CHIP_0); + CHECK(CoreController::CURRENT_COPY == xsc::COPY_0); } if(std::filesystem::exists(CONF_PATH)) { std::uintmax_t n = std::filesystem::remove_all(CONF_PATH); From 1c17aac544b4abfa069be3b1225f87ea3ee14ad9 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 28 Feb 2022 20:27:24 +0100 Subject: [PATCH 15/25] added last unittests --- unittest/rebootLogic/main.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/unittest/rebootLogic/main.cpp b/unittest/rebootLogic/main.cpp index 817bffe6..9d6ef218 100644 --- a/unittest/rebootLogic/main.cpp +++ b/unittest/rebootLogic/main.cpp @@ -232,6 +232,24 @@ TEST_CASE( "Core Controller Reboot File Handling", "[reboot-file]" ) { // Should be on 0 0 now CHECK(CoreController::CURRENT_CHIP == xsc::CHIP_0); CHECK(CoreController::CURRENT_COPY == xsc::COPY_0); + ctrl.performRebootFileHandling(false); + ctrl.parseRebootFile(REBOOT_FILE, rf); + REQUIRE(rf.enabled == 1); + REQUIRE(rf.img00Cnt == 1); + REQUIRE(rf.img01Cnt == 0); + REQUIRE(rf.img10Cnt == 5); + REQUIRE(rf.img11Cnt == 3); + + // Now reset all reboot counters manually + ctrl.executeAction(CoreController::RESET_REBOOT_COUNTER_00, 0, nullptr, 0); + ctrl.executeAction(CoreController::RESET_REBOOT_COUNTER_10, 0, nullptr, 0); + ctrl.executeAction(CoreController::RESET_REBOOT_COUNTER_11, 0, nullptr, 0); + ctrl.parseRebootFile(REBOOT_FILE, rf); + REQUIRE(rf.enabled == 1); + REQUIRE(rf.img00Cnt == 0); + REQUIRE(rf.img01Cnt == 0); + REQUIRE(rf.img10Cnt == 0); + REQUIRE(rf.img11Cnt == 0); } if(std::filesystem::exists(CONF_PATH)) { std::uintmax_t n = std::filesystem::remove_all(CONF_PATH); From 65961695deccdff509e81a002276575d9d5066af Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 28 Feb 2022 20:35:05 +0100 Subject: [PATCH 16/25] small README --- unittest/rebootLogic/CMakeLists.txt | 13 +++---------- unittest/rebootLogic/README.md | 16 ++++++++++++++++ unittest/rebootLogic/src/CMakeLists.txt | 7 +++++++ .../rebootLogic/{ => src}/CoreController.cpp | 0 unittest/rebootLogic/{ => src}/CoreController.h | 0 unittest/rebootLogic/{ => src}/HasActionsIF.h | 0 unittest/rebootLogic/{ => src}/SdCardManager.cpp | 0 unittest/rebootLogic/{ => src}/SdCardManager.h | 0 unittest/rebootLogic/{ => src}/conf.h | 0 unittest/rebootLogic/{ => src}/definitions.h | 0 unittest/rebootLogic/{ => src}/event.cpp | 0 unittest/rebootLogic/{ => src}/event.h | 0 unittest/rebootLogic/{ => src}/libxiphos.cpp | 0 unittest/rebootLogic/{ => src}/libxiphos.h | 0 unittest/rebootLogic/{ => src}/main.cpp | 0 15 files changed, 26 insertions(+), 10 deletions(-) create mode 100644 unittest/rebootLogic/README.md create mode 100644 unittest/rebootLogic/src/CMakeLists.txt rename unittest/rebootLogic/{ => src}/CoreController.cpp (100%) rename unittest/rebootLogic/{ => src}/CoreController.h (100%) rename unittest/rebootLogic/{ => src}/HasActionsIF.h (100%) rename unittest/rebootLogic/{ => src}/SdCardManager.cpp (100%) rename unittest/rebootLogic/{ => src}/SdCardManager.h (100%) rename unittest/rebootLogic/{ => src}/conf.h (100%) rename unittest/rebootLogic/{ => src}/definitions.h (100%) rename unittest/rebootLogic/{ => src}/event.cpp (100%) rename unittest/rebootLogic/{ => src}/event.h (100%) rename unittest/rebootLogic/{ => src}/libxiphos.cpp (100%) rename unittest/rebootLogic/{ => src}/libxiphos.h (100%) rename unittest/rebootLogic/{ => src}/main.cpp (100%) diff --git a/unittest/rebootLogic/CMakeLists.txt b/unittest/rebootLogic/CMakeLists.txt index 9377d45e..dbaf2f28 100644 --- a/unittest/rebootLogic/CMakeLists.txt +++ b/unittest/rebootLogic/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.0) +cmake_minimum_required(VERSION 3.13.0) project(reboot-logic VERSION 0.1.0) include(CTest) @@ -19,16 +19,9 @@ endif() enable_testing() -add_executable(reboot-logic main.cpp) - -target_sources(reboot-logic PRIVATE - main.cpp - CoreController.cpp - SdCardManager.cpp - event.cpp - libxiphos.cpp -) +add_executable(reboot-logic) +add_subdirectory(src) target_link_libraries(reboot-logic PRIVATE Catch2::Catch2WithMain) target_include_directories(reboot-logic PRIVATE diff --git a/unittest/rebootLogic/README.md b/unittest/rebootLogic/README.md new file mode 100644 index 00000000..a51f0745 --- /dev/null +++ b/unittest/rebootLogic/README.md @@ -0,0 +1,16 @@ +Reboot Logic Unittest +======= + +These tests were written with Catch2 and VS code. +Install VS code with the C++ and CMake plugins and open this folder with VS code. +You should be able to run the tests directly. + +It is also recommended to [install Catch2](https://github.com/catchorg/Catch2/blob/devel/docs/cmake-integration.md): + +```sh +git clone https://github.com/catchorg/Catch2.git +cd Catch2 +git checkout v3.0.0-preview4 +cmake -Bbuild -H. -DBUILD_TESTING=OFF +sudo cmake --build build/ --target install +``` diff --git a/unittest/rebootLogic/src/CMakeLists.txt b/unittest/rebootLogic/src/CMakeLists.txt new file mode 100644 index 00000000..674c288a --- /dev/null +++ b/unittest/rebootLogic/src/CMakeLists.txt @@ -0,0 +1,7 @@ +target_sources(reboot-logic PRIVATE + main.cpp + CoreController.cpp + SdCardManager.cpp + event.cpp + libxiphos.cpp +) diff --git a/unittest/rebootLogic/CoreController.cpp b/unittest/rebootLogic/src/CoreController.cpp similarity index 100% rename from unittest/rebootLogic/CoreController.cpp rename to unittest/rebootLogic/src/CoreController.cpp diff --git a/unittest/rebootLogic/CoreController.h b/unittest/rebootLogic/src/CoreController.h similarity index 100% rename from unittest/rebootLogic/CoreController.h rename to unittest/rebootLogic/src/CoreController.h diff --git a/unittest/rebootLogic/HasActionsIF.h b/unittest/rebootLogic/src/HasActionsIF.h similarity index 100% rename from unittest/rebootLogic/HasActionsIF.h rename to unittest/rebootLogic/src/HasActionsIF.h diff --git a/unittest/rebootLogic/SdCardManager.cpp b/unittest/rebootLogic/src/SdCardManager.cpp similarity index 100% rename from unittest/rebootLogic/SdCardManager.cpp rename to unittest/rebootLogic/src/SdCardManager.cpp diff --git a/unittest/rebootLogic/SdCardManager.h b/unittest/rebootLogic/src/SdCardManager.h similarity index 100% rename from unittest/rebootLogic/SdCardManager.h rename to unittest/rebootLogic/src/SdCardManager.h diff --git a/unittest/rebootLogic/conf.h b/unittest/rebootLogic/src/conf.h similarity index 100% rename from unittest/rebootLogic/conf.h rename to unittest/rebootLogic/src/conf.h diff --git a/unittest/rebootLogic/definitions.h b/unittest/rebootLogic/src/definitions.h similarity index 100% rename from unittest/rebootLogic/definitions.h rename to unittest/rebootLogic/src/definitions.h diff --git a/unittest/rebootLogic/event.cpp b/unittest/rebootLogic/src/event.cpp similarity index 100% rename from unittest/rebootLogic/event.cpp rename to unittest/rebootLogic/src/event.cpp diff --git a/unittest/rebootLogic/event.h b/unittest/rebootLogic/src/event.h similarity index 100% rename from unittest/rebootLogic/event.h rename to unittest/rebootLogic/src/event.h diff --git a/unittest/rebootLogic/libxiphos.cpp b/unittest/rebootLogic/src/libxiphos.cpp similarity index 100% rename from unittest/rebootLogic/libxiphos.cpp rename to unittest/rebootLogic/src/libxiphos.cpp diff --git a/unittest/rebootLogic/libxiphos.h b/unittest/rebootLogic/src/libxiphos.h similarity index 100% rename from unittest/rebootLogic/libxiphos.h rename to unittest/rebootLogic/src/libxiphos.h diff --git a/unittest/rebootLogic/main.cpp b/unittest/rebootLogic/src/main.cpp similarity index 100% rename from unittest/rebootLogic/main.cpp rename to unittest/rebootLogic/src/main.cpp From daa3b0084ac00250d2089aa3671dbfa6a3846787 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 1 Mar 2022 11:57:48 +0100 Subject: [PATCH 17/25] extended reboot file handling --- fsfw | 2 +- unittest/rebootLogic/src/CoreController.cpp | 247 ++++++++++++-------- unittest/rebootLogic/src/CoreController.h | 6 + unittest/rebootLogic/src/main.cpp | 9 +- 4 files changed, 168 insertions(+), 96 deletions(-) diff --git a/fsfw b/fsfw index 6e0b9069..2d9216ba 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit 6e0b90696da2dfd2ec4749dfdb73950be2283c25 +Subproject commit 2d9216ba19f1931225daa5b6b6f244a48c09f1b9 diff --git a/unittest/rebootLogic/src/CoreController.cpp b/unittest/rebootLogic/src/CoreController.cpp index 3a6b2e52..a813cde7 100644 --- a/unittest/rebootLogic/src/CoreController.cpp +++ b/unittest/rebootLogic/src/CoreController.cpp @@ -31,6 +31,12 @@ void CoreController::performRebootFileHandling(bool recreateFile) { rebootFile.img11Cnt = 0; rebootFile.lastChip = xsc::Chip::CHIP_0; rebootFile.lastCopy = xsc::Copy::COPY_0; + rebootFile.img00Lock = false; + rebootFile.img01Lock = false; + rebootFile.img10Lock = false; + rebootFile.img11Lock = false; + rebootFile.mechanismNextChip = xsc::Chip::NO_CHIP; + rebootFile.mechanismNextCopy = xsc::Copy::NO_COPY; rebootFile.bootFlag = false; rewriteRebootFile(rebootFile); } else { @@ -39,41 +45,17 @@ void CoreController::performRebootFileHandling(bool recreateFile) { } } - 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; + if (CURRENT_CHIP == xsc::CHIP_0) { + if (CURRENT_COPY == xsc::COPY_0) { + rebootFile.img00Cnt++; + } else { + rebootFile.img01Cnt++; } - 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; + } else { + if (CURRENT_COPY == xsc::COPY_0) { + rebootFile.img10Cnt++; + } else { + rebootFile.img11Cnt++; } } @@ -87,6 +69,27 @@ void CoreController::performRebootFileHandling(bool recreateFile) { rebootFile.bootFlag = false; } + if(rebootFile.mechanismNextChip != xsc::NO_CHIP and rebootFile.mechanismNextCopy != xsc::NO_COPY) { + if(CURRENT_CHIP != rebootFile.mechanismNextChip or CURRENT_COPY != rebootFile.mechanismNextCopy) { + // Firmware or other component might be corrupt and we are on another image then the target + // image specified by the mechanism. We can't really trust the target image anymore. + // Lock it for now + if (rebootFile.mechanismNextChip == xsc::CHIP_0) { + if (rebootFile.mechanismNextCopy == xsc::COPY_0) { + rebootFile.img00Lock = true; + } else { + rebootFile.img01Lock = true; + } + } else { + if (rebootFile.mechanismNextCopy == xsc::COPY_0) { + rebootFile.img10Lock = true; + } else { + rebootFile.img11Lock = true; + } + } + } + } + // Only reboot if the reboot functionality is enabled. // The handler will still increment the boot counts if (rebootFile.enabled and (*rebootFile.relevantBootCnt >= rebootFile.maxCount)) { @@ -104,6 +107,8 @@ void CoreController::performRebootFileHandling(bool recreateFile) { #endif rebootFile.lastChip = CURRENT_CHIP; rebootFile.lastCopy = CURRENT_COPY; + rebootFile.mechanismNextChip = tgtChip; + rebootFile.mechanismNextCopy = tgtCopy; rewriteRebootFile(rebootFile); xsc_boot_copy(static_cast(tgtChip), static_cast(tgtCopy)); @@ -122,82 +127,82 @@ void CoreController::determineAndExecuteReboot(RebootFile &rf, bool &needsReboot if ((CURRENT_CHIP == xsc::CHIP_0) and (CURRENT_COPY == xsc::COPY_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 - std::cout << "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_1; - tgtCopy = xsc::COPY_0; - } - } else { + if (rf.img01Cnt < rf.maxCount and not rf.img01Lock) { tgtCopy = xsc::COPY_1; + return; + } + if (rf.img10Cnt < rf.maxCount and not rf.img10Lock) { + tgtChip = xsc::CHIP_1; + return; } + if (rf.img11Cnt < rf.maxCount and not rf.img11Lock) { + tgtChip = xsc::CHIP_1; + tgtCopy = xsc::COPY_1; + return; + } + // Can't really do much here. Stay on image + std::cout << "All reboot counts too high or all fallback images locked, already on fallback image" << std::endl; + needsReboot = false; + return; } if ((CURRENT_CHIP == xsc::CHIP_0) and (CURRENT_COPY == xsc::COPY_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 { + if (rf.img00Cnt < rf.maxCount and not rf.img00Lock) { // Reboot on fallback image + return; } + if (rf.img10Cnt < rf.maxCount and not rf.img10Lock) { + tgtChip = xsc::CHIP_1; + return; + } + if (rf.img11Cnt < rf.maxCount and not rf.img11Lock) { + tgtChip = xsc::CHIP_1; + tgtCopy = xsc::COPY_1; + } + if(rf.img00Lock) { + needsReboot = false; + } + // Reboot to fallback image } if ((CURRENT_CHIP == xsc::CHIP_1) and (CURRENT_COPY == xsc::COPY_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 { + if (rf.img11Cnt < rf.maxCount and not rf.img11Lock) { tgtChip = xsc::CHIP_1; tgtCopy = xsc::COPY_1; + return; } + if (rf.img00Cnt < rf.maxCount and not rf.img00Lock) { + return; + } + if (rf.img01Cnt < rf.maxCount and not rf.img01Lock) { + tgtCopy = xsc::COPY_1; + return; + } + if(rf.img00Lock) { + needsReboot = false; + } + // Reboot to fallback image } if ((CURRENT_CHIP == xsc::CHIP_1) and (CURRENT_COPY == xsc::COPY_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 { + if (rf.img10Cnt < rf.maxCount and not rf.img10Lock) { tgtChip = xsc::CHIP_1; - tgtCopy = xsc::COPY_0; + return; } + if (rf.img00Cnt < rf.maxCount and not rf.img00Lock) { + return; + } + if (rf.img01Cnt < rf.maxCount and not rf.img01Lock) { + tgtCopy = xsc::COPY_1; + return; + } + if(rf.img00Lock) { + needsReboot = false; + } + // Reboot to fallback image } } @@ -286,6 +291,38 @@ bool CoreController::parseRebootFile(std::string path, RebootFile &rf) { break; } case 6: { + iss >> word; + if (word.find("img00lock:") == string::npos) { + return false; + } + iss >> rf.img00Lock; + break; + } + case 7: { + iss >> word; + if (word.find("img01lock:") == string::npos) { + return false; + } + iss >> rf.img01Lock; + break; + } + case 8: { + iss >> word; + if (word.find("img10lock:") == string::npos) { + return false; + } + iss >> rf.img10Lock; + break; + } + case 9: { + iss >> word; + if (word.find("img11lock:") == string::npos) { + return false; + } + iss >> rf.img11Lock; + break; + } + case 10: { iss >> word; if (word.find("bootflag:") == string::npos) { return false; @@ -293,7 +330,7 @@ bool CoreController::parseRebootFile(std::string path, RebootFile &rf) { iss >> rf.bootFlag; break; } - case 7: { + case 11: { iss >> word; int copyRaw = 0; int chipRaw = 0; @@ -314,6 +351,30 @@ bool CoreController::parseRebootFile(std::string path, RebootFile &rf) { } rf.lastChip = static_cast(chipRaw); rf.lastCopy = static_cast(copyRaw); + break; + } + case 12: { + iss >> word; + int copyRaw = 0; + int chipRaw = 0; + if (word.find("next:") == string::npos) { + return false; + } + iss >> chipRaw; + if (iss.fail()) { + return false; + } + iss >> copyRaw; + if (iss.fail()) { + return false; + } + + if (chipRaw > 2 or copyRaw > 2) { + return false; + } + rf.mechanismNextChip = static_cast(chipRaw); + rf.mechanismNextCopy = static_cast(copyRaw); + break; } } if (iss.fail()) { @@ -362,8 +423,12 @@ void CoreController::rewriteRebootFile(RebootFile file) { rebootFile << "on: " << file.enabled << "\nmaxcnt: " << file.maxCount << "\nimg00: " << file.img00Cnt << "\nimg01: " << file.img01Cnt << "\nimg10: " << file.img10Cnt << "\nimg11: " << file.img11Cnt + << "\nimg00lock: " << file.img00Lock << "\nimg01lock: " << file.img01Lock + << "\nimg10lock: " << file.img01Lock << "\nimg11lock: " << file.img11Lock << "\nbootflag: " << file.bootFlag << "\nlast: " << static_cast(file.lastChip) - << " " << static_cast(file.lastCopy) << "\n"; + << " " << static_cast(file.lastCopy) << "\nnext: " + << static_cast(file.mechanismNextChip) << " " + << static_cast(file.mechanismNextCopy) << "\n"; } } diff --git a/unittest/rebootLogic/src/CoreController.h b/unittest/rebootLogic/src/CoreController.h index d7d20433..e5b56595 100644 --- a/unittest/rebootLogic/src/CoreController.h +++ b/unittest/rebootLogic/src/CoreController.h @@ -24,10 +24,16 @@ struct RebootFile { uint32_t img01Cnt = 0; uint32_t img10Cnt = 0; uint32_t img11Cnt = 0; + bool img00Lock = false; + bool img01Lock = false; + bool img10Lock = false; + bool img11Lock = false; uint32_t* relevantBootCnt = &img00Cnt; bool bootFlag = false; xsc::Chip lastChip = xsc::Chip::CHIP_0; xsc::Copy lastCopy = xsc::Copy::COPY_0; + xsc::Chip mechanismNextChip = xsc::Chip::NO_CHIP; + xsc::Copy mechanismNextCopy = xsc::Copy::NO_COPY; }; class SdCardManager; diff --git a/unittest/rebootLogic/src/main.cpp b/unittest/rebootLogic/src/main.cpp index 9d6ef218..fbd6cc03 100644 --- a/unittest/rebootLogic/src/main.cpp +++ b/unittest/rebootLogic/src/main.cpp @@ -48,8 +48,8 @@ TEST_CASE( "Core Controller Reboot File Handling", "[reboot-file]" ) { REQUIRE(rf.img10Cnt == 0); REQUIRE(rf.img11Cnt == 0); REQUIRE(rf.bootFlag == 0); - REQUIRE(rf.lastChip == 0); - REQUIRE(rf.lastCopy == 0); + REQUIRE(rf.lastChip == xsc::CHIP_0); + REQUIRE(rf.lastCopy == xsc::COPY_0); uint8_t newRebootCnt = 3; CHECK(ctrl.executeAction(CoreController::SET_MAX_REBOOT_CNT, 0, &newRebootCnt, 1) == HasActionsIF::EXECUTION_FINISHED); ctrl.parseRebootFile(REBOOT_FILE, rf); @@ -163,8 +163,9 @@ TEST_CASE( "Core Controller Reboot File Handling", "[reboot-file]" ) { CHECK(((info.p2 >> 16) & 0xFF) == 3); CHECK(((info.p2 >> 8) & 0xFF) == 3); CHECK((info.p2 & 0xFF) == 3); + // No reboot was triggered ctrl.parseRebootFile(REBOOT_FILE, rf); - REQUIRE(rf.img00Cnt == 4); + REQUIRE(rf.img00Cnt == 3); REQUIRE(rf.img01Cnt == 3); REQUIRE(rf.img10Cnt == 3); REQUIRE(rf.img11Cnt == 3); @@ -175,7 +176,7 @@ TEST_CASE( "Core Controller Reboot File Handling", "[reboot-file]" ) { ctrl.performRebootFileHandling(false); ctrl.parseRebootFile(REBOOT_FILE, rf); REQUIRE(rf.enabled == 1); - REQUIRE(rf.img00Cnt == 5); + REQUIRE(rf.img00Cnt == 4); REQUIRE(rf.img01Cnt == 0); REQUIRE(rf.img10Cnt == 3); REQUIRE(rf.img11Cnt == 3); From b279434ef0d33a3c7377febe87d449ba2f15c618 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 1 Mar 2022 13:05:34 +0100 Subject: [PATCH 18/25] update gitignore --- unittest/rebootLogic/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/unittest/rebootLogic/.gitignore b/unittest/rebootLogic/.gitignore index 796b96d1..37749976 100644 --- a/unittest/rebootLogic/.gitignore +++ b/unittest/rebootLogic/.gitignore @@ -1 +1,2 @@ /build +c_cpp_properties.json From 4a5ad4fb4dcd40a2b3f9eeef8aa6ef208349eb05 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 1 Mar 2022 13:34:12 +0100 Subject: [PATCH 19/25] updated OBSW code --- bsp_q7s/core/CoreController.cpp | 262 +++++++++++------- bsp_q7s/core/CoreController.h | 6 + unittest/rebootLogic/CMakeLists.txt | 4 - unittest/rebootLogic/src/CMakeLists.txt | 7 + unittest/rebootLogic/src/CoreController.cpp | 40 +-- unittest/rebootLogic/src/fsfw/CMakeLists.txt | 1 + unittest/rebootLogic/src/fsfw/FSFW.h | 9 + .../src/fsfw/serviceinterface/CMakeLists.txt | 4 + .../fsfw/serviceinterface/ServiceInterface.h | 13 + .../ServiceInterfaceBuffer.cpp | 252 +++++++++++++++++ .../serviceinterface/ServiceInterfaceBuffer.h | 159 +++++++++++ .../ServiceInterfaceStream.cpp | 21 ++ .../serviceinterface/ServiceInterfaceStream.h | 68 +++++ .../serviceInterfaceDefintions.h | 18 ++ unittest/rebootLogic/src/main.cpp | 6 + unittest/rebootLogic/src/print.c | 10 + 16 files changed, 766 insertions(+), 114 deletions(-) create mode 100644 unittest/rebootLogic/src/fsfw/CMakeLists.txt create mode 100644 unittest/rebootLogic/src/fsfw/FSFW.h create mode 100644 unittest/rebootLogic/src/fsfw/serviceinterface/CMakeLists.txt create mode 100644 unittest/rebootLogic/src/fsfw/serviceinterface/ServiceInterface.h create mode 100644 unittest/rebootLogic/src/fsfw/serviceinterface/ServiceInterfaceBuffer.cpp create mode 100644 unittest/rebootLogic/src/fsfw/serviceinterface/ServiceInterfaceBuffer.h create mode 100644 unittest/rebootLogic/src/fsfw/serviceinterface/ServiceInterfaceStream.cpp create mode 100644 unittest/rebootLogic/src/fsfw/serviceinterface/ServiceInterfaceStream.h create mode 100644 unittest/rebootLogic/src/fsfw/serviceinterface/serviceInterfaceDefintions.h create mode 100644 unittest/rebootLogic/src/print.c diff --git a/bsp_q7s/core/CoreController.cpp b/bsp_q7s/core/CoreController.cpp index 098124ac..554eb4d9 100644 --- a/bsp_q7s/core/CoreController.cpp +++ b/bsp_q7s/core/CoreController.cpp @@ -1189,7 +1189,7 @@ void CoreController::performRebootFileHandling(bool recreateFile) { std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE; if (not std::filesystem::exists(path) or recreateFile) { #if OBSW_VERBOSE_LEVEL >= 1 - std::cout << "CoreController::performRebootFileHandling: Recreating reboot file" << std::endl; + sif::info << "CoreController::performRebootFileHandling: Recreating reboot file" << std::endl; #endif rebootFile.enabled = true; rebootFile.img00Cnt = 0; @@ -1198,6 +1198,12 @@ void CoreController::performRebootFileHandling(bool recreateFile) { rebootFile.img11Cnt = 0; rebootFile.lastChip = xsc::Chip::CHIP_0; rebootFile.lastCopy = xsc::Copy::COPY_0; + rebootFile.img00Lock = false; + rebootFile.img01Lock = false; + rebootFile.img10Lock = false; + rebootFile.img11Lock = false; + rebootFile.mechanismNextChip = xsc::Chip::NO_CHIP; + rebootFile.mechanismNextCopy = xsc::Copy::NO_COPY; rebootFile.bootFlag = false; rewriteRebootFile(rebootFile); } else { @@ -1206,41 +1212,17 @@ void CoreController::performRebootFileHandling(bool recreateFile) { } } - 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; + if (CURRENT_CHIP == xsc::CHIP_0) { + if (CURRENT_COPY == xsc::COPY_0) { + rebootFile.img00Cnt++; + } else { + rebootFile.img01Cnt++; } - 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; + } else { + if (CURRENT_COPY == xsc::COPY_0) { + rebootFile.img10Cnt++; + } else { + rebootFile.img11Cnt++; } } @@ -1254,6 +1236,34 @@ void CoreController::performRebootFileHandling(bool recreateFile) { rebootFile.bootFlag = false; } + if (rebootFile.mechanismNextChip != xsc::NO_CHIP and + rebootFile.mechanismNextCopy != xsc::NO_COPY) { + if (CURRENT_CHIP != rebootFile.mechanismNextChip or + CURRENT_COPY != rebootFile.mechanismNextCopy) { + std::string infoString = static_cast(rebootFile.mechanismNextChip) + " " + + static_cast(rebootFile.mechanismNextCopy); + sif::warning << "CoreController::performRebootFileHandling: Expected to be on image" + << infoString << " but currently on other image. Locking" << infoString + << std::endl; + // Firmware or other component might be corrupt and we are on another image then the target + // image specified by the mechanism. We can't really trust the target image anymore. + // Lock it for now + if (rebootFile.mechanismNextChip == xsc::CHIP_0) { + if (rebootFile.mechanismNextCopy == xsc::COPY_0) { + rebootFile.img00Lock = true; + } else { + rebootFile.img01Lock = true; + } + } else { + if (rebootFile.mechanismNextCopy == xsc::COPY_0) { + rebootFile.img10Lock = true; + } else { + rebootFile.img11Lock = true; + } + } + } + } + // Only reboot if the reboot functionality is enabled. // The handler will still increment the boot counts if (rebootFile.enabled and (*rebootFile.relevantBootCnt >= rebootFile.maxCount)) { @@ -1265,11 +1275,13 @@ void CoreController::performRebootFileHandling(bool recreateFile) { if (doReboot) { rebootFile.bootFlag = true; #if OBSW_VERBOSE_LEVEL >= 1 - std::cout << "Boot counter for image " << CURRENT_CHIP << " " << CURRENT_COPY + sif::info << "Boot counter for image " << CURRENT_CHIP << " " << CURRENT_COPY << " too high. Rebooting to " << tgtChip << " " << tgtCopy << std::endl; #endif rebootFile.lastChip = CURRENT_CHIP; rebootFile.lastCopy = CURRENT_COPY; + rebootFile.mechanismNextChip = tgtChip; + rebootFile.mechanismNextCopy = tgtCopy; rewriteRebootFile(rebootFile); xsc_boot_copy(static_cast(tgtChip), static_cast(tgtCopy)); @@ -1287,82 +1299,84 @@ void CoreController::determineAndExecuteReboot(RebootFile &rf, bool &needsReboot if ((CURRENT_CHIP == xsc::CHIP_0) and (CURRENT_COPY == xsc::COPY_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 - std::cout << "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_1; - tgtCopy = xsc::COPY_0; - } - } else { + if (rf.img01Cnt < rf.maxCount and not rf.img01Lock) { tgtCopy = xsc::COPY_1; + return; } + if (rf.img10Cnt < rf.maxCount and not rf.img10Lock) { + tgtChip = xsc::CHIP_1; + return; + } + if (rf.img11Cnt < rf.maxCount and not rf.img11Lock) { + tgtChip = xsc::CHIP_1; + tgtCopy = xsc::COPY_1; + return; + } + // Can't really do much here. Stay on image + sif::warning + << "All reboot counts too high or all fallback images locked, already on fallback image" + << std::endl; + needsReboot = false; + return; } if ((CURRENT_CHIP == xsc::CHIP_0) and (CURRENT_COPY == xsc::COPY_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 { + if (rf.img00Cnt < rf.maxCount and not rf.img00Lock) { // Reboot on fallback image + return; } + if (rf.img10Cnt < rf.maxCount and not rf.img10Lock) { + tgtChip = xsc::CHIP_1; + return; + } + if (rf.img11Cnt < rf.maxCount and not rf.img11Lock) { + tgtChip = xsc::CHIP_1; + tgtCopy = xsc::COPY_1; + } + if (rf.img00Lock) { + needsReboot = false; + } + // Reboot to fallback image } if ((CURRENT_CHIP == xsc::CHIP_1) and (CURRENT_COPY == xsc::COPY_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 { + if (rf.img11Cnt < rf.maxCount and not rf.img11Lock) { tgtChip = xsc::CHIP_1; tgtCopy = xsc::COPY_1; + return; } + if (rf.img00Cnt < rf.maxCount and not rf.img00Lock) { + return; + } + if (rf.img01Cnt < rf.maxCount and not rf.img01Lock) { + tgtCopy = xsc::COPY_1; + return; + } + if (rf.img00Lock) { + needsReboot = false; + } + // Reboot to fallback image } if ((CURRENT_CHIP == xsc::CHIP_1) and (CURRENT_COPY == xsc::COPY_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 { + if (rf.img10Cnt < rf.maxCount and not rf.img10Lock) { tgtChip = xsc::CHIP_1; - tgtCopy = xsc::COPY_0; + return; } + if (rf.img00Cnt < rf.maxCount and not rf.img00Lock) { + return; + } + if (rf.img01Cnt < rf.maxCount and not rf.img01Lock) { + tgtCopy = xsc::COPY_1; + return; + } + if (rf.img00Lock) { + needsReboot = false; + } + // Reboot to fallback image } } @@ -1451,6 +1465,38 @@ bool CoreController::parseRebootFile(std::string path, RebootFile &rf) { break; } case 6: { + iss >> word; + if (word.find("img00lock:") == string::npos) { + return false; + } + iss >> rf.img00Lock; + break; + } + case 7: { + iss >> word; + if (word.find("img01lock:") == string::npos) { + return false; + } + iss >> rf.img01Lock; + break; + } + case 8: { + iss >> word; + if (word.find("img10lock:") == string::npos) { + return false; + } + iss >> rf.img10Lock; + break; + } + case 9: { + iss >> word; + if (word.find("img11lock:") == string::npos) { + return false; + } + iss >> rf.img11Lock; + break; + } + case 10: { iss >> word; if (word.find("bootflag:") == string::npos) { return false; @@ -1458,7 +1504,7 @@ bool CoreController::parseRebootFile(std::string path, RebootFile &rf) { iss >> rf.bootFlag; break; } - case 7: { + case 11: { iss >> word; int copyRaw = 0; int chipRaw = 0; @@ -1479,6 +1525,30 @@ bool CoreController::parseRebootFile(std::string path, RebootFile &rf) { } rf.lastChip = static_cast(chipRaw); rf.lastCopy = static_cast(copyRaw); + break; + } + case 12: { + iss >> word; + int copyRaw = 0; + int chipRaw = 0; + if (word.find("next:") == string::npos) { + return false; + } + iss >> chipRaw; + if (iss.fail()) { + return false; + } + iss >> copyRaw; + if (iss.fail()) { + return false; + } + + if (chipRaw > 2 or copyRaw > 2) { + return false; + } + rf.mechanismNextChip = static_cast(chipRaw); + rf.mechanismNextCopy = static_cast(copyRaw); + break; } } if (iss.fail()) { @@ -1486,7 +1556,7 @@ bool CoreController::parseRebootFile(std::string path, RebootFile &rf) { } lineIdx++; } - if (lineIdx < 8) { + if (lineIdx < 12) { return false; } return true; @@ -1543,7 +1613,11 @@ void CoreController::rewriteRebootFile(RebootFile file) { rebootFile << "on: " << file.enabled << "\nmaxcnt: " << file.maxCount << "\nimg00: " << file.img00Cnt << "\nimg01: " << file.img01Cnt << "\nimg10: " << file.img10Cnt << "\nimg11: " << file.img11Cnt + << "\nimg00lock: " << file.img00Lock << "\nimg01lock: " << file.img01Lock + << "\nimg10lock: " << file.img01Lock << "\nimg11lock: " << file.img11Lock << "\nbootflag: " << file.bootFlag << "\nlast: " << static_cast(file.lastChip) - << " " << static_cast(file.lastCopy) << "\n"; + << " " << static_cast(file.lastCopy) + << "\nnext: " << static_cast(file.mechanismNextChip) << " " + << static_cast(file.mechanismNextCopy) << "\n"; } } diff --git a/bsp_q7s/core/CoreController.h b/bsp_q7s/core/CoreController.h index 0d034c0b..f6835afa 100644 --- a/bsp_q7s/core/CoreController.h +++ b/bsp_q7s/core/CoreController.h @@ -29,10 +29,16 @@ struct RebootFile { uint32_t img01Cnt = 0; uint32_t img10Cnt = 0; uint32_t img11Cnt = 0; + bool img00Lock = false; + bool img01Lock = false; + bool img10Lock = false; + bool img11Lock = false; uint32_t* relevantBootCnt = &img00Cnt; bool bootFlag = false; xsc::Chip lastChip = xsc::Chip::CHIP_0; xsc::Copy lastCopy = xsc::Copy::COPY_0; + xsc::Chip mechanismNextChip = xsc::Chip::NO_CHIP; + xsc::Copy mechanismNextCopy = xsc::Copy::NO_COPY; }; class CoreController : public ExtendedControllerBase { diff --git a/unittest/rebootLogic/CMakeLists.txt b/unittest/rebootLogic/CMakeLists.txt index dbaf2f28..a070f299 100644 --- a/unittest/rebootLogic/CMakeLists.txt +++ b/unittest/rebootLogic/CMakeLists.txt @@ -24,10 +24,6 @@ add_executable(reboot-logic) add_subdirectory(src) target_link_libraries(reboot-logic PRIVATE Catch2::Catch2WithMain) -target_include_directories(reboot-logic PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR} -) - set(CPACK_PROJECT_NAME ${PROJECT_NAME}) set(CPACK_PROJECT_VERSION ${PROJECT_VERSION}) include(CPack) diff --git a/unittest/rebootLogic/src/CMakeLists.txt b/unittest/rebootLogic/src/CMakeLists.txt index 674c288a..97b73226 100644 --- a/unittest/rebootLogic/src/CMakeLists.txt +++ b/unittest/rebootLogic/src/CMakeLists.txt @@ -4,4 +4,11 @@ target_sources(reboot-logic PRIVATE SdCardManager.cpp event.cpp libxiphos.cpp + print.c ) + +target_include_directories(reboot-logic PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} +) + +add_subdirectory(fsfw) diff --git a/unittest/rebootLogic/src/CoreController.cpp b/unittest/rebootLogic/src/CoreController.cpp index a813cde7..b9ba84be 100644 --- a/unittest/rebootLogic/src/CoreController.cpp +++ b/unittest/rebootLogic/src/CoreController.cpp @@ -4,6 +4,7 @@ #include "SdCardManager.h" #include "event.h" #include "libxiphos.h" +#include "fsfw/serviceinterface/ServiceInterface.h" #include #include @@ -22,7 +23,7 @@ void CoreController::performRebootFileHandling(bool recreateFile) { std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE; if (not std::filesystem::exists(path) or recreateFile) { #if OBSW_VERBOSE_LEVEL >= 1 - std::cout << "CoreController::performRebootFileHandling: Recreating reboot file" << std::endl; + sif::info << "CoreController::performRebootFileHandling: Recreating reboot file" << std::endl; #endif rebootFile.enabled = true; rebootFile.img00Cnt = 0; @@ -62,15 +63,22 @@ void CoreController::performRebootFileHandling(bool recreateFile) { 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; + 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; } - if(rebootFile.mechanismNextChip != xsc::NO_CHIP and rebootFile.mechanismNextCopy != xsc::NO_COPY) { - if(CURRENT_CHIP != rebootFile.mechanismNextChip or CURRENT_COPY != rebootFile.mechanismNextCopy) { + if (rebootFile.mechanismNextChip != xsc::NO_CHIP and + rebootFile.mechanismNextCopy != xsc::NO_COPY) { + if (CURRENT_CHIP != rebootFile.mechanismNextChip or + CURRENT_COPY != rebootFile.mechanismNextCopy) { + std::string infoString = static_cast(rebootFile.mechanismNextChip) + " " + + static_cast(rebootFile.mechanismNextCopy); + sif::warning << "CoreController::performRebootFileHandling: Expected to be on image" + << infoString << " but currently on other image. Locking" << infoString + << std::endl; // Firmware or other component might be corrupt and we are on another image then the target // image specified by the mechanism. We can't really trust the target image anymore. // Lock it for now @@ -101,9 +109,8 @@ void CoreController::performRebootFileHandling(bool recreateFile) { if (doReboot) { rebootFile.bootFlag = true; #if OBSW_VERBOSE_LEVEL >= 1 - std::cout << "Boot counter for image " << CURRENT_CHIP << " " << CURRENT_COPY - << " too high. Rebooting to " << tgtChip << " " << tgtCopy - << std::endl; + sif::info << "Boot counter for image " << CURRENT_CHIP << " " << CURRENT_COPY + << " too high. Rebooting to " << tgtChip << " " << tgtCopy << std::endl; #endif rebootFile.lastChip = CURRENT_CHIP; rebootFile.lastCopy = CURRENT_COPY; @@ -118,7 +125,6 @@ void CoreController::performRebootFileHandling(bool recreateFile) { } } - void CoreController::determineAndExecuteReboot(RebootFile &rf, bool &needsReboot, xsc::Chip &tgtChip, xsc::Copy &tgtCopy) { tgtChip = xsc::CHIP_0; @@ -130,7 +136,7 @@ void CoreController::determineAndExecuteReboot(RebootFile &rf, bool &needsReboot if (rf.img01Cnt < rf.maxCount and not rf.img01Lock) { tgtCopy = xsc::COPY_1; return; - } + } if (rf.img10Cnt < rf.maxCount and not rf.img10Lock) { tgtChip = xsc::CHIP_1; return; @@ -141,7 +147,9 @@ void CoreController::determineAndExecuteReboot(RebootFile &rf, bool &needsReboot return; } // Can't really do much here. Stay on image - std::cout << "All reboot counts too high or all fallback images locked, already on fallback image" << std::endl; + sif::warning + << "All reboot counts too high or all fallback images locked, already on fallback image" + << std::endl; needsReboot = false; return; } @@ -160,12 +168,12 @@ void CoreController::determineAndExecuteReboot(RebootFile &rf, bool &needsReboot tgtChip = xsc::CHIP_1; tgtCopy = xsc::COPY_1; } - if(rf.img00Lock) { + if (rf.img00Lock) { needsReboot = false; } // Reboot to fallback image } - if ((CURRENT_CHIP == xsc::CHIP_1) and (CURRENT_COPY == xsc::COPY_0) and + if ((CURRENT_CHIP == xsc::CHIP_1) and (CURRENT_COPY == xsc::COPY_0) and (rf.img10Cnt >= rf.maxCount)) { needsReboot = true; if (rf.img11Cnt < rf.maxCount and not rf.img11Lock) { @@ -180,7 +188,7 @@ void CoreController::determineAndExecuteReboot(RebootFile &rf, bool &needsReboot tgtCopy = xsc::COPY_1; return; } - if(rf.img00Lock) { + if (rf.img00Lock) { needsReboot = false; } // Reboot to fallback image @@ -199,7 +207,7 @@ void CoreController::determineAndExecuteReboot(RebootFile &rf, bool &needsReboot tgtCopy = xsc::COPY_1; return; } - if(rf.img00Lock) { + if (rf.img00Lock) { needsReboot = false; } // Reboot to fallback image @@ -382,7 +390,7 @@ bool CoreController::parseRebootFile(std::string path, RebootFile &rf) { } lineIdx++; } - if (lineIdx < 8) { + if (lineIdx < 12) { return false; } return true; diff --git a/unittest/rebootLogic/src/fsfw/CMakeLists.txt b/unittest/rebootLogic/src/fsfw/CMakeLists.txt new file mode 100644 index 00000000..13b08d67 --- /dev/null +++ b/unittest/rebootLogic/src/fsfw/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(serviceinterface) diff --git a/unittest/rebootLogic/src/fsfw/FSFW.h b/unittest/rebootLogic/src/fsfw/FSFW.h new file mode 100644 index 00000000..06d1f9b5 --- /dev/null +++ b/unittest/rebootLogic/src/fsfw/FSFW.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +#define FSFW_CPP_OSTREAM_ENABLED 1 + +namespace fsfwconfig { +static constexpr size_t FSFW_PRINT_BUFFER_SIZE = 256; +} \ No newline at end of file diff --git a/unittest/rebootLogic/src/fsfw/serviceinterface/CMakeLists.txt b/unittest/rebootLogic/src/fsfw/serviceinterface/CMakeLists.txt new file mode 100644 index 00000000..7eded75e --- /dev/null +++ b/unittest/rebootLogic/src/fsfw/serviceinterface/CMakeLists.txt @@ -0,0 +1,4 @@ +target_sources(reboot-logic PRIVATE + ServiceInterfaceStream.cpp + ServiceInterfaceBuffer.cpp +) \ No newline at end of file diff --git a/unittest/rebootLogic/src/fsfw/serviceinterface/ServiceInterface.h b/unittest/rebootLogic/src/fsfw/serviceinterface/ServiceInterface.h new file mode 100644 index 00000000..9f05b96c --- /dev/null +++ b/unittest/rebootLogic/src/fsfw/serviceinterface/ServiceInterface.h @@ -0,0 +1,13 @@ +#ifndef FSFW_SERVICEINTERFACE_SERVICEINTERFACE_H_ +#define FSFW_SERVICEINTERFACE_SERVICEINTERFACE_H_ + +#include "fsfw/FSFW.h" +#include "serviceInterfaceDefintions.h" + +#if FSFW_CPP_OSTREAM_ENABLED == 1 +#include "ServiceInterfaceStream.h" +#else +#include "ServiceInterfacePrinter.h" +#endif + +#endif /* FSFW_SERVICEINTERFACE_SERVICEINTERFACE_H_ */ diff --git a/unittest/rebootLogic/src/fsfw/serviceinterface/ServiceInterfaceBuffer.cpp b/unittest/rebootLogic/src/fsfw/serviceinterface/ServiceInterfaceBuffer.cpp new file mode 100644 index 00000000..eb951e5c --- /dev/null +++ b/unittest/rebootLogic/src/fsfw/serviceinterface/ServiceInterfaceBuffer.cpp @@ -0,0 +1,252 @@ +#include "ServiceInterfaceBuffer.h" + +#if FSFW_CPP_OSTREAM_ENABLED == 1 + +#include + +#include + +#include "fsfw/serviceinterface/serviceInterfaceDefintions.h" + +#if defined(WIN32) && FSFW_COLORED_OUTPUT == 1 +#include "Windows.h" +#endif + +// to be implemented by bsp +extern "C" void printChar(const char*, bool errStream); + +#ifndef UT699 + +ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string setMessage, bool addCrToPreamble, + bool buffered, bool errStream, uint16_t port) + : isActive(true), + logMessage(setMessage), + addCrToPreamble(addCrToPreamble), + buffered(buffered), + errStream(errStream) { + if (buffered) { + // Set pointers if the stream is buffered. + setp(buf, buf + BUF_SIZE); + } + +#if FSFW_COLORED_OUTPUT == 1 + if (setMessage.find("DEBUG") != std::string::npos) { + colorPrefix = sif::ANSI_COLOR_CYAN; + } else if (setMessage.find("INFO") != std::string::npos) { + colorPrefix = sif::ANSI_COLOR_GREEN; + } else if (setMessage.find("WARNING") != std::string::npos) { + colorPrefix = sif::ANSI_COLOR_MAGENTA; + } else if (setMessage.find("ERROR") != std::string::npos) { + colorPrefix = sif::ANSI_COLOR_RED; + } else { + colorPrefix = sif::ANSI_COLOR_RESET; + } + +#ifdef WIN32 + HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); + DWORD dwMode = 0; + GetConsoleMode(hOut, &dwMode); + dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; + SetConsoleMode(hOut, dwMode); +#endif + +#endif + + preamble.reserve(MAX_PREAMBLE_SIZE); + preamble.resize(MAX_PREAMBLE_SIZE); +} + +void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) { + char array[BUF_SIZE]; + uint32_t length = end - begin; + if (length > sizeof(array)) { + length = sizeof(array); + } + memcpy(array, begin, length); + + for (; begin != end; begin++) { + if (errStream) { + printChar(begin, true); + } else { + printChar(begin, false); + } + } +} + +#endif + +int ServiceInterfaceBuffer::overflow(int c) { + if (not buffered and this->isActive) { + if (c != Traits::eof()) { + if (errStream) { + printChar(reinterpret_cast(&c), true); + } else { + printChar(reinterpret_cast(&c), false); + } + } + return 0; + } + // Handle output + putChars(pbase(), pptr()); + if (c != Traits::eof()) { + char c2 = c; + // Handle the one character that didn't fit to buffer + putChars(&c2, &c2 + 1); + } + // This tells that buffer is empty again + setp(buf, buf + BUF_SIZE - 1); + // I'm not sure about this return value! + return 0; +} + +int ServiceInterfaceBuffer::sync(void) { + if (not this->isActive and not buffered) { + if (not buffered) { + setp(buf, buf + BUF_SIZE - 1); + } + return 0; + } + if (not buffered) { + return 0; + } + + size_t preambleSize = 0; + std::string* preamble = getPreamble(&preambleSize); + // Write logMessage and time + this->putChars(preamble->data(), preamble->data() + preambleSize); + // Handle output + this->putChars(pbase(), pptr()); + // This tells that buffer is empty again + setp(buf, buf + BUF_SIZE - 1); + return 0; +} + +bool ServiceInterfaceBuffer::isBuffered() const { return buffered; } + +std::string* ServiceInterfaceBuffer::getPreamble(size_t* preambleSize) { + size_t currentSize = 0; + char* parsePosition = &preamble[0]; + if (addCrToPreamble) { + preamble[0] = '\r'; + currentSize += 1; + parsePosition += 1; + } + +#if FSFW_COLORED_OUTPUT == 1 + currentSize += sprintf(parsePosition, "%s", colorPrefix.c_str()); + parsePosition += colorPrefix.size(); +#endif + + int32_t charCount = + sprintf(parsePosition, "%s%s | ", this->logMessage.c_str(), sif::ANSI_COLOR_RESET); + if (charCount < 0) { + printf("ServiceInterfaceBuffer: Failure parsing preamble\r\n"); + return &preamble; + } + if (charCount > MAX_PREAMBLE_SIZE) { + printf( + "ServiceInterfaceBuffer: Char count too large for maximum " + "preamble size"); + return &preamble; + } + currentSize += charCount; + if (preambleSize != nullptr) { + *preambleSize = currentSize; + } + return &preamble; +} + +bool ServiceInterfaceBuffer::crAdditionEnabled() const { return addCrToPreamble; } + +#if FSFW_COLORED_OUTPUT == 1 +void ServiceInterfaceBuffer::setAsciiColorPrefix(std::string colorPrefix) { + this->colorPrefix = colorPrefix; +} +#endif + +#ifdef UT699 +#include "../osal/rtems/Interrupt.h" + +ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string set_message, uint16_t port) { + this->log_message = set_message; + this->isActive = true; + setp(buf, buf + BUF_SIZE); +} + +void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) { + char array[BUF_SIZE]; + uint32_t length = end - begin; + if (length > sizeof(array)) { + length = sizeof(array); + } + memcpy(array, begin, length); + + if (!Interrupt::isInterruptInProgress()) { + std::cout << array; + } else { + // Uncomment the following line if you need ISR debug output. + // printk(array); + } +} +#endif // UT699 + +#ifdef ML505 +#include +ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string set_message, uint16_t port) + : isActive(true), + log_message(set_message), + udpSocket(0), + remoteAddressLength(sizeof(remoteAddress)) { + setp(buf, buf + BUF_SIZE); + memset((uint8_t*)&remoteAddress, 0, sizeof(remoteAddress)); + remoteAddress.sin_family = AF_INET; + remoteAddress.sin_port = htons(port); + remoteAddress.sin_addr.s_addr = htonl(inet_addr("192.168.250.100")); +} + +void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) { + char array[BUF_SIZE]; + uint32_t length = end - begin; + if (length > sizeof(array)) { + length = sizeof(array); + } + memcpy(array, begin, length); + + if (udpSocket <= 0) { + initSocket(); + } + + if (udpSocket > 0) { + sendto(udpSocket, array, length, 0, (sockaddr*)&remoteAddress, sizeof(remoteAddress)); + } +} + +void ServiceInterfaceBuffer::initSocket() { + sockaddr_in address; + memset((uint8_t*)&address, 0, sizeof(address)); + address.sin_family = AF_INET; + address.sin_port = htons(0); + address.sin_addr.s_addr = htonl(INADDR_ANY); + + udpSocket = socket(PF_INET, SOCK_DGRAM, 0); + if (socket < 0) { + printf("Error opening socket!\n"); + return; + } + timeval timeout = {0, 20}; + if (setsockopt(udpSocket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) { + printf("Error setting SO_RCVTIMEO socket options!\n"); + return; + } + if (setsockopt(udpSocket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)) < 0) { + printf("Error setting SO_SNDTIMEO socket options!\n"); + return; + } + if (bind(udpSocket, (sockaddr*)&address, sizeof(address)) < 0) { + printf("Error binding socket!\n"); + } +} + +#endif // ML505 + +#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ diff --git a/unittest/rebootLogic/src/fsfw/serviceinterface/ServiceInterfaceBuffer.h b/unittest/rebootLogic/src/fsfw/serviceinterface/ServiceInterfaceBuffer.h new file mode 100644 index 00000000..5b720931 --- /dev/null +++ b/unittest/rebootLogic/src/fsfw/serviceinterface/ServiceInterfaceBuffer.h @@ -0,0 +1,159 @@ +#ifndef FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACEBUFFER_H_ +#define FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACEBUFFER_H_ + +#include "fsfw/FSFW.h" + +#if FSFW_CPP_OSTREAM_ENABLED == 1 + +#include +#include +#include + +#ifndef UT699 + +/** + * @brief This is the underlying stream buffer which implements the + * streambuf class and overloads the overflow() and sync() methods + * @details + * This class is used to modify the output of the stream, for example by adding. + * It also calls the char printing function which is implemented in the + * board supply package (BSP). + */ +class ServiceInterfaceBuffer : public std::streambuf { + friend class ServiceInterfaceStream; + + public: + static constexpr uint8_t MAX_PREAMBLE_SIZE = 40; + + ServiceInterfaceBuffer(std::string setMessage, bool addCrToPreamble, bool buffered, + bool errStream, uint16_t port); + + protected: + bool isActive; + //! This is called when buffer becomes full. If + //! buffer is not used, then this is called every + //! time when characters are put to stream. + int overflow(int c = Traits::eof()) override; + + //! This function is called when stream is flushed, + //! for example when std::endl is put to stream. + int sync(void) override; + + bool isBuffered() const; + + private: + //! For additional message information + std::string logMessage; + std::string preamble; + +#if FSFW_COLORED_OUTPUT == 1 + std::string colorPrefix; + void setAsciiColorPrefix(std::string colorPrefix); +#endif + + // For EOF detection + typedef std::char_traits Traits; + + //! This is useful for some terminal programs which do not have + //! implicit carriage return with newline characters. + bool addCrToPreamble; + + //! Specifies whether the stream operates in buffered or unbuffered mode. + bool buffered; + //! This specifies to print to stderr and work in unbuffered mode. + bool errStream; + + //! Needed for buffered mode. + static size_t const BUF_SIZE = fsfwconfig::FSFW_PRINT_BUFFER_SIZE; + char buf[BUF_SIZE]; + + //! In this function, the characters are parsed. + void putChars(char const* begin, char const* end); + + std::string* getPreamble(size_t* preambleSize = nullptr); + + bool crAdditionEnabled() const; +}; + +#endif + +#ifdef UT699 +class ServiceInterfaceBuffer : public std::basic_streambuf > { + friend class ServiceInterfaceStream; + + public: + ServiceInterfaceBuffer(std::string set_message, uint16_t port); + + protected: + bool isActive; + // This is called when buffer becomes full. If + // buffer is not used, then this is called every + // time when characters are put to stream. + virtual int overflow(int c = Traits::eof()); + + // This function is called when stream is flushed, + // for example when std::endl is put to stream. + virtual int sync(void); + + private: + // For additional message information + std::string log_message; + // For EOF detection + typedef std::char_traits Traits; + + // Work in buffer mode. It is also possible to work without buffer. + static size_t const BUF_SIZE = 128; + char buf[BUF_SIZE]; + + // In this function, the characters are parsed. + void putChars(char const* begin, char const* end); +}; +#endif // UT699 + +#ifdef ML505 +#include +#include +#include +#include +#include + +class ServiceInterfaceBuffer : public std::basic_streambuf > { + friend class ServiceInterfaceStream; + + public: + ServiceInterfaceBuffer(std::string set_message, uint16_t port); + + protected: + bool isActive; + // This is called when buffer becomes full. If + // buffer is not used, then this is called every + // time when characters are put to stream. + virtual int overflow(int c = Traits::eof()); + + // This function is called when stream is flushed, + // for example when std::endl is put to stream. + virtual int sync(void); + + private: + // For additional message information + std::string log_message; + // For EOF detection + typedef std::char_traits Traits; + + // Work in buffer mode. It is also possible to work without buffer. + static size_t const BUF_SIZE = 128; + char buf[BUF_SIZE]; + + // In this function, the characters are parsed. + void putChars(char const* begin, char const* end); + + int udpSocket; + sockaddr_in remoteAddress; + socklen_t remoteAddressLength; + void initSocket(); +}; +#endif // ML505 + +#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ + +#endif /* FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACEBUFFER_H_ */ diff --git a/unittest/rebootLogic/src/fsfw/serviceinterface/ServiceInterfaceStream.cpp b/unittest/rebootLogic/src/fsfw/serviceinterface/ServiceInterfaceStream.cpp new file mode 100644 index 00000000..3ef68c2a --- /dev/null +++ b/unittest/rebootLogic/src/fsfw/serviceinterface/ServiceInterfaceStream.cpp @@ -0,0 +1,21 @@ +#include "ServiceInterfaceStream.h" + +#if FSFW_CPP_OSTREAM_ENABLED == 1 + +ServiceInterfaceStream::ServiceInterfaceStream(std::string setMessage, bool addCrToPreamble, + bool buffered, bool errStream, uint16_t port) + : std::ostream(&streambuf), streambuf(setMessage, addCrToPreamble, buffered, errStream, port) {} + +void ServiceInterfaceStream::setActive(bool myActive) { this->streambuf.isActive = myActive; } + +std::string* ServiceInterfaceStream::getPreamble() { return streambuf.getPreamble(); } + +bool ServiceInterfaceStream::crAdditionEnabled() const { return streambuf.crAdditionEnabled(); } + +#if FSFW_COLORED_OUTPUT == 1 +void ServiceInterfaceStream::setAsciiColorPrefix(std::string asciiColorCode) { + streambuf.setAsciiColorPrefix(asciiColorCode); +} +#endif + +#endif diff --git a/unittest/rebootLogic/src/fsfw/serviceinterface/ServiceInterfaceStream.h b/unittest/rebootLogic/src/fsfw/serviceinterface/ServiceInterfaceStream.h new file mode 100644 index 00000000..bf3424a6 --- /dev/null +++ b/unittest/rebootLogic/src/fsfw/serviceinterface/ServiceInterfaceStream.h @@ -0,0 +1,68 @@ +#ifndef FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACESTREAM_H_ +#define FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACESTREAM_H_ + +#include "fsfw/FSFW.h" + +#include "ServiceInterfaceBuffer.h" + +#if FSFW_CPP_OSTREAM_ENABLED == 1 + +#include +#include + +/** + * Generic service interface stream which can be used like std::cout or + * std::cerr but has additional capability. Add preamble and timestamp + * to output. Can be run in buffered or unbuffered mode. + */ +class ServiceInterfaceStream : public std::ostream { + public: + /** + * This constructor is used by specifying the preamble message. + * Optionally, the output can be directed to stderr and a CR character + * can be prepended to the preamble. + * @param setMessage message of preamble. + * @param addCrToPreamble Useful for applications like Puttty. + * @param buffered specify whether to use buffered mode. + * @param errStream specify which output stream to use (stderr or stdout). + */ + ServiceInterfaceStream(std::string setMessage, bool addCrToPreamble = false, bool buffered = true, + bool errStream = false, uint16_t port = 1234); + + //! An inactive stream will not print anything. + void setActive(bool); + + /** + * This can be used to retrieve the preamble in case it should be printed in + * the unbuffered mode. + * @return Preamle consisting of log message and timestamp. + */ + std::string* getPreamble(); + + /** + * Can be used to determine if the stream was configured to add CR characters in addition + * to newline characters. + * @return + */ + bool crAdditionEnabled() const; + +#if FSFW_COLORED_OUTPUT == 1 + void setAsciiColorPrefix(std::string asciiColorCode); +#endif + + protected: + ServiceInterfaceBuffer streambuf; +}; + +// Forward declaration of interface streams. These should be instantiated in +// main. They can then be used like std::cout or std::cerr. +namespace sif { +extern ServiceInterfaceStream debug; +extern ServiceInterfaceStream info; +extern ServiceInterfaceStream warning; +extern ServiceInterfaceStream error; +} // namespace sif + +#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ + +#endif /* FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACESTREAM_H_ */ diff --git a/unittest/rebootLogic/src/fsfw/serviceinterface/serviceInterfaceDefintions.h b/unittest/rebootLogic/src/fsfw/serviceinterface/serviceInterfaceDefintions.h new file mode 100644 index 00000000..85710578 --- /dev/null +++ b/unittest/rebootLogic/src/fsfw/serviceinterface/serviceInterfaceDefintions.h @@ -0,0 +1,18 @@ +#ifndef FSFW_SERVICEINTERFACE_SERVICEINTERFACEDEFINTIONS_H_ +#define FSFW_SERVICEINTERFACE_SERVICEINTERFACEDEFINTIONS_H_ + +namespace sif { + +enum class OutputTypes { OUT_INFO, OUT_DEBUG, OUT_WARNING, OUT_ERROR }; + +static const char* const ANSI_COLOR_RED = "\x1b[31m"; +static const char* const ANSI_COLOR_GREEN = "\x1b[32m"; +static const char* const ANSI_COLOR_YELLOW = "\x1b[33m"; +static const char* const ANSI_COLOR_BLUE = "\x1b[34m"; +static const char* const ANSI_COLOR_MAGENTA = "\x1b[35m"; +static const char* const ANSI_COLOR_CYAN = "\x1b[36m"; +static const char* const ANSI_COLOR_RESET = "\x1b[0m"; + +} // namespace sif + +#endif /* FSFW_SERVICEINTERFACE_SERVICEINTERFACEDEFINTIONS_H_ */ diff --git a/unittest/rebootLogic/src/main.cpp b/unittest/rebootLogic/src/main.cpp index fbd6cc03..57470861 100644 --- a/unittest/rebootLogic/src/main.cpp +++ b/unittest/rebootLogic/src/main.cpp @@ -2,6 +2,7 @@ #include "libxiphos.h" #include "HasActionsIF.h" #include "event.h" +#include "fsfw/serviceinterface/ServiceInterface.h" #include #include @@ -14,6 +15,11 @@ const std::string REBOOT_FILE = CONF_PATH + "/reboot.txt"; void catFileToConsole(); +ServiceInterfaceStream sif::debug("DEBUG"); +ServiceInterfaceStream sif::info("INFO"); +ServiceInterfaceStream sif::warning("WARNING"); +ServiceInterfaceStream sif::error("ERROR", false, false, true); + TEST_CASE( "Core Controller Reboot File Handling", "[reboot-file]" ) { if(not std::filesystem::exists(CONF_PATH)) { std::filesystem::create_directory(CONF_PATH); diff --git a/unittest/rebootLogic/src/print.c b/unittest/rebootLogic/src/print.c new file mode 100644 index 00000000..a59492b0 --- /dev/null +++ b/unittest/rebootLogic/src/print.c @@ -0,0 +1,10 @@ +#include +#include + +void printChar(const char* character, bool errStream) { + if (errStream) { + putc(*character, stderr); + return; + } + putc(*character, stdout); +} From 684d9b805978eba2d26e24e5dadc8cff9e6f4120 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 1 Mar 2022 13:35:36 +0100 Subject: [PATCH 20/25] repoint fsfw --- fsfw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fsfw b/fsfw index 2d9216ba..6e0b9069 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit 2d9216ba19f1931225daa5b6b6f244a48c09f1b9 +Subproject commit 6e0b90696da2dfd2ec4749dfdb73950be2283c25 From e1112f190332fd2640a1f6e55b60465a1cf0ace3 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 1 Mar 2022 14:44:50 +0100 Subject: [PATCH 21/25] extension for additional safety --- bsp_q7s/core/CoreController.cpp | 104 ++++++++----- bsp_q7s/core/CoreController.h | 10 +- unittest/rebootLogic/src/CoreController.cpp | 76 ++++++---- unittest/rebootLogic/src/CoreController.h | 10 +- unittest/rebootLogic/src/main.cpp | 158 ++++++++++++++++++-- 5 files changed, 270 insertions(+), 88 deletions(-) diff --git a/bsp_q7s/core/CoreController.cpp b/bsp_q7s/core/CoreController.cpp index 554eb4d9..e1c6a430 100644 --- a/bsp_q7s/core/CoreController.cpp +++ b/bsp_q7s/core/CoreController.cpp @@ -131,24 +131,26 @@ ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_ } return HasActionsIF::EXECUTION_FINISHED; } - case (RESET_ALL_REBOOT_COUNTERS): { - resetRebootCount(xsc::ALL_CHIP, xsc::ALL_COPY); + case (RESET_REBOOT_COUNTERS): { + if (size == 0) { + resetRebootCount(xsc::ALL_CHIP, xsc::ALL_COPY); + } else if (size == 2) { + if (data[0] > 1 or data[1] > 1) { + return HasActionsIF::INVALID_PARAMETERS; + } + resetRebootCount(static_cast(data[0]), static_cast(data[1])); + } 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); + case (SWITCH_IMG_LOCK): { + if (size != 3) { + return HasActionsIF::INVALID_PARAMETERS; + } + if (data[1] > 1 or data[2] > 1) { + return HasActionsIF::INVALID_PARAMETERS; + } + setRebootMechanismLock(data[0], static_cast(data[1]), + static_cast(data[2])); return HasActionsIF::EXECUTION_FINISHED; } case (SET_MAX_REBOOT_CNT): { @@ -1184,6 +1186,22 @@ void CoreController::performWatchdogControlOperation() { } } +void CoreController::performMountedSdCardOperations() { + if (doPerformMountedSdCardOps) { + bool sdCardMounted = false; + sdCardMounted = sdcMan->isSdCardMounted(sdInfo.pref); + if (sdCardMounted) { + std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + "/" + CONF_FOLDER; + if (not std::filesystem::exists(path)) { + std::filesystem::create_directory(path); + } + initVersionFile(); + performRebootFileHandling(true); + doPerformMountedSdCardOps = false; + } + } +} + void CoreController::performRebootFileHandling(bool recreateFile) { using namespace std; std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE; @@ -1240,10 +1258,10 @@ void CoreController::performRebootFileHandling(bool recreateFile) { rebootFile.mechanismNextCopy != xsc::NO_COPY) { if (CURRENT_CHIP != rebootFile.mechanismNextChip or CURRENT_COPY != rebootFile.mechanismNextCopy) { - std::string infoString = static_cast(rebootFile.mechanismNextChip) + " " + - static_cast(rebootFile.mechanismNextCopy); - sif::warning << "CoreController::performRebootFileHandling: Expected to be on image" - << infoString << " but currently on other image. Locking" << infoString + std::string infoString = std::to_string(rebootFile.mechanismNextChip) + " " + + std::to_string(rebootFile.mechanismNextCopy); + sif::warning << "CoreController::performRebootFileHandling: Expected to be on image " + << infoString << " but currently on other image. Locking " << infoString << std::endl; // Firmware or other component might be corrupt and we are on another image then the target // image specified by the mechanism. We can't really trust the target image anymore. @@ -1264,6 +1282,8 @@ void CoreController::performRebootFileHandling(bool recreateFile) { } } + rebootFile.lastChip = CURRENT_CHIP; + rebootFile.lastCopy = CURRENT_COPY; // Only reboot if the reboot functionality is enabled. // The handler will still increment the boot counts if (rebootFile.enabled and (*rebootFile.relevantBootCnt >= rebootFile.maxCount)) { @@ -1278,8 +1298,6 @@ void CoreController::performRebootFileHandling(bool recreateFile) { sif::info << "Boot counter for image " << CURRENT_CHIP << " " << CURRENT_COPY << " too high. Rebooting to " << tgtChip << " " << tgtCopy << std::endl; #endif - rebootFile.lastChip = CURRENT_CHIP; - rebootFile.lastCopy = CURRENT_COPY; rebootFile.mechanismNextChip = tgtChip; rebootFile.mechanismNextCopy = tgtCopy; rewriteRebootFile(rebootFile); @@ -1287,8 +1305,10 @@ void CoreController::performRebootFileHandling(bool recreateFile) { static_cast(tgtCopy)); } } else { - rewriteRebootFile(rebootFile); + rebootFile.mechanismNextChip = xsc::NO_CHIP; + rebootFile.mechanismNextCopy = xsc::NO_COPY; } + rewriteRebootFile(rebootFile); } void CoreController::determineAndExecuteReboot(RebootFile &rf, bool &needsReboot, @@ -1589,22 +1609,6 @@ void CoreController::resetRebootCount(xsc::Chip tgtChip, xsc::Copy tgtCopy) { rewriteRebootFile(rebootFile); } -void CoreController::performMountedSdCardOperations() { - if (doPerformMountedSdCardOps) { - bool sdCardMounted = false; - sdCardMounted = sdcMan->isSdCardMounted(sdInfo.pref); - if (sdCardMounted) { - std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + "/" + CONF_FOLDER; - if (not std::filesystem::exists(path)) { - std::filesystem::create_directory(path); - } - initVersionFile(); - performRebootFileHandling(true); - doPerformMountedSdCardOps = false; - } - } -} - void CoreController::rewriteRebootFile(RebootFile file) { std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE; std::ofstream rebootFile(path); @@ -1614,10 +1618,30 @@ void CoreController::rewriteRebootFile(RebootFile file) { << "\nimg00: " << file.img00Cnt << "\nimg01: " << file.img01Cnt << "\nimg10: " << file.img10Cnt << "\nimg11: " << file.img11Cnt << "\nimg00lock: " << file.img00Lock << "\nimg01lock: " << file.img01Lock - << "\nimg10lock: " << file.img01Lock << "\nimg11lock: " << file.img11Lock + << "\nimg10lock: " << file.img10Lock << "\nimg11lock: " << file.img11Lock << "\nbootflag: " << file.bootFlag << "\nlast: " << static_cast(file.lastChip) << " " << static_cast(file.lastCopy) << "\nnext: " << static_cast(file.mechanismNextChip) << " " << static_cast(file.mechanismNextCopy) << "\n"; } } + +void CoreController::setRebootMechanismLock(bool lock, 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::CHIP_0) { + if (tgtCopy == xsc::COPY_0) { + rebootFile.img00Lock = lock; + } else { + rebootFile.img01Lock = lock; + } + } else { + if (tgtCopy == xsc::COPY_0) { + rebootFile.img10Lock = lock; + } else { + rebootFile.img11Lock = lock; + } + } + rewriteRebootFile(rebootFile); +} diff --git a/bsp_q7s/core/CoreController.h b/bsp_q7s/core/CoreController.h index f6835afa..37f5395d 100644 --- a/bsp_q7s/core/CoreController.h +++ b/bsp_q7s/core/CoreController.h @@ -59,12 +59,9 @@ class CoreController : public ExtendedControllerBase { 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 RESET_REBOOT_COUNTERS = 6; + static constexpr ActionId_t SWITCH_IMG_LOCK = 7; + static constexpr ActionId_t SET_MAX_REBOOT_CNT = 8; static constexpr ActionId_t REBOOT_OBC = 32; static constexpr ActionId_t MOUNT_OTHER_COPY = 33; @@ -220,6 +217,7 @@ class CoreController : public ExtendedControllerBase { void determineAndExecuteReboot(RebootFile& rf, bool& needsReboot, xsc::Chip& tgtChip, xsc::Copy& tgtCopy); void resetRebootCount(xsc::Chip tgtChip, xsc::Copy tgtCopy); + void setRebootMechanismLock(bool lock, xsc::Chip tgtChip, xsc::Copy tgtCopy); bool parseRebootFile(std::string path, RebootFile& file); void rewriteRebootFile(RebootFile file); }; diff --git a/unittest/rebootLogic/src/CoreController.cpp b/unittest/rebootLogic/src/CoreController.cpp index b9ba84be..c01d61f8 100644 --- a/unittest/rebootLogic/src/CoreController.cpp +++ b/unittest/rebootLogic/src/CoreController.cpp @@ -74,10 +74,10 @@ void CoreController::performRebootFileHandling(bool recreateFile) { rebootFile.mechanismNextCopy != xsc::NO_COPY) { if (CURRENT_CHIP != rebootFile.mechanismNextChip or CURRENT_COPY != rebootFile.mechanismNextCopy) { - std::string infoString = static_cast(rebootFile.mechanismNextChip) + " " + - static_cast(rebootFile.mechanismNextCopy); - sif::warning << "CoreController::performRebootFileHandling: Expected to be on image" - << infoString << " but currently on other image. Locking" << infoString + std::string infoString = std::to_string(rebootFile.mechanismNextChip) + " " + + std::to_string(rebootFile.mechanismNextCopy); + sif::warning << "CoreController::performRebootFileHandling: Expected to be on image " + << infoString << " but currently on other image. Locking " << infoString << std::endl; // Firmware or other component might be corrupt and we are on another image then the target // image specified by the mechanism. We can't really trust the target image anymore. @@ -98,6 +98,8 @@ void CoreController::performRebootFileHandling(bool recreateFile) { } } + rebootFile.lastChip = CURRENT_CHIP; + rebootFile.lastCopy = CURRENT_COPY; // Only reboot if the reboot functionality is enabled. // The handler will still increment the boot counts if (rebootFile.enabled and (*rebootFile.relevantBootCnt >= rebootFile.maxCount)) { @@ -112,8 +114,6 @@ void CoreController::performRebootFileHandling(bool recreateFile) { sif::info << "Boot counter for image " << CURRENT_CHIP << " " << CURRENT_COPY << " too high. Rebooting to " << tgtChip << " " << tgtCopy << std::endl; #endif - rebootFile.lastChip = CURRENT_CHIP; - rebootFile.lastCopy = CURRENT_COPY; rebootFile.mechanismNextChip = tgtChip; rebootFile.mechanismNextCopy = tgtCopy; rewriteRebootFile(rebootFile); @@ -121,8 +121,10 @@ void CoreController::performRebootFileHandling(bool recreateFile) { static_cast(tgtCopy)); } } else { - rewriteRebootFile(rebootFile); - } + rebootFile.mechanismNextChip = xsc::NO_CHIP; + rebootFile.mechanismNextCopy = xsc::NO_COPY; + } + rewriteRebootFile(rebootFile); } void CoreController::determineAndExecuteReboot(RebootFile &rf, bool &needsReboot, @@ -432,7 +434,7 @@ void CoreController::rewriteRebootFile(RebootFile file) { << "\nimg00: " << file.img00Cnt << "\nimg01: " << file.img01Cnt << "\nimg10: " << file.img10Cnt << "\nimg11: " << file.img11Cnt << "\nimg00lock: " << file.img00Lock << "\nimg01lock: " << file.img01Lock - << "\nimg10lock: " << file.img01Lock << "\nimg11lock: " << file.img11Lock + << "\nimg10lock: " << file.img10Lock << "\nimg11lock: " << file.img11Lock << "\nbootflag: " << file.bootFlag << "\nlast: " << static_cast(file.lastChip) << " " << static_cast(file.lastCopy) << "\nnext: " << static_cast(file.mechanismNextChip) << " " @@ -461,24 +463,26 @@ switch (actionId) { } return HasActionsIF::EXECUTION_FINISHED; } - case (RESET_ALL_REBOOT_COUNTERS): { - resetRebootCount(xsc::ALL_CHIP, xsc::ALL_COPY); + case (RESET_REBOOT_COUNTERS): { + if(size == 0) { + resetRebootCount(xsc::ALL_CHIP, xsc::ALL_COPY); + } else if (size == 2) { + if(data[0] > 1 or data[1] > 1) { + return HasActionsIF::INVALID_PARAMETERS; + } + resetRebootCount(static_cast(data[0]), static_cast(data[1])); + } 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); + case (SWITCH_IMG_LOCK): { + if(size != 3) { + return HasActionsIF::INVALID_PARAMETERS; + } + if(data[1] > 1 or data[2] > 1) { + return HasActionsIF::INVALID_PARAMETERS; + } + setRebootMechanismLock(data[0], static_cast(data[1]), + static_cast(data[2])); return HasActionsIF::EXECUTION_FINISHED; } case(SET_MAX_REBOOT_CNT): { @@ -498,7 +502,27 @@ switch (actionId) { } } +void CoreController::setRebootMechanismLock(bool lock, 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::CHIP_0) { + if (tgtCopy == xsc::COPY_0) { + rebootFile.img00Lock = lock; + } else { + rebootFile.img01Lock = lock; + } + } else { + if (tgtCopy == xsc::COPY_0) { + rebootFile.img10Lock = lock; + } else { + rebootFile.img11Lock = lock; + } + } + rewriteRebootFile(rebootFile); +} + void CoreController::setCurrentBootCopy(xsc::Chip chip, xsc::Copy copy) { CURRENT_CHIP = chip; CURRENT_COPY = copy; -} \ No newline at end of file +} diff --git a/unittest/rebootLogic/src/CoreController.h b/unittest/rebootLogic/src/CoreController.h index e5b56595..737d550d 100644 --- a/unittest/rebootLogic/src/CoreController.h +++ b/unittest/rebootLogic/src/CoreController.h @@ -49,12 +49,9 @@ public: static xsc::Copy CURRENT_COPY; 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 RESET_REBOOT_COUNTERS = 6; + static constexpr ActionId_t SWITCH_IMG_LOCK = 7; + static constexpr ActionId_t SET_MAX_REBOOT_CNT = 8; CoreController(); @@ -64,6 +61,7 @@ public: void performRebootFileHandling(bool recreateFile); void determineAndExecuteReboot(RebootFile& rf, bool& needsReboot, xsc::Chip& tgtChip, xsc::Copy& tgtCopy); + void setRebootMechanismLock(bool lock, 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); diff --git a/unittest/rebootLogic/src/main.cpp b/unittest/rebootLogic/src/main.cpp index 57470861..b24b4014 100644 --- a/unittest/rebootLogic/src/main.cpp +++ b/unittest/rebootLogic/src/main.cpp @@ -25,7 +25,7 @@ TEST_CASE( "Core Controller Reboot File Handling", "[reboot-file]" ) { std::filesystem::create_directory(CONF_PATH); } CoreController ctrl; - + std::array cmdData = {}; SECTION ("Primary") { xsc_libnor_chip_t chip; @@ -99,7 +99,7 @@ TEST_CASE( "Core Controller Reboot File Handling", "[reboot-file]" ) { // Flag was cleared when event was thrown REQUIRE(rf.bootFlag == false); REQUIRE(rf.lastChip == xsc::CHIP_0); - REQUIRE(rf.lastCopy == xsc::COPY_0); + REQUIRE(rf.lastCopy == xsc::COPY_1); ctrl.performRebootFileHandling(false); ctrl.performRebootFileHandling(false); ctrl.parseRebootFile(REBOOT_FILE, rf); @@ -169,26 +169,27 @@ TEST_CASE( "Core Controller Reboot File Handling", "[reboot-file]" ) { CHECK(((info.p2 >> 16) & 0xFF) == 3); CHECK(((info.p2 >> 8) & 0xFF) == 3); CHECK((info.p2 & 0xFF) == 3); - // No reboot was triggered ctrl.parseRebootFile(REBOOT_FILE, rf); - REQUIRE(rf.img00Cnt == 3); + REQUIRE(rf.img00Cnt == 4); REQUIRE(rf.img01Cnt == 3); REQUIRE(rf.img10Cnt == 3); REQUIRE(rf.img11Cnt == 3); // Reset a specific reboot counter - ctrl.executeAction(CoreController::RESET_REBOOT_COUNTER_01, 0, nullptr, 0); + cmdData[0] = 0; + cmdData[1] = 1; + ctrl.executeAction(CoreController::RESET_REBOOT_COUNTERS, 0, cmdData.data(), 2); // Reboot to 0 0 again ctrl.performRebootFileHandling(false); ctrl.parseRebootFile(REBOOT_FILE, rf); REQUIRE(rf.enabled == 1); - REQUIRE(rf.img00Cnt == 4); + REQUIRE(rf.img00Cnt == 5); REQUIRE(rf.img01Cnt == 0); REQUIRE(rf.img10Cnt == 3); REQUIRE(rf.img11Cnt == 3); CHECK(CoreController::CURRENT_CHIP == xsc::CHIP_0); CHECK(CoreController::CURRENT_COPY == xsc::COPY_1); - ctrl.executeAction(CoreController::RESET_ALL_REBOOT_COUNTERS, 0, nullptr, 0); + ctrl.executeAction(CoreController::RESET_REBOOT_COUNTERS, 0, nullptr, 0); ctrl.parseRebootFile(REBOOT_FILE, rf); REQUIRE(rf.enabled == 1); REQUIRE(rf.img00Cnt == 0); @@ -248,15 +249,152 @@ TEST_CASE( "Core Controller Reboot File Handling", "[reboot-file]" ) { REQUIRE(rf.img11Cnt == 3); // Now reset all reboot counters manually - ctrl.executeAction(CoreController::RESET_REBOOT_COUNTER_00, 0, nullptr, 0); - ctrl.executeAction(CoreController::RESET_REBOOT_COUNTER_10, 0, nullptr, 0); - ctrl.executeAction(CoreController::RESET_REBOOT_COUNTER_11, 0, nullptr, 0); + cmdData[0] = 0; + cmdData[1] = 0; + ctrl.executeAction(CoreController::RESET_REBOOT_COUNTERS, 0, cmdData.data(), 2); + cmdData[0] = 1; + cmdData[1] = 0; + ctrl.executeAction(CoreController::RESET_REBOOT_COUNTERS, 0, cmdData.data(), 2); + cmdData[0] = 1; + cmdData[1] = 1; + ctrl.executeAction(CoreController::RESET_REBOOT_COUNTERS, 0, cmdData.data(), 2); ctrl.parseRebootFile(REBOOT_FILE, rf); REQUIRE(rf.enabled == 1); REQUIRE(rf.img00Cnt == 0); REQUIRE(rf.img01Cnt == 0); REQUIRE(rf.img10Cnt == 0); REQUIRE(rf.img11Cnt == 0); + + // Reset lock on 0 1 + cmdData[0] = false; + cmdData[1] = 0; + cmdData[2] = 1; + ctrl.executeAction(CoreController::SWITCH_IMG_LOCK, 0, cmdData.data(), 3); + CHECK(CoreController::CURRENT_CHIP == xsc::CHIP_0); + CHECK(CoreController::CURRENT_COPY == xsc::COPY_0); + ctrl.performRebootFileHandling(false); + ctrl.performRebootFileHandling(false); + ctrl.performRebootFileHandling(false); + // Now should be on 0 1 + ctrl.parseRebootFile(REBOOT_FILE, rf); + CHECK(CoreController::CURRENT_CHIP == xsc::CHIP_0); + CHECK(CoreController::CURRENT_COPY == xsc::COPY_1); + REQUIRE(rf.enabled == 1); + REQUIRE(rf.img00Cnt == 3); + REQUIRE(rf.img01Cnt == 0); + REQUIRE(rf.img10Cnt == 0); + REQUIRE(rf.img11Cnt == 0); + REQUIRE(rf.img00Lock == false); + REQUIRE(rf.img01Lock == false); + REQUIRE(rf.img10Lock == false); + REQUIRE(rf.img11Lock == false); + // Now simulate failure in kernel boot or reboot from ProASIC3 + ctrl.setCurrentBootCopy(xsc::CHIP_0, xsc::COPY_0); + ctrl.performRebootFileHandling(false); + // Image 0 1 should have been marked as invalid now. Reboot will be triggered + // on 1 0 instead of 0 1 because 0 1 is marked as locked + ctrl.parseRebootFile(REBOOT_FILE, rf); + REQUIRE(rf.enabled == 1); + REQUIRE(rf.img00Cnt == 4); + REQUIRE(rf.img01Cnt == 0); + REQUIRE(rf.img10Cnt == 0); + REQUIRE(rf.img11Cnt == 0); + REQUIRE(rf.img00Lock == false); + REQUIRE(rf.img01Lock == true); + REQUIRE(rf.img10Lock == false); + REQUIRE(rf.img11Lock == false); + ctrl.performRebootFileHandling(false); + ctrl.parseRebootFile(REBOOT_FILE, rf); + REQUIRE(rf.enabled == 1); + REQUIRE(rf.img00Cnt == 4); + REQUIRE(rf.img01Cnt == 0); + REQUIRE(rf.img10Cnt == 1); + REQUIRE(rf.img11Cnt == 0); + REQUIRE(rf.img00Lock == false); + REQUIRE(rf.img01Lock == true); + REQUIRE(rf.img10Lock == false); + REQUIRE(rf.img11Lock == false); + // Reset lock on 0 1 again + cmdData[0] = false; + cmdData[1] = 0; + cmdData[2] = 1; + ctrl.executeAction(CoreController::SWITCH_IMG_LOCK, 0, cmdData.data(), 3); + // Lock 1 1 manually + // Reset lock on 0 1 again + cmdData[0] = true; + cmdData[1] = 1; + cmdData[2] = 1; + ctrl.executeAction(CoreController::SWITCH_IMG_LOCK, 0, cmdData.data(), 3); + ctrl.performRebootFileHandling(false); + ctrl.performRebootFileHandling(false); + // Should be on 0 1 now + ctrl.performRebootFileHandling(false); + ctrl.parseRebootFile(REBOOT_FILE, rf); + REQUIRE(rf.enabled == 1); + REQUIRE(rf.img00Cnt == 4); + REQUIRE(rf.img01Cnt == 1); + REQUIRE(rf.img10Cnt == 3); + REQUIRE(rf.img11Cnt == 0); + REQUIRE(rf.img00Lock == false); + REQUIRE(rf.img01Lock == false); + REQUIRE(rf.img10Lock == false); + REQUIRE(rf.img11Lock == true); + // Lock everything except 0 0 + cmdData[0] = true; + cmdData[1] = 0; + cmdData[2] = 1; + ctrl.executeAction(CoreController::SWITCH_IMG_LOCK, 0, cmdData.data(), 3); + cmdData[0] = true; + cmdData[1] = 1; + cmdData[2] = 0; + ctrl.executeAction(CoreController::SWITCH_IMG_LOCK, 0, cmdData.data(), 3); + ctrl.executeAction(CoreController::RESET_REBOOT_COUNTERS, 0, nullptr, 0); + ctrl.parseRebootFile(REBOOT_FILE, rf); + REQUIRE(rf.enabled == 1); + REQUIRE(rf.img00Cnt == 0); + REQUIRE(rf.img01Cnt == 0); + REQUIRE(rf.img10Cnt == 0); + REQUIRE(rf.img11Cnt == 0); + REQUIRE(rf.img00Lock == false); + REQUIRE(rf.img01Lock == true); + REQUIRE(rf.img10Lock == true); + REQUIRE(rf.img11Lock == true); + // Switch to 0 0 + ctrl.setCurrentBootCopy(xsc::CHIP_0, xsc::COPY_0); + ctrl.performRebootFileHandling(false); + ctrl.performRebootFileHandling(false); + ctrl.performRebootFileHandling(false); + // Should still be on 0 0 + ctrl.performRebootFileHandling(false); + ctrl.parseRebootFile(REBOOT_FILE, rf); + REQUIRE(rf.enabled == 1); + REQUIRE(rf.img00Cnt == 4); + REQUIRE(rf.img01Cnt == 0); + REQUIRE(rf.img10Cnt == 0); + REQUIRE(rf.img11Cnt == 0); + REQUIRE(rf.img00Lock == false); + REQUIRE(rf.img01Lock == true); + REQUIRE(rf.img10Lock == true); + REQUIRE(rf.img11Lock == true); + // Unlock 1 0 + cmdData[0] = false; + cmdData[1] = 1; + cmdData[2] = 0; + ctrl.executeAction(CoreController::SWITCH_IMG_LOCK, 0, cmdData.data(), 3); + // Reboots to 1 0 now + ctrl.performRebootFileHandling(false); + ctrl.parseRebootFile(REBOOT_FILE, rf); + REQUIRE(rf.enabled == 1); + REQUIRE(rf.img00Cnt == 5); + REQUIRE(rf.img01Cnt == 0); + REQUIRE(rf.img10Cnt == 0); + REQUIRE(rf.img11Cnt == 0); + REQUIRE(rf.img00Lock == false); + REQUIRE(rf.img01Lock == true); + REQUIRE(rf.img10Lock == false); + REQUIRE(rf.img11Lock == true); + REQUIRE(CoreController::CURRENT_CHIP == xsc::CHIP_1); + REQUIRE(CoreController::CURRENT_COPY == xsc::COPY_0); } if(std::filesystem::exists(CONF_PATH)) { std::uintmax_t n = std::filesystem::remove_all(CONF_PATH); From 84367f8424db3d97c7b0170360584b4d40ff2f5e Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 1 Mar 2022 14:51:12 +0100 Subject: [PATCH 22/25] small tweak --- bsp_q7s/core/CoreController.h | 2 +- unittest/rebootLogic/src/CoreController.h | 2 +- unittest/rebootLogic/src/main.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bsp_q7s/core/CoreController.h b/bsp_q7s/core/CoreController.h index 37f5395d..48bc9b7f 100644 --- a/bsp_q7s/core/CoreController.h +++ b/bsp_q7s/core/CoreController.h @@ -23,7 +23,7 @@ enum Copy : int { COPY_0, COPY_1, NO_COPY, SELF_COPY, ALL_COPY }; struct RebootFile { static constexpr uint8_t DEFAULT_MAX_BOOT_CNT = 10; - bool enabled = false; + bool enabled = true; size_t maxCount = DEFAULT_MAX_BOOT_CNT; uint32_t img00Cnt = 0; uint32_t img01Cnt = 0; diff --git a/unittest/rebootLogic/src/CoreController.h b/unittest/rebootLogic/src/CoreController.h index 737d550d..eec0d959 100644 --- a/unittest/rebootLogic/src/CoreController.h +++ b/unittest/rebootLogic/src/CoreController.h @@ -18,7 +18,7 @@ enum Copy : int { COPY_0, COPY_1, NO_COPY, SELF_COPY, ALL_COPY }; struct RebootFile { static constexpr uint8_t DEFAULT_MAX_BOOT_CNT = 10; - bool enabled = false; + bool enabled = true; size_t maxCount = DEFAULT_MAX_BOOT_CNT; uint32_t img00Cnt = 0; uint32_t img01Cnt = 0; diff --git a/unittest/rebootLogic/src/main.cpp b/unittest/rebootLogic/src/main.cpp index b24b4014..14ae8be8 100644 --- a/unittest/rebootLogic/src/main.cpp +++ b/unittest/rebootLogic/src/main.cpp @@ -32,7 +32,7 @@ TEST_CASE( "Core Controller Reboot File Handling", "[reboot-file]" ) { xsc_libnor_copy_t copy; RebootFile rf = {}; ctrl.rewriteRebootFile(rf); - REQUIRE(rf.enabled == 0); + REQUIRE(rf.enabled == 1); REQUIRE(rf.maxCount == RebootFile::DEFAULT_MAX_BOOT_CNT); REQUIRE(rf.img00Cnt == 0); REQUIRE(rf.img01Cnt == 0); From be122038ed354d6ecd4327c86cf6413685e47203 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 1 Mar 2022 14:56:19 +0100 Subject: [PATCH 23/25] small but important bugfix --- bsp_q7s/core/CoreController.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bsp_q7s/core/CoreController.cpp b/bsp_q7s/core/CoreController.cpp index e1c6a430..b1783054 100644 --- a/bsp_q7s/core/CoreController.cpp +++ b/bsp_q7s/core/CoreController.cpp @@ -1196,7 +1196,7 @@ void CoreController::performMountedSdCardOperations() { std::filesystem::create_directory(path); } initVersionFile(); - performRebootFileHandling(true); + performRebootFileHandling(false); doPerformMountedSdCardOps = false; } } From 9e03f9babe74c77a7248424cbe22edc1c015cac9 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 1 Mar 2022 15:06:59 +0100 Subject: [PATCH 24/25] apply clang format to unittest folder as well --- scripts/apply-clang-format.sh | 2 + unittest/main.cpp | 3 +- unittest/rebootLogic/src/CoreController.cpp | 37 ++++++++++--------- unittest/rebootLogic/src/CoreController.h | 18 ++++----- unittest/rebootLogic/src/HasActionsIF.h | 2 +- unittest/rebootLogic/src/SdCardManager.cpp | 8 +--- unittest/rebootLogic/src/SdCardManager.h | 2 +- unittest/rebootLogic/src/event.cpp | 3 +- unittest/rebootLogic/src/event.h | 3 +- .../serviceinterface/ServiceInterfaceStream.h | 3 +- unittest/rebootLogic/src/libxiphos.cpp | 8 ++-- unittest/rebootLogic/src/libxiphos.h | 20 +++++----- unittest/rebootLogic/src/main.cpp | 25 +++++++------ unittest/rebootLogic/src/print.c | 2 +- 14 files changed, 69 insertions(+), 67 deletions(-) diff --git a/scripts/apply-clang-format.sh b/scripts/apply-clang-format.sh index 724b44a0..eb2f4931 100755 --- a/scripts/apply-clang-format.sh +++ b/scripts/apply-clang-format.sh @@ -10,3 +10,5 @@ find ./bsp_linux_board -iname *.h -o -iname *.cpp -o -iname *.c | xargs clang-fo find ./bsp_hosted -iname *.h -o -iname *.cpp -o -iname *.c | xargs clang-format --style=file -i find ./bsp_egse -iname *.h -o -iname *.cpp -o -iname *.c | xargs clang-format --style=file -i find ./test -iname *.h -o -iname *.cpp -o -iname *.c | xargs clang-format --style=file -i +find ./unittest -iname *.h -o -iname *.cpp -o -iname *.c -o -type d -name build -prune | \ + xargs clang-format --style=file -i diff --git a/unittest/main.cpp b/unittest/main.cpp index 811df98e..1e274ab2 100644 --- a/unittest/main.cpp +++ b/unittest/main.cpp @@ -2,6 +2,5 @@ #include "fsfw_tests/unit/CatchRunner.h" int main(int argc, char* argv[]) { - // fsfwtest::customMain(argc, argv); + // fsfwtest::customMain(argc, argv); } - diff --git a/unittest/rebootLogic/src/CoreController.cpp b/unittest/rebootLogic/src/CoreController.cpp index c01d61f8..87268b45 100644 --- a/unittest/rebootLogic/src/CoreController.cpp +++ b/unittest/rebootLogic/src/CoreController.cpp @@ -1,14 +1,15 @@ -#include "conf.h" -#include "HasActionsIF.h" #include "CoreController.h" -#include "SdCardManager.h" -#include "event.h" -#include "libxiphos.h" -#include "fsfw/serviceinterface/ServiceInterface.h" -#include -#include #include +#include +#include + +#include "HasActionsIF.h" +#include "SdCardManager.h" +#include "conf.h" +#include "event.h" +#include "fsfw/serviceinterface/ServiceInterface.h" +#include "libxiphos.h" xsc::Chip CoreController::CURRENT_CHIP = xsc::Chip::NO_CHIP; xsc::Copy CoreController::CURRENT_COPY = xsc::Copy::NO_COPY; @@ -123,7 +124,7 @@ void CoreController::performRebootFileHandling(bool recreateFile) { } else { rebootFile.mechanismNextChip = xsc::NO_CHIP; rebootFile.mechanismNextCopy = xsc::NO_COPY; - } + } rewriteRebootFile(rebootFile); } @@ -436,15 +437,15 @@ void CoreController::rewriteRebootFile(RebootFile file) { << "\nimg00lock: " << file.img00Lock << "\nimg01lock: " << file.img01Lock << "\nimg10lock: " << file.img10Lock << "\nimg11lock: " << file.img11Lock << "\nbootflag: " << file.bootFlag << "\nlast: " << static_cast(file.lastChip) - << " " << static_cast(file.lastCopy) << "\nnext: " - << static_cast(file.mechanismNextChip) << " " + << " " << static_cast(file.lastCopy) + << "\nnext: " << static_cast(file.mechanismNextChip) << " " << static_cast(file.mechanismNextCopy) << "\n"; } } ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, const uint8_t *data, size_t size) { -switch (actionId) { + switch (actionId) { case (SWITCH_REBOOT_FILE_HANDLING): { if (size < 1) { return HasActionsIF::INVALID_PARAMETERS; @@ -464,10 +465,10 @@ switch (actionId) { return HasActionsIF::EXECUTION_FINISHED; } case (RESET_REBOOT_COUNTERS): { - if(size == 0) { + if (size == 0) { resetRebootCount(xsc::ALL_CHIP, xsc::ALL_COPY); } else if (size == 2) { - if(data[0] > 1 or data[1] > 1) { + if (data[0] > 1 or data[1] > 1) { return HasActionsIF::INVALID_PARAMETERS; } resetRebootCount(static_cast(data[0]), static_cast(data[1])); @@ -475,18 +476,18 @@ switch (actionId) { return HasActionsIF::EXECUTION_FINISHED; } case (SWITCH_IMG_LOCK): { - if(size != 3) { + if (size != 3) { return HasActionsIF::INVALID_PARAMETERS; } - if(data[1] > 1 or data[2] > 1) { + if (data[1] > 1 or data[2] > 1) { return HasActionsIF::INVALID_PARAMETERS; } setRebootMechanismLock(data[0], static_cast(data[1]), static_cast(data[2])); return HasActionsIF::EXECUTION_FINISHED; } - case(SET_MAX_REBOOT_CNT): { - if(size < 1) { + case (SET_MAX_REBOOT_CNT): { + if (size < 1) { return HasActionsIF::INVALID_PARAMETERS; } std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE; diff --git a/unittest/rebootLogic/src/CoreController.h b/unittest/rebootLogic/src/CoreController.h index eec0d959..c79a4ccd 100644 --- a/unittest/rebootLogic/src/CoreController.h +++ b/unittest/rebootLogic/src/CoreController.h @@ -1,12 +1,12 @@ #pragma once -#include "definitions.h" -#include "SdCardManager.h" - -#include #include +#include #include +#include "SdCardManager.h" +#include "definitions.h" + namespace xsc { enum Chip : int { CHIP_0, CHIP_1, NO_CHIP, SELF_CHIP, ALL_CHIP }; @@ -14,7 +14,6 @@ enum Copy : int { COPY_0, COPY_1, NO_COPY, SELF_COPY, ALL_COPY }; } // namespace xsc - struct RebootFile { static constexpr uint8_t DEFAULT_MAX_BOOT_CNT = 10; @@ -39,7 +38,7 @@ struct RebootFile { class SdCardManager; class CoreController { -public: + public: static constexpr char REBOOT_FILE[] = "/conf/reboot.txt"; //! [EXPORT] : [COMMENT] The reboot mechanism was triggered. //! P1: First 16 bits: Last Chip, Last 16 bits: Last Copy, @@ -57,15 +56,16 @@ public: static void setCurrentBootCopy(xsc::Chip chip, xsc::Copy copy); ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, - const uint8_t* data, size_t size); + const uint8_t* data, size_t size); void performRebootFileHandling(bool recreateFile); void determineAndExecuteReboot(RebootFile& rf, bool& needsReboot, xsc::Chip& tgtChip, - xsc::Copy& tgtCopy); + xsc::Copy& tgtCopy); void setRebootMechanismLock(bool lock, 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); -private: + + private: struct SdInfo { sd::SdCard pref = sd::SdCard::NONE; sd::SdState prefState = sd::SdState::OFF; diff --git a/unittest/rebootLogic/src/HasActionsIF.h b/unittest/rebootLogic/src/HasActionsIF.h index 773ad54f..1d56d891 100644 --- a/unittest/rebootLogic/src/HasActionsIF.h +++ b/unittest/rebootLogic/src/HasActionsIF.h @@ -1,7 +1,7 @@ #include "definitions.h" class HasActionsIF { -public: + public: static const ReturnValue_t IS_BUSY = 1; static const ReturnValue_t INVALID_PARAMETERS = 2; static const ReturnValue_t EXECUTION_FINISHED = 3; diff --git a/unittest/rebootLogic/src/SdCardManager.cpp b/unittest/rebootLogic/src/SdCardManager.cpp index 19bfa183..bf725956 100644 --- a/unittest/rebootLogic/src/SdCardManager.cpp +++ b/unittest/rebootLogic/src/SdCardManager.cpp @@ -1,9 +1,5 @@ #include "SdCardManager.h" -std::string SdCardManager::getCurrentMountPrefix(sd::SdCard prefSdCard) { - return "/tmp"; -} +std::string SdCardManager::getCurrentMountPrefix(sd::SdCard prefSdCard) { return "/tmp"; } -bool SdCardManager::isSdCardMounted(sd::SdCard sdCard) { - return true; -} \ No newline at end of file +bool SdCardManager::isSdCardMounted(sd::SdCard sdCard) { return true; } \ No newline at end of file diff --git a/unittest/rebootLogic/src/SdCardManager.h b/unittest/rebootLogic/src/SdCardManager.h index aee31d79..16aee0f4 100644 --- a/unittest/rebootLogic/src/SdCardManager.h +++ b/unittest/rebootLogic/src/SdCardManager.h @@ -17,7 +17,7 @@ enum SdCard : uint8_t { SLOT_0 = 0, SLOT_1 = 1, BOTH, NONE }; } // namespace sd class SdCardManager { -public: + public: std::string getCurrentMountPrefix(sd::SdCard prefSdCard); bool isSdCardMounted(sd::SdCard sdCard); }; diff --git a/unittest/rebootLogic/src/event.cpp b/unittest/rebootLogic/src/event.cpp index e6f6d8f8..54e5575a 100644 --- a/unittest/rebootLogic/src/event.cpp +++ b/unittest/rebootLogic/src/event.cpp @@ -1,4 +1,5 @@ #include "event.h" + #include std::queue EVENT_QUEUE = {}; @@ -13,7 +14,7 @@ void triggerEvent(Event event, uint32_t p1, uint32_t p2) { void eventWasCalled(EventInfo& eventInfo, uint32_t& numEvents) { numEvents = EVENT_QUEUE.size(); - if(not EVENT_QUEUE.empty()) { + if (not EVENT_QUEUE.empty()) { eventInfo = std::move(EVENT_QUEUE.back()); EVENT_QUEUE.pop(); } diff --git a/unittest/rebootLogic/src/event.h b/unittest/rebootLogic/src/event.h index 449836cd..fc831fe9 100644 --- a/unittest/rebootLogic/src/event.h +++ b/unittest/rebootLogic/src/event.h @@ -1,9 +1,10 @@ #pragma once -#include "definitions.h" #include #include +#include "definitions.h" + struct EventInfo { // That was just for testing, follow rule of 0 /* diff --git a/unittest/rebootLogic/src/fsfw/serviceinterface/ServiceInterfaceStream.h b/unittest/rebootLogic/src/fsfw/serviceinterface/ServiceInterfaceStream.h index bf3424a6..ca746e7d 100644 --- a/unittest/rebootLogic/src/fsfw/serviceinterface/ServiceInterfaceStream.h +++ b/unittest/rebootLogic/src/fsfw/serviceinterface/ServiceInterfaceStream.h @@ -1,9 +1,8 @@ #ifndef FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACESTREAM_H_ #define FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACESTREAM_H_ -#include "fsfw/FSFW.h" - #include "ServiceInterfaceBuffer.h" +#include "fsfw/FSFW.h" #if FSFW_CPP_OSTREAM_ENABLED == 1 diff --git a/unittest/rebootLogic/src/libxiphos.cpp b/unittest/rebootLogic/src/libxiphos.cpp index 00bbbae9..914b36e7 100644 --- a/unittest/rebootLogic/src/libxiphos.cpp +++ b/unittest/rebootLogic/src/libxiphos.cpp @@ -1,15 +1,16 @@ #include "libxiphos.h" + #include "CoreController.h" bool rebootWasCalled = false; xsc_libnor_chip_t lastChip; xsc_libnor_copy_t lastCopy; -bool getRebootWasCalled(xsc_libnor_chip_t& tgtChip, xsc_libnor_copy_t& tgtCopy) { +bool getRebootWasCalled(xsc_libnor_chip_t& tgtChip, xsc_libnor_copy_t& tgtCopy) { tgtChip = lastChip; tgtCopy = lastCopy; bool tmp = rebootWasCalled; - if(rebootWasCalled) { + if (rebootWasCalled) { rebootWasCalled = false; } return tmp; @@ -19,5 +20,6 @@ void xsc_boot_copy(xsc_libnor_chip_t boot_chip, xsc_libnor_copy_t boot_copy) { rebootWasCalled = true; lastChip = boot_chip; lastCopy = boot_copy; - CoreController::setCurrentBootCopy(static_cast(boot_chip), static_cast(boot_copy)); + CoreController::setCurrentBootCopy(static_cast(boot_chip), + static_cast(boot_copy)); } \ No newline at end of file diff --git a/unittest/rebootLogic/src/libxiphos.h b/unittest/rebootLogic/src/libxiphos.h index e6a40e45..341007c2 100644 --- a/unittest/rebootLogic/src/libxiphos.h +++ b/unittest/rebootLogic/src/libxiphos.h @@ -2,24 +2,24 @@ /** Type for identifying the nominal or the gold (redundant) flash copy */ typedef enum { - XSC_LIBNOR_COPY_NOMINAL, - XSC_LIBNOR_COPY_GOLD, - XSC_LIBNOR_COPY_TOTAL_NUMBER + XSC_LIBNOR_COPY_NOMINAL, + XSC_LIBNOR_COPY_GOLD, + XSC_LIBNOR_COPY_TOTAL_NUMBER } xsc_libnor_copy_t; /** Type for identifying on of the two NOR flash chips */ typedef enum { - XSC_LIBNOR_CHIP_0, /* First NOR flash chip */ - XSC_LIBNOR_CHIP_1, /* Second NOR flash chip */ - XSC_LIBNOR_CHIP_TOTAL_NUMBER + XSC_LIBNOR_CHIP_0, /* First NOR flash chip */ + XSC_LIBNOR_CHIP_1, /* Second NOR flash chip */ + XSC_LIBNOR_CHIP_TOTAL_NUMBER } xsc_libnor_chip_t; /** * @brief Used to verify whether reboot function was called - * - * @param tgtChip - * @param tgtCopy + * + * @param tgtChip + * @param tgtCopy */ -bool getRebootWasCalled(xsc_libnor_chip_t& tgtChip, xsc_libnor_copy_t& tgtCopy); +bool getRebootWasCalled(xsc_libnor_chip_t& tgtChip, xsc_libnor_copy_t& tgtCopy); void xsc_boot_copy(xsc_libnor_chip_t boot_chip, xsc_libnor_copy_t boot_copy); \ No newline at end of file diff --git a/unittest/rebootLogic/src/main.cpp b/unittest/rebootLogic/src/main.cpp index 14ae8be8..0a0febd7 100644 --- a/unittest/rebootLogic/src/main.cpp +++ b/unittest/rebootLogic/src/main.cpp @@ -1,13 +1,13 @@ +#include +#include +#include +#include + #include "CoreController.h" -#include "libxiphos.h" #include "HasActionsIF.h" #include "event.h" #include "fsfw/serviceinterface/ServiceInterface.h" - -#include -#include -#include -#include +#include "libxiphos.h" static constexpr bool CAT_FILE_TO_CONSOLE = false; const std::string CONF_PATH = "/tmp/conf"; @@ -20,14 +20,14 @@ ServiceInterfaceStream sif::info("INFO"); ServiceInterfaceStream sif::warning("WARNING"); ServiceInterfaceStream sif::error("ERROR", false, false, true); -TEST_CASE( "Core Controller Reboot File Handling", "[reboot-file]" ) { - if(not std::filesystem::exists(CONF_PATH)) { +TEST_CASE("Core Controller Reboot File Handling", "[reboot-file]") { + if (not std::filesystem::exists(CONF_PATH)) { std::filesystem::create_directory(CONF_PATH); } CoreController ctrl; std::array cmdData = {}; - SECTION ("Primary") { + SECTION("Primary") { xsc_libnor_chip_t chip; xsc_libnor_copy_t copy; RebootFile rf = {}; @@ -57,7 +57,8 @@ TEST_CASE( "Core Controller Reboot File Handling", "[reboot-file]" ) { REQUIRE(rf.lastChip == xsc::CHIP_0); REQUIRE(rf.lastCopy == xsc::COPY_0); uint8_t newRebootCnt = 3; - CHECK(ctrl.executeAction(CoreController::SET_MAX_REBOOT_CNT, 0, &newRebootCnt, 1) == HasActionsIF::EXECUTION_FINISHED); + CHECK(ctrl.executeAction(CoreController::SET_MAX_REBOOT_CNT, 0, &newRebootCnt, 1) == + HasActionsIF::EXECUTION_FINISHED); ctrl.parseRebootFile(REBOOT_FILE, rf); REQUIRE(rf.enabled == 1); REQUIRE(rf.maxCount == 3); @@ -396,14 +397,14 @@ TEST_CASE( "Core Controller Reboot File Handling", "[reboot-file]" ) { REQUIRE(CoreController::CURRENT_CHIP == xsc::CHIP_1); REQUIRE(CoreController::CURRENT_COPY == xsc::COPY_0); } - if(std::filesystem::exists(CONF_PATH)) { + if (std::filesystem::exists(CONF_PATH)) { std::uintmax_t n = std::filesystem::remove_all(CONF_PATH); CHECK(n == 2); } } void catFileToConsole() { - if(CAT_FILE_TO_CONSOLE) { + if (CAT_FILE_TO_CONSOLE) { std::ifstream file(REBOOT_FILE); if (file.is_open()) { std::cout << file.rdbuf(); diff --git a/unittest/rebootLogic/src/print.c b/unittest/rebootLogic/src/print.c index a59492b0..3d0d9b9d 100644 --- a/unittest/rebootLogic/src/print.c +++ b/unittest/rebootLogic/src/print.c @@ -1,5 +1,5 @@ -#include #include +#include void printChar(const char* character, bool errStream) { if (errStream) { From 23e2c5ffc8072d56fb81749705b121614a0b2d98 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 1 Mar 2022 15:23:01 +0100 Subject: [PATCH 25/25] repoint fsfw --- fsfw | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fsfw b/fsfw index e05e203c..6e0b9069 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit e05e203c83825b4069bb1391005d46f041b08455 +Subproject commit 6e0b90696da2dfd2ec4749dfdb73950be2283c25