Merge branch 'develop' into acs-flp-safe
All checks were successful
EIVE/eive-obsw/pipeline/pr-develop This commit looks good

This commit is contained in:
Marius Eggert 2023-04-11 09:56:24 +02:00
commit 18be21a310
67 changed files with 1005 additions and 666 deletions

View File

@ -16,6 +16,46 @@ will consitute of a breaking change warranting a new major release:
# [unreleased] # [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 # [v1.43.2] 2023-04-05
## Changed ## Changed

View File

@ -10,8 +10,8 @@
cmake_minimum_required(VERSION 3.13) cmake_minimum_required(VERSION 3.13)
set(OBSW_VERSION_MAJOR 1) set(OBSW_VERSION_MAJOR 1)
set(OBSW_VERSION_MINOR 43) set(OBSW_VERSION_MINOR 44)
set(OBSW_VERSION_REVISION 2) set(OBSW_VERSION_REVISION 0)
# set(CMAKE_VERBOSE TRUE) # set(CMAKE_VERBOSE TRUE)

View File

@ -1,7 +1,7 @@
/** /**
* @brief Auto-generated event translation file. Contains 284 translations. * @brief Auto-generated event translation file. Contains 285 translations.
* @details * @details
* Generated on: 2023-04-04 13:59:07 * Generated on: 2023-04-07 17:42:57
*/ */
#include "translateEvents.h" #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 *CURRENT_IMAGE_INFO_STRING = "CURRENT_IMAGE_INFO";
const char *REBOOT_COUNTER_STRING = "REBOOT_COUNTER"; const char *REBOOT_COUNTER_STRING = "REBOOT_COUNTER";
const char *INDIVIDUAL_BOOT_COUNTS_STRING = "INDIVIDUAL_BOOT_COUNTS"; 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_VALID_SENSOR_TEMPERATURE_STRING = "NO_VALID_SENSOR_TEMPERATURE";
const char *NO_HEALTHY_HEATER_AVAILABLE_STRING = "NO_HEALTHY_HEATER_AVAILABLE"; const char *NO_HEALTHY_HEATER_AVAILABLE_STRING = "NO_HEALTHY_HEATER_AVAILABLE";
const char *SYRLINKS_OVERHEATING_STRING = "SYRLINKS_OVERHEATING"; const char *SYRLINKS_OVERHEATING_STRING = "SYRLINKS_OVERHEATING";
@ -815,7 +816,9 @@ const char *translateEvents(Event event) {
case (14008): case (14008):
return INDIVIDUAL_BOOT_COUNTS_STRING; return INDIVIDUAL_BOOT_COUNTS_STRING;
case (14010): case (14010):
return I2C_UNAVAILABLE_REBOOT_STRING; return TRYING_I2C_RECOVERY_STRING;
case (14011):
return I2C_REBOOT_STRING;
case (14100): case (14100):
return NO_VALID_SENSOR_TEMPERATURE_STRING; return NO_VALID_SENSOR_TEMPERATURE_STRING;
case (14101): case (14101):

View File

@ -2,7 +2,7 @@
* @brief Auto-generated object translation file. * @brief Auto-generated object translation file.
* @details * @details
* Contains 171 translations. * Contains 171 translations.
* Generated on: 2023-04-04 13:59:07 * Generated on: 2023-04-07 17:42:57
*/ */
#include "translateObjects.h" #include "translateObjects.h"

View File

@ -252,7 +252,7 @@ ReturnValue_t openSpi(const std::string& devname, int flags, GpioIF* gpioIF, gpi
fd = open(devname.c_str(), flags); fd = open(devname.c_str(), flags);
if (fd < 0) { if (fd < 0) {
sif::error << "rwSpiCallback::spiCallback: Failed to open device file" << std::endl; 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 // Pull SPI CS low. For now, no support for active high given

View File

@ -9,6 +9,7 @@
#include "fsfw/serviceinterface/ServiceInterface.h" #include "fsfw/serviceinterface/ServiceInterface.h"
#include "fsfw/timemanager/Stopwatch.h" #include "fsfw/timemanager/Stopwatch.h"
#include "fsfw/version.h" #include "fsfw/version.h"
#include "mission/sysDefs.h"
#include "watchdog/definitions.h" #include "watchdog/definitions.h"
#if OBSW_ADD_TMTC_UDP_SERVER == 1 #if OBSW_ADD_TMTC_UDP_SERVER == 1
#include "fsfw/osal/common/UdpTmTcBridge.h" #include "fsfw/osal/common/UdpTmTcBridge.h"
@ -31,8 +32,7 @@
xsc::Chip CoreController::CURRENT_CHIP = xsc::Chip::NO_CHIP; xsc::Chip CoreController::CURRENT_CHIP = xsc::Chip::NO_CHIP;
xsc::Copy CoreController::CURRENT_COPY = xsc::Copy::NO_COPY; xsc::Copy CoreController::CURRENT_COPY = xsc::Copy::NO_COPY;
CoreController::CoreController(object_id_t objectId, const std::atomic_uint16_t &i2cErrors, CoreController::CoreController(object_id_t objectId, bool enableHkSet)
bool enableHkSet)
: ExtendedControllerBase(objectId, 5), : ExtendedControllerBase(objectId, 5),
enableHkSet(enableHkSet), enableHkSet(enableHkSet),
cmdExecutor(4096), cmdExecutor(4096),
@ -40,8 +40,7 @@ CoreController::CoreController(object_id_t objectId, const std::atomic_uint16_t
cmdRepliesSizes(128), cmdRepliesSizes(128),
opDivider5(5), opDivider5(5),
opDivider10(10), opDivider10(10),
hkSet(this), hkSet(this) {
i2cErrors(i2cErrors) {
cmdExecutor.setRingBuffer(&cmdReplyBuf, &cmdRepliesSizes); cmdExecutor.setRingBuffer(&cmdReplyBuf, &cmdRepliesSizes);
try { try {
sdcMan = SdCardManager::instance(); 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. // Set up state of SD card manager and own initial state.
// Stopwatch watch; // Stopwatch watch;
sdcMan->updateSdCardStateFile(); sdcMan->updateSdCardStateFile();
sdcMan->updateSdStatePair();
SdCardManager::SdStatePair sdStates; SdCardManager::SdStatePair sdStates;
sdcMan->getSdCardsStatus(sdStates); sdcMan->getSdCardsStatus(sdStates);
auto sdCard = sdcMan->getPreferredSdCard(); auto sdCard = sdcMan->getPreferredSdCard();
@ -110,17 +108,12 @@ void CoreController::performControlOperation() {
sdStateMachine(); sdStateMachine();
performMountedSdCardOperations(); performMountedSdCardOperations();
readHkData(); 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) { if (shellCmdIsExecuting) {
bool replyReceived = false; bool replyReceived = false;
// TODO: We could read the data in the ring buffer and send it as an action data reply. // 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) { if (cmdExecutor.check(replyReceived) == CommandExecutor::EXECUTION_FINISHED) {
actionHelper.finish(true, successRecipient, EXECUTE_SHELL_CMD); actionHelper.finish(true, successRecipient, core::EXECUTE_SHELL_CMD);
shellCmdIsExecuting = false; shellCmdIsExecuting = false;
cmdReplyBuf.clear(); cmdReplyBuf.clear();
while (not cmdRepliesSizes.empty()) { while (not cmdRepliesSizes.empty()) {
@ -163,7 +156,7 @@ ReturnValue_t CoreController::initialize() {
sdStateMachine(); sdStateMachine();
triggerEvent(REBOOT_SW, CURRENT_CHIP, CURRENT_COPY); triggerEvent(core::REBOOT_SW, CURRENT_CHIP, CURRENT_COPY);
EventManagerIF *eventManager = EventManagerIF *eventManager =
ObjectManager::instance()->get<EventManagerIF>(objects::EVENT_MANAGER); ObjectManager::instance()->get<EventManagerIF>(objects::EVENT_MANAGER);
if (eventManager == nullptr or eventQueue == nullptr) { if (eventManager == nullptr or eventQueue == nullptr) {
@ -202,6 +195,7 @@ ReturnValue_t CoreController::initializeAfterTaskCreation() {
ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t *data, size_t size) { const uint8_t *data, size_t size) {
using namespace core;
switch (actionId) { switch (actionId) {
case (ANNOUNCE_VERSION): { case (ANNOUNCE_VERSION): {
uint32_t p1 = (common::OBSW_VERSION_MAJOR << 24) | (common::OBSW_VERSION_MINOR << 16) | 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) { if (sdInfo.cfgMode == SdCfgMode::COLD_REDUNDANT) {
updateSdInfoOther(); updateInternalSdInfo();
sif::info << "Cold redundant SD card configuration, preferred SD card: " sif::info << "Cold redundant SD card configuration, preferred SD card: "
<< static_cast<int>(sdInfo.active) << std::endl; << static_cast<int>(sdInfo.active) << std::endl;
result = sdColdRedundantBlockingInit(); result = sdColdRedundantBlockingInit();
@ -409,23 +403,23 @@ ReturnValue_t CoreController::sdStateMachine() {
} else { } else {
// Still update SD state file // Still update SD state file
if (sdInfo.cfgMode == SdCfgMode::PASSIVE) { if (sdInfo.cfgMode == SdCfgMode::PASSIVE) {
sdFsmState = SdStates::UPDATE_INFO; sdFsmState = SdStates::UPDATE_SD_INFO_END;
} else { } else {
sdInfo.cycleCount = 0; sdInfo.cycleCount = 0;
sdInfo.commandExecuted = false; sdInfo.commandPending = false;
sdFsmState = SdStates::GET_INFO; sdFsmState = SdStates::UPDATE_SD_INFO_START;
} }
} }
} }
// This lambda checks the non-blocking operation and assigns the new state on success. // This lambda checks the non-blocking operation of the SD card manager and assigns the new
// It returns true for an operation success and false otherwise // state on success. It returns true for an operation success and false otherwise
auto nonBlockingOpChecking = [&](SdStates newStateOnSuccess, uint16_t maxCycleCount, auto nonBlockingSdcOpChecking = [&](SdStates newStateOnSuccess, uint16_t maxCycleCount,
std::string opPrintout) { std::string opPrintout) {
SdCardManager::OpStatus status = sdcMan->checkCurrentOp(operation); SdCardManager::OpStatus status = sdcMan->checkCurrentOp(operation);
if (status == SdCardManager::OpStatus::SUCCESS) { if (status == SdCardManager::OpStatus::SUCCESS) {
sdFsmState = newStateOnSuccess; sdFsmState = newStateOnSuccess;
sdInfo.commandExecuted = false; sdInfo.commandPending = false;
sdInfo.cycleCount = 0; sdInfo.cycleCount = 0;
return true; return true;
} else if (sdInfo.cycleCount > 4) { } else if (sdInfo.cycleCount > 4) {
@ -436,26 +430,29 @@ ReturnValue_t CoreController::sdStateMachine() {
return false; return false;
}; };
if (sdFsmState == SdStates::GET_INFO) { if (sdFsmState == SdStates::UPDATE_SD_INFO_START) {
if (not sdInfo.commandExecuted) { if (not sdInfo.commandPending) {
// Create updated status file // Create updated status file
result = sdcMan->updateSdCardStateFile(); result = sdcMan->updateSdCardStateFile();
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
sif::warning << "CoreController::sdStateMachine: Updating SD card state file failed" sif::warning << "CoreController::sdStateMachine: Updating SD card state file failed"
<< std::endl; << 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); 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) { 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; sif::warning << "Preferred SD card invalid. Setting to card 0.." << std::endl;
sdInfo.active = sd::SdCard::SLOT_0; sdInfo.active = sd::SdCard::SLOT_0;
@ -467,7 +464,11 @@ ReturnValue_t CoreController::sdStateMachine() {
sif::info << "Cold redundant SD card configuration, target SD card: " sif::info << "Cold redundant SD card configuration, target SD card: "
<< static_cast<int>(sdInfo.active) << std::endl; << static_cast<int>(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) { if (sdInfo.activeState == sd::SdState::MOUNTED) {
// Already mounted, so we can perform handling of the other side.
#if OBSW_VERBOSE_LEVEL >= 1 #if OBSW_VERBOSE_LEVEL >= 1
std::string mountString; std::string mountString;
if (sdInfo.active == sd::SdCard::SLOT_0) { if (sdInfo.active == sd::SdCard::SLOT_0) {
@ -480,27 +481,57 @@ ReturnValue_t CoreController::sdStateMachine() {
#endif #endif
sdcMan->setActiveSdCard(sdInfo.active); sdcMan->setActiveSdCard(sdInfo.active);
currMntPrefix = sdcMan->getCurrentMountPrefix(); currMntPrefix = sdcMan->getCurrentMountPrefix();
sdFsmState = SdStates::DETERMINE_OTHER; tgtState = SdStates::DETERMINE_OTHER;
} else if (sdInfo.activeState == sd::SdState::OFF) { } 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); 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) { } 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 { } else {
if (nonBlockingOpChecking(SdStates::MOUNT_SELF, 10, "Setting SDC state")) { if (nonBlockingSdcOpChecking(SdStates::MOUNT_SELF, 10, "Setting SDC state")) {
sdInfo.activeState = sd::SdState::ON; sdInfo.activeState = sd::SdState::ON;
currentStateSetter(sdInfo.active, 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 (sdFsmState == SdStates::MOUNT_SELF) {
if (not sdInfo.commandExecuted) { if (not sdInfo.commandPending) {
result = sdCardSetup(sdInfo.active, sd::SdState::MOUNTED, sdInfo.activeChar); result = sdCardSetup(sdInfo.active, sd::SdState::MOUNTED, sdInfo.activeChar);
sdInfo.commandExecuted = true; sdInfo.commandPending = true;
} else { } else {
if (nonBlockingOpChecking(SdStates::DETERMINE_OTHER, 5, "Mounting SD card")) { if (nonBlockingSdcOpChecking(SdStates::DETERMINE_OTHER, 5, "Mounting SD card")) {
sdcMan->setActiveSdCard(sdInfo.active); sdcMan->setActiveSdCard(sdInfo.active);
currMntPrefix = sdcMan->getCurrentMountPrefix(); currMntPrefix = sdcMan->getCurrentMountPrefix();
sdInfo.activeState = sd::SdState::MOUNTED; sdInfo.activeState = sd::SdState::MOUNTED;
@ -537,23 +568,33 @@ ReturnValue_t CoreController::sdStateMachine() {
if (sdFsmState == SdStates::SET_STATE_OTHER) { if (sdFsmState == SdStates::SET_STATE_OTHER) {
// Set state of other SD card to ON or OFF, depending on redundancy mode // Set state of other SD card to ON or OFF, depending on redundancy mode
if (sdInfo.cfgMode == SdCfgMode::COLD_REDUNDANT) { if (sdInfo.cfgMode == SdCfgMode::COLD_REDUNDANT) {
if (not sdInfo.commandExecuted) { if (not sdInfo.commandPending) {
result = sdCardSetup(sdInfo.other, sd::SdState::OFF, sdInfo.otherChar, false); result = sdCardSetup(sdInfo.other, sd::SdState::OFF, sdInfo.otherChar, false);
sdInfo.commandExecuted = true; sdInfo.commandPending = true;
} else { } else {
if (nonBlockingOpChecking(SdStates::SKIP_CYCLE_BEFORE_INFO_UPDATE, 10, if (nonBlockingSdcOpChecking(SdStates::SKIP_CYCLE_BEFORE_INFO_UPDATE, 10,
"Switching off other SD card")) { "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; sdInfo.otherState = sd::SdState::OFF;
currentStateSetter(sdInfo.other, sd::SdState::OFF); currentStateSetter(sdInfo.other, sd::SdState::OFF);
} }
} }
} else if (sdInfo.cfgMode == SdCfgMode::HOT_REDUNDANT) { } 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); result = sdCardSetup(sdInfo.other, sd::SdState::ON, sdInfo.otherChar, false);
sdInfo.commandExecuted = true; sdInfo.commandPending = true;
} else { } else {
if (nonBlockingOpChecking(SdStates::MOUNT_UNMOUNT_OTHER, 10, if (nonBlockingSdcOpChecking(SdStates::MOUNT_UNMOUNT_OTHER, 10,
"Switching on other SD card")) { "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; sdInfo.otherState = sd::SdState::ON;
currentStateSetter(sdInfo.other, sd::SdState::ON); currentStateSetter(sdInfo.other, sd::SdState::ON);
} }
@ -564,21 +605,25 @@ ReturnValue_t CoreController::sdStateMachine() {
if (sdFsmState == SdStates::MOUNT_UNMOUNT_OTHER) { if (sdFsmState == SdStates::MOUNT_UNMOUNT_OTHER) {
// Mount or unmount other SD card, depending on redundancy mode // Mount or unmount other SD card, depending on redundancy mode
if (sdInfo.cfgMode == SdCfgMode::COLD_REDUNDANT) { if (sdInfo.cfgMode == SdCfgMode::COLD_REDUNDANT) {
if (not sdInfo.commandExecuted) { if (not sdInfo.commandPending) {
result = sdCardSetup(sdInfo.other, sd::SdState::ON, sdInfo.otherChar); result = sdCardSetup(sdInfo.other, sd::SdState::ON, sdInfo.otherChar);
sdInfo.commandExecuted = true; sdInfo.commandPending = true;
} else { } 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; sdInfo.otherState = sd::SdState::ON;
currentStateSetter(sdInfo.other, 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) { } else if (sdInfo.cfgMode == SdCfgMode::HOT_REDUNDANT) {
if (not sdInfo.commandExecuted) { if (not sdInfo.commandPending) {
result = sdCardSetup(sdInfo.other, sd::SdState::MOUNTED, sdInfo.otherChar); result = sdCardSetup(sdInfo.other, sd::SdState::MOUNTED, sdInfo.otherChar);
sdInfo.commandExecuted = true; sdInfo.commandPending = true;
} else { } 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; sdInfo.otherState = sd::SdState::MOUNTED;
currentStateSetter(sdInfo.other, 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) { if (sdFsmState == SdStates::SKIP_CYCLE_BEFORE_INFO_UPDATE) {
sdFsmState = SdStates::UPDATE_INFO; sdFsmState = SdStates::UPDATE_SD_INFO_END;
} else if (sdFsmState == SdStates::UPDATE_INFO) { } else if (sdFsmState == SdStates::UPDATE_SD_INFO_END) {
// Update status file // Update status file
result = sdcMan->updateSdCardStateFile(); result = sdcMan->updateSdCardStateFile();
if (result != returnvalue::OK) { 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; sdFsmState = SdStates::IDLE;
sdInfo.cycleCount = 0; sdInfo.cycleCount = 0;
sdcMan->setBlocking(false); sdcMan->setBlocking(false);
@ -604,8 +652,16 @@ ReturnValue_t CoreController::sdStateMachine() {
actionHelper.finish(true, sdCommandingInfo.commander, sdCommandingInfo.actionId, actionHelper.finish(true, sdCommandingInfo.commander, sdCommandingInfo.actionId,
returnvalue::OK); 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) { if (not sdInfo.initFinished) {
updateSdInfoOther(); updateInternalSdInfo();
sdInfo.initFinished = true; sdInfo.initFinished = true;
sif::info << "SD card initialization finished" << std::endl; sif::info << "SD card initialization finished" << std::endl;
} }
@ -982,7 +1038,7 @@ ReturnValue_t CoreController::gracefulShutdownTasks(xsc::Chip chip, xsc::Copy co
return result; return result;
} }
void CoreController::updateSdInfoOther() { void CoreController::updateInternalSdInfo() {
if (sdInfo.active == sd::SdCard::SLOT_0) { if (sdInfo.active == sd::SdCard::SLOT_0) {
sdInfo.activeChar = "0"; sdInfo.activeChar = "0";
sdInfo.otherChar = "1"; sdInfo.otherChar = "1";
@ -1324,7 +1380,7 @@ ReturnValue_t CoreController::performSdCardCheck() {
someSdCardActive = true; someSdCardActive = true;
} }
if (not someSdCardActive and remountAttemptFlag) { if (not someSdCardActive and remountAttemptFlag) {
triggerEvent(NO_SD_CARD_ACTIVE); triggerEvent(core::NO_SD_CARD_ACTIVE);
initSdCardBlocking(); initSdCardBlocking();
remountAttemptFlag = false; remountAttemptFlag = false;
} }
@ -1378,7 +1434,7 @@ void CoreController::performRebootFileHandling(bool recreateFile) {
if (rebootFile.bootFlag) { if (rebootFile.bootFlag) {
// Trigger event to inform ground that a reboot was triggered // Trigger event to inform ground that a reboot was triggered
uint32_t p1 = rebootFile.lastChip << 16 | rebootFile.lastCopy; 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 // Clear the boot flag
rebootFile.bootFlag = false; rebootFile.bootFlag = false;
} }
@ -2035,6 +2091,11 @@ bool CoreController::startSdStateMachine(sd::SdCard targetActiveSd, SdCfgMode mo
} }
sdFsmState = SdStates::START; sdFsmState = SdStates::START;
sdInfo.active = targetActiveSd; 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; sdInfo.cfgMode = mode;
sdCommandingInfo.actionId = actionId; sdCommandingInfo.actionId = actionId;
sdCommandingInfo.commander = commander; sdCommandingInfo.commander = commander;
@ -2047,8 +2108,9 @@ void CoreController::announceBootCounts() {
rebootFile.img00Cnt + rebootFile.img01Cnt + rebootFile.img10Cnt + rebootFile.img11Cnt; rebootFile.img00Cnt + rebootFile.img01Cnt + rebootFile.img10Cnt + rebootFile.img11Cnt;
uint32_t individualBootCountsP1 = (rebootFile.img00Cnt << 16) | rebootFile.img01Cnt; uint32_t individualBootCountsP1 = (rebootFile.img00Cnt << 16) | rebootFile.img01Cnt;
uint32_t individualBootCountsP2 = (rebootFile.img10Cnt << 16) | rebootFile.img11Cnt; uint32_t individualBootCountsP2 = (rebootFile.img10Cnt << 16) | rebootFile.img11Cnt;
triggerEvent(INDIVIDUAL_BOOT_COUNTS, individualBootCountsP1, individualBootCountsP2); triggerEvent(core::INDIVIDUAL_BOOT_COUNTS, individualBootCountsP1, individualBootCountsP2);
triggerEvent(REBOOT_COUNTER, (totalBootCount >> 32) & 0xffffffff, totalBootCount & 0xffffffff); triggerEvent(core::REBOOT_COUNTER, (totalBootCount >> 32) & 0xffffffff,
totalBootCount & 0xffffffff);
} }
bool CoreController::isNumber(const std::string &s) { bool CoreController::isNumber(const std::string &s) {

View File

@ -78,64 +78,7 @@ class CoreController : public ExtendedControllerBase {
static constexpr dur_millis_t INIT_SD_CARD_CHECK_TIMEOUT = 5000; static constexpr dur_millis_t INIT_SD_CARD_CHECK_TIMEOUT = 5000;
static constexpr dur_millis_t DEFAULT_SD_CARD_CHECK_TIMEOUT = 60000; static constexpr dur_millis_t DEFAULT_SD_CARD_CHECK_TIMEOUT = 60000;
static constexpr ActionId_t LIST_DIRECTORY_INTO_FILE = 0; CoreController(object_id_t objectId, bool enableHkSet);
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);
virtual ~CoreController(); virtual ~CoreController();
ReturnValue_t initialize() override; ReturnValue_t initialize() override;
@ -186,8 +129,8 @@ class CoreController : public ExtendedControllerBase {
enum class SdStates { enum class SdStates {
NONE, NONE,
START, START,
GET_INFO, UPDATE_SD_INFO_START,
SET_STATE_SELF, SKIP_TWO_CYCLES_IF_SD_LOCKED,
MOUNT_SELF, MOUNT_SELF,
// Determine operations for other SD card, depending on redundancy configuration // Determine operations for other SD card, depending on redundancy configuration
DETERMINE_OTHER, DETERMINE_OTHER,
@ -197,7 +140,7 @@ class CoreController : public ExtendedControllerBase {
// Skip period because the shell command used to generate the info file sometimes is // Skip period because the shell command used to generate the info file sometimes is
// missing the last performed operation if executed too early // missing the last performed operation if executed too early
SKIP_CYCLE_BEFORE_INFO_UPDATE, SKIP_CYCLE_BEFORE_INFO_UPDATE,
UPDATE_INFO, UPDATE_SD_INFO_END,
// SD initialization done // SD initialization done
IDLE IDLE
}; };
@ -210,22 +153,28 @@ class CoreController : public ExtendedControllerBase {
MessageQueueIF* eventQueue = nullptr; MessageQueueIF* eventQueue = nullptr;
SdStates sdFsmState = SdStates::START; SdStates sdFsmState = SdStates::START;
SdStates fsmStateAfterDelay = SdStates::IDLE;
enum SdCfgMode { PASSIVE, COLD_REDUNDANT, HOT_REDUNDANT }; enum SdCfgMode { PASSIVE, COLD_REDUNDANT, HOT_REDUNDANT };
struct SdFsmParams { struct SdFsmParams {
SdCfgMode cfgMode = SdCfgMode::COLD_REDUNDANT; SdCfgMode cfgMode = SdCfgMode::COLD_REDUNDANT;
sd::SdCard active = sd::SdCard::NONE; sd::SdCard active = sd::SdCard::NONE;
sd::SdCard other = 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 activeChar = "0";
std::string otherChar = "1"; std::string otherChar = "1";
sd::SdState activeState = sd::SdState::OFF;
sd::SdState otherState = sd::SdState::OFF;
std::pair<bool, bool> mountSwitch = {true, true}; std::pair<bool, bool> mountSwitch = {true, true};
// Used to track whether a command was executed // This flag denotes that the SD card usage is locked. This is relevant if SD cards go off
bool commandExecuted = true; // 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; bool initFinished = false;
SdCardManager::SdStatePair currentState; SdCardManager::SdStatePair currentState;
uint16_t cycleCount = 0; uint16_t cycleCount = 0;
uint16_t skippedCyclesCount = 0;
} sdInfo; } sdInfo;
struct SdCommanding { struct SdCommanding {
@ -266,7 +215,6 @@ class CoreController : public ExtendedControllerBase {
PoolEntry<float> plVoltageEntry = PoolEntry<float>(0.0); PoolEntry<float> plVoltageEntry = PoolEntry<float>(0.0);
core::HkSet hkSet; core::HkSet hkSet;
const std::atomic_uint16_t& i2cErrors;
#if OBSW_SD_CARD_MUST_BE_ON == 1 #if OBSW_SD_CARD_MUST_BE_ON == 1
bool remountAttemptFlag = true; bool remountAttemptFlag = true;
@ -290,7 +238,7 @@ class CoreController : public ExtendedControllerBase {
void initPrint(); void initPrint();
ReturnValue_t sdStateMachine(); ReturnValue_t sdStateMachine();
void updateSdInfoOther(); void updateInternalSdInfo();
ReturnValue_t sdCardSetup(sd::SdCard sdCard, sd::SdState targetState, std::string sdChar, ReturnValue_t sdCardSetup(sd::SdCard sdCard, sd::SdState targetState, std::string sdChar,
bool printOutput = true); bool printOutput = true);
ReturnValue_t executeSwUpdate(SwUpdateSources sourceDir, const uint8_t* data, size_t size); ReturnValue_t executeSwUpdate(SwUpdateSources sourceDir, const uint8_t* data, size_t size);

View File

@ -23,7 +23,6 @@ class HealthTableIF;
class AcsBoardAssembly; class AcsBoardAssembly;
class GpioIF; class GpioIF;
extern std::atomic_uint16_t I2C_FATAL_ERRORS;
extern std::atomic_bool PTME_LOCKED; extern std::atomic_bool PTME_LOCKED;
namespace ObjectFactory { namespace ObjectFactory {

View File

@ -237,7 +237,7 @@ void scheduling::initTasks() {
#if OBSW_ADD_RW == 1 #if OBSW_ADD_RW == 1
PeriodicTaskIF* rwPolling = 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); 0.4, missedDeadlineFunc, &RR_SCHEDULING);
result = rwPolling->addComponent(objects::RW_POLLING_TASK); result = rwPolling->addComponent(objects::RW_POLLING_TASK);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {

View File

@ -5,7 +5,7 @@
#include <fsfw/power/DummyPowerSwitcher.h> #include <fsfw/power/DummyPowerSwitcher.h>
#include <fsfw_hal/common/gpio/GpioCookie.h> #include <fsfw_hal/common/gpio/GpioCookie.h>
#include <mission/power/gsDefs.h> #include <mission/power/gsDefs.h>
#include <mission/system/tree/system.h> #include <mission/system/systemTree.h>
#include <mission/utility/DummySdCardManager.h> #include <mission/utility/DummySdCardManager.h>
#include "OBSWConfig.h" #include "OBSWConfig.h"
@ -71,7 +71,7 @@ void ObjectFactory::produce(void* args) {
dummy::createDummies(dummyCfg, *pwrSwitcher, gpioComIF); 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 // Regular FM code, does not work for EM if the hardware is not connected
// createPcduComponents(gpioComIF, &pwrSwitcher); // createPcduComponents(gpioComIF, &pwrSwitcher);

View File

@ -2,6 +2,7 @@
#include <fsfw/storagemanager/LocalPool.h> #include <fsfw/storagemanager/LocalPool.h>
#include <fsfw/storagemanager/PoolManager.h> #include <fsfw/storagemanager/PoolManager.h>
#include <mission/power/gsDefs.h> #include <mission/power/gsDefs.h>
#include <mission/system/EiveSystem.h>
#include "OBSWConfig.h" #include "OBSWConfig.h"
#include "bsp_q7s/core/CoreController.h" #include "bsp_q7s/core/CoreController.h"
@ -13,7 +14,7 @@
#include "linux/ObjectFactory.h" #include "linux/ObjectFactory.h"
#include "linux/callbacks/gpioCallbacks.h" #include "linux/callbacks/gpioCallbacks.h"
#include "mission/genericFactory.h" #include "mission/genericFactory.h"
#include "mission/system/tree/system.h" #include "mission/system/systemTree.h"
#include "mission/tmtc/tmFilters.h" #include "mission/tmtc/tmFilters.h"
void ObjectFactory::produce(void* args) { void ObjectFactory::produce(void* args) {
@ -43,8 +44,10 @@ void ObjectFactory::produce(void* args) {
q7s::gpioCallbacks::initSpiCsDecoder(gpioComIF); q7s::gpioCallbacks::initSpiCsDecoder(gpioComIF);
gpioCallbacks::disableAllDecoder(gpioComIF); gpioCallbacks::disableAllDecoder(gpioComIF);
new CoreController(objects::CORE_CONTROLLER, I2C_FATAL_ERRORS, enableHkSets); new CoreController(objects::CORE_CONTROLLER, enableHkSets);
createPcduComponents(gpioComIF, &pwrSwitcher, enableHkSets); createPcduComponents(gpioComIF, &pwrSwitcher, enableHkSets);
satsystem::EIVE_SYSTEM.setI2cRecoveryParams(pwrSwitcher);
auto* stackHandler = new Stack5VHandler(*pwrSwitcher); auto* stackHandler = new Stack5VHandler(*pwrSwitcher);
#if OBSW_ADD_RAD_SENSORS == 1 #if OBSW_ADD_RAD_SENSORS == 1

View File

@ -309,32 +309,6 @@ void SdCardManager::resetState() {
currentOp = Operations::IDLE; 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) { void SdCardManager::processSdStatusLine(std::string& line, uint8_t& idx, sd::SdCard& currentSd) {
using namespace std; using namespace std;
istringstream iss(line); istringstream iss(line);
@ -407,6 +381,7 @@ ReturnValue_t SdCardManager::setPreferredSdCard(sd::SdCard sdCard) {
} }
ReturnValue_t SdCardManager::updateSdCardStateFile() { ReturnValue_t SdCardManager::updateSdCardStateFile() {
using namespace std;
if (cmdExecutor.getCurrentState() == CommandExecutor::States::PENDING) { if (cmdExecutor.getCurrentState() == CommandExecutor::States::PENDING) {
return CommandExecutor::COMMAND_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); std::string updateCmd = "q7hw sd info all > " + std::string(SD_STATE_FILE);
cmdExecutor.load(updateCmd, true, printCmdOutput); cmdExecutor.load(updateCmd, true, printCmdOutput);
ReturnValue_t result = cmdExecutor.execute(); ReturnValue_t result = cmdExecutor.execute();
if (blocking and result != returnvalue::OK) { if (result != returnvalue::OK) {
utility::handleSystemError(cmdExecutor.getLastError(), "SdCardManager::mountSdCard"); 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 { const char* SdCardManager::getCurrentMountPrefix() const {
@ -585,3 +581,8 @@ void SdCardManager::markUnusable() {
MutexGuard mg(defaultLock, LOCK_TYPE, OTHER_TIMEOUT, LOCK_CTX); MutexGuard mg(defaultLock, LOCK_TYPE, OTHER_TIMEOUT, LOCK_CTX);
markedUnusable = true; markedUnusable = true;
} }
void SdCardManager::markUsable() {
MutexGuard mg(defaultLock, LOCK_TYPE, OTHER_TIMEOUT, LOCK_CTX);
markedUnusable = false;
}

View File

@ -117,16 +117,6 @@ class SdCardManager : public SystemObject, public SdCardMountedIF {
ReturnValue_t switchOffSdCard(sd::SdCard sdCard, bool doUnmountSdCard = true, ReturnValue_t switchOffSdCard(sd::SdCard sdCard, bool doUnmountSdCard = true,
SdStatePair* statusPair = nullptr); SdStatePair* statusPair = nullptr);
/**
* Update the state file or creates one if it does not exist. You need to call this
* function before calling #sdCardActive
* @return
* - 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 * 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 * 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); ReturnValue_t performFsck(sd::SdCard sdcard, bool printOutput, int& linuxError);
void markUnusable(); void markUnusable();
void markUsable();
private: private:
CommandExecutor cmdExecutor; CommandExecutor cmdExecutor;
@ -234,7 +225,15 @@ class SdCardManager : public SystemObject, public SdCardMountedIF {
SdCardManager(); 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); ReturnValue_t setSdCardState(sd::SdCard sdCard, bool on);

View File

@ -16,7 +16,7 @@
#include "fsfw/version.h" #include "fsfw/version.h"
#include "mission/acs/defs.h" #include "mission/acs/defs.h"
#include "mission/com/defs.h" #include "mission/com/defs.h"
#include "mission/system/tree/system.h" #include "mission/system/systemTree.h"
#include "q7sConfig.h" #include "q7sConfig.h"
#include "watchdog/definitions.h" #include "watchdog/definitions.h"

View File

@ -37,19 +37,19 @@ uint32_t BpxDummy::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { return
ReturnValue_t BpxDummy::initializeLocalDataPool(localpool::DataPool &localDataPoolMap, ReturnValue_t BpxDummy::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) { LocalDataPoolManager &poolManager) {
localDataPoolMap.emplace(BpxBattery::BATT_TEMP_1, &battTemp1); localDataPoolMap.emplace(bpxBat::BATT_TEMP_1, &battTemp1);
localDataPoolMap.emplace(BpxBattery::BATT_TEMP_2, &battTemp2); localDataPoolMap.emplace(bpxBat::BATT_TEMP_2, &battTemp2);
localDataPoolMap.emplace(BpxBattery::BATT_TEMP_3, &battTemp3); localDataPoolMap.emplace(bpxBat::BATT_TEMP_3, &battTemp3);
localDataPoolMap.emplace(BpxBattery::BATT_TEMP_4, &battTemp4); localDataPoolMap.emplace(bpxBat::BATT_TEMP_4, &battTemp4);
localDataPoolMap.emplace(BpxBattery::CHARGE_CURRENT, &chargeCurrent); localDataPoolMap.emplace(bpxBat::CHARGE_CURRENT, &chargeCurrent);
localDataPoolMap.emplace(BpxBattery::DISCHARGE_CURRENT, &dischargeCurrent); localDataPoolMap.emplace(bpxBat::DISCHARGE_CURRENT, &dischargeCurrent);
localDataPoolMap.emplace(BpxBattery::HEATER_CURRENT, &heaterCurrent); localDataPoolMap.emplace(bpxBat::HEATER_CURRENT, &heaterCurrent);
localDataPoolMap.emplace(BpxBattery::BATT_VOLTAGE, &battVolt); localDataPoolMap.emplace(bpxBat::BATT_VOLTAGE, &battVolt);
localDataPoolMap.emplace(BpxBattery::REBOOT_COUNTER, &rebootCounter); localDataPoolMap.emplace(bpxBat::REBOOT_COUNTER, &rebootCounter);
localDataPoolMap.emplace(BpxBattery::BOOTCAUSE, &bootCause); localDataPoolMap.emplace(bpxBat::BOOTCAUSE, &bootCause);
localDataPoolMap.emplace(BpxBattery::BATTERY_HEATER_MODE, &battheatMode); localDataPoolMap.emplace(bpxBat::BATTERY_HEATER_MODE, &battheatMode);
localDataPoolMap.emplace(BpxBattery::BATTHEAT_LOW_LIMIT, &battheatLow); localDataPoolMap.emplace(bpxBat::BATTHEAT_LOW_LIMIT, &battheatLow);
localDataPoolMap.emplace(BpxBattery::BATTHEAT_HIGH_LIMIT, &battheatHigh); localDataPoolMap.emplace(bpxBat::BATTHEAT_HIGH_LIMIT, &battheatHigh);
return returnvalue::OK; return returnvalue::OK;
} }

View File

@ -7,9 +7,9 @@ RwDummy::RwDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie)
RwDummy::~RwDummy() {} 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; } ReturnValue_t RwDummy::buildNormalDeviceCommand(DeviceCommandId_t *id) { return NOTHING_TO_SEND; }

View File

@ -7,9 +7,9 @@ StarTrackerDummy::StarTrackerDummy(object_id_t objectId, object_id_t comif, Cook
StarTrackerDummy::~StarTrackerDummy() {} 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) { ReturnValue_t StarTrackerDummy::buildNormalDeviceCommand(DeviceCommandId_t *id) {
return NOTHING_TO_SEND; return NOTHING_TO_SEND;

2
fsfw

@ -1 +1 @@
Subproject commit 6650c293da09d8851c2bd6c4d6e6c5a8390d003e Subproject commit 285d327b97514946f0714e477289f67ee8bd413f

View File

@ -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 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 11402;0x2c8a;HEATER_WENT_ON;INFO;No description;mission/tcs/HeaterHandler.h
11403;0x2c8b;HEATER_WENT_OFF;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 11404;0x2c8c;SWITCH_ALREADY_ON;INFO;No description;mission/tcs/HeaterHandler.h
11405;0x2c8d;SWITCH_ALREADY_OFF;LOW;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 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 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 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 13903;0x364f;INSERT_CONFIGFILEVALUE_FAILED;MEDIUM;No description;mission/utility/GlobalConfigHandler.h
13904;0x3650;WRITE_CONFIGFILE_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 13905;0x3651;READ_CONFIGFILE_FAILED;MEDIUM;No description;mission/utility/GlobalConfigHandler.h
14000;0x36b0;ALLOC_FAILURE;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;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;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;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;mission/sysDefs.h
14003;0x36b3;REBOOT_HW;MEDIUM;No description;bsp_q7s/core/CoreController.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.;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.;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.;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.;mission/sysDefs.h
14006;0x36b6;CURRENT_IMAGE_INFO;INFO;P1: Current Chip, P2: Current Copy;bsp_q7s/core/CoreController.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.;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.;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.;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.;mission/sysDefs.h
14010;0x36ba;I2C_UNAVAILABLE_REBOOT;MEDIUM;No description;bsp_q7s/core/CoreController.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 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 14101;0x3715;NO_HEALTHY_HEATER_AVAILABLE;MEDIUM;No description;mission/controller/tcsDefs.h
14102;0x3716;SYRLINKS_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h 14102;0x3716;SYRLINKS_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h

1 Event ID (dec) Event ID (hex) Name Severity Description File Path
101 11401 0x2c89 GPIO_PULL_LOW_FAILED LOW No description mission/tcs/HeaterHandler.h
102 11402 0x2c8a HEATER_WENT_ON INFO No description mission/tcs/HeaterHandler.h
103 11403 0x2c8b HEATER_WENT_OFF INFO No description mission/tcs/HeaterHandler.h
104 11404 0x2c8c SWITCH_ALREADY_ON LOW INFO No description mission/tcs/HeaterHandler.h
105 11405 0x2c8d SWITCH_ALREADY_OFF LOW INFO No description mission/tcs/HeaterHandler.h
106 11406 0x2c8e MAIN_SWITCH_TIMEOUT MEDIUM No description mission/tcs/HeaterHandler.h
107 11407 0x2c8f FAULTY_HEATER_WAS_ON LOW No description mission/tcs/HeaterHandler.h
108 11500 0x2cec BURN_PHASE_START INFO P1: Burn duration in milliseconds, P2: Dry run flag mission/SolarArrayDeploymentHandler.h
251 13903 0x364f INSERT_CONFIGFILEVALUE_FAILED MEDIUM No description mission/utility/GlobalConfigHandler.h
252 13904 0x3650 WRITE_CONFIGFILE_FAILED MEDIUM No description mission/utility/GlobalConfigHandler.h
253 13905 0x3651 READ_CONFIGFILE_FAILED MEDIUM No description mission/utility/GlobalConfigHandler.h
254 14000 0x36b0 ALLOC_FAILURE MEDIUM No description bsp_q7s/core/CoreController.h mission/sysDefs.h
255 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 mission/sysDefs.h
256 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 mission/sysDefs.h
257 14003 0x36b3 REBOOT_HW MEDIUM No description bsp_q7s/core/CoreController.h mission/sysDefs.h
258 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 mission/sysDefs.h
259 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 mission/sysDefs.h
260 14006 0x36b6 CURRENT_IMAGE_INFO INFO P1: Current Chip, P2: Current Copy bsp_q7s/core/CoreController.h mission/sysDefs.h
261 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 mission/sysDefs.h
262 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 mission/sysDefs.h
263 14010 0x36ba I2C_UNAVAILABLE_REBOOT TRYING_I2C_RECOVERY MEDIUM No description I2C is unavailable. Trying recovery of I2C bus by power cycling all I2C devices. bsp_q7s/core/CoreController.h mission/sysDefs.h
264 14011 0x36bb I2C_REBOOT MEDIUM I2C is unavailable. Recovery did not work, performing full reboot. mission/sysDefs.h
265 14100 0x3714 NO_VALID_SENSOR_TEMPERATURE MEDIUM No description mission/controller/tcsDefs.h
266 14101 0x3715 NO_HEALTHY_HEATER_AVAILABLE MEDIUM No description mission/controller/tcsDefs.h
267 14102 0x3716 SYRLINKS_OVERHEATING HIGH No description mission/controller/tcsDefs.h

View File

@ -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 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 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 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 0x3f01;DLEE_StreamTooShort;No description;1;DLE_ENCODER;fsfw/src/fsfw/globalfunctions/DleEncoder.h
0x3f02;DLEE_PossiblePacketLoss;No description;2;DLE_ENCODER;fsfw/src/fsfw/globalfunctions/DleParser.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 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 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 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 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 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 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 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/linux/spi/SpiComIF.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/linux/spi/SpiComIF.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 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 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 0x4603;HURT_UartRxBufferTooSmall;No description;3;HAL_UART;fsfw/src/fsfw_hal/linux/serial/SerialComIF.h

1 Full ID (hex) Name Description Unique ID Subsytem Name File Path
371 0x3e03 HKM_PeriodicHelperInvalid No description 3 HOUSEKEEPING_MANAGER fsfw/src/fsfw/datapoollocal/LocalDataPoolManager.h
372 0x3e04 HKM_PoolobjectNotFound No description 4 HOUSEKEEPING_MANAGER fsfw/src/fsfw/datapoollocal/LocalDataPoolManager.h
373 0x3e05 HKM_DatasetNotFound No description 5 HOUSEKEEPING_MANAGER fsfw/src/fsfw/datapoollocal/LocalDataPoolManager.h
374 0x3f01 DLEE_NoPacketFound DLEE_StreamTooShort No description 1 DLE_ENCODER fsfw/src/fsfw/globalfunctions/DleParser.h fsfw/src/fsfw/globalfunctions/DleEncoder.h
375 0x3f02 DLEE_PossiblePacketLoss DLEE_DecodingError No description 2 DLE_ENCODER fsfw/src/fsfw/globalfunctions/DleParser.h fsfw/src/fsfw/globalfunctions/DleEncoder.h
376 0x4201 PUS11_InvalidTypeTimeWindow No description 1 PUS_SERVICE_11 fsfw/src/fsfw/pus/Service11TelecommandScheduling.h
377 0x4202 PUS11_InvalidTimeWindow No description 2 PUS_SERVICE_11 fsfw/src/fsfw/pus/Service11TelecommandScheduling.h
378 0x4203 PUS11_TimeshiftingNotPossible No description 3 PUS_SERVICE_11 fsfw/src/fsfw/pus/Service11TelecommandScheduling.h
402 0x4403 UXOS_CommandError Command execution failed 3 LINUX_OSAL fsfw/src/fsfw_hal/linux/CommandExecutor.h
403 0x4404 UXOS_NoCommandLoadedOrPending 4 LINUX_OSAL fsfw/src/fsfw_hal/linux/CommandExecutor.h
404 0x4406 UXOS_PcloseCallError No description 6 LINUX_OSAL fsfw/src/fsfw_hal/linux/CommandExecutor.h
405 0x4500 HSPI_OpeningFileFailed No description 0 HAL_SPI fsfw/src/fsfw_hal/linux/spi/SpiComIF.h fsfw/src/fsfw_hal/common/spi/spiCommon.h
406 0x4501 HSPI_FullDuplexTransferFailed No description 1 HAL_SPI fsfw/src/fsfw_hal/linux/spi/SpiComIF.h fsfw/src/fsfw_hal/common/spi/spiCommon.h
407 0x4502 HSPI_HalfDuplexTransferFailed No description 2 HAL_SPI fsfw/src/fsfw_hal/linux/spi/SpiComIF.h fsfw/src/fsfw_hal/common/spi/spiCommon.h
408 0x4503 HSPI_Timeout No description 3 HAL_SPI fsfw/src/fsfw_hal/common/spi/spiCommon.h
409 0x4504 HSPI_Busy No description 4 HAL_SPI fsfw/src/fsfw_hal/common/spi/spiCommon.h
410 0x4505 HSPI_GenericError No description 5 HAL_SPI fsfw/src/fsfw_hal/common/spi/spiCommon.h
411 0x4601 HURT_UartReadFailure No description 1 HAL_UART fsfw/src/fsfw_hal/linux/serial/SerialComIF.h
412 0x4602 HURT_UartReadSizeMissmatch No description 2 HAL_UART fsfw/src/fsfw_hal/linux/serial/SerialComIF.h
413 0x4603 HURT_UartRxBufferTooSmall No description 3 HAL_UART fsfw/src/fsfw_hal/linux/serial/SerialComIF.h

View File

@ -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 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 11402;0x2c8a;HEATER_WENT_ON;INFO;No description;mission/tcs/HeaterHandler.h
11403;0x2c8b;HEATER_WENT_OFF;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 11404;0x2c8c;SWITCH_ALREADY_ON;INFO;No description;mission/tcs/HeaterHandler.h
11405;0x2c8d;SWITCH_ALREADY_OFF;LOW;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 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 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 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 13903;0x364f;INSERT_CONFIGFILEVALUE_FAILED;MEDIUM;No description;mission/utility/GlobalConfigHandler.h
13904;0x3650;WRITE_CONFIGFILE_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 13905;0x3651;READ_CONFIGFILE_FAILED;MEDIUM;No description;mission/utility/GlobalConfigHandler.h
14000;0x36b0;ALLOC_FAILURE;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;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;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;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;mission/sysDefs.h
14003;0x36b3;REBOOT_HW;MEDIUM;No description;bsp_q7s/core/CoreController.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.;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.;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.;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.;mission/sysDefs.h
14006;0x36b6;CURRENT_IMAGE_INFO;INFO;P1: Current Chip, P2: Current Copy;bsp_q7s/core/CoreController.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.;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.;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.;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.;mission/sysDefs.h
14010;0x36ba;I2C_UNAVAILABLE_REBOOT;MEDIUM;No description;bsp_q7s/core/CoreController.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 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 14101;0x3715;NO_HEALTHY_HEATER_AVAILABLE;MEDIUM;No description;mission/controller/tcsDefs.h
14102;0x3716;SYRLINKS_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h 14102;0x3716;SYRLINKS_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h

1 Event ID (dec) Event ID (hex) Name Severity Description File Path
101 11401 0x2c89 GPIO_PULL_LOW_FAILED LOW No description mission/tcs/HeaterHandler.h
102 11402 0x2c8a HEATER_WENT_ON INFO No description mission/tcs/HeaterHandler.h
103 11403 0x2c8b HEATER_WENT_OFF INFO No description mission/tcs/HeaterHandler.h
104 11404 0x2c8c SWITCH_ALREADY_ON LOW INFO No description mission/tcs/HeaterHandler.h
105 11405 0x2c8d SWITCH_ALREADY_OFF LOW INFO No description mission/tcs/HeaterHandler.h
106 11406 0x2c8e MAIN_SWITCH_TIMEOUT MEDIUM No description mission/tcs/HeaterHandler.h
107 11407 0x2c8f FAULTY_HEATER_WAS_ON LOW No description mission/tcs/HeaterHandler.h
108 11500 0x2cec BURN_PHASE_START INFO P1: Burn duration in milliseconds, P2: Dry run flag mission/SolarArrayDeploymentHandler.h
251 13903 0x364f INSERT_CONFIGFILEVALUE_FAILED MEDIUM No description mission/utility/GlobalConfigHandler.h
252 13904 0x3650 WRITE_CONFIGFILE_FAILED MEDIUM No description mission/utility/GlobalConfigHandler.h
253 13905 0x3651 READ_CONFIGFILE_FAILED MEDIUM No description mission/utility/GlobalConfigHandler.h
254 14000 0x36b0 ALLOC_FAILURE MEDIUM No description bsp_q7s/core/CoreController.h mission/sysDefs.h
255 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 mission/sysDefs.h
256 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 mission/sysDefs.h
257 14003 0x36b3 REBOOT_HW MEDIUM No description bsp_q7s/core/CoreController.h mission/sysDefs.h
258 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 mission/sysDefs.h
259 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 mission/sysDefs.h
260 14006 0x36b6 CURRENT_IMAGE_INFO INFO P1: Current Chip, P2: Current Copy bsp_q7s/core/CoreController.h mission/sysDefs.h
261 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 mission/sysDefs.h
262 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 mission/sysDefs.h
263 14010 0x36ba I2C_UNAVAILABLE_REBOOT TRYING_I2C_RECOVERY MEDIUM No description I2C is unavailable. Trying recovery of I2C bus by power cycling all I2C devices. bsp_q7s/core/CoreController.h mission/sysDefs.h
264 14011 0x36bb I2C_REBOOT MEDIUM I2C is unavailable. Recovery did not work, performing full reboot. mission/sysDefs.h
265 14100 0x3714 NO_VALID_SENSOR_TEMPERATURE MEDIUM No description mission/controller/tcsDefs.h
266 14101 0x3715 NO_HEALTHY_HEATER_AVAILABLE MEDIUM No description mission/controller/tcsDefs.h
267 14102 0x3716 SYRLINKS_OVERHEATING HIGH No description mission/controller/tcsDefs.h

View File

@ -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 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 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 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 0x3f01;DLEE_StreamTooShort;No description;1;DLE_ENCODER;fsfw/src/fsfw/globalfunctions/DleEncoder.h
0x3f02;DLEE_PossiblePacketLoss;No description;2;DLE_ENCODER;fsfw/src/fsfw/globalfunctions/DleParser.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 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 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 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 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 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 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 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/linux/spi/SpiComIF.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/linux/spi/SpiComIF.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 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 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 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 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 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 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 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 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 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 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 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 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 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 0x66a0;SADPL_CommandNotSupported;No description;160;SA_DEPL_HANDLER;mission/SolarArrayDeploymentHandler.h
0x66a1;SADPL_DeploymentAlreadyExecuting;No description;161;SA_DEPL_HANDLER;mission/SolarArrayDeploymentHandler.h 0x66a1;SADPL_DeploymentAlreadyExecuting;No description;161;SA_DEPL_HANDLER;mission/SolarArrayDeploymentHandler.h

1 Full ID (hex) Name Description Unique ID Subsytem Name File Path
371 0x3e03 HKM_PeriodicHelperInvalid No description 3 HOUSEKEEPING_MANAGER fsfw/src/fsfw/datapoollocal/LocalDataPoolManager.h
372 0x3e04 HKM_PoolobjectNotFound No description 4 HOUSEKEEPING_MANAGER fsfw/src/fsfw/datapoollocal/LocalDataPoolManager.h
373 0x3e05 HKM_DatasetNotFound No description 5 HOUSEKEEPING_MANAGER fsfw/src/fsfw/datapoollocal/LocalDataPoolManager.h
374 0x3f01 DLEE_NoPacketFound DLEE_StreamTooShort No description 1 DLE_ENCODER fsfw/src/fsfw/globalfunctions/DleParser.h fsfw/src/fsfw/globalfunctions/DleEncoder.h
375 0x3f02 DLEE_PossiblePacketLoss DLEE_DecodingError No description 2 DLE_ENCODER fsfw/src/fsfw/globalfunctions/DleParser.h fsfw/src/fsfw/globalfunctions/DleEncoder.h
376 0x4201 PUS11_InvalidTypeTimeWindow No description 1 PUS_SERVICE_11 fsfw/src/fsfw/pus/Service11TelecommandScheduling.h
377 0x4202 PUS11_InvalidTimeWindow No description 2 PUS_SERVICE_11 fsfw/src/fsfw/pus/Service11TelecommandScheduling.h
378 0x4203 PUS11_TimeshiftingNotPossible No description 3 PUS_SERVICE_11 fsfw/src/fsfw/pus/Service11TelecommandScheduling.h
402 0x4403 UXOS_CommandError Command execution failed 3 LINUX_OSAL fsfw/src/fsfw_hal/linux/CommandExecutor.h
403 0x4404 UXOS_NoCommandLoadedOrPending 4 LINUX_OSAL fsfw/src/fsfw_hal/linux/CommandExecutor.h
404 0x4406 UXOS_PcloseCallError No description 6 LINUX_OSAL fsfw/src/fsfw_hal/linux/CommandExecutor.h
405 0x4500 HSPI_OpeningFileFailed No description 0 HAL_SPI fsfw/src/fsfw_hal/linux/spi/SpiComIF.h fsfw/src/fsfw_hal/common/spi/spiCommon.h
406 0x4501 HSPI_FullDuplexTransferFailed No description 1 HAL_SPI fsfw/src/fsfw_hal/linux/spi/SpiComIF.h fsfw/src/fsfw_hal/common/spi/spiCommon.h
407 0x4502 HSPI_HalfDuplexTransferFailed No description 2 HAL_SPI fsfw/src/fsfw_hal/linux/spi/SpiComIF.h fsfw/src/fsfw_hal/common/spi/spiCommon.h
408 0x4503 HSPI_Timeout No description 3 HAL_SPI fsfw/src/fsfw_hal/common/spi/spiCommon.h
409 0x4504 HSPI_Busy No description 4 HAL_SPI fsfw/src/fsfw_hal/common/spi/spiCommon.h
410 0x4505 HSPI_GenericError No description 5 HAL_SPI fsfw/src/fsfw_hal/common/spi/spiCommon.h
411 0x4601 HURT_UartReadFailure No description 1 HAL_UART fsfw/src/fsfw_hal/linux/serial/SerialComIF.h
412 0x4602 HURT_UartReadSizeMissmatch No description 2 HAL_UART fsfw/src/fsfw_hal/linux/serial/SerialComIF.h
413 0x4603 HURT_UartRxBufferTooSmall No description 3 HAL_UART fsfw/src/fsfw_hal/linux/serial/SerialComIF.h
496 0x58a3 SUSS_ExecutionFailed Command execution failed 163 SUS_HANDLER mission/acs/RwHandler.h
497 0x58a4 SUSS_CrcError Reaction wheel reply has invalid crc 164 SUS_HANDLER mission/acs/RwHandler.h
498 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
499 0x59a0 IPCI_PapbBusy No description 160 CCSDS_IP_CORE_BRIDGE linux/ipcore/PapbVcInterface.h
500 0x5aa0 PTME_UnknownVcId No description 160 PTME linux/ipcore/Ptme.h
501 0x5c01 STRHLP_SdNotMounted SD card specified in path string not mounted 1 STR_HELPER linux/acs/StrComHandler.h
543 0x63a0 NVMB_KeyNotExists Specified key does not exist in json file 160 NVM_PARAM_BASE mission/memory/NvmParameterBase.h
544 0x64a0 FSHLP_SdNotMounted SD card specified with path string not mounted 160 FILE_SYSTEM_HELPER bsp_q7s/fs/FilesystemHelper.h
545 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
546 0x65a0 PLMPHLP_FileClosedAccidentally File accidentally close 160 PLOC_MPSOC_HELPER linux/payload/PlocMpsocHelper.h
547 0x66a0 SADPL_CommandNotSupported No description 160 SA_DEPL_HANDLER mission/SolarArrayDeploymentHandler.h
548 0x66a1 SADPL_DeploymentAlreadyExecuting No description 161 SA_DEPL_HANDLER mission/SolarArrayDeploymentHandler.h

View File

@ -1,7 +1,7 @@
/** /**
* @brief Auto-generated event translation file. Contains 284 translations. * @brief Auto-generated event translation file. Contains 285 translations.
* @details * @details
* Generated on: 2023-04-04 13:59:07 * Generated on: 2023-04-07 17:42:57
*/ */
#include "translateEvents.h" #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 *CURRENT_IMAGE_INFO_STRING = "CURRENT_IMAGE_INFO";
const char *REBOOT_COUNTER_STRING = "REBOOT_COUNTER"; const char *REBOOT_COUNTER_STRING = "REBOOT_COUNTER";
const char *INDIVIDUAL_BOOT_COUNTS_STRING = "INDIVIDUAL_BOOT_COUNTS"; 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_VALID_SENSOR_TEMPERATURE_STRING = "NO_VALID_SENSOR_TEMPERATURE";
const char *NO_HEALTHY_HEATER_AVAILABLE_STRING = "NO_HEALTHY_HEATER_AVAILABLE"; const char *NO_HEALTHY_HEATER_AVAILABLE_STRING = "NO_HEALTHY_HEATER_AVAILABLE";
const char *SYRLINKS_OVERHEATING_STRING = "SYRLINKS_OVERHEATING"; const char *SYRLINKS_OVERHEATING_STRING = "SYRLINKS_OVERHEATING";
@ -815,7 +816,9 @@ const char *translateEvents(Event event) {
case (14008): case (14008):
return INDIVIDUAL_BOOT_COUNTS_STRING; return INDIVIDUAL_BOOT_COUNTS_STRING;
case (14010): case (14010):
return I2C_UNAVAILABLE_REBOOT_STRING; return TRYING_I2C_RECOVERY_STRING;
case (14011):
return I2C_REBOOT_STRING;
case (14100): case (14100):
return NO_VALID_SENSOR_TEMPERATURE_STRING; return NO_VALID_SENSOR_TEMPERATURE_STRING;
case (14101): case (14101):

View File

@ -2,7 +2,7 @@
* @brief Auto-generated object translation file. * @brief Auto-generated object translation file.
* @details * @details
* Contains 175 translations. * Contains 175 translations.
* Generated on: 2023-04-04 13:59:07 * Generated on: 2023-04-07 17:42:57
*/ */
#include "translateObjects.h" #include "translateObjects.h"

View File

@ -373,7 +373,7 @@ ReturnValue_t AcsBoardPolling::readAdisCfg(SpiCookie& cookie, size_t transferLen
std::string device = spiComIF.getSpiDev(); std::string device = spiComIF.getSpiDev();
UnixFileGuard fileHelper(device, fileDescriptor, O_RDWR, "SpiComIF::sendMessage"); UnixFileGuard fileHelper(device, fileDescriptor, O_RDWR, "SpiComIF::sendMessage");
if (fileHelper.getOpenResult() != returnvalue::OK) { if (fileHelper.getOpenResult() != returnvalue::OK) {
return SpiComIF::OPENING_FILE_FAILED; return spi::OPENING_FILE_FAILED;
} }
spi::SpiModes spiMode = spi::SpiModes::MODE_0; spi::SpiModes spiMode = spi::SpiModes::MODE_0;
uint32_t spiSpeed = 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()); retval = ioctl(fileDescriptor, SPI_IOC_MESSAGE(1), cookie.getTransferStructHandle());
if (retval < 0) { if (retval < 0) {
utility::handleIoctlError("SpiComIF::sendMessage: ioctl error."); utility::handleIoctlError("SpiComIF::sendMessage: ioctl error.");
result = SpiComIF::FULL_DUPLEX_TRANSFER_FAILED; result = spi::FULL_DUPLEX_TRANSFER_FAILED;
} }
#if FSFW_HAL_SPI_WIRETAPPING == 1 #if FSFW_HAL_SPI_WIRETAPPING == 1
comIf->performSpiWiretapping(cookie); comIf->performSpiWiretapping(cookie);

View File

@ -22,6 +22,7 @@ class ImtqPollingTask : public SystemObject,
ReturnValue_t initialize() override; ReturnValue_t initialize() override;
private: private:
//! [EXPORT] : [SKIP]
static constexpr ReturnValue_t NO_REPLY_AVAILABLE = returnvalue::makeCode(2, 0); static constexpr ReturnValue_t NO_REPLY_AVAILABLE = returnvalue::makeCode(2, 0);
enum class InternalState { IDLE, IS_BUSY } state = InternalState::IDLE; enum class InternalState { IDLE, IS_BUSY } state = InternalState::IDLE;

View File

@ -11,6 +11,7 @@
#include <unistd.h> #include <unistd.h>
#include "devConf.h" #include "devConf.h"
#include "mission/acs/defs.h"
#include "mission/acs/rwHelpers.h" #include "mission/acs/rwHelpers.h"
RwPollingTask::RwPollingTask(object_id_t objectId, const char* spiDev, GpioIF& gpioIF) RwPollingTask::RwPollingTask(object_id_t objectId, const char* spiDev, GpioIF& gpioIF)
@ -35,6 +36,7 @@ ReturnValue_t RwPollingTask::performOperation(uint8_t operationCode) {
semaphore->acquire(); semaphore->acquire();
// This loop takes 50 ms on a debug build. // This loop takes 50 ms on a debug build.
// Stopwatch watch; // Stopwatch watch;
// Give all device handlers some time to submit requests.
TaskFactory::delayTask(5); TaskFactory::delayTask(5);
int fd = 0; int fd = 0;
for (auto& skip : skipCommandingForRw) { for (auto& skip : skipCommandingForRw) {
@ -45,13 +47,24 @@ ReturnValue_t RwPollingTask::performOperation(uint8_t operationCode) {
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
continue; continue;
} }
acs::SimpleSensorMode currentMode;
rws::SpecialRwRequest specialRequest;
for (unsigned idx = 0; idx < rwCookies.size(); idx++) { 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); prepareSimpleCommand(rws::RESET_MCU);
// No point in commanding that specific RW for the cycle. // No point in commanding that specific RW for the cycle.
skipCommandingForRw[idx] = true; skipCommandingForRw[idx] = true;
writeOneRwCmd(idx, fd); writeOneRwCmd(idx, fd);
} else if (rwCookies[idx]->setSpeed) { } else if (skipSetSpeedReply[idx]) {
prepareSetSpeedCmd(idx); prepareSetSpeedCmd(idx);
if (writeOneRwCmd(idx, fd) != returnvalue::OK) { if (writeOneRwCmd(idx, fd) != returnvalue::OK) {
continue; continue;
@ -121,31 +134,14 @@ ReturnValue_t RwPollingTask::initializeInterface(CookieIF* cookie) {
ReturnValue_t RwPollingTask::sendMessage(CookieIF* cookie, const uint8_t* sendData, ReturnValue_t RwPollingTask::sendMessage(CookieIF* cookie, const uint8_t* sendData,
size_t sendLen) { size_t sendLen) {
if (sendData == nullptr or sendLen < 8) { if (sendData == nullptr or sendLen != sizeof(rws::RwRequest)) {
return DeviceHandlerIF::INVALID_DATA; return DeviceHandlerIF::INVALID_DATA;
} }
int32_t speed = 0; const rws::RwRequest* rwRequest = reinterpret_cast<const rws::RwRequest*>(sendData);
uint16_t rampTime = 0; uint8_t rwIdx = rwRequest->rwIdx;
const uint8_t* currentBuf = sendData;
bool setSpeed = currentBuf[0];
currentBuf += 1;
sendLen -= 1;
SerializeAdapter::deSerialize(&speed, &currentBuf, &sendLen, SerializeIF::Endianness::MACHINE);
SerializeAdapter::deSerialize(&rampTime, &currentBuf, &sendLen, SerializeIF::Endianness::MACHINE);
rws::SpecialRwRequest specialRequest = rws::SpecialRwRequest::REQUEST_NONE;
if (sendLen == 8 and sendData[7] < static_cast<uint8_t>(rws::SpecialRwRequest::NUM_REQUESTS)) {
specialRequest = static_cast<rws::SpecialRwRequest>(sendData[7]);
}
RwCookie* rwCookie = dynamic_cast<RwCookie*>(cookie);
if (rwCookie == nullptr) {
return returnvalue::FAILED;
}
{ {
MutexGuard mg(ipcLock); MutexGuard mg(ipcLock);
rwCookie->setSpeed = setSpeed; std::memcpy(&rwRequests[rwIdx], rwRequest, sizeof(rws::RwRequest));
rwCookie->currentRwSpeed = speed;
rwCookie->currentRampTime = rampTime;
rwCookie->specialRequest = specialRequest;
if (state == InternalState::IDLE) { if (state == InternalState::IDLE) {
state = InternalState::IS_BUSY; state = InternalState::IS_BUSY;
semaphore->release(); semaphore->release();
@ -202,7 +198,7 @@ ReturnValue_t RwPollingTask::openSpi(int flags, int& fd) {
fd = open(spiDev, flags); fd = open(spiDev, flags);
if (fd < 0) { if (fd < 0) {
sif::error << "RwPollingTask::openSpi: Failed to open device file" << std::endl; sif::error << "RwPollingTask::openSpi: Failed to open device file" << std::endl;
return SpiComIF::OPENING_FILE_FAILED; return spi::OPENING_FILE_FAILED;
} }
return returnvalue::OK; return returnvalue::OK;
@ -332,7 +328,7 @@ ReturnValue_t RwPollingTask::writeOneRwCmd(uint8_t rwIdx, int fd) {
ReturnValue_t RwPollingTask::readAllRws(DeviceCommandId_t id) { ReturnValue_t RwPollingTask::readAllRws(DeviceCommandId_t id) {
// SPI dev will be opened in readNextReply on demand. // SPI dev will be opened in readNextReply on demand.
for (unsigned idx = 0; idx < rwCookies.size(); idx++) { 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; continue;
} }
uint8_t* replyBuf; uint8_t* replyBuf;
@ -395,7 +391,7 @@ void RwPollingTask::fillSpecialRequestArray() {
specialRequestIds[idx] = DeviceHandlerIF::NO_COMMAND_ID; specialRequestIds[idx] = DeviceHandlerIF::NO_COMMAND_ID;
continue; continue;
} }
switch (rwCookies[idx]->specialRequest) { switch (rwRequests[idx].specialRequest) {
case (rws::SpecialRwRequest::GET_TM): { case (rws::SpecialRwRequest::GET_TM): {
specialRequestIds[idx] = rws::GET_TM; specialRequestIds[idx] = rws::GET_TM;
break; break;
@ -426,14 +422,14 @@ void RwPollingTask::handleSpecialRequests() {
writeOneRwCmd(idx, fd); writeOneRwCmd(idx, fd);
} }
closeSpi(fd); closeSpi(fd);
usleep(rws::SPI_REPLY_DELAY);
for (unsigned idx = 0; idx < rwCookies.size(); idx++) { for (unsigned idx = 0; idx < rwCookies.size(); idx++) {
if (specialRequestIds[idx] == DeviceHandlerIF::NO_COMMAND_ID) { if (specialRequestIds[idx] == DeviceHandlerIF::NO_COMMAND_ID) {
continue; continue;
} }
uint8_t* replyBuf; uint8_t* replyBuf;
size_t maxReadLen = idAndIdxToReadBuffer(specialRequestIds[idx], idx, &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) { if (result == returnvalue::OK) {
// The first byte is always a flag which shows whether the value was read // The first byte is always a flag which shows whether the value was read
// properly at least once. // properly at least once.
@ -455,17 +451,12 @@ void RwPollingTask::setAllReadFlagsFalse() {
} }
} }
// This closes the SPI void RwPollingTask::closeSpi(int fd) { close(fd); }
void RwPollingTask::closeSpi(int fd) {
// This will perform the function to close the SPI
close(fd);
// The SPI is now closed.
}
ReturnValue_t RwPollingTask::sendOneMessage(int fd, RwCookie& rwCookie) { ReturnValue_t RwPollingTask::sendOneMessage(int fd, RwCookie& rwCookie) {
gpioId_t gpioId = rwCookie.getChipSelectPin(); gpioId_t gpioId = rwCookie.getChipSelectPin();
if (spiLock == nullptr) { 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; return returnvalue::FAILED;
} }
// Add datalinklayer like specified in the datasheet. // 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); rws::encodeHdlc(writeBuffer.data(), writeLen, encodedBuffer.data(), lenToSend);
pullCsLow(gpioId, gpioIF); pullCsLow(gpioId, gpioIF);
if (write(fd, encodedBuffer.data(), lenToSend) != static_cast<ssize_t>(lenToSend)) { if (write(fd, encodedBuffer.data(), lenToSend) != static_cast<ssize_t>(lenToSend)) {
sif::error << "rwSpiCallback::spiCallback: Write failed!" << std::endl; sif::error << "RwPollingTask: Write failed!" << std::endl;
pullCsHigh(gpioId, gpioIF); pullCsHigh(gpioId, gpioIF);
return rws::SPI_WRITE_FAILURE; 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 RwPollingTask::pullCsLow(gpioId_t gpioId, GpioIF& gpioIF) {
ReturnValue_t result = spiLock->lockMutex(TIMEOUT_TYPE, TIMEOUT_MS); ReturnValue_t result = spiLock->lockMutex(TIMEOUT_TYPE, TIMEOUT_MS);
if (result != returnvalue::OK) { 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; return result;
} }
// Pull SPI CS low. For now, no support for active high given // 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; uint16_t rampTimeToSet = 10;
{ {
MutexGuard mg(ipcLock); MutexGuard mg(ipcLock);
speedToSet = rwCookies[rwIdx]->currentRwSpeed; speedToSet = rwRequests[rwIdx].currentRwSpeed;
rampTimeToSet = rwCookies[rwIdx]->currentRampTime; rampTimeToSet = rwRequests[rwIdx].currentRampTime;
} }
size_t serLen = 1; size_t serLen = 1;
SerializeAdapter::serialize(&speedToSet, &serPtr, &serLen, writeBuffer.size(), SerializeAdapter::serialize(&speedToSet, &serPtr, &serLen, writeBuffer.size(),

View File

@ -8,6 +8,7 @@
#include <fsfw_hal/common/gpio/GpioIF.h> #include <fsfw_hal/common/gpio/GpioIF.h>
#include <fsfw_hal/linux/spi/SpiComIF.h> #include <fsfw_hal/linux/spi/SpiComIF.h>
#include <fsfw_hal/linux/spi/SpiCookie.h> #include <fsfw_hal/linux/spi/SpiCookie.h>
#include <mission/acs/defs.h>
#include "mission/acs/rwHelpers.h" #include "mission/acs/rwHelpers.h"
@ -26,10 +27,6 @@ class RwCookie : public SpiCookie {
std::array<uint8_t, REPLY_BUF_LEN> replyBuf{}; std::array<uint8_t, REPLY_BUF_LEN> replyBuf{};
std::array<uint8_t, REPLY_BUF_LEN> exchangeBuf{}; std::array<uint8_t, REPLY_BUF_LEN> exchangeBuf{};
MutexIF* bufLock; MutexIF* bufLock;
bool setSpeed = true;
int32_t currentRwSpeed = 0;
uint16_t currentRampTime = 0;
rws::SpecialRwRequest specialRequest = rws::SpecialRwRequest::REQUEST_NONE;
uint8_t rwIdx; uint8_t rwIdx;
}; };
@ -50,8 +47,10 @@ class RwPollingTask : public SystemObject, public ExecutableObjectIF, public Dev
const char* spiDev; const char* spiDev;
GpioIF& gpioIF; GpioIF& gpioIF;
std::array<bool, 4> skipCommandingForRw; std::array<bool, 4> skipCommandingForRw;
std::array<bool, 4> skipSetSpeedReply;
std::array<DeviceCommandId_t, 4> specialRequestIds; std::array<DeviceCommandId_t, 4> specialRequestIds;
std::array<RwCookie*, 4> rwCookies; std::array<RwCookie*, 4> rwCookies;
std::array<rws::RwRequest, 4> rwRequests{};
std::array<uint8_t, rws::MAX_CMD_SIZE> writeBuffer; std::array<uint8_t, rws::MAX_CMD_SIZE> writeBuffer;
std::array<uint8_t, rws::MAX_CMD_SIZE * 2> encodedBuffer; std::array<uint8_t, rws::MAX_CMD_SIZE * 2> encodedBuffer;

View File

@ -37,7 +37,7 @@ void I2cTestClass::battInit() {
if (ioctl(bpxInfo.fd, I2C_SLAVE, bpxInfo.addr) < 0) { if (ioctl(bpxInfo.fd, I2C_SLAVE, bpxInfo.addr) < 0) {
sif::error << "Failed to acquire bus access and/or talk to slave" << std::endl; 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; cmdBuf[1] = 0x42;
sendLen = 2; sendLen = 2;
ReturnValue_t result = i2cWrite(bpxInfo.fd, cmdBuf.data(), sendLen); 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) { if (ioctl(bpxInfo.fd, I2C_SLAVE, bpxInfo.addr) < 0) {
sif::error << "Failed to acquire bus access and/or talk to slave" << std::endl; 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; sendLen = 1;
ReturnValue_t result = i2cWrite(bpxInfo.fd, cmdBuf.data(), sendLen); ReturnValue_t result = i2cWrite(bpxInfo.fd, cmdBuf.data(), sendLen);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {

View File

@ -20,6 +20,7 @@ class SyrlinksComHandler : public DeviceCommunicationIF,
//! [EXPORT] : [SKIP] //! [EXPORT] : [SKIP]
static constexpr ReturnValue_t NO_SERIAL_DATA_READ = returnvalue::makeCode(2, 0); 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); static constexpr ReturnValue_t NO_PACKET_FOUND = returnvalue::makeCode(2, 1);
enum class State { SLEEPING, ACTIVE } state = State::SLEEPING; enum class State { SLEEPING, ACTIVE } state = State::SLEEPING;

View File

@ -1,7 +1,7 @@
/** /**
* @brief Auto-generated event translation file. Contains 284 translations. * @brief Auto-generated event translation file. Contains 285 translations.
* @details * @details
* Generated on: 2023-04-04 13:59:07 * Generated on: 2023-04-07 17:42:57
*/ */
#include "translateEvents.h" #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 *CURRENT_IMAGE_INFO_STRING = "CURRENT_IMAGE_INFO";
const char *REBOOT_COUNTER_STRING = "REBOOT_COUNTER"; const char *REBOOT_COUNTER_STRING = "REBOOT_COUNTER";
const char *INDIVIDUAL_BOOT_COUNTS_STRING = "INDIVIDUAL_BOOT_COUNTS"; 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_VALID_SENSOR_TEMPERATURE_STRING = "NO_VALID_SENSOR_TEMPERATURE";
const char *NO_HEALTHY_HEATER_AVAILABLE_STRING = "NO_HEALTHY_HEATER_AVAILABLE"; const char *NO_HEALTHY_HEATER_AVAILABLE_STRING = "NO_HEALTHY_HEATER_AVAILABLE";
const char *SYRLINKS_OVERHEATING_STRING = "SYRLINKS_OVERHEATING"; const char *SYRLINKS_OVERHEATING_STRING = "SYRLINKS_OVERHEATING";
@ -815,7 +816,9 @@ const char *translateEvents(Event event) {
case (14008): case (14008):
return INDIVIDUAL_BOOT_COUNTS_STRING; return INDIVIDUAL_BOOT_COUNTS_STRING;
case (14010): case (14010):
return I2C_UNAVAILABLE_REBOOT_STRING; return TRYING_I2C_RECOVERY_STRING;
case (14011):
return I2C_REBOOT_STRING;
case (14100): case (14100):
return NO_VALID_SENSOR_TEMPERATURE_STRING; return NO_VALID_SENSOR_TEMPERATURE_STRING;
case (14101): case (14101):

View File

@ -2,7 +2,7 @@
* @brief Auto-generated object translation file. * @brief Auto-generated object translation file.
* @details * @details
* Contains 175 translations. * Contains 175 translations.
* Generated on: 2023-04-04 13:59:07 * Generated on: 2023-04-07 17:42:57
*/ */
#include "translateObjects.h" #include "translateObjects.h"

View File

@ -10,6 +10,7 @@
class ScexHelper : public SerializeIF { class ScexHelper : public SerializeIF {
public: public:
//! [EXPORT] : [SKIP]
static const ReturnValue_t INVALID_CRC = returnvalue::makeCode(0, 2); static const ReturnValue_t INVALID_CRC = returnvalue::makeCode(0, 2);
ScexHelper(); ScexHelper();

View File

@ -4,6 +4,7 @@
#include <fsfw/globalfunctions/CRC.h> #include <fsfw/globalfunctions/CRC.h>
#include <fsfw/globalfunctions/arrayprinter.h> #include <fsfw/globalfunctions/arrayprinter.h>
#include <fsfw_hal/common/gpio/GpioIF.h> #include <fsfw_hal/common/gpio/GpioIF.h>
#include <mission/acs/defs.h>
#include "OBSWConfig.h" #include "OBSWConfig.h"
@ -23,44 +24,52 @@ RwHandler::RwHandler(object_id_t objectId, object_id_t comIF, CookieIF* comCooki
if (gpioComIF == nullptr) { if (gpioComIF == nullptr) {
sif::error << "RwHandler: Invalid gpio communication interface" << std::endl; sif::error << "RwHandler: Invalid gpio communication interface" << std::endl;
} }
currentRequest.rwIdx = rwIdx;
} }
RwHandler::~RwHandler() {} RwHandler::~RwHandler() {}
void RwHandler::doStartUp() { void RwHandler::doStartUp() {
internalState = InternalState::DEFAULT; internalState = InternalState::DEFAULT;
if (gpioComIF->pullHigh(enableGpio) != returnvalue::OK) { 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); updatePeriodicReply(true, rws::REPLY_ID);
statusSet.setReportingEnabled(true); statusSet.setReportingEnabled(true);
setMode(_MODE_TO_ON); setMode(_MODE_TO_ON);
} }
void RwHandler::doShutDown() { void RwHandler::doShutDown() {
if (gpioComIF->pullLow(enableGpio) != returnvalue::OK) { if (internalState != InternalState::SHUTDOWN) {
sif::debug << "RwHandler::doStartUp: Failed to pull enable gpio to low"; internalState = InternalState::SHUTDOWN;
shutdownState = ShutdownState::SET_SPEED_ZERO;
offTransitionCountdown.resetTimer();
} }
internalState = InternalState::DEFAULT; if ((internalState == InternalState::SHUTDOWN) and
updatePeriodicReply(false, rws::REPLY_ID); (shutdownState == ShutdownState::DONE or offTransitionCountdown.hasTimedOut())) {
{ if (gpioComIF->pullLow(enableGpio) != returnvalue::OK) {
PoolReadGuard pg(&statusSet); sif::error << "RW Handler " << rwIdx << ": Failed to pull ENABLE pin low for shutdown";
statusSet.currSpeed = 0.0; }
statusSet.referenceSpeed = 0.0; updatePeriodicReply(false, rws::REPLY_ID);
statusSet.state = 0; {
statusSet.setValidity(false, true); PoolReadGuard pg(&statusSet);
statusSet.setReportingEnabled(false); 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) { 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) { 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; return NOTHING_TO_SEND;
} }
@ -119,32 +142,36 @@ ReturnValue_t RwHandler::buildCommandFromCommand(DeviceCommandId_t deviceCommand
return result; return result;
} }
// set speed flag. // set speed flag.
commandBuffer[0] = true; currentRequest.setSpeed = true;
rawPacketLen = 1; rwSpeedActuationSet.getRwSpeed(currentRequest.currentRwSpeed, currentRequest.currentRampTime);
uint8_t* currentCmdBuf = commandBuffer + 1; currentRequest.specialRequest = rws::SpecialRwRequest::REQUEST_NONE;
rwSpeedActuationSet.serialize(&currentCmdBuf, &rawPacketLen, sizeof(commandBuffer), rawPacket = reinterpret_cast<uint8_t*>(&currentRequest);
SerializeIF::Endianness::MACHINE); rawPacketLen = sizeof(rws::RwRequest);
commandBuffer[rawPacketLen++] = static_cast<uint8_t>(rws::SpecialRwRequest::REQUEST_NONE);
rawPacket = commandBuffer;
return returnvalue::OK; return returnvalue::OK;
} }
case (rws::RESET_MCU): { case (rws::RESET_MCU): {
commandBuffer[0] = false; currentRequest.setSpeed = false;
commandBuffer[7] = static_cast<uint8_t>(rws::SpecialRwRequest::RESET_MCU); currentRequest.specialRequest = rws::SpecialRwRequest::RESET_MCU;
internalState = InternalState::RESET_MCU; internalState = InternalState::RESET_MCU;
rawPacket = reinterpret_cast<uint8_t*>(&currentRequest);
rawPacketLen = sizeof(rws::RwRequest);
return returnvalue::OK; return returnvalue::OK;
} }
case (rws::INIT_RW_CONTROLLER): { case (rws::INIT_RW_CONTROLLER): {
commandBuffer[0] = false; currentRequest.setSpeed = false;
commandBuffer[7] = static_cast<uint8_t>(rws::SpecialRwRequest::INIT_RW_CONTROLLER); currentRequest.specialRequest = rws::SpecialRwRequest::INIT_RW_CONTROLLER;
internalState = InternalState::INIT_RW_CONTROLLER; internalState = InternalState::INIT_RW_CONTROLLER;
rawPacket = reinterpret_cast<uint8_t*>(&currentRequest);
rawPacketLen = sizeof(rws::RwRequest);
return returnvalue::OK; return returnvalue::OK;
} }
case (rws::GET_TM): { case (rws::GET_TM): {
commandBuffer[0] = false; currentRequest.setSpeed = false;
commandBuffer[7] = static_cast<uint8_t>(rws::SpecialRwRequest::GET_TM); currentRequest.specialRequest = rws::SpecialRwRequest::GET_TM;
internalState = InternalState::GET_TM; internalState = InternalState::GET_TM;
rawPacket = reinterpret_cast<uint8_t*>(&currentRequest);
rawPacketLen = sizeof(rws::RwRequest);
return returnvalue::OK; return returnvalue::OK;
} }
default: default:
@ -172,6 +199,9 @@ ReturnValue_t RwHandler::scanForReply(const uint8_t* start, size_t remainingSize
*foundLen = remainingSize; *foundLen = remainingSize;
*foundId = rws::REPLY_ID; *foundId = rws::REPLY_ID;
} }
if (internalState == InternalState::SHUTDOWN and shutdownState == ShutdownState::STOP_POLLING) {
shutdownState = ShutdownState::DONE;
}
return returnvalue::OK; return returnvalue::OK;
} }
@ -381,6 +411,12 @@ void RwHandler::handleGetRwStatusReply(const uint8_t* packet) {
statusSet.setValidity(true, true); 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) { if (statusSet.state == rws::STATE_ERROR) {
// Trigger FDIR reaction, first recovery, then faulty if it doesnt fix the issue. // Trigger FDIR reaction, first recovery, then faulty if it doesnt fix the issue.
triggerEvent(DeviceHandlerIF::DEVICE_WANTS_HARD_REBOOT, statusSet.state.value, 0); triggerEvent(DeviceHandlerIF::DEVICE_WANTS_HARD_REBOOT, statusSet.state.value, 0);

View File

@ -75,6 +75,8 @@ class RwHandler : public DeviceHandlerBase {
GpioIF* gpioComIF = nullptr; GpioIF* gpioComIF = nullptr;
gpioId_t enableGpio = gpio::NO_GPIO; gpioId_t enableGpio = gpio::NO_GPIO;
bool debugMode = false; bool debugMode = false;
Countdown offTransitionCountdown = Countdown(5000);
rws::RwRequest currentRequest;
rws::StatusSet statusSet; rws::StatusSet statusSet;
rws::LastResetSatus lastResetStatusSet; rws::LastResetSatus lastResetStatusSet;
@ -87,27 +89,16 @@ class RwHandler : public DeviceHandlerBase {
PoolEntry<int32_t> rwSpeed = PoolEntry<int32_t>({0}); PoolEntry<int32_t> rwSpeed = PoolEntry<int32_t>({0});
PoolEntry<uint16_t> rampTime = PoolEntry<uint16_t>({10}); PoolEntry<uint16_t> rampTime = PoolEntry<uint16_t>({10});
enum class InternalState { enum class InternalState { DEFAULT, GET_TM, INIT_RW_CONTROLLER, RESET_MCU, SHUTDOWN };
DEFAULT, enum class ShutdownState {
GET_TM, NONE,
INIT_RW_CONTROLLER, SET_SPEED_ZERO,
RESET_MCU, STOP_POLLING,
// GET_RESET_STATUS, DONE,
// CLEAR_RESET_STATUS, } shutdownState = ShutdownState::NONE;
// READ_TEMPERATURE,
// SET_SPEED,
// GET_RW_SATUS
};
InternalState internalState = InternalState::DEFAULT; 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 * @brief This function checks if the receiced speed and ramp time to set are in a valid
* range. * range.
@ -115,13 +106,6 @@ class RwHandler : public DeviceHandlerBase {
*/ */
ReturnValue_t checkSpeedAndRampTime(); 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 * @brief This function writes the last reset status retrieved with the get last reset status
* command into the reset status dataset. * command into the reset status dataset.

View File

@ -4,6 +4,7 @@
#include <fsfw/datapoollocal/LocalPoolVariable.h> #include <fsfw/datapoollocal/LocalPoolVariable.h>
#include <fsfw/datapoollocal/StaticLocalDataSet.h> #include <fsfw/datapoollocal/StaticLocalDataSet.h>
#include <fsfw/devicehandlers/DeviceHandlerIF.h> #include <fsfw/devicehandlers/DeviceHandlerIF.h>
#include <mission/acs/defs.h>
#include "eive/resultClassIds.h" #include "eive/resultClassIds.h"
#include "events/subsystemIdRanges.h" #include "events/subsystemIdRanges.h"
@ -36,6 +37,15 @@ enum class SpecialRwRequest : uint8_t {
NUM_REQUESTS 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 uint8_t INTERFACE_ID = CLASS_ID::RW_HANDLER;
static const ReturnValue_t SPI_WRITE_FAILURE = MAKE_RETURN_CODE(0xB0); static const ReturnValue_t SPI_WRITE_FAILURE = MAKE_RETURN_CODE(0xB0);

View File

@ -45,6 +45,10 @@ ReturnValue_t PersistentLogTmStoreTask::performOperation(uint8_t opCode) {
// TODO: Might not be necessary // TODO: Might not be necessary
sif::debug << "VC busy, delaying" << std::endl; sif::debug << "VC busy, delaying" << std::endl;
TaskFactory::delayTask(10); 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);
} }
} }
} }

View File

@ -29,6 +29,7 @@ ReturnValue_t PersistentSingleTmStoreTask::performOperation(uint8_t opCode) {
TaskFactory::delayTask(10); TaskFactory::delayTask(10);
} else { } else {
// TODO: Would be best to remove this, but not delaying here can lead to evil issues. // 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); TaskFactory::delayTask(2);
} }
} }

View File

@ -182,14 +182,10 @@ class ThermalController : public ExtendedControllerBase {
susMax1227::SusDataset susSet11; susMax1227::SusDataset susSet11;
lp_var_t<float> tempQ7s = lp_var_t<float>(objects::CORE_CONTROLLER, core::PoolIds::TEMPERATURE); lp_var_t<float> tempQ7s = lp_var_t<float>(objects::CORE_CONTROLLER, core::PoolIds::TEMPERATURE);
lp_var_t<int16_t> battTemp1 = lp_var_t<int16_t> battTemp1 = lp_var_t<int16_t>(objects::BPX_BATT_HANDLER, bpxBat::BATT_TEMP_1);
lp_var_t<int16_t>(objects::BPX_BATT_HANDLER, BpxBattery::BATT_TEMP_1); lp_var_t<int16_t> battTemp2 = lp_var_t<int16_t>(objects::BPX_BATT_HANDLER, bpxBat::BATT_TEMP_2);
lp_var_t<int16_t> battTemp2 = lp_var_t<int16_t> battTemp3 = lp_var_t<int16_t>(objects::BPX_BATT_HANDLER, bpxBat::BATT_TEMP_3);
lp_var_t<int16_t>(objects::BPX_BATT_HANDLER, BpxBattery::BATT_TEMP_2); lp_var_t<int16_t> battTemp4 = lp_var_t<int16_t>(objects::BPX_BATT_HANDLER, bpxBat::BATT_TEMP_4);
lp_var_t<int16_t> battTemp3 =
lp_var_t<int16_t>(objects::BPX_BATT_HANDLER, BpxBattery::BATT_TEMP_3);
lp_var_t<int16_t> battTemp4 =
lp_var_t<int16_t>(objects::BPX_BATT_HANDLER, BpxBattery::BATT_TEMP_4);
lp_var_t<int32_t> tempRw1 = lp_var_t<int32_t>(objects::RW1, rws::TEMPERATURE_C); lp_var_t<int32_t> tempRw1 = lp_var_t<int32_t>(objects::RW1, rws::TEMPERATURE_C);
lp_var_t<int32_t> tempRw2 = lp_var_t<int32_t>(objects::RW2, rws::TEMPERATURE_C); lp_var_t<int32_t> tempRw2 = lp_var_t<int32_t>(objects::RW2, rws::TEMPERATURE_C);
lp_var_t<int32_t> tempRw3 = lp_var_t<int32_t>(objects::RW3, rws::TEMPERATURE_C); lp_var_t<int32_t> tempRw3 = lp_var_t<int32_t>(objects::RW3, rws::TEMPERATURE_C);

View File

@ -726,7 +726,7 @@ ReturnValue_t PayloadPcduHandler::transferAsTwo(SpiComIF* comIf, SpiCookie* cook
int fileDescriptor = 0; int fileDescriptor = 0;
UnixFileGuard fileHelper(comIf->getSpiDev(), fileDescriptor, O_RDWR, "SpiComIF::sendMessage"); UnixFileGuard fileHelper(comIf->getSpiDev(), fileDescriptor, O_RDWR, "SpiComIF::sendMessage");
if (fileHelper.getOpenResult() != returnvalue::OK) { if (fileHelper.getOpenResult() != returnvalue::OK) {
return SpiComIF::OPENING_FILE_FAILED; return spi::OPENING_FILE_FAILED;
} }
spi::SpiModes spiMode = spi::SpiModes::MODE_0; spi::SpiModes spiMode = spi::SpiModes::MODE_0;
uint32_t spiSpeed = 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()); retval = ioctl(fileDescriptor, SPI_IOC_MESSAGE(1), cookie->getTransferStructHandle());
if (retval < 0) { if (retval < 0) {
utility::handleIoctlError("SpiComIF::sendMessage: ioctl error."); utility::handleIoctlError("SpiComIF::sendMessage: ioctl error.");
result = SpiComIF::FULL_DUPLEX_TRANSFER_FAILED; result = spi::FULL_DUPLEX_TRANSFER_FAILED;
} }
#if FSFW_HAL_SPI_WIRETAPPING == 1 #if FSFW_HAL_SPI_WIRETAPPING == 1
comIf->performSpiWiretapping(cookie); comIf->performSpiWiretapping(cookie);
@ -804,7 +804,7 @@ ReturnValue_t PayloadPcduHandler::transferAsTwo(SpiComIF* comIf, SpiCookie* cook
retval = ioctl(fileDescriptor, SPI_IOC_MESSAGE(1), cookie->getTransferStructHandle()); retval = ioctl(fileDescriptor, SPI_IOC_MESSAGE(1), cookie->getTransferStructHandle());
if (retval < 0) { if (retval < 0) {
utility::handleIoctlError("SpiComIF::sendMessage: ioctl error."); utility::handleIoctlError("SpiComIF::sendMessage: ioctl error.");
result = SpiComIF::FULL_DUPLEX_TRANSFER_FAILED; result = spi::FULL_DUPLEX_TRANSFER_FAILED;
} }
#if FSFW_HAL_SPI_WIRETAPPING == 1 #if FSFW_HAL_SPI_WIRETAPPING == 1
comIf->performSpiWiretapping(cookie); comIf->performSpiWiretapping(cookie);

View File

@ -27,54 +27,56 @@ void BpxBatteryHandler::doStartUp() {
void BpxBatteryHandler::doShutDown() { void BpxBatteryHandler::doShutDown() {
// Perform a COM check on reboot // Perform a COM check on reboot
state = States::CHECK_COM; state = States::CHECK_COM;
setMode(MODE_OFF);
} }
ReturnValue_t BpxBatteryHandler::buildNormalDeviceCommand(DeviceCommandId_t* id) { ReturnValue_t BpxBatteryHandler::buildNormalDeviceCommand(DeviceCommandId_t* id) {
*id = BpxBattery::GET_HK; *id = bpxBat::GET_HK;
return buildCommandFromCommand(*id, nullptr, 0); return buildCommandFromCommand(*id, nullptr, 0);
} }
ReturnValue_t BpxBatteryHandler::buildTransitionDeviceCommand(DeviceCommandId_t* id) { ReturnValue_t BpxBatteryHandler::buildTransitionDeviceCommand(DeviceCommandId_t* id) {
if (state == States::CHECK_COM) { if (state == States::CHECK_COM) {
*id = BpxBattery::PING; *id = bpxBat::PING;
return buildCommandFromCommand(*id, nullptr, 0); return buildCommandFromCommand(*id, nullptr, 0);
} }
return returnvalue::OK; return returnvalue::OK;
} }
void BpxBatteryHandler::fillCommandAndReplyMap() { void BpxBatteryHandler::fillCommandAndReplyMap() {
using namespace BpxBattery; using namespace bpxBat;
insertInCommandAndReplyMap(GET_HK, 1, &hkSet, GET_HK_REPLY_LEN); insertInCommandAndReplyMap(GET_HK, 1, &hkSet, GET_HK_REPLY_LEN);
insertInCommandAndReplyMap(BpxBattery::PING, 1, nullptr, PING_REPLY_LEN); insertInCommandAndReplyMap(bpxBat::PING, 1, nullptr, PING_REPLY_LEN);
insertInCommandAndReplyMap(BpxBattery::REBOOT, 1, nullptr, 0); insertInCommandAndReplyMap(bpxBat::REBOOT, 1, nullptr, 0);
insertInCommandAndReplyMap(BpxBattery::RESET_COUNTERS, 1, nullptr, EMPTY_REPLY_LEN); insertInCommandAndReplyMap(bpxBat::RESET_COUNTERS, 1, nullptr, EMPTY_REPLY_LEN);
insertInCommandAndReplyMap(BpxBattery::CONFIG_CMD, 1, nullptr, EMPTY_REPLY_LEN); insertInCommandAndReplyMap(bpxBat::CONFIG_CMD, 1, nullptr, EMPTY_REPLY_LEN);
insertInCommandAndReplyMap(BpxBattery::CONFIG_GET, 1, &cfgSet, CONFIG_GET_REPLY_LEN); insertInCommandAndReplyMap(bpxBat::CONFIG_GET, 1, &cfgSet, CONFIG_GET_REPLY_LEN);
} }
ReturnValue_t BpxBatteryHandler::buildCommandFromCommand(DeviceCommandId_t deviceCommand, ReturnValue_t BpxBatteryHandler::buildCommandFromCommand(DeviceCommandId_t deviceCommand,
const uint8_t* commandData, const uint8_t* commandData,
size_t commandDataLen) { size_t commandDataLen) {
switch (deviceCommand) { switch (deviceCommand) {
case (BpxBattery::GET_HK): { case (bpxBat::GET_HK): {
cmdBuf[0] = BpxBattery::PORT_GET_HK; cmdBuf[0] = bpxBat::PORT_GET_HK;
this->rawPacketLen = 1; this->rawPacketLen = 1;
break; break;
} }
case (BpxBattery::PING): { case (bpxBat::PING): {
if (commandDataLen == 1 and commandData != nullptr) { if (commandDataLen == 1 and commandData != nullptr) {
sentPingByte = commandData[0]; sentPingByte = commandData[0];
} else { } 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; cmdBuf[1] = sentPingByte;
this->rawPacketLen = 2; this->rawPacketLen = 2;
break; break;
} }
case (BpxBattery::REBOOT): { case (bpxBat::REBOOT): {
cmdBuf[0] = BpxBattery::PORT_REBOOT; sif::info << "BPX BATT: Executing reboot command" << std::endl;
cmdBuf[0] = bpxBat::PORT_REBOOT;
cmdBuf[1] = 0x80; cmdBuf[1] = 0x80;
cmdBuf[2] = 0x07; cmdBuf[2] = 0x07;
cmdBuf[3] = 0x80; cmdBuf[3] = 0x80;
@ -85,26 +87,26 @@ ReturnValue_t BpxBatteryHandler::buildCommandFromCommand(DeviceCommandId_t devic
triggerEvent(DeviceHandlerIF::DEVICE_WANTS_HARD_REBOOT); triggerEvent(DeviceHandlerIF::DEVICE_WANTS_HARD_REBOOT);
break; break;
} }
case (BpxBattery::RESET_COUNTERS): { case (bpxBat::RESET_COUNTERS): {
cmdBuf[0] = BpxBattery::PORT_RESET_COUNTERS; cmdBuf[0] = bpxBat::PORT_RESET_COUNTERS;
cmdBuf[1] = BpxBattery::RESET_COUNTERS_MAGIC_VALUE; cmdBuf[1] = bpxBat::RESET_COUNTERS_MAGIC_VALUE;
this->rawPacketLen = 2; this->rawPacketLen = 2;
break; break;
} }
case (BpxBattery::CONFIG_CMD): { case (bpxBat::CONFIG_CMD): {
cmdBuf[0] = BpxBattery::PORT_CONFIG_CMD; cmdBuf[0] = bpxBat::PORT_CONFIG_CMD;
// Needs to be set to 0x01 according to datasheet // Needs to be set to 0x01 according to datasheet
cmdBuf[1] = 0x01; cmdBuf[1] = 0x01;
this->rawPacketLen = 2; this->rawPacketLen = 2;
break; break;
} }
case (BpxBattery::CONFIG_GET): { case (bpxBat::CONFIG_GET): {
cmdBuf[0] = BpxBattery::PORT_CONFIG_GET; cmdBuf[0] = bpxBat::PORT_CONFIG_GET;
this->rawPacketLen = 1; this->rawPacketLen = 1;
break; break;
} }
case (BpxBattery::CONFIG_SET): { case (bpxBat::CONFIG_SET): {
cmdBuf[0] = BpxBattery::PORT_CONFIG_SET; cmdBuf[0] = bpxBat::PORT_CONFIG_SET;
if (commandDataLen != 3) { if (commandDataLen != 3) {
return DeviceHandlerIF::INVALID_NUMBER_OR_LENGTH_OF_PARAMETERS; return DeviceHandlerIF::INVALID_NUMBER_OR_LENGTH_OF_PARAMETERS;
} }
@ -114,8 +116,8 @@ ReturnValue_t BpxBatteryHandler::buildCommandFromCommand(DeviceCommandId_t devic
this->rawPacketLen = 4; this->rawPacketLen = 4;
break; break;
} }
case (BpxBattery::MAN_HEAT_ON): { case (bpxBat::MAN_HEAT_ON): {
cmdBuf[0] = BpxBattery::PORT_MAN_HEAT_ON; cmdBuf[0] = bpxBat::PORT_MAN_HEAT_ON;
if (commandDataLen != 2) { if (commandDataLen != 2) {
return DeviceHandlerIF::INVALID_NUMBER_OR_LENGTH_OF_PARAMETERS; return DeviceHandlerIF::INVALID_NUMBER_OR_LENGTH_OF_PARAMETERS;
} }
@ -125,8 +127,8 @@ ReturnValue_t BpxBatteryHandler::buildCommandFromCommand(DeviceCommandId_t devic
this->rawPacketLen = 3; this->rawPacketLen = 3;
break; break;
} }
case (BpxBattery::MAN_HEAT_OFF): { case (bpxBat::MAN_HEAT_OFF): {
cmdBuf[0] = BpxBattery::PORT_MAN_HEAT_OFF; cmdBuf[0] = bpxBat::PORT_MAN_HEAT_OFF;
this->rawPacketLen = 1; this->rawPacketLen = 1;
break; break;
} }
@ -142,35 +144,35 @@ ReturnValue_t BpxBatteryHandler::buildCommandFromCommand(DeviceCommandId_t devic
ReturnValue_t BpxBatteryHandler::scanForReply(const uint8_t* start, size_t remainingSize, ReturnValue_t BpxBatteryHandler::scanForReply(const uint8_t* start, size_t remainingSize,
DeviceCommandId_t* foundId, size_t* foundLen) { DeviceCommandId_t* foundId, size_t* foundLen) {
using namespace BpxBattery; using namespace bpxBat;
switch (lastCmd) { switch (lastCmd) {
case (BpxBattery::GET_HK): { case (bpxBat::GET_HK): {
if (remainingSize != GET_HK_REPLY_LEN) { if (remainingSize != GET_HK_REPLY_LEN) {
return DeviceHandlerIF::LENGTH_MISSMATCH; return DeviceHandlerIF::LENGTH_MISSMATCH;
} }
break; break;
} }
case (BpxBattery::PING): case (bpxBat::PING):
case (BpxBattery::MAN_HEAT_ON): case (bpxBat::MAN_HEAT_ON):
case (BpxBattery::MAN_HEAT_OFF): { case (bpxBat::MAN_HEAT_OFF): {
if (remainingSize != PING_REPLY_LEN) { if (remainingSize != PING_REPLY_LEN) {
return DeviceHandlerIF::LENGTH_MISSMATCH; return DeviceHandlerIF::LENGTH_MISSMATCH;
} }
break; break;
} }
case (BpxBattery::REBOOT): { case (bpxBat::REBOOT): {
// Ignore // Ignore
break; break;
} }
case (BpxBattery::RESET_COUNTERS): case (bpxBat::RESET_COUNTERS):
case (BpxBattery::CONFIG_CMD): case (bpxBat::CONFIG_CMD):
case (BpxBattery::CONFIG_SET): { case (bpxBat::CONFIG_SET): {
if (remainingSize != EMPTY_REPLY_LEN) { if (remainingSize != EMPTY_REPLY_LEN) {
return DeviceHandlerIF::LENGTH_MISSMATCH; return DeviceHandlerIF::LENGTH_MISSMATCH;
} }
break; break;
} }
case (BpxBattery::CONFIG_GET): { case (bpxBat::CONFIG_GET): {
if (remainingSize != CONFIG_GET_REPLY_LEN) { if (remainingSize != CONFIG_GET_REPLY_LEN) {
return DeviceHandlerIF::LENGTH_MISSMATCH; 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) { 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; return DeviceHandlerIF::DEVICE_REPORTED_ERROR;
} }
switch (id) { switch (id) {
case (BpxBattery::GET_HK): { case (bpxBat::GET_HK): {
PoolReadGuard rg(&hkSet); PoolReadGuard rg(&hkSet);
ReturnValue_t result = hkSet.parseRawHk(packet + 2, 21); ReturnValue_t result = hkSet.parseRawHk(packet + 2, 21);
hkSet.setValidity(true, true); hkSet.setValidity(true, true);
@ -213,7 +215,7 @@ ReturnValue_t BpxBatteryHandler::interpretDeviceReply(DeviceCommandId_t id, cons
} }
break; break;
} }
case (BpxBattery::PING): { case (bpxBat::PING): {
if (packet[2] != sentPingByte) { if (packet[2] != sentPingByte) {
return DeviceHandlerIF::INVALID_DATA; return DeviceHandlerIF::INVALID_DATA;
} }
@ -222,19 +224,19 @@ ReturnValue_t BpxBatteryHandler::interpretDeviceReply(DeviceCommandId_t id, cons
} }
break; break;
} }
case (BpxBattery::RESET_COUNTERS): case (bpxBat::RESET_COUNTERS):
case (BpxBattery::CONFIG_CMD): case (bpxBat::CONFIG_CMD):
case (BpxBattery::CONFIG_SET): { case (bpxBat::CONFIG_SET): {
break; break;
} }
case (BpxBattery::MAN_HEAT_ON): case (bpxBat::MAN_HEAT_ON):
case (BpxBattery::MAN_HEAT_OFF): { case (bpxBat::MAN_HEAT_OFF): {
if (packet[2] != 0x01) { if (packet[2] != 0x01) {
return DeviceHandlerIF::DEVICE_DID_NOT_EXECUTE; return DeviceHandlerIF::DEVICE_DID_NOT_EXECUTE;
} }
break; break;
} }
case (BpxBattery::CONFIG_GET): { case (bpxBat::CONFIG_GET): {
PoolReadGuard rg(&cfgSet); PoolReadGuard rg(&cfgSet);
ReturnValue_t result = cfgSet.parseRawHk(packet + 2, 3); ReturnValue_t result = cfgSet.parseRawHk(packet + 2, 3);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
@ -243,7 +245,7 @@ ReturnValue_t BpxBatteryHandler::interpretDeviceReply(DeviceCommandId_t id, cons
cfgSet.setValidity(true, true); cfgSet.setValidity(true, true);
break; break;
} }
case (BpxBattery::REBOOT): { case (bpxBat::REBOOT): {
break; break;
} }
default: { default: {
@ -257,20 +259,20 @@ uint32_t BpxBatteryHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo)
ReturnValue_t BpxBatteryHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap, ReturnValue_t BpxBatteryHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) { LocalDataPoolManager& poolManager) {
localDataPoolMap.emplace(BpxBattery::BATT_TEMP_1, &battTemp1); localDataPoolMap.emplace(bpxBat::BATT_TEMP_1, &battTemp1);
localDataPoolMap.emplace(BpxBattery::BATT_TEMP_2, &battTemp2); localDataPoolMap.emplace(bpxBat::BATT_TEMP_2, &battTemp2);
localDataPoolMap.emplace(BpxBattery::BATT_TEMP_3, &battTemp3); localDataPoolMap.emplace(bpxBat::BATT_TEMP_3, &battTemp3);
localDataPoolMap.emplace(BpxBattery::BATT_TEMP_4, &battTemp4); localDataPoolMap.emplace(bpxBat::BATT_TEMP_4, &battTemp4);
localDataPoolMap.emplace(BpxBattery::CHARGE_CURRENT, &chargeCurrent); localDataPoolMap.emplace(bpxBat::CHARGE_CURRENT, &chargeCurrent);
localDataPoolMap.emplace(BpxBattery::DISCHARGE_CURRENT, &dischargeCurrent); localDataPoolMap.emplace(bpxBat::DISCHARGE_CURRENT, &dischargeCurrent);
localDataPoolMap.emplace(BpxBattery::HEATER_CURRENT, &heaterCurrent); localDataPoolMap.emplace(bpxBat::HEATER_CURRENT, &heaterCurrent);
localDataPoolMap.emplace(BpxBattery::BATT_VOLTAGE, &battVolt); localDataPoolMap.emplace(bpxBat::BATT_VOLTAGE, &battVolt);
localDataPoolMap.emplace(BpxBattery::REBOOT_COUNTER, &rebootCounter); localDataPoolMap.emplace(bpxBat::REBOOT_COUNTER, &rebootCounter);
localDataPoolMap.emplace(BpxBattery::BOOTCAUSE, &bootCause); localDataPoolMap.emplace(bpxBat::BOOTCAUSE, &bootCause);
localDataPoolMap.emplace(BpxBattery::BATTERY_HEATER_MODE, &battheatMode); localDataPoolMap.emplace(bpxBat::BATTERY_HEATER_MODE, &battheatMode);
localDataPoolMap.emplace(BpxBattery::BATTHEAT_LOW_LIMIT, &battheatLow); localDataPoolMap.emplace(bpxBat::BATTHEAT_LOW_LIMIT, &battheatLow);
localDataPoolMap.emplace(BpxBattery::BATTHEAT_HIGH_LIMIT, &battheatHigh); localDataPoolMap.emplace(bpxBat::BATTHEAT_HIGH_LIMIT, &battheatHigh);
poolManager.subscribeForRegularPeriodicPacket( poolManager.subscribeForRegularPeriodicPacket(
subdp::RegularHkPeriodicParams(hkSet.getSid(), enableHkSets, 20.0)); subdp::RegularHkPeriodicParams(hkSet.getSid(), enableHkSets, 20.0));

View File

@ -25,7 +25,7 @@ class BpxBatteryHandler : public DeviceHandlerBase {
bool commandExecuted = false; bool commandExecuted = false;
bool debugMode = false; bool debugMode = false;
bool goToNormalModeImmediately = 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 #if OBSW_THREAD_TRACING == 1
uint32_t opCounter = 0; uint32_t opCounter = 0;
#endif #endif

View File

@ -8,7 +8,7 @@
#include "fsfw/devicehandlers/DeviceHandlerIF.h" #include "fsfw/devicehandlers/DeviceHandlerIF.h"
namespace BpxBattery { namespace bpxBat {
enum LocalPoolIds { enum LocalPoolIds {
CHARGE_CURRENT = 0, CHARGE_CURRENT = 0,
@ -114,18 +114,18 @@ class BpxHkDeserializer : public SerialLinkedListAdapter<SerializeIF> {
} }
}; };
}; // namespace BpxBattery }; // namespace bpxBat
/** /**
* @brief BPX HK data holder * @brief BPX HK data holder
*/ */
class BpxBatteryHk : public StaticLocalDataSet<BpxBattery::HK_ENTRIES> { class BpxBatteryHk : public StaticLocalDataSet<bpxBat::HK_ENTRIES> {
public: public:
/** /**
* Constructor for data users * Constructor for data users
* @param gyroId * @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(); setAllVariablesReadOnly();
} }
@ -176,28 +176,25 @@ class BpxBatteryHk : public StaticLocalDataSet<BpxBattery::HK_ENTRIES> {
} }
//! Charge current in mA //! Charge current in mA
lp_var_t<uint16_t> chargeCurrent = lp_var_t<uint16_t> chargeCurrent = lp_var_t<uint16_t>(sid.objectId, bpxBat::CHARGE_CURRENT, this);
lp_var_t<uint16_t>(sid.objectId, BpxBattery::CHARGE_CURRENT, this);
//! Discharge current in mA //! Discharge current in mA
lp_var_t<uint16_t> dischargeCurrent = lp_var_t<uint16_t> dischargeCurrent =
lp_var_t<uint16_t>(sid.objectId, BpxBattery::DISCHARGE_CURRENT, this); lp_var_t<uint16_t>(sid.objectId, bpxBat::DISCHARGE_CURRENT, this);
//! Heater current in mA //! Heater current in mA
lp_var_t<uint16_t> heaterCurrent = lp_var_t<uint16_t> heaterCurrent = lp_var_t<uint16_t>(sid.objectId, bpxBat::HEATER_CURRENT, this);
lp_var_t<uint16_t>(sid.objectId, BpxBattery::HEATER_CURRENT, this);
//! Battery voltage in mV //! Battery voltage in mV
lp_var_t<uint16_t> battVoltage = lp_var_t<uint16_t>(sid.objectId, BpxBattery::BATT_VOLTAGE, this); lp_var_t<uint16_t> battVoltage = lp_var_t<uint16_t>(sid.objectId, bpxBat::BATT_VOLTAGE, this);
//! Battery temperature 1 in degC //! Battery temperature 1 in degC
lp_var_t<int16_t> battTemp1 = lp_var_t<int16_t>(sid.objectId, BpxBattery::BATT_TEMP_1, this); lp_var_t<int16_t> battTemp1 = lp_var_t<int16_t>(sid.objectId, bpxBat::BATT_TEMP_1, this);
//! Battery temperature 2 in degC //! Battery temperature 2 in degC
lp_var_t<int16_t> battTemp2 = lp_var_t<int16_t>(sid.objectId, BpxBattery::BATT_TEMP_2, this); lp_var_t<int16_t> battTemp2 = lp_var_t<int16_t>(sid.objectId, bpxBat::BATT_TEMP_2, this);
//! Battery temperature 3 in degC //! Battery temperature 3 in degC
lp_var_t<int16_t> battTemp3 = lp_var_t<int16_t>(sid.objectId, BpxBattery::BATT_TEMP_3, this); lp_var_t<int16_t> battTemp3 = lp_var_t<int16_t>(sid.objectId, bpxBat::BATT_TEMP_3, this);
//! Battery temperature 4 in degC //! Battery temperature 4 in degC
lp_var_t<int16_t> battTemp4 = lp_var_t<int16_t>(sid.objectId, BpxBattery::BATT_TEMP_4, this); lp_var_t<int16_t> battTemp4 = lp_var_t<int16_t>(sid.objectId, bpxBat::BATT_TEMP_4, this);
lp_var_t<uint32_t> rebootCounter = lp_var_t<uint32_t> rebootCounter = lp_var_t<uint32_t>(sid.objectId, bpxBat::REBOOT_COUNTER, this);
lp_var_t<uint32_t>(sid.objectId, BpxBattery::REBOOT_COUNTER, this); lp_var_t<uint8_t> bootcause = lp_var_t<uint8_t>(sid.objectId, bpxBat::BOOTCAUSE, this);
lp_var_t<uint8_t> bootcause = lp_var_t<uint8_t>(sid.objectId, BpxBattery::BOOTCAUSE, this);
private: private:
friend class BpxBatteryHandler; friend class BpxBatteryHandler;
@ -205,16 +202,16 @@ class BpxBatteryHk : public StaticLocalDataSet<BpxBattery::HK_ENTRIES> {
* Constructor for data creator * Constructor for data creator
* @param hkOwner * @param hkOwner
*/ */
BpxBatteryHk(HasLocalDataPoolIF* hkOwner) : StaticLocalDataSet(hkOwner, BpxBattery::HK_SET_ID) {} BpxBatteryHk(HasLocalDataPoolIF* hkOwner) : StaticLocalDataSet(hkOwner, bpxBat::HK_SET_ID) {}
}; };
class BpxBatteryCfg : public StaticLocalDataSet<BpxBattery::CFG_ENTRIES> { class BpxBatteryCfg : public StaticLocalDataSet<bpxBat::CFG_ENTRIES> {
public: public:
/** /**
* Constructor for data users * Constructor for data users
* @param gyroId * @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(); setAllVariablesReadOnly();
} }
@ -230,13 +227,12 @@ class BpxBatteryCfg : public StaticLocalDataSet<BpxBattery::CFG_ENTRIES> {
//! Mode for battheater [0=OFF,1=Auto] //! Mode for battheater [0=OFF,1=Auto]
lp_var_t<uint8_t> battheatermode = lp_var_t<uint8_t> battheatermode =
lp_var_t<uint8_t>(sid.objectId, BpxBattery::BATTERY_HEATER_MODE, this); lp_var_t<uint8_t>(sid.objectId, bpxBat::BATTERY_HEATER_MODE, this);
//! Turn heater on at [degC] //! Turn heater on at [degC]
lp_var_t<int8_t> battheaterLow = lp_var_t<int8_t> battheaterLow = lp_var_t<int8_t>(sid.objectId, bpxBat::BATTHEAT_LOW_LIMIT, this);
lp_var_t<int8_t>(sid.objectId, BpxBattery::BATTHEAT_LOW_LIMIT, this);
//! Turn heater off at [degC] //! Turn heater off at [degC]
lp_var_t<int8_t> battheaterHigh = lp_var_t<int8_t> battheaterHigh =
lp_var_t<int8_t>(sid.objectId, BpxBattery::BATTHEAT_HIGH_LIMIT, this); lp_var_t<int8_t>(sid.objectId, bpxBat::BATTHEAT_HIGH_LIMIT, this);
private: private:
friend class BpxBatteryHandler; friend class BpxBatteryHandler;
@ -244,8 +240,7 @@ class BpxBatteryCfg : public StaticLocalDataSet<BpxBattery::CFG_ENTRIES> {
* Constructor for data creator * Constructor for data creator
* @param hkOwner * @param hkOwner
*/ */
BpxBatteryCfg(HasLocalDataPoolIF* hkOwner) BpxBatteryCfg(HasLocalDataPoolIF* hkOwner) : StaticLocalDataSet(hkOwner, bpxBat::CFG_SET_ID) {}
: StaticLocalDataSet(hkOwner, BpxBattery::CFG_SET_ID) {}
}; };
#endif /* MISSION_POWER_BPXBATTDEFS_H_ */ #endif /* MISSION_POWER_BPXBATTDEFS_H_ */

View File

@ -1,12 +1,79 @@
#ifndef MISSION_SYSDEFS_H_ #ifndef MISSION_SYSDEFS_H_
#define MISSION_SYSDEFS_H_ #define MISSION_SYSDEFS_H_
#include <atomic>
#include "acs/defs.h" #include "acs/defs.h"
extern std::atomic_uint16_t I2C_FATAL_ERRORS;
namespace satsystem { namespace satsystem {
enum Mode : Mode_t { BOOT = 5, SAFE = acs::AcsMode::SAFE, PTG_IDLE = acs::AcsMode::PTG_IDLE }; 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_ */ #endif /* MISSION_SYSDEFS_H_ */

View File

@ -5,4 +5,6 @@ add_subdirectory(com)
add_subdirectory(fdir) add_subdirectory(fdir)
add_subdirectory(power) 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)

View File

@ -0,0 +1,278 @@
#include "EiveSystem.h"
#include <eive/objects.h>
#include <fsfw/events/EventManager.h>
#include <fsfw/ipc/QueueFactory.h>
#include <fsfw/power/PowerSwitchIF.h>
#include <mission/acs/defs.h>
#include <mission/com/defs.h>
#include <mission/controller/tcsDefs.h>
#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<void*>(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<HasActionsIF>(objects::BPX_BATT_HANDLER);
if (bpxDest == nullptr) {
return ObjectManager::CHILD_INIT_FAILED;
}
bpxBattQueueId = bpxDest->getCommandQueue();
auto* coreCtrl = ObjectManager::instance()->get<HasActionsIF>(objects::CORE_CONTROLLER);
if (coreCtrl == nullptr) {
return ObjectManager::CHILD_INIT_FAILED;
}
coreCtrlQueueId = coreCtrl->getCommandQueue();
auto* manager = ObjectManager::instance()->get<EventManagerIF>(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);
}

View File

@ -0,0 +1,60 @@
#ifndef MISSION_SYSTEM_EIVESYSTEM_H_
#define MISSION_SYSTEM_EIVESYSTEM_H_
#include <fsfw/action/HasActionsIF.h>
#include <fsfw/power/PowerSwitchIF.h>
#include <fsfw/subsystem/Subsystem.h>
#include <atomic>
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_ */

View File

@ -56,12 +56,12 @@ ReturnValue_t RwAssembly::checkChildrenStateOn(Mode_t wantedMode, Submode_t want
} }
} }
} catch (const std::out_of_range& e) { } 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 (devsInCorrectMode < 3) {
if (warningSwitch) { if (warningSwitch) {
sif::warning << "RwAssembly::checkChildrenStateOn: Only " << devsInCorrectMode sif::warning << "RW ASSY: Only " << devsInCorrectMode << " devices in correct mode"
<< " devices in correct mode" << std::endl; << std::endl;
warningSwitch = false; warningSwitch = false;
} }
return NOT_ENOUGH_CHILDREN_IN_CORRECT_STATE; 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 RwAssembly::handleNormalOrOnModeCmd(Mode_t mode, Submode_t submode) {
ReturnValue_t result = returnvalue::OK; ReturnValue_t result = returnvalue::OK;
bool needsSecondStep = false;
Mode_t devMode = 0;
object_id_t objId = 0; object_id_t objId = 0;
try { try {
for (uint8_t idx = 0; idx < NUMBER_RWS; idx++) { for (uint8_t idx = 0; idx < NUMBER_RWS; idx++) {
devMode = childrenMap.at(helper.rwIds[idx]).mode; if (isUseable(objId, mode)) {
objId = helper.rwIds[idx];
if (mode == devMode) {
modeTable[idx].setMode(mode); modeTable[idx].setMode(mode);
} else if (mode == DeviceHandlerIF::MODE_NORMAL) { modeTable[idx].setSubmode(submode);
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);
}
} }
} }
} catch (const std::out_of_range& e) { } catch (const std::out_of_range& e) {
sif::error << "TcsBoardAssembly: Invalid children map: " << e.what() << std::endl; sif::error << "RW ASSY: Invalid children map: " << e.what() << std::endl;
}
if (needsSecondStep) {
result = NEED_SECOND_STEP;
} }
return result; return result;
} }
@ -172,15 +144,3 @@ ReturnValue_t RwAssembly::initialize() {
} }
return AssemblyBase::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;
}
}
}

View File

@ -41,11 +41,6 @@ class RwAssembly : public AssemblyBase {
ReturnValue_t isModeCombinationValid(Mode_t mode, Submode_t submode) override; ReturnValue_t isModeCombinationValid(Mode_t mode, Submode_t submode) override;
void startTransition(Mode_t mode, Submode_t submode) override; void startTransition(Mode_t mode, Submode_t submode) override;
void handleModeReached() 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_ */ #endif /* MISSION_SYSTEM_RWASS_H_ */

View File

@ -11,7 +11,7 @@
#include "eive/objects.h" #include "eive/objects.h"
#include "mission/acs/defs.h" #include "mission/acs/defs.h"
#include "mission/power/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); AcsSubsystem satsystem::acs::ACS_SUBSYSTEM(objects::ACS_SUBSYSTEM, 12, 24);

View File

@ -228,3 +228,27 @@ bool ComSubsystem::isTxMode(Mode_t mode) {
} }
return false; 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);
}

View File

@ -47,6 +47,7 @@ class ComSubsystem : public Subsystem, public ReceivesParameterMessagesIF {
ReturnValue_t initialize() override; ReturnValue_t initialize() override;
void startTransition(Mode_t mode, Submode_t submode) override; void startTransition(Mode_t mode, Submode_t submode) override;
void announceMode(bool recursive) override;
void readEventQueue(); void readEventQueue();
void handleEventMessage(EventMessage *eventMessage); void handleEventMessage(EventMessage *eventMessage);

View File

@ -6,7 +6,7 @@
#include "eive/objects.h" #include "eive/objects.h"
#include "mission/com/defs.h" #include "mission/com/defs.h"
#include "mission/system/tree/util.h" #include "mission/system/treeUtil.h"
const auto check = subsystem::checkInsert; const auto check = subsystem::checkInsert;

View File

@ -1,9 +1,4 @@
target_sources( target_sources(
${LIB_EIVE_MISSION} ${LIB_EIVE_MISSION}
PRIVATE EiveSystem.cpp PRIVATE CamSwitcher.cpp TcsSubsystem.cpp PayloadSubsystem.cpp
CamSwitcher.cpp Stack5VHandler.cpp PowerStateMachineBase.cpp TcsBoardAssembly.cpp)
TcsSubsystem.cpp
PayloadSubsystem.cpp
Stack5VHandler.cpp
PowerStateMachineBase.cpp
TcsBoardAssembly.cpp)

View File

@ -1,111 +0,0 @@
#include "EiveSystem.h"
#include <eive/objects.h>
#include <fsfw/events/EventManager.h>
#include <fsfw/ipc/QueueFactory.h>
#include <mission/acs/defs.h>
#include <mission/com/defs.h>
#include <mission/controller/tcsDefs.h>
#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<void*>(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<EventManagerIF>(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); }

View File

@ -1,21 +0,0 @@
#ifndef MISSION_SYSTEM_EIVESYSTEM_H_
#define MISSION_SYSTEM_EIVESYSTEM_H_
#include <fsfw/subsystem/Subsystem.h>
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_ */

View File

@ -1,4 +1,4 @@
#include "system.h" #include "systemTree.h"
#include <fsfw/devicehandlers/DeviceHandlerIF.h> #include <fsfw/devicehandlers/DeviceHandlerIF.h>
#include <fsfw/subsystem/Subsystem.h> #include <fsfw/subsystem/Subsystem.h>
@ -6,12 +6,14 @@
#include <mission/sysDefs.h> #include <mission/sysDefs.h>
#include <mission/system/com/comModeTree.h> #include <mission/system/com/comModeTree.h>
#include <atomic>
#include "eive/objects.h" #include "eive/objects.h"
#include "mission/com/defs.h" #include "mission/com/defs.h"
#include "mission/system/acs/acsModeTree.h" #include "mission/system/acs/acsModeTree.h"
#include "payloadModeTree.h" #include "mission/system/tree/payloadModeTree.h"
#include "tcsModeTree.h" #include "mission/system/tree/tcsModeTree.h"
#include "util.h" #include "treeUtil.h"
namespace { namespace {
// Alias for checker function // Alias for checker function
@ -41,7 +43,7 @@ void satsystem::init() {
EIVE_SYSTEM.setInitialMode(satsystem::Mode::BOOT, 0); 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<ModeListEntry, 5>()); auto EIVE_SEQUENCE_BOOT = std::make_pair(satsystem::Mode::BOOT, FixedArrayList<ModeListEntry, 5>());
auto EIVE_TABLE_BOOT_TGT = auto EIVE_TABLE_BOOT_TGT =

View File

@ -1,7 +1,7 @@
#ifndef MISSION_SYSTEM_TREE_SYSTEM_H_ #ifndef MISSION_SYSTEM_TREE_SYSTEM_H_
#define MISSION_SYSTEM_TREE_SYSTEM_H_ #define MISSION_SYSTEM_TREE_SYSTEM_H_
#include <mission/system/objects/EiveSystem.h> #include <mission/system/EiveSystem.h>
namespace satsystem { namespace satsystem {

View File

@ -1,2 +1 @@
target_sources(${LIB_EIVE_MISSION} PRIVATE payloadModeTree.cpp tcsModeTree.cpp target_sources(${LIB_EIVE_MISSION} PRIVATE payloadModeTree.cpp tcsModeTree.cpp)
system.cpp util.cpp)

View File

@ -10,7 +10,7 @@
#include "eive/objects.h" #include "eive/objects.h"
#include "mission/power/defs.h" #include "mission/power/defs.h"
#include "mission/system/objects/PayloadSubsystem.h" #include "mission/system/objects/PayloadSubsystem.h"
#include "util.h" #include "mission/system/treeUtil.h"
namespace { namespace {
void initOffSequence(Subsystem& ss, ModeListEntry& eh); void initOffSequence(Subsystem& ss, ModeListEntry& eh);

View File

@ -3,7 +3,7 @@
#include "eive/objects.h" #include "eive/objects.h"
#include "fsfw/devicehandlers/DeviceHandlerIF.h" #include "fsfw/devicehandlers/DeviceHandlerIF.h"
#include "fsfw/subsystem/Subsystem.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); TcsSubsystem satsystem::tcs::SUBSYSTEM(objects::TCS_SUBSYSTEM, 12, 24);

View File

@ -1,4 +1,4 @@
#include "util.h" #include "treeUtil.h"
#include "fsfw/container/FixedMap.h" #include "fsfw/container/FixedMap.h"
#include "fsfw/serviceinterface.h" #include "fsfw/serviceinterface.h"

View File

@ -331,7 +331,6 @@ void HeaterHandler::handleSwitchOffCommand(heater::Switchers heaterIdx) {
} }
} }
} else { } else {
sif::info << "HeaterHandler::handleSwitchOffCommand: Switch already off" << std::endl;
triggerEvent(SWITCH_ALREADY_OFF, heaterIdx); triggerEvent(SWITCH_ALREADY_OFF, heaterIdx);
} }
if (heater.replyQueue != NO_COMMANDER) { if (heater.replyQueue != NO_COMMANDER) {

View File

@ -101,8 +101,8 @@ class HeaterHandler : public ExecutableObjectIF,
static constexpr Event GPIO_PULL_LOW_FAILED = MAKE_EVENT(1, severity::LOW); 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_ON = event::makeEvent(SUBSYSTEM_ID, 2, severity::INFO);
static constexpr Event HEATER_WENT_OFF = event::makeEvent(SUBSYSTEM_ID, 3, 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_ON = MAKE_EVENT(4, severity::INFO);
static constexpr Event SWITCH_ALREADY_OFF = MAKE_EVENT(5, severity::LOW); static constexpr Event SWITCH_ALREADY_OFF = MAKE_EVENT(5, severity::INFO);
static constexpr Event MAIN_SWITCH_TIMEOUT = MAKE_EVENT(6, severity::MEDIUM); 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 //! 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); static constexpr Event FAULTY_HEATER_WAS_ON = event::makeEvent(SUBSYSTEM_ID, 7, severity::LOW);

View File

@ -338,6 +338,8 @@ ReturnValue_t PersistentTmStore::createMostRecentFile(std::optional<uint8_t> suf
ReturnValue_t PersistentTmStore::initializeTmStore() { ReturnValue_t PersistentTmStore::initializeTmStore() {
Clock::getClock_timeval(&currentTv); Clock::getClock_timeval(&currentTv);
updateBaseDir(); updateBaseDir();
// Reset active file, base directory might have changed.
activeFile = std::nullopt;
return assignAndOrCreateMostRecentFile(); return assignAndOrCreateMostRecentFile();
} }

2
tmtc

@ -1 +1 @@
Subproject commit dcf7d0af71f6ba9d569f9f56604e9245a0233427 Subproject commit 43b530cdb7dfe6774962bf4b8a880e1c9a6e6580