Compare commits

..

5 Commits

15 changed files with 69 additions and 69 deletions

View File

@ -35,7 +35,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## Changed ## Changed
- send HK one-parameter-report back to sender instead of default hk queue
- Complete overhaul of HK subsystem. Replaced local data pool manager by periodic HK - Complete overhaul of HK subsystem. Replaced local data pool manager by periodic HK
helper. The shared pool and the periodic HK generation are now distinct concepts. helper. The shared pool and the periodic HK generation are now distinct concepts.
- The local HK manager was replaced by a periodic HK helper which has reduced responsibilities. - The local HK manager was replaced by a periodic HK helper which has reduced responsibilities.

View File

@ -71,7 +71,7 @@ bool AssemblyBase::handleChildrenChangedHealth() {
if (iter == childrenMap.end()) { if (iter == childrenMap.end()) {
return false; return false;
} }
HealthState healthState = healthHelper.healthTable->getHealth(convertToDeviceObjectId(iter->first)); HealthState healthState = healthHelper.healthTable->getHealth(iter->first);
if (healthState == HasHealthIF::NEEDS_RECOVERY) { if (healthState == HasHealthIF::NEEDS_RECOVERY) {
triggerEvent(TRYING_RECOVERY, iter->first, 0); triggerEvent(TRYING_RECOVERY, iter->first, 0);
recoveryState = RECOVERY_STARTED; recoveryState = RECOVERY_STARTED;
@ -92,15 +92,10 @@ void AssemblyBase::handleChildrenTransition() {
if (commandsOutstanding <= 0) { if (commandsOutstanding <= 0) {
switch (internalState) { switch (internalState) {
case STATE_NEED_SECOND_STEP: case STATE_NEED_SECOND_STEP:
{
internalState = STATE_SECOND_STEP; internalState = STATE_SECOND_STEP;
ReturnValue_t result = commandChildren(targetMode, targetSubmode); commandChildren(targetMode, targetSubmode);
if(result == NEED_SECOND_STEP) {
internalState = STATE_NEED_SECOND_STEP;
}
return; return;
} case STATE_OVERWRITE_HEALTH: {
case STATE_OVERWRITE_HEALTH: {
internalState = STATE_SINGLE_STEP; internalState = STATE_SINGLE_STEP;
ReturnValue_t result = commandChildren(mode, submode); ReturnValue_t result = commandChildren(mode, submode);
if (result == NEED_SECOND_STEP) { if (result == NEED_SECOND_STEP) {
@ -175,7 +170,7 @@ ReturnValue_t AssemblyBase::checkChildrenStateOff() {
ReturnValue_t AssemblyBase::checkChildOff(uint32_t objectId) { ReturnValue_t AssemblyBase::checkChildOff(uint32_t objectId) {
ChildInfo childInfo = childrenMap.find(objectId)->second; ChildInfo childInfo = childrenMap.find(objectId)->second;
if (healthHelper.healthTable->isCommandable(convertToDeviceObjectId(objectId))) { if (healthHelper.healthTable->isCommandable(objectId)) {
if (childInfo.submode != SUBMODE_NONE) { if (childInfo.submode != SUBMODE_NONE) {
return returnvalue::FAILED; return returnvalue::FAILED;
} else { } else {
@ -232,7 +227,7 @@ bool AssemblyBase::checkAndHandleRecovery() {
case RECOVERY_STARTED: case RECOVERY_STARTED:
// The recovery was already start in #handleChildrenChangedHealth and we just need // The recovery was already start in #handleChildrenChangedHealth and we just need
// to wait for an off time period. // to wait for an off time period.
// The timeout can be defined by #setRecoveryWaitTimer // TODO: make time period configurable
recoveryState = RECOVERY_WAIT; recoveryState = RECOVERY_WAIT;
recoveryOffTimer.resetTimer(); recoveryOffTimer.resetTimer();
return true; return true;
@ -240,14 +235,14 @@ bool AssemblyBase::checkAndHandleRecovery() {
if (recoveryOffTimer.isBusy()) { if (recoveryOffTimer.isBusy()) {
return true; return true;
} }
triggerEvent(RECOVERY_WAITING, recoveringDevice->first); triggerEvent(RECOVERY_STEP, 0);
sendHealthCommand(recoveringDevice->second.commandQueue, HEALTHY); sendHealthCommand(recoveringDevice->second.commandQueue, HEALTHY);
internalState = STATE_NONE; internalState = STATE_NONE;
recoveryState = RECOVERY_ONGOING; recoveryState = RECOVERY_ONGOING;
// Don't check state! // Don't check state!
return true; return true;
case RECOVERY_ONGOING: case RECOVERY_ONGOING:
triggerEvent(RECOVERY_RESTARTING, recoveringDevice->first); triggerEvent(RECOVERY_STEP, 1);
recoveryState = RECOVERY_ONGOING_2; recoveryState = RECOVERY_ONGOING_2;
recoveringDevice->second.healthChanged = false; recoveringDevice->second.healthChanged = false;
// Device should be healthy again, so restart a transition. // Device should be healthy again, so restart a transition.
@ -255,7 +250,7 @@ bool AssemblyBase::checkAndHandleRecovery() {
doStartTransition(targetMode, targetSubmode); doStartTransition(targetMode, targetSubmode);
return true; return true;
case RECOVERY_ONGOING_2: case RECOVERY_ONGOING_2:
triggerEvent(RECOVERY_DONE, recoveringDevice->first); triggerEvent(RECOVERY_DONE);
// Now we're through, but not sure if it was successful. // Now we're through, but not sure if it was successful.
recoveryState = RECOVERY_IDLE; recoveryState = RECOVERY_IDLE;
return false; return false;
@ -269,15 +264,7 @@ void AssemblyBase::overwriteDeviceHealth(object_id_t objectId, HasHealthIF::Heal
triggerEvent(OVERWRITING_HEALTH, objectId, oldHealth); triggerEvent(OVERWRITING_HEALTH, objectId, oldHealth);
internalState = STATE_OVERWRITE_HEALTH; internalState = STATE_OVERWRITE_HEALTH;
modeHelper.setForced(true); modeHelper.setForced(true);
if(childrenMap.find(objectId) != childrenMap.end()) { sendHealthCommand(childrenMap[objectId].commandQueue, EXTERNAL_CONTROL);
sendHealthCommand(childrenMap.at(objectId).commandQueue, EXTERNAL_CONTROL);
} else {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << std::hex << SystemObject::getObjectId() << ": invalid mode table entry"
<< std::endl;
#endif
}
} }
void AssemblyBase::triggerModeHelperEvents(Mode_t mode, Submode_t submode) { void AssemblyBase::triggerModeHelperEvents(Mode_t mode, Submode_t submode) {
@ -287,7 +274,3 @@ void AssemblyBase::triggerModeHelperEvents(Mode_t mode, Submode_t submode) {
triggerEvent(CHANGING_MODE, mode, submode); triggerEvent(CHANGING_MODE, mode, submode);
} }
} }
void AssemblyBase::setRecoveryWaitTimer(uint32_t timeoutMS) {
recoveryOffTimer.setTimeout(timeoutMS);
}

View File

@ -206,8 +206,6 @@ class AssemblyBase : public SubsystemBase {
void overwriteDeviceHealth(object_id_t objectId, HasHealthIF::HealthState oldHealth); void overwriteDeviceHealth(object_id_t objectId, HasHealthIF::HealthState oldHealth);
void triggerModeHelperEvents(Mode_t mode, Submode_t submode); void triggerModeHelperEvents(Mode_t mode, Submode_t submode);
void setRecoveryWaitTimer(uint32_t timeoutMS);
}; };
#endif /* FSFW_DEVICEHANDLERS_ASSEMBLYBASE_H_ */ #endif /* FSFW_DEVICEHANDLERS_ASSEMBLYBASE_H_ */

View File

@ -145,20 +145,20 @@ void FreshDeviceHandlerBase::setToExternalControl() { setHealth(HealthState::EXT
// System Object overrides. // System Object overrides.
ReturnValue_t FreshDeviceHandlerBase::initialize() { ReturnValue_t FreshDeviceHandlerBase::initialize() {
ReturnValue_t result = modeHelper.initialize(); // ModeHelper.initialize() is an empty function, always returns OK ReturnValue_t result = modeHelper.initialize();
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;
} }
result = healthHelper.initialize(); result = healthHelper.initialize();
if (result != returnvalue::OK) { // check if all objects were successfully registered with HEALTHY flag stored in table (otherwise default HEALTHY = HEALTHY) if (result != returnvalue::OK) {
return result; return result;
} }
result = actionHelper.initialize(messageQueue); result = actionHelper.initialize(messageQueue);
if (result != returnvalue::OK) { // check if actionHelper got messageQueue assigned to use for its work successfully if (result != returnvalue::OK) {
return result; return result;
} }
result = paramHelper.initialize(); result = paramHelper.initialize();
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;
} }
@ -190,4 +190,6 @@ ReturnValue_t FreshDeviceHandlerBase::getParameter(uint8_t domainId, uint8_t uni
return INVALID_DOMAIN_ID; return INVALID_DOMAIN_ID;
} }
datapool::SharedPool* FreshDeviceHandlerBase::getOptionalSharedPool() { return nullptr; } datapool::SharedPool* FreshDeviceHandlerBase::getOptionalSharedPool() { return nullptr; }
ModeHelper& FreshDeviceHandlerBase::getModeHelper() { return this->modeHelper; }

View File

@ -97,6 +97,11 @@ class FreshDeviceHandlerBase : public SystemObject,
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF& parent) override; ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF& parent) override;
ModeTreeChildIF& getModeTreeChildIF() override; ModeTreeChildIF& getModeTreeChildIF() override;
/**
* @brief Return an interface to the ModeHelper.
*/
ModeHelper& getModeHelper();
protected: protected:
ActionHelper actionHelper; ActionHelper actionHelper;
ModeHelper modeHelper; ModeHelper modeHelper;

View File

@ -27,19 +27,13 @@ class HasHealthIF {
static const Event CHILD_PROBLEMS = MAKE_EVENT(8, severity::LOW); static const Event CHILD_PROBLEMS = MAKE_EVENT(8, severity::LOW);
//! Assembly overwrites health information of children to keep satellite alive. //! Assembly overwrites health information of children to keep satellite alive.
static const Event OVERWRITING_HEALTH = MAKE_EVENT(9, severity::LOW); static const Event OVERWRITING_HEALTH = MAKE_EVENT(9, severity::LOW);
//! Someone starts a recovery of a component (typically power-cycle). //! Someone starts a recovery of a component (typically power-cycle). No parameters.
//! P1: Object Id of the recovering device.
static const Event TRYING_RECOVERY = MAKE_EVENT(10, severity::MEDIUM); static const Event TRYING_RECOVERY = MAKE_EVENT(10, severity::MEDIUM);
//! Recovery is ongoing. Comes twice during recovery.
//! P1: 0 for the first, 1 for the second event. P2: 0
static const Event RECOVERY_STEP = MAKE_EVENT(11, severity::MEDIUM);
//! Recovery was completed. Not necessarily successful. No parameters. //! Recovery was completed. Not necessarily successful. No parameters.
//! P1: Object Id of the recovering device.
static const Event RECOVERY_DONE = MAKE_EVENT(12, severity::MEDIUM); static const Event RECOVERY_DONE = MAKE_EVENT(12, severity::MEDIUM);
//! Recovery is ongoing. The recovering device is currently OFF, waiting for restart.
//! P1: Object Id of the recovering device.
static const Event RECOVERY_WAITING = MAKE_EVENT(13, severity::MEDIUM);
//! Recovery is ongoing. Restarting the recovering device.
//! P1: Object Id of the recovering device.
static const Event RECOVERY_RESTARTING = MAKE_EVENT(14, severity::MEDIUM);
virtual ~HasHealthIF() {} virtual ~HasHealthIF() {}
virtual MessageQueueId_t getCommandQueue() const = 0; virtual MessageQueueId_t getCommandQueue() const = 0;

View File

@ -9,6 +9,7 @@
#include "fsfw/housekeeping/HousekeepingSnapshot.h" #include "fsfw/housekeeping/HousekeepingSnapshot.h"
#include "fsfw/ipc/QueueFactory.h" #include "fsfw/ipc/QueueFactory.h"
#include "fsfw/objectmanager/ObjectManager.h" #include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/timemanager/CCSDSTime.h"
using namespace hk; using namespace hk;
@ -83,7 +84,6 @@ ReturnValue_t PeriodicHelper::performHkOperation() {
ReturnValue_t PeriodicHelper::handleHousekeepingMessage(CommandMessage* message) { ReturnValue_t PeriodicHelper::handleHousekeepingMessage(CommandMessage* message) {
Command_t command = message->getCommand(); Command_t command = message->getCommand();
MessageQueueId_t sender = message->getSender();
dp::sid_t sid = HousekeepingMessage::getStructureId(message); dp::sid_t sid = HousekeepingMessage::getStructureId(message);
ReturnValue_t result = returnvalue::OK; ReturnValue_t result = returnvalue::OK;
switch (command) { switch (command) {
@ -113,7 +113,7 @@ ReturnValue_t PeriodicHelper::handleHousekeepingMessage(CommandMessage* message)
} }
case (HousekeepingMessage::GENERATE_ONE_PARAMETER_REPORT): { case (HousekeepingMessage::GENERATE_ONE_PARAMETER_REPORT): {
return generateHousekeepingPacket(HousekeepingMessage::getStructureId(message), sender); return generateHousekeepingPacket(HousekeepingMessage::getStructureId(message));
} }
default: default:

View File

@ -35,8 +35,12 @@ ReturnValue_t ModeHelper::handleModeCommand(CommandMessage* command) {
commandedMode = mode; commandedMode = mode;
commandedSubmode = submode; commandedSubmode = submode;
if ((parentQueueId != MessageQueueIF::NO_QUEUE) && // if (((parentQueueId != MessageQueueIF::NO_QUEUE) &&
(theOneWhoCommandedAMode != parentQueueId)) { // (theOneWhoCommandedAMode != parentQueueId))) {
// owner->setToExternalControl();
// }
if(theOneWhoCommandedAMode != parentQueueId and theOneWhoCommandedAMode != powerswitchQueueId) {
owner->setToExternalControl(); owner->setToExternalControl();
} }
@ -106,3 +110,7 @@ bool ModeHelper::isTimedOut() { return countdown.hasTimedOut(); }
bool ModeHelper::isForced() { return forced; } bool ModeHelper::isForced() { return forced; }
void ModeHelper::setForced(bool forced) { this->forced = forced; } void ModeHelper::setForced(bool forced) { this->forced = forced; }
void ModeHelper::setPowerSwitchQueueId(MessageQueueId_t queueId) {
powerswitchQueueId = queueId;
}

View File

@ -21,10 +21,15 @@ class ModeHelper {
/** /**
* @param parentQueue the Queue id of the parent object. * @param parentQueue the Queue id of the parent object.
* Set to 0 if no parent present * Set to MessageQueueIF::NO_QUEUE if no parent present
*/ */
void setParentQueue(MessageQueueId_t parentQueueId); void setParentQueue(MessageQueueId_t parentQueueId);
/**
* Set to MessageQueue::NO_QUEUE if no powerswitch is commanding the obejct.
*/
void setPowerSwitchQueueId(MessageQueueId_t queueId);
ReturnValue_t initialize(MessageQueueId_t parentQueueId); ReturnValue_t initialize(MessageQueueId_t parentQueueId);
ReturnValue_t initialize(void); ReturnValue_t initialize(void);
@ -42,6 +47,7 @@ class ModeHelper {
protected: protected:
HasModesIF *owner; HasModesIF *owner;
MessageQueueId_t parentQueueId = MessageQueueIF::NO_QUEUE; MessageQueueId_t parentQueueId = MessageQueueIF::NO_QUEUE;
MessageQueueId_t powerswitchQueueId = MessageQueueIF::NO_QUEUE;
Countdown countdown; Countdown countdown;

View File

@ -29,7 +29,7 @@ enum framework_objects : object_id_t {
// MODE_STORE = 0x53010100, // MODE_STORE = 0x53010100,
EVENT_MANAGER = 0x53030000, EVENT_MANAGER = 0x53030000,
INTERNAL_ERROR_REPORTER = 0x53040000, INTERNAL_ERROR_REPORTER = 0x53040000,
IPC_STORE = 0x534f0300, // Inter-process communication IPC_STORE = 0x534f0300,
// IDs for PUS Packet Communication // IDs for PUS Packet Communication
TC_STORE = 0x534f0100, TC_STORE = 0x534f0100,
TM_STORE = 0x534f0200, TM_STORE = 0x534f0200,

View File

@ -117,7 +117,7 @@ ReturnValue_t ParameterHelper::sendParameter(MessageQueueId_t to, uint32_t id,
ReturnValue_t ParameterHelper::initialize() { ReturnValue_t ParameterHelper::initialize() {
ownerQueueId = owner->getCommandQueue(); ownerQueueId = owner->getCommandQueue();
storage = ObjectManager::instance()->get<StorageManagerIF>(objects::IPC_STORE); // get storage pointer for inter-process communication storage = ObjectManager::instance()->get<StorageManagerIF>(objects::IPC_STORE);
if (storage == nullptr) { if (storage == nullptr) {
return ObjectManagerIF::CHILD_INIT_FAILED; return ObjectManagerIF::CHILD_INIT_FAILED;
} }

View File

@ -64,6 +64,11 @@ void SubsystemBase::executeTable(HybridIterator<ModeListEntry> tableIter, Submod
for (; tableIter.value != nullptr; ++tableIter) { for (; tableIter.value != nullptr; ++tableIter) {
object_id_t object = tableIter.value->getObject(); object_id_t object = tableIter.value->getObject();
// As default, the objectId in the commandTable is the same as the one in the childrenMap.
// The user has to specify otherwise if required.
object = commandObjectIdToChildrenMapObjectId(object);
if ((iter = childrenMap.find(object)) == childrenMap.end()) { if ((iter = childrenMap.find(object)) == childrenMap.end()) {
// illegal table entry, should only happen due to misconfigured mode table // illegal table entry, should only happen due to misconfigured mode table
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
@ -78,9 +83,9 @@ void SubsystemBase::executeTable(HybridIterator<ModeListEntry> tableIter, Submod
submodeToCommand = targetSubmode; submodeToCommand = targetSubmode;
} }
if (healthHelper.healthTable->hasHealth(convertToDeviceObjectId(object))) { if (healthHelper.healthTable->hasHealth(object)) {
switch (healthHelper.healthTable->getHealth(convertToDeviceObjectId(object))) { switch (healthHelper.healthTable->getHealth(object)) {
case NEEDS_RECOVERY: case NEEDS_RECOVERY:
case FAULTY: case FAULTY:
case PERMANENT_FAULTY: case PERMANENT_FAULTY:
@ -119,7 +124,11 @@ void SubsystemBase::executeTable(HybridIterator<ModeListEntry> tableIter, Submod
continue; // don't send redundant mode commands (produces event spam), but still command if continue; // don't send redundant mode commands (produces event spam), but still command if
// mode is forced to reach lower levels // mode is forced to reach lower levels
} }
ReturnValue_t result = commandQueue->sendMessage(iter->second.commandQueue, &command);
// Get the messageQueueId if the receiver specified by the commandTable.
// This the same MessageQueueId as stored in the childrenMap if the commanded object is part of the childrenMap.
MessageQueueId_t commandedReceiver = ObjectManager::instance()->get<HasHealthIF>(tableIter->getObject())->getCommandQueue();
ReturnValue_t result = commandQueue->sendMessage(commandedReceiver, &command);
if (result == returnvalue::OK) { if (result == returnvalue::OK) {
++commandsOutstanding; ++commandsOutstanding;
} }
@ -354,6 +363,6 @@ ReturnValue_t SubsystemBase::registerChild(object_id_t childObjectId, MessageQue
return returnvalue::OK; return returnvalue::OK;
} }
object_id_t SubsystemBase::convertToDeviceObjectId(object_id_t id) { object_id_t SubsystemBase::commandObjectIdToChildrenMapObjectId(object_id_t commandId) {
return id; return commandId;
} }

View File

@ -155,10 +155,13 @@ class SubsystemBase : public SystemObject,
virtual void modeChanged(); virtual void modeChanged();
/** /**
* @brief Provides an adaptation point for the user to change an objectId into * @brief This converts the objectId of the object we want to send a mode command to into the
* a different objectId. * objectId of the corresponding object in the childrenMap for the current mode command.
*/ * As default implementation, this is the same objectId, and this functions returns it's input value
virtual object_id_t convertToDeviceObjectId(object_id_t id); *
* It is up to the user to specify otherwise.
*/
virtual object_id_t commandObjectIdToChildrenMapObjectId(object_id_t commandId);
}; };
#endif /* FSFW_SUBSYSTEM_SUBSYSTEMBASE_H_ */ #endif /* FSFW_SUBSYSTEM_SUBSYSTEMBASE_H_ */

View File

@ -114,11 +114,6 @@ void TmStoreMessage::setDownlinkContentTimeMessage(CommandMessage* cmd, store_ad
cmd->setParameter2(storeId.raw); cmd->setParameter2(storeId.raw);
} }
void TmStoreMessage::setStopDownlinkContentMessage(CommandMessage* cmd, store_address_t storeId) {
cmd->setCommand(STOP_DOWNLINK_STORE_CONTENT);
cmd->setParameter2(storeId.raw);
}
uint32_t TmStoreMessage::getAddressLow(CommandMessage* cmd) { return cmd->getParameter(); } uint32_t TmStoreMessage::getAddressLow(CommandMessage* cmd) { return cmd->getParameter(); }
uint32_t TmStoreMessage::getAddressHigh(CommandMessage* cmd) { return cmd->getParameter2(); } uint32_t TmStoreMessage::getAddressHigh(CommandMessage* cmd) { return cmd->getParameter2(); }

View File

@ -21,7 +21,6 @@ class TmStoreMessage {
static void setStoreCatalogueReportMessage(CommandMessage* cmd, object_id_t objectId, static void setStoreCatalogueReportMessage(CommandMessage* cmd, object_id_t objectId,
store_address_t storeId); store_address_t storeId);
static void setDownlinkContentTimeMessage(CommandMessage* cmd, store_address_t storeId); static void setDownlinkContentTimeMessage(CommandMessage* cmd, store_address_t storeId);
static void setStopDownlinkContentMessage(CommandMessage* cmd, store_address_t storeId);
static void setIndexReportMessage(CommandMessage* cmd, store_address_t storeId); static void setIndexReportMessage(CommandMessage* cmd, store_address_t storeId);
static ReturnValue_t setDeleteBlocksMessage(CommandMessage* cmd, uint32_t addressLow, static ReturnValue_t setDeleteBlocksMessage(CommandMessage* cmd, uint32_t addressLow,
uint32_t addressHigh); uint32_t addressHigh);
@ -55,7 +54,6 @@ class TmStoreMessage {
static const Command_t DOWNLINK_STORE_CONTENT_BLOCKS = MAKE_COMMAND_ID(12); static const Command_t DOWNLINK_STORE_CONTENT_BLOCKS = MAKE_COMMAND_ID(12);
static const Command_t REPORT_INDEX_REQUEST = MAKE_COMMAND_ID(13); static const Command_t REPORT_INDEX_REQUEST = MAKE_COMMAND_ID(13);
static const Command_t INDEX_REPORT = MAKE_COMMAND_ID(14); static const Command_t INDEX_REPORT = MAKE_COMMAND_ID(14);
static const Command_t STOP_DOWNLINK_STORE_CONTENT = MAKE_COMMAND_ID(15);
private: private:
TmStoreMessage(); TmStoreMessage();