Merge remote-tracking branch 'origin/develop' into continue_tcs_tests
All checks were successful
EIVE/eive-obsw/pipeline/pr-develop This commit looks good

This commit is contained in:
Robin Müller 2023-04-08 15:57:06 +02:00
commit ece053e5c3
No known key found for this signature in database
GPG Key ID: 11D4952C8CCEF814
29 changed files with 295 additions and 229 deletions

View File

@ -16,6 +16,12 @@ 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.
- Heater states array in TCS controller was too small.
## Changed ## Changed
- TCS controller now only has an OFF mode and an ON mode - TCS controller now only has an OFF mode and an ON mode
@ -26,12 +32,31 @@ will consitute of a breaking change warranting a new major release:
commanded, all heaters will be switched off and then no further heater commanded, all heaters will be switched off and then no further heater
commanding will be done. commanding will be done.
# [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 ## Fixed
- RW Assembly: Correctly transition back to off when more than 1 devices is OFF. Also do this - 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. when this was due to two devices being marked faulty.
- RW dummy and STR dummy components: Set/Update modes correctly. - RW dummy and STR dummy components: Set/Update modes correctly.
- Heater states array in TCS controller was too small. - 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

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 285 translations. * @brief Auto-generated event translation file. Contains 285 translations.
* @details * @details
* Generated on: 2023-04-07 11:06:14 * Generated on: 2023-04-07 17:42:57
*/ */
#include "translateEvents.h" #include "translateEvents.h"

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-07 11:06:14 * 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

@ -54,7 +54,6 @@ CoreController::CoreController(object_id_t objectId, bool enableHkSet)
// 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();
@ -368,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();
@ -404,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) {
@ -431,26 +430,16 @@ 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();
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;
@ -478,12 +467,12 @@ ReturnValue_t CoreController::sdStateMachine() {
sdFsmState = SdStates::DETERMINE_OTHER; sdFsmState = SdStates::DETERMINE_OTHER;
} else if (sdInfo.activeState == sd::SdState::OFF) { } else if (sdInfo.activeState == sd::SdState::OFF) {
sdCardSetup(sdInfo.active, sd::SdState::ON, sdInfo.activeChar, false); sdCardSetup(sdInfo.active, sd::SdState::ON, sdInfo.activeChar, false);
sdInfo.commandExecuted = true; sdInfo.commandPending = true;
} else if (sdInfo.activeState == sd::SdState::ON) { } else if (sdInfo.activeState == sd::SdState::ON) {
sdFsmState = SdStates::MOUNT_SELF; sdFsmState = SdStates::MOUNT_SELF;
} }
} 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);
} }
@ -491,11 +480,11 @@ ReturnValue_t CoreController::sdStateMachine() {
} }
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;
@ -532,22 +521,22 @@ 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; 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; sdInfo.otherState = sd::SdState::ON;
currentStateSetter(sdInfo.other, sd::SdState::ON); currentStateSetter(sdInfo.other, sd::SdState::ON);
@ -559,21 +548,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);
} }
@ -582,14 +575,15 @@ 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();
sdInfo.commandPending = false;
sdFsmState = SdStates::IDLE; sdFsmState = SdStates::IDLE;
sdInfo.cycleCount = 0; sdInfo.cycleCount = 0;
sdcMan->setBlocking(false); sdcMan->setBlocking(false);
@ -599,8 +593,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;
} }
@ -977,7 +979,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";

View File

