TCS continued #576

Merged
muellerr merged 19 commits from continue_tcs_tests into develop 2023-04-13 18:10:35 +02:00
29 changed files with 295 additions and 229 deletions
Showing only changes of commit ece053e5c3 - Show all commits

View File

@ -16,6 +16,12 @@ will consitute of a breaking change warranting a new major release:
# [unreleased]
## Fixed
- Bugfixes and improvements for SDC state machine. Internal state was not updated correctly due
to a regression, so commanding the SDC state machine externally lead to confusing results.
- Heater states array in TCS controller was too small.
## Changed
- 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
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
- 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.
- 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

View File

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

View File

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

View File

@ -2,7 +2,7 @@
* @brief Auto-generated object translation file.
* @details
* Contains 171 translations.
* Generated on: 2023-04-07 11:06:14
* Generated on: 2023-04-07 17:42:57
*/
#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);
if (fd < 0) {
sif::error << "rwSpiCallback::spiCallback: Failed to open device file" << std::endl;
return SpiComIF::OPENING_FILE_FAILED;
return spi::OPENING_FILE_FAILED;
}
// Pull SPI CS low. For now, no support for active high given

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.
// Stopwatch watch;
sdcMan->updateSdCardStateFile();
sdcMan->updateSdStatePair();
SdCardManager::SdStatePair sdStates;
sdcMan->getSdCardsStatus(sdStates);
auto sdCard = sdcMan->getPreferredSdCard();
@ -368,7 +367,7 @@ ReturnValue_t CoreController::initSdCardBlocking() {
}
if (sdInfo.cfgMode == SdCfgMode::COLD_REDUNDANT) {
updateSdInfoOther();
updateInternalSdInfo();
sif::info << "Cold redundant SD card configuration, preferred SD card: "
<< static_cast<int>(sdInfo.active) << std::endl;
result = sdColdRedundantBlockingInit();
@ -404,23 +403,23 @@ ReturnValue_t CoreController::sdStateMachine() {
} else {
// Still update SD state file
if (sdInfo.cfgMode == SdCfgMode::PASSIVE) {
sdFsmState = SdStates::UPDATE_INFO;
sdFsmState = SdStates::UPDATE_SD_INFO_END;
} else {
sdInfo.cycleCount = 0;
sdInfo.commandExecuted = false;
sdFsmState = SdStates::GET_INFO;
sdInfo.commandPending = false;
sdFsmState = SdStates::UPDATE_SD_INFO_START;
}
}
}
// This lambda checks the non-blocking operation and assigns the new state on success.
// It returns true for an operation success and false otherwise
auto nonBlockingOpChecking = [&](SdStates newStateOnSuccess, uint16_t maxCycleCount,
std::string opPrintout) {
// This lambda checks the non-blocking operation of the SD card manager and assigns the new
// state on success. It returns true for an operation success and false otherwise
auto nonBlockingSdcOpChecking = [&](SdStates newStateOnSuccess, uint16_t maxCycleCount,
std::string opPrintout) {
SdCardManager::OpStatus status = sdcMan->checkCurrentOp(operation);
if (status == SdCardManager::OpStatus::SUCCESS) {
sdFsmState = newStateOnSuccess;
sdInfo.commandExecuted = false;
sdInfo.commandPending = false;
sdInfo.cycleCount = 0;
return true;
} else if (sdInfo.cycleCount > 4) {
@ -431,26 +430,16 @@ ReturnValue_t CoreController::sdStateMachine() {
return false;
};
if (sdFsmState == SdStates::GET_INFO) {
if (not sdInfo.commandExecuted) {
if (sdFsmState == SdStates::UPDATE_SD_INFO_START) {
if (not sdInfo.commandPending) {
// Create updated status file
result = sdcMan->updateSdCardStateFile();
if (result != returnvalue::OK) {
sif::warning << "CoreController::sdStateMachine: Updating SD card state file failed"
<< std::endl;
}
sdFsmState = SdStates::SET_STATE_SELF;
sdInfo.commandExecuted = false;
sdInfo.cycleCount = 0;
} else {
nonBlockingOpChecking(SdStates::SET_STATE_SELF, 4, "Updating SDC file");
}
}
if (sdFsmState == SdStates::SET_STATE_SELF) {
if (not sdInfo.commandExecuted) {
result = sdcMan->getSdCardsStatus(sdInfo.currentState);
updateSdInfoOther();
updateInternalSdInfo();
if (sdInfo.active != sd::SdCard::SLOT_0 and sdInfo.active != sd::SdCard::SLOT_1) {
sif::warning << "Preferred SD card invalid. Setting to card 0.." << std::endl;
sdInfo.active = sd::SdCard::SLOT_0;
@ -478,12 +467,12 @@ ReturnValue_t CoreController::sdStateMachine() {
sdFsmState = SdStates::DETERMINE_OTHER;
} else if (sdInfo.activeState == sd::SdState::OFF) {
sdCardSetup(sdInfo.active, sd::SdState::ON, sdInfo.activeChar, false);
sdInfo.commandExecuted = true;
sdInfo.commandPending = true;
} else if (sdInfo.activeState == sd::SdState::ON) {
sdFsmState = SdStates::MOUNT_SELF;
}
} else {
if (nonBlockingOpChecking(SdStates::MOUNT_SELF, 10, "Setting SDC state")) {
if (nonBlockingSdcOpChecking(SdStates::MOUNT_SELF, 10, "Setting SDC state")) {
sdInfo.activeState = sd::SdState::ON;
currentStateSetter(sdInfo.active, sd::SdState::ON);
}
@ -491,11 +480,11 @@ ReturnValue_t CoreController::sdStateMachine() {
}
if (sdFsmState == SdStates::MOUNT_SELF) {
if (not sdInfo.commandExecuted) {
if (not sdInfo.commandPending) {
result = sdCardSetup(sdInfo.active, sd::SdState::MOUNTED, sdInfo.activeChar);
sdInfo.commandExecuted = true;
sdInfo.commandPending = true;
} else {
if (nonBlockingOpChecking(SdStates::DETERMINE_OTHER, 5, "Mounting SD card")) {
if (nonBlockingSdcOpChecking(SdStates::DETERMINE_OTHER, 5, "Mounting SD card")) {
sdcMan->setActiveSdCard(sdInfo.active);
currMntPrefix = sdcMan->getCurrentMountPrefix();
sdInfo.activeState = sd::SdState::MOUNTED;
@ -532,23 +521,23 @@ ReturnValue_t CoreController::sdStateMachine() {
if (sdFsmState == SdStates::SET_STATE_OTHER) {
// Set state of other SD card to ON or OFF, depending on redundancy mode
if (sdInfo.cfgMode == SdCfgMode::COLD_REDUNDANT) {
if (not sdInfo.commandExecuted) {
if (not sdInfo.commandPending) {
result = sdCardSetup(sdInfo.other, sd::SdState::OFF, sdInfo.otherChar, false);
sdInfo.commandExecuted = true;
sdInfo.commandPending = true;
} else {
if (nonBlockingOpChecking(SdStates::SKIP_CYCLE_BEFORE_INFO_UPDATE, 10,
"Switching off other SD card")) {
if (nonBlockingSdcOpChecking(SdStates::SKIP_CYCLE_BEFORE_INFO_UPDATE, 10,
"Switching off other SD card")) {
sdInfo.otherState = sd::SdState::OFF;
currentStateSetter(sdInfo.other, sd::SdState::OFF);
}
}
} else if (sdInfo.cfgMode == SdCfgMode::HOT_REDUNDANT) {
if (not sdInfo.commandExecuted) {
if (not sdInfo.commandPending) {
result = sdCardSetup(sdInfo.other, sd::SdState::ON, sdInfo.otherChar, false);
sdInfo.commandExecuted = true;
sdInfo.commandPending = true;
} else {
if (nonBlockingOpChecking(SdStates::MOUNT_UNMOUNT_OTHER, 10,
"Switching on other SD card")) {
if (nonBlockingSdcOpChecking(SdStates::MOUNT_UNMOUNT_OTHER, 10,
"Switching on other SD card")) {
sdInfo.otherState = sd::SdState::ON;
currentStateSetter(sdInfo.other, sd::SdState::ON);
}
@ -559,21 +548,25 @@ ReturnValue_t CoreController::sdStateMachine() {
if (sdFsmState == SdStates::MOUNT_UNMOUNT_OTHER) {
// Mount or unmount other SD card, depending on redundancy mode
if (sdInfo.cfgMode == SdCfgMode::COLD_REDUNDANT) {
if (not sdInfo.commandExecuted) {
if (not sdInfo.commandPending) {
result = sdCardSetup(sdInfo.other, sd::SdState::ON, sdInfo.otherChar);
sdInfo.commandExecuted = true;
sdInfo.commandPending = true;
} else {
if (nonBlockingOpChecking(SdStates::SET_STATE_OTHER, 10, "Unmounting other SD card")) {
if (nonBlockingSdcOpChecking(SdStates::SET_STATE_OTHER, 10, "Unmounting other SD card")) {
sdInfo.otherState = sd::SdState::ON;
currentStateSetter(sdInfo.other, sd::SdState::ON);
} else {
sdInfo.otherState = sd::SdState::ON;
currentStateSetter(sdInfo.other, sd::SdState::ON);
sdFsmState = SdStates::SET_STATE_OTHER;
}
}
} else if (sdInfo.cfgMode == SdCfgMode::HOT_REDUNDANT) {
if (not sdInfo.commandExecuted) {
if (not sdInfo.commandPending) {
result = sdCardSetup(sdInfo.other, sd::SdState::MOUNTED, sdInfo.otherChar);
sdInfo.commandExecuted = true;
sdInfo.commandPending = true;
} else {
if (nonBlockingOpChecking(SdStates::UPDATE_INFO, 4, "Mounting other SD card")) {
if (nonBlockingSdcOpChecking(SdStates::UPDATE_SD_INFO_END, 4, "Mounting other SD card")) {
sdInfo.otherState = sd::SdState::MOUNTED;
currentStateSetter(sdInfo.other, sd::SdState::MOUNTED);
}
@ -582,14 +575,15 @@ ReturnValue_t CoreController::sdStateMachine() {
}
if (sdFsmState == SdStates::SKIP_CYCLE_BEFORE_INFO_UPDATE) {
sdFsmState = SdStates::UPDATE_INFO;
} else if (sdFsmState == SdStates::UPDATE_INFO) {
sdFsmState = SdStates::UPDATE_SD_INFO_END;
} else if (sdFsmState == SdStates::UPDATE_SD_INFO_END) {
// Update status file
result = sdcMan->updateSdCardStateFile();
if (result != returnvalue::OK) {
sif::warning << "CoreController::initialize: Updating SD card state file failed" << std::endl;
sif::warning << "CoreController: Updating SD card state file failed" << std::endl;
}
sdInfo.commandExecuted = false;
updateInternalSdInfo();
sdInfo.commandPending = false;
sdFsmState = SdStates::IDLE;
sdInfo.cycleCount = 0;
sdcMan->setBlocking(false);
@ -599,8 +593,16 @@ ReturnValue_t CoreController::sdStateMachine() {
actionHelper.finish(true, sdCommandingInfo.commander, sdCommandingInfo.actionId,
returnvalue::OK);
}
const char *modeStr = "UNKNOWN";
if (sdInfo.cfgMode == SdCfgMode::COLD_REDUNDANT) {
modeStr = "COLD REDUNDANT";
} else if (sdInfo.cfgMode == SdCfgMode::HOT_REDUNDANT) {
modeStr = "HOT REDUNDANT";
}
sif::info << "SD card update into " << modeStr
<< " mode finished. Active SD: " << sdInfo.activeChar << std::endl;
if (not sdInfo.initFinished) {
updateSdInfoOther();
updateInternalSdInfo();
sdInfo.initFinished = true;
sif::info << "SD card initialization finished" << std::endl;
}
@ -977,7 +979,7 @@ ReturnValue_t CoreController::gracefulShutdownTasks(xsc::Chip chip, xsc::Copy co
return result;
}
void CoreController::updateSdInfoOther() {
void CoreController::updateInternalSdInfo() {
if (sdInfo.active == sd::SdCard::SLOT_0) {
sdInfo.activeChar = "0";
sdInfo.otherChar = "1";

View File

@ -129,8 +129,7 @@ class CoreController : public ExtendedControllerBase {
enum class SdStates {
NONE,
START,
GET_INFO,
SET_STATE_SELF,
UPDATE_SD_INFO_START,
MOUNT_SELF,
// Determine operations for other SD card, depending on redundancy configuration
DETERMINE_OTHER,
@ -140,7 +139,7 @@ class CoreController : public ExtendedControllerBase {
// Skip period because the shell command used to generate the info file sometimes is
// missing the last performed operation if executed too early
SKIP_CYCLE_BEFORE_INFO_UPDATE,
UPDATE_INFO,
UPDATE_SD_INFO_END,
// SD initialization done
IDLE
};
@ -159,13 +158,12 @@ class CoreController : public ExtendedControllerBase {
SdCfgMode cfgMode = SdCfgMode::COLD_REDUNDANT;
sd::SdCard active = sd::SdCard::NONE;
sd::SdCard other = sd::SdCard::NONE;
sd::SdState activeState = sd::SdState::OFF;
sd::SdState otherState = sd::SdState::OFF;
std::string activeChar = "0";
std::string otherChar = "1";
sd::SdState activeState = sd::SdState::OFF;
sd::SdState otherState = sd::SdState::OFF;
std::pair<bool, bool> mountSwitch = {true, true};
// Used to track whether a command was executed
bool commandExecuted = true;
bool commandPending = true;
bool initFinished = false;
SdCardManager::SdStatePair currentState;
uint16_t cycleCount = 0;
@ -232,7 +230,7 @@ class CoreController : public ExtendedControllerBase {
void initPrint();
ReturnValue_t sdStateMachine();
void updateSdInfoOther();
void updateInternalSdInfo();
ReturnValue_t sdCardSetup(sd::SdCard sdCard, sd::SdState targetState, std::string sdChar,
bool printOutput = true);
ReturnValue_t executeSwUpdate(SwUpdateSources sourceDir, const uint8_t* data, size_t size);

View File

@ -237,7 +237,7 @@ void scheduling::initTasks() {
#if OBSW_ADD_RW == 1
PeriodicTaskIF* rwPolling =
factory->createPeriodicTask("RW_POLLING_TASK", 80, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2,
factory->createPeriodicTask("RW_POLLING_TASK", 75, PeriodicTaskIF::MINIMUM_STACK_SIZE * 2,
0.4, missedDeadlineFunc, &RR_SCHEDULING);
result = rwPolling->addComponent(objects::RW_POLLING_TASK);
if (result != returnvalue::OK) {

View File

@ -309,32 +309,6 @@ void SdCardManager::resetState() {
currentOp = Operations::IDLE;
}
ReturnValue_t SdCardManager::updateSdStatePair() {
using namespace std;
std::error_code e;
if (not filesystem::exists(SD_STATE_FILE, e)) {
return STATUS_FILE_NEXISTS;
}
// Now the file should exist in any case. Still check whether it exists.
fstream sdStatus(SD_STATE_FILE);
if (not sdStatus.good()) {
return STATUS_FILE_NEXISTS;
}
string line;
uint8_t idx = 0;
sd::SdCard currentSd = sd::SdCard::SLOT_0;
// Process status file line by line
while (std::getline(sdStatus, line)) {
processSdStatusLine(line, idx, currentSd);
}
if (sdStates.first != sd::SdState::MOUNTED && sdStates.second != sd::SdState::MOUNTED) {
sdCardActive = false;
}
return returnvalue::OK;
}
void SdCardManager::processSdStatusLine(std::string& line, uint8_t& idx, sd::SdCard& currentSd) {
using namespace std;
istringstream iss(line);
@ -407,6 +381,7 @@ ReturnValue_t SdCardManager::setPreferredSdCard(sd::SdCard sdCard) {
}
ReturnValue_t SdCardManager::updateSdCardStateFile() {
using namespace std;
if (cmdExecutor.getCurrentState() == CommandExecutor::States::PENDING) {
return CommandExecutor::COMMAND_PENDING;
}
@ -414,10 +389,31 @@ ReturnValue_t SdCardManager::updateSdCardStateFile() {
std::string updateCmd = "q7hw sd info all > " + std::string(SD_STATE_FILE);
cmdExecutor.load(updateCmd, true, printCmdOutput);
ReturnValue_t result = cmdExecutor.execute();
if (blocking and result != returnvalue::OK) {
if (result != returnvalue::OK) {
utility::handleSystemError(cmdExecutor.getLastError(), "SdCardManager::mountSdCard");
}
return result;
std::error_code e;
if (not filesystem::exists(SD_STATE_FILE, e)) {
return STATUS_FILE_NEXISTS;
}
// Now the file should exist in any case. Still check whether it exists.
fstream sdStatus(SD_STATE_FILE);
if (not sdStatus.good()) {
return STATUS_FILE_NEXISTS;
}
string line;
uint8_t idx = 0;
sd::SdCard currentSd = sd::SdCard::SLOT_0;
// Process status file line by line
while (std::getline(sdStatus, line)) {
processSdStatusLine(line, idx, currentSd);
}
if (sdStates.first != sd::SdState::MOUNTED && sdStates.second != sd::SdState::MOUNTED) {
sdCardActive = false;
}
return returnvalue::OK;
}
const char* SdCardManager::getCurrentMountPrefix() const {

View File

@ -117,16 +117,6 @@ class SdCardManager : public SystemObject, public SdCardMountedIF {
ReturnValue_t switchOffSdCard(sd::SdCard sdCard, bool doUnmountSdCard = true,
SdStatePair* statusPair = nullptr);
/**
* Update the state file or creates one if it does not exist. You need to call this
* function before calling #sdCardActive
* @return
* - returnvalue::OK if the state file was updated successfully
* - CommandExecutor::COMMAND_PENDING: Non-blocking command is pending
* - returnvalue::FAILED: blocking command failed
*/
ReturnValue_t updateSdCardStateFile();
/**
* Get the state of the SD cards. If the state file does not exist, this function will
* take care of updating it. If it does not, the function will use the state file to get
@ -234,7 +224,15 @@ class SdCardManager : public SystemObject, public SdCardMountedIF {
SdCardManager();
ReturnValue_t updateSdStatePair();
/**
* Update the state file or creates one if it does not exist. You need to call this
* function before calling #sdCardActive
* @return
* - returnvalue::OK if the state file was updated successfully
* - CommandExecutor::COMMAND_PENDING: Non-blocking command is pending
* - returnvalue::FAILED: blocking command failed
*/
ReturnValue_t updateSdCardStateFile();
ReturnValue_t setSdCardState(sd::SdCard sdCard, bool on);

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
0x4404;UXOS_NoCommandLoadedOrPending;;4;LINUX_OSAL;fsfw/src/fsfw_hal/linux/CommandExecutor.h
0x4406;UXOS_PcloseCallError;No description;6;LINUX_OSAL;fsfw/src/fsfw_hal/linux/CommandExecutor.h
0x4500;HSPI_HalTimeoutRetval;No description;0;HAL_SPI;fsfw/src/fsfw_hal/stm32h7/spi/spiDefinitions.h
0x4501;HSPI_HalBusyRetval;No description;1;HAL_SPI;fsfw/src/fsfw_hal/stm32h7/spi/spiDefinitions.h
0x4502;HSPI_HalErrorRetval;No description;2;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_FullDuplexTransferFailed;No description;1;HAL_SPI;fsfw/src/fsfw_hal/common/spi/spiCommon.h
0x4502;HSPI_HalfDuplexTransferFailed;No description;2;HAL_SPI;fsfw/src/fsfw_hal/common/spi/spiCommon.h
0x4503;HSPI_Timeout;No description;3;HAL_SPI;fsfw/src/fsfw_hal/common/spi/spiCommon.h
0x4504;HSPI_Busy;No description;4;HAL_SPI;fsfw/src/fsfw_hal/common/spi/spiCommon.h
0x4505;HSPI_GenericError;No description;5;HAL_SPI;fsfw/src/fsfw_hal/common/spi/spiCommon.h
0x4601;HURT_UartReadFailure;No description;1;HAL_UART;fsfw/src/fsfw_hal/linux/serial/SerialComIF.h
0x4602;HURT_UartReadSizeMissmatch;No description;2;HAL_UART;fsfw/src/fsfw_hal/linux/serial/SerialComIF.h
0x4603;HURT_UartRxBufferTooSmall;No description;3;HAL_UART;fsfw/src/fsfw_hal/linux/serial/SerialComIF.h

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_OpeningFileFailed No description 0 HAL_SPI fsfw/src/fsfw_hal/common/spi/spiCommon.h
406 0x4501 HSPI_FullDuplexTransferFailed No description 1 HAL_SPI fsfw/src/fsfw_hal/common/spi/spiCommon.h
407 0x4502 HSPI_HalfDuplexTransferFailed No description 2 HAL_SPI 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 0x4503 0x4601 HSPI_Timeout HURT_UartReadFailure No description 3 1 HAL_SPI HAL_UART fsfw/src/fsfw_hal/common/spi/spiCommon.h fsfw/src/fsfw_hal/linux/serial/SerialComIF.h
412 0x4504 0x4602 HSPI_Busy HURT_UartReadSizeMissmatch No description 4 2 HAL_SPI HAL_UART fsfw/src/fsfw_hal/common/spi/spiCommon.h fsfw/src/fsfw_hal/linux/serial/SerialComIF.h
413 0x4505 0x4603 HSPI_GenericError HURT_UartRxBufferTooSmall No description 5 3 HAL_SPI HAL_UART fsfw/src/fsfw_hal/common/spi/spiCommon.h 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
0x4404;UXOS_NoCommandLoadedOrPending;;4;LINUX_OSAL;fsfw/src/fsfw_hal/linux/CommandExecutor.h
0x4406;UXOS_PcloseCallError;No description;6;LINUX_OSAL;fsfw/src/fsfw_hal/linux/CommandExecutor.h
0x4500;HSPI_HalTimeoutRetval;No description;0;HAL_SPI;fsfw/src/fsfw_hal/stm32h7/spi/spiDefinitions.h
0x4501;HSPI_HalBusyRetval;No description;1;HAL_SPI;fsfw/src/fsfw_hal/stm32h7/spi/spiDefinitions.h
0x4502;HSPI_HalErrorRetval;No description;2;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_FullDuplexTransferFailed;No description;1;HAL_SPI;fsfw/src/fsfw_hal/common/spi/spiCommon.h
0x4502;HSPI_HalfDuplexTransferFailed;No description;2;HAL_SPI;fsfw/src/fsfw_hal/common/spi/spiCommon.h
0x4503;HSPI_Timeout;No description;3;HAL_SPI;fsfw/src/fsfw_hal/common/spi/spiCommon.h
0x4504;HSPI_Busy;No description;4;HAL_SPI;fsfw/src/fsfw_hal/common/spi/spiCommon.h
0x4505;HSPI_GenericError;No description;5;HAL_SPI;fsfw/src/fsfw_hal/common/spi/spiCommon.h
0x4601;HURT_UartReadFailure;No description;1;HAL_UART;fsfw/src/fsfw_hal/linux/serial/SerialComIF.h
0x4602;HURT_UartReadSizeMissmatch;No description;2;HAL_UART;fsfw/src/fsfw_hal/linux/serial/SerialComIF.h
0x4603;HURT_UartRxBufferTooSmall;No description;3;HAL_UART;fsfw/src/fsfw_hal/linux/serial/SerialComIF.h

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_OpeningFileFailed No description 0 HAL_SPI fsfw/src/fsfw_hal/common/spi/spiCommon.h
406 0x4501 HSPI_FullDuplexTransferFailed No description 1 HAL_SPI fsfw/src/fsfw_hal/common/spi/spiCommon.h
407 0x4502 HSPI_HalfDuplexTransferFailed No description 2 HAL_SPI 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 0x4503 0x4601 HSPI_Timeout HURT_UartReadFailure No description 3 1 HAL_SPI HAL_UART fsfw/src/fsfw_hal/common/spi/spiCommon.h fsfw/src/fsfw_hal/linux/serial/SerialComIF.h
412 0x4504 0x4602 HSPI_Busy HURT_UartReadSizeMissmatch No description 4 2 HAL_SPI HAL_UART fsfw/src/fsfw_hal/common/spi/spiCommon.h fsfw/src/fsfw_hal/linux/serial/SerialComIF.h
413 0x4505 0x4603 HSPI_GenericError HURT_UartRxBufferTooSmall No description 5 3 HAL_SPI HAL_UART fsfw/src/fsfw_hal/common/spi/spiCommon.h fsfw/src/fsfw_hal/linux/serial/SerialComIF.h

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -75,6 +75,8 @@ class RwHandler : public DeviceHandlerBase {
GpioIF* gpioComIF = nullptr;
gpioId_t enableGpio = gpio::NO_GPIO;
bool debugMode = false;
Countdown offTransitionCountdown = Countdown(5000);
rws::RwRequest currentRequest;
rws::StatusSet statusSet;
rws::LastResetSatus lastResetStatusSet;
@ -87,27 +89,16 @@ class RwHandler : public DeviceHandlerBase {
PoolEntry<int32_t> rwSpeed = PoolEntry<int32_t>({0});
PoolEntry<uint16_t> rampTime = PoolEntry<uint16_t>({10});
enum class InternalState {
DEFAULT,
GET_TM,
INIT_RW_CONTROLLER,
RESET_MCU,
// GET_RESET_STATUS,
// CLEAR_RESET_STATUS,
// READ_TEMPERATURE,
// SET_SPEED,
// GET_RW_SATUS
};
enum class InternalState { DEFAULT, GET_TM, INIT_RW_CONTROLLER, RESET_MCU, SHUTDOWN };
enum class ShutdownState {
NONE,
SET_SPEED_ZERO,
STOP_POLLING,
DONE,
} shutdownState = ShutdownState::NONE;
InternalState internalState = InternalState::DEFAULT;
/**
* @brief This function can be used to build commands which do not contain any data apart
* from the command id and the CRC.
* @param commandId The command id of the command to build.
*/
// void prepareSimpleCommand(DeviceCommandId_t id);
/**
* @brief This function checks if the receiced speed and ramp time to set are in a valid
* range.
@ -115,13 +106,6 @@ class RwHandler : public DeviceHandlerBase {
*/
ReturnValue_t checkSpeedAndRampTime();
/**
* @brief This function prepares the set speed command from the dataSet received with
* an action message or set in the software.
* @return returnvalue::OK if successful, otherwise error code.
*/
// ReturnValue_t prepareSetSpeedCmd();
/**
* @brief This function writes the last reset status retrieved with the get last reset status
* command into the reset status dataset.

View File

@ -4,6 +4,7 @@
#include <fsfw/datapoollocal/LocalPoolVariable.h>
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
#include <fsfw/devicehandlers/DeviceHandlerIF.h>
#include <mission/acs/defs.h>
#include "eive/resultClassIds.h"
#include "events/subsystemIdRanges.h"
@ -36,6 +37,15 @@ enum class SpecialRwRequest : uint8_t {
NUM_REQUESTS
};
struct RwRequest {
acs::SimpleSensorMode mode = acs::SimpleSensorMode::OFF;
bool setSpeed = true;
int32_t currentRwSpeed = 0;
uint16_t currentRampTime = 0;
rws::SpecialRwRequest specialRequest = rws::SpecialRwRequest::REQUEST_NONE;
uint8_t rwIdx = 0;
};
static const uint8_t INTERFACE_ID = CLASS_ID::RW_HANDLER;
static const ReturnValue_t SPI_WRITE_FAILURE = MAKE_RETURN_CODE(0xB0);

View File

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

View File

@ -144,9 +144,6 @@ ReturnValue_t EiveSystem::executeAction(ActionId_t actionId, MessageQueueId_t co
case (EXECUTE_I2C_REBOOT): {
triggerEvent(core::TRYING_I2C_RECOVERY);
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;
this->actionCommandedBy = commandedBy;
return returnvalue::OK;
@ -264,11 +261,11 @@ void EiveSystem::commandSelfToSafe() { startTransition(satsystem::Mode::SAFE, 0)
void EiveSystem::commonI2cRecoverySequenceFinish() {
alreadyTriedI2cRecovery = true;
performI2cReboot = false;
i2cRecoveryClearCountdown.resetTimer();
i2cRebootState = I2cRebootState::NONE;
// Reset this counter. If I2C devices are still problematic, we will get a full reboot
// next time this count goes above 5.
// 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();
}

View File

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

View File

@ -228,3 +228,27 @@ bool ComSubsystem::isTxMode(Mode_t mode) {
}
return false;
}
void ComSubsystem::announceMode(bool recursive) {
const char *modeStr = "UNKNOWN";
switch (mode) {
case (com::RX_ONLY): {
modeStr = "RX_ONLY";
break;
}
case (com::RX_AND_TX_LOW_DATARATE): {
modeStr = "RX_AND_TX_LOW_DATARATE";
break;
}
case (com::RX_AND_TX_HIGH_DATARATE): {
modeStr = "RX_AND_TX_HIGH_DATARATE";
break;
}
case (com::RX_AND_TX_DEFAULT_DATARATE): {
modeStr = "RX_AND_TX_DEFAULT_DATARATE";
break;
}
}
sif::info << "COM subsystem is now in " << modeStr << " mode" << std::endl;
return Subsystem::announceMode(recursive);
}

View File

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

2
tmtc

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