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-11 16:14:53 +02:00
commit 8d9755c17f
No known key found for this signature in database
GPG Key ID: 11D4952C8CCEF814
7 changed files with 105 additions and 3 deletions

View File

@ -24,13 +24,23 @@ will consitute of a breaking change warranting a new major release:
## Changed ## 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.
- TCS controller now only has an OFF mode and an ON mode - TCS controller now only has an OFF mode and an ON mode
- Allow specifying custom OBSW update filename. This allowed keeping a cleaner file structure
where each update has a name including the version
- The files extracted during an update process are deleted after the update was performed to keep
the update directory cleaner.
## Added ## Added
- TCS controller: SUBMODE_NO_HEATER_CTRL (1) added for ON mode. If this submode is - TCS controller: SUBMODE_NO_HEATER_CTRL (1) added for ON mode. If this submode is
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.
- 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.
# [v1.44.0] 2023-04-07 # [v1.44.0] 2023-04-07

View File

@ -440,6 +440,19 @@ ReturnValue_t CoreController::sdStateMachine() {
} }
result = sdcMan->getSdCardsStatus(sdInfo.currentState); result = sdcMan->getSdCardsStatus(sdInfo.currentState);
updateInternalSdInfo(); 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;
@ -451,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) {
@ -464,20 +481,50 @@ 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.commandPending = 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 (nonBlockingSdcOpChecking(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.commandPending) { if (not sdInfo.commandPending) {
@ -529,6 +576,11 @@ ReturnValue_t CoreController::sdStateMachine() {
"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 {
// Continue.. avoid being stuck here..
sdFsmState = SdStates::SKIP_CYCLE_BEFORE_INFO_UPDATE;
sdInfo.otherState = sd::SdState::OFF;
currentStateSetter(sdInfo.other, sd::SdState::OFF);
} }
} }
} else if (sdInfo.cfgMode == SdCfgMode::HOT_REDUNDANT) { } else if (sdInfo.cfgMode == SdCfgMode::HOT_REDUNDANT) {
@ -540,6 +592,11 @@ ReturnValue_t CoreController::sdStateMachine() {
"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);
} else {
// Contnue.. avoid being stuck here.
sdFsmState = SdStates::MOUNT_UNMOUNT_OTHER;
sdInfo.otherState = sd::SdState::ON;
currentStateSetter(sdInfo.other, sd::SdState::ON);
} }
} }
} }
@ -583,6 +640,8 @@ ReturnValue_t CoreController::sdStateMachine() {
sif::warning << "CoreController: Updating SD card state file failed" << std::endl; sif::warning << "CoreController: Updating SD card state file failed" << std::endl;
} }
updateInternalSdInfo(); updateInternalSdInfo();
// Mark usable again in any case.
sdcMan->markUsable();
sdInfo.commandPending = false; sdInfo.commandPending = false;
sdFsmState = SdStates::IDLE; sdFsmState = SdStates::IDLE;
sdInfo.cycleCount = 0; sdInfo.cycleCount = 0;
@ -1925,7 +1984,14 @@ ReturnValue_t CoreController::executeSwUpdate(SwUpdateSources sourceDir, const u
} else if (sourceDir == SwUpdateSources::TMP_DIR) { } else if (sourceDir == SwUpdateSources::TMP_DIR) {
prefixPath = path("/tmp"); prefixPath = path("/tmp");
} }
path archivePath = prefixPath / path(config::OBSW_UPDATE_ARCHIVE_FILE_NAME); path archivePath;
// It is optionally possible to supply the source file path
if (size > 2) {
archivePath = prefixPath / std::string(reinterpret_cast<const char *>(data + 2), size - 2);
} else {
archivePath = prefixPath / path(config::OBSW_UPDATE_ARCHIVE_FILE_NAME);
}
sif::info << "Updating with archive path " << archivePath << std::endl;
std::error_code e; std::error_code e;
if (not exists(archivePath, e)) { if (not exists(archivePath, e)) {
return HasFileSystemIF::FILE_DOES_NOT_EXIST; return HasFileSystemIF::FILE_DOES_NOT_EXIST;
@ -2012,6 +2078,10 @@ ReturnValue_t CoreController::executeSwUpdate(SwUpdateSources sourceDir, const u
cmd.str(""); cmd.str("");
cmd.clear(); cmd.clear();
// Remove the extracted files to keep directories clean.
std::filesystem::remove(strippedImagePath, e);
std::filesystem::remove(obswVersionFilePath, e);
// TODO: This takes a long time and will block the core controller.. Maybe use command executor? // TODO: This takes a long time and will block the core controller.. Maybe use command executor?
// For now dont care.. // For now dont care..
cmd << "writeprotect " << std::to_string(data[0]) << " " << std::to_string(data[1]) << " 1"; cmd << "writeprotect " << std::to_string(data[0]) << " " << std::to_string(data[1]) << " 1";
@ -2032,6 +2102,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;

View File

@ -130,6 +130,7 @@ class CoreController : public ExtendedControllerBase {
NONE, NONE,
START, START,
UPDATE_SD_INFO_START, UPDATE_SD_INFO_START,
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,
@ -152,6 +153,7 @@ 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 {
@ -163,10 +165,16 @@ class CoreController : public ExtendedControllerBase {
sd::SdState activeState = sd::SdState::OFF; sd::SdState activeState = sd::SdState::OFF;
sd::SdState otherState = sd::SdState::OFF; sd::SdState otherState = sd::SdState::OFF;
std::pair<bool, bool> mountSwitch = {true, true}; std::pair<bool, bool> mountSwitch = {true, true};
// This flag denotes that the SD card usage is locked. This is relevant if SD cards go off
// to leave appliation using the SD cards some time to detect the SD card is not usable anymore.
// This is relevant if the active SD card is being switched. The SD card will also be locked
// when going from hot-redundant mode to cold-redundant mode.
bool lockSdCardUsage = false;
bool commandPending = true; bool 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 {

View File

@ -68,6 +68,7 @@ void ObjectFactory::produce(void* args) {
#else #else
createPcduComponents(gpioComIF, &pwrSwitcher, enableHkSets); createPcduComponents(gpioComIF, &pwrSwitcher, enableHkSets);
#endif #endif
satsystem::EIVE_SYSTEM.setI2cRecoveryParams(pwrSwitcher);
dummy::createDummies(dummyCfg, *pwrSwitcher, gpioComIF); dummy::createDummies(dummyCfg, *pwrSwitcher, gpioComIF);

View File

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

@ -205,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;

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