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

This commit is contained in:
2022-05-12 14:11:46 +02:00
59 changed files with 1063 additions and 1718 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -5,6 +5,7 @@ target_sources(${LIB_EIVE_MISSION} PRIVATE
PayloadSubsystem.cpp
AcsBoardAssembly.cpp
RwAssembly.cpp
SusAssembly.cpp
DualLanePowerStateMachine.cpp
PowerStateMachineBase.cpp

View 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;
}
}
}

View 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_ */

View File

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

View File

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