diff --git a/src/fsfw/devicehandlers/DeviceHandlerBase.cpp b/src/fsfw/devicehandlers/DeviceHandlerBase.cpp index 8ab540a0..ae986ca3 100644 --- a/src/fsfw/devicehandlers/DeviceHandlerBase.cpp +++ b/src/fsfw/devicehandlers/DeviceHandlerBase.cpp @@ -22,8 +22,6 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, object_id_t device CookieIF* comCookie, FailureIsolationBase* fdirInstance, size_t cmdQueueSize) : SystemObject(setObjectId), - mode(MODE_OFF), - submode(SUBMODE_NONE), wiretappingMode(OFF), storedRawData(StorageManagerIF::INVALID_ADDRESS), deviceCommunicationId(deviceCommunication), @@ -38,6 +36,8 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, object_id_t device defaultFDIRUsed(fdirInstance == nullptr), switchOffWasReported(false), childTransitionDelay(5000), + mode(MODE_OFF), + submode(SUBMODE_NONE), transitionSourceMode(_MODE_POWER_DOWN), transitionSourceSubMode(SUBMODE_NONE) { commandQueue = QueueFactory::instance()->createMessageQueue( @@ -352,7 +352,6 @@ void DeviceHandlerBase::doStateMachine() { currentUptime - timeoutStart >= powerSwitcher->getSwitchDelayMs()) { triggerEvent(MODE_TRANSITION_FAILED, PowerSwitchIF::SWITCH_TIMEOUT, 0); setMode(_MODE_POWER_DOWN); - callChildStatemachine(); break; } ReturnValue_t switchState = getStateOfSwitches(); @@ -567,11 +566,23 @@ void DeviceHandlerBase::setTransition(Mode_t modeTo, Submode_t submodeTo) { void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) { /* TODO: This will probably be done by the LocalDataPoolManager now */ // changeHK(mode, submode, false); + + /** + * handle transition from OFF to NORMAL by continuing towards normal when ON is reached + */ + if (newMode == MODE_ON and continueToNormal) { + continueToNormal = false; + mode = _MODE_TO_NORMAL; + return; + } + submode = newSubmode; mode = newMode; modeChanged(); setNormalDatapoolEntriesInvalid(); if (!isTransitionalMode()) { + //clear this flag when a non-transitional Mode is reached to be safe + continueToNormal = false; modeHelper.modeChanged(newMode, newSubmode); announceMode(false); } @@ -1056,8 +1067,7 @@ Mode_t DeviceHandlerBase::getBaseMode(Mode_t transitionMode) { return transitionMode & ~(TRANSITION_MODE_BASE_ACTION_MASK | TRANSITION_MODE_CHILD_ACTION_MASK); } -// SHOULDDO: Allow transition from OFF to NORMAL to reduce complexity in assemblies. And, by the -// way, throw away DHB and write a new one: +// SHOULDDO: throw away DHB and write a new one: // - Include power and thermal completely, but more modular :-) // - Don't use modes for state transitions, reduce FSM (Finte State Machine) complexity. // - Modularization? @@ -1069,11 +1079,10 @@ ReturnValue_t DeviceHandlerBase::checkModeCommand(Mode_t commandedMode, Submode_ if ((mode == MODE_ERROR_ON) && (commandedMode != MODE_OFF)) { return TRANS_NOT_ALLOWED; } - if ((commandedMode == MODE_NORMAL) && (mode == MODE_OFF)) { - return TRANS_NOT_ALLOWED; - } - if ((commandedMode == MODE_ON) && (mode == MODE_OFF) and (thermalSet != nullptr)) { + // Do not check thermal state for MODE_RAW + if ((mode == MODE_OFF) and ((commandedMode == MODE_ON) or (commandedMode == MODE_NORMAL)) and + (thermalSet != nullptr)) { ReturnValue_t result = thermalSet->read(); if (result == returnvalue::OK) { if ((thermalSet->heaterRequest.value != ThermalComponentIF::STATE_REQUEST_IGNORE) and @@ -1088,6 +1097,7 @@ ReturnValue_t DeviceHandlerBase::checkModeCommand(Mode_t commandedMode, Submode_ } void DeviceHandlerBase::startTransition(Mode_t commandedMode, Submode_t commandedSubmode) { + continueToNormal = false; switch (commandedMode) { case MODE_ON: handleTransitionToOnMode(commandedMode, commandedSubmode); @@ -1117,8 +1127,9 @@ void DeviceHandlerBase::startTransition(Mode_t commandedMode, Submode_t commande case MODE_NORMAL: if (mode != MODE_OFF) { setTransition(MODE_NORMAL, commandedSubmode); - } else { - replyReturnvalueToCommand(HasModesIF::TRANS_NOT_ALLOWED); + } else { // mode is off + continueToNormal = true; + handleTransitionToOnMode(MODE_NORMAL, commandedSubmode); } break; } diff --git a/src/fsfw/devicehandlers/DeviceHandlerBase.h b/src/fsfw/devicehandlers/DeviceHandlerBase.h index 700e960d..1fc4b1de 100644 --- a/src/fsfw/devicehandlers/DeviceHandlerBase.h +++ b/src/fsfw/devicehandlers/DeviceHandlerBase.h @@ -102,6 +102,54 @@ class DeviceHandlerBase : public DeviceHandlerIF, DeviceHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, CookieIF *comCookie, FailureIsolationBase *fdirInstance = nullptr, size_t cmdQueueSize = 20); + + /** + * extending the modes of DeviceHandler IF for internal state machine + */ + static constexpr uint8_t TRANSITION_MODE_CHILD_ACTION_MASK = 0x20; + static constexpr uint8_t TRANSITION_MODE_BASE_ACTION_MASK = 0x10; + //! This is a transitional state which can not be commanded. The device + //! handler performs all commands to get the device in a state ready to + //! perform commands. When this is completed, the mode changes to @c MODE_ON. + static const Mode_t _MODE_START_UP = TRANSITION_MODE_CHILD_ACTION_MASK | 5; + //! This is a transitional state which can not be commanded. + //! The device handler performs all actions and commands to get the device + //! shut down. When the device is off, the mode changes to @c MODE_OFF. + //! It is possible to set the mode to _MODE_SHUT_DOWN to use the to off + //! transition if available. + static const Mode_t _MODE_SHUT_DOWN = TRANSITION_MODE_CHILD_ACTION_MASK | 6; + //! It is possible to set the mode to _MODE_TO_ON to use the to on + //! transition if available. + static const Mode_t _MODE_TO_ON = TRANSITION_MODE_CHILD_ACTION_MASK | HasModesIF::MODE_ON; + //! It is possible to set the mode to _MODE_TO_RAW to use the to raw + //! transition if available. + static const Mode_t _MODE_TO_RAW = TRANSITION_MODE_CHILD_ACTION_MASK | MODE_RAW; + //! It is possible to set the mode to _MODE_TO_NORMAL to use the to normal + //! transition if available. + static const Mode_t _MODE_TO_NORMAL = TRANSITION_MODE_CHILD_ACTION_MASK | MODE_NORMAL; + //! This is a transitional state which can not be commanded. + //! The device is shut down and ready to be switched off. + //! After the command to set the switch off has been sent, + //! the mode changes to @c _MODE_WAIT_OFF + static const Mode_t _MODE_POWER_DOWN = TRANSITION_MODE_BASE_ACTION_MASK | 1; + //! This is a transitional state which can not be commanded. The device + //! will be switched on in this state. After the command to set the switch + //! on has been sent, the mode changes to @c _MODE_WAIT_ON. + static const Mode_t _MODE_POWER_ON = TRANSITION_MODE_BASE_ACTION_MASK | 2; + //! This is a transitional state which can not be commanded. The switch has + //! been commanded off and the handler waits for it to be off. + //! When the switch is off, the mode changes to @c MODE_OFF. + static const Mode_t _MODE_WAIT_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 3; + //! This is a transitional state which can not be commanded. The switch + //! has been commanded on and the handler waits for it to be on. + //! When the switch is on, the mode changes to @c _MODE_TO_ON. + static const Mode_t _MODE_WAIT_ON = TRANSITION_MODE_BASE_ACTION_MASK | 4; + //! This is a transitional state which can not be commanded. The switch has + //! been commanded off and is off now. This state is only to do an RMAP + //! cycle once more where the doSendRead() function will set the mode to + //! MODE_OFF. The reason to do this is to get rid of stuck packets in the IO Board. + static const Mode_t _MODE_SWITCH_IS_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 5; + void setHkDestination(object_id_t hkDestination); /** @@ -684,15 +732,18 @@ class DeviceHandlerBase : public DeviceHandlerIF, size_t rawPacketLen = 0; /** - * The mode the device handler is currently in. - * This should never be changed directly but only with setMode() - */ - Mode_t mode; + * Get the current mode + * + * set via setMode() + */ + Mode_t getMode(); + /** - * The submode the device handler is currently in. - * This should never be changed directly but only with setMode() - */ - Submode_t submode; + * Get the current Submode + * + * set via setMode() + */ + Submode_t getSubmode; /** This is the counter value from performOperation(). */ uint8_t pstStep = 0; @@ -873,8 +924,8 @@ class DeviceHandlerBase : public DeviceHandlerIF, * Do the transition to the main modes (MODE_ON, MODE_NORMAL and MODE_RAW). * * If the transition is complete, the mode should be set to the target mode, - * which can be deduced from the current mode which is - * [_MODE_TO_ON, _MODE_TO_NORMAL, _MODE_TO_RAW] + * which can be deduced from the current mode (which is + * [_MODE_TO_ON, _MODE_TO_NORMAL, _MODE_TO_RAW]) using getBaseMode() * * The intended target submode is already set. * The origin submode can be read in subModeFrom. @@ -1170,6 +1221,19 @@ class DeviceHandlerBase : public DeviceHandlerIF, */ uint32_t childTransitionDelay; + /** + * The mode the device handler is currently in. + * This should not be changed directly but only with setMode() + */ + Mode_t mode; + + + /** + * The submode the device handler is currently in. + * This should not be changed directly but only with setMode() + */ + Submode_t submode; + /** * @brief The mode the current transition originated from * @@ -1187,6 +1251,15 @@ class DeviceHandlerBase : public DeviceHandlerIF, */ Submode_t transitionSourceSubMode; + /** + * used to make the state machine continue from ON to NOMAL when + * a Device is commanded to NORMAL in OFF mode + * + * set in startTransition() + * evaluated in setMode() to continue to NORMAL when ON is reached + */ + bool continueToNormal; + /** * read the command queue */ diff --git a/src/fsfw/devicehandlers/DeviceHandlerIF.h b/src/fsfw/devicehandlers/DeviceHandlerIF.h index 1fc63d3b..672f2830 100644 --- a/src/fsfw/devicehandlers/DeviceHandlerIF.h +++ b/src/fsfw/devicehandlers/DeviceHandlerIF.h @@ -24,8 +24,6 @@ class DeviceHandlerIF { static const DeviceCommandId_t RAW_COMMAND_ID = -1; static const DeviceCommandId_t NO_COMMAND_ID = -2; - static constexpr uint8_t TRANSITION_MODE_CHILD_ACTION_MASK = 0x20; - static constexpr uint8_t TRANSITION_MODE_BASE_ACTION_MASK = 0x10; using dh_heater_request_t = uint8_t; using dh_thermal_state_t = int8_t; @@ -54,47 +52,6 @@ class DeviceHandlerIF { //! device still is powered. In this mode, only a mode change to @c MODE_OFF //! can be commanded, which tries to switch off the device again. static const Mode_t MODE_ERROR_ON = 4; - //! This is a transitional state which can not be commanded. The device - //! handler performs all commands to get the device in a state ready to - //! perform commands. When this is completed, the mode changes to @c MODE_ON. - static const Mode_t _MODE_START_UP = TRANSITION_MODE_CHILD_ACTION_MASK | 5; - //! This is a transitional state which can not be commanded. - //! The device handler performs all actions and commands to get the device - //! shut down. When the device is off, the mode changes to @c MODE_OFF. - //! It is possible to set the mode to _MODE_SHUT_DOWN to use the to off - //! transition if available. - static const Mode_t _MODE_SHUT_DOWN = TRANSITION_MODE_CHILD_ACTION_MASK | 6; - //! It is possible to set the mode to _MODE_TO_ON to use the to on - //! transition if available. - static const Mode_t _MODE_TO_ON = TRANSITION_MODE_CHILD_ACTION_MASK | HasModesIF::MODE_ON; - //! It is possible to set the mode to _MODE_TO_RAW to use the to raw - //! transition if available. - static const Mode_t _MODE_TO_RAW = TRANSITION_MODE_CHILD_ACTION_MASK | MODE_RAW; - //! It is possible to set the mode to _MODE_TO_NORMAL to use the to normal - //! transition if available. - static const Mode_t _MODE_TO_NORMAL = TRANSITION_MODE_CHILD_ACTION_MASK | MODE_NORMAL; - //! This is a transitional state which can not be commanded. - //! The device is shut down and ready to be switched off. - //! After the command to set the switch off has been sent, - //! the mode changes to @c MODE_WAIT_OFF - static const Mode_t _MODE_POWER_DOWN = TRANSITION_MODE_BASE_ACTION_MASK | 1; - //! This is a transitional state which can not be commanded. The device - //! will be switched on in this state. After the command to set the switch - //! on has been sent, the mode changes to @c MODE_WAIT_ON. - static const Mode_t _MODE_POWER_ON = TRANSITION_MODE_BASE_ACTION_MASK | 2; - //! This is a transitional state which can not be commanded. The switch has - //! been commanded off and the handler waits for it to be off. - //! When the switch is off, the mode changes to @c MODE_OFF. - static const Mode_t _MODE_WAIT_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 3; - //! This is a transitional state which can not be commanded. The switch - //! has been commanded on and the handler waits for it to be on. - //! When the switch is on, the mode changes to @c MODE_TO_ON. - static const Mode_t _MODE_WAIT_ON = TRANSITION_MODE_BASE_ACTION_MASK | 4; - //! This is a transitional state which can not be commanded. The switch has - //! been commanded off and is off now. This state is only to do an RMAP - //! cycle once more where the doSendRead() function will set the mode to - //! MODE_OFF. The reason to do this is to get rid of stuck packets in the IO Board. - static const Mode_t _MODE_SWITCH_IS_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 5; static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::CDH; static const Event DEVICE_BUILDING_COMMAND_FAILED = MAKE_EVENT(0, severity::LOW); diff --git a/src/fsfw_hal/devicehandlers/MgmLIS3MDLHandler.cpp b/src/fsfw_hal/devicehandlers/MgmLIS3MDLHandler.cpp index 9cb16c35..1ff42890 100644 --- a/src/fsfw_hal/devicehandlers/MgmLIS3MDLHandler.cpp +++ b/src/fsfw_hal/devicehandlers/MgmLIS3MDLHandler.cpp @@ -195,7 +195,7 @@ ReturnValue_t MgmLIS3MDLHandler::scanForReply(const uint8_t *start, size_t len, #endif return DeviceHandlerIF::INVALID_DATA; } - if (mode == _MODE_START_UP) { + if (getMode() == _MODE_START_UP) { commandExecuted = true; } @@ -224,7 +224,7 @@ ReturnValue_t MgmLIS3MDLHandler::scanForReply(const uint8_t *start, size_t len, return DeviceHandlerIF::INVALID_DATA; } - if (mode == _MODE_START_UP) { + if (getMode() == _MODE_START_UP) { commandExecuted = true; } } diff --git a/src/fsfw_hal/devicehandlers/MgmRM3100Handler.cpp b/src/fsfw_hal/devicehandlers/MgmRM3100Handler.cpp index a32153eb..707ca338 100644 --- a/src/fsfw_hal/devicehandlers/MgmRM3100Handler.cpp +++ b/src/fsfw_hal/devicehandlers/MgmRM3100Handler.cpp @@ -169,7 +169,7 @@ ReturnValue_t MgmRM3100Handler::interpretDeviceReply(DeviceCommandId_t id, const case (RM3100::CONFIGURE_CYCLE_COUNT): case (RM3100::CONFIGURE_TMRC): { // We can only check whether write was successful with read operation - if (mode == _MODE_START_UP) { + if (getMode() == _MODE_START_UP) { commandExecuted = true; } break; @@ -192,7 +192,7 @@ ReturnValue_t MgmRM3100Handler::interpretDeviceReply(DeviceCommandId_t id, const if (packet[1] == tmrcRegValue) { commandExecuted = true; // Reading TMRC was commanded. Trigger event to inform ground - if (mode != _MODE_START_UP) { + if (getMode() != _MODE_START_UP) { triggerEvent(tmrcSet, tmrcRegValue, 0); } } else { @@ -211,7 +211,7 @@ ReturnValue_t MgmRM3100Handler::interpretDeviceReply(DeviceCommandId_t id, const return DeviceHandlerIF::DEVICE_REPLY_INVALID; } // Reading TMRC was commanded. Trigger event to inform ground - if (mode != _MODE_START_UP) { + if (getMode() != _MODE_START_UP) { uint32_t eventParam1 = (cycleCountX << 16) | cycleCountY; triggerEvent(cycleCountersSet, eventParam1, cycleCountZ); } diff --git a/src/fsfw_tests/integration/devices/TestDeviceHandler.cpp b/src/fsfw_tests/integration/devices/TestDeviceHandler.cpp index fdf02a70..b6a6f465 100644 --- a/src/fsfw_tests/integration/devices/TestDeviceHandler.cpp +++ b/src/fsfw_tests/integration/devices/TestDeviceHandler.cpp @@ -65,7 +65,7 @@ ReturnValue_t TestDevice::buildNormalDeviceCommand(DeviceCommandId_t* id) { } ReturnValue_t TestDevice::buildTransitionDeviceCommand(DeviceCommandId_t* id) { - if (mode == _MODE_TO_ON) { + if (getMode() == _MODE_TO_ON) { if (fullInfoPrintout) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::info << "TestDevice" << deviceIdx @@ -80,7 +80,7 @@ ReturnValue_t TestDevice::buildTransitionDeviceCommand(DeviceCommandId_t* id) { #endif } } - if (mode == _MODE_TO_NORMAL) { + if (getMode() == _MODE_TO_NORMAL) { if (fullInfoPrintout) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::info << "TestDevice" << deviceIdx @@ -97,7 +97,7 @@ ReturnValue_t TestDevice::buildTransitionDeviceCommand(DeviceCommandId_t* id) { setMode(MODE_NORMAL); } - if (mode == _MODE_SHUT_DOWN) { + if (getMode() == _MODE_SHUT_DOWN) { if (fullInfoPrintout) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::info << "TestDevice" << deviceIdx @@ -118,7 +118,7 @@ ReturnValue_t TestDevice::buildTransitionDeviceCommand(DeviceCommandId_t* id) { } void TestDevice::doTransition(Mode_t modeFrom, Submode_t submodeFrom) { - if (mode == _MODE_TO_NORMAL) { + if (getMode() == _MODE_TO_NORMAL) { if (fullInfoPrintout) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::info << "TestDevice" << deviceIdx diff --git a/unittests/mocks/DeviceHandlerMock.cpp b/unittests/mocks/DeviceHandlerMock.cpp index ef0a23d8..3ad80048 100644 --- a/unittests/mocks/DeviceHandlerMock.cpp +++ b/unittests/mocks/DeviceHandlerMock.cpp @@ -5,7 +5,7 @@ DeviceHandlerMock::DeviceHandlerMock(object_id_t objectId, object_id_t deviceCommunication, CookieIF *comCookie, FailureIsolationBase *fdirInstance) : DeviceHandlerBase(objectId, deviceCommunication, comCookie, fdirInstance) { - mode = MODE_ON; + setMode(MODE_ON); } DeviceHandlerMock::~DeviceHandlerMock() = default;