diff --git a/CHANGELOG.md b/CHANGELOG.md index 359d8b03..e3995873 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,46 @@ will consitute of a breaking change warranting a new major release: # [unreleased] +## Fixed + +- Bugfixes and improvements for SDC state machine. Internal state was not updated correctly due + to a regression, so commanding the SDC state machine externally lead to confusing results. +- Fixed a bug in persistent TM store, where the active file was not reset of SD card switches. + SD card switch from 0 to 1 and vice-versa works without errors from persistent TM stores now. + +## Changed + +- Added additional logic for SDC state machine so that the SD cards are marked unusable when + the active SD card is switched or there is a transition from hot redundant to cold redundant mode. + This gives other tasks some time to register the SD cards being unusable, and therefore provides + a way for them to perform any re-initialization tasks necessary after SD card switches. + +# [v1.44.0] 2023-04-07 + +- eive-tmtc: v2.22.0 + +## Added + +- Special I2C recovery handling. If the I2C bus is unavailable for whatever reason, the EIVE + system component will power-cycle all I2C devices by first going to the OFF/BOOT mode, then + power-cycling the 3V3 stack and rebooting the battery, and finally going back to safe mode. + If this does not restore the bus, a full reboot will be performed. This special sequence can + be commanded as well. + +## Fixed + +- RW Assembly: Correctly transition back to off when more than 1 devices is OFF. Also do this + when this was due to two devices being marked faulty. +- RW dummy and STR dummy components: Set/Update modes correctly. +- RW handlers: Bugfix for TM set retrieval and special request handling in general where the CRC + check always failed for special request. Also removed an unnecessary delay for special requests. +- RW handlers: Polling is now disabled for RWs which are off. + +## Changed + +- RW shutdown now waits for the speed to be near 0 or for a OFF transition countdown to be expired + before going to off. + # [v1.43.2] 2023-04-05 ## Changed diff --git a/CMakeLists.txt b/CMakeLists.txt index d8724476..7989ff35 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,8 +10,8 @@ cmake_minimum_required(VERSION 3.13) set(OBSW_VERSION_MAJOR 1) -set(OBSW_VERSION_MINOR 43) -set(OBSW_VERSION_REVISION 2) +set(OBSW_VERSION_MINOR 44) +set(OBSW_VERSION_REVISION 0) # set(CMAKE_VERBOSE TRUE) diff --git a/bsp_hosted/fsfwconfig/events/translateEvents.cpp b/bsp_hosted/fsfwconfig/events/translateEvents.cpp index 25c6c39d..c4b537e8 100644 --- a/bsp_hosted/fsfwconfig/events/translateEvents.cpp +++ b/bsp_hosted/fsfwconfig/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** - * @brief Auto-generated event translation file. Contains 284 translations. + * @brief Auto-generated event translation file. Contains 285 translations. * @details - * Generated on: 2023-04-04 13:59:07 + * Generated on: 2023-04-07 17:42:57 */ #include "translateEvents.h" @@ -266,7 +266,8 @@ const char *VERSION_INFO_STRING = "VERSION_INFO"; const char *CURRENT_IMAGE_INFO_STRING = "CURRENT_IMAGE_INFO"; const char *REBOOT_COUNTER_STRING = "REBOOT_COUNTER"; const char *INDIVIDUAL_BOOT_COUNTS_STRING = "INDIVIDUAL_BOOT_COUNTS"; -const char *I2C_UNAVAILABLE_REBOOT_STRING = "I2C_UNAVAILABLE_REBOOT"; +const char *TRYING_I2C_RECOVERY_STRING = "TRYING_I2C_RECOVERY"; +const char *I2C_REBOOT_STRING = "I2C_REBOOT"; const char *NO_VALID_SENSOR_TEMPERATURE_STRING = "NO_VALID_SENSOR_TEMPERATURE"; const char *NO_HEALTHY_HEATER_AVAILABLE_STRING = "NO_HEALTHY_HEATER_AVAILABLE"; const char *SYRLINKS_OVERHEATING_STRING = "SYRLINKS_OVERHEATING"; @@ -815,7 +816,9 @@ const char *translateEvents(Event event) { case (14008): return INDIVIDUAL_BOOT_COUNTS_STRING; case (14010): - return I2C_UNAVAILABLE_REBOOT_STRING; + return TRYING_I2C_RECOVERY_STRING; + case (14011): + return I2C_REBOOT_STRING; case (14100): return NO_VALID_SENSOR_TEMPERATURE_STRING; case (14101): diff --git a/bsp_hosted/fsfwconfig/objects/translateObjects.cpp b/bsp_hosted/fsfwconfig/objects/translateObjects.cpp index 8962edfc..148ac0b3 100644 --- a/bsp_hosted/fsfwconfig/objects/translateObjects.cpp +++ b/bsp_hosted/fsfwconfig/objects/translateObjects.cpp @@ -2,7 +2,7 @@ * @brief Auto-generated object translation file. * @details * Contains 171 translations. - * Generated on: 2023-04-04 13:59:07 + * Generated on: 2023-04-07 17:42:57 */ #include "translateObjects.h" diff --git a/bsp_q7s/callbacks/rwSpiCallback.cpp b/bsp_q7s/callbacks/rwSpiCallback.cpp index 311b843e..60ad5664 100644 --- a/bsp_q7s/callbacks/rwSpiCallback.cpp +++ b/bsp_q7s/callbacks/rwSpiCallback.cpp @@ -252,7 +252,7 @@ ReturnValue_t openSpi(const std::string& devname, int flags, GpioIF* gpioIF, gpi fd = open(devname.c_str(), flags); if (fd < 0) { sif::error << "rwSpiCallback::spiCallback: Failed to open device file" << std::endl; - return SpiComIF::OPENING_FILE_FAILED; + return spi::OPENING_FILE_FAILED; } // Pull SPI CS low. For now, no support for active high given diff --git a/bsp_q7s/core/CoreController.cpp b/bsp_q7s/core/CoreController.cpp index c895106b..9e40b03c 100644 --- a/bsp_q7s/core/CoreController.cpp +++ b/bsp_q7s/core/CoreController.cpp @@ -9,6 +9,7 @@ #include "fsfw/serviceinterface/ServiceInterface.h" #include "fsfw/timemanager/Stopwatch.h" #include "fsfw/version.h" +#include "mission/sysDefs.h" #include "watchdog/definitions.h" #if OBSW_ADD_TMTC_UDP_SERVER == 1 #include "fsfw/osal/common/UdpTmTcBridge.h" @@ -31,8 +32,7 @@ xsc::Chip CoreController::CURRENT_CHIP = xsc::Chip::NO_CHIP; xsc::Copy CoreController::CURRENT_COPY = xsc::Copy::NO_COPY; -CoreController::CoreController(object_id_t objectId, const std::atomic_uint16_t &i2cErrors, - bool enableHkSet) +CoreController::CoreController(object_id_t objectId, bool enableHkSet) : ExtendedControllerBase(objectId, 5), enableHkSet(enableHkSet), cmdExecutor(4096), @@ -40,8 +40,7 @@ CoreController::CoreController(object_id_t objectId, const std::atomic_uint16_t cmdRepliesSizes(128), opDivider5(5), opDivider10(10), - hkSet(this), - i2cErrors(i2cErrors) { + hkSet(this) { cmdExecutor.setRingBuffer(&cmdReplyBuf, &cmdRepliesSizes); try { sdcMan = SdCardManager::instance(); @@ -55,7 +54,6 @@ CoreController::CoreController(object_id_t objectId, const std::atomic_uint16_t // Set up state of SD card manager and own initial state. // Stopwatch watch; sdcMan->updateSdCardStateFile(); - sdcMan->updateSdStatePair(); SdCardManager::SdStatePair sdStates; sdcMan->getSdCardsStatus(sdStates); auto sdCard = sdcMan->getPreferredSdCard(); @@ -110,17 +108,12 @@ void CoreController::performControlOperation() { sdStateMachine(); performMountedSdCardOperations(); readHkData(); - if (i2cErrors >= 5) { - bool protOpPerformed = false; - triggerEvent(I2C_UNAVAILABLE_REBOOT); - gracefulShutdownTasks(CURRENT_CHIP, CURRENT_COPY, protOpPerformed); - std::system("xsc_boot_copy -r"); - } + if (shellCmdIsExecuting) { bool replyReceived = false; // TODO: We could read the data in the ring buffer and send it as an action data reply. if (cmdExecutor.check(replyReceived) == CommandExecutor::EXECUTION_FINISHED) { - actionHelper.finish(true, successRecipient, EXECUTE_SHELL_CMD); + actionHelper.finish(true, successRecipient, core::EXECUTE_SHELL_CMD); shellCmdIsExecuting = false; cmdReplyBuf.clear(); while (not cmdRepliesSizes.empty()) { @@ -163,7 +156,7 @@ ReturnValue_t CoreController::initialize() { sdStateMachine(); - triggerEvent(REBOOT_SW, CURRENT_CHIP, CURRENT_COPY); + triggerEvent(core::REBOOT_SW, CURRENT_CHIP, CURRENT_COPY); EventManagerIF *eventManager = ObjectManager::instance()->get(objects::EVENT_MANAGER); if (eventManager == nullptr or eventQueue == nullptr) { @@ -202,6 +195,7 @@ ReturnValue_t CoreController::initializeAfterTaskCreation() { ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, const uint8_t *data, size_t size) { + using namespace core; switch (actionId) { case (ANNOUNCE_VERSION): { uint32_t p1 = (common::OBSW_VERSION_MAJOR << 24) | (common::OBSW_VERSION_MINOR << 16) | @@ -373,7 +367,7 @@ ReturnValue_t CoreController::initSdCardBlocking() { } if (sdInfo.cfgMode == SdCfgMode::COLD_REDUNDANT) { - updateSdInfoOther(); + updateInternalSdInfo(); sif::info << "Cold redundant SD card configuration, preferred SD card: " << static_cast(sdInfo.active) << std::endl; result = sdColdRedundantBlockingInit(); @@ -409,23 +403,23 @@ ReturnValue_t CoreController::sdStateMachine() { } else { // Still update SD state file if (sdInfo.cfgMode == SdCfgMode::PASSIVE) { - sdFsmState = SdStates::UPDATE_INFO; + sdFsmState = SdStates::UPDATE_SD_INFO_END; } else { sdInfo.cycleCount = 0; - sdInfo.commandExecuted = false; - sdFsmState = SdStates::GET_INFO; + sdInfo.commandPending = false; + sdFsmState = SdStates::UPDATE_SD_INFO_START; } } } - // This lambda checks the non-blocking operation and assigns the new state on success. - // It returns true for an operation success and false otherwise - auto nonBlockingOpChecking = [&](SdStates newStateOnSuccess, uint16_t maxCycleCount, - std::string opPrintout) { + // This lambda checks the non-blocking operation of the SD card manager and assigns the new + // state on success. It returns true for an operation success and false otherwise + auto nonBlockingSdcOpChecking = [&](SdStates newStateOnSuccess, uint16_t maxCycleCount, + std::string opPrintout) { SdCardManager::OpStatus status = sdcMan->checkCurrentOp(operation); if (status == SdCardManager::OpStatus::SUCCESS) { sdFsmState = newStateOnSuccess; - sdInfo.commandExecuted = false; + sdInfo.commandPending = false; sdInfo.cycleCount = 0; return true; } else if (sdInfo.cycleCount > 4) { @@ -436,26 +430,29 @@ ReturnValue_t CoreController::sdStateMachine() { return false; }; - if (sdFsmState == SdStates::GET_INFO) { - if (not sdInfo.commandExecuted) { + if (sdFsmState == SdStates::UPDATE_SD_INFO_START) { + if (not sdInfo.commandPending) { // Create updated status file result = sdcMan->updateSdCardStateFile(); if (result != returnvalue::OK) { sif::warning << "CoreController::sdStateMachine: Updating SD card state file failed" << std::endl; } - sdFsmState = SdStates::SET_STATE_SELF; - sdInfo.commandExecuted = false; - sdInfo.cycleCount = 0; - } else { - nonBlockingOpChecking(SdStates::SET_STATE_SELF, 4, "Updating SDC file"); - } - } - - if (sdFsmState == SdStates::SET_STATE_SELF) { - if (not sdInfo.commandExecuted) { result = sdcMan->getSdCardsStatus(sdInfo.currentState); - updateSdInfoOther(); + updateInternalSdInfo(); + auto currentlyActiveSdc = sdcMan->getActiveSdCard(); + // Used/active SD card switches, so mark SD card unusable so other tasks have some time + // registering the unavailable SD card. + if (not currentlyActiveSdc.has_value() or + ((currentlyActiveSdc.value() == sd::SdCard::SLOT_0) and + (sdInfo.active == sd::SdCard::SLOT_1)) or + ((currentlyActiveSdc.value() == sd::SdCard::SLOT_1) and + (sdInfo.active == sd::SdCard::SLOT_0))) { + sdInfo.lockSdCardUsage = true; + } + if (sdInfo.lockSdCardUsage) { + sdcMan->markUnusable(); + } if (sdInfo.active != sd::SdCard::SLOT_0 and sdInfo.active != sd::SdCard::SLOT_1) { sif::warning << "Preferred SD card invalid. Setting to card 0.." << std::endl; sdInfo.active = sd::SdCard::SLOT_0; @@ -467,7 +464,11 @@ ReturnValue_t CoreController::sdStateMachine() { sif::info << "Cold redundant SD card configuration, target SD card: " << static_cast(sdInfo.active) << std::endl; } + SdStates tgtState = SdStates::IDLE; + bool skipCycles = sdInfo.lockSdCardUsage; + // Need to do different things depending on state of SD card which will be active. if (sdInfo.activeState == sd::SdState::MOUNTED) { + // Already mounted, so we can perform handling of the other side. #if OBSW_VERBOSE_LEVEL >= 1 std::string mountString; if (sdInfo.active == sd::SdCard::SLOT_0) { @@ -480,27 +481,57 @@ ReturnValue_t CoreController::sdStateMachine() { #endif sdcMan->setActiveSdCard(sdInfo.active); currMntPrefix = sdcMan->getCurrentMountPrefix(); - sdFsmState = SdStates::DETERMINE_OTHER; + tgtState = SdStates::DETERMINE_OTHER; } else if (sdInfo.activeState == sd::SdState::OFF) { + // It's okay to do the delay after swichting active SD on, no one can use it anyway.. sdCardSetup(sdInfo.active, sd::SdState::ON, sdInfo.activeChar, false); - sdInfo.commandExecuted = true; + sdInfo.commandPending = true; + // Do not skip cycles here, would mess up the state machine. We skip the cycles after + // the SD card was switched on. + skipCycles = false; + // Remain on the current state. + tgtState = sdFsmState; } else if (sdInfo.activeState == sd::SdState::ON) { - sdFsmState = SdStates::MOUNT_SELF; + // We can do the delay before mounting where applicable. + tgtState = SdStates::MOUNT_SELF; + } + if (skipCycles) { + sdFsmState = SdStates::SKIP_TWO_CYCLES_IF_SD_LOCKED; + fsmStateAfterDelay = tgtState; + sdInfo.skippedCyclesCount = 0; + } else { + sdFsmState = tgtState; } } else { - if (nonBlockingOpChecking(SdStates::MOUNT_SELF, 10, "Setting SDC state")) { + if (nonBlockingSdcOpChecking(SdStates::MOUNT_SELF, 10, "Setting SDC state")) { sdInfo.activeState = sd::SdState::ON; currentStateSetter(sdInfo.active, sd::SdState::ON); + // Skip the two cycles now. + if (sdInfo.lockSdCardUsage) { + sdFsmState = SdStates::SKIP_TWO_CYCLES_IF_SD_LOCKED; + fsmStateAfterDelay = SdStates::MOUNT_SELF; + sdInfo.skippedCyclesCount = 0; + } } } } + if (sdFsmState == SdStates::SKIP_TWO_CYCLES_IF_SD_LOCKED) { + sdInfo.skippedCyclesCount++; + // Count to three because this branch will run in the same FSM cycle. + if (sdInfo.skippedCyclesCount == 3) { + sdFsmState = fsmStateAfterDelay; + fsmStateAfterDelay = SdStates::IDLE; + sdInfo.skippedCyclesCount = 0; + } + } + if (sdFsmState == SdStates::MOUNT_SELF) { - if (not sdInfo.commandExecuted) { + if (not sdInfo.commandPending) { result = sdCardSetup(sdInfo.active, sd::SdState::MOUNTED, sdInfo.activeChar); - sdInfo.commandExecuted = true; + sdInfo.commandPending = true; } else { - if (nonBlockingOpChecking(SdStates::DETERMINE_OTHER, 5, "Mounting SD card")) { + if (nonBlockingSdcOpChecking(SdStates::DETERMINE_OTHER, 5, "Mounting SD card")) { sdcMan->setActiveSdCard(sdInfo.active); currMntPrefix = sdcMan->getCurrentMountPrefix(); sdInfo.activeState = sd::SdState::MOUNTED; @@ -537,23 +568,33 @@ ReturnValue_t CoreController::sdStateMachine() { if (sdFsmState == SdStates::SET_STATE_OTHER) { // Set state of other SD card to ON or OFF, depending on redundancy mode if (sdInfo.cfgMode == SdCfgMode::COLD_REDUNDANT) { - if (not sdInfo.commandExecuted) { + if (not sdInfo.commandPending) { result = sdCardSetup(sdInfo.other, sd::SdState::OFF, sdInfo.otherChar, false); - sdInfo.commandExecuted = true; + sdInfo.commandPending = true; } else { - if (nonBlockingOpChecking(SdStates::SKIP_CYCLE_BEFORE_INFO_UPDATE, 10, - "Switching off other SD card")) { + if (nonBlockingSdcOpChecking(SdStates::SKIP_CYCLE_BEFORE_INFO_UPDATE, 10, + "Switching off other SD card")) { + sdInfo.otherState = sd::SdState::OFF; + currentStateSetter(sdInfo.other, sd::SdState::OFF); + } else { + // Continue.. avoid being stuck here.. + sdFsmState = SdStates::SKIP_CYCLE_BEFORE_INFO_UPDATE; sdInfo.otherState = sd::SdState::OFF; currentStateSetter(sdInfo.other, sd::SdState::OFF); } } } else if (sdInfo.cfgMode == SdCfgMode::HOT_REDUNDANT) { - if (not sdInfo.commandExecuted) { + if (not sdInfo.commandPending) { result = sdCardSetup(sdInfo.other, sd::SdState::ON, sdInfo.otherChar, false); - sdInfo.commandExecuted = true; + sdInfo.commandPending = true; } else { - if (nonBlockingOpChecking(SdStates::MOUNT_UNMOUNT_OTHER, 10, - "Switching on other SD card")) { + if (nonBlockingSdcOpChecking(SdStates::MOUNT_UNMOUNT_OTHER, 10, + "Switching on other SD card")) { + sdInfo.otherState = sd::SdState::ON; + currentStateSetter(sdInfo.other, sd::SdState::ON); + } else { + // Contnue.. avoid being stuck here. + sdFsmState = SdStates::MOUNT_UNMOUNT_OTHER; sdInfo.otherState = sd::SdState::ON; currentStateSetter(sdInfo.other, sd::SdState::ON); } @@ -564,21 +605,25 @@ ReturnValue_t CoreController::sdStateMachine() { if (sdFsmState == SdStates::MOUNT_UNMOUNT_OTHER) { // Mount or unmount other SD card, depending on redundancy mode if (sdInfo.cfgMode == SdCfgMode::COLD_REDUNDANT) { - if (not sdInfo.commandExecuted) { + if (not sdInfo.commandPending) { result = sdCardSetup(sdInfo.other, sd::SdState::ON, sdInfo.otherChar); - sdInfo.commandExecuted = true; + sdInfo.commandPending = true; } else { - if (nonBlockingOpChecking(SdStates::SET_STATE_OTHER, 10, "Unmounting other SD card")) { + if (nonBlockingSdcOpChecking(SdStates::SET_STATE_OTHER, 10, "Unmounting other SD card")) { sdInfo.otherState = sd::SdState::ON; currentStateSetter(sdInfo.other, sd::SdState::ON); + } else { + sdInfo.otherState = sd::SdState::ON; + currentStateSetter(sdInfo.other, sd::SdState::ON); + sdFsmState = SdStates::SET_STATE_OTHER; } } } else if (sdInfo.cfgMode == SdCfgMode::HOT_REDUNDANT) { - if (not sdInfo.commandExecuted) { + if (not sdInfo.commandPending) { result = sdCardSetup(sdInfo.other, sd::SdState::MOUNTED, sdInfo.otherChar); - sdInfo.commandExecuted = true; + sdInfo.commandPending = true; } else { - if (nonBlockingOpChecking(SdStates::UPDATE_INFO, 4, "Mounting other SD card")) { + if (nonBlockingSdcOpChecking(SdStates::UPDATE_SD_INFO_END, 4, "Mounting other SD card")) { sdInfo.otherState = sd::SdState::MOUNTED; currentStateSetter(sdInfo.other, sd::SdState::MOUNTED); } @@ -587,14 +632,17 @@ ReturnValue_t CoreController::sdStateMachine() { } if (sdFsmState == SdStates::SKIP_CYCLE_BEFORE_INFO_UPDATE) { - sdFsmState = SdStates::UPDATE_INFO; - } else if (sdFsmState == SdStates::UPDATE_INFO) { + sdFsmState = SdStates::UPDATE_SD_INFO_END; + } else if (sdFsmState == SdStates::UPDATE_SD_INFO_END) { // Update status file result = sdcMan->updateSdCardStateFile(); if (result != returnvalue::OK) { - sif::warning << "CoreController::initialize: Updating SD card state file failed" << std::endl; + sif::warning << "CoreController: Updating SD card state file failed" << std::endl; } - sdInfo.commandExecuted = false; + updateInternalSdInfo(); + // Mark usable again in any case. + sdcMan->markUsable(); + sdInfo.commandPending = false; sdFsmState = SdStates::IDLE; sdInfo.cycleCount = 0; sdcMan->setBlocking(false); @@ -604,8 +652,16 @@ ReturnValue_t CoreController::sdStateMachine() { actionHelper.finish(true, sdCommandingInfo.commander, sdCommandingInfo.actionId, returnvalue::OK); } + const char *modeStr = "UNKNOWN"; + if (sdInfo.cfgMode == SdCfgMode::COLD_REDUNDANT) { + modeStr = "COLD REDUNDANT"; + } else if (sdInfo.cfgMode == SdCfgMode::HOT_REDUNDANT) { + modeStr = "HOT REDUNDANT"; + } + sif::info << "SD card update into " << modeStr + << " mode finished. Active SD: " << sdInfo.activeChar << std::endl; if (not sdInfo.initFinished) { - updateSdInfoOther(); + updateInternalSdInfo(); sdInfo.initFinished = true; sif::info << "SD card initialization finished" << std::endl; } @@ -982,7 +1038,7 @@ ReturnValue_t CoreController::gracefulShutdownTasks(xsc::Chip chip, xsc::Copy co return result; } -void CoreController::updateSdInfoOther() { +void CoreController::updateInternalSdInfo() { if (sdInfo.active == sd::SdCard::SLOT_0) { sdInfo.activeChar = "0"; sdInfo.otherChar = "1"; @@ -1324,7 +1380,7 @@ ReturnValue_t CoreController::performSdCardCheck() { someSdCardActive = true; } if (not someSdCardActive and remountAttemptFlag) { - triggerEvent(NO_SD_CARD_ACTIVE); + triggerEvent(core::NO_SD_CARD_ACTIVE); initSdCardBlocking(); remountAttemptFlag = false; } @@ -1378,7 +1434,7 @@ 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; - triggerEvent(REBOOT_MECHANISM_TRIGGERED, p1, 0); + triggerEvent(core::REBOOT_MECHANISM_TRIGGERED, p1, 0); // Clear the boot flag rebootFile.bootFlag = false; } @@ -2035,6 +2091,11 @@ bool CoreController::startSdStateMachine(sd::SdCard targetActiveSd, SdCfgMode mo } sdFsmState = SdStates::START; sdInfo.active = targetActiveSd; + // If we are going from 2 SD cards to one, lock SD card usage in any case because 1 SD card is + // going off. + if (sdInfo.cfgMode == SdCfgMode::HOT_REDUNDANT and mode == SdCfgMode::COLD_REDUNDANT) { + sdInfo.lockSdCardUsage = true; + } sdInfo.cfgMode = mode; sdCommandingInfo.actionId = actionId; sdCommandingInfo.commander = commander; @@ -2047,8 +2108,9 @@ void CoreController::announceBootCounts() { rebootFile.img00Cnt + rebootFile.img01Cnt + rebootFile.img10Cnt + rebootFile.img11Cnt; uint32_t individualBootCountsP1 = (rebootFile.img00Cnt << 16) | rebootFile.img01Cnt; uint32_t individualBootCountsP2 = (rebootFile.img10Cnt << 16) | rebootFile.img11Cnt; - triggerEvent(INDIVIDUAL_BOOT_COUNTS, individualBootCountsP1, individualBootCountsP2); - triggerEvent(REBOOT_COUNTER, (totalBootCount >> 32) & 0xffffffff, totalBootCount & 0xffffffff); + triggerEvent(core::INDIVIDUAL_BOOT_COUNTS, individualBootCountsP1, individualBootCountsP2); + triggerEvent(core::REBOOT_COUNTER, (totalBootCount >> 32) & 0xffffffff, + totalBootCount & 0xffffffff); } bool CoreController::isNumber(const std::string &s) { diff --git a/bsp_q7s/core/CoreController.h b/bsp_q7s/core/CoreController.h index 72d63b15..22b1f6ff 100644 --- a/bsp_q7s/core/CoreController.h +++ b/bsp_q7s/core/CoreController.h @@ -78,64 +78,7 @@ class CoreController : public ExtendedControllerBase { static constexpr dur_millis_t INIT_SD_CARD_CHECK_TIMEOUT = 5000; static constexpr dur_millis_t DEFAULT_SD_CARD_CHECK_TIMEOUT = 60000; - static constexpr ActionId_t LIST_DIRECTORY_INTO_FILE = 0; - static constexpr ActionId_t ANNOUNCE_VERSION = 1; - static constexpr ActionId_t ANNOUNCE_CURRENT_IMAGE = 2; - static constexpr ActionId_t ANNOUNCE_BOOT_COUNTS = 3; - static constexpr ActionId_t SWITCH_REBOOT_FILE_HANDLING = 5; - 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 OBSW_UPDATE_FROM_SD_0 = 10; - static constexpr ActionId_t OBSW_UPDATE_FROM_SD_1 = 11; - static constexpr ActionId_t OBSW_UPDATE_FROM_TMP = 12; - - static constexpr ActionId_t SWITCH_TO_SD_0 = 16; - static constexpr ActionId_t SWITCH_TO_SD_1 = 17; - static constexpr ActionId_t SWITCH_TO_BOTH_SD_CARDS = 18; - - //! Reboot using the xsc_boot_copy command - static constexpr ActionId_t XSC_REBOOT_OBC = 32; - static constexpr ActionId_t MOUNT_OTHER_COPY = 33; - //! Reboot using the reboot command - static constexpr ActionId_t REBOOT_OBC = 34; - - static constexpr ActionId_t EXECUTE_SHELL_CMD = 40; - - 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 occurred. Can also be a systemd reboot. - //! P1: Current Chip, P2: Current Copy - static constexpr Event REBOOT_SW = event::makeEvent(SUBSYSTEM_ID, 1, severity::LOW); - //! [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); - //! [EXPORT] : [COMMENT] No SD card was active. Core controller will attempt to re-initialize - //! a SD card. - static constexpr Event NO_SD_CARD_ACTIVE = event::makeEvent(SUBSYSTEM_ID, 4, severity::HIGH); - //! [EXPORT] : [COMMENT] - //! P1: Byte 0: Major, Byte 1: Minor, Byte 2: Patch, Byte 3: Has Git Hash - //! P2: First four letters of Git SHA is the last byte of P1 is set. - static constexpr Event VERSION_INFO = event::makeEvent(SUBSYSTEM_ID, 5, severity::INFO); - //! [EXPORT] : [COMMENT] P1: Current Chip, P2: Current Copy - static constexpr Event CURRENT_IMAGE_INFO = event::makeEvent(SUBSYSTEM_ID, 6, severity::INFO); - //! [EXPORT] : [COMMENT] Total reboot counter, which is the sum of the boot count of all - //! individual images. - static constexpr Event REBOOT_COUNTER = event::makeEvent(SUBSYSTEM_ID, 7, severity::INFO); - //! [EXPORT] : [COMMENT] Get the boot count of the individual images. - //! P1: First 16 bits boot count of image 0 0, last 16 bits boot count of image 0 1. - //! P2: First 16 bits boot count of image 1 0, last 16 bits boot count of image 1 1. - static constexpr Event INDIVIDUAL_BOOT_COUNTS = event::makeEvent(SUBSYSTEM_ID, 8, severity::INFO); - static constexpr Event I2C_UNAVAILABLE_REBOOT = - event::makeEvent(SUBSYSTEM_ID, 10, severity::MEDIUM); - - CoreController(object_id_t objectId, const std::atomic_uint16_t& i2cErrors, bool enableHkSet); + CoreController(object_id_t objectId, bool enableHkSet); virtual ~CoreController(); ReturnValue_t initialize() override; @@ -186,8 +129,8 @@ class CoreController : public ExtendedControllerBase { enum class SdStates { NONE, START, - GET_INFO, - SET_STATE_SELF, + UPDATE_SD_INFO_START, + SKIP_TWO_CYCLES_IF_SD_LOCKED, MOUNT_SELF, // Determine operations for other SD card, depending on redundancy configuration DETERMINE_OTHER, @@ -197,7 +140,7 @@ class CoreController : public ExtendedControllerBase { // Skip period because the shell command used to generate the info file sometimes is // missing the last performed operation if executed too early SKIP_CYCLE_BEFORE_INFO_UPDATE, - UPDATE_INFO, + UPDATE_SD_INFO_END, // SD initialization done IDLE }; @@ -210,22 +153,28 @@ class CoreController : public ExtendedControllerBase { MessageQueueIF* eventQueue = nullptr; SdStates sdFsmState = SdStates::START; + SdStates fsmStateAfterDelay = SdStates::IDLE; enum SdCfgMode { PASSIVE, COLD_REDUNDANT, HOT_REDUNDANT }; struct SdFsmParams { SdCfgMode cfgMode = SdCfgMode::COLD_REDUNDANT; sd::SdCard active = sd::SdCard::NONE; sd::SdCard other = sd::SdCard::NONE; - sd::SdState activeState = sd::SdState::OFF; - sd::SdState otherState = sd::SdState::OFF; std::string activeChar = "0"; std::string otherChar = "1"; + sd::SdState activeState = sd::SdState::OFF; + sd::SdState otherState = sd::SdState::OFF; std::pair mountSwitch = {true, true}; - // Used to track whether a command was executed - bool commandExecuted = true; + // This flag denotes that the SD card usage is locked. This is relevant if SD cards go off + // to leave appliation using the SD cards some time to detect the SD card is not usable anymore. + // This is relevant if the active SD card is being switched. The SD card will also be locked + // when going from hot-redundant mode to cold-redundant mode. + bool lockSdCardUsage = false; + bool commandPending = true; bool initFinished = false; SdCardManager::SdStatePair currentState; uint16_t cycleCount = 0; + uint16_t skippedCyclesCount = 0; } sdInfo; struct SdCommanding { @@ -266,7 +215,6 @@ class CoreController : public ExtendedControllerBase { PoolEntry plVoltageEntry = PoolEntry(0.0); core::HkSet hkSet; - const std::atomic_uint16_t& i2cErrors; #if OBSW_SD_CARD_MUST_BE_ON == 1 bool remountAttemptFlag = true; @@ -290,7 +238,7 @@ class CoreController : public ExtendedControllerBase { void initPrint(); ReturnValue_t sdStateMachine(); - void updateSdInfoOther(); + void updateInternalSdInfo(); ReturnValue_t sdCardSetup(sd::SdCard sdCard, sd::SdState targetState, std::string sdChar, bool printOutput = true); ReturnValue_t executeSwUpdate(SwUpdateSources sourceDir, const uint8_t* data, size_t size); diff --git a/bsp_q7s/core/ObjectFactory.h b/bsp_q7s/core/ObjectFactory.h index 9daa4d01..b5685389 100644 --- a/bsp_q7s/core/ObjectFactory.h +++ b/bsp_q7s/core/ObjectFactory.h @@ -23,7 +23,6 @@ class HealthTableIF; class AcsBoardAssembly; class GpioIF; -extern std::atomic_uint16_t I2C_FATAL_ERRORS; extern std::atomic_bool PTME_LOCKED; namespace ObjectFactory { diff --git a/bsp_q7s/core/scheduling.cpp b/bsp_q7s/core/scheduling.cpp index e248938a..3f7000c7 100644 --- a/bsp_q7s/core/scheduling.cpp +++ b/bsp_q7s/core/scheduling.cpp @@ -237,7 +237,7 @@ void scheduling::initTasks() { #if OBSW_ADD_RW == 1 PeriodicTaskIF* rwPolling = - factory->createPeriodicTask("RW_POLLING_TASK", 80, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2, + factory->createPeriodicTask("RW_POLLING_TASK", 75, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2, 0.4, missedDeadlineFunc, &RR_SCHEDULING); result = rwPolling->addComponent(objects::RW_POLLING_TASK); if (result != returnvalue::OK) { diff --git a/bsp_q7s/em/emObjectFactory.cpp b/bsp_q7s/em/emObjectFactory.cpp index ad520441..e43d34f2 100644 --- a/bsp_q7s/em/emObjectFactory.cpp +++ b/bsp_q7s/em/emObjectFactory.cpp @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include #include "OBSWConfig.h" @@ -71,7 +71,7 @@ void ObjectFactory::produce(void* args) { dummy::createDummies(dummyCfg, *pwrSwitcher, gpioComIF); - new CoreController(objects::CORE_CONTROLLER, I2C_FATAL_ERRORS, enableHkSets); + new CoreController(objects::CORE_CONTROLLER, enableHkSets); // Regular FM code, does not work for EM if the hardware is not connected // createPcduComponents(gpioComIF, &pwrSwitcher); diff --git a/bsp_q7s/fmObjectFactory.cpp b/bsp_q7s/fmObjectFactory.cpp index 963c897b..5cb7c751 100644 --- a/bsp_q7s/fmObjectFactory.cpp +++ b/bsp_q7s/fmObjectFactory.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include "OBSWConfig.h" #include "bsp_q7s/core/CoreController.h" @@ -13,7 +14,7 @@ #include "linux/ObjectFactory.h" #include "linux/callbacks/gpioCallbacks.h" #include "mission/genericFactory.h" -#include "mission/system/tree/system.h" +#include "mission/system/systemTree.h" #include "mission/tmtc/tmFilters.h" void ObjectFactory::produce(void* args) { @@ -43,8 +44,10 @@ void ObjectFactory::produce(void* args) { q7s::gpioCallbacks::initSpiCsDecoder(gpioComIF); gpioCallbacks::disableAllDecoder(gpioComIF); - new CoreController(objects::CORE_CONTROLLER, I2C_FATAL_ERRORS, enableHkSets); + new CoreController(objects::CORE_CONTROLLER, enableHkSets); createPcduComponents(gpioComIF, &pwrSwitcher, enableHkSets); + satsystem::EIVE_SYSTEM.setI2cRecoveryParams(pwrSwitcher); + auto* stackHandler = new Stack5VHandler(*pwrSwitcher); #if OBSW_ADD_RAD_SENSORS == 1 diff --git a/bsp_q7s/fs/SdCardManager.cpp b/bsp_q7s/fs/SdCardManager.cpp index 89d3aaff..14e3e6aa 100644 --- a/bsp_q7s/fs/SdCardManager.cpp +++ b/bsp_q7s/fs/SdCardManager.cpp @@ -309,32 +309,6 @@ void SdCardManager::resetState() { currentOp = Operations::IDLE; } -ReturnValue_t SdCardManager::updateSdStatePair() { - using namespace std; - - std::error_code e; - if (not filesystem::exists(SD_STATE_FILE, e)) { - return STATUS_FILE_NEXISTS; - } - - // Now the file should exist in any case. Still check whether it exists. - fstream sdStatus(SD_STATE_FILE); - if (not sdStatus.good()) { - return STATUS_FILE_NEXISTS; - } - string line; - uint8_t idx = 0; - sd::SdCard currentSd = sd::SdCard::SLOT_0; - // Process status file line by line - while (std::getline(sdStatus, line)) { - processSdStatusLine(line, idx, currentSd); - } - if (sdStates.first != sd::SdState::MOUNTED && sdStates.second != sd::SdState::MOUNTED) { - sdCardActive = false; - } - return returnvalue::OK; -} - void SdCardManager::processSdStatusLine(std::string& line, uint8_t& idx, sd::SdCard& currentSd) { using namespace std; istringstream iss(line); @@ -407,6 +381,7 @@ ReturnValue_t SdCardManager::setPreferredSdCard(sd::SdCard sdCard) { } ReturnValue_t SdCardManager::updateSdCardStateFile() { + using namespace std; if (cmdExecutor.getCurrentState() == CommandExecutor::States::PENDING) { return CommandExecutor::COMMAND_PENDING; } @@ -414,10 +389,31 @@ ReturnValue_t SdCardManager::updateSdCardStateFile() { std::string updateCmd = "q7hw sd info all > " + std::string(SD_STATE_FILE); cmdExecutor.load(updateCmd, true, printCmdOutput); ReturnValue_t result = cmdExecutor.execute(); - if (blocking and result != returnvalue::OK) { + if (result != returnvalue::OK) { utility::handleSystemError(cmdExecutor.getLastError(), "SdCardManager::mountSdCard"); } - return result; + + std::error_code e; + if (not filesystem::exists(SD_STATE_FILE, e)) { + return STATUS_FILE_NEXISTS; + } + + // Now the file should exist in any case. Still check whether it exists. + fstream sdStatus(SD_STATE_FILE); + if (not sdStatus.good()) { + return STATUS_FILE_NEXISTS; + } + string line; + uint8_t idx = 0; + sd::SdCard currentSd = sd::SdCard::SLOT_0; + // Process status file line by line + while (std::getline(sdStatus, line)) { + processSdStatusLine(line, idx, currentSd); + } + if (sdStates.first != sd::SdState::MOUNTED && sdStates.second != sd::SdState::MOUNTED) { + sdCardActive = false; + } + return returnvalue::OK; } const char* SdCardManager::getCurrentMountPrefix() const { @@ -585,3 +581,8 @@ void SdCardManager::markUnusable() { MutexGuard mg(defaultLock, LOCK_TYPE, OTHER_TIMEOUT, LOCK_CTX); markedUnusable = true; } + +void SdCardManager::markUsable() { + MutexGuard mg(defaultLock, LOCK_TYPE, OTHER_TIMEOUT, LOCK_CTX); + markedUnusable = false; +} diff --git a/bsp_q7s/fs/SdCardManager.h b/bsp_q7s/fs/SdCardManager.h index b7e2a09f..7a4a7cbe 100644 --- a/bsp_q7s/fs/SdCardManager.h +++ b/bsp_q7s/fs/SdCardManager.h @@ -117,16 +117,6 @@ class SdCardManager : public SystemObject, public SdCardMountedIF { ReturnValue_t switchOffSdCard(sd::SdCard sdCard, bool doUnmountSdCard = true, SdStatePair* statusPair = nullptr); - /** - * Update the state file or creates one if it does not exist. You need to call this - * function before calling #sdCardActive - * @return - * - returnvalue::OK if the state file was updated successfully - * - CommandExecutor::COMMAND_PENDING: Non-blocking command is pending - * - returnvalue::FAILED: blocking command failed - */ - ReturnValue_t updateSdCardStateFile(); - /** * Get the state of the SD cards. If the state file does not exist, this function will * take care of updating it. If it does not, the function will use the state file to get @@ -215,6 +205,7 @@ class SdCardManager : public SystemObject, public SdCardMountedIF { ReturnValue_t performFsck(sd::SdCard sdcard, bool printOutput, int& linuxError); void markUnusable(); + void markUsable(); private: CommandExecutor cmdExecutor; @@ -234,7 +225,15 @@ class SdCardManager : public SystemObject, public SdCardMountedIF { SdCardManager(); - ReturnValue_t updateSdStatePair(); + /** + * Update the state file or creates one if it does not exist. You need to call this + * function before calling #sdCardActive + * @return + * - returnvalue::OK if the state file was updated successfully + * - CommandExecutor::COMMAND_PENDING: Non-blocking command is pending + * - returnvalue::FAILED: blocking command failed + */ + ReturnValue_t updateSdCardStateFile(); ReturnValue_t setSdCardState(sd::SdCard sdCard, bool on); diff --git a/bsp_q7s/obsw.cpp b/bsp_q7s/obsw.cpp index d2d640f3..dc547b03 100644 --- a/bsp_q7s/obsw.cpp +++ b/bsp_q7s/obsw.cpp @@ -16,7 +16,7 @@ #include "fsfw/version.h" #include "mission/acs/defs.h" #include "mission/com/defs.h" -#include "mission/system/tree/system.h" +#include "mission/system/systemTree.h" #include "q7sConfig.h" #include "watchdog/definitions.h" diff --git a/dummies/BpxDummy.cpp b/dummies/BpxDummy.cpp index ca546285..085bd841 100644 --- a/dummies/BpxDummy.cpp +++ b/dummies/BpxDummy.cpp @@ -37,19 +37,19 @@ uint32_t BpxDummy::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { return ReturnValue_t BpxDummy::initializeLocalDataPool(localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { - localDataPoolMap.emplace(BpxBattery::BATT_TEMP_1, &battTemp1); - localDataPoolMap.emplace(BpxBattery::BATT_TEMP_2, &battTemp2); - localDataPoolMap.emplace(BpxBattery::BATT_TEMP_3, &battTemp3); - localDataPoolMap.emplace(BpxBattery::BATT_TEMP_4, &battTemp4); - localDataPoolMap.emplace(BpxBattery::CHARGE_CURRENT, &chargeCurrent); - localDataPoolMap.emplace(BpxBattery::DISCHARGE_CURRENT, &dischargeCurrent); - localDataPoolMap.emplace(BpxBattery::HEATER_CURRENT, &heaterCurrent); - localDataPoolMap.emplace(BpxBattery::BATT_VOLTAGE, &battVolt); - localDataPoolMap.emplace(BpxBattery::REBOOT_COUNTER, &rebootCounter); - localDataPoolMap.emplace(BpxBattery::BOOTCAUSE, &bootCause); + localDataPoolMap.emplace(bpxBat::BATT_TEMP_1, &battTemp1); + localDataPoolMap.emplace(bpxBat::BATT_TEMP_2, &battTemp2); + localDataPoolMap.emplace(bpxBat::BATT_TEMP_3, &battTemp3); + localDataPoolMap.emplace(bpxBat::BATT_TEMP_4, &battTemp4); + localDataPoolMap.emplace(bpxBat::CHARGE_CURRENT, &chargeCurrent); + localDataPoolMap.emplace(bpxBat::DISCHARGE_CURRENT, &dischargeCurrent); + localDataPoolMap.emplace(bpxBat::HEATER_CURRENT, &heaterCurrent); + localDataPoolMap.emplace(bpxBat::BATT_VOLTAGE, &battVolt); + localDataPoolMap.emplace(bpxBat::REBOOT_COUNTER, &rebootCounter); + localDataPoolMap.emplace(bpxBat::BOOTCAUSE, &bootCause); - localDataPoolMap.emplace(BpxBattery::BATTERY_HEATER_MODE, &battheatMode); - localDataPoolMap.emplace(BpxBattery::BATTHEAT_LOW_LIMIT, &battheatLow); - localDataPoolMap.emplace(BpxBattery::BATTHEAT_HIGH_LIMIT, &battheatHigh); + localDataPoolMap.emplace(bpxBat::BATTERY_HEATER_MODE, &battheatMode); + localDataPoolMap.emplace(bpxBat::BATTHEAT_LOW_LIMIT, &battheatLow); + localDataPoolMap.emplace(bpxBat::BATTHEAT_HIGH_LIMIT, &battheatHigh); return returnvalue::OK; } diff --git a/dummies/RwDummy.cpp b/dummies/RwDummy.cpp index afc3a54f..0f97f24a 100644 --- a/dummies/RwDummy.cpp +++ b/dummies/RwDummy.cpp @@ -7,9 +7,9 @@ RwDummy::RwDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie) RwDummy::~RwDummy() {} -void RwDummy::doStartUp() {} +void RwDummy::doStartUp() { setMode(MODE_ON); } -void RwDummy::doShutDown() {} +void RwDummy::doShutDown() { setMode(MODE_OFF); } ReturnValue_t RwDummy::buildNormalDeviceCommand(DeviceCommandId_t *id) { return NOTHING_TO_SEND; } diff --git a/dummies/StarTrackerDummy.cpp b/dummies/StarTrackerDummy.cpp index 937b3422..d70c9a1b 100644 --- a/dummies/StarTrackerDummy.cpp +++ b/dummies/StarTrackerDummy.cpp @@ -7,9 +7,9 @@ StarTrackerDummy::StarTrackerDummy(object_id_t objectId, object_id_t comif, Cook StarTrackerDummy::~StarTrackerDummy() {} -void StarTrackerDummy::doStartUp() {} +void StarTrackerDummy::doStartUp() { setMode(MODE_ON); } -void StarTrackerDummy::doShutDown() {} +void StarTrackerDummy::doShutDown() { setMode(_MODE_POWER_DOWN); } ReturnValue_t StarTrackerDummy::buildNormalDeviceCommand(DeviceCommandId_t *id) { return NOTHING_TO_SEND; diff --git a/fsfw b/fsfw index 6650c293..285d327b 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit 6650c293da09d8851c2bd6c4d6e6c5a8390d003e +Subproject commit 285d327b97514946f0714e477289f67ee8bd413f diff --git a/generators/bsp_hosted_events.csv b/generators/bsp_hosted_events.csv index d7265738..af15edff 100644 --- a/generators/bsp_hosted_events.csv +++ b/generators/bsp_hosted_events.csv @@ -101,8 +101,8 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path 11401;0x2c89;GPIO_PULL_LOW_FAILED;LOW;No description;mission/tcs/HeaterHandler.h 11402;0x2c8a;HEATER_WENT_ON;INFO;No description;mission/tcs/HeaterHandler.h 11403;0x2c8b;HEATER_WENT_OFF;INFO;No description;mission/tcs/HeaterHandler.h -11404;0x2c8c;SWITCH_ALREADY_ON;LOW;No description;mission/tcs/HeaterHandler.h -11405;0x2c8d;SWITCH_ALREADY_OFF;LOW;No description;mission/tcs/HeaterHandler.h +11404;0x2c8c;SWITCH_ALREADY_ON;INFO;No description;mission/tcs/HeaterHandler.h +11405;0x2c8d;SWITCH_ALREADY_OFF;INFO;No description;mission/tcs/HeaterHandler.h 11406;0x2c8e;MAIN_SWITCH_TIMEOUT;MEDIUM;No description;mission/tcs/HeaterHandler.h 11407;0x2c8f;FAULTY_HEATER_WAS_ON;LOW;No description;mission/tcs/HeaterHandler.h 11500;0x2cec;BURN_PHASE_START;INFO;P1: Burn duration in milliseconds, P2: Dry run flag;mission/SolarArrayDeploymentHandler.h @@ -251,16 +251,17 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path 13903;0x364f;INSERT_CONFIGFILEVALUE_FAILED;MEDIUM;No description;mission/utility/GlobalConfigHandler.h 13904;0x3650;WRITE_CONFIGFILE_FAILED;MEDIUM;No description;mission/utility/GlobalConfigHandler.h 13905;0x3651;READ_CONFIGFILE_FAILED;MEDIUM;No description;mission/utility/GlobalConfigHandler.h -14000;0x36b0;ALLOC_FAILURE;MEDIUM;No description;bsp_q7s/core/CoreController.h -14001;0x36b1;REBOOT_SW;LOW; Software reboot occurred. Can also be a systemd reboot. P1: Current Chip, P2: Current Copy;bsp_q7s/core/CoreController.h -14002;0x36b2;REBOOT_MECHANISM_TRIGGERED;MEDIUM;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;bsp_q7s/core/CoreController.h -14003;0x36b3;REBOOT_HW;MEDIUM;No description;bsp_q7s/core/CoreController.h -14004;0x36b4;NO_SD_CARD_ACTIVE;HIGH;No SD card was active. Core controller will attempt to re-initialize a SD card.;bsp_q7s/core/CoreController.h -14005;0x36b5;VERSION_INFO;INFO;P1: Byte 0: Major, Byte 1: Minor, Byte 2: Patch, Byte 3: Has Git Hash P2: First four letters of Git SHA is the last byte of P1 is set.;bsp_q7s/core/CoreController.h -14006;0x36b6;CURRENT_IMAGE_INFO;INFO;P1: Current Chip, P2: Current Copy;bsp_q7s/core/CoreController.h -14007;0x36b7;REBOOT_COUNTER;INFO;Total reboot counter, which is the sum of the boot count of all individual images.;bsp_q7s/core/CoreController.h -14008;0x36b8;INDIVIDUAL_BOOT_COUNTS;INFO;Get the boot count of the individual images. P1: First 16 bits boot count of image 0 0, last 16 bits boot count of image 0 1. P2: First 16 bits boot count of image 1 0, last 16 bits boot count of image 1 1.;bsp_q7s/core/CoreController.h -14010;0x36ba;I2C_UNAVAILABLE_REBOOT;MEDIUM;No description;bsp_q7s/core/CoreController.h +14000;0x36b0;ALLOC_FAILURE;MEDIUM;No description;mission/sysDefs.h +14001;0x36b1;REBOOT_SW;LOW; Software reboot occurred. Can also be a systemd reboot. P1: Current Chip, P2: Current Copy;mission/sysDefs.h +14002;0x36b2;REBOOT_MECHANISM_TRIGGERED;MEDIUM;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;mission/sysDefs.h +14003;0x36b3;REBOOT_HW;MEDIUM;No description;mission/sysDefs.h +14004;0x36b4;NO_SD_CARD_ACTIVE;HIGH;No SD card was active. Core controller will attempt to re-initialize a SD card.;mission/sysDefs.h +14005;0x36b5;VERSION_INFO;INFO;P1: Byte 0: Major, Byte 1: Minor, Byte 2: Patch, Byte 3: Has Git Hash P2: First four letters of Git SHA is the last byte of P1 is set.;mission/sysDefs.h +14006;0x36b6;CURRENT_IMAGE_INFO;INFO;P1: Current Chip, P2: Current Copy;mission/sysDefs.h +14007;0x36b7;REBOOT_COUNTER;INFO;Total reboot counter, which is the sum of the boot count of all individual images.;mission/sysDefs.h +14008;0x36b8;INDIVIDUAL_BOOT_COUNTS;INFO;Get the boot count of the individual images. P1: First 16 bits boot count of image 0 0, last 16 bits boot count of image 0 1. P2: First 16 bits boot count of image 1 0, last 16 bits boot count of image 1 1.;mission/sysDefs.h +14010;0x36ba;TRYING_I2C_RECOVERY;MEDIUM;I2C is unavailable. Trying recovery of I2C bus by power cycling all I2C devices.;mission/sysDefs.h +14011;0x36bb;I2C_REBOOT;MEDIUM;I2C is unavailable. Recovery did not work, performing full reboot.;mission/sysDefs.h 14100;0x3714;NO_VALID_SENSOR_TEMPERATURE;MEDIUM;No description;mission/controller/tcsDefs.h 14101;0x3715;NO_HEALTHY_HEATER_AVAILABLE;MEDIUM;No description;mission/controller/tcsDefs.h 14102;0x3716;SYRLINKS_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h diff --git a/generators/bsp_hosted_returnvalues.csv b/generators/bsp_hosted_returnvalues.csv index 0b20221c..5b8cb74b 100644 --- a/generators/bsp_hosted_returnvalues.csv +++ b/generators/bsp_hosted_returnvalues.csv @@ -371,8 +371,8 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path 0x3e03;HKM_PeriodicHelperInvalid;No description;3;HOUSEKEEPING_MANAGER;fsfw/src/fsfw/datapoollocal/LocalDataPoolManager.h 0x3e04;HKM_PoolobjectNotFound;No description;4;HOUSEKEEPING_MANAGER;fsfw/src/fsfw/datapoollocal/LocalDataPoolManager.h 0x3e05;HKM_DatasetNotFound;No description;5;HOUSEKEEPING_MANAGER;fsfw/src/fsfw/datapoollocal/LocalDataPoolManager.h -0x3f01;DLEE_NoPacketFound;No description;1;DLE_ENCODER;fsfw/src/fsfw/globalfunctions/DleParser.h -0x3f02;DLEE_PossiblePacketLoss;No description;2;DLE_ENCODER;fsfw/src/fsfw/globalfunctions/DleParser.h +0x3f01;DLEE_StreamTooShort;No description;1;DLE_ENCODER;fsfw/src/fsfw/globalfunctions/DleEncoder.h +0x3f02;DLEE_DecodingError;No description;2;DLE_ENCODER;fsfw/src/fsfw/globalfunctions/DleEncoder.h 0x4201;PUS11_InvalidTypeTimeWindow;No description;1;PUS_SERVICE_11;fsfw/src/fsfw/pus/Service11TelecommandScheduling.h 0x4202;PUS11_InvalidTimeWindow;No description;2;PUS_SERVICE_11;fsfw/src/fsfw/pus/Service11TelecommandScheduling.h 0x4203;PUS11_TimeshiftingNotPossible;No description;3;PUS_SERVICE_11;fsfw/src/fsfw/pus/Service11TelecommandScheduling.h @@ -402,9 +402,12 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path 0x4403;UXOS_CommandError;Command execution failed;3;LINUX_OSAL;fsfw/src/fsfw_hal/linux/CommandExecutor.h 0x4404;UXOS_NoCommandLoadedOrPending;;4;LINUX_OSAL;fsfw/src/fsfw_hal/linux/CommandExecutor.h 0x4406;UXOS_PcloseCallError;No description;6;LINUX_OSAL;fsfw/src/fsfw_hal/linux/CommandExecutor.h -0x4500;HSPI_OpeningFileFailed;No description;0;HAL_SPI;fsfw/src/fsfw_hal/linux/spi/SpiComIF.h -0x4501;HSPI_FullDuplexTransferFailed;No description;1;HAL_SPI;fsfw/src/fsfw_hal/linux/spi/SpiComIF.h -0x4502;HSPI_HalfDuplexTransferFailed;No description;2;HAL_SPI;fsfw/src/fsfw_hal/linux/spi/SpiComIF.h +0x4500;HSPI_OpeningFileFailed;No description;0;HAL_SPI;fsfw/src/fsfw_hal/common/spi/spiCommon.h +0x4501;HSPI_FullDuplexTransferFailed;No description;1;HAL_SPI;fsfw/src/fsfw_hal/common/spi/spiCommon.h +0x4502;HSPI_HalfDuplexTransferFailed;No description;2;HAL_SPI;fsfw/src/fsfw_hal/common/spi/spiCommon.h +0x4503;HSPI_Timeout;No description;3;HAL_SPI;fsfw/src/fsfw_hal/common/spi/spiCommon.h +0x4504;HSPI_Busy;No description;4;HAL_SPI;fsfw/src/fsfw_hal/common/spi/spiCommon.h +0x4505;HSPI_GenericError;No description;5;HAL_SPI;fsfw/src/fsfw_hal/common/spi/spiCommon.h 0x4601;HURT_UartReadFailure;No description;1;HAL_UART;fsfw/src/fsfw_hal/linux/serial/SerialComIF.h 0x4602;HURT_UartReadSizeMissmatch;No description;2;HAL_UART;fsfw/src/fsfw_hal/linux/serial/SerialComIF.h 0x4603;HURT_UartRxBufferTooSmall;No description;3;HAL_UART;fsfw/src/fsfw_hal/linux/serial/SerialComIF.h diff --git a/generators/bsp_q7s_events.csv b/generators/bsp_q7s_events.csv index d7265738..af15edff 100644 --- a/generators/bsp_q7s_events.csv +++ b/generators/bsp_q7s_events.csv @@ -101,8 +101,8 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path 11401;0x2c89;GPIO_PULL_LOW_FAILED;LOW;No description;mission/tcs/HeaterHandler.h 11402;0x2c8a;HEATER_WENT_ON;INFO;No description;mission/tcs/HeaterHandler.h 11403;0x2c8b;HEATER_WENT_OFF;INFO;No description;mission/tcs/HeaterHandler.h -11404;0x2c8c;SWITCH_ALREADY_ON;LOW;No description;mission/tcs/HeaterHandler.h -11405;0x2c8d;SWITCH_ALREADY_OFF;LOW;No description;mission/tcs/HeaterHandler.h +11404;0x2c8c;SWITCH_ALREADY_ON;INFO;No description;mission/tcs/HeaterHandler.h +11405;0x2c8d;SWITCH_ALREADY_OFF;INFO;No description;mission/tcs/HeaterHandler.h 11406;0x2c8e;MAIN_SWITCH_TIMEOUT;MEDIUM;No description;mission/tcs/HeaterHandler.h 11407;0x2c8f;FAULTY_HEATER_WAS_ON;LOW;No description;mission/tcs/HeaterHandler.h 11500;0x2cec;BURN_PHASE_START;INFO;P1: Burn duration in milliseconds, P2: Dry run flag;mission/SolarArrayDeploymentHandler.h @@ -251,16 +251,17 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path 13903;0x364f;INSERT_CONFIGFILEVALUE_FAILED;MEDIUM;No description;mission/utility/GlobalConfigHandler.h 13904;0x3650;WRITE_CONFIGFILE_FAILED;MEDIUM;No description;mission/utility/GlobalConfigHandler.h 13905;0x3651;READ_CONFIGFILE_FAILED;MEDIUM;No description;mission/utility/GlobalConfigHandler.h -14000;0x36b0;ALLOC_FAILURE;MEDIUM;No description;bsp_q7s/core/CoreController.h -14001;0x36b1;REBOOT_SW;LOW; Software reboot occurred. Can also be a systemd reboot. P1: Current Chip, P2: Current Copy;bsp_q7s/core/CoreController.h -14002;0x36b2;REBOOT_MECHANISM_TRIGGERED;MEDIUM;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;bsp_q7s/core/CoreController.h -14003;0x36b3;REBOOT_HW;MEDIUM;No description;bsp_q7s/core/CoreController.h -14004;0x36b4;NO_SD_CARD_ACTIVE;HIGH;No SD card was active. Core controller will attempt to re-initialize a SD card.;bsp_q7s/core/CoreController.h -14005;0x36b5;VERSION_INFO;INFO;P1: Byte 0: Major, Byte 1: Minor, Byte 2: Patch, Byte 3: Has Git Hash P2: First four letters of Git SHA is the last byte of P1 is set.;bsp_q7s/core/CoreController.h -14006;0x36b6;CURRENT_IMAGE_INFO;INFO;P1: Current Chip, P2: Current Copy;bsp_q7s/core/CoreController.h -14007;0x36b7;REBOOT_COUNTER;INFO;Total reboot counter, which is the sum of the boot count of all individual images.;bsp_q7s/core/CoreController.h -14008;0x36b8;INDIVIDUAL_BOOT_COUNTS;INFO;Get the boot count of the individual images. P1: First 16 bits boot count of image 0 0, last 16 bits boot count of image 0 1. P2: First 16 bits boot count of image 1 0, last 16 bits boot count of image 1 1.;bsp_q7s/core/CoreController.h -14010;0x36ba;I2C_UNAVAILABLE_REBOOT;MEDIUM;No description;bsp_q7s/core/CoreController.h +14000;0x36b0;ALLOC_FAILURE;MEDIUM;No description;mission/sysDefs.h +14001;0x36b1;REBOOT_SW;LOW; Software reboot occurred. Can also be a systemd reboot. P1: Current Chip, P2: Current Copy;mission/sysDefs.h +14002;0x36b2;REBOOT_MECHANISM_TRIGGERED;MEDIUM;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;mission/sysDefs.h +14003;0x36b3;REBOOT_HW;MEDIUM;No description;mission/sysDefs.h +14004;0x36b4;NO_SD_CARD_ACTIVE;HIGH;No SD card was active. Core controller will attempt to re-initialize a SD card.;mission/sysDefs.h +14005;0x36b5;VERSION_INFO;INFO;P1: Byte 0: Major, Byte 1: Minor, Byte 2: Patch, Byte 3: Has Git Hash P2: First four letters of Git SHA is the last byte of P1 is set.;mission/sysDefs.h +14006;0x36b6;CURRENT_IMAGE_INFO;INFO;P1: Current Chip, P2: Current Copy;mission/sysDefs.h +14007;0x36b7;REBOOT_COUNTER;INFO;Total reboot counter, which is the sum of the boot count of all individual images.;mission/sysDefs.h +14008;0x36b8;INDIVIDUAL_BOOT_COUNTS;INFO;Get the boot count of the individual images. P1: First 16 bits boot count of image 0 0, last 16 bits boot count of image 0 1. P2: First 16 bits boot count of image 1 0, last 16 bits boot count of image 1 1.;mission/sysDefs.h +14010;0x36ba;TRYING_I2C_RECOVERY;MEDIUM;I2C is unavailable. Trying recovery of I2C bus by power cycling all I2C devices.;mission/sysDefs.h +14011;0x36bb;I2C_REBOOT;MEDIUM;I2C is unavailable. Recovery did not work, performing full reboot.;mission/sysDefs.h 14100;0x3714;NO_VALID_SENSOR_TEMPERATURE;MEDIUM;No description;mission/controller/tcsDefs.h 14101;0x3715;NO_HEALTHY_HEATER_AVAILABLE;MEDIUM;No description;mission/controller/tcsDefs.h 14102;0x3716;SYRLINKS_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h diff --git a/generators/bsp_q7s_returnvalues.csv b/generators/bsp_q7s_returnvalues.csv index 0f87fdbe..fcb4a5ee 100644 --- a/generators/bsp_q7s_returnvalues.csv +++ b/generators/bsp_q7s_returnvalues.csv @@ -371,8 +371,8 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path 0x3e03;HKM_PeriodicHelperInvalid;No description;3;HOUSEKEEPING_MANAGER;fsfw/src/fsfw/datapoollocal/LocalDataPoolManager.h 0x3e04;HKM_PoolobjectNotFound;No description;4;HOUSEKEEPING_MANAGER;fsfw/src/fsfw/datapoollocal/LocalDataPoolManager.h 0x3e05;HKM_DatasetNotFound;No description;5;HOUSEKEEPING_MANAGER;fsfw/src/fsfw/datapoollocal/LocalDataPoolManager.h -0x3f01;DLEE_NoPacketFound;No description;1;DLE_ENCODER;fsfw/src/fsfw/globalfunctions/DleParser.h -0x3f02;DLEE_PossiblePacketLoss;No description;2;DLE_ENCODER;fsfw/src/fsfw/globalfunctions/DleParser.h +0x3f01;DLEE_StreamTooShort;No description;1;DLE_ENCODER;fsfw/src/fsfw/globalfunctions/DleEncoder.h +0x3f02;DLEE_DecodingError;No description;2;DLE_ENCODER;fsfw/src/fsfw/globalfunctions/DleEncoder.h 0x4201;PUS11_InvalidTypeTimeWindow;No description;1;PUS_SERVICE_11;fsfw/src/fsfw/pus/Service11TelecommandScheduling.h 0x4202;PUS11_InvalidTimeWindow;No description;2;PUS_SERVICE_11;fsfw/src/fsfw/pus/Service11TelecommandScheduling.h 0x4203;PUS11_TimeshiftingNotPossible;No description;3;PUS_SERVICE_11;fsfw/src/fsfw/pus/Service11TelecommandScheduling.h @@ -402,9 +402,12 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path 0x4403;UXOS_CommandError;Command execution failed;3;LINUX_OSAL;fsfw/src/fsfw_hal/linux/CommandExecutor.h 0x4404;UXOS_NoCommandLoadedOrPending;;4;LINUX_OSAL;fsfw/src/fsfw_hal/linux/CommandExecutor.h 0x4406;UXOS_PcloseCallError;No description;6;LINUX_OSAL;fsfw/src/fsfw_hal/linux/CommandExecutor.h -0x4500;HSPI_OpeningFileFailed;No description;0;HAL_SPI;fsfw/src/fsfw_hal/linux/spi/SpiComIF.h -0x4501;HSPI_FullDuplexTransferFailed;No description;1;HAL_SPI;fsfw/src/fsfw_hal/linux/spi/SpiComIF.h -0x4502;HSPI_HalfDuplexTransferFailed;No description;2;HAL_SPI;fsfw/src/fsfw_hal/linux/spi/SpiComIF.h +0x4500;HSPI_OpeningFileFailed;No description;0;HAL_SPI;fsfw/src/fsfw_hal/common/spi/spiCommon.h +0x4501;HSPI_FullDuplexTransferFailed;No description;1;HAL_SPI;fsfw/src/fsfw_hal/common/spi/spiCommon.h +0x4502;HSPI_HalfDuplexTransferFailed;No description;2;HAL_SPI;fsfw/src/fsfw_hal/common/spi/spiCommon.h +0x4503;HSPI_Timeout;No description;3;HAL_SPI;fsfw/src/fsfw_hal/common/spi/spiCommon.h +0x4504;HSPI_Busy;No description;4;HAL_SPI;fsfw/src/fsfw_hal/common/spi/spiCommon.h +0x4505;HSPI_GenericError;No description;5;HAL_SPI;fsfw/src/fsfw_hal/common/spi/spiCommon.h 0x4601;HURT_UartReadFailure;No description;1;HAL_UART;fsfw/src/fsfw_hal/linux/serial/SerialComIF.h 0x4602;HURT_UartReadSizeMissmatch;No description;2;HAL_UART;fsfw/src/fsfw_hal/linux/serial/SerialComIF.h 0x4603;HURT_UartRxBufferTooSmall;No description;3;HAL_UART;fsfw/src/fsfw_hal/linux/serial/SerialComIF.h @@ -493,8 +496,6 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path 0x58a3;SUSS_ExecutionFailed;Command execution failed;163;SUS_HANDLER;mission/acs/RwHandler.h 0x58a4;SUSS_CrcError;Reaction wheel reply has invalid crc;164;SUS_HANDLER;mission/acs/RwHandler.h 0x58a5;SUSS_ValueNotRead;No description;165;SUS_HANDLER;mission/acs/RwHandler.h -0x5900;IPCI_NoReplyAvailable;No description;0;CCSDS_IP_CORE_BRIDGE;linux/acs/ImtqPollingTask.h -0x5901;IPCI_NoPacketFound;No description;1;CCSDS_IP_CORE_BRIDGE;linux/com/SyrlinksComHandler.h 0x59a0;IPCI_PapbBusy;No description;160;CCSDS_IP_CORE_BRIDGE;linux/ipcore/PapbVcInterface.h 0x5aa0;PTME_UnknownVcId;No description;160;PTME;linux/ipcore/Ptme.h 0x5c01;STRHLP_SdNotMounted;SD card specified in path string not mounted;1;STR_HELPER;linux/acs/StrComHandler.h @@ -542,7 +543,6 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path 0x63a0;NVMB_KeyNotExists;Specified key does not exist in json file;160;NVM_PARAM_BASE;mission/memory/NvmParameterBase.h 0x64a0;FSHLP_SdNotMounted;SD card specified with path string not mounted;160;FILE_SYSTEM_HELPER;bsp_q7s/fs/FilesystemHelper.h 0x64a1;FSHLP_FileNotExists;Specified file does not exist on filesystem;161;FILE_SYSTEM_HELPER;bsp_q7s/fs/FilesystemHelper.h -0x6502;PLMPHLP_InvalidCrc;No description;2;PLOC_MPSOC_HELPER;linux/payload/ScexHelper.h 0x65a0;PLMPHLP_FileClosedAccidentally;File accidentally close;160;PLOC_MPSOC_HELPER;linux/payload/PlocMpsocHelper.h 0x66a0;SADPL_CommandNotSupported;No description;160;SA_DEPL_HANDLER;mission/SolarArrayDeploymentHandler.h 0x66a1;SADPL_DeploymentAlreadyExecuting;No description;161;SA_DEPL_HANDLER;mission/SolarArrayDeploymentHandler.h diff --git a/generators/events/translateEvents.cpp b/generators/events/translateEvents.cpp index 25c6c39d..c4b537e8 100644 --- a/generators/events/translateEvents.cpp +++ b/generators/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** - * @brief Auto-generated event translation file. Contains 284 translations. + * @brief Auto-generated event translation file. Contains 285 translations. * @details - * Generated on: 2023-04-04 13:59:07 + * Generated on: 2023-04-07 17:42:57 */ #include "translateEvents.h" @@ -266,7 +266,8 @@ const char *VERSION_INFO_STRING = "VERSION_INFO"; const char *CURRENT_IMAGE_INFO_STRING = "CURRENT_IMAGE_INFO"; const char *REBOOT_COUNTER_STRING = "REBOOT_COUNTER"; const char *INDIVIDUAL_BOOT_COUNTS_STRING = "INDIVIDUAL_BOOT_COUNTS"; -const char *I2C_UNAVAILABLE_REBOOT_STRING = "I2C_UNAVAILABLE_REBOOT"; +const char *TRYING_I2C_RECOVERY_STRING = "TRYING_I2C_RECOVERY"; +const char *I2C_REBOOT_STRING = "I2C_REBOOT"; const char *NO_VALID_SENSOR_TEMPERATURE_STRING = "NO_VALID_SENSOR_TEMPERATURE"; const char *NO_HEALTHY_HEATER_AVAILABLE_STRING = "NO_HEALTHY_HEATER_AVAILABLE"; const char *SYRLINKS_OVERHEATING_STRING = "SYRLINKS_OVERHEATING"; @@ -815,7 +816,9 @@ const char *translateEvents(Event event) { case (14008): return INDIVIDUAL_BOOT_COUNTS_STRING; case (14010): - return I2C_UNAVAILABLE_REBOOT_STRING; + return TRYING_I2C_RECOVERY_STRING; + case (14011): + return I2C_REBOOT_STRING; case (14100): return NO_VALID_SENSOR_TEMPERATURE_STRING; case (14101): diff --git a/generators/objects/translateObjects.cpp b/generators/objects/translateObjects.cpp index c579b741..76ce0db3 100644 --- a/generators/objects/translateObjects.cpp +++ b/generators/objects/translateObjects.cpp @@ -2,7 +2,7 @@ * @brief Auto-generated object translation file. * @details * Contains 175 translations. - * Generated on: 2023-04-04 13:59:07 + * Generated on: 2023-04-07 17:42:57 */ #include "translateObjects.h" diff --git a/linux/acs/AcsBoardPolling.cpp b/linux/acs/AcsBoardPolling.cpp index 1013f24b..b289ef70 100644 --- a/linux/acs/AcsBoardPolling.cpp +++ b/linux/acs/AcsBoardPolling.cpp @@ -373,7 +373,7 @@ ReturnValue_t AcsBoardPolling::readAdisCfg(SpiCookie& cookie, size_t transferLen std::string device = spiComIF.getSpiDev(); UnixFileGuard fileHelper(device, fileDescriptor, O_RDWR, "SpiComIF::sendMessage"); if (fileHelper.getOpenResult() != returnvalue::OK) { - return SpiComIF::OPENING_FILE_FAILED; + return spi::OPENING_FILE_FAILED; } spi::SpiModes spiMode = spi::SpiModes::MODE_0; uint32_t spiSpeed = 0; @@ -416,7 +416,7 @@ ReturnValue_t AcsBoardPolling::readAdisCfg(SpiCookie& cookie, size_t transferLen retval = ioctl(fileDescriptor, SPI_IOC_MESSAGE(1), cookie.getTransferStructHandle()); if (retval < 0) { utility::handleIoctlError("SpiComIF::sendMessage: ioctl error."); - result = SpiComIF::FULL_DUPLEX_TRANSFER_FAILED; + result = spi::FULL_DUPLEX_TRANSFER_FAILED; } #if FSFW_HAL_SPI_WIRETAPPING == 1 comIf->performSpiWiretapping(cookie); diff --git a/linux/acs/ImtqPollingTask.h b/linux/acs/ImtqPollingTask.h index 8ffe307b..914343d6 100644 --- a/linux/acs/ImtqPollingTask.h +++ b/linux/acs/ImtqPollingTask.h @@ -22,6 +22,7 @@ class ImtqPollingTask : public SystemObject, ReturnValue_t initialize() override; private: + //! [EXPORT] : [SKIP] static constexpr ReturnValue_t NO_REPLY_AVAILABLE = returnvalue::makeCode(2, 0); enum class InternalState { IDLE, IS_BUSY } state = InternalState::IDLE; diff --git a/linux/acs/RwPollingTask.cpp b/linux/acs/RwPollingTask.cpp index 07958d8b..126ad0ea 100644 --- a/linux/acs/RwPollingTask.cpp +++ b/linux/acs/RwPollingTask.cpp @@ -11,6 +11,7 @@ #include #include "devConf.h" +#include "mission/acs/defs.h" #include "mission/acs/rwHelpers.h" RwPollingTask::RwPollingTask(object_id_t objectId, const char* spiDev, GpioIF& gpioIF) @@ -35,6 +36,7 @@ ReturnValue_t RwPollingTask::performOperation(uint8_t operationCode) { semaphore->acquire(); // This loop takes 50 ms on a debug build. // Stopwatch watch; + // Give all device handlers some time to submit requests. TaskFactory::delayTask(5); int fd = 0; for (auto& skip : skipCommandingForRw) { @@ -45,13 +47,24 @@ ReturnValue_t RwPollingTask::performOperation(uint8_t operationCode) { if (result != returnvalue::OK) { continue; } + acs::SimpleSensorMode currentMode; + rws::SpecialRwRequest specialRequest; + for (unsigned idx = 0; idx < rwCookies.size(); idx++) { - if (rwCookies[idx]->specialRequest == rws::SpecialRwRequest::RESET_MCU) { + { + MutexGuard mg(ipcLock); + currentMode = rwRequests[idx].mode; + specialRequest = rwRequests[idx].specialRequest; + skipSetSpeedReply[idx] = rwRequests[idx].setSpeed; + } + if (currentMode == acs::SimpleSensorMode::OFF) { + skipCommandingForRw[idx] = true; + } else if (specialRequest == rws::SpecialRwRequest::RESET_MCU) { prepareSimpleCommand(rws::RESET_MCU); // No point in commanding that specific RW for the cycle. skipCommandingForRw[idx] = true; writeOneRwCmd(idx, fd); - } else if (rwCookies[idx]->setSpeed) { + } else if (skipSetSpeedReply[idx]) { prepareSetSpeedCmd(idx); if (writeOneRwCmd(idx, fd) != returnvalue::OK) { continue; @@ -121,31 +134,14 @@ ReturnValue_t RwPollingTask::initializeInterface(CookieIF* cookie) { ReturnValue_t RwPollingTask::sendMessage(CookieIF* cookie, const uint8_t* sendData, size_t sendLen) { - if (sendData == nullptr or sendLen < 8) { + if (sendData == nullptr or sendLen != sizeof(rws::RwRequest)) { return DeviceHandlerIF::INVALID_DATA; } - int32_t speed = 0; - uint16_t rampTime = 0; - const uint8_t* currentBuf = sendData; - bool setSpeed = currentBuf[0]; - currentBuf += 1; - sendLen -= 1; - SerializeAdapter::deSerialize(&speed, ¤tBuf, &sendLen, SerializeIF::Endianness::MACHINE); - SerializeAdapter::deSerialize(&rampTime, ¤tBuf, &sendLen, SerializeIF::Endianness::MACHINE); - rws::SpecialRwRequest specialRequest = rws::SpecialRwRequest::REQUEST_NONE; - if (sendLen == 8 and sendData[7] < static_cast(rws::SpecialRwRequest::NUM_REQUESTS)) { - specialRequest = static_cast(sendData[7]); - } - RwCookie* rwCookie = dynamic_cast(cookie); - if (rwCookie == nullptr) { - return returnvalue::FAILED; - } + const rws::RwRequest* rwRequest = reinterpret_cast(sendData); + uint8_t rwIdx = rwRequest->rwIdx; { MutexGuard mg(ipcLock); - rwCookie->setSpeed = setSpeed; - rwCookie->currentRwSpeed = speed; - rwCookie->currentRampTime = rampTime; - rwCookie->specialRequest = specialRequest; + std::memcpy(&rwRequests[rwIdx], rwRequest, sizeof(rws::RwRequest)); if (state == InternalState::IDLE) { state = InternalState::IS_BUSY; semaphore->release(); @@ -202,7 +198,7 @@ ReturnValue_t RwPollingTask::openSpi(int flags, int& fd) { fd = open(spiDev, flags); if (fd < 0) { sif::error << "RwPollingTask::openSpi: Failed to open device file" << std::endl; - return SpiComIF::OPENING_FILE_FAILED; + return spi::OPENING_FILE_FAILED; } return returnvalue::OK; @@ -332,7 +328,7 @@ ReturnValue_t RwPollingTask::writeOneRwCmd(uint8_t rwIdx, int fd) { ReturnValue_t RwPollingTask::readAllRws(DeviceCommandId_t id) { // SPI dev will be opened in readNextReply on demand. for (unsigned idx = 0; idx < rwCookies.size(); idx++) { - if (((id == rws::SET_SPEED) and !rwCookies[idx]->setSpeed) or skipCommandingForRw[idx]) { + if (((id == rws::SET_SPEED) and !skipSetSpeedReply[idx]) or skipCommandingForRw[idx]) { continue; } uint8_t* replyBuf; @@ -395,7 +391,7 @@ void RwPollingTask::fillSpecialRequestArray() { specialRequestIds[idx] = DeviceHandlerIF::NO_COMMAND_ID; continue; } - switch (rwCookies[idx]->specialRequest) { + switch (rwRequests[idx].specialRequest) { case (rws::SpecialRwRequest::GET_TM): { specialRequestIds[idx] = rws::GET_TM; break; @@ -426,14 +422,14 @@ void RwPollingTask::handleSpecialRequests() { writeOneRwCmd(idx, fd); } closeSpi(fd); - usleep(rws::SPI_REPLY_DELAY); for (unsigned idx = 0; idx < rwCookies.size(); idx++) { if (specialRequestIds[idx] == DeviceHandlerIF::NO_COMMAND_ID) { continue; } uint8_t* replyBuf; size_t maxReadLen = idAndIdxToReadBuffer(specialRequestIds[idx], idx, &replyBuf); - result = readNextReply(*rwCookies[idx], replyBuf, maxReadLen); + // Skip first byte for actual read buffer: Valid byte + result = readNextReply(*rwCookies[idx], replyBuf + 1, maxReadLen); if (result == returnvalue::OK) { // The first byte is always a flag which shows whether the value was read // properly at least once. @@ -455,17 +451,12 @@ void RwPollingTask::setAllReadFlagsFalse() { } } -// This closes the SPI -void RwPollingTask::closeSpi(int fd) { - // This will perform the function to close the SPI - close(fd); - // The SPI is now closed. -} +void RwPollingTask::closeSpi(int fd) { close(fd); } ReturnValue_t RwPollingTask::sendOneMessage(int fd, RwCookie& rwCookie) { gpioId_t gpioId = rwCookie.getChipSelectPin(); if (spiLock == nullptr) { - sif::debug << "rwSpiCallback::spiCallback: Mutex or GPIO interface invalid" << std::endl; + sif::warning << "RwPollingTask: Mutex or GPIO interface invalid" << std::endl; return returnvalue::FAILED; } // Add datalinklayer like specified in the datasheet. @@ -473,7 +464,7 @@ ReturnValue_t RwPollingTask::sendOneMessage(int fd, RwCookie& rwCookie) { rws::encodeHdlc(writeBuffer.data(), writeLen, encodedBuffer.data(), lenToSend); pullCsLow(gpioId, gpioIF); if (write(fd, encodedBuffer.data(), lenToSend) != static_cast(lenToSend)) { - sif::error << "rwSpiCallback::spiCallback: Write failed!" << std::endl; + sif::error << "RwPollingTask: Write failed!" << std::endl; pullCsHigh(gpioId, gpioIF); return rws::SPI_WRITE_FAILURE; } @@ -484,7 +475,7 @@ ReturnValue_t RwPollingTask::sendOneMessage(int fd, RwCookie& rwCookie) { ReturnValue_t RwPollingTask::pullCsLow(gpioId_t gpioId, GpioIF& gpioIF) { ReturnValue_t result = spiLock->lockMutex(TIMEOUT_TYPE, TIMEOUT_MS); if (result != returnvalue::OK) { - sif::debug << "RwPollingTask::pullCsLow: Failed to lock mutex" << std::endl; + sif::warning << "RwPollingTask::pullCsLow: Failed to lock mutex" << std::endl; return result; } // Pull SPI CS low. For now, no support for active high given @@ -525,8 +516,8 @@ ReturnValue_t RwPollingTask::prepareSetSpeedCmd(uint8_t rwIdx) { uint16_t rampTimeToSet = 10; { MutexGuard mg(ipcLock); - speedToSet = rwCookies[rwIdx]->currentRwSpeed; - rampTimeToSet = rwCookies[rwIdx]->currentRampTime; + speedToSet = rwRequests[rwIdx].currentRwSpeed; + rampTimeToSet = rwRequests[rwIdx].currentRampTime; } size_t serLen = 1; SerializeAdapter::serialize(&speedToSet, &serPtr, &serLen, writeBuffer.size(), diff --git a/linux/acs/RwPollingTask.h b/linux/acs/RwPollingTask.h index 5fb25d1d..f06bc622 100644 --- a/linux/acs/RwPollingTask.h +++ b/linux/acs/RwPollingTask.h @@ -8,6 +8,7 @@ #include #include #include +#include #include "mission/acs/rwHelpers.h" @@ -26,10 +27,6 @@ class RwCookie : public SpiCookie { std::array replyBuf{}; std::array exchangeBuf{}; MutexIF* bufLock; - bool setSpeed = true; - int32_t currentRwSpeed = 0; - uint16_t currentRampTime = 0; - rws::SpecialRwRequest specialRequest = rws::SpecialRwRequest::REQUEST_NONE; uint8_t rwIdx; }; @@ -50,8 +47,10 @@ class RwPollingTask : public SystemObject, public ExecutableObjectIF, public Dev const char* spiDev; GpioIF& gpioIF; std::array skipCommandingForRw; + std::array skipSetSpeedReply; std::array specialRequestIds; std::array rwCookies; + std::array rwRequests{}; std::array writeBuffer; std::array encodedBuffer; diff --git a/linux/boardtest/I2cTestClass.cpp b/linux/boardtest/I2cTestClass.cpp index 4d4e6267..1b9f82fe 100644 --- a/linux/boardtest/I2cTestClass.cpp +++ b/linux/boardtest/I2cTestClass.cpp @@ -37,7 +37,7 @@ void I2cTestClass::battInit() { if (ioctl(bpxInfo.fd, I2C_SLAVE, bpxInfo.addr) < 0) { sif::error << "Failed to acquire bus access and/or talk to slave" << std::endl; } - cmdBuf[0] = BpxBattery::PORT_PING; + cmdBuf[0] = bpxBat::PORT_PING; cmdBuf[1] = 0x42; sendLen = 2; ReturnValue_t result = i2cWrite(bpxInfo.fd, cmdBuf.data(), sendLen); @@ -66,7 +66,7 @@ void I2cTestClass::battPeriodic() { if (ioctl(bpxInfo.fd, I2C_SLAVE, bpxInfo.addr) < 0) { sif::error << "Failed to acquire bus access and/or talk to slave" << std::endl; } - cmdBuf[0] = BpxBattery::PORT_GET_HK; + cmdBuf[0] = bpxBat::PORT_GET_HK; sendLen = 1; ReturnValue_t result = i2cWrite(bpxInfo.fd, cmdBuf.data(), sendLen); if (result != returnvalue::OK) { diff --git a/linux/com/SyrlinksComHandler.h b/linux/com/SyrlinksComHandler.h index 39e8f312..bab1af48 100644 --- a/linux/com/SyrlinksComHandler.h +++ b/linux/com/SyrlinksComHandler.h @@ -20,6 +20,7 @@ class SyrlinksComHandler : public DeviceCommunicationIF, //! [EXPORT] : [SKIP] static constexpr ReturnValue_t NO_SERIAL_DATA_READ = returnvalue::makeCode(2, 0); + //! [EXPORT] : [SKIP] static constexpr ReturnValue_t NO_PACKET_FOUND = returnvalue::makeCode(2, 1); enum class State { SLEEPING, ACTIVE } state = State::SLEEPING; diff --git a/linux/fsfwconfig/events/translateEvents.cpp b/linux/fsfwconfig/events/translateEvents.cpp index 25c6c39d..c4b537e8 100644 --- a/linux/fsfwconfig/events/translateEvents.cpp +++ b/linux/fsfwconfig/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** - * @brief Auto-generated event translation file. Contains 284 translations. + * @brief Auto-generated event translation file. Contains 285 translations. * @details - * Generated on: 2023-04-04 13:59:07 + * Generated on: 2023-04-07 17:42:57 */ #include "translateEvents.h" @@ -266,7 +266,8 @@ const char *VERSION_INFO_STRING = "VERSION_INFO"; const char *CURRENT_IMAGE_INFO_STRING = "CURRENT_IMAGE_INFO"; const char *REBOOT_COUNTER_STRING = "REBOOT_COUNTER"; const char *INDIVIDUAL_BOOT_COUNTS_STRING = "INDIVIDUAL_BOOT_COUNTS"; -const char *I2C_UNAVAILABLE_REBOOT_STRING = "I2C_UNAVAILABLE_REBOOT"; +const char *TRYING_I2C_RECOVERY_STRING = "TRYING_I2C_RECOVERY"; +const char *I2C_REBOOT_STRING = "I2C_REBOOT"; const char *NO_VALID_SENSOR_TEMPERATURE_STRING = "NO_VALID_SENSOR_TEMPERATURE"; const char *NO_HEALTHY_HEATER_AVAILABLE_STRING = "NO_HEALTHY_HEATER_AVAILABLE"; const char *SYRLINKS_OVERHEATING_STRING = "SYRLINKS_OVERHEATING"; @@ -815,7 +816,9 @@ const char *translateEvents(Event event) { case (14008): return INDIVIDUAL_BOOT_COUNTS_STRING; case (14010): - return I2C_UNAVAILABLE_REBOOT_STRING; + return TRYING_I2C_RECOVERY_STRING; + case (14011): + return I2C_REBOOT_STRING; case (14100): return NO_VALID_SENSOR_TEMPERATURE_STRING; case (14101): diff --git a/linux/fsfwconfig/objects/translateObjects.cpp b/linux/fsfwconfig/objects/translateObjects.cpp index c579b741..76ce0db3 100644 --- a/linux/fsfwconfig/objects/translateObjects.cpp +++ b/linux/fsfwconfig/objects/translateObjects.cpp @@ -2,7 +2,7 @@ * @brief Auto-generated object translation file. * @details * Contains 175 translations. - * Generated on: 2023-04-04 13:59:07 + * Generated on: 2023-04-07 17:42:57 */ #include "translateObjects.h" diff --git a/linux/payload/ScexHelper.h b/linux/payload/ScexHelper.h index b95c605b..649ee7e9 100644 --- a/linux/payload/ScexHelper.h +++ b/linux/payload/ScexHelper.h @@ -10,6 +10,7 @@ class ScexHelper : public SerializeIF { public: + //! [EXPORT] : [SKIP] static const ReturnValue_t INVALID_CRC = returnvalue::makeCode(0, 2); ScexHelper(); diff --git a/mission/acs/RwHandler.cpp b/mission/acs/RwHandler.cpp index 87979ae8..3a5cabf8 100644 --- a/mission/acs/RwHandler.cpp +++ b/mission/acs/RwHandler.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "OBSWConfig.h" @@ -23,44 +24,52 @@ RwHandler::RwHandler(object_id_t objectId, object_id_t comIF, CookieIF* comCooki if (gpioComIF == nullptr) { sif::error << "RwHandler: Invalid gpio communication interface" << std::endl; } + currentRequest.rwIdx = rwIdx; } + RwHandler::~RwHandler() {} void RwHandler::doStartUp() { internalState = InternalState::DEFAULT; if (gpioComIF->pullHigh(enableGpio) != returnvalue::OK) { - sif::debug << "RwHandler::doStartUp: Failed to pull enable gpio to high"; + sif::error << "RW Handler " << rwIdx << ": Failed to pull ENABLE pin high for startup"; } + currentRequest.mode = acs::SimpleSensorMode::NORMAL; updatePeriodicReply(true, rws::REPLY_ID); statusSet.setReportingEnabled(true); setMode(_MODE_TO_ON); } void RwHandler::doShutDown() { - if (gpioComIF->pullLow(enableGpio) != returnvalue::OK) { - sif::debug << "RwHandler::doStartUp: Failed to pull enable gpio to low"; + if (internalState != InternalState::SHUTDOWN) { + internalState = InternalState::SHUTDOWN; + shutdownState = ShutdownState::SET_SPEED_ZERO; + offTransitionCountdown.resetTimer(); } - internalState = InternalState::DEFAULT; - updatePeriodicReply(false, rws::REPLY_ID); - { - PoolReadGuard pg(&statusSet); - statusSet.currSpeed = 0.0; - statusSet.referenceSpeed = 0.0; - statusSet.state = 0; - statusSet.setValidity(false, true); - statusSet.setReportingEnabled(false); + if ((internalState == InternalState::SHUTDOWN) and + (shutdownState == ShutdownState::DONE or offTransitionCountdown.hasTimedOut())) { + if (gpioComIF->pullLow(enableGpio) != returnvalue::OK) { + sif::error << "RW Handler " << rwIdx << ": Failed to pull ENABLE pin low for shutdown"; + } + updatePeriodicReply(false, rws::REPLY_ID); + { + PoolReadGuard pg(&statusSet); + statusSet.currSpeed = 0.0; + statusSet.referenceSpeed = 0.0; + statusSet.state = 0; + statusSet.setValidity(false, true); + statusSet.setReportingEnabled(false); + } + { + PoolReadGuard pg(&tmDataset); + tmDataset.setValidity(false, true); + } + internalState = InternalState::DEFAULT; + shutdownState = ShutdownState::NONE; + // The power switch is handled by the assembly, so we can go off here directly. + setMode(MODE_OFF); } - { - PoolReadGuard pg(&tmDataset); - tmDataset.setValidity(false, true); - } - { - PoolReadGuard pg(&rwSpeedActuationSet); - rwSpeedActuationSet.setRwSpeed(0, 10); - } - // The power switch is handled by the assembly, so we can go off here directly. - setMode(MODE_OFF); } ReturnValue_t RwHandler::buildNormalDeviceCommand(DeviceCommandId_t* id) { @@ -77,6 +86,20 @@ ReturnValue_t RwHandler::buildNormalDeviceCommand(DeviceCommandId_t* id) { } ReturnValue_t RwHandler::buildTransitionDeviceCommand(DeviceCommandId_t* id) { + if (internalState == InternalState::SHUTDOWN) { + if (shutdownState == ShutdownState::SET_SPEED_ZERO) { + { + PoolReadGuard pg(&rwSpeedActuationSet); + rwSpeedActuationSet.setRwSpeed(0, 10); + } + *id = rws::REQUEST_ID; + return buildCommandFromCommand(*id, nullptr, 0); + } else if (shutdownState == ShutdownState::STOP_POLLING) { + currentRequest.mode = acs::SimpleSensorMode::OFF; + *id = rws::REQUEST_ID; + return buildCommandFromCommand(*id, nullptr, 0); + } + } return NOTHING_TO_SEND; } @@ -119,32 +142,36 @@ ReturnValue_t RwHandler::buildCommandFromCommand(DeviceCommandId_t deviceCommand return result; } // set speed flag. - commandBuffer[0] = true; - rawPacketLen = 1; - uint8_t* currentCmdBuf = commandBuffer + 1; - rwSpeedActuationSet.serialize(¤tCmdBuf, &rawPacketLen, sizeof(commandBuffer), - SerializeIF::Endianness::MACHINE); - commandBuffer[rawPacketLen++] = static_cast(rws::SpecialRwRequest::REQUEST_NONE); - rawPacket = commandBuffer; + currentRequest.setSpeed = true; + rwSpeedActuationSet.getRwSpeed(currentRequest.currentRwSpeed, currentRequest.currentRampTime); + currentRequest.specialRequest = rws::SpecialRwRequest::REQUEST_NONE; + rawPacket = reinterpret_cast(¤tRequest); + rawPacketLen = sizeof(rws::RwRequest); return returnvalue::OK; } case (rws::RESET_MCU): { - commandBuffer[0] = false; - commandBuffer[7] = static_cast(rws::SpecialRwRequest::RESET_MCU); + currentRequest.setSpeed = false; + currentRequest.specialRequest = rws::SpecialRwRequest::RESET_MCU; internalState = InternalState::RESET_MCU; + rawPacket = reinterpret_cast(¤tRequest); + rawPacketLen = sizeof(rws::RwRequest); return returnvalue::OK; } case (rws::INIT_RW_CONTROLLER): { - commandBuffer[0] = false; - commandBuffer[7] = static_cast(rws::SpecialRwRequest::INIT_RW_CONTROLLER); + currentRequest.setSpeed = false; + currentRequest.specialRequest = rws::SpecialRwRequest::INIT_RW_CONTROLLER; internalState = InternalState::INIT_RW_CONTROLLER; + rawPacket = reinterpret_cast(¤tRequest); + rawPacketLen = sizeof(rws::RwRequest); return returnvalue::OK; } case (rws::GET_TM): { - commandBuffer[0] = false; - commandBuffer[7] = static_cast(rws::SpecialRwRequest::GET_TM); + currentRequest.setSpeed = false; + currentRequest.specialRequest = rws::SpecialRwRequest::GET_TM; internalState = InternalState::GET_TM; + rawPacket = reinterpret_cast(¤tRequest); + rawPacketLen = sizeof(rws::RwRequest); return returnvalue::OK; } default: @@ -172,6 +199,9 @@ ReturnValue_t RwHandler::scanForReply(const uint8_t* start, size_t remainingSize *foundLen = remainingSize; *foundId = rws::REPLY_ID; } + if (internalState == InternalState::SHUTDOWN and shutdownState == ShutdownState::STOP_POLLING) { + shutdownState = ShutdownState::DONE; + } return returnvalue::OK; } @@ -381,6 +411,12 @@ void RwHandler::handleGetRwStatusReply(const uint8_t* packet) { statusSet.setValidity(true, true); + if (internalState == InternalState::SHUTDOWN and std::abs(tmDataset.rwCurrSpeed.value) <= 2 and + shutdownState == ShutdownState::SET_SPEED_ZERO) { + // Finish transition to off. + shutdownState = ShutdownState::STOP_POLLING; + } + if (statusSet.state == rws::STATE_ERROR) { // Trigger FDIR reaction, first recovery, then faulty if it doesnt fix the issue. triggerEvent(DeviceHandlerIF::DEVICE_WANTS_HARD_REBOOT, statusSet.state.value, 0); diff --git a/mission/acs/RwHandler.h b/mission/acs/RwHandler.h index 0537ef8c..a8903b81 100644 --- a/mission/acs/RwHandler.h +++ b/mission/acs/RwHandler.h @@ -75,6 +75,8 @@ class RwHandler : public DeviceHandlerBase { GpioIF* gpioComIF = nullptr; gpioId_t enableGpio = gpio::NO_GPIO; bool debugMode = false; + Countdown offTransitionCountdown = Countdown(5000); + rws::RwRequest currentRequest; rws::StatusSet statusSet; rws::LastResetSatus lastResetStatusSet; @@ -87,27 +89,16 @@ class RwHandler : public DeviceHandlerBase { PoolEntry rwSpeed = PoolEntry({0}); PoolEntry rampTime = PoolEntry({10}); - enum class InternalState { - DEFAULT, - GET_TM, - INIT_RW_CONTROLLER, - RESET_MCU, - // GET_RESET_STATUS, - // CLEAR_RESET_STATUS, - // READ_TEMPERATURE, - // SET_SPEED, - // GET_RW_SATUS - }; + enum class InternalState { DEFAULT, GET_TM, INIT_RW_CONTROLLER, RESET_MCU, SHUTDOWN }; + enum class ShutdownState { + NONE, + SET_SPEED_ZERO, + STOP_POLLING, + DONE, + } shutdownState = ShutdownState::NONE; InternalState internalState = InternalState::DEFAULT; - /** - * @brief This function can be used to build commands which do not contain any data apart - * from the command id and the CRC. - * @param commandId The command id of the command to build. - */ - // void prepareSimpleCommand(DeviceCommandId_t id); - /** * @brief This function checks if the receiced speed and ramp time to set are in a valid * range. @@ -115,13 +106,6 @@ class RwHandler : public DeviceHandlerBase { */ ReturnValue_t checkSpeedAndRampTime(); - /** - * @brief This function prepares the set speed command from the dataSet received with - * an action message or set in the software. - * @return returnvalue::OK if successful, otherwise error code. - */ - // ReturnValue_t prepareSetSpeedCmd(); - /** * @brief This function writes the last reset status retrieved with the get last reset status * command into the reset status dataset. diff --git a/mission/acs/rwHelpers.h b/mission/acs/rwHelpers.h index 05e63db0..76512119 100644 --- a/mission/acs/rwHelpers.h +++ b/mission/acs/rwHelpers.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "eive/resultClassIds.h" #include "events/subsystemIdRanges.h" @@ -36,6 +37,15 @@ enum class SpecialRwRequest : uint8_t { NUM_REQUESTS }; +struct RwRequest { + acs::SimpleSensorMode mode = acs::SimpleSensorMode::OFF; + bool setSpeed = true; + int32_t currentRwSpeed = 0; + uint16_t currentRampTime = 0; + rws::SpecialRwRequest specialRequest = rws::SpecialRwRequest::REQUEST_NONE; + uint8_t rwIdx = 0; +}; + static const uint8_t INTERFACE_ID = CLASS_ID::RW_HANDLER; static const ReturnValue_t SPI_WRITE_FAILURE = MAKE_RETURN_CODE(0xB0); diff --git a/mission/com/PersistentLogTmStoreTask.cpp b/mission/com/PersistentLogTmStoreTask.cpp index 0fc02461..77f2bb7d 100644 --- a/mission/com/PersistentLogTmStoreTask.cpp +++ b/mission/com/PersistentLogTmStoreTask.cpp @@ -45,6 +45,10 @@ ReturnValue_t PersistentLogTmStoreTask::performOperation(uint8_t opCode) { // TODO: Might not be necessary sif::debug << "VC busy, delaying" << std::endl; TaskFactory::delayTask(10); + } else { + // TODO: Would be best to remove this, but not delaying here can lead to evil issues. + // Polling the PAPB of the PTME core too often leads to scheuduling issues. + TaskFactory::delayTask(2); } } } diff --git a/mission/com/PersistentSingleTmStoreTask.cpp b/mission/com/PersistentSingleTmStoreTask.cpp index 61173265..1b77365b 100644 --- a/mission/com/PersistentSingleTmStoreTask.cpp +++ b/mission/com/PersistentSingleTmStoreTask.cpp @@ -29,6 +29,7 @@ ReturnValue_t PersistentSingleTmStoreTask::performOperation(uint8_t opCode) { TaskFactory::delayTask(10); } else { // TODO: Would be best to remove this, but not delaying here can lead to evil issues. + // Polling the PAPB of the PTME core too often leads to scheuduling issues. TaskFactory::delayTask(2); } } diff --git a/mission/controller/ThermalController.h b/mission/controller/ThermalController.h index d531e813..631a37aa 100644 --- a/mission/controller/ThermalController.h +++ b/mission/controller/ThermalController.h @@ -182,14 +182,10 @@ class ThermalController : public ExtendedControllerBase { susMax1227::SusDataset susSet11; lp_var_t tempQ7s = lp_var_t(objects::CORE_CONTROLLER, core::PoolIds::TEMPERATURE); - lp_var_t battTemp1 = - lp_var_t(objects::BPX_BATT_HANDLER, BpxBattery::BATT_TEMP_1); - lp_var_t battTemp2 = - lp_var_t(objects::BPX_BATT_HANDLER, BpxBattery::BATT_TEMP_2); - lp_var_t battTemp3 = - lp_var_t(objects::BPX_BATT_HANDLER, BpxBattery::BATT_TEMP_3); - lp_var_t battTemp4 = - lp_var_t(objects::BPX_BATT_HANDLER, BpxBattery::BATT_TEMP_4); + lp_var_t battTemp1 = lp_var_t(objects::BPX_BATT_HANDLER, bpxBat::BATT_TEMP_1); + lp_var_t battTemp2 = lp_var_t(objects::BPX_BATT_HANDLER, bpxBat::BATT_TEMP_2); + lp_var_t battTemp3 = lp_var_t(objects::BPX_BATT_HANDLER, bpxBat::BATT_TEMP_3); + lp_var_t battTemp4 = lp_var_t(objects::BPX_BATT_HANDLER, bpxBat::BATT_TEMP_4); lp_var_t tempRw1 = lp_var_t(objects::RW1, rws::TEMPERATURE_C); lp_var_t tempRw2 = lp_var_t(objects::RW2, rws::TEMPERATURE_C); lp_var_t tempRw3 = lp_var_t(objects::RW3, rws::TEMPERATURE_C); diff --git a/mission/payload/PayloadPcduHandler.cpp b/mission/payload/PayloadPcduHandler.cpp index ff0c8557..9223f454 100644 --- a/mission/payload/PayloadPcduHandler.cpp +++ b/mission/payload/PayloadPcduHandler.cpp @@ -726,7 +726,7 @@ ReturnValue_t PayloadPcduHandler::transferAsTwo(SpiComIF* comIf, SpiCookie* cook int fileDescriptor = 0; UnixFileGuard fileHelper(comIf->getSpiDev(), fileDescriptor, O_RDWR, "SpiComIF::sendMessage"); if (fileHelper.getOpenResult() != returnvalue::OK) { - return SpiComIF::OPENING_FILE_FAILED; + return spi::OPENING_FILE_FAILED; } spi::SpiModes spiMode = spi::SpiModes::MODE_0; uint32_t spiSpeed = 0; @@ -782,7 +782,7 @@ ReturnValue_t PayloadPcduHandler::transferAsTwo(SpiComIF* comIf, SpiCookie* cook retval = ioctl(fileDescriptor, SPI_IOC_MESSAGE(1), cookie->getTransferStructHandle()); if (retval < 0) { utility::handleIoctlError("SpiComIF::sendMessage: ioctl error."); - result = SpiComIF::FULL_DUPLEX_TRANSFER_FAILED; + result = spi::FULL_DUPLEX_TRANSFER_FAILED; } #if FSFW_HAL_SPI_WIRETAPPING == 1 comIf->performSpiWiretapping(cookie); @@ -804,7 +804,7 @@ ReturnValue_t PayloadPcduHandler::transferAsTwo(SpiComIF* comIf, SpiCookie* cook retval = ioctl(fileDescriptor, SPI_IOC_MESSAGE(1), cookie->getTransferStructHandle()); if (retval < 0) { utility::handleIoctlError("SpiComIF::sendMessage: ioctl error."); - result = SpiComIF::FULL_DUPLEX_TRANSFER_FAILED; + result = spi::FULL_DUPLEX_TRANSFER_FAILED; } #if FSFW_HAL_SPI_WIRETAPPING == 1 comIf->performSpiWiretapping(cookie); diff --git a/mission/power/BpxBatteryHandler.cpp b/mission/power/BpxBatteryHandler.cpp index 6b258ab2..b4aece40 100644 --- a/mission/power/BpxBatteryHandler.cpp +++ b/mission/power/BpxBatteryHandler.cpp @@ -27,54 +27,56 @@ void BpxBatteryHandler::doStartUp() { void BpxBatteryHandler::doShutDown() { // Perform a COM check on reboot state = States::CHECK_COM; + setMode(MODE_OFF); } ReturnValue_t BpxBatteryHandler::buildNormalDeviceCommand(DeviceCommandId_t* id) { - *id = BpxBattery::GET_HK; + *id = bpxBat::GET_HK; return buildCommandFromCommand(*id, nullptr, 0); } ReturnValue_t BpxBatteryHandler::buildTransitionDeviceCommand(DeviceCommandId_t* id) { if (state == States::CHECK_COM) { - *id = BpxBattery::PING; + *id = bpxBat::PING; return buildCommandFromCommand(*id, nullptr, 0); } return returnvalue::OK; } void BpxBatteryHandler::fillCommandAndReplyMap() { - using namespace BpxBattery; + using namespace bpxBat; insertInCommandAndReplyMap(GET_HK, 1, &hkSet, GET_HK_REPLY_LEN); - insertInCommandAndReplyMap(BpxBattery::PING, 1, nullptr, PING_REPLY_LEN); - insertInCommandAndReplyMap(BpxBattery::REBOOT, 1, nullptr, 0); - insertInCommandAndReplyMap(BpxBattery::RESET_COUNTERS, 1, nullptr, EMPTY_REPLY_LEN); - insertInCommandAndReplyMap(BpxBattery::CONFIG_CMD, 1, nullptr, EMPTY_REPLY_LEN); - insertInCommandAndReplyMap(BpxBattery::CONFIG_GET, 1, &cfgSet, CONFIG_GET_REPLY_LEN); + insertInCommandAndReplyMap(bpxBat::PING, 1, nullptr, PING_REPLY_LEN); + insertInCommandAndReplyMap(bpxBat::REBOOT, 1, nullptr, 0); + insertInCommandAndReplyMap(bpxBat::RESET_COUNTERS, 1, nullptr, EMPTY_REPLY_LEN); + insertInCommandAndReplyMap(bpxBat::CONFIG_CMD, 1, nullptr, EMPTY_REPLY_LEN); + insertInCommandAndReplyMap(bpxBat::CONFIG_GET, 1, &cfgSet, CONFIG_GET_REPLY_LEN); } ReturnValue_t BpxBatteryHandler::buildCommandFromCommand(DeviceCommandId_t deviceCommand, const uint8_t* commandData, size_t commandDataLen) { switch (deviceCommand) { - case (BpxBattery::GET_HK): { - cmdBuf[0] = BpxBattery::PORT_GET_HK; + case (bpxBat::GET_HK): { + cmdBuf[0] = bpxBat::PORT_GET_HK; this->rawPacketLen = 1; break; } - case (BpxBattery::PING): { + case (bpxBat::PING): { if (commandDataLen == 1 and commandData != nullptr) { sentPingByte = commandData[0]; } else { - sentPingByte = BpxBattery::DEFAULT_PING_SENT_BYTE; + sentPingByte = bpxBat::DEFAULT_PING_SENT_BYTE; } - cmdBuf[0] = BpxBattery::PORT_PING; + cmdBuf[0] = bpxBat::PORT_PING; cmdBuf[1] = sentPingByte; this->rawPacketLen = 2; break; } - case (BpxBattery::REBOOT): { - cmdBuf[0] = BpxBattery::PORT_REBOOT; + case (bpxBat::REBOOT): { + sif::info << "BPX BATT: Executing reboot command" << std::endl; + cmdBuf[0] = bpxBat::PORT_REBOOT; cmdBuf[1] = 0x80; cmdBuf[2] = 0x07; cmdBuf[3] = 0x80; @@ -85,26 +87,26 @@ ReturnValue_t BpxBatteryHandler::buildCommandFromCommand(DeviceCommandId_t devic triggerEvent(DeviceHandlerIF::DEVICE_WANTS_HARD_REBOOT); break; } - case (BpxBattery::RESET_COUNTERS): { - cmdBuf[0] = BpxBattery::PORT_RESET_COUNTERS; - cmdBuf[1] = BpxBattery::RESET_COUNTERS_MAGIC_VALUE; + case (bpxBat::RESET_COUNTERS): { + cmdBuf[0] = bpxBat::PORT_RESET_COUNTERS; + cmdBuf[1] = bpxBat::RESET_COUNTERS_MAGIC_VALUE; this->rawPacketLen = 2; break; } - case (BpxBattery::CONFIG_CMD): { - cmdBuf[0] = BpxBattery::PORT_CONFIG_CMD; + case (bpxBat::CONFIG_CMD): { + cmdBuf[0] = bpxBat::PORT_CONFIG_CMD; // Needs to be set to 0x01 according to datasheet cmdBuf[1] = 0x01; this->rawPacketLen = 2; break; } - case (BpxBattery::CONFIG_GET): { - cmdBuf[0] = BpxBattery::PORT_CONFIG_GET; + case (bpxBat::CONFIG_GET): { + cmdBuf[0] = bpxBat::PORT_CONFIG_GET; this->rawPacketLen = 1; break; } - case (BpxBattery::CONFIG_SET): { - cmdBuf[0] = BpxBattery::PORT_CONFIG_SET; + case (bpxBat::CONFIG_SET): { + cmdBuf[0] = bpxBat::PORT_CONFIG_SET; if (commandDataLen != 3) { return DeviceHandlerIF::INVALID_NUMBER_OR_LENGTH_OF_PARAMETERS; } @@ -114,8 +116,8 @@ ReturnValue_t BpxBatteryHandler::buildCommandFromCommand(DeviceCommandId_t devic this->rawPacketLen = 4; break; } - case (BpxBattery::MAN_HEAT_ON): { - cmdBuf[0] = BpxBattery::PORT_MAN_HEAT_ON; + case (bpxBat::MAN_HEAT_ON): { + cmdBuf[0] = bpxBat::PORT_MAN_HEAT_ON; if (commandDataLen != 2) { return DeviceHandlerIF::INVALID_NUMBER_OR_LENGTH_OF_PARAMETERS; } @@ -125,8 +127,8 @@ ReturnValue_t BpxBatteryHandler::buildCommandFromCommand(DeviceCommandId_t devic this->rawPacketLen = 3; break; } - case (BpxBattery::MAN_HEAT_OFF): { - cmdBuf[0] = BpxBattery::PORT_MAN_HEAT_OFF; + case (bpxBat::MAN_HEAT_OFF): { + cmdBuf[0] = bpxBat::PORT_MAN_HEAT_OFF; this->rawPacketLen = 1; break; } @@ -142,35 +144,35 @@ ReturnValue_t BpxBatteryHandler::buildCommandFromCommand(DeviceCommandId_t devic ReturnValue_t BpxBatteryHandler::scanForReply(const uint8_t* start, size_t remainingSize, DeviceCommandId_t* foundId, size_t* foundLen) { - using namespace BpxBattery; + using namespace bpxBat; switch (lastCmd) { - case (BpxBattery::GET_HK): { + case (bpxBat::GET_HK): { if (remainingSize != GET_HK_REPLY_LEN) { return DeviceHandlerIF::LENGTH_MISSMATCH; } break; } - case (BpxBattery::PING): - case (BpxBattery::MAN_HEAT_ON): - case (BpxBattery::MAN_HEAT_OFF): { + case (bpxBat::PING): + case (bpxBat::MAN_HEAT_ON): + case (bpxBat::MAN_HEAT_OFF): { if (remainingSize != PING_REPLY_LEN) { return DeviceHandlerIF::LENGTH_MISSMATCH; } break; } - case (BpxBattery::REBOOT): { + case (bpxBat::REBOOT): { // Ignore break; } - case (BpxBattery::RESET_COUNTERS): - case (BpxBattery::CONFIG_CMD): - case (BpxBattery::CONFIG_SET): { + case (bpxBat::RESET_COUNTERS): + case (bpxBat::CONFIG_CMD): + case (bpxBat::CONFIG_SET): { if (remainingSize != EMPTY_REPLY_LEN) { return DeviceHandlerIF::LENGTH_MISSMATCH; } break; } - case (BpxBattery::CONFIG_GET): { + case (bpxBat::CONFIG_GET): { if (remainingSize != CONFIG_GET_REPLY_LEN) { return DeviceHandlerIF::LENGTH_MISSMATCH; } @@ -187,11 +189,11 @@ ReturnValue_t BpxBatteryHandler::scanForReply(const uint8_t* start, size_t remai } ReturnValue_t BpxBatteryHandler::interpretDeviceReply(DeviceCommandId_t id, const uint8_t* packet) { - if (id != BpxBattery::REBOOT and packet[1] != 0) { + if (id != bpxBat::REBOOT and packet[1] != 0) { return DeviceHandlerIF::DEVICE_REPORTED_ERROR; } switch (id) { - case (BpxBattery::GET_HK): { + case (bpxBat::GET_HK): { PoolReadGuard rg(&hkSet); ReturnValue_t result = hkSet.parseRawHk(packet + 2, 21); hkSet.setValidity(true, true); @@ -213,7 +215,7 @@ ReturnValue_t BpxBatteryHandler::interpretDeviceReply(DeviceCommandId_t id, cons } break; } - case (BpxBattery::PING): { + case (bpxBat::PING): { if (packet[2] != sentPingByte) { return DeviceHandlerIF::INVALID_DATA; } @@ -222,19 +224,19 @@ ReturnValue_t BpxBatteryHandler::interpretDeviceReply(DeviceCommandId_t id, cons } break; } - case (BpxBattery::RESET_COUNTERS): - case (BpxBattery::CONFIG_CMD): - case (BpxBattery::CONFIG_SET): { + case (bpxBat::RESET_COUNTERS): + case (bpxBat::CONFIG_CMD): + case (bpxBat::CONFIG_SET): { break; } - case (BpxBattery::MAN_HEAT_ON): - case (BpxBattery::MAN_HEAT_OFF): { + case (bpxBat::MAN_HEAT_ON): + case (bpxBat::MAN_HEAT_OFF): { if (packet[2] != 0x01) { return DeviceHandlerIF::DEVICE_DID_NOT_EXECUTE; } break; } - case (BpxBattery::CONFIG_GET): { + case (bpxBat::CONFIG_GET): { PoolReadGuard rg(&cfgSet); ReturnValue_t result = cfgSet.parseRawHk(packet + 2, 3); if (result != returnvalue::OK) { @@ -243,7 +245,7 @@ ReturnValue_t BpxBatteryHandler::interpretDeviceReply(DeviceCommandId_t id, cons cfgSet.setValidity(true, true); break; } - case (BpxBattery::REBOOT): { + case (bpxBat::REBOOT): { break; } default: { @@ -257,20 +259,20 @@ uint32_t BpxBatteryHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) ReturnValue_t BpxBatteryHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap, LocalDataPoolManager& poolManager) { - localDataPoolMap.emplace(BpxBattery::BATT_TEMP_1, &battTemp1); - localDataPoolMap.emplace(BpxBattery::BATT_TEMP_2, &battTemp2); - localDataPoolMap.emplace(BpxBattery::BATT_TEMP_3, &battTemp3); - localDataPoolMap.emplace(BpxBattery::BATT_TEMP_4, &battTemp4); - localDataPoolMap.emplace(BpxBattery::CHARGE_CURRENT, &chargeCurrent); - localDataPoolMap.emplace(BpxBattery::DISCHARGE_CURRENT, &dischargeCurrent); - localDataPoolMap.emplace(BpxBattery::HEATER_CURRENT, &heaterCurrent); - localDataPoolMap.emplace(BpxBattery::BATT_VOLTAGE, &battVolt); - localDataPoolMap.emplace(BpxBattery::REBOOT_COUNTER, &rebootCounter); - localDataPoolMap.emplace(BpxBattery::BOOTCAUSE, &bootCause); + localDataPoolMap.emplace(bpxBat::BATT_TEMP_1, &battTemp1); + localDataPoolMap.emplace(bpxBat::BATT_TEMP_2, &battTemp2); + localDataPoolMap.emplace(bpxBat::BATT_TEMP_3, &battTemp3); + localDataPoolMap.emplace(bpxBat::BATT_TEMP_4, &battTemp4); + localDataPoolMap.emplace(bpxBat::CHARGE_CURRENT, &chargeCurrent); + localDataPoolMap.emplace(bpxBat::DISCHARGE_CURRENT, &dischargeCurrent); + localDataPoolMap.emplace(bpxBat::HEATER_CURRENT, &heaterCurrent); + localDataPoolMap.emplace(bpxBat::BATT_VOLTAGE, &battVolt); + localDataPoolMap.emplace(bpxBat::REBOOT_COUNTER, &rebootCounter); + localDataPoolMap.emplace(bpxBat::BOOTCAUSE, &bootCause); - localDataPoolMap.emplace(BpxBattery::BATTERY_HEATER_MODE, &battheatMode); - localDataPoolMap.emplace(BpxBattery::BATTHEAT_LOW_LIMIT, &battheatLow); - localDataPoolMap.emplace(BpxBattery::BATTHEAT_HIGH_LIMIT, &battheatHigh); + localDataPoolMap.emplace(bpxBat::BATTERY_HEATER_MODE, &battheatMode); + localDataPoolMap.emplace(bpxBat::BATTHEAT_LOW_LIMIT, &battheatLow); + localDataPoolMap.emplace(bpxBat::BATTHEAT_HIGH_LIMIT, &battheatHigh); poolManager.subscribeForRegularPeriodicPacket( subdp::RegularHkPeriodicParams(hkSet.getSid(), enableHkSets, 20.0)); diff --git a/mission/power/BpxBatteryHandler.h b/mission/power/BpxBatteryHandler.h index 0f6d835c..d01691a9 100644 --- a/mission/power/BpxBatteryHandler.h +++ b/mission/power/BpxBatteryHandler.h @@ -25,7 +25,7 @@ class BpxBatteryHandler : public DeviceHandlerBase { bool commandExecuted = false; bool debugMode = false; bool goToNormalModeImmediately = false; - uint8_t sentPingByte = BpxBattery::DEFAULT_PING_SENT_BYTE; + uint8_t sentPingByte = bpxBat::DEFAULT_PING_SENT_BYTE; #if OBSW_THREAD_TRACING == 1 uint32_t opCounter = 0; #endif diff --git a/mission/power/bpxBattDefs.h b/mission/power/bpxBattDefs.h index 1808c94a..6df87efd 100644 --- a/mission/power/bpxBattDefs.h +++ b/mission/power/bpxBattDefs.h @@ -8,7 +8,7 @@ #include "fsfw/devicehandlers/DeviceHandlerIF.h" -namespace BpxBattery { +namespace bpxBat { enum LocalPoolIds { CHARGE_CURRENT = 0, @@ -114,18 +114,18 @@ class BpxHkDeserializer : public SerialLinkedListAdapter { } }; -}; // namespace BpxBattery +}; // namespace bpxBat /** * @brief BPX HK data holder */ -class BpxBatteryHk : public StaticLocalDataSet { +class BpxBatteryHk : public StaticLocalDataSet { public: /** * Constructor for data users * @param gyroId */ - BpxBatteryHk(object_id_t bpxId) : StaticLocalDataSet(sid_t(bpxId, BpxBattery::HK_SET_ID)) { + BpxBatteryHk(object_id_t bpxId) : StaticLocalDataSet(sid_t(bpxId, bpxBat::HK_SET_ID)) { setAllVariablesReadOnly(); } @@ -176,28 +176,25 @@ class BpxBatteryHk : public StaticLocalDataSet { } //! Charge current in mA - lp_var_t chargeCurrent = - lp_var_t(sid.objectId, BpxBattery::CHARGE_CURRENT, this); + lp_var_t chargeCurrent = lp_var_t(sid.objectId, bpxBat::CHARGE_CURRENT, this); //! Discharge current in mA lp_var_t dischargeCurrent = - lp_var_t(sid.objectId, BpxBattery::DISCHARGE_CURRENT, this); + lp_var_t(sid.objectId, bpxBat::DISCHARGE_CURRENT, this); //! Heater current in mA - lp_var_t heaterCurrent = - lp_var_t(sid.objectId, BpxBattery::HEATER_CURRENT, this); + lp_var_t heaterCurrent = lp_var_t(sid.objectId, bpxBat::HEATER_CURRENT, this); //! Battery voltage in mV - lp_var_t battVoltage = lp_var_t(sid.objectId, BpxBattery::BATT_VOLTAGE, this); + lp_var_t battVoltage = lp_var_t(sid.objectId, bpxBat::BATT_VOLTAGE, this); //! Battery temperature 1 in degC - lp_var_t battTemp1 = lp_var_t(sid.objectId, BpxBattery::BATT_TEMP_1, this); + lp_var_t battTemp1 = lp_var_t(sid.objectId, bpxBat::BATT_TEMP_1, this); //! Battery temperature 2 in degC - lp_var_t battTemp2 = lp_var_t(sid.objectId, BpxBattery::BATT_TEMP_2, this); + lp_var_t battTemp2 = lp_var_t(sid.objectId, bpxBat::BATT_TEMP_2, this); //! Battery temperature 3 in degC - lp_var_t battTemp3 = lp_var_t(sid.objectId, BpxBattery::BATT_TEMP_3, this); + lp_var_t battTemp3 = lp_var_t(sid.objectId, bpxBat::BATT_TEMP_3, this); //! Battery temperature 4 in degC - lp_var_t battTemp4 = lp_var_t(sid.objectId, BpxBattery::BATT_TEMP_4, this); - lp_var_t rebootCounter = - lp_var_t(sid.objectId, BpxBattery::REBOOT_COUNTER, this); - lp_var_t bootcause = lp_var_t(sid.objectId, BpxBattery::BOOTCAUSE, this); + lp_var_t battTemp4 = lp_var_t(sid.objectId, bpxBat::BATT_TEMP_4, this); + lp_var_t rebootCounter = lp_var_t(sid.objectId, bpxBat::REBOOT_COUNTER, this); + lp_var_t bootcause = lp_var_t(sid.objectId, bpxBat::BOOTCAUSE, this); private: friend class BpxBatteryHandler; @@ -205,16 +202,16 @@ class BpxBatteryHk : public StaticLocalDataSet { * Constructor for data creator * @param hkOwner */ - BpxBatteryHk(HasLocalDataPoolIF* hkOwner) : StaticLocalDataSet(hkOwner, BpxBattery::HK_SET_ID) {} + BpxBatteryHk(HasLocalDataPoolIF* hkOwner) : StaticLocalDataSet(hkOwner, bpxBat::HK_SET_ID) {} }; -class BpxBatteryCfg : public StaticLocalDataSet { +class BpxBatteryCfg : public StaticLocalDataSet { public: /** * Constructor for data users * @param gyroId */ - BpxBatteryCfg(object_id_t bpxId) : StaticLocalDataSet(sid_t(bpxId, BpxBattery::CFG_SET_ID)) { + BpxBatteryCfg(object_id_t bpxId) : StaticLocalDataSet(sid_t(bpxId, bpxBat::CFG_SET_ID)) { setAllVariablesReadOnly(); } @@ -230,13 +227,12 @@ class BpxBatteryCfg : public StaticLocalDataSet { //! Mode for battheater [0=OFF,1=Auto] lp_var_t battheatermode = - lp_var_t(sid.objectId, BpxBattery::BATTERY_HEATER_MODE, this); + lp_var_t(sid.objectId, bpxBat::BATTERY_HEATER_MODE, this); //! Turn heater on at [degC] - lp_var_t battheaterLow = - lp_var_t(sid.objectId, BpxBattery::BATTHEAT_LOW_LIMIT, this); + lp_var_t battheaterLow = lp_var_t(sid.objectId, bpxBat::BATTHEAT_LOW_LIMIT, this); //! Turn heater off at [degC] lp_var_t battheaterHigh = - lp_var_t(sid.objectId, BpxBattery::BATTHEAT_HIGH_LIMIT, this); + lp_var_t(sid.objectId, bpxBat::BATTHEAT_HIGH_LIMIT, this); private: friend class BpxBatteryHandler; @@ -244,8 +240,7 @@ class BpxBatteryCfg : public StaticLocalDataSet { * Constructor for data creator * @param hkOwner */ - BpxBatteryCfg(HasLocalDataPoolIF* hkOwner) - : StaticLocalDataSet(hkOwner, BpxBattery::CFG_SET_ID) {} + BpxBatteryCfg(HasLocalDataPoolIF* hkOwner) : StaticLocalDataSet(hkOwner, bpxBat::CFG_SET_ID) {} }; #endif /* MISSION_POWER_BPXBATTDEFS_H_ */ diff --git a/mission/sysDefs.h b/mission/sysDefs.h index 70ff8138..7a729d6e 100644 --- a/mission/sysDefs.h +++ b/mission/sysDefs.h @@ -1,12 +1,79 @@ #ifndef MISSION_SYSDEFS_H_ #define MISSION_SYSDEFS_H_ +#include + #include "acs/defs.h" +extern std::atomic_uint16_t I2C_FATAL_ERRORS; + namespace satsystem { enum Mode : Mode_t { BOOT = 5, SAFE = acs::AcsMode::SAFE, PTG_IDLE = acs::AcsMode::PTG_IDLE }; } +namespace core { +static constexpr ActionId_t LIST_DIRECTORY_INTO_FILE = 0; +static constexpr ActionId_t ANNOUNCE_VERSION = 1; +static constexpr ActionId_t ANNOUNCE_CURRENT_IMAGE = 2; +static constexpr ActionId_t ANNOUNCE_BOOT_COUNTS = 3; +static constexpr ActionId_t SWITCH_REBOOT_FILE_HANDLING = 5; +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 OBSW_UPDATE_FROM_SD_0 = 10; +static constexpr ActionId_t OBSW_UPDATE_FROM_SD_1 = 11; +static constexpr ActionId_t OBSW_UPDATE_FROM_TMP = 12; + +static constexpr ActionId_t SWITCH_TO_SD_0 = 16; +static constexpr ActionId_t SWITCH_TO_SD_1 = 17; +static constexpr ActionId_t SWITCH_TO_BOTH_SD_CARDS = 18; + +//! Reboot using the xsc_boot_copy command +static constexpr ActionId_t XSC_REBOOT_OBC = 32; +static constexpr ActionId_t MOUNT_OTHER_COPY = 33; +//! Reboot using the reboot command +static constexpr ActionId_t REBOOT_OBC = 34; + +static constexpr ActionId_t EXECUTE_SHELL_CMD = 40; + +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 occurred. Can also be a systemd reboot. +//! P1: Current Chip, P2: Current Copy +static constexpr Event REBOOT_SW = event::makeEvent(SUBSYSTEM_ID, 1, severity::LOW); +//! [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); +//! [EXPORT] : [COMMENT] No SD card was active. Core controller will attempt to re-initialize +//! a SD card. +static constexpr Event NO_SD_CARD_ACTIVE = event::makeEvent(SUBSYSTEM_ID, 4, severity::HIGH); +//! [EXPORT] : [COMMENT] +//! P1: Byte 0: Major, Byte 1: Minor, Byte 2: Patch, Byte 3: Has Git Hash +//! P2: First four letters of Git SHA is the last byte of P1 is set. +static constexpr Event VERSION_INFO = event::makeEvent(SUBSYSTEM_ID, 5, severity::INFO); +//! [EXPORT] : [COMMENT] P1: Current Chip, P2: Current Copy +static constexpr Event CURRENT_IMAGE_INFO = event::makeEvent(SUBSYSTEM_ID, 6, severity::INFO); +//! [EXPORT] : [COMMENT] Total reboot counter, which is the sum of the boot count of all +//! individual images. +static constexpr Event REBOOT_COUNTER = event::makeEvent(SUBSYSTEM_ID, 7, severity::INFO); +//! [EXPORT] : [COMMENT] Get the boot count of the individual images. +//! P1: First 16 bits boot count of image 0 0, last 16 bits boot count of image 0 1. +//! P2: First 16 bits boot count of image 1 0, last 16 bits boot count of image 1 1. +static constexpr Event INDIVIDUAL_BOOT_COUNTS = event::makeEvent(SUBSYSTEM_ID, 8, severity::INFO); +//! [EXPORT] : [COMMENT] I2C is unavailable. Trying recovery of I2C bus by power cycling all I2C +//! devices. +static constexpr Event TRYING_I2C_RECOVERY = event::makeEvent(SUBSYSTEM_ID, 10, severity::MEDIUM); +//! [EXPORT] : [COMMENT] I2C is unavailable. Recovery did not work, performing full reboot. +static constexpr Event I2C_REBOOT = event::makeEvent(SUBSYSTEM_ID, 11, severity::MEDIUM); + +} // namespace core + #endif /* MISSION_SYSDEFS_H_ */ diff --git a/mission/system/CMakeLists.txt b/mission/system/CMakeLists.txt index 44122d7e..51e47ef4 100644 --- a/mission/system/CMakeLists.txt +++ b/mission/system/CMakeLists.txt @@ -5,4 +5,6 @@ add_subdirectory(com) add_subdirectory(fdir) add_subdirectory(power) -target_sources(${LIB_EIVE_MISSION} PRIVATE DualLanePowerStateMachine.cpp) +target_sources( + ${LIB_EIVE_MISSION} PRIVATE systemTree.cpp DualLanePowerStateMachine.cpp + EiveSystem.cpp treeUtil.cpp) diff --git a/mission/system/EiveSystem.cpp b/mission/system/EiveSystem.cpp new file mode 100644 index 00000000..f93aa099 --- /dev/null +++ b/mission/system/EiveSystem.cpp @@ -0,0 +1,278 @@ +#include "EiveSystem.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "mission/power/bpxBattDefs.h" +#include "mission/power/defs.h" +#include "mission/sysDefs.h" + +EiveSystem::EiveSystem(object_id_t setObjectId, uint32_t maxNumberOfSequences, + uint32_t maxNumberOfTables, std::atomic_uint16_t& i2cErrors) + : Subsystem(setObjectId, maxNumberOfSequences, maxNumberOfTables), + actionHelper(this, commandQueue), + i2cErrors(i2cErrors) { + auto mqArgs = MqArgs(SubsystemBase::getObjectId(), static_cast(this)); + eventQueue = + QueueFactory::instance()->createMessageQueue(10, EventMessage::EVENT_MESSAGE_SIZE, &mqArgs); +} + +void EiveSystem::announceMode(bool recursive) { + const char* modeStr = "UNKNOWN"; + switch (mode) { + case (satsystem::Mode::BOOT): { + modeStr = "OFF/BOOT"; + break; + } + case (satsystem::Mode::SAFE): { + modeStr = "SAFE"; + break; + } + case (satsystem::Mode::PTG_IDLE): { + modeStr = "POINTING IDLE"; + break; + } + case (acs::AcsMode::PTG_INERTIAL): { + modeStr = "POINTING INERTIAL"; + break; + } + case (acs::AcsMode::PTG_TARGET): { + modeStr = "POINTING TARGET"; + break; + } + case (acs::AcsMode::PTG_TARGET_GS): { + modeStr = "POINTING TARGET GS"; + break; + } + } + sif::info << "EIVE system is now in " << modeStr << " mode" << std::endl; + return Subsystem::announceMode(recursive); +} + +void EiveSystem::performChildOperation() { + Subsystem::performChildOperation(); + handleEventMessages(); + if (not isInTransition and performSafeRecovery) { + commandSelfToSafe(); + performSafeRecovery = false; + return; + } + i2cRecoveryLogic(); +} + +ReturnValue_t EiveSystem::initialize() { + if (powerSwitcher == nullptr) { + return ObjectManager::CHILD_INIT_FAILED; + } + ReturnValue_t result = actionHelper.initialize(); + if (result != returnvalue::OK) { + return result; + } + + auto* bpxDest = ObjectManager::instance()->get(objects::BPX_BATT_HANDLER); + if (bpxDest == nullptr) { + return ObjectManager::CHILD_INIT_FAILED; + } + bpxBattQueueId = bpxDest->getCommandQueue(); + + auto* coreCtrl = ObjectManager::instance()->get(objects::CORE_CONTROLLER); + if (coreCtrl == nullptr) { + return ObjectManager::CHILD_INIT_FAILED; + } + coreCtrlQueueId = coreCtrl->getCommandQueue(); + + auto* manager = ObjectManager::instance()->get(objects::EVENT_MANAGER); + if (manager == nullptr) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "AcsSubsystem::initialize: Invalid event manager" << std::endl; +#endif + return ObjectManagerIF::CHILD_INIT_FAILED; + } + result = manager->registerListener(eventQueue->getId()); + if (result != returnvalue::OK) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::warning << "AcsSubsystem::registerListener: Failed to register as " + "listener" + << std::endl; +#endif + return ObjectManagerIF::CHILD_INIT_FAILED; + } + manager->subscribeToEvent(eventQueue->getId(), + event::getEventId(tcsCtrl::PCDU_SYSTEM_OVERHEATING)); + manager->subscribeToEvent(eventQueue->getId(), event::getEventId(tcsCtrl::OBC_OVERHEATING)); + + // manager->subscribeToEvent(eventQueue->getId(), event::getEventId(CoreController::)) + return Subsystem::initialize(); +} + +void EiveSystem::handleEventMessages() { + EventMessage event; + for (ReturnValue_t status = eventQueue->receiveMessage(&event); status == returnvalue::OK; + status = eventQueue->receiveMessage(&event)) { + switch (event.getMessageId()) { + case EventMessage::EVENT_MESSAGE: + switch (event.getEvent()) { + case tcsCtrl::OBC_OVERHEATING: + case tcsCtrl::PCDU_SYSTEM_OVERHEATING: { + if (isInTransition) { + performSafeRecovery = true; + return; + } + + commandSelfToSafe(); + break; + } + } + break; + default: + sif::debug << "EiveSystem: Did not subscribe to event " << event.getEvent() << std::endl; + break; + } + } +} + +MessageQueueId_t EiveSystem::getCommandQueue() const { return Subsystem::getCommandQueue(); } + +ReturnValue_t EiveSystem::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, + const uint8_t* data, size_t size) { + switch (actionId) { + case (EXECUTE_I2C_REBOOT): { + triggerEvent(core::TRYING_I2C_RECOVERY); + performI2cReboot = true; + i2cRebootState = I2cRebootState::SYSTEM_MODE_BOOT; + this->actionCommandedBy = commandedBy; + return returnvalue::OK; + } + default: { + return HasActionsIF::INVALID_ACTION_ID; + } + } + return returnvalue::OK; +} + +void EiveSystem::setI2cRecoveryParams(PowerSwitchIF* pwrSwitcher) { + this->powerSwitcher = pwrSwitcher; +} + +void EiveSystem::i2cRecoveryLogic() { + ReturnValue_t result; + if (not performI2cReboot) { + // If a recovery worked, need to reset these flags and the error count after some time. + if (i2cRecoveryClearCountdown.hasTimedOut()) { + i2cErrors = 0; + alreadyTriedI2cRecovery = false; + i2cRebootHandlingCountdown.resetTimer(); + } + // If an I2C recovery is not ongoing and the I2C error counter is above a threshold, try + // recovery or reboot if recovery was already attempted. + if (i2cErrors >= 5) { + if (not alreadyTriedI2cRecovery) { + // Try recovery. + executeAction(EXECUTE_I2C_REBOOT, MessageQueueIF::NO_QUEUE, nullptr, 0); + } else { + // We already tried an I2C recovery but the bus is still broken. + // Send full reboot request to core controller. + CommandMessage msg; + ActionMessage::setCommand(&msg, core::REBOOT_OBC, store_address_t()); + result = commandQueue->sendMessage(coreCtrlQueueId, &msg); + } + } + } + if (not isInTransition and performI2cReboot) { + switch (i2cRebootState) { + case (I2cRebootState::NONE): { + break; + } + case (I2cRebootState::SYSTEM_MODE_BOOT): { + startTransition(satsystem::Mode::BOOT, 0); + i2cRebootState = I2cRebootState::SWITCH_3V3_STACK_OFF_AND_BATT_REBOOT; + i2cRebootHandlingCountdown.resetTimer(); + break; + } + case (I2cRebootState::SWITCH_3V3_STACK_OFF_AND_BATT_REBOOT): { + if (mode == satsystem::Mode::BOOT) { + result = powerSwitcher->sendSwitchCommand(power::Switches::P60_DOCK_3V3_STACK, + PowerSwitchIF::SWITCH_OFF); + if (result != returnvalue::OK) { + actionHelper.finish(false, actionCommandedBy, EXECUTE_I2C_REBOOT, result); + commonI2cRecoverySequenceFinish(); + return; + } + CommandMessage msg; + store_address_t dummy{}; + ActionMessage::setCommand(&msg, bpxBat::REBOOT, dummy); + result = commandQueue->sendMessage(bpxBattQueueId, &msg); + if (result != returnvalue::OK) { + actionHelper.finish(false, actionCommandedBy, EXECUTE_I2C_REBOOT, result); + commonI2cRecoverySequenceFinish(); + return; + } + i2cRebootState = I2cRebootState::WAIT_CYCLE; + } + break; + } + case (I2cRebootState::WAIT_CYCLE): { + i2cRebootState = I2cRebootState::SWITCH_3V3_STACK_ON; + break; + } + case (I2cRebootState::SWITCH_3V3_STACK_ON): { + result = powerSwitcher->sendSwitchCommand(power::Switches::P60_DOCK_3V3_STACK, + PowerSwitchIF::SWITCH_ON); + if (result != returnvalue::OK) { + actionHelper.finish(false, actionCommandedBy, EXECUTE_I2C_REBOOT, result); + commonI2cRecoverySequenceFinish(); + return; + } + i2cRebootState = I2cRebootState::SYSTEM_MODE_SAFE; + break; + } + case (I2cRebootState::SYSTEM_MODE_SAFE): { + if (powerSwitcher->getSwitchState(power::Switches::P60_DOCK_3V3_STACK) == + PowerSwitchIF::SWITCH_ON) { + // This should always be accepted + commonI2cRecoverySequenceFinish(); + actionHelper.finish(true, actionCommandedBy, EXECUTE_I2C_REBOOT); + } + break; + } + default: { + sif::error << "EiveSystem: Unexpected I2C reboot state" << std::endl; + break; + } + } + // Timeout handling for the internal procedure. + if (i2cRebootState != I2cRebootState::NONE and i2cRebootHandlingCountdown.hasTimedOut()) { + actionHelper.finish(false, actionCommandedBy, EXECUTE_I2C_REBOOT, returnvalue::FAILED); + // Command stack back on in any case. + powerSwitcher->sendSwitchCommand(power::Switches::P60_DOCK_3V3_STACK, + PowerSwitchIF::SWITCH_ON); + commonI2cRecoverySequenceFinish(); + } + } +} + +void EiveSystem::commandSelfToSafe() { startTransition(satsystem::Mode::SAFE, 0); } + +void EiveSystem::commonI2cRecoverySequenceFinish() { + alreadyTriedI2cRecovery = true; + performI2cReboot = false; + i2cRebootState = I2cRebootState::NONE; + // Reset this counter and the recovery clear countdown. If I2C devices are still problematic, + // we will get a full reboot next time this count goes above 5. + i2cErrors = 0; + i2cRecoveryClearCountdown.resetTimer(); + // This should always be accepted + commandSelfToSafe(); +} + +ReturnValue_t EiveSystem::handleCommandMessage(CommandMessage* message) { + if (message->getMessageType() == messagetypes::ACTION) { + return actionHelper.handleActionMessage(message); + } + return Subsystem::handleCommandMessage(message); +} diff --git a/mission/system/EiveSystem.h b/mission/system/EiveSystem.h new file mode 100644 index 00000000..504d4317 --- /dev/null +++ b/mission/system/EiveSystem.h @@ -0,0 +1,60 @@ +#ifndef MISSION_SYSTEM_EIVESYSTEM_H_ +#define MISSION_SYSTEM_EIVESYSTEM_H_ + +#include +#include +#include + +#include + +class EiveSystem : public Subsystem, public HasActionsIF { + public: + static constexpr ActionId_t EXECUTE_I2C_REBOOT = 10; + + EiveSystem(object_id_t setObjectId, uint32_t maxNumberOfSequences, uint32_t maxNumberOfTables, + std::atomic_uint16_t& i2cErrors); + + void setI2cRecoveryParams(PowerSwitchIF* pwrSwitcher); + + [[nodiscard]] MessageQueueId_t getCommandQueue() const override; + + private: + enum class I2cRebootState { + NONE, + SYSTEM_MODE_BOOT, + SWITCH_3V3_STACK_OFF_AND_BATT_REBOOT, + WAIT_CYCLE, + SWITCH_3V3_STACK_ON, + SYSTEM_MODE_SAFE + } i2cRebootState = I2cRebootState::NONE; + + MessageQueueIF* eventQueue = nullptr; + bool performSafeRecovery = false; + bool performI2cReboot = false; + bool alreadyTriedI2cRecovery = false; + + ActionHelper actionHelper; + PowerSwitchIF* powerSwitcher = nullptr; + std::atomic_uint16_t& i2cErrors; + + MessageQueueId_t bpxBattQueueId = MessageQueueIF::NO_QUEUE; + MessageQueueId_t coreCtrlQueueId = MessageQueueIF::NO_QUEUE; + MessageQueueId_t actionCommandedBy = MessageQueueIF::NO_QUEUE; + Countdown i2cRebootHandlingCountdown = Countdown(10000); + // After 1 minute, clear the flag to avoid full reboots on I2C issues. + Countdown i2cRecoveryClearCountdown = Countdown(60000); + ReturnValue_t initialize() override; + void performChildOperation() override; + void announceMode(bool recursive) override; + + ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, + const uint8_t* data, size_t size) override; + ReturnValue_t handleCommandMessage(CommandMessage* message) override; + + void i2cRecoveryLogic(); + void handleEventMessages(); + void commandSelfToSafe(); + void commonI2cRecoverySequenceFinish(); +}; + +#endif /* MISSION_SYSTEM_EIVESYSTEM_H_ */ diff --git a/mission/system/acs/RwAssembly.cpp b/mission/system/acs/RwAssembly.cpp index ce90f4f5..eacd8d0d 100644 --- a/mission/system/acs/RwAssembly.cpp +++ b/mission/system/acs/RwAssembly.cpp @@ -56,12 +56,12 @@ ReturnValue_t RwAssembly::checkChildrenStateOn(Mode_t wantedMode, Submode_t want } } } catch (const std::out_of_range& e) { - sif::error << "RwAssembly: Invalid children map: " << e.what() << std::endl; + sif::error << "RW ASSY: Invalid children map: " << e.what() << std::endl; } if (devsInCorrectMode < 3) { if (warningSwitch) { - sif::warning << "RwAssembly::checkChildrenStateOn: Only " << devsInCorrectMode - << " devices in correct mode" << std::endl; + sif::warning << "RW ASSY: Only " << devsInCorrectMode << " devices in correct mode" + << std::endl; warningSwitch = false; } return NOT_ENOUGH_CHILDREN_IN_CORRECT_STATE; @@ -106,46 +106,18 @@ void RwAssembly::handleModeReached() { } } -void RwAssembly::handleChildrenLostMode(ReturnValue_t result) { - AssemblyBase::handleChildrenLostMode(result); -} - ReturnValue_t RwAssembly::handleNormalOrOnModeCmd(Mode_t mode, Submode_t submode) { ReturnValue_t result = returnvalue::OK; - bool needsSecondStep = false; - Mode_t devMode = 0; object_id_t objId = 0; try { for (uint8_t idx = 0; idx < NUMBER_RWS; idx++) { - devMode = childrenMap.at(helper.rwIds[idx]).mode; - objId = helper.rwIds[idx]; - if (mode == devMode) { + if (isUseable(objId, mode)) { modeTable[idx].setMode(mode); - } else if (mode == DeviceHandlerIF::MODE_NORMAL) { - if (isUseable(objId, devMode)) { - if (devMode == MODE_ON) { - modeTable[idx].setMode(mode); - modeTable[idx].setSubmode(SUBMODE_NONE); - } else { - modeTable[idx].setMode(MODE_ON); - modeTable[idx].setSubmode(SUBMODE_NONE); - if (internalState != STATE_SECOND_STEP) { - needsSecondStep = true; - } - } - } - } else if (mode == MODE_ON) { - if (isUseable(objId, devMode)) { - modeTable[idx].setMode(MODE_ON); - modeTable[idx].setSubmode(SUBMODE_NONE); - } + modeTable[idx].setSubmode(submode); } } } catch (const std::out_of_range& e) { - sif::error << "TcsBoardAssembly: Invalid children map: " << e.what() << std::endl; - } - if (needsSecondStep) { - result = NEED_SECOND_STEP; + sif::error << "RW ASSY: Invalid children map: " << e.what() << std::endl; } return result; } @@ -172,15 +144,3 @@ ReturnValue_t RwAssembly::initialize() { } return AssemblyBase::initialize(); } - -void RwAssembly::handleModeTransitionFailed(ReturnValue_t result) { - if (targetMode == MODE_OFF) { - AssemblyBase::handleModeTransitionFailed(result); - } else { - if (modeTransitionFailedSwitch) { - // To avoid transitioning back to off - triggerEvent(MODE_TRANSITION_FAILED, result); - modeTransitionFailedSwitch = false; - } - } -} diff --git a/mission/system/acs/RwAssembly.h b/mission/system/acs/RwAssembly.h index 0eb0b59f..540e37cc 100644 --- a/mission/system/acs/RwAssembly.h +++ b/mission/system/acs/RwAssembly.h @@ -41,11 +41,6 @@ class RwAssembly : public AssemblyBase { ReturnValue_t isModeCombinationValid(Mode_t mode, Submode_t submode) override; void startTransition(Mode_t mode, Submode_t submode) override; void handleModeReached() override; - - // These two overrides prevent a transition of the whole assembly back to off just because - // some devices are not working - void handleChildrenLostMode(ReturnValue_t result) override; - void handleModeTransitionFailed(ReturnValue_t result) override; }; #endif /* MISSION_SYSTEM_RWASS_H_ */ diff --git a/mission/system/acs/acsModeTree.cpp b/mission/system/acs/acsModeTree.cpp index 85d2ea45..185ad9eb 100644 --- a/mission/system/acs/acsModeTree.cpp +++ b/mission/system/acs/acsModeTree.cpp @@ -11,7 +11,7 @@ #include "eive/objects.h" #include "mission/acs/defs.h" #include "mission/power/defs.h" -#include "mission/system/tree/util.h" +#include "mission/system/treeUtil.h" AcsSubsystem satsystem::acs::ACS_SUBSYSTEM(objects::ACS_SUBSYSTEM, 12, 24); diff --git a/mission/system/com/ComSubsystem.cpp b/mission/system/com/ComSubsystem.cpp index 5001dbe5..fa2c31d3 100644 --- a/mission/system/com/ComSubsystem.cpp +++ b/mission/system/com/ComSubsystem.cpp @@ -228,3 +228,27 @@ bool ComSubsystem::isTxMode(Mode_t mode) { } return false; } + +void ComSubsystem::announceMode(bool recursive) { + const char *modeStr = "UNKNOWN"; + switch (mode) { + case (com::RX_ONLY): { + modeStr = "RX_ONLY"; + break; + } + case (com::RX_AND_TX_LOW_DATARATE): { + modeStr = "RX_AND_TX_LOW_DATARATE"; + break; + } + case (com::RX_AND_TX_HIGH_DATARATE): { + modeStr = "RX_AND_TX_HIGH_DATARATE"; + break; + } + case (com::RX_AND_TX_DEFAULT_DATARATE): { + modeStr = "RX_AND_TX_DEFAULT_DATARATE"; + break; + } + } + sif::info << "COM subsystem is now in " << modeStr << " mode" << std::endl; + return Subsystem::announceMode(recursive); +} diff --git a/mission/system/com/ComSubsystem.h b/mission/system/com/ComSubsystem.h index 476bf646..529e28fd 100644 --- a/mission/system/com/ComSubsystem.h +++ b/mission/system/com/ComSubsystem.h @@ -47,6 +47,7 @@ class ComSubsystem : public Subsystem, public ReceivesParameterMessagesIF { ReturnValue_t initialize() override; void startTransition(Mode_t mode, Submode_t submode) override; + void announceMode(bool recursive) override; void readEventQueue(); void handleEventMessage(EventMessage *eventMessage); diff --git a/mission/system/com/comModeTree.cpp b/mission/system/com/comModeTree.cpp index bb9a8d10..23611ea2 100644 --- a/mission/system/com/comModeTree.cpp +++ b/mission/system/com/comModeTree.cpp @@ -6,7 +6,7 @@ #include "eive/objects.h" #include "mission/com/defs.h" -#include "mission/system/tree/util.h" +#include "mission/system/treeUtil.h" const auto check = subsystem::checkInsert; diff --git a/mission/system/objects/CMakeLists.txt b/mission/system/objects/CMakeLists.txt index 53cc200d..b2fe6056 100644 --- a/mission/system/objects/CMakeLists.txt +++ b/mission/system/objects/CMakeLists.txt @@ -1,9 +1,4 @@ target_sources( ${LIB_EIVE_MISSION} - PRIVATE EiveSystem.cpp - CamSwitcher.cpp - TcsSubsystem.cpp - PayloadSubsystem.cpp - Stack5VHandler.cpp - PowerStateMachineBase.cpp - TcsBoardAssembly.cpp) + PRIVATE CamSwitcher.cpp TcsSubsystem.cpp PayloadSubsystem.cpp + Stack5VHandler.cpp PowerStateMachineBase.cpp TcsBoardAssembly.cpp) diff --git a/mission/system/objects/EiveSystem.cpp b/mission/system/objects/EiveSystem.cpp deleted file mode 100644 index f6b99b1e..00000000 --- a/mission/system/objects/EiveSystem.cpp +++ /dev/null @@ -1,111 +0,0 @@ -#include "EiveSystem.h" - -#include -#include -#include -#include -#include -#include - -#include "mission/sysDefs.h" - -EiveSystem::EiveSystem(object_id_t setObjectId, uint32_t maxNumberOfSequences, - uint32_t maxNumberOfTables) - : Subsystem(setObjectId, maxNumberOfSequences, maxNumberOfTables) { - auto mqArgs = MqArgs(SubsystemBase::getObjectId(), static_cast(this)); - eventQueue = - QueueFactory::instance()->createMessageQueue(10, EventMessage::EVENT_MESSAGE_SIZE, &mqArgs); -} - -void EiveSystem::announceMode(bool recursive) { - const char* modeStr = "UNKNOWN"; - switch (mode) { - case (satsystem::Mode::BOOT): { - modeStr = "OFF/BOOT"; - break; - } - case (satsystem::Mode::SAFE): { - modeStr = "SAFE"; - break; - } - case (satsystem::Mode::PTG_IDLE): { - modeStr = "POINTING IDLE"; - break; - } - case (acs::AcsMode::PTG_INERTIAL): { - modeStr = "POINTING INERTIAL"; - break; - } - case (acs::AcsMode::PTG_TARGET): { - modeStr = "POINTING TARGET"; - break; - } - case (acs::AcsMode::PTG_TARGET_GS): { - modeStr = "POINTING TARGET GS"; - break; - } - } - sif::info << "EIVE system is now in " << modeStr << " mode" << std::endl; - return Subsystem::announceMode(recursive); -} - -void EiveSystem::performChildOperation() { - Subsystem::performChildOperation(); - handleEventMessages(); - if (not isInTransition and performSafeRecovery) { - commandSelfToSafe(); - performSafeRecovery = false; - } -} - -ReturnValue_t EiveSystem::initialize() { - auto* manager = ObjectManager::instance()->get(objects::EVENT_MANAGER); - if (manager == nullptr) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::error << "AcsSubsystem::initialize: Invalid event manager" << std::endl; -#endif - return ObjectManagerIF::CHILD_INIT_FAILED; - } - ReturnValue_t result = manager->registerListener(eventQueue->getId()); - if (result != returnvalue::OK) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "AcsSubsystem::registerListener: Failed to register as " - "listener" - << std::endl; -#endif - return ObjectManagerIF::CHILD_INIT_FAILED; - } - manager->subscribeToEvent(eventQueue->getId(), - event::getEventId(tcsCtrl::PCDU_SYSTEM_OVERHEATING)); - manager->subscribeToEvent(eventQueue->getId(), event::getEventId(tcsCtrl::OBC_OVERHEATING)); - - return Subsystem::initialize(); -} - -void EiveSystem::handleEventMessages() { - EventMessage event; - for (ReturnValue_t status = eventQueue->receiveMessage(&event); status == returnvalue::OK; - status = eventQueue->receiveMessage(&event)) { - switch (event.getMessageId()) { - case EventMessage::EVENT_MESSAGE: - switch (event.getEvent()) { - case tcsCtrl::OBC_OVERHEATING: - case tcsCtrl::PCDU_SYSTEM_OVERHEATING: { - if (isInTransition) { - performSafeRecovery = true; - return; - } - - commandSelfToSafe(); - break; - } - } - break; - default: - sif::debug << "EiveSystem: Did not subscribe to event " << event.getEvent() << std::endl; - break; - } - } -} - -void EiveSystem::commandSelfToSafe() { startTransition(satsystem::Mode::SAFE, 0); } diff --git a/mission/system/objects/EiveSystem.h b/mission/system/objects/EiveSystem.h deleted file mode 100644 index 06110775..00000000 --- a/mission/system/objects/EiveSystem.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MISSION_SYSTEM_EIVESYSTEM_H_ -#define MISSION_SYSTEM_EIVESYSTEM_H_ - -#include - -class EiveSystem : public Subsystem { - public: - EiveSystem(object_id_t setObjectId, uint32_t maxNumberOfSequences, uint32_t maxNumberOfTables); - - private: - MessageQueueIF* eventQueue = nullptr; - bool performSafeRecovery = false; - - ReturnValue_t initialize() override; - void performChildOperation() override; - void announceMode(bool recursive) override; - void handleEventMessages(); - void commandSelfToSafe(); -}; - -#endif /* MISSION_SYSTEM_EIVESYSTEM_H_ */ diff --git a/mission/system/tree/system.cpp b/mission/system/systemTree.cpp similarity index 97% rename from mission/system/tree/system.cpp rename to mission/system/systemTree.cpp index 6e3b3f72..73a6b4b7 100644 --- a/mission/system/tree/system.cpp +++ b/mission/system/systemTree.cpp @@ -1,4 +1,4 @@ -#include "system.h" +#include "systemTree.h" #include #include @@ -6,12 +6,14 @@ #include #include +#include + #include "eive/objects.h" #include "mission/com/defs.h" #include "mission/system/acs/acsModeTree.h" -#include "payloadModeTree.h" -#include "tcsModeTree.h" -#include "util.h" +#include "mission/system/tree/payloadModeTree.h" +#include "mission/system/tree/tcsModeTree.h" +#include "treeUtil.h" namespace { // Alias for checker function @@ -41,7 +43,7 @@ void satsystem::init() { EIVE_SYSTEM.setInitialMode(satsystem::Mode::BOOT, 0); } -EiveSystem satsystem::EIVE_SYSTEM = EiveSystem(objects::EIVE_SYSTEM, 12, 24); +EiveSystem satsystem::EIVE_SYSTEM = EiveSystem(objects::EIVE_SYSTEM, 12, 24, I2C_FATAL_ERRORS); auto EIVE_SEQUENCE_BOOT = std::make_pair(satsystem::Mode::BOOT, FixedArrayList()); auto EIVE_TABLE_BOOT_TGT = diff --git a/mission/system/tree/system.h b/mission/system/systemTree.h similarity index 82% rename from mission/system/tree/system.h rename to mission/system/systemTree.h index b1c90c82..9d769277 100644 --- a/mission/system/tree/system.h +++ b/mission/system/systemTree.h @@ -1,7 +1,7 @@ #ifndef MISSION_SYSTEM_TREE_SYSTEM_H_ #define MISSION_SYSTEM_TREE_SYSTEM_H_ -#include +#include namespace satsystem { diff --git a/mission/system/tree/CMakeLists.txt b/mission/system/tree/CMakeLists.txt index a6764013..8715d8e1 100644 --- a/mission/system/tree/CMakeLists.txt +++ b/mission/system/tree/CMakeLists.txt @@ -1,2 +1 @@ -target_sources(${LIB_EIVE_MISSION} PRIVATE payloadModeTree.cpp tcsModeTree.cpp - system.cpp util.cpp) +target_sources(${LIB_EIVE_MISSION} PRIVATE payloadModeTree.cpp tcsModeTree.cpp) diff --git a/mission/system/tree/payloadModeTree.cpp b/mission/system/tree/payloadModeTree.cpp index ab67852d..b2d74dd2 100644 --- a/mission/system/tree/payloadModeTree.cpp +++ b/mission/system/tree/payloadModeTree.cpp @@ -10,7 +10,7 @@ #include "eive/objects.h" #include "mission/power/defs.h" #include "mission/system/objects/PayloadSubsystem.h" -#include "util.h" +#include "mission/system/treeUtil.h" namespace { void initOffSequence(Subsystem& ss, ModeListEntry& eh); diff --git a/mission/system/tree/tcsModeTree.cpp b/mission/system/tree/tcsModeTree.cpp index b7188b17..2cdb5052 100644 --- a/mission/system/tree/tcsModeTree.cpp +++ b/mission/system/tree/tcsModeTree.cpp @@ -3,7 +3,7 @@ #include "eive/objects.h" #include "fsfw/devicehandlers/DeviceHandlerIF.h" #include "fsfw/subsystem/Subsystem.h" -#include "mission/system/tree/util.h" +#include "mission/system/treeUtil.h" TcsSubsystem satsystem::tcs::SUBSYSTEM(objects::TCS_SUBSYSTEM, 12, 24); diff --git a/mission/system/tree/util.cpp b/mission/system/treeUtil.cpp similarity index 96% rename from mission/system/tree/util.cpp rename to mission/system/treeUtil.cpp index 935e9d79..0e95f273 100644 --- a/mission/system/tree/util.cpp +++ b/mission/system/treeUtil.cpp @@ -1,4 +1,4 @@ -#include "util.h" +#include "treeUtil.h" #include "fsfw/container/FixedMap.h" #include "fsfw/serviceinterface.h" diff --git a/mission/system/tree/util.h b/mission/system/treeUtil.h similarity index 100% rename from mission/system/tree/util.h rename to mission/system/treeUtil.h diff --git a/mission/tcs/HeaterHandler.cpp b/mission/tcs/HeaterHandler.cpp index 4ec82c08..9105e380 100644 --- a/mission/tcs/HeaterHandler.cpp +++ b/mission/tcs/HeaterHandler.cpp @@ -331,7 +331,6 @@ void HeaterHandler::handleSwitchOffCommand(heater::Switchers heaterIdx) { } } } else { - sif::info << "HeaterHandler::handleSwitchOffCommand: Switch already off" << std::endl; triggerEvent(SWITCH_ALREADY_OFF, heaterIdx); } if (heater.replyQueue != NO_COMMANDER) { diff --git a/mission/tcs/HeaterHandler.h b/mission/tcs/HeaterHandler.h index 6787b660..5bbd85f4 100644 --- a/mission/tcs/HeaterHandler.h +++ b/mission/tcs/HeaterHandler.h @@ -101,8 +101,8 @@ class HeaterHandler : public ExecutableObjectIF, static constexpr Event GPIO_PULL_LOW_FAILED = MAKE_EVENT(1, severity::LOW); static constexpr Event HEATER_WENT_ON = event::makeEvent(SUBSYSTEM_ID, 2, severity::INFO); static constexpr Event HEATER_WENT_OFF = event::makeEvent(SUBSYSTEM_ID, 3, severity::INFO); - static constexpr Event SWITCH_ALREADY_ON = MAKE_EVENT(4, severity::LOW); - static constexpr Event SWITCH_ALREADY_OFF = MAKE_EVENT(5, severity::LOW); + static constexpr Event SWITCH_ALREADY_ON = MAKE_EVENT(4, severity::INFO); + static constexpr Event SWITCH_ALREADY_OFF = MAKE_EVENT(5, severity::INFO); static constexpr Event MAIN_SWITCH_TIMEOUT = MAKE_EVENT(6, severity::MEDIUM); //! A faulty heater was one. The SW will autonomously attempt to shut it down. P1: Heater Index static constexpr Event FAULTY_HEATER_WAS_ON = event::makeEvent(SUBSYSTEM_ID, 7, severity::LOW); diff --git a/mission/tmtc/PersistentTmStore.cpp b/mission/tmtc/PersistentTmStore.cpp index bace6025..7c3738fc 100644 --- a/mission/tmtc/PersistentTmStore.cpp +++ b/mission/tmtc/PersistentTmStore.cpp @@ -338,6 +338,8 @@ ReturnValue_t PersistentTmStore::createMostRecentFile(std::optional suf ReturnValue_t PersistentTmStore::initializeTmStore() { Clock::getClock_timeval(¤tTv); updateBaseDir(); + // Reset active file, base directory might have changed. + activeFile = std::nullopt; return assignAndOrCreateMostRecentFile(); } diff --git a/tmtc b/tmtc index dcf7d0af..43b530cd 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit dcf7d0af71f6ba9d569f9f56604e9245a0233427 +Subproject commit 43b530cdb7dfe6774962bf4b8a880e1c9a6e6580