Compare commits

..

1 Commits

Author SHA1 Message Date
e73b9ff72c Merge pull request 'v6.0.0' (#729) from development into master
Some checks failed
fsfw/fsfw/pipeline/head There was a failure building this commit
Reviewed-on: #729
2023-02-23 13:42:48 +01:00
186 changed files with 1658 additions and 3240 deletions

3
.gitignore vendored
View File

@ -10,8 +10,5 @@
.settings
.metadata
# VSCode
.vscode
/build*
/cmake-build*

View File

@ -8,42 +8,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
# [unreleased]
## Fixes
- Important bugfix in CFDP PDU header format: The entity length field and the transaction sequence
number fields stored the actual length of the field instead of the length minus 1 like specified
in the CFDP standard.
- PUS Health Service: Size check for set health command.
Perform operation completion for announce health command.
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/746
- Linux OSAL `getUptime` fix: Check validity of `/proc/uptime` file before reading uptime.
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/745
- Small tweak for version getter
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/744
## Added
- add CFDP subsystem ID
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/742
## Changed
- Bump ETL version to 20.35.14
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/748
- Renamed `PCDU_2` subsystem ID to `POWER_SWITCH_IF`.
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/743
- Add new `PowerSwitchIF::SWITCH_UNKNOWN` returnvalue.
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/743
- Assert that `FixedArrayList` is larger than 0 at compile time.
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/740
## Added
- `EventManager`: Add function to print all listeners.
## Changed
- `EventManager`: Queue depth is configurable now
# [v6.0.0] 2023-02-10
## Fixes

View File

@ -72,7 +72,7 @@ set(FSFW_ETL_LIB_MAJOR_VERSION
20
CACHE STRING "ETL library major version requirement")
set(FSFW_ETL_LIB_VERSION
${FSFW_ETL_LIB_MAJOR_VERSION}.36.0
${FSFW_ETL_LIB_MAJOR_VERSION}.28.0
CACHE STRING "ETL library exact version requirement")
set(FSFW_ETL_LINK_TARGET etl::etl)
@ -80,7 +80,7 @@ set(FSFW_CATCH2_LIB_MAJOR_VERSION
3
CACHE STRING "Catch2 library major version requirement")
set(FSFW_CATCH2_LIB_VERSION
v${FSFW_CATCH2_LIB_MAJOR_VERSION}.3.2
v${FSFW_CATCH2_LIB_MAJOR_VERSION}.1.0
CACHE STRING "Catch2 library exact version requirement")
# Keep this off by default for now. See PR:

View File

@ -97,7 +97,7 @@ pipeline {
sh 'rsync -r --delete docs/sphinx/* buildfix@documentation.irs.uni-stuttgart.de:/fsfw/development'
}
}
dir(BUILDDIR_LINUX) {
dir(BUILDDIR) {
sshagent(credentials: ['documentation-buildfix']) {
sh 'rsync -r --delete fsfw-tests_coverage/* buildfix@documentation.irs.uni-stuttgart.de:/fsfw/coverage/development'
}
@ -116,7 +116,7 @@ pipeline {
sh 'rsync -r --delete docs/sphinx/* buildfix@documentation.irs.uni-stuttgart.de:/fsfw/master'
}
}
dir(BUILDDIR_LINUX) {
dir(BUILDDIR) {
sshagent(credentials: ['documentation-buildfix']) {
sh 'rsync -r --delete fsfw-tests_coverage/* buildfix@documentation.irs.uni-stuttgart.de:/fsfw/coverage/master'
}

View File

@ -8,4 +8,4 @@ if(FSFW_ADD_HAL)
add_subdirectory(fsfw_hal)
endif()
#add_subdirectory(fsfw_tests)
add_subdirectory(fsfw_tests)

View File

@ -7,7 +7,7 @@ add_subdirectory(cfdp)
add_subdirectory(container)
add_subdirectory(controller)
add_subdirectory(datapool)
#add_subdirectory(datapoollocal)
add_subdirectory(datapoollocal)
add_subdirectory(devicehandlers)
add_subdirectory(events)
add_subdirectory(fdir)
@ -15,22 +15,20 @@ add_subdirectory(globalfunctions)
add_subdirectory(health)
add_subdirectory(housekeeping)
add_subdirectory(internalerror)
add_subdirectory(introspection)
add_subdirectory(ipc)
add_subdirectory(memory)
add_subdirectory(modes)
add_subdirectory(objectmanager)
add_subdirectory(parameters)
#add_subdirectory(power)
add_subdirectory(power)
add_subdirectory(serialize)
add_subdirectory(serviceinterface)
add_subdirectory(storagemanager)
add_subdirectory(subsystem)
add_subdirectory(tasks)
add_subdirectory(tcdistribution)
#add_subdirectory(thermal)
add_subdirectory(thermal)
add_subdirectory(timemanager)
add_subdirectory(tmtc)
add_subdirectory(tmtcpacket)
add_subdirectory(tmtcservices)
add_subdirectory(filesystem)
@ -38,7 +36,7 @@ add_subdirectory(filesystem)
# Optional
if(FSFW_ADD_MONITORING)
#add_subdirectory(monitoring)
add_subdirectory(monitoring)
endif()
if(FSFW_ADD_PUS)
add_subdirectory(pus)

View File

@ -1,7 +1,6 @@
#ifndef FSFW_INC_FSFW_ACTION_H_
#define FSFW_INC_FSFW_ACTION_H_
#include "fsfw/action/Action.h"
#include "fsfw/action/ActionHelper.h"
#include "fsfw/action/ActionMessage.h"
#include "fsfw/action/CommandActionHelper.h"

View File

@ -1,70 +0,0 @@
#include "Action.h"
#include <fsfw/serialize/SerializeAdapter.h>
#include <fsfw/ipc/MessageQueueIF.h>
#undef Action
#ifdef FSFW_INTROSPECTION
Action::Action() {}
void Action::setEnum(EnumIF *theEnum) {
id = theEnum->getValue();
name = theEnum->getDescription();
}
const char *Action::getName() { return name; }
#else
Action::Action(ActionId_t id) : id(id) {}
#endif
ActionId_t Action::getId() { return id; }
void Action::clear() {
tc = store_address_t();
tcOffset = 0;
commandedBy = MessageQueueIF::NO_QUEUE;
}
void Action::registerParameter(ParameterIF *parameter) { parameterList.push_back(parameter); }
std::vector<ParameterIF *> const *Action::getParameters() const { return &parameterList; }
size_t Action::getSerializedSize() const {
size_t size = SerializeAdapter::getSerializedSize(&id);
for (auto parameter : *getParameters()) {
size += parameter->getSerializedSize();
}
return size;
}
ReturnValue_t Action::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
Endianness streamEndianness) const {
ReturnValue_t result = SerializeAdapter::serialize(&id, buffer, size, maxSize, streamEndianness);
if (result != returnvalue::OK) {
return result;
}
for (auto parameter : *getParameters()) {
result = parameter->serialize(buffer, size, maxSize, streamEndianness);
if (result != returnvalue::OK) {
return result;
}
}
return result;
}
ReturnValue_t Action::deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) {
ReturnValue_t result = returnvalue::OK;/* TODO not needed as must have been read before to find this
action = SerializeAdapter::deSerialize(&id, buffer, size, streamEndianness);
if (result != returnvalue::OK) {
return result;
}*/
for (auto parameter : *getParameters()) {
result = parameter->deSerialize(buffer, size, streamEndianness);
if (result != returnvalue::OK) {
return result;
}
}
return result;
}

View File

@ -1,64 +0,0 @@
#pragma once
#include <fsfw/introspection/HasTmTcParametersIF.h>
#include <fsfw/serialize/SerializeIF.h>
#include <stdint.h>
#include <vector>
#include "ActionMessage.h"
#ifdef FSFW_INTROSPECTION
#include "../introspection/Enum.h"
#endif
// TODO ActionId_t
class Action : public SerializeIF, public HasTmTcParametersIF {
public:
#ifdef FSFW_INTROSPECTION
Action();
void setEnum(EnumIF *id);
const char *getName();
#else
Action(ActionId_t id);
#endif
store_address_t getTc();
size_t getTcOffset();
// if an action is triggered by a TC, this should be set to be able to handle replies
// TODO make deleting it safe
// TODO integrate with internal commands
store_address_t tc;
size_t tcOffset;
MessageQueueId_t commandedBy;
ActionId_t getId();
void clear();
[[nodiscard]] virtual ReturnValue_t handle() = 0;
void registerParameter(ParameterIF *parameter) override;
std::vector<ParameterIF *> const *getParameters() const override;
ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
Endianness streamEndianness) const override;
size_t getSerializedSize() const override;
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) override;
private:
ActionId_t id;
#ifdef FSFW_INTROSPECTION
const char *name;
#endif
std::vector<ParameterIF *> parameterList;
};

View File

@ -1,6 +1,3 @@
#include <fsfw/serialize/SerializeAdapter.h>
#include <fsfw/tmtc/TmMessage.h>
#include "fsfw/action.h"
#include "fsfw/ipc/MessageQueueSenderIF.h"
#include "fsfw/objectmanager/ObjectManager.h"
@ -13,8 +10,8 @@ ActionHelper::~ActionHelper() = default;
ReturnValue_t ActionHelper::handleActionMessage(CommandMessage* command) {
if (command->getCommand() == ActionMessage::EXECUTE_ACTION) {
prepareExecution(command->getSender(), ActionMessage::getOffset(command),
ActionMessage::getStoreId(command));
ActionId_t currentAction = ActionMessage::getActionId(command);
prepareExecution(command->getSender(), currentAction, ActionMessage::getStoreId(command));
return returnvalue::OK;
} else {
return CommandMessage::UNKNOWN_COMMAND;
@ -26,12 +23,6 @@ ReturnValue_t ActionHelper::initialize(MessageQueueIF* queueToUse_) {
if (ipcStore == nullptr) {
return returnvalue::FAILED;
}
tmManager = ObjectManager::instance()->get<TmManager>(objects::TM_MANAGER);
if (tmManager == nullptr) {
return returnvalue::FAILED;
}
if (queueToUse_ != nullptr) {
setQueueToUse(queueToUse_);
}
@ -66,89 +57,28 @@ void ActionHelper::finish(bool success, MessageQueueId_t reportTo, ActionId_t co
void ActionHelper::setQueueToUse(MessageQueueIF* queue) { queueToUse = queue; }
MessageQueueIF const* ActionHelper::getQueue() const { return queueToUse; }
void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, size_t offset,
void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId,
store_address_t dataAddress) {
const uint8_t* tcData = nullptr;
size_t tcDataSize = 0;
ReturnValue_t result = ipcStore->getData(dataAddress, &tcData, &tcDataSize);
const uint8_t* dataPtr = nullptr;
size_t size = 0;
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
if (result != returnvalue::OK) {
CommandMessage reply;
ActionMessage::setStepReply(&reply, 0 /*TODO*/, 0, result);
// queueToUse->sendMessage(commandedBy, &reply);
ipcStore->deleteData(dataAddress);
ActionMessage::setStepReply(&reply, actionId, 0, result);
queueToUse->sendMessage(commandedBy, &reply);
return;
}
FsfwProtocolHeader header;
const uint8_t* dataPtr = tcData + offset;
size_t size = tcDataSize - offset;
result = header.deSerialize(&dataPtr, &size, SerializeIF::Endianness::NETWORK);
if (header.getInterface() != HasActionsIF::INTERFACE_ID or
header.getFunction() != HasActionsIF::Functions::EXECUTE_ACTION) {
CommandMessage reply;
ActionMessage::setStepReply(&reply, 0 /*TODO*/, 0, result);
// queueToUse->sendMessage(commandedBy, &reply);
ipcStore->deleteData(dataAddress);
return;
}
ActionId_t actionId;
result =
SerializeAdapter::deSerialize(&actionId, &dataPtr, &size, SerializeIF::Endianness::NETWORK);
if (result != returnvalue::OK) {
CommandMessage reply;
ActionMessage::setStepReply(&reply, 0 /*TODO*/, 0, result);
// queueToUse->sendMessage(commandedBy, &reply);
ipcStore->deleteData(dataAddress);
return;
}
auto actionIter = actionMap.find(actionId);
if (actionIter == actionMap.end()) {
CommandMessage reply;
ActionMessage::setStepReply(&reply, actionId, 0, HasActionsIF::INVALID_ACTION_ID);
// queueToUse->sendMessage(commandedBy, &reply);
ipcStore->deleteData(dataAddress);
return;
}
Action* action = actionIter->second;
result = action->deSerialize(&dataPtr, &size, SerializeIF::Endianness::NETWORK);
if ((result != returnvalue::OK) || (size != 0)) { // TODO write unittest for second condition
CommandMessage reply;
ActionMessage::setStepReply(&reply, actionId, 0, HasActionsIF::INVALID_PARAMETERS);
// queueToUse->sendMessage(commandedBy, &reply);
ipcStore->deleteData(dataAddress);
return;
}
// TODO call action->check()
action->commandedBy = commandedBy;
result = owner->executeAction(action);
// TODO safetify dynamic cast
result = tmManager->sendTmPacket(dynamic_cast<SystemObjectIF*>(owner)->getObjectId(), HasActionsIF::INTERFACE_ID,
HasActionsIF::Functions::EXECUTION_IN_PROGRESS, action,
dataAddress, offset);
if (result != returnvalue::OK) {
sif::error << "replying action failed " << std::hex << result << std::dec << std::endl;
}
// ipcStore->deleteData(dataAddress);
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
ipcStore->deleteData(dataAddress);
if (result == HasActionsIF::EXECUTION_FINISHED) {
CommandMessage reply;
ActionMessage::setCompletionReply(&reply, actionId, true, result);
// queueToUse->sendMessage(commandedBy, &reply);
queueToUse->sendMessage(commandedBy, &reply);
}
if (result != returnvalue::OK) {
CommandMessage reply;
ActionMessage::setStepReply(&reply, actionId, 0, result);
// queueToUse->sendMessage(commandedBy, &reply);
queueToUse->sendMessage(commandedBy, &reply);
return;
}
}
@ -233,11 +163,3 @@ ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo, ActionId_t rep
}
return result;
}
void ActionHelper::registerAction(Action* action) {
// TODO error handling
ActionId_t id = action->getId();
actionMap.emplace(id, action);
}
std::map<ActionId_t, Action*> const* ActionHelper::getActionMap() { return &actionMap; }

View File

@ -1,12 +1,9 @@
#ifndef FSFW_ACTION_ACTIONHELPER_H_
#define FSFW_ACTION_ACTIONHELPER_H_
#include <fsfw/tmtc/TmManager.h>
#include "ActionMessage.h"
#include "fsfw/ipc/MessageQueueIF.h"
#include "fsfw/serialize/SerializeIF.h"
/**
* @brief Action Helper is a helper class which handles action messages
*
@ -101,16 +98,6 @@ class ActionHelper {
*/
void setQueueToUse(MessageQueueIF* queue);
/**
* Needed so templateAction can check if actionHelper was
* contructed already to aid in debuggig a nasty coding error.
*/
MessageQueueIF const* getQueue() const;
void registerAction(Action* action);
std::map<ActionId_t, Action*> const* getActionMap();
protected:
//! Increase of value of this per step
static const uint8_t STEP_OFFSET = 1;
@ -119,11 +106,8 @@ class ActionHelper {
//! Queue to be used as response sender, has to be set in ctor or with
//! setQueueToUse
MessageQueueIF* queueToUse;
TmManager* tmManager = nullptr;
//! Pointer to an IPC Store, initialized during construction or
StorageManagerIF* ipcStore = nullptr;
//! Map of all implemented Actions
std::map<ActionId_t, Action*> actionMap;
/**
* Internal function called by handleActionMessage
@ -131,7 +115,7 @@ class ActionHelper {
* @param actionId ID of action to be done
* @param dataAddress Address of additional data in IPC Store
*/
virtual void prepareExecution(MessageQueueId_t commandedBy, size_t offset,
virtual void prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId,
store_address_t dataAddress);
/**
* @brief Default implementation is empty.

View File

@ -6,14 +6,14 @@ ActionMessage::ActionMessage() = default;
ActionMessage::~ActionMessage() = default;
void ActionMessage::setCommand(CommandMessage* message, size_t offset,
void ActionMessage::setCommand(CommandMessage* message, ActionId_t fid,
store_address_t parameters) {
message->setCommand(EXECUTE_ACTION);
message->setParameter(offset);
message->setParameter(fid);
message->setParameter2(parameters.raw);
}
size_t ActionMessage::getOffset(const CommandMessage* message) {
ActionId_t ActionMessage::getActionId(const CommandMessage* message) {
return ActionId_t(message->getParameter());
}

View File

@ -27,9 +27,9 @@ class ActionMessage {
static const Command_t COMPLETION_FAILED = MAKE_COMMAND_ID(6);
virtual ~ActionMessage();
static void setCommand(CommandMessage* message, size_t offset, store_address_t parameters);
static void setCommand(CommandMessage* message, ActionId_t fid, store_address_t parameters);
static size_t getOffset(const CommandMessage* message);
static ActionId_t getActionId(const CommandMessage* message);
static store_address_t getStoreId(const CommandMessage* message);
static void setStepReply(CommandMessage* message, ActionId_t fid, uint8_t step,

View File

@ -1,3 +1,3 @@
target_sources(
${LIB_FSFW_NAME} PRIVATE Action.cpp ActionHelper.cpp ActionMessage.cpp
${LIB_FSFW_NAME} PRIVATE ActionHelper.cpp ActionMessage.cpp
CommandActionHelper.cpp SimpleActionHelper.cpp)

View File

@ -74,24 +74,24 @@ ReturnValue_t CommandActionHelper::handleReply(CommandMessage *reply) {
switch (reply->getCommand()) {
case ActionMessage::COMPLETION_SUCCESS:
commandCount--;
// owner->completionSuccessfulReceived(ActionMessage::getActionId(reply)); TODO
owner->completionSuccessfulReceived(ActionMessage::getActionId(reply));
return returnvalue::OK;
case ActionMessage::COMPLETION_FAILED:
commandCount--;
// owner->completionFailedReceived(ActionMessage::getActionId(reply),
// ActionMessage::getReturnCode(reply));
owner->completionFailedReceived(ActionMessage::getActionId(reply),
ActionMessage::getReturnCode(reply));
return returnvalue::OK;
case ActionMessage::STEP_SUCCESS:
// owner->stepSuccessfulReceived(ActionMessage::getActionId(reply),
// ActionMessage::getStep(reply));
owner->stepSuccessfulReceived(ActionMessage::getActionId(reply),
ActionMessage::getStep(reply));
return returnvalue::OK;
case ActionMessage::STEP_FAILED:
commandCount--;
// owner->stepFailedReceived(ActionMessage::getActionId(reply), ActionMessage::getStep(reply),
// ActionMessage::getReturnCode(reply));
owner->stepFailedReceived(ActionMessage::getActionId(reply), ActionMessage::getStep(reply),
ActionMessage::getReturnCode(reply));
return returnvalue::OK;
case ActionMessage::DATA_REPLY:
// extractDataForOwner(ActionMessage::getActionId(reply), ActionMessage::getStoreId(reply));
extractDataForOwner(ActionMessage::getActionId(reply), ActionMessage::getStoreId(reply));
return returnvalue::OK;
default:
return returnvalue::FAILED;

View File

@ -1,13 +1,11 @@
#ifndef FSFW_ACTION_HASACTIONSIF_H_
#define FSFW_ACTION_HASACTIONSIF_H_
#include "Action.h"
#include "ActionHelper.h"
#include "ActionMessage.h"
#include "SimpleActionHelper.h"
#include "fsfw/ipc/MessageQueueIF.h"
#include "fsfw/returnvalues/returnvalue.h"
#include <fsfw/tmtc/FsfwProtocolHeader.h>
/**
* @brief
@ -42,18 +40,12 @@ class HasActionsIF {
static const ReturnValue_t INVALID_PARAMETERS = MAKE_RETURN_CODE(2);
static const ReturnValue_t EXECUTION_FINISHED = MAKE_RETURN_CODE(3);
static const ReturnValue_t INVALID_ACTION_ID = MAKE_RETURN_CODE(4);
enum Functions : FsfwProtocolHeader::FunctionType_t { EXECUTE_ACTION, EXECUTION_IN_PROGRESS };
virtual ~HasActionsIF() = default;
/**
* Function to get the MessageQueueId_t of the implementing object
* @return MessageQueueId_t of the object
*
*/
[[nodiscard]] virtual MessageQueueId_t getCommandQueue() const = 0;
virtual ActionHelper* getActionHelper() = 0;
/**
* Execute or initialize the execution of a certain function.
* The ActionHelpers will execute this function and behave differently
@ -63,7 +55,8 @@ class HasActionsIF {
* -@c EXECUTION_FINISHED Finish reply will be generated
* -@c Not returnvalue::OK Step failure reply will be generated
*/
virtual ReturnValue_t executeAction(Action* action) = 0;
virtual ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size) = 0;
};
#endif /* FSFW_ACTION_HASACTIONSIF_H_ */

