Merge remote-tracking branch 'origin/develop' into mueller/heater-health-if
Some checks failed
EIVE/eive-obsw/pipeline/pr-develop There was a failure building this commit
Some checks failed
EIVE/eive-obsw/pipeline/pr-develop There was a failure building this commit
This commit is contained in:
@@ -408,7 +408,7 @@ ReturnValue_t GyroADIS1650XHandler::spiSendCallback(SpiComIF *comIf, SpiCookie *
|
||||
int retval = 0;
|
||||
// Prepare transfer
|
||||
int fileDescriptor = 0;
|
||||
std::string device = cookie->getSpiDevice();
|
||||
std::string device = comIf->getSpiDev();
|
||||
UnixFileGuard fileHelper(device, &fileDescriptor, O_RDWR, "SpiComIF::sendMessage");
|
||||
if (fileHelper.getOpenResult() != HasReturnvaluesIF::RETURN_OK) {
|
||||
return SpiComIF::OPENING_FILE_FAILED;
|
||||
|
@@ -697,8 +697,7 @@ ReturnValue_t PayloadPcduHandler::transferAsTwo(SpiComIF* comIf, SpiCookie* cook
|
||||
int retval = 0;
|
||||
// Prepare transfer
|
||||
int fileDescriptor = 0;
|
||||
std::string device = cookie->getSpiDevice();
|
||||
UnixFileGuard fileHelper(device, &fileDescriptor, O_RDWR, "SpiComIF::sendMessage");
|
||||
UnixFileGuard fileHelper(comIf->getSpiDev(), &fileDescriptor, O_RDWR, "SpiComIF::sendMessage");
|
||||
if (fileHelper.getOpenResult() != HasReturnvaluesIF::RETURN_OK) {
|
||||
return SpiComIF::OPENING_FILE_FAILED;
|
||||
}
|
||||
|
@@ -2,22 +2,22 @@
|
||||
|
||||
#include <fsfw/datapool/PoolReadGuard.h>
|
||||
#include <fsfw/globalfunctions/CRC.h>
|
||||
#include <fsfw_hal/common/gpio/GpioIF.h>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
|
||||
RwHandler::RwHandler(object_id_t objectId, object_id_t comIF, CookieIF* comCookie,
|
||||
LinuxLibgpioIF* gpioComIF, gpioId_t enableGpio)
|
||||
GpioIF* gpioComIF, gpioId_t enableGpio)
|
||||
: DeviceHandlerBase(objectId, comIF, comCookie),
|
||||
gpioComIF(gpioComIF),
|
||||
enableGpio(enableGpio),
|
||||
temperatureSet(this),
|
||||
statusSet(this),
|
||||
lastResetStatusSet(this),
|
||||
tmDataset(this) {
|
||||
if (comCookie == NULL) {
|
||||
if (comCookie == nullptr) {
|
||||
sif::error << "RwHandler: Invalid com cookie" << std::endl;
|
||||
}
|
||||
if (gpioComIF == NULL) {
|
||||
if (gpioComIF == nullptr) {
|
||||
sif::error << "RwHandler: Invalid gpio communication interface" << std::endl;
|
||||
}
|
||||
}
|
||||
@@ -46,11 +46,6 @@ ReturnValue_t RwHandler::buildNormalDeviceCommand(DeviceCommandId_t* id) {
|
||||
*id = RwDefinitions::GET_LAST_RESET_STATUS;
|
||||
internalState = InternalState::READ_TEMPERATURE;
|
||||
break;
|
||||
case InternalState::CLEAR_RESET_STATUS:
|
||||
*id = RwDefinitions::CLEAR_LAST_RESET_STATUS;
|
||||
/** After reset status is cleared, reset status will be polled again for verification */
|
||||
internalState = InternalState::GET_RESET_STATUS;
|
||||
break;
|
||||
case InternalState::READ_TEMPERATURE:
|
||||
*id = RwDefinitions::GET_TEMPERATURE;
|
||||
internalState = InternalState::GET_RW_SATUS;
|
||||
@@ -59,6 +54,11 @@ ReturnValue_t RwHandler::buildNormalDeviceCommand(DeviceCommandId_t* id) {
|
||||
*id = RwDefinitions::GET_RW_STATUS;
|
||||
internalState = InternalState::GET_RESET_STATUS;
|
||||
break;
|
||||
case InternalState::CLEAR_RESET_STATUS:
|
||||
*id = RwDefinitions::CLEAR_LAST_RESET_STATUS;
|
||||
/** After reset status is cleared, reset status will be polled again for verification */
|
||||
internalState = InternalState::GET_RESET_STATUS;
|
||||
break;
|
||||
default:
|
||||
sif::debug << "RwHandler::buildNormalDeviceCommand: Invalid internal step" << std::endl;
|
||||
break;
|
||||
@@ -133,7 +133,7 @@ void RwHandler::fillCommandAndReplyMap() {
|
||||
RwDefinitions::SIZE_GET_RW_STATUS);
|
||||
this->insertInCommandAndReplyMap(RwDefinitions::INIT_RW_CONTROLLER, 1, nullptr,
|
||||
RwDefinitions::SIZE_INIT_RW);
|
||||
this->insertInCommandAndReplyMap(RwDefinitions::GET_TEMPERATURE, 1, &temperatureSet,
|
||||
this->insertInCommandAndReplyMap(RwDefinitions::GET_TEMPERATURE, 1, nullptr,
|
||||
RwDefinitions::SIZE_GET_TEMPERATURE_REPLY);
|
||||
this->insertInCommandAndReplyMap(RwDefinitions::SET_SPEED, 1, nullptr,
|
||||
RwDefinitions::SIZE_SET_SPEED_REPLY);
|
||||
@@ -239,8 +239,6 @@ ReturnValue_t RwHandler::interpretDeviceReply(DeviceCommandId_t id, const uint8_
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
void RwHandler::setNormalDatapoolEntriesInvalid() {}
|
||||
|
||||
uint32_t RwHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { return 5000; }
|
||||
|
||||
ReturnValue_t RwHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
||||
@@ -279,7 +277,6 @@ ReturnValue_t RwHandler::initializeLocalDataPool(localpool::DataPool& localDataP
|
||||
localDataPoolMap.emplace(RwDefinitions::SPI_BYTES_READ, new PoolEntry<uint32_t>({0}));
|
||||
localDataPoolMap.emplace(RwDefinitions::SPI_REG_OVERRUN_ERRORS, new PoolEntry<uint32_t>({0}));
|
||||
localDataPoolMap.emplace(RwDefinitions::SPI_TOTAL_ERRORS, new PoolEntry<uint32_t>({0}));
|
||||
poolManager.subscribeForPeriodicPacket(temperatureSet.getSid(), false, 30.0, false);
|
||||
poolManager.subscribeForPeriodicPacket(statusSet.getSid(), false, 5.0, true);
|
||||
poolManager.subscribeForPeriodicPacket(tmDataset.getSid(), false, 30.0, false);
|
||||
return RETURN_OK;
|
||||
@@ -335,16 +332,18 @@ void RwHandler::prepareSetSpeedCmd(const uint8_t* commandData, size_t commandDat
|
||||
void RwHandler::handleResetStatusReply(const uint8_t* packet) {
|
||||
PoolReadGuard rg(&lastResetStatusSet);
|
||||
uint8_t offset = 2;
|
||||
uint8_t resetStatus = *(packet + offset);
|
||||
if (resetStatus != RwDefinitions::CLEARED) {
|
||||
uint8_t resetStatus = packet[offset];
|
||||
if (resetStatus != 0) {
|
||||
internalState = InternalState::CLEAR_RESET_STATUS;
|
||||
lastResetStatusSet.lastResetStatus = resetStatus;
|
||||
lastResetStatusSet.lastNonClearedResetStatus = resetStatus;
|
||||
triggerEvent(RwDefinitions::RESET_OCCURED, resetStatus, 0);
|
||||
}
|
||||
lastResetStatusSet.currentResetStatus = resetStatus;
|
||||
if (debugMode) {
|
||||
#if OBSW_VERBOSE_LEVEL >= 1
|
||||
sif::info << "RwHandler::handleResetStatusReply: Last reset status: "
|
||||
<< static_cast<unsigned int>(lastResetStatusSet.lastResetStatus.value) << std::endl;
|
||||
<< static_cast<unsigned int>(lastResetStatusSet.lastNonClearedResetStatus.value)
|
||||
<< std::endl;
|
||||
sif::info << "RwHandler::handleResetStatusReply: Current reset status: "
|
||||
<< static_cast<unsigned int>(lastResetStatusSet.currentResetStatus.value)
|
||||
<< std::endl;
|
||||
@@ -353,24 +352,33 @@ void RwHandler::handleResetStatusReply(const uint8_t* packet) {
|
||||
}
|
||||
|
||||
void RwHandler::handleGetRwStatusReply(const uint8_t* packet) {
|
||||
PoolReadGuard rg(&statusSet);
|
||||
PoolReadGuard rg0(&statusSet);
|
||||
PoolReadGuard rg1(&tmDataset);
|
||||
uint8_t offset = 2;
|
||||
statusSet.currSpeed = *(packet + offset + 3) << 24 | *(packet + offset + 2) << 16 |
|
||||
*(packet + offset + 1) << 8 | *(packet + offset);
|
||||
tmDataset.rwCurrSpeed = statusSet.currSpeed;
|
||||
tmDataset.rwCurrSpeed.setValid(true);
|
||||
offset += 4;
|
||||
statusSet.referenceSpeed = *(packet + offset + 3) << 24 | *(packet + offset + 2) << 16 |
|
||||
*(packet + offset + 1) << 8 | *(packet + offset);
|
||||
tmDataset.rwRefSpeed = statusSet.referenceSpeed;
|
||||
tmDataset.rwRefSpeed.setValid(true);
|
||||
offset += 4;
|
||||
statusSet.state = *(packet + offset);
|
||||
tmDataset.rwState = statusSet.state;
|
||||
tmDataset.rwState.setValid(true);
|
||||
offset += 1;
|
||||
statusSet.clcMode = *(packet + offset);
|
||||
tmDataset.rwClcMode = statusSet.clcMode;
|
||||
tmDataset.rwClcMode.setValid(true);
|
||||
|
||||
statusSet.setValidity(true, true);
|
||||
|
||||
if (statusSet.state == RwDefinitions::STATE_ERROR) {
|
||||
/**
|
||||
* This requires the commanding of the init reaction wheel controller command to recover
|
||||
* form error state which must be handled by the FDIR instance.
|
||||
*/
|
||||
triggerEvent(ERROR_STATE);
|
||||
// This requires the commanding of the init reaction wheel controller command to recover
|
||||
// from error state which must be handled by the FDIR instance.
|
||||
triggerEvent(RwDefinitions::ERROR_STATE, statusSet.state.value, 0);
|
||||
sif::error << "RwHandler::handleGetRwStatusReply: Reaction wheel in error state" << std::endl;
|
||||
}
|
||||
|
||||
@@ -389,14 +397,14 @@ void RwHandler::handleGetRwStatusReply(const uint8_t* packet) {
|
||||
}
|
||||
|
||||
void RwHandler::handleTemperatureReply(const uint8_t* packet) {
|
||||
PoolReadGuard rg(&temperatureSet);
|
||||
PoolReadGuard rg(&statusSet);
|
||||
uint8_t offset = 2;
|
||||
temperatureSet.temperatureCelcius = *(packet + offset + 3) << 24 | *(packet + offset + 2) << 16 |
|
||||
*(packet + offset + 1) << 8 | *(packet + offset);
|
||||
statusSet.temperatureCelcius = *(packet + offset + 3) << 24 | *(packet + offset + 2) << 16 |
|
||||
*(packet + offset + 1) << 8 | *(packet + offset);
|
||||
if (debugMode) {
|
||||
#if OBSW_VERBOSE_LEVEL >= 1
|
||||
sif::info << "RwHandler::handleTemperatureReply: Temperature: "
|
||||
<< temperatureSet.temperatureCelcius << " °C" << std::endl;
|
||||
sif::info << "RwHandler::handleTemperatureReply: Temperature: " << statusSet.temperatureCelcius
|
||||
<< " °C" << std::endl;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@@ -2,10 +2,12 @@
|
||||
#define MISSION_DEVICES_RWHANDLER_H_
|
||||
|
||||
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
|
||||
#include <fsfw_hal/linux/gpio/LinuxLibgpioIF.h>
|
||||
#include <fsfw_hal/common/gpio/gpioDefinitions.h>
|
||||
#include <mission/devices/devicedefinitions/RwDefinitions.h>
|
||||
#include <string.h>
|
||||
|
||||
class GpioIF;
|
||||
|
||||
/**
|
||||
* @brief This is the device handler for the reaction wheel from nano avionics.
|
||||
*
|
||||
@@ -28,7 +30,7 @@ class RwHandler : public DeviceHandlerBase {
|
||||
* @param enablePin GPIO connected to the enable pin of the reaction wheels. Must be pulled
|
||||
* to high to enable the device.
|
||||
*/
|
||||
RwHandler(object_id_t objectId, object_id_t comIF, CookieIF* comCookie, LinuxLibgpioIF* gpioComIF,
|
||||
RwHandler(object_id_t objectId, object_id_t comIF, CookieIF* comCookie, GpioIF* gpioComIF,
|
||||
gpioId_t enableGpio);
|
||||
|
||||
void setDebugMode(bool enable);
|
||||
@@ -64,14 +66,11 @@ class RwHandler : public DeviceHandlerBase {
|
||||
ReturnValue_t scanForReply(const uint8_t* start, size_t remainingSize, DeviceCommandId_t* foundId,
|
||||
size_t* foundLen) override;
|
||||
ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, const uint8_t* packet) override;
|
||||
void setNormalDatapoolEntriesInvalid() override;
|
||||
uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override;
|
||||
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
||||
LocalDataPoolManager& poolManager) override;
|
||||
|
||||
private:
|
||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::RW_HANDLER;
|
||||
|
||||
//! [EXPORT] : [COMMENT] Action Message with invalid speed was received. Valid speeds must be in
|
||||
//! the range of [-65000; 1000] or [1000; 65000]
|
||||
static const ReturnValue_t INVALID_SPEED = MAKE_RETURN_CODE(0xA0);
|
||||
@@ -84,14 +83,10 @@ class RwHandler : public DeviceHandlerBase {
|
||||
//! [EXPORT] : [COMMENT] Reaction wheel reply has invalid crc
|
||||
static const ReturnValue_t CRC_ERROR = MAKE_RETURN_CODE(0xA4);
|
||||
|
||||
//! [EXPORT] : [COMMENT] Reaction wheel signals an error state
|
||||
static const Event ERROR_STATE = MAKE_EVENT(1, severity::HIGH);
|
||||
|
||||
LinuxLibgpioIF* gpioComIF = nullptr;
|
||||
GpioIF* gpioComIF = nullptr;
|
||||
gpioId_t enableGpio = gpio::NO_GPIO;
|
||||
bool debugMode = false;
|
||||
|
||||
RwDefinitions::TemperatureSet temperatureSet;
|
||||
RwDefinitions::StatusSet statusSet;
|
||||
RwDefinitions::LastResetSatus lastResetStatusSet;
|
||||
RwDefinitions::TmDataset tmDataset;
|
||||
|
@@ -9,6 +9,13 @@
|
||||
|
||||
namespace RwDefinitions {
|
||||
|
||||
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::RW_HANDLER;
|
||||
|
||||
//! [EXPORT] : [COMMENT] Reaction wheel signals an error state
|
||||
static constexpr Event ERROR_STATE = MAKE_EVENT(1, severity::HIGH);
|
||||
|
||||
static constexpr Event RESET_OCCURED = event::makeEvent(SUBSYSTEM_ID, 2, severity::LOW);
|
||||
|
||||
static const uint32_t SPI_REPLY_DELAY = 70000; // us
|
||||
|
||||
enum PoolIds : lp_id_t {
|
||||
@@ -48,14 +55,13 @@ enum PoolIds : lp_id_t {
|
||||
|
||||
enum States : uint8_t { STATE_ERROR, IDLE, COASTING, RUNNING_SPEED_STABLE, RUNNING_SPEED_CHANGING };
|
||||
|
||||
enum LastResetStatus : uint8_t {
|
||||
CLEARED = 0,
|
||||
PIN_RESET = 1,
|
||||
POR_PDR_BOR_RESET = 2,
|
||||
SOFTWARE_RESET = 4,
|
||||
INDEPENDENT_WATCHDOG_RESET = 8,
|
||||
WINDOW_WATCHDOG_RESET = 16,
|
||||
LOW_POWER_RESET = 32
|
||||
enum LastResetStatusBitPos : uint8_t {
|
||||
PIN_RESET = 0,
|
||||
POR_PDR_BOR_RESET = 1,
|
||||
SOFTWARE_RESET = 2,
|
||||
INDEPENDENT_WATCHDOG_RESET = 3,
|
||||
WINDOW_WATCHDOG_RESET = 4,
|
||||
LOW_POWER_RESET = 5
|
||||
};
|
||||
|
||||
static const DeviceCommandId_t RESET_MCU = 1;
|
||||
@@ -91,25 +97,11 @@ static const size_t MAX_CMD_SIZE = 9;
|
||||
static const size_t MAX_REPLY_SIZE = 2 * SIZE_GET_TELEMETRY_REPLY;
|
||||
|
||||
static const uint8_t LAST_RESET_ENTRIES = 2;
|
||||
static const uint8_t TEMPERATURE_SET_ENTRIES = 1;
|
||||
static const uint8_t STATUS_SET_ENTRIES = 4;
|
||||
static const uint8_t STATUS_SET_ENTRIES = 5;
|
||||
static const uint8_t TM_SET_ENTRIES = 24;
|
||||
|
||||
/**
|
||||
* @brief This dataset can be used to store the temperature of a reaction wheel.
|
||||
*/
|
||||
class TemperatureSet : public StaticLocalDataSet<TEMPERATURE_SET_ENTRIES> {
|
||||
public:
|
||||
TemperatureSet(HasLocalDataPoolIF* owner) : StaticLocalDataSet(owner, TEMPERATURE_SET_ID) {}
|
||||
|
||||
TemperatureSet(object_id_t objectId) : StaticLocalDataSet(sid_t(objectId, TEMPERATURE_SET_ID)) {}
|
||||
|
||||
lp_var_t<int32_t> temperatureCelcius =
|
||||
lp_var_t<int32_t>(sid.objectId, PoolIds::TEMPERATURE_C, this);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This dataset can be used to store the reaction wheel status.
|
||||
* @brief This dataset can be used to store the data periodically polled from the RW
|
||||
*/
|
||||
class StatusSet : public StaticLocalDataSet<STATUS_SET_ENTRIES> {
|
||||
public:
|
||||
@@ -117,6 +109,8 @@ class StatusSet : public StaticLocalDataSet<STATUS_SET_ENTRIES> {
|
||||
|
||||
StatusSet(object_id_t objectId) : StaticLocalDataSet(sid_t(objectId, STATUS_SET_ID)) {}
|
||||
|
||||
lp_var_t<int32_t> temperatureCelcius =
|
||||
lp_var_t<int32_t>(sid.objectId, PoolIds::TEMPERATURE_C, this);
|
||||
lp_var_t<int32_t> currSpeed = lp_var_t<int32_t>(sid.objectId, PoolIds::CURR_SPEED, this);
|
||||
lp_var_t<int32_t> referenceSpeed =
|
||||
lp_var_t<int32_t>(sid.objectId, PoolIds::REFERENCE_SPEED, this);
|
||||
@@ -133,8 +127,10 @@ class LastResetSatus : public StaticLocalDataSet<LAST_RESET_ENTRIES> {
|
||||
|
||||
LastResetSatus(object_id_t objectId) : StaticLocalDataSet(sid_t(objectId, LAST_RESET_ID)) {}
|
||||
|
||||
lp_var_t<uint8_t> lastResetStatus =
|
||||
// If a reset occurs, the status code will be cached into this variable
|
||||
lp_var_t<uint8_t> lastNonClearedResetStatus =
|
||||
lp_var_t<uint8_t>(sid.objectId, PoolIds::LAST_RESET_STATUS, this);
|
||||
// This will always contain the last polled reset status
|
||||
lp_var_t<uint8_t> currentResetStatus =
|
||||
lp_var_t<uint8_t>(sid.objectId, PoolIds::CURRRENT_RESET_STATUS, this);
|
||||
};
|
||||
|
@@ -10,7 +10,7 @@ static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PCDU_HANDLER;
|
||||
//! [EXPORT] : [COMMENT] Indicates that a FSFW object requested setting a switch
|
||||
//! P1: 1 if on was requested, 0 for off | P2: Switch Index
|
||||
static constexpr Event SWITCH_CMD_SENT = event::makeEvent(SUBSYSTEM_ID, 0, severity::INFO);
|
||||
//! [EXPORT] : [COMMENT] Indicated that a swithc state has changed
|
||||
//! [EXPORT] : [COMMENT] Indicated that a switch state has changed
|
||||
//! P1: New switch state, 1 for on, 0 for off | P2: Switch Index
|
||||
static constexpr Event SWITCH_HAS_CHANGED = event::makeEvent(SUBSYSTEM_ID, 1, severity::INFO);
|
||||
static constexpr Event SWITCHING_Q7S_DENIED = event::makeEvent(SUBSYSTEM_ID, 2, severity::MEDIUM);
|
||||
|
@@ -5,6 +5,7 @@ target_sources(${LIB_EIVE_MISSION} PRIVATE
|
||||
PayloadSubsystem.cpp
|
||||
|
||||
AcsBoardAssembly.cpp
|
||||
RwAssembly.cpp
|
||||
SusAssembly.cpp
|
||||
DualLanePowerStateMachine.cpp
|
||||
PowerStateMachineBase.cpp
|
||||
|
191
mission/system/RwAssembly.cpp
Normal file
191
mission/system/RwAssembly.cpp
Normal file
@@ -0,0 +1,191 @@
|
||||
#include "RwAssembly.h"
|
||||
|
||||
RwAssembly::RwAssembly(object_id_t objectId, object_id_t parentId, PowerSwitchIF* pwrSwitcher,
|
||||
power::Switch_t switcher, RwHelper helper)
|
||||
: AssemblyBase(objectId, parentId), helper(helper), switcher(pwrSwitcher, switcher) {
|
||||
ModeListEntry entry;
|
||||
for (uint8_t idx = 0; idx < NUMBER_RWS; idx++) {
|
||||
entry.setObject(helper.rwIds[idx]);
|
||||
entry.setMode(MODE_OFF);
|
||||
entry.setSubmode(SUBMODE_NONE);
|
||||
entry.setInheritSubmode(false);
|
||||
modeTable.insert(entry);
|
||||
}
|
||||
}
|
||||
|
||||
void RwAssembly::performChildOperation() {
|
||||
auto state = switcher.getState();
|
||||
if (state != PowerSwitcher::WAIT_OFF and state != PowerSwitcher::WAIT_ON) {
|
||||
AssemblyBase::performChildOperation();
|
||||
return;
|
||||
}
|
||||
switcher.doStateMachine();
|
||||
if (state == PowerSwitcher::WAIT_OFF and switcher.getState() == PowerSwitcher::SWITCH_IS_OFF) {
|
||||
// Indicator that a transition to off is finished
|
||||
AssemblyBase::handleModeReached();
|
||||
} else if (state == PowerSwitcher::WAIT_ON and
|
||||
switcher.getState() == PowerSwitcher::SWITCH_IS_ON) {
|
||||
// Indicator that mode commanding can be performed now
|
||||
AssemblyBase::startTransition(targetMode, targetSubmode);
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t RwAssembly::commandChildren(Mode_t mode, Submode_t submode) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
modeTransitionFailedSwitch = true;
|
||||
// Initialize the mode table to ensure all devices are in a defined state
|
||||
for (uint8_t idx = 0; idx < NUMBER_RWS; idx++) {
|
||||
modeTable[idx].setMode(MODE_OFF);
|
||||
modeTable[idx].setSubmode(SUBMODE_NONE);
|
||||
}
|
||||
if (recoveryState != RecoveryState::RECOVERY_STARTED) {
|
||||
if (mode == DeviceHandlerIF::MODE_NORMAL or mode == MODE_ON) {
|
||||
result = handleNormalOrOnModeCmd(mode, submode);
|
||||
}
|
||||
}
|
||||
HybridIterator<ModeListEntry> tableIter(modeTable.begin(), modeTable.end());
|
||||
executeTable(tableIter);
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t RwAssembly::checkChildrenStateOn(Mode_t wantedMode, Submode_t wantedSubmode) {
|
||||
int devsInCorrectMode = 0;
|
||||
try {
|
||||
for (uint8_t idx = 0; idx < NUMBER_RWS; idx++) {
|
||||
if (childrenMap.at(helper.rwIds[idx]).mode == wantedMode) {
|
||||
devsInCorrectMode++;
|
||||
}
|
||||
}
|
||||
} catch (const std::out_of_range& e) {
|
||||
sif::error << "RwAssembly: Invalid children map: " << e.what() << std::endl;
|
||||
}
|
||||
if (devsInCorrectMode < 3) {
|
||||
if (warningSwitch) {
|
||||
sif::warning << "RwAssembly::checkChildrenStateOn: Only " << devsInCorrectMode
|
||||
<< " devices in correct mode" << std::endl;
|
||||
warningSwitch = false;
|
||||
}
|
||||
return NOT_ENOUGH_CHILDREN_IN_CORRECT_STATE;
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t RwAssembly::isModeCombinationValid(Mode_t mode, Submode_t submode) {
|
||||
if (mode == MODE_ON or mode == MODE_OFF or mode == DeviceHandlerIF::MODE_NORMAL) {
|
||||
return RETURN_OK;
|
||||
}
|
||||
return HasModesIF::INVALID_MODE;
|
||||
}
|
||||
|
||||
void RwAssembly::startTransition(Mode_t mode, Submode_t submode) {
|
||||
if (mode != MODE_OFF) {
|
||||
switcher.turnOn(true);
|
||||
switcher.doStateMachine();
|
||||
if (switcher.getState() == PowerSwitcher::SWITCH_IS_ON) {
|
||||
AssemblyBase::startTransition(mode, submode);
|
||||
} else {
|
||||
// Need to wait with mode commanding until power switcher is done
|
||||
targetMode = mode;
|
||||
targetSubmode = submode;
|
||||
}
|
||||
} else {
|
||||
// Perform regular mode commanding first
|
||||
AssemblyBase::startTransition(mode, submode);
|
||||
}
|
||||
}
|
||||
|
||||
void RwAssembly::handleModeReached() {
|
||||
if (targetMode == MODE_OFF) {
|
||||
switcher.turnOff(true);
|
||||
switcher.doStateMachine();
|
||||
// Need to wait with call to AssemblyBase::handleModeReached until power switcher is done
|
||||
if (switcher.getState() == PowerSwitcher::SWITCH_IS_OFF) {
|
||||
AssemblyBase::handleModeReached();
|
||||
}
|
||||
} else {
|
||||
AssemblyBase::handleModeReached();
|
||||
}
|
||||
}
|
||||
|
||||
void RwAssembly::handleChildrenLostMode(ReturnValue_t result) {
|
||||
AssemblyBase::handleChildrenLostMode(result);
|
||||
}
|
||||
|
||||
ReturnValue_t RwAssembly::handleNormalOrOnModeCmd(Mode_t mode, Submode_t submode) {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
bool needsSecondStep = false;
|
||||
Mode_t devMode = 0;
|
||||
object_id_t objId = 0;
|
||||
try {
|
||||
for (uint8_t idx = 0; idx < NUMBER_RWS; idx++) {
|
||||
devMode = childrenMap.at(helper.rwIds[idx]).mode;
|
||||
objId = helper.rwIds[idx];
|
||||
if (mode == devMode) {
|
||||
modeTable[idx].setMode(mode);
|
||||
} else if (mode == DeviceHandlerIF::MODE_NORMAL) {
|
||||
if (isUseable(objId, devMode)) {
|
||||
if (devMode == MODE_ON) {
|
||||
modeTable[idx].setMode(mode);
|
||||
modeTable[idx].setSubmode(SUBMODE_NONE);
|
||||
} else {
|
||||
modeTable[idx].setMode(MODE_ON);
|
||||
modeTable[idx].setSubmode(SUBMODE_NONE);
|
||||
if (internalState != STATE_SECOND_STEP) {
|
||||
needsSecondStep = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (mode == MODE_ON) {
|
||||
if (isUseable(objId, devMode)) {
|
||||
modeTable[idx].setMode(MODE_ON);
|
||||
modeTable[idx].setSubmode(SUBMODE_NONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (const std::out_of_range& e) {
|
||||
sif::error << "TcsBoardAssembly: Invalid children map: " << e.what() << std::endl;
|
||||
}
|
||||
if (needsSecondStep) {
|
||||
result = NEED_SECOND_STEP;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool RwAssembly::isUseable(object_id_t object, Mode_t mode) {
|
||||
if (healthHelper.healthTable->isFaulty(object)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if device is already in target mode
|
||||
if (childrenMap[object].mode == mode) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (healthHelper.healthTable->isCommandable(object)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ReturnValue_t RwAssembly::initialize() {
|
||||
ReturnValue_t result = RETURN_OK;
|
||||
for (const auto& obj : helper.rwIds) {
|
||||
result = registerChild(obj);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return SubsystemBase::initialize();
|
||||
}
|
||||
|
||||
void RwAssembly::handleModeTransitionFailed(ReturnValue_t result) {
|
||||
if (targetMode == MODE_OFF) {
|
||||
AssemblyBase::handleModeTransitionFailed(result);
|
||||
} else {
|
||||
if (modeTransitionFailedSwitch) {
|
||||
// To avoid transitioning back to off
|
||||
triggerEvent(MODE_TRANSITION_FAILED, result);
|
||||
modeTransitionFailedSwitch = false;
|
||||
}
|
||||
}
|
||||
}
|
51
mission/system/RwAssembly.h
Normal file
51
mission/system/RwAssembly.h
Normal file
@@ -0,0 +1,51 @@
|
||||
#ifndef MISSION_SYSTEM_RWASS_H_
|
||||
#define MISSION_SYSTEM_RWASS_H_
|
||||
|
||||
#include <fsfw/devicehandlers/AssemblyBase.h>
|
||||
#include <fsfw/power/PowerSwitcher.h>
|
||||
|
||||
struct RwHelper {
|
||||
RwHelper(std::array<object_id_t, 4> rwIds) : rwIds(rwIds) {}
|
||||
|
||||
std::array<object_id_t, 4> rwIds = {};
|
||||
};
|
||||
|
||||
class RwAssembly : public AssemblyBase {
|
||||
public:
|
||||
RwAssembly(object_id_t objectId, object_id_t parentId, PowerSwitchIF* pwrSwitcher,
|
||||
power::Switch_t switcher, RwHelper helper);
|
||||
|
||||
private:
|
||||
static constexpr uint8_t NUMBER_RWS = 4;
|
||||
RwHelper helper;
|
||||
PowerSwitcher switcher;
|
||||
bool warningSwitch = true;
|
||||
bool modeTransitionFailedSwitch = true;
|
||||
FixedArrayList<ModeListEntry, NUMBER_RWS> modeTable;
|
||||
|
||||
ReturnValue_t initialize() override;
|
||||
|
||||
ReturnValue_t handleNormalOrOnModeCmd(Mode_t mode, Submode_t submode);
|
||||
/**
|
||||
* Check whether it makes sense to send mode commands to the device
|
||||
* @param object
|
||||
* @param mode
|
||||
* @return
|
||||
*/
|
||||
bool isUseable(object_id_t object, Mode_t mode);
|
||||
|
||||
// AssemblyBase implementation
|
||||
void performChildOperation() override;
|
||||
ReturnValue_t commandChildren(Mode_t mode, Submode_t submode) override;
|
||||
ReturnValue_t checkChildrenStateOn(Mode_t wantedMode, Submode_t wantedSubmode) override;
|
||||
ReturnValue_t isModeCombinationValid(Mode_t mode, Submode_t submode) override;
|
||||
void startTransition(Mode_t mode, Submode_t submode) override;
|
||||
void handleModeReached() override;
|
||||
|
||||
// These two overrides prevent a transition of the whole assembly back to off just because
|
||||
// some devices are not working
|
||||
void handleChildrenLostMode(ReturnValue_t result) override;
|
||||
void handleModeTransitionFailed(ReturnValue_t result) override;
|
||||
};
|
||||
|
||||
#endif /* MISSION_SYSTEM_RWASS_H_ */
|
@@ -32,7 +32,6 @@ void TcsBoardAssembly::performChildOperation() {
|
||||
switcher.getState() == PowerSwitcher::SWITCH_IS_ON) {
|
||||
// Indicator that mode commanding can be performed now
|
||||
AssemblyBase::startTransition(targetMode, targetSubmode);
|
||||
// AssemblyBase::performChildOperation();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -21,8 +21,6 @@ class TcsBoardAssembly : public AssemblyBase, public ConfirmsFailuresIF {
|
||||
|
||||
ReturnValue_t initialize() override;
|
||||
|
||||
void performChildOperation() override;
|
||||
|
||||
private:
|
||||
static constexpr uint8_t NUMBER_RTDS = 16;
|
||||
PowerSwitcher switcher;
|
||||
@@ -44,6 +42,7 @@ class TcsBoardAssembly : public AssemblyBase, public ConfirmsFailuresIF {
|
||||
MessageQueueId_t getEventReceptionQueue() override;
|
||||
|
||||
// AssemblyBase implementation
|
||||
void performChildOperation() override;
|
||||
ReturnValue_t commandChildren(Mode_t mode, Submode_t submode) override;
|
||||
ReturnValue_t checkChildrenStateOn(Mode_t wantedMode, Submode_t wantedSubmode) override;
|
||||
ReturnValue_t isModeCombinationValid(Mode_t mode, Submode_t submode) override;
|
||||
|
Reference in New Issue
Block a user