@ -129,8 +129,7 @@ class CoreController : public ExtendedControllerBase {
enum class SdStates { enum class SdStates {
NONE, NONE,
START, START,
GET_INFO, UPDATE_SD_INFO_START,
SET_STATE_SELF,
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,
@ -140,7 +139,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
}; };
@ -159,13 +158,12 @@ class CoreController : public ExtendedControllerBase {
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 bool commandPending = true;
bool commandExecuted = true;
bool initFinished = false; bool initFinished = false;
SdCardManager::SdStatePair currentState; SdCardManager::SdStatePair currentState;
uint16_t cycleCount = 0; uint16_t cycleCount = 0;
@ -232,7 +230,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

@ -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

@ -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 {

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
@ -234,7 +224,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);

2
fsfw

@ -1 +1 @@
Subproject commit e97fa5ac84db7ab5c10a31c2c78b26057cfacb71 Subproject commit 285d327b97514946f0714e477289f67ee8bd413f

View File

@ -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_HalTimeoutRetval;No description;0;HAL_SPI;fsfw/src/fsfw_hal/stm32h7/spi/spiDefinitions.h 0x4500;HSPI_OpeningFileFailed;No description;0;HAL_SPI;fsfw/src/fsfw_hal/common/spi/spiCommon.h
0x4501;HSPI_HalBusyRetval;No description;1;HAL_SPI;fsfw/src/fsfw_hal/stm32h7/spi/spiDefinitions.h 0x4501;HSPI_FullDuplexTransferFailed;No description;1;HAL_SPI;fsfw/src/fsfw_hal/common/spi/spiCommon.h
0x4502;HSPI_HalErrorRetval;No description;2;HAL_SPI;fsfw/src/fsfw_hal/stm32h7/spi/spiDefinitions.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
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_HalTimeoutRetval HSPI_OpeningFileFailed No description 0 HAL_SPI fsfw/src/fsfw_hal/stm32h7/spi/spiDefinitions.h fsfw/src/fsfw_hal/common/spi/spiCommon.h
406 0x4501 HSPI_HalBusyRetval HSPI_FullDuplexTransferFailed No description 1 HAL_SPI fsfw/src/fsfw_hal/stm32h7/spi/spiDefinitions.h fsfw/src/fsfw_hal/common/spi/spiCommon.h
407 0x4502 HSPI_HalErrorRetval HSPI_HalfDuplexTransferFailed No description 2 HAL_SPI fsfw/src/fsfw_hal/stm32h7/spi/spiDefinitions.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

@ -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_HalTimeoutRetval;No description;0;HAL_SPI;fsfw/src/fsfw_hal/stm32h7/spi/spiDefinitions.h 0x4500;HSPI_OpeningFileFailed;No description;0;HAL_SPI;fsfw/src/fsfw_hal/common/spi/spiCommon.h
0x4501;HSPI_HalBusyRetval;No description;1;HAL_SPI;fsfw/src/fsfw_hal/stm32h7/spi/spiDefinitions.h 0x4501;HSPI_FullDuplexTransferFailed;No description;1;HAL_SPI;fsfw/src/fsfw_hal/common/spi/spiCommon.h
0x4502;HSPI_HalErrorRetval;No description;2;HAL_SPI;fsfw/src/fsfw_hal/stm32h7/spi/spiDefinitions.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
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_HalTimeoutRetval HSPI_OpeningFileFailed No description 0 HAL_SPI fsfw/src/fsfw_hal/stm32h7/spi/spiDefinitions.h fsfw/src/fsfw_hal/common/spi/spiCommon.h
406 0x4501 HSPI_HalBusyRetval HSPI_FullDuplexTransferFailed No description 1 HAL_SPI fsfw/src/fsfw_hal/stm32h7/spi/spiDefinitions.h fsfw/src/fsfw_hal/common/spi/spiCommon.h
407 0x4502 HSPI_HalErrorRetval HSPI_HalfDuplexTransferFailed No description 2 HAL_SPI fsfw/src/fsfw_hal/stm32h7/spi/spiDefinitions.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

@ -1,7 +1,7 @@
/** /**
* @brief Auto-generated event translation file. Contains 285 translations. * @brief Auto-generated event translation file. Contains 285 translations.
* @details * @details
* Generated on: 2023-04-07 11:06:14 * Generated on: 2023-04-07 17:42:57
*/ */
#include "translateEvents.h" #include "translateEvents.h"

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-07 11:06:14 * 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

@ -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

@ -1,7 +1,7 @@
/** /**
* @brief Auto-generated event translation file. Contains 285 translations. * @brief Auto-generated event translation file. Contains 285 translations.
* @details * @details
* Generated on: 2023-04-07 11:06:14 * Generated on: 2023-04-07 17:42:57
*/ */
#include "translateEvents.h" #include "translateEvents.h"

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-07 11:06:14 * Generated on: 2023-04-07 17:42:57
*/ */
#include "translateObjects.h" #include "translateObjects.h"

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,25 +24,34 @@ 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();
}
if ((internalState == InternalState::SHUTDOWN) and
(shutdownState == ShutdownState::DONE or offTransitionCountdown.hasTimedOut())) {
if (gpioComIF->pullLow(enableGpio) != returnvalue::OK) {
sif::error << "RW Handler " << rwIdx << ": Failed to pull ENABLE pin low for shutdown";
} }
internalState = InternalState::DEFAULT;
updatePeriodicReply(false, rws::REPLY_ID); updatePeriodicReply(false, rws::REPLY_ID);
{ {
PoolReadGuard pg(&statusSet); PoolReadGuard pg(&statusSet);
@ -55,13 +65,12 @@ void RwHandler::doShutDown() {
PoolReadGuard pg(&tmDataset); PoolReadGuard pg(&tmDataset);
tmDataset.setValidity(false, true); tmDataset.setValidity(false, true);
} }
{ internalState = InternalState::DEFAULT;
PoolReadGuard pg(&rwSpeedActuationSet); shutdownState = ShutdownState::NONE;
rwSpeedActuationSet.setRwSpeed(0, 10);
}
// The power switch is handled by the assembly, so we can go off here directly. // The power switch is handled by the assembly, so we can go off here directly.
setMode(MODE_OFF); setMode(MODE_OFF);
} }
}
ReturnValue_t RwHandler::buildNormalDeviceCommand(DeviceCommandId_t* id) { ReturnValue_t RwHandler::buildNormalDeviceCommand(DeviceCommandId_t* id) {
switch (internalState) { switch (internalState) {
@ -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

@ -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

@ -144,9 +144,6 @@ ReturnValue_t EiveSystem::executeAction(ActionId_t actionId, MessageQueueId_t co
case (EXECUTE_I2C_REBOOT): { case (EXECUTE_I2C_REBOOT): {
triggerEvent(core::TRYING_I2C_RECOVERY); triggerEvent(core::TRYING_I2C_RECOVERY);
performI2cReboot = true; performI2cReboot = true;
// This flag is more related to autonomous recovery handling, so we reset it here if this
// reboot sequence is commanded manually.
alreadyTriedI2cRecovery = false;
i2cRebootState = I2cRebootState::SYSTEM_MODE_BOOT; i2cRebootState = I2cRebootState::SYSTEM_MODE_BOOT;
this->actionCommandedBy = commandedBy; this->actionCommandedBy = commandedBy;
return returnvalue::OK; return returnvalue::OK;
@ -264,11 +261,11 @@ void EiveSystem::commandSelfToSafe() { startTransition(satsystem::Mode::SAFE, 0)
void EiveSystem::commonI2cRecoverySequenceFinish() { void EiveSystem::commonI2cRecoverySequenceFinish() {
alreadyTriedI2cRecovery = true; alreadyTriedI2cRecovery = true;
performI2cReboot = false; performI2cReboot = false;
i2cRecoveryClearCountdown.resetTimer();
i2cRebootState = I2cRebootState::NONE; i2cRebootState = I2cRebootState::NONE;
// Reset this counter. If I2C devices are still problematic, we will get a full reboot // Reset this counter and the recovery clear countdown. If I2C devices are still problematic,
// next time this count goes above 5. // we will get a full reboot next time this count goes above 5.
i2cErrors = 0; i2cErrors = 0;
i2cRecoveryClearCountdown.resetTimer();
// This should always be accepted // This should always be accepted
commandSelfToSafe(); commandSelfToSafe();
} }

View File

@ -41,7 +41,6 @@ class EiveSystem : public Subsystem, public HasActionsIF {
MessageQueueId_t coreCtrlQueueId = MessageQueueIF::NO_QUEUE; MessageQueueId_t coreCtrlQueueId = MessageQueueIF::NO_QUEUE;
MessageQueueId_t actionCommandedBy = MessageQueueIF::NO_QUEUE; MessageQueueId_t actionCommandedBy = MessageQueueIF::NO_QUEUE;
Countdown i2cRebootHandlingCountdown = Countdown(10000); Countdown i2cRebootHandlingCountdown = Countdown(10000);
// Countdown i2cUnavailableCountdown = Countdown(30000);
// After 1 minute, clear the flag to avoid full reboots on I2C issues. // After 1 minute, clear the flag to avoid full reboots on I2C issues.
Countdown i2cRecoveryClearCountdown = Countdown(60000); Countdown i2cRecoveryClearCountdown = Countdown(60000);
ReturnValue_t initialize() override; ReturnValue_t initialize() override;

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);

2
tmtc

@ -1 +1 @@
Subproject commit 91a8a2e89519ac20d9ddabec2d8eaeb7707718d5 Subproject commit 43b530cdb7dfe6774962bf4b8a880e1c9a6e6580