View File

@ -1,6 +1,4 @@
#include "fsfw/action.h"
#include <fsfw/serialize/SerializeAdapter.h>
SimpleActionHelper::SimpleActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue)
: ActionHelper(setOwner, useThisQueue), isExecuting(false) {}
@ -32,57 +30,25 @@ void SimpleActionHelper::resetHelper() {
lastCommander = 0;
}
void SimpleActionHelper::prepareExecution(MessageQueueId_t commandedBy, size_t offset,
store_address_t dataAddress) {
void SimpleActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId,
store_address_t dataAddress) {
CommandMessage reply;
if (isExecuting) {
ipcStore->deleteData(dataAddress);
ActionMessage::setStepReply(&reply, 0 /*TODO*/, 0, HasActionsIF::IS_BUSY);
ActionMessage::setStepReply(&reply, actionId, 0, HasActionsIF::IS_BUSY);
queueToUse->sendMessage(commandedBy, &reply);
}
const uint8_t* dataPtr = nullptr;
size_t size = 0;
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
if (result != returnvalue::OK) {
ActionMessage::setStepReply(&reply, 0 /*TODO*/, 0, result);
queueToUse->sendMessage(commandedBy, &reply);
ipcStore->deleteData(dataAddress);
return;
}
dataPtr += offset;
size -=offset;
ActionId_t actionId;
result = SerializeAdapter::deSerialize(&actionId, &dataPtr, &size, SerializeIF::Endianness::NETWORK);
if (result != returnvalue::OK) {
CommandMessage reply;
ActionMessage::setStepReply(&reply, actionId, 0, result);
queueToUse->sendMessage(commandedBy, &reply);
ipcStore->deleteData(dataAddress);
return;
}
auto actionIter = actionMap.find(actionId);
if (actionIter == actionMap.end()){
CommandMessage reply;
ActionMessage::setStepReply(&reply, actionId, 0, HasActionsIF::INVALID_ACTION_ID);
queueToUse->sendMessage(commandedBy, &reply);
ipcStore->deleteData(dataAddress);
return;
}
Action* action = actionIter->second;
result = action->deSerialize(&dataPtr, &size, SerializeIF::Endianness::NETWORK);
if ((result != returnvalue::OK) or (size != 0)) {
CommandMessage reply;
ActionMessage::setStepReply(&reply, actionId, 0, HasActionsIF::INVALID_PARAMETERS);
queueToUse->sendMessage(commandedBy, &reply);
ipcStore->deleteData(dataAddress);
return;
}
result = action->handle();
lastCommander = commandedBy;
lastAction = actionId;
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
ipcStore->deleteData(dataAddress);
switch (result) {
case returnvalue::OK:

View File

@ -17,8 +17,8 @@ class SimpleActionHelper : public ActionHelper {
ReturnValue_t reportData(SerializeIF* data);
protected:
virtual void prepareExecution(MessageQueueId_t commandedBy, size_t offset,
store_address_t dataAddress) override;
void prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId,
store_address_t dataAddress) override;
void resetHelper() override;
private:

View File

@ -1,29 +0,0 @@
#pragma once
#include "Action.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
template <class owner_class, class action_type, class ActionEnum>
class TemplateAction : public Action {
public:
#ifdef FSFW_INTROSPECTION
TemplateAction(owner_class *myOwner, ActionEnum id) : Action(), myOwner(myOwner) {
Action::setEnum(&id);
if (myOwner->getActionHelper() == nullptr) {
sif::error
<< "TemplateAction::TemplateAction: Action instances need to be created (ie located) after the actionHelper instance."
<< "Program will segfault now..." << std::endl;
}
myOwner->getActionHelper()->registerAction(this);
}
#else
TemplateAction(owner_class *myOwner, ActionEnum id) : Action((uint32_t)id), myOwner(myOwner) {
myOwner->getActionHelper()->registerAction(this);
}
#endif
ReturnValue_t handle() override { return myOwner->handleAction(dynamic_cast<action_type *>(this)); }
private:
owner_class *myOwner;
};

View File

@ -51,9 +51,8 @@ class VarLenField : public SerializeIF {
return os;
}
#endif
private:
using SerializeIF::deSerialize; // we overloaded above, so this is needed to uncofuse the
// compiler
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) override;

View File

@ -24,8 +24,8 @@ ReturnValue_t HeaderCreator::serialize(uint8_t **buffer, size_t *size, size_t ma
*buffer += 1;
**buffer = pduDataFieldLen & 0x00ff;
*buffer += 1;
**buffer = segmentationCtrl << 7 | ((pduConf.sourceId.getWidth() - 1) << 4) |
segmentMetadataFlag << 3 | (pduConf.seqNum.getWidth() - 1);
**buffer = segmentationCtrl << 7 | pduConf.sourceId.getWidth() << 4 | segmentMetadataFlag << 3 |
pduConf.seqNum.getWidth();
*buffer += 1;
*size += 4;
ReturnValue_t result = pduConf.sourceId.serialize(buffer, size, maxSize, streamEndianness);

View File

@ -78,11 +78,11 @@ cfdp::SegmentationControl PduHeaderReader::getSegmentationControl() const {
}
cfdp::WidthInBytes PduHeaderReader::getLenEntityIds() const {
return static_cast<cfdp::WidthInBytes>(((pointers.fixedHeader->fourthByte >> 4) & 0b111) + 1);
return static_cast<cfdp::WidthInBytes>((pointers.fixedHeader->fourthByte >> 4) & 0x07);
}
cfdp::WidthInBytes PduHeaderReader::getLenSeqNum() const {
return static_cast<cfdp::WidthInBytes>((pointers.fixedHeader->fourthByte & 0b111) + 1);
return static_cast<cfdp::WidthInBytes>(pointers.fixedHeader->fourthByte & 0x07);
}
cfdp::SegmentMetadataFlag PduHeaderReader::getSegmentMetadataFlag() const {

View File

@ -23,8 +23,6 @@ class EntityIdTlv : public TlvIF {
*/
ReturnValue_t deSerialize(cfdp::Tlv& tlv, Endianness endianness);
using SerializeIF::deSerialize; // we overloaded this function, so this is needed to unconfuse
// the compiler
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) override;

View File

@ -26,8 +26,6 @@ class FilestoreRequestTlv : public cfdp::FilestoreTlvBase {
*/
ReturnValue_t deSerialize(cfdp::Tlv &tlv, Endianness endianness);
using SerializeIF::deSerialize; // we overloaded above, so this is needed to uncofuse the
// compiler
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) override;

View File

@ -29,8 +29,6 @@ class FilestoreResponseTlv : public cfdp::FilestoreTlvBase {
*/
ReturnValue_t deSerialize(const cfdp::Tlv& tlv, Endianness endianness);
using SerializeIF::deSerialize; // we overloaded this function, so this is needed to unconfuse
// the compiler
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) override;

View File

@ -12,7 +12,6 @@ template <typename T, size_t MAX_SIZE, typename count_t = uint8_t>
class FixedArrayList : public ArrayList<T, count_t> {
static_assert(MAX_SIZE <= std::numeric_limits<count_t>::max(),
"count_t is not large enough to hold MAX_SIZE");
static_assert(MAX_SIZE > 0, "MAX_SIZE is 0");
private:
T data[MAX_SIZE];

View File

@ -155,8 +155,8 @@ class FixedMap : public SerializeIF {
uint32_t maxSize() const { return theMap.maxSize(); }
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const override {
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const {
ReturnValue_t result =
SerializeAdapter::serialize(&this->_size, buffer, size, maxSize, streamEndianness);
uint32_t i = 0;
@ -170,7 +170,7 @@ class FixedMap : public SerializeIF {
return result;
}
size_t getSerializedSize() const override {
virtual size_t getSerializedSize() const {
uint32_t printSize = sizeof(_size);
uint32_t i = 0;
@ -182,8 +182,8 @@ class FixedMap : public SerializeIF {
return printSize;
}
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) override {
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) {
ReturnValue_t result =
SerializeAdapter::deSerialize(&this->_size, buffer, size, streamEndianness);
if (this->_size > theMap.maxSize()) {

View File

@ -1 +1,2 @@
target_sources(${LIB_FSFW_NAME} PRIVATE ControllerBase.cpp)
target_sources(${LIB_FSFW_NAME} PRIVATE ControllerBase.cpp
ExtendedControllerBase.cpp)

View File

@ -12,10 +12,7 @@ ControllerBase::ControllerBase(object_id_t setObjectId, object_id_t parentId,
mode(MODE_OFF),
submode(SUBMODE_NONE),
modeHelper(this),
healthHelper(this, setObjectId),
actionHelper(this, commandQueue),
datapoolHelper(this),
housekeepingHelper(this) {
healthHelper(this, setObjectId) {
commandQueue = QueueFactory::instance()->createMessageQueue(commandQueueDepth);
}
@ -48,21 +45,6 @@ ReturnValue_t ControllerBase::initialize() {
return result;
}
result = actionHelper.initialize(commandQueue);
if (result != returnvalue::OK) {
return result;
}
result = housekeepingHelper.initialize();
if (result != returnvalue::OK) {
return result;
}
result = datapoolHelper.initialize();
if (result != returnvalue::OK) {
return result;
}
return returnvalue::OK;
}
@ -82,12 +64,6 @@ void ControllerBase::handleQueue() {
if (result == returnvalue::OK) {
continue;
}
result = actionHelper.handleActionMessage(&command);
if (result == returnvalue::OK) {
continue;
}
result = handleCommandMessage(&command);
if (result == returnvalue::OK) {
continue;
@ -123,15 +99,6 @@ ReturnValue_t ControllerBase::performOperation(uint8_t opCode) {
return returnvalue::OK;
}
const ModeHelper* ControllerBase::getModeHelper() const { return &modeHelper; }
ActionHelper* ControllerBase::getActionHelper() { return &actionHelper; }
ReturnValue_t ControllerBase::executeAction(Action* action) { return action->handle(); }
DatapoolHelper* ControllerBase::getDatapoolHelper() { return &datapoolHelper; }
HousekeepingHelper* ControllerBase::getHousekeepingHelper() { return &housekeepingHelper; }
void ControllerBase::modeChanged(Mode_t mode_, Submode_t submode_) {}
ReturnValue_t ControllerBase::setHealth(HealthState health) {

View File

@ -1,15 +1,13 @@
#ifndef FSFW_CONTROLLER_CONTROLLERBASE_H_
#define FSFW_CONTROLLER_CONTROLLERBASE_H_
#include <fsfw/health/HasHealthIF.h>
#include <fsfw/health/HealthHelper.h>
#include <fsfw/introspection/ClasslessEnum.h>
#include <fsfw/modes/HasModesIF.h>
#include <fsfw/action/HasActionsIF.h>
#include <fsfw/datapool/HasDatapoolIF.h>
#include <fsfw/objectmanager/SystemObject.h>
#include <fsfw/tasks/ExecutableObjectIF.h>
#include <fsfw/tasks/PeriodicTaskIF.h>
#include "fsfw/health/HasHealthIF.h"
#include "fsfw/health/HealthHelper.h"
#include "fsfw/modes/HasModesIF.h"
#include "fsfw/modes/ModeHelper.h"
#include "fsfw/objectmanager/SystemObject.h"
#include "fsfw/tasks/ExecutableObjectIF.h"
#include "fsfw/tasks/PeriodicTaskIF.h"
/**
* @brief Generic base class for controller classes
@ -19,14 +17,10 @@
*/
class ControllerBase : public HasModesIF,
public HasHealthIF,
public HasDatapoolIF,
public HasActionsIF,
public ExecutableObjectIF,
public SystemObject {
public:
FSFW_CLASSLESS_ENUM(ControllerModes, Mode_t,
((CONTROLLER_MODE_ON, MODE_ON, "On"))((CONTROLLER_MODE_OFF, MODE_OFF,
"Off"))((MODE_NORMAL, 2, "Normal")))
static const Mode_t MODE_NORMAL = 2;
ControllerBase(object_id_t setObjectId, object_id_t parentId, size_t commandQueueDepth = 3);
~ControllerBase() override;
@ -45,17 +39,6 @@ class ControllerBase : public HasModesIF,
void setTaskIF(PeriodicTaskIF *task) override;
ReturnValue_t initializeAfterTaskCreation() override;
/** HasModeIF overrides */
const ModeHelper *getModeHelper() const override;
/** HasActionsIF override */
ActionHelper* getActionHelper() override;
ReturnValue_t executeAction(Action* action) override;
/** HasDatapoolIF overrides */
DatapoolHelper* getDatapoolHelper() override;
HousekeepingHelper* getHousekeepingHelper() override;
protected:
/**
* Implemented by child class. Handle command messages which are not
@ -85,12 +68,6 @@ class ControllerBase : public HasModesIF,
HealthHelper healthHelper;
ActionHelper actionHelper;
DatapoolHelper datapoolHelper;
HousekeepingHelper housekeepingHelper;
/**
* Pointer to the task which executes this component,
* is invalid before setTaskIF was called.

View File

@ -8,12 +8,11 @@ ExtendedControllerBase::ExtendedControllerBase(object_id_t objectId, object_id_t
ExtendedControllerBase::~ExtendedControllerBase() = default;
ActionHelper *ExtendedControllerBase::getActionHelper() {
return &actionHelper;
}
ReturnValue_t ExtendedControllerBase::executeAction(Action *action) {
return action->handle();
ReturnValue_t ExtendedControllerBase::executeAction(ActionId_t actionId,
MessageQueueId_t commandedBy,
const uint8_t *data, size_t size) {
/* Needs to be overriden and implemented by child class. */
return returnvalue::OK;
}
object_id_t ExtendedControllerBase::getObjectId() const { return SystemObject::getObjectId(); }

View File

@ -29,10 +29,6 @@ class ExtendedControllerBase : public ControllerBase,
ReturnValue_t performOperation(uint8_t opCode) override;
ReturnValue_t initializeAfterTaskCreation() override;
/* HasActionsIF overrides */
ActionHelper* getActionHelper() override;
ReturnValue_t executeAction(Action* actionId) override;
protected:
LocalDataPoolManager poolManager;
ActionHelper actionHelper;
@ -53,6 +49,10 @@ class ExtendedControllerBase : public ControllerBase,
/* Handle the four messages mentioned above */
void handleQueue() override;
/* HasActionsIF overrides */
ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size) override;
/* HasLocalDatapoolIF overrides */
LocalDataPoolManager* getHkManagerHandle() override;
[[nodiscard]] object_id_t getObjectId() const override;

View File

@ -1 +1 @@
target_sources(${LIB_FSFW_NAME} PRIVATE Dataset.cpp DatapoolHelper.cpp)
target_sources(${LIB_FSFW_NAME} PRIVATE PoolDataSetBase.cpp PoolEntry.cpp)

View File

@ -1,20 +0,0 @@
#include "DatapoolHelper.h"
DatapoolHelper::DatapoolHelper(HasDatapoolIF* owner) : HousekeepingHelper(owner) {}
ReturnValue_t DatapoolHelper::initialize() {
return HousekeepingHelper::initialize();
}
const Dataset* DatapoolHelper::getDataSet(HousekeepingSetId_t id) {
auto iter = dataSets.find(id);
if (iter == dataSets.end()) {
return nullptr;
}
return iter->second;
}
void DatapoolHelper::registerSet(Dataset* set) {
auto id = set->getId();
dataSets.emplace(id, set);
}

View File

@ -1,28 +0,0 @@
#pragma once
#include "Dataset.h"
#include "HasDatapoolIF.h"
#include <fsfw/housekeeping/HousekeepingHelper.h>
#include <stdint.h>
#include <map>
class DatapoolHelper : public HousekeepingHelper {
public:
DatapoolHelper(HasDatapoolIF *owner);
~DatapoolHelper() = default;
const Dataset* getDataSet(HousekeepingSetId_t id);
const std::map<HousekeepingSetId_t, Dataset*>* getDatasets() const {
return &dataSets;
}
void registerSet(Dataset* set);
ReturnValue_t initialize();
private:
std::map<HousekeepingSetId_t, Dataset*> dataSets;
};

View File

@ -1,141 +0,0 @@
#include "Dataset.h"
#include <fsfw/ipc/MutexFactory.h>
#include <fsfw/objectmanager/ObjectManager.h>
#include <fsfw/returnvalues/returnvalue.h>
//TODO for non allocated: detect if initialized, and if not, call it
#include "HasDatapoolIF.h"
#ifdef FSFW_INTROSPECTION
Dataset::Dataset(HasDatapoolIF* owner, const EnumIF &id, bool allowUserCommit)
: HousekeepingSet(owner, id), allocated(true), allowUserCommit(allowUserCommit) {
this->owner.pointer = owner;
owner->getDatapoolHelper()->registerSet(this);
mutex = MutexFactory::instance()->createMutex();
}
Dataset::Dataset(uint32_t owner_id, const EnumIF &id)
: HousekeepingSet(nullptr, id), allocated(false), allowUserCommit(false) {
this->owner.id = owner_id;
}
#else
Dataset::Dataset(HasDatapoolIF* owner, HousekeepingSetId_t id, bool allowUserCommit)
: HousekeepingSet(owner, id), allocated(true), allowUserCommit(allowUserCommit) {
this->owner.pointer = owner;
owner->getDatapoolHelper()->registerSet(this);
mutex = MutexFactory::instance()->createMutex();
}
Dataset::Dataset(uint32_t owner_id, HousekeepingSetId_t id) : HousekeepingSet(nullptr, id) {
this->owner.id = owner_id;
}
#endif
Dataset::~Dataset() { MutexFactory::instance()->deleteMutex(mutex); }
void Dataset::commit() {
if ((!allocated) && (!allowUserCommit)) {
return;
}
lock();
for (auto variable : variables) {
variable->commit();
}
unlock();
}
void Dataset::commit(bool valid) {
if ((!allocated) && (!allowUserCommit)) {
return;
}
setAllValid(valid);
commit();
}
void Dataset::setAllValid(bool valid) {
if ((!allocated) && (!allowUserCommit)) {
return;
}
for (auto variable : variables) {
variable->setValid(valid);
}
}
void Dataset::read() {
lock();
for (auto variable : variables) {
variable->read();
}
unlock();
}
bool Dataset::hasChanged() {
bool changed = hasChangedNoRead();
read();
return changed;
}
bool Dataset::hasChangedOrOlderThan(uint32_t seconds) {
bool changed = hasChanged();
// TODO time
read();
return changed;
}
const std::vector<DatasetEntryIF*>* Dataset::getVariables() const { return &variables; }
ReturnValue_t Dataset::initialize() {
if (allocated) {
// nothing to do
return returnvalue::OK;
}
HasDatapoolIF* actualOwner = ObjectManager::instance()->get<HasDatapoolIF>(owner.id);
if (actualOwner == nullptr) {
puts("owner type");
return returnvalue::FAILED;
}
const Dataset* theOtherSet = actualOwner->getDatapoolHelper()->getDataSet(this->id);
if (theOtherSet == nullptr) {
puts("no set");
return returnvalue::FAILED;
}
if (theOtherSet->variables.size() != variables.size()) {
return returnvalue::FAILED;
}
this->mutex = theOtherSet->mutex;
this->allowUserCommit = theOtherSet->allowUserCommit;
for (size_t i = 0; i < variables.size(); i++) {
variables[i]->connect(theOtherSet->variables[i]);
}
return returnvalue::OK;
}
// operator[]
bool Dataset::registerEntry(DatasetEntryIF* entry) {
variables.push_back(entry);
return allocated;
}
void Dataset::lock() { mutex->lockMutex(MutexIF::TimeoutType::BLOCKING); }
void Dataset::unlock() { mutex->unlockMutex(); }
bool Dataset::hasChangedNoRead() {
bool changed = false;
for (auto variable : variables) {
if (variable->changed()) {
changed = true;
break;
}
}
return changed;
}

View File

@ -1,183 +0,0 @@
#pragma once
#include <fsfw/housekeeping/HousekeepingSet.h>
#include <fsfw/introspection/Enum.h>
#include <fsfw/ipc/MutexIF.h>
#include <fsfw/returnvalues/returnvalue.h>
#include <fsfw/storagemanager/storeAddress.h>
#include <stdint.h>
#include <vector>
#include "DatasetEntryIF.h"
// TODO ring inclusion
// #include "HasDatapoolIF.h"
class HasDatapoolIF;
// TODO allow user commit and reporting TM
/**
* This class has a dual use
*
* 1) It is used as an IPC method:
* It implements a shared memory which can be written and read by different parties
*
* 2) It is used to define data that is to be downlinked, either periodically or
* triggered by an (abstract, not in the sense of fsfw/events) event occuring, ie
* data was received from an external source and should be shared with ground.
*
* Generating a downlinked report is coupled to commiting, as without a commit there is no
* change in information to be reported.
*
* Nominally, the decision to report is done by the set itself, depending on its settings.
* If a report is to be forced regardless of these settings, the commitAndReport() functions
* are provided which will always generate a report.
*
* Periodic reports are not tied to a specific tc and are reported as "unrequested". When forcing
* a report, optionally a tc can be provided which (logically) triggered the report.
*
* And, as life is complicated, there is a third set of commits: commitAndReportIfRequested(). Same
* as before, but this time, a report is only generated, if the store_address_t is valid. These are
* used if at the place where the commit is called, it is not known if there is a request (cf DHB
* interpretDeviceReply)
*/
class Dataset : public HousekeepingSet {
protected:
#ifdef FSFW_INTROSPECTION
Dataset(HasDatapoolIF* owner, const EnumIF &id, bool allowUserCommit);
Dataset(uint32_t owner_id, const EnumIF &id);
#else
Dataset(HasDatapoolIF* owner, HousekeepingSetId_t id, bool allowUserCommit);
Dataset(uint32_t owner_id, HousekeepingSetId_t id);
#endif
public:
~Dataset() override;
/**
* Copy content of local copies into actual variable
*
*/
void commit();
/**
* Copy content of local copies into actual variable
*
* calls setValid(valid) before committing
*
*/
void commit(bool valid);
/**
* Copy content of local copies into actual variable
* Force sending of TM packet
*
*/
void commitAndReport();
/**
* Copy content of local copies into actual variable
* Force sending of TM packet
*
* calls setValid(valid) before committing
*
*/
void commitAndReport(bool valid);
/**
* Copy content of local copies into actual variable
* Force sending of TM packet, in reference to tc
*
*/
void commitAndReport(store_address_t tc, size_t tc_offset);
/**
* Copy content of local copies into actual variable
* Force sending of TM packet, in reference to tc
*
* calls setValid(valid) before committing
*
*/
void commitAndReport(bool valid, store_address_t tc, size_t tc_offset);
/**
* Copy content of local copies into actual variable
* Force sending of TM packet, in reference to tc, if tc is valid
*
*/
void commitAndReportIfRequested(store_address_t tc, size_t tc_offset);
/**
* Copy content of local copies into actual variable
* Force sending of TM packet, in reference to tc, if tc is valid
*
* calls setValid(valid) before committing
*
*/
void commitAndReportIfRequested(bool valid, store_address_t tc, size_t tc_offset);
/**
* set all contained variables to #valid
*
*/
void setAllValid(bool valid);
/**
* Copy content of actual variables into local copies
*
*
*/
void read();
/**
* returns true if local copies and actual variables differ
*
* implicitely calls read()
*/
bool hasChanged();
/**
* returns true if local copies and actual variables differ
* or time since last time true has been returned is greater than
* supplied time
*
* implicitely calls read()
*
*/
bool hasChangedOrOlderThan(uint32_t seconds);
/**
* get List of contained Valiables
*/
virtual const std::vector<DatasetEntryIF*>* getVariables() const;
ReturnValue_t initialize();
// operator[]
bool registerEntry(DatasetEntryIF*);
protected:
bool allocated;
bool allowUserCommit;
union {
object_id_t id;
HasDatapoolIF* pointer;
} owner;
MutexIF* mutex;
std::vector<DatasetEntryIF*> variables;
/**
* lock the mutex of the set
*/
void lock();
/**
* unlock the mutex of the set
*/
void unlock();
bool hasChangedNoRead();
};

View File

@ -1,87 +0,0 @@
#pragma once
#include <fsfw/introspection/Parameter.h>
#include <fsfw/introspection/Types.h>
#include <fsfw/introspection/TypesHelper.h>
#include <stdio.h>
#include "Dataset.h"
#include "DatasetEntryIF.h"
// TODO: ifdef introspection stuff
template <typename T>
class DatasetEntry : public Parameter<T>, public DatasetEntryIF {
protected:
#ifdef FSFW_INTROSPECTION
DatasetEntry(Dataset *owner, const char *name)
: Parameter<T>(owner, name)
#else
DatasetEntry(Dataset *owner)
: Parameter<T>(owner)
#endif
{
allocated = owner->registerEntry(this);
if (!allocated) {
return;
}
storedValue = new T();
storedValid = new bool;
}
public:
#ifdef FSFW_INTROSPECTION
static DatasetEntry createDatasetEntry(Dataset *owner, const char *name) {
return DatasetEntry(owner, name);
}
#else
static DatasetEntry createDatasetEntry(Dataset *owner) { return DatasetEntry(owner); }
#endif
~DatasetEntry() {
if (allocated) {
delete storedValue;
delete storedValid;
}
}
virtual void setValid(bool isValid) { valid = isValid; }
virtual bool getValid() { return valid; }
//T value; //TODO can this be private?
protected:
virtual void commit() {
*storedValue = Parameter<T>::value;
*storedValid = valid;
}
virtual void read() {
Parameter<T>::value = *storedValue;
valid = *storedValid;
}
virtual void connect(DatasetEntryIF *entry) {
DatasetEntry<T> *theOther = dynamic_cast<DatasetEntry<T> *>(entry);
if (theOther == nullptr) {
// Configuration error
return;
}
this->storedValue = theOther->storedValue;
this->storedValid = theOther->storedValid;
}
virtual bool changed() { return ((Parameter<T>::value != *storedValue) || (valid != *storedValid)); }
private:
T *storedValue;
bool *storedValid;
bool valid;
bool allocated;
};
#ifdef FSFW_INTROSPECTION
#define createDatasetEntry(p1, p2) createDatasetEntry(p1, p2)
#else
#define createDatasetEntry(p1, p2) createDatasetEntry(p1)
#endif

View File

@ -1,39 +0,0 @@
#ifndef FSFW_DATAPOOL_POOLENTRYIF_H_
#define FSFW_DATAPOOL_POOLENTRYIF_H_
#include <cstdint>
#include <fsfw/introspection/Types.h>
class DatasetEntryIF {
friend class Dataset;
public:
virtual ~DatasetEntryIF() {}
/**
* @brief This method allows to set the valid information of the pool entry.
*/
virtual void setValid(bool isValid) = 0;
/**
* @brief This method allows to set the valid information of the pool entry.
*/
virtual bool getValid() = 0;
protected:
virtual void commit() = 0;
virtual void read() = 0;
virtual void connect(DatasetEntryIF* entry) = 0;
/**
* returns if value and actual value is different
*/
virtual bool changed() = 0;
private:
};
#endif /* FSFW_DATAPOOL_POOLENTRYIF_H_ */

View File

@ -1,13 +0,0 @@
#pragma once
//TODO ring
class DatapoolHelper;
#include "DatapoolHelper.h"
#include <fsfw/housekeeping/GeneratesHousekeepingIF.h>
class HasDatapoolIF: public GeneratesHousekeepingIF {
public:
virtual ~HasDatapoolIF() = default;
virtual DatapoolHelper* getDatapoolHelper() = 0;
};

View File

@ -0,0 +1,217 @@
#include "fsfw/datapool/PoolDataSetBase.h"
#include <cstring>
#include "fsfw/datapool/ReadCommitIFAttorney.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
PoolDataSetBase::PoolDataSetBase(PoolVariableIF** registeredVariablesArray,
const size_t maxFillCount)
: registeredVariables(registeredVariablesArray), maxFillCount(maxFillCount) {}
PoolDataSetBase::~PoolDataSetBase() {}
ReturnValue_t PoolDataSetBase::registerVariable(PoolVariableIF* variable) {
if (registeredVariables == nullptr) {
/* Underlying container invalid */
return returnvalue::FAILED;
}
if (state != States::STATE_SET_UNINITIALISED) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "DataSet::registerVariable: Call made in wrong position." << std::endl;
#else
sif::printError("DataSet::registerVariable: Call made in wrong position.");
#endif
return DataSetIF::DATA_SET_UNINITIALISED;
}
if (variable == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "DataSet::registerVariable: Pool variable is nullptr." << std::endl;
#else
sif::printError("DataSet::registerVariable: Pool variable is nullptr.\n");
#endif
return DataSetIF::POOL_VAR_NULL;
}
if (fillCount >= maxFillCount) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "DataSet::registerVariable: DataSet is full." << std::endl;
#else
sif::printError("DataSet::registerVariable: DataSet is full.\n");
#endif
return DataSetIF::DATA_SET_FULL;
}
registeredVariables[fillCount] = variable;
fillCount++;
return returnvalue::OK;
}
ReturnValue_t PoolDataSetBase::read(MutexIF::TimeoutType timeoutType, uint32_t lockTimeout) {
ReturnValue_t result = returnvalue::OK;
ReturnValue_t error = result;
if (state == States::STATE_SET_UNINITIALISED) {
lockDataPool(timeoutType, lockTimeout);
for (uint16_t count = 0; count < fillCount; count++) {
result = readVariable(count);
if (result != returnvalue::OK) {
error = result;
}
}
state = States::STATE_SET_WAS_READ;
unlockDataPool();
} else {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "PoolDataSetBase::read: Call made in wrong position. Don't forget to "
"commit member datasets!"
<< std::endl;
#else
sif::printWarning(
"PoolDataSetBase::read: Call made in wrong position. Don't forget to "
"commit member datasets!\n");
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
result = SET_WAS_ALREADY_READ;
}
if (error != returnvalue::OK) {
result = error;
}
return result;
}
uint16_t PoolDataSetBase::getFillCount() const { return fillCount; }
ReturnValue_t PoolDataSetBase::readVariable(uint16_t count) {
ReturnValue_t result = returnvalue::OK;
if (registeredVariables[count] == nullptr) {
/* Configuration error. */
return returnvalue::FAILED;
}
/* These checks are often performed by the respective variable implementation too, but I guess
a double check does not hurt. */
if (registeredVariables[count]->getReadWriteMode() != PoolVariableIF::VAR_WRITE and
registeredVariables[count]->getDataPoolId() != PoolVariableIF::NO_PARAMETER) {
if (protectEveryReadCommitCall) {
result =
registeredVariables[count]->read(timeoutTypeForSingleVars, mutexTimeoutForSingleVars);
} else {
/* The readWithoutLock function is protected, so we use the attorney here */
result = ReadCommitIFAttorney::readWithoutLock(registeredVariables[count]);
}
if (result != returnvalue::OK) {
result = INVALID_PARAMETER_DEFINITION;
}
}
return result;
}
ReturnValue_t PoolDataSetBase::commit(MutexIF::TimeoutType timeoutType, uint32_t lockTimeout) {
if (state == States::STATE_SET_WAS_READ) {
handleAlreadyReadDatasetCommit(timeoutType, lockTimeout);
return returnvalue::OK;
} else {
return handleUnreadDatasetCommit(timeoutType, lockTimeout);
}
}
void PoolDataSetBase::handleAlreadyReadDatasetCommit(MutexIF::TimeoutType timeoutType,
uint32_t lockTimeout) {
lockDataPool(timeoutType, lockTimeout);
for (uint16_t count = 0; count < fillCount; count++) {
if ((registeredVariables[count]->getReadWriteMode() != PoolVariableIF::VAR_READ) and
(registeredVariables[count]->getDataPoolId() != PoolVariableIF::NO_PARAMETER)) {
if (protectEveryReadCommitCall) {
registeredVariables[count]->commit(timeoutTypeForSingleVars, mutexTimeoutForSingleVars);
} else {
/* The commitWithoutLock function is protected, so we use the attorney here */
ReadCommitIFAttorney::commitWithoutLock(registeredVariables[count]);
}
}
}
state = States::STATE_SET_UNINITIALISED;
unlockDataPool();
}
ReturnValue_t PoolDataSetBase::handleUnreadDatasetCommit(MutexIF::TimeoutType timeoutType,
uint32_t lockTimeout) {
ReturnValue_t result = returnvalue::OK;
lockDataPool(timeoutType, lockTimeout);
for (uint16_t count = 0; count < fillCount; count++) {
if ((registeredVariables[count]->getReadWriteMode() == PoolVariableIF::VAR_WRITE) and
(registeredVariables[count]->getDataPoolId() != PoolVariableIF::NO_PARAMETER)) {
if (protectEveryReadCommitCall) {
result =
registeredVariables[count]->commit(timeoutTypeForSingleVars, mutexTimeoutForSingleVars);
} else {
/* The commitWithoutLock function is protected, so we use the attorney here */
ReadCommitIFAttorney::commitWithoutLock(registeredVariables[count]);
}
} else if (registeredVariables[count]->getDataPoolId() != PoolVariableIF::NO_PARAMETER) {
if (result != COMMITING_WITHOUT_READING) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "DataSet::commit(): commit-without-read call made "
"with non write-only variable."
<< std::endl;
#endif
result = COMMITING_WITHOUT_READING;
}
}
}
state = States::STATE_SET_UNINITIALISED;
unlockDataPool();
return result;
}
ReturnValue_t PoolDataSetBase::lockDataPool(MutexIF::TimeoutType timeoutType,
uint32_t lockTimeout) {
return returnvalue::OK;
}
ReturnValue_t PoolDataSetBase::unlockDataPool() { return returnvalue::OK; }
ReturnValue_t PoolDataSetBase::serialize(uint8_t** buffer, size_t* size, const size_t maxSize,
SerializeIF::Endianness streamEndianness) const {
ReturnValue_t result = returnvalue::FAILED;
for (uint16_t count = 0; count < fillCount; count++) {
result = registeredVariables[count]->serialize(buffer, size, maxSize, streamEndianness);
if (result != returnvalue::OK) {
return result;
}
}
return result;
}
ReturnValue_t PoolDataSetBase::deSerialize(const uint8_t** buffer, size_t* size,
SerializeIF::Endianness streamEndianness) {
ReturnValue_t result = returnvalue::FAILED;
for (uint16_t count = 0; count < fillCount; count++) {
result = registeredVariables[count]->deSerialize(buffer, size, streamEndianness);
if (result != returnvalue::OK) {
return result;
}
}
return result;
}
size_t PoolDataSetBase::getSerializedSize() const {
uint32_t size = 0;
for (uint16_t count = 0; count < fillCount; count++) {
size += registeredVariables[count]->getSerializedSize();
}
return size;
}
void PoolDataSetBase::setContainer(PoolVariableIF** variablesContainer) {
this->registeredVariables = variablesContainer;
}
PoolVariableIF** PoolDataSetBase::getContainer() const { return registeredVariables; }
void PoolDataSetBase::setReadCommitProtectionBehaviour(bool protectEveryReadCommit,
MutexIF::TimeoutType timeoutType,
uint32_t mutexTimeout) {
this->protectEveryReadCommitCall = protectEveryReadCommit;
this->timeoutTypeForSingleVars = timeoutType;
this->mutexTimeoutForSingleVars = mutexTimeout;
}

View File

@ -0,0 +1,173 @@
#ifndef FSFW_DATAPOOL_POOLDATASETBASE_H_
#define FSFW_DATAPOOL_POOLDATASETBASE_H_
#include "PoolDataSetIF.h"
#include "PoolVariableIF.h"
#include "fsfw/ipc/MutexIF.h"
#include "fsfw/serialize/SerializeIF.h"
/**
* @brief The DataSetBase class manages a set of locally checked out variables.
* @details
* This class manages a list, where a set of local variables (or pool variables)
* are registered. They are checked-out (i.e. their values are looked
* up and copied) with the read call. After the user finishes working with the
* pool variables, he can write back all variable values to the pool with
* the commit call. The data set manages locking and freeing the data pool,
* to ensure that all values are read and written back at once.
*
* An internal state manages usage of this class. Variables may only be
* registered before the read call is made, and the commit call only
* after the read call.
*
* If pool variables are writable and not committed until destruction
* of the set, the DataSet class automatically sets the valid flag in the
* data pool to invalid (without) changing the variable's value.
*
* The base class lockDataPool und unlockDataPool implementation are empty
* and should be implemented to protect the underlying pool type.
* @author Bastian Baetz
* @ingroup data_pool
*/
class PoolDataSetBase : public PoolDataSetIF, public SerializeIF {
public:
/**
* @brief Creates an empty dataset. Use registerVariable or
* supply a pointer to this dataset to PoolVariable
* initializations to register pool variables.
*/
PoolDataSetBase(PoolVariableIF** registeredVariablesArray, size_t maxFillCount);
/* Forbidden for now */
PoolDataSetBase(const PoolDataSetBase& otherSet) = delete;
const PoolDataSetBase& operator=(const PoolDataSetBase& otherSet) = delete;
~PoolDataSetBase() override;
/**
* @brief The read call initializes reading out all registered variables.
* It is mandatory to call commit after every read call!
* @details
* It iterates through the list of registered variables and calls all read()
* functions of the registered pool variables (which read out their values
* from the data pool) which are not write-only.
* In case of an error (e.g. a wrong data type, or an invalid data pool id),
* the operation is aborted and @c INVALID_PARAMETER_DEFINITION returned.
*
* The data pool is locked during the whole read operation and
* freed afterwards. It is mandatory to call commit after a read call,
* even if the read operation is not successful!
* @return
* - @c returnvalue::OK if all variables were read successfully.
* - @c INVALID_PARAMETER_DEFINITION if a pool entry does not exist or there
* is a type conflict.
* - @c SET_WAS_ALREADY_READ if read() is called twice without calling
* commit() in between
*/
virtual ReturnValue_t read(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
uint32_t lockTimeout = 20) override;
/**
* @brief The commit call initializes writing back the registered variables.
* @details
* It iterates through the list of registered variables and calls the
* commit() method of the remaining registered variables (which write back
* their values to the pool).
*
* The data pool is locked during the whole commit operation and
* freed afterwards. The state changes to "was committed" after this operation.
*
* If the set does contain at least one variable which is not write-only
* commit() can only be called after read(). If the set only contains
* variables which are write only, commit() can be called without a
* preceding read() call. Every read call must be followed by a commit call!
* @return - @c returnvalue::OK if all variables were read successfully.
* - @c COMMITING_WITHOUT_READING if set was not read yet and
* contains non write-only variables
*/
virtual ReturnValue_t commit(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
uint32_t lockTimeout = 20) override;
/**
* Register the passed pool variable instance into the data set.
* @param variable
* @return
*/
virtual ReturnValue_t registerVariable(PoolVariableIF* variable) override;
/**
* Provides the means to lock the underlying data structure to ensure
* thread-safety. Default implementation is empty
* @return Always returns -@c returnvalue::OK
*/
virtual ReturnValue_t lockDataPool(
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
uint32_t timeoutMs = 20) override;
/**
* Provides the means to unlock the underlying data structure to ensure
* thread-safety. Default implementation is empty
* @return Always returns -@c returnvalue::OK
*/
virtual ReturnValue_t unlockDataPool() override;
virtual uint16_t getFillCount() const override;
/* SerializeIF implementations */
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, const size_t maxSize,
SerializeIF::Endianness streamEndianness) const override;
virtual size_t getSerializedSize() const override;
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
SerializeIF::Endianness streamEndianness) override;
/**
* Can be used to individually protect every read and commit call.
* @param protectEveryReadCommit
* @param mutexTimeout
*/
void setReadCommitProtectionBehaviour(
bool protectEveryReadCommit, MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
uint32_t mutexTimeout = 20);
protected:
/**
* @brief The fill_count attribute ensures that the variables
* register in the correct array position and that the maximum
* number of variables is not exceeded.
*/
uint16_t fillCount = 0;
/**
* States of the seet.
*/
enum class States {
STATE_SET_UNINITIALISED, //!< DATA_SET_UNINITIALISED
STATE_SET_WAS_READ //!< DATA_SET_WAS_READ
};
/**
* @brief state manages the internal state of the data set,
* which is important e.g. for the behavior on destruction.
*/
States state = States::STATE_SET_UNINITIALISED;
/**
* @brief This array represents all pool variables registered in this set.
* Child classes can use a static or dynamic container to create
* an array of registered variables and assign the first entry here.
*/
PoolVariableIF** registeredVariables = nullptr;
const size_t maxFillCount = 0;
void setContainer(PoolVariableIF** variablesContainer);
PoolVariableIF** getContainer() const;
private:
bool protectEveryReadCommitCall = false;
MutexIF::TimeoutType timeoutTypeForSingleVars = MutexIF::TimeoutType::WAITING;
uint32_t mutexTimeoutForSingleVars = 20;
ReturnValue_t readVariable(uint16_t count);
void handleAlreadyReadDatasetCommit(
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING, uint32_t timeoutMs = 20);
ReturnValue_t handleUnreadDatasetCommit(
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING, uint32_t timeoutMs = 20);
};
#endif /* FSFW_DATAPOOL_POOLDATASETBASE_H_ */

View File

@ -0,0 +1,34 @@
#ifndef FSFW_DATAPOOL_POOLDATASETIF_H_
#define FSFW_DATAPOOL_POOLDATASETIF_H_
#include "DataSetIF.h"
#include "ReadCommitIF.h"
/**
* @brief Extendes the DataSetIF by adding abstract functions to lock
* and unlock a data pool and read/commit semantics.
*/
class PoolDataSetIF : virtual public DataSetIF, virtual public ReadCommitIF {
public:
virtual ~PoolDataSetIF(){};
/**
* @brief Most underlying data structures will have a pool like structure
* and will require a lock and unlock mechanism to ensure
* thread-safety
* @return Lock operation result
*/
virtual ReturnValue_t lockDataPool(
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
uint32_t timeoutMs = 20) = 0;
/**
* @brief Unlock call corresponding to the lock call.
* @return Unlock operation result
*/
virtual ReturnValue_t unlockDataPool() = 0;
virtual bool isValid() const = 0;
};
#endif /* FSFW_DATAPOOL_POOLDATASETIF_H_ */

View File

@ -0,0 +1,102 @@
#include "fsfw/datapool/PoolEntry.h"
#include <algorithm>
#include <cstring>
#include "fsfw/globalfunctions/arrayprinter.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
template <typename T>
PoolEntry<T>::PoolEntry(uint8_t len, bool setValid) : length(len), valid(setValid) {
this->address = new T[this->length]();
std::memset(this->address, 0, this->getByteSize());
}
template <typename T>
PoolEntry<T>::PoolEntry(std::initializer_list<T> initValues, bool setValid)
: length(static_cast<uint8_t>(initValues.size())), valid(setValid) {
this->address = new T[this->length]();
if (initValues.size() > 0) {
std::copy(initValues.begin(), initValues.end(), this->address);
}
}
template <typename T>
PoolEntry<T>::PoolEntry(const T* initValue, uint8_t setLength, bool setValid)
: length(setLength), valid(setValid) {
this->address = new T[this->length]();
if (initValue != nullptr) {
std::memcpy(this->address, initValue, this->getByteSize());
}
}
// As the data pool is global, this dtor is only be called on program exit.
// Warning! Never copy pool entries!
template <typename T>
PoolEntry<T>::~PoolEntry() {
delete[] this->address;
}
template <typename T>
uint16_t PoolEntry<T>::getByteSize() {
return (sizeof(T) * this->length);
}
template <typename T>
uint8_t PoolEntry<T>::getSize() {
return this->length;
}
template <typename T>
void* PoolEntry<T>::getRawData() {
return this->address;
}
template <typename T>
void PoolEntry<T>::setValid(bool isValid) {
this->valid = isValid;
}
template <typename T>
bool PoolEntry<T>::getValid() {
return valid;
}
template <typename T>
void PoolEntry<T>::print() {
const char* validString = nullptr;
if (valid) {
validString = "Valid";
} else {
validString = "Invalid";
}
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "PoolEntry information." << std::endl;
sif::info << "PoolEntry validity: " << validString << std::endl;
#else
sif::printInfo("PoolEntry information.\n");
sif::printInfo("PoolEntry validity: %s\n", validString);
#endif
arrayprinter::print(reinterpret_cast<uint8_t*>(address), getByteSize());
}
template <typename T>
inline T* PoolEntry<T>::getDataPtr() {
return this->address;
}
template <typename T>
Type PoolEntry<T>::getType() {
return PodTypeConversion<T>::type;
}
template class PoolEntry<uint8_t>;
template class PoolEntry<uint16_t>;
template class PoolEntry<uint32_t>;
template class PoolEntry<uint64_t>;
template class PoolEntry<int8_t>;
template class PoolEntry<int16_t>;
template class PoolEntry<int32_t>;
template class PoolEntry<int64_t>;
template class PoolEntry<float>;
template class PoolEntry<double>;

View File

@ -0,0 +1,140 @@
#ifndef FSFW_DATAPOOL_POOLENTRY_H_
#define FSFW_DATAPOOL_POOLENTRY_H_
#include <cstddef>
#include <initializer_list>
#include <type_traits>
#include "PoolEntryIF.h"
/**
* @brief This is a small helper class that defines a single data pool entry.
* @details
* The helper is used to store all information together with the data as a
* single data pool entry. The content's type is defined by the template
* argument.
*
* It is prepared for use with plain old data types, but may be
* extended to complex types if necessary. It can be initialized with a
* certain value, size and validity flag.
*
* It holds a pointer to the real data and offers methods to access this data
* and to acquire additional information (such as validity and array/byte size).
* It is NOT intended to be used outside DataPool implementations as it performs
* dynamic memory allocation.
*
* @ingroup data_pool
*/
template <typename T>
class PoolEntry : public PoolEntryIF {
public:
static_assert(not std::is_same<T, bool>::value,
"Do not use boolean for the PoolEntry type, use uint8_t "
"instead! The ECSS standard defines a boolean as a one bit "
"field. Therefore it is preferred to store a boolean as an "
"uint8_t");
PoolEntry(uint8_t len = 1, bool setValid = false);
/**
* @brief In the classe's constructor, space is allocated on the heap and
* potential initialization values are copied to that space.
* @details
* Not passing any arguments will initialize an non-array pool entry
* with an initial invalid state and the value 0.
* Please note that if an initializer list is passed, the length of the
* initializer list needs to be correct for vector entries because
* required allocated space will be deduced from the initializer list length
* and the pool entry type.
* @param initValue
* Initializer list with values to initialize with, for example {0, 0} to
* initialize the a pool entry of a vector with two entries to 0.
* @param setValid
* Sets the initialization flag. It is invalid by default.
*/
PoolEntry(std::initializer_list<T> initValue, bool setValid = false);
/**
* @brief In the classe's constructor, space is allocated on the heap and
* potential init values are copied to that space.
* @param initValue
* A pointer to the single value or array that holds the init value.
* With the default value (nullptr), the entry is initalized with all 0.
* @param setLength
* Defines the array length of this entry.
* @param setValid
* Sets the initialization flag. It is invalid by default.
*/
PoolEntry(const T* initValue, uint8_t setLength = 1, bool setValid = false);
//! Explicitely deleted copy ctor, copying is not allowed.
PoolEntry(const PoolEntry&) = delete;
//! Explicitely deleted copy assignment, copying is not allowed.
PoolEntry& operator=(const PoolEntry&) = delete;
/**
* @brief The allocated memory for the variable is freed
* in the destructor.
* @details
* As the data pool is global, this dtor is only called on program exit.
* PoolEntries shall never be copied, as a copy might delete the variable
* on the heap.
*/
~PoolEntry();
/**
* Return typed pointer to start of data.
* @return
*/
T* getDataPtr();
/**
* @brief getSize returns the array size of the entry.
* @details
* For non-array pool entries return type size, for vector entries
* return type size times the number of entries.
*/
uint8_t getSize();
/**
* @brief This operation returns the size in bytes.
* @details The size is calculated by sizeof(type) * array_size.
*/
uint16_t getByteSize();
/**
* @brief This operation returns a the address pointer casted to void*.
*/
void* getRawData();
/**
* @brief This method allows to set the valid information
* of the pool entry.
*/
void setValid(bool isValid);
/**
* @brief This method allows to get the valid information
* of the pool entry.
*/
bool getValid();
/**
* @brief This is a debug method that prints all values and the valid
* information to the screen. It prints all array entries in a row.
*/
void print();
Type getType();
private:
/**
* @brief This attribute stores the length information.
*/
uint8_t length;
/**
* @brief Here, the validity information for a variable is stored.
* Every entry (single variable or vector) has one valid flag.
*/
uint8_t valid;
/**
* @brief This is the address pointing to the allocated memory.
*/
T* address;
};
#endif /* FSFW_DATAPOOL_POOLENTRY_H_ */

View File

@ -0,0 +1,28 @@
#ifndef FSFW_DATAPOOL_POOLVARLIST_H_
#define FSFW_DATAPOOL_POOLVARLIST_H_
#include "../datapool/PoolVariableIF.h"
#include "../datapoolglob/GlobalPoolVariable.h"
template <class T, uint8_t n_var>
class PoolVarList {
private:
GlobPoolVar<T> variables[n_var];
public:
PoolVarList(const uint32_t set_id[n_var], DataSetIF* dataSet,
PoolVariableIF::ReadWriteMode_t setReadWriteMode) {
// I really should have a look at the new init list c++ syntax.
if (dataSet == NULL) {
return;
}
for (uint8_t count = 0; count < n_var; count++) {
variables[count].dataPoolId = set_id[count];
variables[count].readWriteMode = setReadWriteMode;
dataSet->registerVariable(&variables[count]);
}
}
GlobPoolVar<T>& operator[](int i) { return variables[i]; }
};
#endif /* FSFW_DATAPOOL_POOLVARLIST_H_ */

View File

@ -0,0 +1,62 @@
#ifndef FSFW_DATAPOOL_POOLVARIABLEIF_H_
#define FSFW_DATAPOOL_POOLVARIABLEIF_H_
#include "../returnvalues/returnvalue.h"
#include "../serialize/SerializeIF.h"
#include "ReadCommitIF.h"
/**
* @brief This interface is used to control data pool
* variable representations.
* @details
* To securely handle data pool variables, all pool entries are locally
* managed by data pool variable access classes, which are called pool
* variables. To ensure a common state of a set of variables needed in a
* function, these local pool variables again are managed by other classes,
* like the DataSet classes. This interface provides unified access to
* local pool variables for such manager classes.
* @author Bastian Baetz
* @ingroup data_pool
*/
class PoolVariableIF : public SerializeIF, public ReadCommitIF {
public:
static constexpr uint8_t INTERFACE_ID = CLASS_ID::POOL_VARIABLE_IF;
static constexpr ReturnValue_t INVALID_READ_WRITE_MODE = MAKE_RETURN_CODE(0xA0);
static constexpr ReturnValue_t INVALID_POOL_ENTRY = MAKE_RETURN_CODE(0xA1);
static constexpr bool VALID = 1;
static constexpr bool INVALID = 0;
static constexpr uint32_t NO_PARAMETER = 0xffffffff;
enum ReadWriteMode_t { VAR_READ, VAR_WRITE, VAR_READ_WRITE };
/**
* @brief This is an empty virtual destructor,
* as it is proposed for C++ interfaces.
*/
virtual ~PoolVariableIF() {}
/**
* @brief This method returns if the variable is write-only,
* read-write or read-only.
*/
virtual ReadWriteMode_t getReadWriteMode() const = 0;
virtual void setReadWriteMode(ReadWriteMode_t newMode) = 0;
/**
* @brief This operation shall return the data pool id of the variable.
*/
virtual uint32_t getDataPoolId() const = 0;
/**
* @brief With this call, the valid information of the
* variable is returned.
*/
virtual bool isValid() const = 0;
/**
* @brief With this call, the valid information of the variable is set.
*/
virtual void setValid(bool validity) = 0;
};
using pool_rwm_t = PoolVariableIF::ReadWriteMode_t;
#endif /* FSFW_DATAPOOL_POOLVARIABLEIF_H_ */

View File

@ -0,0 +1,27 @@
#ifndef FSFW_DATAPOOL_READCOMMITIF_H_
#define FSFW_DATAPOOL_READCOMMITIF_H_
#include "../ipc/MutexIF.h"
#include "../returnvalues/returnvalue.h"
/**
* @brief Common interface for all software objects which employ read-commit
* semantics.
*/
class ReadCommitIF {
friend class ReadCommitIFAttorney;
public:
virtual ~ReadCommitIF() {}
virtual ReturnValue_t read(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) = 0;
virtual ReturnValue_t commit(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) = 0;
protected:
/* Optional and protected because this is interesting for classes grouping members with commit
and read semantics where the lock is only necessary once. */
virtual ReturnValue_t readWithoutLock() { return read(MutexIF::TimeoutType::WAITING, 20); }
virtual ReturnValue_t commitWithoutLock() { return commit(MutexIF::TimeoutType::WAITING, 20); }
};
#endif /* FSFW_DATAPOOL_READCOMMITIF_H_ */

View File

@ -0,0 +1,30 @@
#ifndef FSFW_DATAPOOL_READCOMMITIFATTORNEY_H_
#define FSFW_DATAPOOL_READCOMMITIFATTORNEY_H_
#include <fsfw/datapool/ReadCommitIF.h>
#include <fsfw/returnvalues/returnvalue.h>
/**
* @brief This class determines which members are allowed to access protected members
* of the ReadCommitIF.
*/
class ReadCommitIFAttorney {
private:
static ReturnValue_t readWithoutLock(ReadCommitIF* readCommitIF) {
if (readCommitIF == nullptr) {
return returnvalue::FAILED;
}
return readCommitIF->readWithoutLock();
}
static ReturnValue_t commitWithoutLock(ReadCommitIF* readCommitIF) {
if (readCommitIF == nullptr) {
return returnvalue::FAILED;
}
return readCommitIF->commitWithoutLock();
}
friend class PoolDataSetBase;
};
#endif /* FSFW_DATAPOOL_READCOMMITIFATTORNEY_H_ */

View File

@ -0,0 +1,16 @@
#ifndef FRAMEWORK_DATAPOOL_SHAREDDATASETIF_H_
#define FRAMEWORK_DATAPOOL_SHAREDDATASETIF_H_
#include "PoolDataSetIF.h"
class SharedDataSetIF {
public:
virtual ~SharedDataSetIF(){};
private:
virtual ReturnValue_t lockDataset(MutexIF::TimeoutType timeoutType,
dur_millis_t mutexTimeout) = 0;
virtual ReturnValue_t unlockDataset() = 0;
};
#endif /* FRAMEWORK_DATAPOOL_SHAREDDATASETIF_H_ */

11
src/fsfw/datapoollocal.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef FSFW_DATAPOOLLOCAL_DATAPOOLLOCAL_H_
#define FSFW_DATAPOOLLOCAL_DATAPOOLLOCAL_H_
/* Collected related headers */
#include "fsfw/datapoollocal/LocalDataSet.h"
#include "fsfw/datapoollocal/LocalPoolVariable.h"
#include "fsfw/datapoollocal/LocalPoolVector.h"
#include "fsfw/datapoollocal/SharedLocalDataSet.h"
#include "fsfw/datapoollocal/StaticLocalDataSet.h"
#endif /* FSFW_DATAPOOLLOCAL_DATAPOOLLOCAL_H_ */

View File

@ -6,8 +6,8 @@
#include "AccessLocalPoolF.h"
#include "ProvidesDataPoolSubscriptionIF.h"
#include "fsfw/datapoollocal/DataSetIF.h"
#include "fsfw/datapoollocal/PoolEntry.h"
#include "fsfw/datapool/DataSetIF.h"
#include "fsfw/datapool/PoolEntry.h"
#include "fsfw/housekeeping/AcceptsHkPacketsIF.h"
#include "fsfw/housekeeping/HousekeepingMessage.h"
#include "fsfw/housekeeping/HousekeepingPacketDownlink.h"

View File

@ -87,9 +87,9 @@ class LocalPoolVariable : public LocalPoolObjectBase {
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
SerializeIF::Endianness streamEndianness) const override;
size_t getSerializedSize() const override;
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
SerializeIF::Endianness streamEndianness) override;
virtual size_t getSerializedSize() const override;
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
SerializeIF::Endianness streamEndianness) override;
/**
* @brief This is a call to read the array's values

View File

@ -98,11 +98,11 @@ class LocalPoolVector : public LocalPoolObjectBase {
T& operator[](size_t i);
const T& operator[](size_t i) const;
ReturnValue_t serialize(uint8_t** buffer, size_t* size, const size_t maxSize,
SerializeIF::Endianness streamEndiannes) const override;
size_t getSerializedSize() const override;
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
SerializeIF::Endianness streamEndianness) override;
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, const size_t maxSize,
SerializeIF::Endianness streamEndiannes) const override;
virtual size_t getSerializedSize() const override;
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
SerializeIF::Endianness streamEndianness) override;
/**
* @brief This is a call to read the array's values

View File

@ -4,7 +4,7 @@
#include <cstdint>
#include <map>
#include "PoolEntryIF.h"
#include "../datapool/PoolEntryIF.h"
#include "../objectmanager/SystemObjectIF.h"
#include "../objectmanager/frameworkObjects.h"

View File

@ -12,7 +12,7 @@ ChildHandlerBase::ChildHandlerBase(object_id_t setObjectId, object_id_t deviceCo
parentId(parent),
childHandlerFdir(setObjectId) {
this->setHkDestination(hkDestination);
this->setThermalStateRequestPoolIds(); //TODO
this->setThermalStateRequestPoolIds(thermalStatePoolId, thermalRequestPoolId);
}
ChildHandlerBase::~ChildHandlerBase() {}

View File

@ -1,9 +1,11 @@
#include "fsfw/devicehandlers/DeviceHandlerBase.h"
#include "DeviceHandlerBase.h"
#include "fsfw/datapool/PoolReadGuard.h"
#include "fsfw/datapoollocal/LocalPoolVariable.h"
#include "fsfw/devicehandlers/AcceptsDeviceResponsesIF.h"
#include "fsfw/devicehandlers/DeviceTmReportingWrapper.h"
#include "fsfw/globalfunctions/CRC.h"
#include "fsfw/housekeeping/HousekeepingMessage.h"
#include "fsfw/ipc/MessageQueueMessage.h"
#include "fsfw/ipc/QueueFactory.h"
#include "fsfw/objectmanager/ObjectManager.h"
@ -31,7 +33,7 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, object_id_t device
modeHelper(this),
parameterHelper(this),
actionHelper(this, nullptr),
datapoolHelper(this),
poolManager(this, nullptr),
childTransitionFailure(returnvalue::OK),
fdirInstance(fdirInstance),
defaultFDIRUsed(fdirInstance == nullptr),
@ -57,7 +59,12 @@ void DeviceHandlerBase::setHkDestination(object_id_t hkDestination) {
this->hkDestination = hkDestination;
}
void DeviceHandlerBase::setThermalStateRequestPoolIds() {}
void DeviceHandlerBase::setThermalStateRequestPoolIds(lp_id_t thermalStatePoolId,
lp_id_t heaterRequestPoolId,
uint32_t thermalSetId) {
thermalSet =
new DeviceHandlerThermalSet(this, thermalSetId, thermalStatePoolId, heaterRequestPoolId);
}
DeviceHandlerBase::~DeviceHandlerBase() {
if (comCookie != nullptr) {
@ -108,6 +115,9 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) {
break;
case CommunicationAction::GET_READ:
doGetRead();
/* This will be performed after datasets have been updated by the
custom device implementation. */
poolManager.performHkOperation();
break;
default:
break;
@ -196,10 +206,6 @@ ReturnValue_t DeviceHandlerBase::initialize() {
if (result != returnvalue::OK) {
return result;
}
result = datapoolHelper.initialize();
if (result != returnvalue::OK) {
return result;
}
result = fdirInstance->initialize();
if (result != returnvalue::OK) {
return result;
@ -210,22 +216,22 @@ ReturnValue_t DeviceHandlerBase::initialize() {
return result;
}
// result = poolManager.initialize(commandQueue);
// if (result != returnvalue::OK) {
// return result;
// }
result = poolManager.initialize(commandQueue);
if (result != returnvalue::OK) {
return result;
}
fillCommandAndReplyMap();
// if (thermalSet != nullptr) { //TODO
// // Set temperature target state to NON_OP.
// result = thermalSet->read();
// if (result == returnvalue::OK) {
// thermalSet->heaterRequest.value = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL;
// thermalSet->heaterRequest.setValid(true);
// thermalSet->commit();
// }
// }
if (thermalSet != nullptr) {
// Set temperature target state to NON_OP.
result = thermalSet->read();
if (result == returnvalue::OK) {
thermalSet->heaterRequest.value = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL;
thermalSet->heaterRequest.setValid(true);
thermalSet->commit();
}
}
return returnvalue::OK;
}
@ -285,10 +291,10 @@ void DeviceHandlerBase::readCommandQueue() {
return;
}
// result = poolManager.handleHousekeepingMessage(&command); //TODO
// if (result == returnvalue::OK) {
// return;
// }
result = poolManager.handleHousekeepingMessage(&command);
if (result == returnvalue::OK) {
return;
}
result = handleDeviceHandlerMessage(&command);
if (result == returnvalue::OK) {
@ -415,7 +421,7 @@ ReturnValue_t DeviceHandlerBase::isModeCombinationValid(Mode_t mode, Submode_t s
}
ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap(
DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles, void* replyDataSet /*TODO*/,
DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles, LocalPoolDataSetBase* replyDataSet,
size_t replyLen, bool periodic, bool hasDifferentReplyId, DeviceCommandId_t replyId,
Countdown* countdown) {
// No need to check, as we may try to insert multiple times.
@ -430,14 +436,14 @@ ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap(
ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId,
uint16_t maxDelayCycles,
void* dataSet/*TODO*/, size_t replyLen,
LocalPoolDataSetBase* dataSet, size_t replyLen,
bool periodic, Countdown* countdown) {
DeviceReplyInfo info;
info.maxDelayCycles = maxDelayCycles;
info.periodic = periodic;
info.delayCycles = 0;
info.replyLen = replyLen;
//info.dataSet = dataSet;
info.dataSet = dataSet;
info.command = deviceCommandMap.end();
info.countdown = countdown;
auto resultPair = deviceReplyMap.emplace(replyId, info);
@ -530,15 +536,15 @@ ReturnValue_t DeviceHandlerBase::updatePeriodicReply(bool enable, DeviceCommandI
return returnvalue::OK;
}
// ReturnValue_t DeviceHandlerBase::setReplyDataset(DeviceCommandId_t replyId,
// void* dataSet/*TODO*/) {
// auto replyIter = deviceReplyMap.find(replyId);
// if (replyIter == deviceReplyMap.end()) {
// return returnvalue::FAILED;
// }
// replyIter->second.dataSet = dataSet;
// return returnvalue::OK;
// }
ReturnValue_t DeviceHandlerBase::setReplyDataset(DeviceCommandId_t replyId,
LocalPoolDataSetBase* dataSet) {
auto replyIter = deviceReplyMap.find(replyId);
if (replyIter == deviceReplyMap.end()) {
return returnvalue::FAILED;
}
replyIter->second.dataSet = dataSet;
return returnvalue::OK;
}
void DeviceHandlerBase::callChildStatemachine() {
if (mode == _MODE_START_UP) {
@ -574,15 +580,15 @@ void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) {
}
Clock::getUptime(&timeoutStart);
// if (mode == MODE_OFF and thermalSet != nullptr) { //TODO
// ReturnValue_t result = thermalSet->read();
// if (result == returnvalue::OK) {
// if (thermalSet->heaterRequest.value != ThermalComponentIF::STATE_REQUEST_IGNORE) {
// thermalSet->heaterRequest.value = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL;
// }
// thermalSet->heaterRequest.commit(PoolVariableIF::VALID);
// }
// }
if (mode == MODE_OFF and thermalSet != nullptr) {
ReturnValue_t result = thermalSet->read();
if (result == returnvalue::OK) {
if (thermalSet->heaterRequest.value != ThermalComponentIF::STATE_REQUEST_IGNORE) {
thermalSet->heaterRequest.value = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL;
}
thermalSet->heaterRequest.commit(PoolVariableIF::VALID);
}
}
/* TODO: This will probably be done by the LocalDataPoolManager now */
// changeHK(mode, submode, true);
}
@ -1071,14 +1077,14 @@ ReturnValue_t DeviceHandlerBase::checkModeCommand(Mode_t commandedMode, Submode_
}
if ((commandedMode == MODE_ON) && (mode == MODE_OFF) and (thermalSet != nullptr)) {
// ReturnValue_t result = thermalSet->read(); //TODO
// if (result == returnvalue::OK) {
// if ((thermalSet->heaterRequest.value != ThermalComponentIF::STATE_REQUEST_IGNORE) and
// (not ThermalComponentIF::isOperational(thermalSet->thermalState.value))) {
// triggerEvent(ThermalComponentIF::TEMP_NOT_IN_OP_RANGE, thermalSet->thermalState.value);
// return NON_OP_TEMPERATURE;
// }
// }
ReturnValue_t result = thermalSet->read();
if (result == returnvalue::OK) {
if ((thermalSet->heaterRequest.value != ThermalComponentIF::STATE_REQUEST_IGNORE) and
(not ThermalComponentIF::isOperational(thermalSet->thermalState.value))) {
triggerEvent(ThermalComponentIF::TEMP_NOT_IN_OP_RANGE, thermalSet->thermalState.value);
return NON_OP_TEMPERATURE;
}
}
}
return isModeCombinationValid(commandedMode, commandedSubmode);
@ -1130,15 +1136,15 @@ void DeviceHandlerBase::handleTransitionToOnMode(Mode_t commandedMode, Submode_t
// need to call it twice
childTransitionDelay = getTransitionDelayMs(_MODE_START_UP, MODE_ON);
triggerEvent(CHANGING_MODE, commandedMode, commandedSubmode);
// if (thermalSet != nullptr) { //TODO
// ReturnValue_t result = thermalSet->read();
// if (result == returnvalue::OK) {
// if (thermalSet->heaterRequest != ThermalComponentIF::STATE_REQUEST_IGNORE) {
// thermalSet->heaterRequest = ThermalComponentIF::STATE_REQUEST_OPERATIONAL;
// thermalSet->commit();
// }
// }
// }
if (thermalSet != nullptr) {
ReturnValue_t result = thermalSet->read();
if (result == returnvalue::OK) {
if (thermalSet->heaterRequest != ThermalComponentIF::STATE_REQUEST_IGNORE) {
thermalSet->heaterRequest = ThermalComponentIF::STATE_REQUEST_OPERATIONAL;
thermalSet->commit();
}
}
}
} else {
setTransition(MODE_ON, commandedSubmode);
}
@ -1308,23 +1314,22 @@ void DeviceHandlerBase::handleDeviceTm(const SerializeIF& dataSet, DeviceCommand
}
}
ActionHelper* DeviceHandlerBase::getActionHelper() { return &actionHelper; }
ReturnValue_t DeviceHandlerBase::executeAction(Action* action) {
ReturnValue_t DeviceHandlerBase::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size) {
ReturnValue_t result = acceptExternalDeviceCommands();
if (result != returnvalue::OK) {
return result;
}
DeviceCommandMap::iterator iter = deviceCommandMap.find(action->getId());
DeviceCommandMap::iterator iter = deviceCommandMap.find(actionId);
if (iter == deviceCommandMap.end()) {
result = COMMAND_NOT_SUPPORTED;
} else if (iter->second.isExecuting) {
result = COMMAND_ALREADY_SENT;
} else {
result = action->handle();
iter->second.sendReplyTo = commandedBy;
result = buildCommandFromCommand(actionId, data, size);
}
if (result == returnvalue::OK) {
iter->second.sendReplyTo = action->commandedBy;
iter->second.isExecuting = true;
cookieInfo.pendingCommand = iter;
cookieInfo.state = COOKIE_WRITE_READY;
@ -1454,12 +1459,24 @@ void DeviceHandlerBase::debugInterface(uint8_t positionTracker, object_id_t obje
void DeviceHandlerBase::performOperationHook() {}
ReturnValue_t DeviceHandlerBase::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) {
if (thermalSet != nullptr) {
localDataPoolMap.emplace(thermalSet->thermalStatePoolId,
new PoolEntry<DeviceHandlerIF::dh_thermal_state_t>);
localDataPoolMap.emplace(thermalSet->heaterRequestPoolId,
new PoolEntry<DeviceHandlerIF::dh_heater_request_t>);
}
return returnvalue::OK;
}
ReturnValue_t DeviceHandlerBase::initializeAfterTaskCreation() {
// In this function, the task handle should be valid if the task
// was implemented correctly. We still check to be 1000 % sure :-)
if (executingTask != nullptr) {
pstIntervalMs = executingTask->getPeriodMs();
}
this->poolManager.initializeAfterTaskCreation();
if (setStartupImmediately) {
startTransition(MODE_ON, SUBMODE_NONE);
@ -1467,10 +1484,21 @@ ReturnValue_t DeviceHandlerBase::initializeAfterTaskCreation() {
return returnvalue::OK;
}
LocalPoolDataSetBase* DeviceHandlerBase::getDataSetHandle(sid_t sid) {
auto iter = deviceReplyMap.find(sid.ownerSetId);
if (iter != deviceReplyMap.end()) {
return iter->second.dataSet;
} else {
return nullptr;
}
}
object_id_t DeviceHandlerBase::getObjectId() const { return SystemObject::getObjectId(); }
void DeviceHandlerBase::setStartUpImmediately() { this->setStartupImmediately = true; }
dur_millis_t DeviceHandlerBase::getPeriodicOperationFrequency() const { return pstIntervalMs; }
DeviceCommandId_t DeviceHandlerBase::getPendingCommand() const {
if (cookieInfo.pendingCommand != deviceCommandMap.end()) {
return cookieInfo.pendingCommand->first;
@ -1479,19 +1507,16 @@ DeviceCommandId_t DeviceHandlerBase::getPendingCommand() const {
}
void DeviceHandlerBase::setNormalDatapoolEntriesInvalid() {
// for (const auto& reply : deviceReplyMap) {
// if (reply.second.dataSet != nullptr) {
// PoolReadGuard pg(reply.second.dataSet);
// if (pg.getReadResult() == returnvalue::OK) {
// reply.second.dataSet->setValidity(false, true);
// }
// }
// }
for (const auto& reply : deviceReplyMap) {
if (reply.second.dataSet != nullptr) {
PoolReadGuard pg(reply.second.dataSet);
if (pg.getReadResult() == returnvalue::OK) {
reply.second.dataSet->setValidity(false, true);
}
}
}
}
DatapoolHelper* DeviceHandlerBase::getDatapoolHelper() { return &datapoolHelper; }
HousekeepingHelper* DeviceHandlerBase::getHousekeepingHelper() { return &datapoolHelper; }
void DeviceHandlerBase::printWarningOrError(sif::OutputTypes errorType, const char* functionName,
ReturnValue_t errorCode, const char* errorPrint) {
if (errorPrint == nullptr) {
@ -1532,6 +1557,8 @@ void DeviceHandlerBase::printWarningOrError(sif::OutputTypes errorType, const ch
}
}
LocalDataPoolManager* DeviceHandlerBase::getHkManagerHandle() { return &poolManager; }
MessageQueueId_t DeviceHandlerBase::getCommanderQueueId(DeviceCommandId_t replyId) const {
auto commandIter = deviceCommandMap.find(replyId);
if (commandIter == deviceCommandMap.end()) {
@ -1539,5 +1566,3 @@ MessageQueueId_t DeviceHandlerBase::getCommanderQueueId(DeviceCommandId_t replyI
}
return commandIter->second.sendReplyTo;
}
ModeHelper const* DeviceHandlerBase::getModeHelper() const { return &modeHelper; }

View File

@ -6,11 +6,12 @@
#include "DeviceCommunicationIF.h"
#include "DeviceHandlerFailureIsolation.h"
#include "DeviceHandlerIF.h"
#include "DeviceHandlerThermalSet.h"
#include "fsfw/action/ActionHelper.h"
#include "fsfw/action/HasActionsIF.h"
// #include "fsfw/datapool/PoolVariableIF.h"
#include "fsfw/datapool/HasDatapoolIF.h"
// #include "fsfw/datapoollocal/LocalDataPoolManager.h"
#include "fsfw/datapool/PoolVariableIF.h"
#include "fsfw/datapoollocal/HasLocalDataPoolIF.h"
#include "fsfw/datapoollocal/LocalDataPoolManager.h"
#include "fsfw/health/HealthHelper.h"
#include "fsfw/ipc/MessageQueueIF.h"
#include "fsfw/modes/HasModesIF.h"
@ -83,7 +84,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
public HasHealthIF,
public HasActionsIF,
public ReceivesParameterMessagesIF,
public HasDatapoolIF {
public HasLocalDataPoolIF {
friend void(Factory::setStaticFrameworkObjectIds)();
public:
@ -112,7 +113,10 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* @param thermalStatePoolId
* @param thermalRequestPoolId
*/
void setThermalStateRequestPoolIds(); // TODO
void setThermalStateRequestPoolIds(
lp_id_t thermalStatePoolId = DeviceHandlerIF::DEFAULT_THERMAL_STATE_POOL_ID,
lp_id_t thermalRequestPoolId = DeviceHandlerIF::DEFAULT_THERMAL_HEATING_REQUEST_POOL_ID,
uint32_t thermalSetId = DeviceHandlerIF::DEFAULT_THERMAL_SET_ID);
/**
* @brief Helper function to ease device handler development.
* This will instruct the transition to MODE_ON immediately
@ -196,14 +200,13 @@ class DeviceHandlerBase : public DeviceHandlerIF,
*/
virtual void setParentQueue(MessageQueueId_t parentQueueId);
/** @brief Implementations required for HasActionIF */
ActionHelper *getActionHelper() override;
ReturnValue_t executeAction(Action *action) override;
/** @brief Implementation required for HasActionIF */
ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t *data, size_t size) override;
Mode_t getTransitionSourceMode() const;
Submode_t getTransitionSourceSubMode() const;
void getMode(Mode_t *mode, Submode_t *submode) override;
ModeHelper const *getModeHelper() const override;
virtual void getMode(Mode_t *mode, Submode_t *submode);
HealthState getHealth();
ReturnValue_t setHealth(HealthState health);
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
@ -307,10 +310,35 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* - Anything else triggers an even with the returnvalue as a parameter
*/
virtual ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t *id) = 0;
/**
* @brief Build a device command packet from data supplied by a direct
* command (PUS Service 8)
* @details
* This will be called if an functional command via PUS Service 8 is received and is
* the primary interface for functional command instead of #executeAction for users. The
* supplied ActionId_t action ID will be converted to a DeviceCommandId_t command ID after
* an internal check whether the action ID is a key in the device command map.
*
* #rawPacket and #rawPacketLen should be set by this method to the packet to be sent.
* The existence of the command in the command map and the command size check against 0 are
* done by the base class.
*
* @param deviceCommand The command to build, already checked against deviceCommandMap
* @param commandData Pointer to the data from the direct command
* @param commandDataLen Length of commandData
* @return
* - @c returnvalue::OK to send command after #rawPacket and #rawPacketLen
* have been set.
* - @c HasActionsIF::EXECUTION_COMPLETE to generate a finish reply immediately. This can
* be used if no reply is expected
* - Anything else triggers an event with the return code as a parameter as well as a
* step reply failed with the return code
*/
virtual ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand,
const uint8_t *commandData,
size_t commandDataLen) = 0;
/* Reply handling */
// TODO add way to say, not enough data in buffer, try again later
// ComIF needs to decide if buffer will be appended or overwritten
/**
* @brief Scans a buffer for a valid reply.
* @details
@ -426,7 +454,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* - @c returnvalue::FAILED else.
*/
ReturnValue_t insertInCommandAndReplyMap(DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles,
void *replyDataSet = nullptr,
LocalPoolDataSetBase *replyDataSet = nullptr,
size_t replyLen = 0, bool periodic = false,
bool hasDifferentReplyId = false,
DeviceCommandId_t replyId = 0,
@ -447,7 +475,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* - @c returnvalue::FAILED else.
*/
ReturnValue_t insertInReplyMap(DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles,
void *dataSet = nullptr, size_t replyLen = 0,
LocalPoolDataSetBase *dataSet = nullptr, size_t replyLen = 0,
bool periodic = false, Countdown *countdown = nullptr);
/**
@ -495,7 +523,13 @@ class DeviceHandlerBase : public DeviceHandlerIF,
*/
ReturnValue_t updateReplyMapEntry(DeviceCommandId_t deviceReply, uint16_t delayCycles,
uint16_t maxDelayCycles, bool periodic = false);
/**
* @brief Can be used to set the dataset corresponding to a reply ID manually.
* @details
* Used by the local data pool manager.
*/
ReturnValue_t setReplyDataset(DeviceCommandId_t replyId, LocalPoolDataSetBase *dataset);
/**
* Get the time needed to transit from modeFrom to modeTo.
*
@ -514,7 +548,15 @@ class DeviceHandlerBase : public DeviceHandlerIF,
*/
virtual uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) = 0;
/* Functions used by the local data pool manager */
/**
* This function is used to initialize the local housekeeping pool
* entries. The default implementation leaves the pool empty.
* @param localDataPoolMap
* @return
*/
virtual ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) override;
/**
* @brief Set all datapool variables that are update periodically in
* normal mode invalid
@ -524,11 +566,16 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* variables inside the dataset to invalid. The user can override this
* method optionally.
*/
virtual void setNormalDatapoolEntriesInvalid(); //TODO
DatapoolHelper* getDatapoolHelper() override;
HousekeepingHelper* getHousekeepingHelper() override;
virtual void setNormalDatapoolEntriesInvalid();
/**
* @brief Get the dataset handle for a given SID.
* @details
* The default implementation will use the deviceCommandMap to look for the corresponding
* dataset handle. The user can override this function if this is not desired.
* @param sid
* @return
*/
virtual LocalPoolDataSetBase *getDataSetHandle(sid_t sid) override;
/* HasModesIF overrides */
virtual void startTransition(Mode_t mode, Submode_t submode) override;
@ -698,7 +745,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
/* Action helper for HasActionsIF */
ActionHelper actionHelper;
/* Housekeeping Manager */
DatapoolHelper datapoolHelper;
LocalDataPoolManager poolManager;
/**
* @brief Information about commands
@ -739,7 +786,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
//! The dataset used to access housekeeping data related to the
//! respective device reply. Will point to a dataset held by
//! the child handler (if one is specified)
// LocalPoolDataSetBase *dataSet = nullptr; TODO
LocalPoolDataSetBase *dataSet = nullptr;
//! The command that expects this reply.
DeviceCommandMap::iterator command;
//! Instead of using delayCycles to specify the maximum time to wait for the device reply, it
@ -771,7 +818,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
//! and to send replies.
MessageQueueIF *commandQueue = nullptr;
void *thermalSet = nullptr; //TODO
DeviceHandlerThermalSet *thermalSet = nullptr;
/**
* Optional Error code. Can be set in doStartUp(), doShutDown() and
@ -888,6 +935,12 @@ class DeviceHandlerBase : public DeviceHandlerIF,
*/
virtual void doOnActivity();
/**
* Required for HasLocalDataPoolIF, return a handle to the local pool manager.
* @return
*/
LocalDataPoolManager *getHkManagerHandle() override;
/**
* Returns the delay cycle count of a reply.
* A count != 0 indicates that the command is already executed.
@ -979,7 +1032,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* by #switches are on
* - @c PowerSwitchIF::SWITCH_OFF one of the switches specified by
* #switches are off
* - @c returnvalue::FAILED if an error occured
* - @c PowerSwitchIF::returnvalue::FAILED if an error occured
*/
ReturnValue_t getStateOfSwitches();
@ -1254,6 +1307,8 @@ class DeviceHandlerBase : public DeviceHandlerIF,
ReturnValue_t handleDeviceHandlerMessage(CommandMessage *message);
virtual dur_millis_t getPeriodicOperationFrequency() const override;
void parseReply(const uint8_t *receivedData, size_t receivedDataLen);
void handleTransitionToOnMode(Mode_t commandedMode, Submode_t commandedSubmode);

View File

@ -4,8 +4,7 @@
#include "fsfw/health/HealthTableIF.h"
#include "fsfw/modes/HasModesIF.h"
#include "fsfw/objectmanager/ObjectManager.h"
//#include "fsfw/power/Fuse.h"
#include <fsfw/power/PowerSwitchIF.h>
#include "fsfw/power/Fuse.h"
#include "fsfw/serviceinterface/ServiceInterfaceStream.h"
#include "fsfw/thermal/ThermalComponentIF.h"
@ -78,16 +77,16 @@ ReturnValue_t DeviceHandlerFailureIsolation::eventReceived(EventMessage* event)
}
}
break;
// case Fuse::FUSE_WENT_OFF:
// // Not so good, because PCDU reacted.
// case Fuse::POWER_ABOVE_HIGH_LIMIT:
// // Better, because software detected over-current.
// setFaulty(event->getEvent());
// break;
// case Fuse::POWER_BELOW_LOW_LIMIT:
// // Device might got stuck during boot, retry.
// handleRecovery(event->getEvent());
// break;
case Fuse::FUSE_WENT_OFF:
// Not so good, because PCDU reacted.
case Fuse::POWER_ABOVE_HIGH_LIMIT:
// Better, because software detected over-current.
setFaulty(event->getEvent());
break;
case Fuse::POWER_BELOW_LOW_LIMIT:
// Device might got stuck during boot, retry.
handleRecovery(event->getEvent());
break;
//****Thermal*****
case ThermalComponentIF::COMPONENT_TEMP_LOW:
case ThermalComponentIF::COMPONENT_TEMP_HIGH:

View File

@ -2,8 +2,8 @@
#define FSFW_DEVICEHANDLERS_DEVICEHANDLERIF_H_
#include "../action/HasActionsIF.h"
#include "../datapoollocal/localPoolDefinitions.h"
#include "../events/Event.h"
#include "../introspection/ClasslessEnum.h"
#include "../ipc/MessageQueueSenderIF.h"
#include "../modes/HasModesIF.h"
#include "DeviceHandlerMessage.h"
@ -37,30 +37,23 @@ class DeviceHandlerIF {
* The mode of the device itself is transparent to the user but related to the mode of the
* handler. MODE_ON and MODE_OFF are included in hasModesIF.h
*/
FSFW_CLASSLESS_ENUM(
DeviceHandlerMode, Mode_t,
//! The device is powered and ready to perform operations. In this mode, no
//! commands are sent by the device handler itself, but direct commands can be
//! commanded and will be executed/forwarded to the device
//! This is an alias of MODE_ON to have the FSFW_ENUM complete for introspection
((DEVICEHANDLER_MODE_ON, HasModesIF::MODE_ON, "On"))
//! The device is powered off. The only command accepted in this
//! mode is a mode change to on.
//! This is an alias of MODE_OFF to have the FSFW_ENUM complete for introspection
((DEVICEHANDLER_MODE_OFF, HasModesIF::MODE_OFF, "Off"))
//! The device is powered on and the device handler periodically sends
//! commands. The commands to be sent are selected by the handler
//! according to the submode.
((MODE_NORMAL, 2, "Normal"))
//! The device is powered on and ready to perform operations. In this mode,
//! raw commands can be sent. The device handler will send all replies
//! received from the command back to the commanding object as raw TM
((MODE_RAW, 3, "Raw"))
//! The device is shut down but the switch could not be turned off, so the
//! 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.
((MODE_ERROR_ON, 4, "Error")))
// MODE_ON = 0, //!< The device is powered and ready to perform operations. In this mode, no
// commands are sent by the device handler itself, but direct commands van be commanded and will
// be interpreted MODE_OFF = 1, //!< The device is powered off. The only command accepted in this
// mode is a mode change to on.
//! The device is powered on and the device handler periodically sends
//! commands. The commands to be sent are selected by the handler
//! according to the submode.
static const Mode_t MODE_NORMAL = 2;
//! The device is powered on and ready to perform operations. In this mode,
//! raw commands can be sent. The device handler will send all replies
//! received from the command back to the commanding object.
static const Mode_t MODE_RAW = 3;
//! The device is shut down but the switch could not be turned off, so the
//! 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.
@ -169,10 +162,10 @@ class DeviceHandlerIF {
NOTHING //!< Do nothing.
};
static constexpr uint32_t DEFAULT_THERMAL_SET_ID = 0; // TODO sid_t::INVALID_SET_ID - 1;
static constexpr uint32_t DEFAULT_THERMAL_SET_ID = sid_t::INVALID_SET_ID - 1;
static constexpr int DEFAULT_THERMAL_STATE_POOL_ID = 0; // TODOlocalpool::INVALID_LPID - 2;
static constexpr int DEFAULT_THERMAL_HEATING_REQUEST_POOL_ID = 0; // TODOlocalpool::INVALID_LPID - 1;
static constexpr lp_id_t DEFAULT_THERMAL_STATE_POOL_ID = localpool::INVALID_LPID - 2;
static constexpr lp_id_t DEFAULT_THERMAL_HEATING_REQUEST_POOL_ID = localpool::INVALID_LPID - 1;
/**
* Default Destructor

View File

@ -15,12 +15,11 @@ const LocalPool::LocalPoolConfig EventManager::poolConfig = {
{fsfwconfig::FSFW_EVENTMGMT_EVENTIDMATCHERS, sizeof(EventIdRangeMatcher)},
{fsfwconfig::FSFW_EVENTMGMR_RANGEMATCHERS, sizeof(ReporterRangeMatcher)}};
EventManager::EventManager(object_id_t setObjectId, uint32_t eventQueueDepth)
EventManager::EventManager(object_id_t setObjectId)
: SystemObject(setObjectId), factoryBackend(0, poolConfig, false, true) {
mutex = MutexFactory::instance()->createMutex();
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
eventReportQueue = QueueFactory::instance()->createMessageQueue(
eventQueueDepth, EventMessage::EVENT_MESSAGE_SIZE, &mqArgs);
eventReportQueue = QueueFactory::instance()->createMessageQueue(MAX_EVENTS_PER_CYCLE,
EventMessage::EVENT_MESSAGE_SIZE);
}
EventManager::~EventManager() {
@ -39,16 +38,6 @@ ReturnValue_t EventManager::performOperation(uint8_t opCode) {
if (result == returnvalue::OK) {
#if FSFW_OBJ_EVENT_TRANSLATION == 1
printEvent(&message);
#else
//TODO
sif::debug << "EventManager: ";
sif::debug << "0x" << std::hex << std::setw(8) << std::setfill('0') << message.getReporter()
<< std::setfill(' ') << std::dec;
sif::debug << " reported event with ID " << message.getEventId() << std::endl;
sif::debug << std::hex << "P1 Hex: 0x"
<< message.getParameter1() << " | P1 Dec: " << std::dec << message.getParameter1()
<< std::hex << " | P2 Hex: 0x" << message.getParameter2()
<< " | P2 Dec: " << std::dec << message.getParameter2() << std::endl;
#endif
notifyListeners(&message);
}
@ -58,20 +47,9 @@ ReturnValue_t EventManager::performOperation(uint8_t opCode) {
void EventManager::notifyListeners(EventMessage* message) {
lockMutex();
for (auto& listener : listenerList) {
if (listener.second.match(message)) {
ReturnValue_t result =
MessageQueueSenderIF::sendMessage(listener.first, message, message->getSender());
if (result != returnvalue::OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << std::hex << "EventManager::notifyListeners: MSG to 0x" << std::setfill('0')
<< std::setw(8) << listener.first << " failed with result 0x" << std::setw(4)
<< result << std::setfill(' ') << std::endl;
#else
sif::printError("Sending message to listener 0x%08x failed with result %04x\n",
listener.first, result);
#endif
}
for (auto iter = listenerList.begin(); iter != listenerList.end(); ++iter) {
if (iter->second.match(message)) {
MessageQueueSenderIF::sendMessage(iter->first, message, message->getSender());
}
}
unlockMutex();
@ -222,19 +200,4 @@ void EventManager::printUtility(sif::OutputTypes printType, EventMessage* messag
}
}
void EventManager::printListeners() {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "Event manager listener MQ IDs:" << std::setfill('0') << std::hex << std::endl;
for (auto& listener : listenerList) {
sif::info << "0x" << std::setw(8) << listener.first << std::endl;
}
sif::info << std::dec << std::setfill(' ');
#else
sif::printInfo("Event manager listener MQ IDs:\n");
for (auto& listener : listenerList) {
sif::printInfo("0x%08x\n", listener.first);
}
#endif
}
#endif /* FSFW_OBJ_EVENT_TRANSLATION == 1 */

View File

@ -21,7 +21,9 @@ extern const char* translateEvents(Event event);
class EventManager : public EventManagerIF, public ExecutableObjectIF, public SystemObject {
public:
EventManager(object_id_t setObjectId, uint32_t eventQueueDepth);
static const uint16_t MAX_EVENTS_PER_CYCLE = 80;
EventManager(object_id_t setObjectId);
virtual ~EventManager();
void setMutexTimeout(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs);
@ -42,7 +44,6 @@ class EventManager : public EventManagerIF, public ExecutableObjectIF, public Sy
object_id_t reporterFrom = 0, object_id_t reporterTo = 0,
bool reporterInverted = false);
ReturnValue_t performOperation(uint8_t opCode);
void printListeners();
protected:
MessageQueueIF* eventReportQueue = nullptr;

View File

@ -10,7 +10,7 @@ enum : uint8_t {
CDH = 28,
TCS_1 = 59,
PCDU_1 = 42,
POWER_SWITCH_IF = 43,
PCDU_2 = 43,
HEATER = 50,
T_SENSORS = 52,
FDIR = 70,
@ -33,7 +33,6 @@ enum : uint8_t {
PUS_SERVICE_23 = 103,
MGM_LIS3MDL = 106,
MGM_RM3100 = 107,
CFDP = 108,
FW_SUBSYSTEM_ID_RANGE
};

View File

@ -44,13 +44,13 @@ class Type : public SerializeIF {
static ActualType_t getActualType(uint8_t ptc, uint8_t pfc);
ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
Endianness streamEndianness) const override;
virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
Endianness streamEndianness) const override;
size_t getSerializedSize() const override;
virtual size_t getSerializedSize() const override;
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) override;
virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) override;
private:
ActualType_t actualType;

View File

@ -1,2 +1,2 @@
target_sources(${LIB_FSFW_NAME} PRIVATE HousekeepingHelper.cpp
HousekeepingSet.cpp )
target_sources(${LIB_FSFW_NAME} PRIVATE HousekeepingMessage.cpp
PeriodicHousekeepingHelper.cpp)

View File

@ -1,16 +0,0 @@
#pragma once
#include <fsfw/tmtc/FsfwProtocolHeader.h>
#include "HousekeepingHelper.h"
class GeneratesHousekeepingIF {
public:
static const uint8_t INTERFACE_ID = CLASS_ID::GENERATES_HOUSEKEEPING;
enum Functions : FsfwProtocolHeader::FunctionType_t { REPORT };
virtual ~GeneratesHousekeepingIF() = default;
virtual HousekeepingHelper* getHousekeepingHelper() = 0;
};

View File

@ -1,46 +0,0 @@
#include "HousekeepingHelper.h"
#include <fsfw/objectmanager/ObjectManager.h>
#include "GeneratesHousekeepingIF.h"
HousekeepingHelper::HousekeepingHelper(GeneratesHousekeepingIF* owner) : owner(owner) {}
ReturnValue_t HousekeepingHelper::initialize() {
tmManager = ObjectManager::instance()->get<TmManager>(objects::TM_MANAGER);
if (tmManager == nullptr) {
return returnvalue::FAILED;
}
return returnvalue::OK;
}
const HousekeepingSet* HousekeepingHelper::getHousekeepingSet(HousekeepingSetId_t id) {
auto iter = housekeepingSets.find(id);
if (iter == housekeepingSets.end()) {
return nullptr;
}
return iter->second;
}
void HousekeepingHelper::registerSet(HousekeepingSet* set) {
auto id = set->getId();
housekeepingSets.emplace(id, set);
}
ReturnValue_t HousekeepingHelper::reportHousekeeping(HousekeepingSet* set, const Action* action) {
SystemObjectIF* ownerAsObject = dynamic_cast<SystemObjectIF*>(owner);
if (ownerAsObject == nullptr) {
sif::error << "Duuuuuuuude, what the hell?" << std::endl;
return returnvalue::FAILED;
}
store_address_t tc;
size_t tcOffset = 0;
if (action != nullptr) {
tc = action->tc;
tcOffset = action->tcOffset;
}
return tmManager->sendTmPacket(ownerAsObject->getObjectId(),
GeneratesHousekeepingIF::INTERFACE_ID,
GeneratesHousekeepingIF::Functions::REPORT, set, tc, tcOffset);
}

View File

@ -1,36 +0,0 @@
#pragma once
#include <fsfw/returnvalues/returnvalue.h>
#include <fsfw/serialize/SerializeIF.h>
#include <fsfw/tmtc/TmManager.h>
#include <map>
#include "HousekeepingSet.h"
class HousekeepingHelper {
friend class HousekeepingSet;
public:
HousekeepingHelper(GeneratesHousekeepingIF* owner);
~HousekeepingHelper() = default;
const HousekeepingSet* getHousekeepingSet(HousekeepingSetId_t id);
const std::map<HousekeepingSetId_t, HousekeepingSet*>* getHousekeepingSets() const {
return &housekeepingSets;
}
ReturnValue_t initialize();
protected:
GeneratesHousekeepingIF* owner;
TmManager* tmManager = nullptr;
void registerSet(HousekeepingSet* set);
ReturnValue_t reportHousekeeping(HousekeepingSet* set, const Action* action = nullptr);
private:
std::map<HousekeepingSetId_t, HousekeepingSet*> housekeepingSets;
};

View File

@ -1,146 +0,0 @@
#include "HousekeepingSet.h"
#include <fsfw/datapool/DatasetEntryIF.h>
#include "GeneratesHousekeepingIF.h"
#ifdef FSFW_INTROSPECTION
HousekeepingSet::HousekeepingSet(GeneratesHousekeepingIF* owner, const EnumIF &id) {
if (owner != nullptr) {
helper = owner->getHousekeepingHelper();
helper->registerSet(this);
}
this->id = id.getValue();
description = id.getDescription();
}
const char* HousekeepingSet::getDescription() const { return description; }
#else
HousekeepingSet::HousekeepingSet(GeneratesHousekeepingIF* owner, HousekeepingSetId_t id) : id(id) {
if (owner != nullptr) {
helper = owner->getHousekeepingHelper();
helper->registerSet(this);
}
}
#endif
HousekeepingSet::~HousekeepingSet() {}
void HousekeepingSet::report(const Action* action) {
if (helper != nullptr) {
helper->reportHousekeeping(this, action);
}
}
ReturnValue_t HousekeepingSet::serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const {
ReturnValue_t result = SerializeAdapter::serialize(&id, buffer, size, maxSize, streamEndianness);
if (result != returnvalue::OK) {
return result;
}
for (auto parameter : parameterList) {
result = parameter->serialize(buffer, size, maxSize, streamEndianness);
if (result != returnvalue::OK) {
return result;
}
}
// Fill valid flags
size_t index = 0;
for (auto parameter : parameterList) {
size_t byteIndex = index / 8;
size_t bitIndex = index % 8;
if (*size + byteIndex > maxSize) { // TODO audition me
return SerializeIF::STREAM_TOO_SHORT;
}
/**
* check if the parameter is a datasetParameter which knows its validity
* If not, just set to valid
*/
DatasetEntryIF* dataSetParameter = dynamic_cast<DatasetEntryIF*>(parameter);
if (dataSetParameter != nullptr) {
if (dataSetParameter->getValid()) {
(*buffer)[byteIndex] |= (1 << bitIndex);
} else {
(*buffer)[byteIndex] &= ~(1 << bitIndex);
}
} else {
(*buffer)[byteIndex] |= (1 << bitIndex);
}
index++;
}
*size += (parameterList.size() - 1) / 8 + 1;
if (*size > maxSize) {
// how did we end up here
return SerializeIF::STREAM_TOO_SHORT;
}
*buffer += (parameterList.size() - 1) / 8 + 1;
return returnvalue::OK;
}
size_t HousekeepingSet::getSerializedSize() const {
size_t size = SerializeAdapter::getSerializedSize(&id);
for (auto parameter : parameterList) {
size += parameter->getSerializedSize();
}
const size_t validBytes = (parameterList.size() - 1) / 8 + 1;
size += validBytes;
return size;
}
ReturnValue_t HousekeepingSet::deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) {
ReturnValue_t result = returnvalue::OK;
/**
* When deserializing, the id needs to be deserialized first, to find the correct class to
* deserialize with. Consequentely, it is assumed, that the pointer was already advanced
*
* SerializeAdapter::deSerialize(&id, buffer, size, streamEndianness); if (result !=
*/
for (auto parameter : *getParameters()) {
result = parameter->deSerialize(buffer, size, streamEndianness);
if (result != returnvalue::OK) {
return result;
}
}
// read valid flags
size_t index = 0;
for (auto parameter : parameterList) {
size_t byteIndex = index / 8;
size_t bitIndex = index % 8;
if (byteIndex > *size) { // TODO audition me
return SerializeIF::BUFFER_TOO_SHORT;
}
/**
* check if the parameter is a datasetParameter which knows its validity
* If not, just set to valid
*/
DatasetEntryIF* dataSetParameter = dynamic_cast<DatasetEntryIF*>(parameter);
if (dataSetParameter != nullptr) {
bool valid = ((*buffer)[byteIndex] & (1 << bitIndex)) != 0;
dataSetParameter->setValid(valid);
}
index++;
}
if (*size < (parameterList.size() - 1) / 8 + 1) {
// how did we end up here
return SerializeIF::BUFFER_TOO_SHORT;
}
*size -= (parameterList.size() - 1) / 8 + 1;
*buffer += (parameterList.size() - 1) / 8 + 1;
return returnvalue::OK;
}
void HousekeepingSet::registerParameter(ParameterIF* parameter) {
parameterList.push_back(parameter);
}
std::vector<ParameterIF*> const* HousekeepingSet::getParameters() const { return &parameterList; }

View File

@ -1,54 +0,0 @@
#pragma once
#include <fsfw/action/Action.h>
#include <fsfw/introspection/Enum.h>
#include <fsfw/introspection/HasTmTcParametersIF.h>
#include <fsfw/serialize/SerializeIF.h>
#include <cstdint>
class HousekeepingHelper;
class GeneratesHousekeepingIF;
using HousekeepingSetId_t = uint32_t;
class HousekeepingSet : public HasTmTcParametersIF, public SerializeIF {
friend class ParameterIF;
public:
#ifdef FSFW_INTROSPECTION
HousekeepingSet(GeneratesHousekeepingIF* owner, const EnumIF &id);
#else
HousekeepingSet(GeneratesHousekeepingIF* owner, HousekeepingSetId_t id);
#endif
virtual ~HousekeepingSet();
HousekeepingSetId_t getId() const { return id; }
virtual void report(const Action* action = nullptr);
std::vector<ParameterIF*> const* getParameters() const override;
#ifdef FSFW_INTROSPECTION
const char* getDescription() const;
#endif
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const override;
size_t getSerializedSize() const override;
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) override;
protected:
HousekeepingHelper* helper = nullptr;
HousekeepingSetId_t id;
#ifdef FSFW_INTROSPECTION
const char* description;
#endif
std::vector<ParameterIF*> parameterList;
void registerParameter(ParameterIF* parameter) override;
};

View File

@ -54,8 +54,8 @@ class HousekeepingSnapshot : public SerializeIF {
HousekeepingSnapshot(uint8_t* timeStamp, size_t timeStampSize, LocalPoolObjectBase* dataSetPtr)
: timeStamp(timeStamp), timeStampSize(timeStampSize), updateData(dataSetPtr){};
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const {
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const {
if (timeStamp != nullptr) {
/* Endianness will always be MACHINE, so we can simply use memcpy
here. */
@ -70,15 +70,15 @@ class HousekeepingSnapshot : public SerializeIF {
return updateData->serialize(buffer, size, maxSize, streamEndianness);
}
size_t getSerializedSize() const {
virtual size_t getSerializedSize() const {
if (updateData == nullptr) {
return 0;
}
return timeStampSize + updateData->getSerializedSize();
}
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
SerializeIF::Endianness streamEndianness) override {
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
SerializeIF::Endianness streamEndianness) override {
if (*size < timeStampSize) {
return SerializeIF::STREAM_TOO_SHORT;
}

View File

@ -1,22 +1,22 @@
#ifndef FSFW_INTERNALERROR_INTERNALERRORDATASET_H_
#define FSFW_INTERNALERROR_INTERNALERRORDATASET_H_
#include <cstdint>
#include <fsfw/objectmanager/SystemObjectIF.h>
#include <fsfw/datapoollocal/LocalPoolVariable.h>
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
enum errorPoolIds { TM_HITS, QUEUE_HITS, STORE_HITS };
class InternalErrorDataset {
class InternalErrorDataset : public StaticLocalDataSet<3 * sizeof(uint32_t)> {
public:
static constexpr uint8_t ERROR_SET_ID = 0;
InternalErrorDataset(void* owner) {}
InternalErrorDataset(HasLocalDataPoolIF* owner) : StaticLocalDataSet(owner, ERROR_SET_ID) {}
InternalErrorDataset(object_id_t objectId) {}
InternalErrorDataset(object_id_t objectId) : StaticLocalDataSet(sid_t(objectId, ERROR_SET_ID)) {}
// lp_var_t<uint32_t> tmHits = lp_var_t<uint32_t>(sid.objectId, TM_HITS, this);
// lp_var_t<uint32_t> queueHits = lp_var_t<uint32_t>(sid.objectId, QUEUE_HITS, this);
// lp_var_t<uint32_t> storeHits = lp_var_t<uint32_t>(sid.objectId, STORE_HITS, this);
lp_var_t<uint32_t> tmHits = lp_var_t<uint32_t>(sid.objectId, TM_HITS, this);
lp_var_t<uint32_t> queueHits = lp_var_t<uint32_t>(sid.objectId, QUEUE_HITS, this);
lp_var_t<uint32_t> storeHits = lp_var_t<uint32_t>(sid.objectId, STORE_HITS, this);
};
#endif /* FSFW_INTERNALERROR_INTERNALERRORDATASET_H_ */

View File

@ -1,17 +1,22 @@
#include "fsfw/internalerror/InternalErrorReporter.h"
#include "fsfw/datapool/PoolReadGuard.h"
#include "fsfw/ipc/MutexFactory.h"
#include "fsfw/ipc/QueueFactory.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth)
: SystemObject(setObjectId),
poolManager(this, commandQueue),
internalErrorSid(setObjectId, InternalErrorDataset::ERROR_SET_ID),
internalErrorDataset(this) {
commandQueue = QueueFactory::instance()->createMessageQueue(messageQueueDepth);
mutex = MutexFactory::instance()->createMutex();
}
InternalErrorReporter::~InternalErrorReporter() {
MutexFactory::instance()->deleteMutex(mutex);
QueueFactory::instance()->deleteMessageQueue(commandQueue);
}
void InternalErrorReporter::setDiagnosticPrintout(bool enable) {
@ -19,6 +24,12 @@ void InternalErrorReporter::setDiagnosticPrintout(bool enable) {
}
ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) {
CommandMessage message;
ReturnValue_t result = commandQueue->receiveMessage(&message);
if (result != MessageQueueIF::EMPTY) {
poolManager.handleHousekeepingMessage(&message);
}
uint32_t newQueueHits = getAndResetQueueHits();
uint32_t newTmHits = getAndResetTmHits();
uint32_t newStoreHits = getAndResetStoreHits();
@ -42,19 +53,20 @@ ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) {
}
#endif
// {
// PoolReadGuard readGuard(&internalErrorDataset);
// if (readGuard.getReadResult() == returnvalue::OK) {
// internalErrorDataset.queueHits.value += newQueueHits;
// internalErrorDataset.storeHits.value += newStoreHits;
// internalErrorDataset.tmHits.value += newTmHits;
// internalErrorDataset.setValidity(true, true);
// if ((newQueueHits != 0) or (newStoreHits != 0) or (newTmHits != 0)) {
// internalErrorDataset.setChanged(true);
// }
// }
// }
{
PoolReadGuard readGuard(&internalErrorDataset);
if (readGuard.getReadResult() == returnvalue::OK) {
internalErrorDataset.queueHits.value += newQueueHits;
internalErrorDataset.storeHits.value += newStoreHits;
internalErrorDataset.tmHits.value += newTmHits;
internalErrorDataset.setValidity(true, true);
if ((newQueueHits != 0) or (newStoreHits != 0) or (newTmHits != 0)) {
internalErrorDataset.setChanged(true);
}
}
}
poolManager.performHkOperation();
return returnvalue::OK;
}
@ -111,15 +123,47 @@ void InternalErrorReporter::incrementStoreHits() {
object_id_t InternalErrorReporter::getObjectId() const { return SystemObject::getObjectId(); }
// MessageQueueId_t InternalErrorReporter::getCommandQueue() const {
// return this->commandQueue->getId();
// }
MessageQueueId_t InternalErrorReporter::getCommandQueue() const {
return this->commandQueue->getId();
}
ReturnValue_t InternalErrorReporter::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) {
localDataPoolMap.emplace(errorPoolIds::TM_HITS, &tmHitsEntry);
localDataPoolMap.emplace(errorPoolIds::QUEUE_HITS, &queueHitsEntry);
localDataPoolMap.emplace(errorPoolIds::STORE_HITS, &storeHitsEntry);
poolManager.subscribeForDiagPeriodicPacket(subdp::DiagnosticsHkPeriodicParams(
internalErrorSid, false,
static_cast<float>(getPeriodicOperationFrequency()) / static_cast<float>(1000.0)));
internalErrorDataset.setValidity(true, true);
return returnvalue::OK;
}
dur_millis_t InternalErrorReporter::getPeriodicOperationFrequency() const {
return this->executingTask->getPeriodMs();
}
LocalPoolDataSetBase *InternalErrorReporter::getDataSetHandle(sid_t sid) {
return &internalErrorDataset;
}
void InternalErrorReporter::setTaskIF(PeriodicTaskIF *task) { this->executingTask = task; }
ReturnValue_t InternalErrorReporter::initialize() {
ReturnValue_t result = poolManager.initialize(commandQueue);
if (result != returnvalue::OK) {
return result;
}
return SystemObject::initialize();
}
ReturnValue_t InternalErrorReporter::initializeAfterTaskCreation() {
return poolManager.initializeAfterTaskCreation();
}
void InternalErrorReporter::setMutexTimeout(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
this->timeoutType = timeoutType;
this->timeoutMs = timeoutMs;
}
LocalDataPoolManager *InternalErrorReporter::getHkManagerHandle() { return &poolManager; }

Some files were not shown because too many files have changed in this diff Show More