Compare commits

..

25 Commits

Author SHA1 Message Date
39310c3fad Merge branch 'service_11_bugfixes' into mueller/new-cfdp-update-with-handlers 2023-01-13 11:15:50 +01:00
d16c5024dc small include improvement 2023-01-13 11:15:36 +01:00
bf311757a2 Merge branch 'service_11_bugfixes' into mueller/new-cfdp-update-with-handlers 2023-01-13 10:59:48 +01:00
a4531e4ced typo 2023-01-13 10:59:39 +01:00
cbe1b65a33 Merge branch 'service_11_bugfixes' into mueller/new-cfdp-update-with-handlers 2023-01-13 10:56:24 +01:00
80f0060cd2 Merge remote-tracking branch 'origin/development' into mueller/new-cfdp-update-with-handlers 2023-01-13 10:56:16 +01:00
97c629ad84 update changelog 2023-01-13 10:53:36 +01:00
bf12f284fa add size and crc check for contained TC 2023-01-13 10:53:04 +01:00
8589f4d63a Merge pull request 'updates for source sequence counter' (#714) from eive/fsfw:source_seq_counter_update into development
Reviewed-on: fsfw/fsfw#714
2022-12-19 15:00:28 +01:00
ca80589233 make get const 2022-12-19 14:58:08 +01:00
f2ebaed092 Merge pull request 'vec getter, reset for content' (#716) from eive/fsfw:get_cmd_exec_read_buf into development
Reviewed-on: fsfw/fsfw#716
2022-12-19 14:56:11 +01:00
f0b89e98df Merge pull request 'printout handling improvements' (#717) from eive/fsfw:i2c_printout_improvements into development
Reviewed-on: fsfw/fsfw#717
2022-12-19 14:45:04 +01:00
5557d95994 Merge branch 'development' into i2c_printout_improvements 2022-12-05 14:20:58 +01:00
fc24c9b5d8 Merge branch 'development' into get_cmd_exec_read_buf 2022-12-05 14:20:52 +01:00
7ef69c839c Merge pull request 'small fix to allow teardown handling' (#713) from eive/fsfw:mueller/shutdown_for_failed_to_on_transition into development
Reviewed-on: fsfw/fsfw#713
2022-11-28 14:30:15 +01:00
9b798d798e Merge pull request 'DLE parser' (#711) from eive/fsfw:mueller/dle_parser into development
Reviewed-on: fsfw/fsfw#711
2022-11-28 14:13:18 +01:00
b13453f46b vec getter, reset for content 2022-11-28 08:43:54 +01:00
d0e322d7e2 printout handling improvements 2022-11-28 08:42:08 +01:00
ecde164f68 updates for source sequence counter 2022-11-28 08:30:45 +01:00
50930b41ba Merge remote-tracking branch 'upstream/development' into mueller/dle_parser 2022-11-28 08:27:24 +01:00
bf4ca56658 Merge branch 'development' into mueller/shutdown_for_failed_to_on_transition 2022-11-21 15:29:11 +01:00
16ffa00155 Merge branch 'development' into mueller/dle_parser 2022-11-21 15:28:34 +01:00
f05295bada small fix to allow teardown handling 2022-11-17 15:16:29 +01:00
8199b8f359 bump changelog 2022-11-15 11:45:39 +01:00
9483c2809d DLE parser 2022-11-15 11:26:53 +01:00
102 changed files with 758 additions and 1293 deletions

View File

@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## Fixes
- TC Scheduler Service 11: Add size and CRC check for contained TC.
- Only delete health table entry in `HealthHelper` destructor if
health table was set.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/710/files
@ -27,6 +28,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## Added
- `DleParser` helper class to parse DLE encoded packets from a byte stream.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/711
- `UioMapper` is able to resolve symlinks now.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/709
- Add new `UnsignedByteField` class
@ -231,6 +234,7 @@ https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/593
- https://gitlab.kitware.com/cmake/cmake/-/issues/21696
Easiest solution for now: Keep this option OFF by default.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/616
- Linux HAL: Add wiretapping option for I2C. Enabled with `FSFW_HAL_I2C_WIRETAPPING` defined to 1
- Dedicated Version class and constant `fsfw::FSFW_VERSION` containing version information
inside `fsfw/version.h`
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/559
@ -245,17 +249,6 @@ https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/593
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/590
- `Subsystem`: New API to add table and sequence entries
## HAL
- SPI: Cache the SPI device in the communication interface. Architecturally, this makes a
lot more sense because each ComIF should be responsible for one SPI bus.
- SPI: Move the empty transfer to update the line polarity to separate function. This means
it is not automatically called when calling the setter function for SPI speed and mode.
The user should call this function after locking the CS mutex if multiple SPI devices with
differing speeds and modes are attached to one bus.
- SPI: Getter functions for SPI speed and mode.
- I2C: Add wiretapping option for I2C. Enabled with `FSFW_HAL_I2C_WIRETAPPING` defined to 1.
## Fixed
- TCP TMTC Server: `MutexGuard` was not created properly in

View File

@ -196,7 +196,7 @@ message(
)
# Check whether the user has already installed ETL first
find_package(${FSFW_ETL_LIB_NAME} ${FSFW_ETL_LIB_MAJOR_VERSION} CONFIG QUIET)
find_package(${FSFW_ETL_LIB_NAME} ${FSFW_ETL_LIB_MAJOR_VERSION} QUIET)
# Not installed, so use FetchContent to download and provide etl
if(NOT ${FSFW_ETL_LIB_NAME}_FOUND)
message(

View File

@ -51,10 +51,7 @@ exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
html_theme = "alabaster"
html_theme_options = {
"extra_nav_links": {
"Impressum": "https://www.uni-stuttgart.de/impressum",
"Datenschutz": "https://info.irs.uni-stuttgart.de/datenschutz/datenschutzWebmit.html",
}
"extra_nav_links": {"Impressum" : "https://www.uni-stuttgart.de/impressum", "Datenschutz": "https://info.irs.uni-stuttgart.de/datenschutz/datenschutzWebmit.html"}
}

View File

@ -16,8 +16,8 @@ class CommandActionHelper {
public:
explicit CommandActionHelper(CommandsActionsIF* owner);
virtual ~CommandActionHelper();
ReturnValue_t commandAction(object_id_t commandTo, ActionId_t actionId,
const uint8_t* data = nullptr, uint32_t size = 0);
ReturnValue_t commandAction(object_id_t commandTo, ActionId_t actionId, const uint8_t* data,
uint32_t size);
ReturnValue_t commandAction(object_id_t commandTo, ActionId_t actionId, SerializeIF* data);
ReturnValue_t initialize();
ReturnValue_t handleReply(CommandMessage* reply);

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

@ -4,31 +4,48 @@
#include "fsfw/ipc/QueueFactory.h"
#include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/subsystem/SubsystemBase.h"
#include "fsfw/subsystem/helper.h"
ControllerBase::ControllerBase(object_id_t setObjectId, size_t commandQueueDepth)
ControllerBase::ControllerBase(object_id_t setObjectId, object_id_t parentId,
size_t commandQueueDepth)
: SystemObject(setObjectId),
parentId(parentId),
mode(MODE_OFF),
submode(SUBMODE_NONE),
modeHelper(this),
healthHelper(this, setObjectId) {
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
commandQueue = QueueFactory::instance()->createMessageQueue(
commandQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
commandQueue = QueueFactory::instance()->createMessageQueue(commandQueueDepth);
}
ControllerBase::~ControllerBase() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }
ReturnValue_t ControllerBase::initialize() {
ReturnValue_t result = modeHelper.initialize();
ReturnValue_t result = SystemObject::initialize();
if (result != returnvalue::OK) {
return result;
}
result = healthHelper.initialize();
MessageQueueId_t parentQueue = 0;
if (parentId != objects::NO_OBJECT) {
auto* parent = ObjectManager::instance()->get<SubsystemBase>(parentId);
if (parent == nullptr) {
return returnvalue::FAILED;
}
parentQueue = parent->getCommandQueue();
parent->registerChild(getObjectId());
}
result = healthHelper.initialize(parentQueue);
if (result != returnvalue::OK) {
return result;
}
return SystemObject::initialize();
result = modeHelper.initialize(parentQueue);
if (result != returnvalue::OK) {
return result;
}
return returnvalue::OK;
}
MessageQueueId_t ControllerBase::getCommandQueue() const { return commandQueue->getId(); }
@ -101,13 +118,3 @@ void ControllerBase::setTaskIF(PeriodicTaskIF* task_) { executingTask = task_; }
void ControllerBase::changeHK(Mode_t mode_, Submode_t submode_, bool enable) {}
ReturnValue_t ControllerBase::initializeAfterTaskCreation() { return returnvalue::OK; }
const HasHealthIF* ControllerBase::getOptHealthIF() const { return this; }
const HasModesIF& ControllerBase::getModeIF() const { return *this; }
ModeTreeChildIF& ControllerBase::getModeTreeChildIF() { return *this; }
ReturnValue_t ControllerBase::connectModeTreeParent(HasModeTreeChildrenIF& parent) {
return modetree::connectModeTreeParent(parent, *this, healthHelper, modeHelper);
}

View File

@ -6,9 +6,6 @@
#include "fsfw/modes/HasModesIF.h"
#include "fsfw/modes/ModeHelper.h"
#include "fsfw/objectmanager/SystemObject.h"
#include "fsfw/subsystem/HasModeTreeChildrenIF.h"
#include "fsfw/subsystem/ModeTreeChildIF.h"
#include "fsfw/subsystem/ModeTreeConnectionIF.h"
#include "fsfw/tasks/ExecutableObjectIF.h"
#include "fsfw/tasks/PeriodicTaskIF.h"
@ -21,18 +18,13 @@
class ControllerBase : public HasModesIF,
public HasHealthIF,
public ExecutableObjectIF,
public ModeTreeChildIF,
public ModeTreeConnectionIF,
public SystemObject {
public:
static const Mode_t MODE_NORMAL = 2;
ControllerBase(object_id_t setObjectId, size_t commandQueueDepth = 3);
ControllerBase(object_id_t setObjectId, object_id_t parentId, size_t commandQueueDepth = 3);
~ControllerBase() override;
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF &parent) override;
ModeTreeChildIF &getModeTreeChildIF() override;
/** SystemObject override */
ReturnValue_t initialize() override;
@ -46,8 +38,6 @@ class ControllerBase : public HasModesIF,
ReturnValue_t performOperation(uint8_t opCode) override;
void setTaskIF(PeriodicTaskIF *task) override;
ReturnValue_t initializeAfterTaskCreation() override;
const HasHealthIF *getOptHealthIF() const override;
const HasModesIF &getModeIF() const override;
protected:
/**
@ -66,6 +56,8 @@ class ControllerBase : public HasModesIF,
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode) override = 0;
const object_id_t parentId;
Mode_t mode;
Submode_t submode;

View File

@ -1,7 +1,8 @@
#include "fsfw/controller/ExtendedControllerBase.h"
ExtendedControllerBase::ExtendedControllerBase(object_id_t objectId, size_t commandQueueDepth)
: ControllerBase(objectId, commandQueueDepth),
ExtendedControllerBase::ExtendedControllerBase(object_id_t objectId, object_id_t parentId,
size_t commandQueueDepth)
: ControllerBase(objectId, parentId, commandQueueDepth),
poolManager(this, commandQueue),
actionHelper(this, commandQueue) {}

View File

@ -17,7 +17,7 @@ class ExtendedControllerBase : public ControllerBase,
public HasActionsIF,
public HasLocalDataPoolIF {
public:
ExtendedControllerBase(object_id_t objectId, size_t commandQueueDepth = 3);
ExtendedControllerBase(object_id_t objectId, object_id_t parentId, size_t commandQueueDepth = 3);
~ExtendedControllerBase() override;
/* SystemObjectIF overrides */

View File

@ -570,10 +570,6 @@ ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage(CommandMessage* me
CommandMessage reply;
if (result != returnvalue::OK) {
if (result == WRONG_HK_PACKET_TYPE) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "handleHousekeepingMessage",
WRONG_HK_PACKET_TYPE);
}
HousekeepingMessage::setHkRequestFailureReply(&reply, sid, result);
} else {
HousekeepingMessage::setHkRequestSuccessReply(&reply, sid);
@ -829,8 +825,6 @@ void LocalDataPoolManager::printWarningOrError(sif::OutputTypes outputType,
errorPrint = "Dataset not found";
} else if (error == POOLOBJECT_NOT_FOUND) {
errorPrint = "Pool Object not found";
} else if (error == WRONG_HK_PACKET_TYPE) {
errorPrint = "Wrong Packet Type";
} else if (error == returnvalue::FAILED) {
if (outputType == sif::OutputTypes::OUT_WARNING) {
errorPrint = "Generic Warning";

View File

@ -162,7 +162,6 @@ class LocalPoolDataSetBase : public PoolDataSetBase, public MarkChangedIF {
object_id_t getCreatorObjectId();
bool getReportingEnabled() const;
void setReportingEnabled(bool enabled);
/**
* Returns the current periodic HK generation interval this set
@ -190,6 +189,7 @@ class LocalPoolDataSetBase : public PoolDataSetBase, public MarkChangedIF {
* Used for periodic generation.
*/
bool reportingEnabled = false;
void setReportingEnabled(bool enabled);
void initializePeriodicHelper(float collectionInterval, dur_millis_t minimumPeriodicInterval,
uint8_t nonDiagIntervalFactor = 5);

View File

@ -1,7 +1,7 @@
#include "fsfw/devicehandlers/AssemblyBase.h"
AssemblyBase::AssemblyBase(object_id_t objectId, uint16_t commandQueueDepth)
: SubsystemBase(objectId, MODE_OFF, commandQueueDepth),
AssemblyBase::AssemblyBase(object_id_t objectId, object_id_t parentId, uint16_t commandQueueDepth)
: SubsystemBase(objectId, parentId, MODE_OFF, commandQueueDepth),
internalState(STATE_NONE),
recoveryState(RECOVERY_IDLE),
recoveringDevice(childrenMap.end()),
@ -26,7 +26,11 @@ void AssemblyBase::performChildOperation() {
void AssemblyBase::startTransition(Mode_t mode, Submode_t submode) {
doStartTransition(mode, submode);
triggerModeHelperEvents(mode, submode);
if (modeHelper.isForced()) {
triggerEvent(FORCING_MODE, mode, submode);
} else {
triggerEvent(CHANGING_MODE, mode, submode);
}
}
void AssemblyBase::doStartTransition(Mode_t mode, Submode_t submode) {
@ -73,10 +77,9 @@ bool AssemblyBase::handleChildrenChangedHealth() {
}
HealthState healthState = healthHelper.healthTable->getHealth(iter->first);
if (healthState == HasHealthIF::NEEDS_RECOVERY) {
triggerEvent(TRYING_RECOVERY, iter->first, 0);
triggerEvent(TRYING_RECOVERY);
recoveryState = RECOVERY_STARTED;
recoveringDevice = iter;
// The user needs to take care of commanding the children off in commandChildren
doStartTransition(targetMode, targetSubmode);
} else {
triggerEvent(CHILD_CHANGED_HEALTH);
@ -225,9 +228,6 @@ ReturnValue_t AssemblyBase::handleHealthReply(CommandMessage* message) {
bool AssemblyBase::checkAndHandleRecovery() {
switch (recoveryState) {
case RECOVERY_STARTED:
// The recovery was already start in #handleChildrenChangedHealth and we just need
// to wait for an off time period.
// TODO: make time period configurable
recoveryState = RECOVERY_WAIT;
recoveryOffTimer.resetTimer();
return true;
@ -266,11 +266,3 @@ void AssemblyBase::overwriteDeviceHealth(object_id_t objectId, HasHealthIF::Heal
modeHelper.setForced(true);
sendHealthCommand(childrenMap[objectId].commandQueue, EXTERNAL_CONTROL);
}
void AssemblyBase::triggerModeHelperEvents(Mode_t mode, Submode_t submode) {
if (modeHelper.isForced()) {
triggerEvent(FORCING_MODE, mode, submode);
} else {
triggerEvent(CHANGING_MODE, mode, submode);
}
}

View File

@ -12,8 +12,7 @@
* Documentation: Dissertation Baetz p.156, 157.
*
* This class reduces the complexity of controller components which would
* otherwise be needed for the handling of redundant devices. However, it can also be used to
* manage the mode keeping and recovery of non-redundant devices
* otherwise be needed for the handling of redundant devices.
*
* The template class monitors mode and health state of its children
* and checks availability of devices on every detected change.
@ -27,9 +26,11 @@
*
* Important:
*
* The implementation must call #registerChild for all commanded children during initialization.
* The implementation must call registerChild(object_id_t child)
* for all commanded children during initialization.
* The implementation must call the initialization function of the base class.
* (This will call the function in SubsystemBase)
*
*/
class AssemblyBase : public SubsystemBase {
public:
@ -41,15 +42,14 @@ class AssemblyBase : public SubsystemBase {
static const ReturnValue_t NEED_TO_CHANGE_HEALTH = MAKE_RETURN_CODE(0x05);
static const ReturnValue_t NOT_ENOUGH_CHILDREN_IN_CORRECT_STATE = MAKE_RETURN_CODE(0xa1);
AssemblyBase(object_id_t objectId, uint16_t commandQueueDepth = 8);
AssemblyBase(object_id_t objectId, object_id_t parentId, uint16_t commandQueueDepth = 8);
virtual ~AssemblyBase();
protected:
/**
* Command children to reach [mode,submode] combination. Can be done by setting
* #commandsOutstanding correctly, or using #executeTable. In case of an FDIR recovery,
* the user needs to ensure that the target devices are healthy. If a device is not healthy,
* a recovery might be on-going and the device needs to be commanded to off first.
* Command children to reach [mode,submode] combination
* Can be done by setting #commandsOutstanding correctly,
* or using executeTable()
* @param mode
* @param submode
* @return
@ -120,19 +120,8 @@ class AssemblyBase : public SubsystemBase {
virtual ReturnValue_t handleHealthReply(CommandMessage *message);
/**
* @brief Default periodic handler
* @details
* This is the default periodic handler which will be called by the SubsystemBase
* performOperation. It performs the child transitions or reacts to changed health/mode states
* of children objects
*/
virtual void performChildOperation() override;
virtual void performChildOperation();
/**
* This function handles changed mode or health states of children
* @return
*/
bool handleChildrenChanged();
/**
@ -145,37 +134,12 @@ class AssemblyBase : public SubsystemBase {
bool handleChildrenChangedHealth();
/**
* Core transition handler. The default implementation will only do something if
* #commandsOutstanding is smaller or equal to zero, which means that all mode commands
* from the #doPerformTransition call were executed successfully.
*
* Unless a second step was requested, the function will then use #checkChildrenState to
* determine whether the target mode was reached.
*
* There is some special handling for certain (internal) modes:
* - A second step is necessary. #commandChildren will be performed again
* - The device health was overwritten. #commandChildren will be called
* - A recovery is ongoing. #checkAndHandleRecovery will be called.
*/
virtual void handleChildrenTransition();
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, uint32_t *msToReachTheMode);
/**
* Calls #doStartTransition and triggers an informative event as well that the mode will
* change
* @param mode
* @param submode
*/
virtual void startTransition(Mode_t mode, Submode_t submode);
/**
* This function starts the transition by setting the internal #targetSubmode and #targetMode
* variables and then calling the #commandChildren function.
* @param mode
* @param submode
*/
virtual void doStartTransition(Mode_t mode, Submode_t submode);
virtual bool isInTransition();
@ -196,7 +160,7 @@ class AssemblyBase : public SubsystemBase {
* Manages recovery of a device
* @return true if recovery is still ongoing, false else.
*/
virtual bool checkAndHandleRecovery();
bool checkAndHandleRecovery();
/**
* Helper method to overwrite health state of one of the children.
@ -204,8 +168,6 @@ class AssemblyBase : public SubsystemBase {
* @param objectId Must be a registered child.
*/
void overwriteDeviceHealth(object_id_t objectId, HasHealthIF::HealthState oldHealth);
void triggerModeHelperEvents(Mode_t mode, Submode_t submode);
};
#endif /* FSFW_DEVICEHANDLERS_ASSEMBLYBASE_H_ */

View File

@ -3,12 +3,17 @@
#include "fsfw/subsystem/SubsystemBase.h"
ChildHandlerBase::ChildHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication,
CookieIF* cookie, HasModeTreeChildrenIF& parent,
FailureIsolationBase* customFdir, size_t cmdQueueSize)
CookieIF* cookie, object_id_t hkDestination,
uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId,
object_id_t parent, FailureIsolationBase* customFdir,
size_t cmdQueueSize)
: DeviceHandlerBase(setObjectId, deviceCommunication, cookie,
(customFdir == nullptr ? &childHandlerFdir : customFdir), cmdQueueSize),
parent(parent),
childHandlerFdir(setObjectId) {}
parentId(parent),
childHandlerFdir(setObjectId) {
this->setHkDestination(hkDestination);
this->setThermalStateRequestPoolIds(thermalStatePoolId, thermalRequestPoolId);
}
ChildHandlerBase::~ChildHandlerBase() {}
@ -18,5 +23,21 @@ ReturnValue_t ChildHandlerBase::initialize() {
return result;
}
return DeviceHandlerBase::connectModeTreeParent(parent);
MessageQueueId_t parentQueue = 0;
if (parentId != objects::NO_OBJECT) {
SubsystemBase* parent = ObjectManager::instance()->get<SubsystemBase>(parentId);
if (parent == NULL) {
return returnvalue::FAILED;
}
parentQueue = parent->getCommandQueue();
parent->registerChild(getObjectId());
}
healthHelper.setParentQueue(parentQueue);
modeHelper.setParentQueue(parentQueue);
return returnvalue::OK;
}

View File

@ -1,23 +1,22 @@
#ifndef FSFW_DEVICEHANDLER_CHILDHANDLERBASE_H_
#define FSFW_DEVICEHANDLER_CHILDHANDLERBASE_H_
#include <fsfw/subsystem/HasModeTreeChildrenIF.h>
#include "ChildHandlerFDIR.h"
#include "DeviceHandlerBase.h"
class ChildHandlerBase : public DeviceHandlerBase {
public:
ChildHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, CookieIF* cookie,
HasModeTreeChildrenIF& parent, FailureIsolationBase* customFdir = nullptr,
size_t cmdQueueSize = 20);
object_id_t hkDestination, uint32_t thermalStatePoolId,
uint32_t thermalRequestPoolId, object_id_t parent = objects::NO_OBJECT,
FailureIsolationBase* customFdir = nullptr, size_t cmdQueueSize = 20);
virtual ~ChildHandlerBase();
virtual ReturnValue_t initialize();
protected:
HasModeTreeChildrenIF& parent;
const uint32_t parentId;
ChildHandlerFDIR childHandlerFdir;
};

View File

@ -1,4 +1,4 @@
#include "DeviceHandlerBase.h"
#include "fsfw/devicehandlers/DeviceHandlerBase.h"
#include "fsfw/datapoollocal/LocalPoolVariable.h"
#include "fsfw/devicehandlers/AcceptsDeviceResponsesIF.h"
@ -12,7 +12,6 @@
#include "fsfw/serviceinterface/ServiceInterface.h"
#include "fsfw/storagemanager/StorageManagerIF.h"
#include "fsfw/subsystem/SubsystemBase.h"
#include "fsfw/subsystem/helper.h"
#include "fsfw/thermal/ThermalComponentIF.h"
object_id_t DeviceHandlerBase::powerSwitcherId = objects::NO_OBJECT;
@ -23,6 +22,8 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, object_id_t device
CookieIF* comCookie, FailureIsolationBase* fdirInstance,
size_t cmdQueueSize)
: SystemObject(setObjectId),
mode(MODE_OFF),
submode(SUBMODE_NONE),
wiretappingMode(OFF),
storedRawData(StorageManagerIF::INVALID_ADDRESS),
deviceCommunicationId(deviceCommunication),
@ -37,13 +38,10 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, object_id_t device
defaultFDIRUsed(fdirInstance == nullptr),
switchOffWasReported(false),
childTransitionDelay(5000),
mode(MODE_OFF),
submode(SUBMODE_NONE),
transitionSourceMode(_MODE_POWER_DOWN),
transitionSourceSubMode(SUBMODE_NONE) {
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
commandQueue = QueueFactory::instance()->createMessageQueue(
cmdQueueSize, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
cmdQueueSize, MessageQueueMessage::MAX_MESSAGE_SIZE);
insertInCommandMap(RAW_COMMAND_ID);
cookieInfo.state = COOKIE_UNUSED;
cookieInfo.pendingCommand = deviceCommandMap.end();
@ -51,6 +49,9 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, object_id_t device
printWarningOrError(sif::OutputTypes::OUT_ERROR, "DeviceHandlerBase", returnvalue::FAILED,
"Invalid cookie");
}
if (this->fdirInstance == nullptr) {
this->fdirInstance = new DeviceHandlerFailureIsolation(setObjectId, defaultFdirParentId);
}
}
void DeviceHandlerBase::setHkDestination(object_id_t hkDestination) {
@ -128,10 +129,6 @@ ReturnValue_t DeviceHandlerBase::initialize() {
if (result != returnvalue::OK) {
return result;
}
if (this->fdirInstance == nullptr) {
this->fdirInstance =
new DeviceHandlerFailureIsolation(this->getObjectId(), defaultFdirParentId);
}
communicationInterface =
ObjectManager::instance()->get<DeviceCommunicationIF>(deviceCommunicationId);
@ -355,6 +352,7 @@ void DeviceHandlerBase::doStateMachine() {
currentUptime - timeoutStart >= powerSwitcher->getSwitchDelayMs()) {
triggerEvent(MODE_TRANSITION_FAILED, PowerSwitchIF::SWITCH_TIMEOUT, 0);
setMode(_MODE_POWER_DOWN);
callChildStatemachine();
break;
}
ReturnValue_t switchState = getStateOfSwitches();
@ -368,12 +366,13 @@ void DeviceHandlerBase::doStateMachine() {
}
} break;
case _MODE_WAIT_OFF: {
uint32_t currentUptime;
Clock::getUptime(&currentUptime);
if (powerSwitcher == nullptr) {
setMode(MODE_OFF);
break;
}
uint32_t currentUptime;
Clock::getUptime(&currentUptime);
if (currentUptime - timeoutStart >= powerSwitcher->getSwitchDelayMs()) {
triggerEvent(MODE_TRANSITION_FAILED, PowerSwitchIF::SWITCH_TIMEOUT, 0);
setMode(MODE_ERROR_ON);
@ -568,25 +567,13 @@ void DeviceHandlerBase::setTransition(Mode_t modeTo, Submode_t submodeTo) {
}
void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) {
/**
* handle transition from OFF to NORMAL by continuing towards normal when ON is reached
*/
if (newMode == MODE_ON and continueToNormal) {
continueToNormal = false;
mode = _MODE_TO_NORMAL;
return;
}
/* TODO: This will probably be done by the LocalDataPoolManager now */
// changeHK(mode, submode, false);
submode = newSubmode;
mode = newMode;
modeChanged();
setNormalDatapoolEntriesInvalid();
if (newMode == MODE_OFF) {
disableCommandsAndReplies();
}
if (!isTransitionalMode()) {
// clear this flag when a non-transitional Mode is reached to be safe
continueToNormal = false;
modeHelper.modeChanged(newMode, newSubmode);
announceMode(false);
}
@ -1071,7 +1058,8 @@ Mode_t DeviceHandlerBase::getBaseMode(Mode_t transitionMode) {
return transitionMode & ~(TRANSITION_MODE_BASE_ACTION_MASK | TRANSITION_MODE_CHILD_ACTION_MASK);
}
// SHOULDDO: throw away DHB and write a new one:
// SHOULDDO: Allow transition from OFF to NORMAL to reduce complexity in assemblies. And, by the
// way, throw away DHB and write a new one:
// - Include power and thermal completely, but more modular :-)
// - Don't use modes for state transitions, reduce FSM (Finte State Machine) complexity.
// - Modularization?
@ -1083,10 +1071,11 @@ ReturnValue_t DeviceHandlerBase::checkModeCommand(Mode_t commandedMode, Submode_
if ((mode == MODE_ERROR_ON) && (commandedMode != MODE_OFF)) {
return TRANS_NOT_ALLOWED;
}
if ((commandedMode == MODE_NORMAL) && (mode == MODE_OFF)) {
return TRANS_NOT_ALLOWED;
}
// Do not check thermal state for MODE_RAW
if ((mode == MODE_OFF) and ((commandedMode == MODE_ON) or (commandedMode == MODE_NORMAL)) and
(thermalSet != nullptr)) {
if ((commandedMode == MODE_ON) && (mode == MODE_OFF) and (thermalSet != nullptr)) {
ReturnValue_t result = thermalSet->read();
if (result == returnvalue::OK) {
if ((thermalSet->heaterRequest.value != ThermalComponentIF::STATE_REQUEST_IGNORE) and
@ -1101,7 +1090,6 @@ ReturnValue_t DeviceHandlerBase::checkModeCommand(Mode_t commandedMode, Submode_
}
void DeviceHandlerBase::startTransition(Mode_t commandedMode, Submode_t commandedSubmode) {
continueToNormal = false;
switch (commandedMode) {
case MODE_ON:
handleTransitionToOnMode(commandedMode, commandedSubmode);
@ -1131,9 +1119,8 @@ void DeviceHandlerBase::startTransition(Mode_t commandedMode, Submode_t commande
case MODE_NORMAL:
if (mode != MODE_OFF) {
setTransition(MODE_NORMAL, commandedSubmode);
} else { // mode is off
continueToNormal = true;
handleTransitionToOnMode(MODE_NORMAL, commandedSubmode);
} else {
replyReturnvalueToCommand(HasModesIF::TRANS_NOT_ALLOWED);
}
break;
}
@ -1291,7 +1278,6 @@ void DeviceHandlerBase::handleDeviceTm(const SerializeIF& dataSet, DeviceCommand
if (iter->second.command != deviceCommandMap.end()) {
MessageQueueId_t queueId = iter->second.command->second.sendReplyTo;
// This may fail, but we'll ignore the fault.
if (queueId != NO_COMMANDER) {
// This may fail, but we'll ignore the fault.
actionHelper.reportData(queueId, replyId, const_cast<SerializeIF*>(&dataSet));
@ -1470,8 +1456,6 @@ void DeviceHandlerBase::setTaskIF(PeriodicTaskIF* task) { executingTask = task;
void DeviceHandlerBase::debugInterface(uint8_t positionTracker, object_id_t objectId,
uint32_t parameter) {}
Submode_t DeviceHandlerBase::getInitialSubmode() { return SUBMODE_NONE; }
void DeviceHandlerBase::performOperationHook() {}
ReturnValue_t DeviceHandlerBase::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
@ -1494,7 +1478,7 @@ ReturnValue_t DeviceHandlerBase::initializeAfterTaskCreation() {
this->poolManager.initializeAfterTaskCreation();
if (setStartupImmediately) {
startTransition(MODE_ON, getInitialSubmode());
startTransition(MODE_ON, SUBMODE_NONE);
}
return returnvalue::OK;
}
@ -1578,52 +1562,3 @@ MessageQueueId_t DeviceHandlerBase::getCommanderQueueId(DeviceCommandId_t replyI
}
return commandIter->second.sendReplyTo;
}
void DeviceHandlerBase::setCustomFdir(FailureIsolationBase* fdir) { this->fdirInstance = fdir; }
void DeviceHandlerBase::setPowerSwitcher(PowerSwitchIF* switcher) {
this->powerSwitcher = switcher;
}
Mode_t DeviceHandlerBase::getMode() { return mode; }
Submode_t DeviceHandlerBase::getSubmode() { return submode; }
void DeviceHandlerBase::disableCommandsAndReplies() {
for (auto& command : deviceCommandMap) {
if (command.second.isExecuting) {
command.second.isExecuting = false;
}
}
for (auto& reply : deviceReplyMap) {
if (!reply.second.periodic) {
if (reply.second.countdown != nullptr) {
reply.second.countdown->timeOut();
} else {
reply.second.delayCycles = 0;
}
reply.second.active = false;
}
}
}
ReturnValue_t DeviceHandlerBase::connectModeTreeParent(HasModeTreeChildrenIF& parent) {
return modetree::connectModeTreeParent(parent, *this, healthHelper, modeHelper);
}
const HasHealthIF* DeviceHandlerBase::getOptHealthIF() const { return this; }
const HasModesIF& DeviceHandlerBase::getModeIF() const { return *this; }
ModeTreeChildIF& DeviceHandlerBase::getModeTreeChildIF() { return *this; }
ReturnValue_t DeviceHandlerBase::finishAction(bool success, DeviceCommandId_t action,
ReturnValue_t result) {
auto commandIter = deviceCommandMap.find(action);
if (commandIter == deviceCommandMap.end()) {
return MessageQueueIF::NO_QUEUE;
}
commandIter->second.isExecuting = false;
actionHelper.finish(success, commandIter->second.sendReplyTo, action, result);
return returnvalue::OK;
}

View File

@ -21,7 +21,6 @@
#include "fsfw/returnvalues/returnvalue.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
#include "fsfw/serviceinterface/serviceInterfaceDefintions.h"
#include "fsfw/subsystem/ModeTreeConnectionIF.h"
#include "fsfw/tasks/ExecutableObjectIF.h"
#include "fsfw/tasks/PeriodicTaskIF.h"
@ -84,8 +83,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
public HasModesIF,
public HasHealthIF,
public HasActionsIF,
public ModeTreeChildIF,
public ModeTreeConnectionIF,
public ReceivesParameterMessagesIF,
public HasLocalDataPoolIF {
friend void(Factory::setStaticFrameworkObjectIds)();
@ -105,56 +102,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
DeviceHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, CookieIF *comCookie,
FailureIsolationBase *fdirInstance = nullptr, size_t cmdQueueSize = 20);
void setCustomFdir(FailureIsolationBase *fdir);
void setPowerSwitcher(PowerSwitchIF *switcher);
/**
* extending the modes of DeviceHandler IF for internal state machine
*/
static constexpr uint8_t TRANSITION_MODE_CHILD_ACTION_MASK = 0x20;
static constexpr uint8_t TRANSITION_MODE_BASE_ACTION_MASK = 0x10;
//! This is a transitional state which can not be commanded. The device
//! handler performs all commands to get the device in a state ready to
//! perform commands. When this is completed, the mode changes to @c MODE_ON.
static const Mode_t _MODE_START_UP = TRANSITION_MODE_CHILD_ACTION_MASK | 5;
//! This is a transitional state which can not be commanded.
//! The device handler performs all actions and commands to get the device
//! shut down. When the device is off, the mode changes to @c MODE_OFF.
//! It is possible to set the mode to _MODE_SHUT_DOWN to use the to off
//! transition if available.
static const Mode_t _MODE_SHUT_DOWN = TRANSITION_MODE_CHILD_ACTION_MASK | 6;
//! It is possible to set the mode to _MODE_TO_ON to use the to on
//! transition if available.
static const Mode_t _MODE_TO_ON = TRANSITION_MODE_CHILD_ACTION_MASK | HasModesIF::MODE_ON;
//! It is possible to set the mode to _MODE_TO_RAW to use the to raw
//! transition if available.
static const Mode_t _MODE_TO_RAW = TRANSITION_MODE_CHILD_ACTION_MASK | MODE_RAW;
//! It is possible to set the mode to _MODE_TO_NORMAL to use the to normal
//! transition if available.
static const Mode_t _MODE_TO_NORMAL = TRANSITION_MODE_CHILD_ACTION_MASK | MODE_NORMAL;
//! This is a transitional state which can not be commanded.
//! The device is shut down and ready to be switched off.
//! After the command to set the switch off has been sent,
//! the mode changes to @c _MODE_WAIT_OFF
static const Mode_t _MODE_POWER_DOWN = TRANSITION_MODE_BASE_ACTION_MASK | 1;
//! This is a transitional state which can not be commanded. The device
//! will be switched on in this state. After the command to set the switch
//! on has been sent, the mode changes to @c _MODE_WAIT_ON.
static const Mode_t _MODE_POWER_ON = TRANSITION_MODE_BASE_ACTION_MASK | 2;
//! This is a transitional state which can not be commanded. The switch has
//! been commanded off and the handler waits for it to be off.
//! When the switch is off, the mode changes to @c MODE_OFF.
static const Mode_t _MODE_WAIT_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 3;
//! This is a transitional state which can not be commanded. The switch
//! has been commanded on and the handler waits for it to be on.
//! When the switch is on, the mode changes to @c _MODE_TO_ON.
static const Mode_t _MODE_WAIT_ON = TRANSITION_MODE_BASE_ACTION_MASK | 4;
//! This is a transitional state which can not be commanded. The switch has
//! been commanded off and is off now. This state is only to do an RMAP
//! cycle once more where the doSendRead() function will set the mode to
//! MODE_OFF. The reason to do this is to get rid of stuck packets in the IO Board.
static const Mode_t _MODE_SWITCH_IS_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 5;
void setHkDestination(object_id_t hkDestination);
/**
@ -170,10 +117,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
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);
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF &parent) override;
ModeTreeChildIF &getModeTreeChildIF() override;
/**
* @brief Helper function to ease device handler development.
* This will instruct the transition to MODE_ON immediately
@ -219,7 +162,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* @param counter Specifies which Action to perform
* @return returnvalue::OK for successful execution
*/
ReturnValue_t performOperation(uint8_t counter) override;
virtual ReturnValue_t performOperation(uint8_t counter) override;
/**
* @brief Initializes the device handler
@ -229,14 +172,14 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* Calls fillCommandAndReplyMap().
* @return
*/
ReturnValue_t initialize() override;
virtual ReturnValue_t initialize() override;
/**
* @brief Intialization steps performed after all tasks have been created.
* This function will be called by the executing task.
* @return
*/
ReturnValue_t initializeAfterTaskCreation() override;
virtual ReturnValue_t initializeAfterTaskCreation() override;
/** Destructor. */
virtual ~DeviceHandlerBase();
@ -253,8 +196,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
virtual object_id_t getObjectId() const override;
/**
* This is a helper method for classes which are parent nodes in the mode tree.
* It registers the passed queue as the destination for mode and health messages.
* @param parentQueueId
*/
virtual void setParentQueue(MessageQueueId_t parentQueueId);
@ -454,8 +395,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
*/
virtual ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) = 0;
MessageQueueId_t getCommanderQueueId(DeviceCommandId_t replyId) const;
ReturnValue_t finishAction(bool success, DeviceCommandId_t action, ReturnValue_t result);
/**
* Helper function to get pending command. This is useful for devices
* like SPI sensors to identify the last sent command.
@ -524,14 +463,14 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* @brief This is a helper method to insert replies in the reply map.
* @param deviceCommand Identifier of the reply to add.
* @param maxDelayCycles The maximum number of delay cycles the reply waits
* until it times out.
* until it times out.
* @param periodic Indicates if the command is periodic (i.e. it is sent
* by the device repeatedly without request) or not. Default is aperiodic (0).
* Please note that periodic replies are disabled by default. You can enable them with
* #updatePeriodicReply
* by the device repeatedly without request) or not. Default is aperiodic (0).
* Please note that periodic replies are disabled by default. You can enable them with
* #updatePeriodicReply
* @param countdown Instead of using maxDelayCycles to timeout a device reply it is also possible
* to provide a pointer to a Countdown object which will signal the timeout
* when expired
* to provide a pointer to a Countdown object which will signal the timeout
* when expired
* @return - @c returnvalue::OK when the command was successfully inserted,
* - @c returnvalue::FAILED else.
*/
@ -716,12 +655,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
virtual void debugInterface(uint8_t positionTracker = 0, object_id_t objectId = 0,
uint32_t parameter = 0);
/**
* @brief Can be overwritten by a child to specify the initial submode when device has been set
* to startup immediately.
*/
virtual Submode_t getInitialSubmode();
protected:
static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_BASE;
@ -751,18 +684,15 @@ class DeviceHandlerBase : public DeviceHandlerIF,
size_t rawPacketLen = 0;
/**
* Get the current mode
*
* set via setMode()
* The mode the device handler is currently in.
* This should never be changed directly but only with setMode()
*/
Mode_t getMode();
Mode_t mode;
/**
* Get the current Submode
*
* set via setMode()
* The submode the device handler is currently in.
* This should never be changed directly but only with setMode()
*/
Submode_t getSubmode();
Submode_t submode;
/** This is the counter value from performOperation(). */
uint8_t pstStep = 0;
@ -843,18 +773,11 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* This is used to keep track of pending replies.
*/
struct DeviceReplyInfo {
//! For Command-Reply combinations:
//! The maximum number of cycles the handler should wait for a reply
//! to this command.
//!
//! Reply Only:
//! For periodic replies, this variable will be the number of delay cycles between the replies.
//! For the non-periodic variant, this variable is not used as there is no meaningful
//! definition for delay
uint16_t maxDelayCycles;
//! This variable will be set to #maxDelayCycles if a reply is expected.
//! For non-periodic replies without a command, this variable is unused.
//! A runtime value of 0 means there is no reply is currently expected.
//! The currently remaining cycles the handler should wait for a reply,
//! 0 means there is no reply expected
uint16_t delayCycles;
size_t replyLen = 0; //!< Expected size of the reply.
//! if this is !=0, the delayCycles will not be reset to 0 but to
@ -910,7 +833,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
/** Pointer to the used FDIR instance. If not provided by child,
* default class is instantiated. */
FailureIsolationBase *fdirInstance;
object_id_t parent = objects::NO_OBJECT;
//! To correctly delete the default instance.
bool defaultFDIRUsed;
@ -951,8 +873,8 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* Do the transition to the main modes (MODE_ON, MODE_NORMAL and MODE_RAW).
*
* If the transition is complete, the mode should be set to the target mode,
* which can be deduced from the current mode (which is
* [_MODE_TO_ON, _MODE_TO_NORMAL, _MODE_TO_RAW]) using getBaseMode()
* which can be deduced from the current mode which is
* [_MODE_TO_ON, _MODE_TO_NORMAL, _MODE_TO_RAW]
*
* The intended target submode is already set.
* The origin submode can be read in subModeFrom.
@ -1019,9 +941,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
*/
LocalDataPoolManager *getHkManagerHandle() override;
const HasHealthIF *getOptHealthIF() const override;
const HasModesIF &getModeIF() const override;
/**
* Returns the delay cycle count of a reply.
* A count != 0 indicates that the command is already executed.
@ -1201,22 +1120,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
*/
virtual ReturnValue_t doSendReadHook();
/**
* Send a RMAP getRead command.
*
* The size of the getRead command is #maxDeviceReplyLen.
* This is always executed, independently from the current mode.
*/
virtual void doSendRead(void);
/**
* Check the getRead reply and the contained data.
*
* If data was received scanForReply() and, if successful, handleReply()
* are called. If the current mode is @c MODE_RAW, the received packet
* is sent to the commanding object via commandQueue.
*/
virtual void doGetRead();
private:
/**
* State a cookie is in.
@ -1267,18 +1170,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
*/
uint32_t childTransitionDelay;
/**
* The mode the device handler is currently in.
* This should not be changed directly but only with setMode()
*/
Mode_t mode;
/**
* The submode the device handler is currently in.
* This should not be changed directly but only with setMode()
*/
Submode_t submode;
/**
* @brief The mode the current transition originated from
*
@ -1296,15 +1187,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
*/
Submode_t transitionSourceSubMode;
/**
* used to make the state machine continue from ON to NOMAL when
* a Device is commanded to NORMAL in OFF mode
*
* set in startTransition()
* evaluated in setMode() to continue to NORMAL when ON is reached
*/
bool continueToNormal;
/**
* read the command queue
*/
@ -1373,6 +1255,21 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* - if the action was successful, the reply timout counter is initialized
*/
void doGetWrite(void);
/**
* Send a RMAP getRead command.
*
* The size of the getRead command is #maxDeviceReplyLen.
* This is always executed, independently from the current mode.
*/
void doSendRead(void);
/**
* Check the getRead reply and the contained data.
*
* If data was received scanForReply() and, if successful, handleReply()
* are called. If the current mode is @c MODE_RAW, the received packet
* is sent to the commanding object via commandQueue.
*/
void doGetRead(void);
/**
* @brief Resets replies which use a timeout to detect missed replies.
@ -1426,11 +1323,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
void printWarningOrError(sif::OutputTypes errorType, const char *functionName,
ReturnValue_t errorCode = returnvalue::FAILED,
const char *errorPrint = nullptr);
/**
* @brief Disables all commands and replies when device is set to MODE_OFF
*/
void disableCommandsAndReplies();
};
#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERBASE_H_ */

View File

@ -29,7 +29,6 @@ ReturnValue_t DeviceHandlerFailureIsolation::eventReceived(EventMessage* event)
switch (event->getEvent()) {
case HasModesIF::MODE_TRANSITION_FAILED:
case HasModesIF::OBJECT_IN_INVALID_MODE:
case DeviceHandlerIF::DEVICE_WANTS_HARD_REBOOT:
// We'll try a recovery as long as defined in MAX_REBOOT.
// Might cause some AssemblyBase cycles, so keep number low.
handleRecovery(event->getEvent());

View File

@ -24,6 +24,9 @@ class DeviceHandlerIF {
static const DeviceCommandId_t RAW_COMMAND_ID = -1;
static const DeviceCommandId_t NO_COMMAND_ID = -2;
static constexpr uint8_t TRANSITION_MODE_CHILD_ACTION_MASK = 0x20;
static constexpr uint8_t TRANSITION_MODE_BASE_ACTION_MASK = 0x10;
using dh_heater_request_t = uint8_t;
using dh_thermal_state_t = int8_t;
@ -51,6 +54,47 @@ class DeviceHandlerIF {
//! device still is powered. In this mode, only a mode change to @c MODE_OFF
//! can be commanded, which tries to switch off the device again.
static const Mode_t MODE_ERROR_ON = 4;
//! This is a transitional state which can not be commanded. The device
//! handler performs all commands to get the device in a state ready to
//! perform commands. When this is completed, the mode changes to @c MODE_ON.
static const Mode_t _MODE_START_UP = TRANSITION_MODE_CHILD_ACTION_MASK | 5;
//! This is a transitional state which can not be commanded.
//! The device handler performs all actions and commands to get the device
//! shut down. When the device is off, the mode changes to @c MODE_OFF.
//! It is possible to set the mode to _MODE_SHUT_DOWN to use the to off
//! transition if available.
static const Mode_t _MODE_SHUT_DOWN = TRANSITION_MODE_CHILD_ACTION_MASK | 6;
//! It is possible to set the mode to _MODE_TO_ON to use the to on
//! transition if available.
static const Mode_t _MODE_TO_ON = TRANSITION_MODE_CHILD_ACTION_MASK | HasModesIF::MODE_ON;
//! It is possible to set the mode to _MODE_TO_RAW to use the to raw
//! transition if available.
static const Mode_t _MODE_TO_RAW = TRANSITION_MODE_CHILD_ACTION_MASK | MODE_RAW;
//! It is possible to set the mode to _MODE_TO_NORMAL to use the to normal
//! transition if available.
static const Mode_t _MODE_TO_NORMAL = TRANSITION_MODE_CHILD_ACTION_MASK | MODE_NORMAL;
//! This is a transitional state which can not be commanded.
//! The device is shut down and ready to be switched off.
//! After the command to set the switch off has been sent,
//! the mode changes to @c MODE_WAIT_OFF
static const Mode_t _MODE_POWER_DOWN = TRANSITION_MODE_BASE_ACTION_MASK | 1;
//! This is a transitional state which can not be commanded. The device
//! will be switched on in this state. After the command to set the switch
//! on has been sent, the mode changes to @c MODE_WAIT_ON.
static const Mode_t _MODE_POWER_ON = TRANSITION_MODE_BASE_ACTION_MASK | 2;
//! This is a transitional state which can not be commanded. The switch has
//! been commanded off and the handler waits for it to be off.
//! When the switch is off, the mode changes to @c MODE_OFF.
static const Mode_t _MODE_WAIT_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 3;
//! This is a transitional state which can not be commanded. The switch
//! has been commanded on and the handler waits for it to be on.
//! When the switch is on, the mode changes to @c MODE_TO_ON.
static const Mode_t _MODE_WAIT_ON = TRANSITION_MODE_BASE_ACTION_MASK | 4;
//! This is a transitional state which can not be commanded. The switch has
//! been commanded off and is off now. This state is only to do an RMAP
//! cycle once more where the doSendRead() function will set the mode to
//! MODE_OFF. The reason to do this is to get rid of stuck packets in the IO Board.
static const Mode_t _MODE_SWITCH_IS_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 5;
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::CDH;
static const Event DEVICE_BUILDING_COMMAND_FAILED = MAKE_EVENT(0, severity::LOW);
@ -65,7 +109,6 @@ class DeviceHandlerIF {
static const Event INVALID_DEVICE_COMMAND = MAKE_EVENT(8, severity::LOW);
static const Event MONITORING_LIMIT_EXCEEDED = MAKE_EVENT(9, severity::LOW);
static const Event MONITORING_AMBIGUOUS = MAKE_EVENT(10, severity::HIGH);
static const Event DEVICE_WANTS_HARD_REBOOT = MAKE_EVENT(11, severity::HIGH);
static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_IF;

View File

@ -1,9 +1,9 @@
#ifndef FSFW_DEVICEHANDLERS_DEVICETMREPORTINGWRAPPER_H_
#define FSFW_DEVICEHANDLERS_DEVICETMREPORTINGWRAPPER_H_
#include "fsfw/action/HasActionsIF.h"
#include "fsfw/objectmanager/SystemObjectIF.h"
#include "fsfw/serialize/SerializeIF.h"
#include "../action/HasActionsIF.h"
#include "../objectmanager/SystemObjectIF.h"
#include "../serialize/SerializeIF.h"
class DeviceTmReportingWrapper : public SerializeIF {
public:

View File

@ -8,9 +8,7 @@ HealthDevice::HealthDevice(object_id_t setObjectId, MessageQueueId_t parentQueue
parentQueue(parentQueue),
commandQueue(),
healthHelper(this, setObjectId) {
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
commandQueue = QueueFactory::instance()->createMessageQueue(
3, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
commandQueue = QueueFactory::instance()->createMessageQueue(3);
}
HealthDevice::~HealthDevice() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }

View File

@ -18,9 +18,8 @@ const LocalPool::LocalPoolConfig EventManager::poolConfig = {
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(
MAX_EVENTS_PER_CYCLE, EventMessage::EVENT_MESSAGE_SIZE, &mqArgs);
eventReportQueue = QueueFactory::instance()->createMessageQueue(MAX_EVENTS_PER_CYCLE,
EventMessage::EVENT_MESSAGE_SIZE);
}
EventManager::~EventManager() {
@ -47,20 +46,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();
@ -206,19 +194,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

@ -43,7 +43,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

@ -9,9 +9,8 @@
FailureIsolationBase::FailureIsolationBase(object_id_t owner, object_id_t parent,
uint8_t messageDepth, uint8_t parameterDomainBase)
: ownerId(owner), faultTreeParent(parent), parameterDomainBase(parameterDomainBase) {
auto mqArgs = MqArgs(owner, static_cast<void*>(this));
eventQueue = QueueFactory::instance()->createMessageQueue(
messageDepth, EventMessage::EVENT_MESSAGE_SIZE, &mqArgs);
eventQueue =
QueueFactory::instance()->createMessageQueue(messageDepth, EventMessage::EVENT_MESSAGE_SIZE);
}
FailureIsolationBase::~FailureIsolationBase() {
@ -62,12 +61,11 @@ ReturnValue_t FailureIsolationBase::initialize() {
ObjectManager::instance()->get<ConfirmsFailuresIF>(faultTreeParent);
if (parentIF == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "FailureIsolationBase::intialize: Parent object "
<< "invalid" << std::endl;
sif::error << "Make sure it implements ConfirmsFailuresIF" << std::endl;
#else
sif::printError("FailureIsolationBase::intialize: Parent object invalid\n");
sif::printError("Make sure it implements ConfirmsFailuresIF\n");
sif::error << "FailureIsolationBase::intialize: Parent object"
<< "invalid." << std::endl;
#endif
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Make sure it implements ConfirmsFailuresIF." << std::endl;
#endif
return ObjectManagerIF::CHILD_INIT_FAILED;
return returnvalue::FAILED;

View File

@ -12,12 +12,13 @@
class FailureIsolationBase : public ConfirmsFailuresIF, public HasParametersIF {
public:
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::FDIR_1;
//! FDIR has an internal state, which changed from par2 (oldState) to par1 (newState).
static const Event FDIR_CHANGED_STATE = MAKE_EVENT(1, severity::INFO);
//! FDIR tries to restart device. Par1: event that caused recovery.
static const Event FDIR_STARTS_RECOVERY = MAKE_EVENT(2, severity::MEDIUM);
//! FDIR turns off device. Par1: event that caused recovery.
static const Event FDIR_TURNS_OFF_DEVICE = MAKE_EVENT(3, severity::MEDIUM);
static const Event FDIR_CHANGED_STATE =
MAKE_EVENT(1, severity::INFO); //!< FDIR has an internal state, which changed from par2
//!< (oldState) to par1 (newState).
static const Event FDIR_STARTS_RECOVERY = MAKE_EVENT(
2, severity::MEDIUM); //!< FDIR tries to restart device. Par1: event that caused recovery.
static const Event FDIR_TURNS_OFF_DEVICE = MAKE_EVENT(
3, severity::MEDIUM); //!< FDIR turns off device. Par1: event that caused recovery.
FailureIsolationBase(object_id_t owner, object_id_t parent = objects::NO_OBJECT,
uint8_t messageDepth = 10, uint8_t parameterDomainBase = 0xF0);

View File

@ -40,7 +40,6 @@ class HasFileSystemIF {
//! [EXPORT] : P1: Can be file system specific error code
static constexpr ReturnValue_t GENERIC_FILE_ERROR = MAKE_RETURN_CODE(0);
static constexpr ReturnValue_t GENERIC_DIR_ERROR = MAKE_RETURN_CODE(1);
static constexpr ReturnValue_t FILESYSTEM_INACTIVE = MAKE_RETURN_CODE(2);
static constexpr ReturnValue_t GENERIC_RENAME_ERROR = MAKE_RETURN_CODE(3);
//! [EXPORT] : File system is currently busy

View File

@ -16,24 +16,26 @@ class HasHealthIF {
};
static const uint8_t INTERFACE_ID = CLASS_ID::HAS_HEALTH_IF;
static constexpr ReturnValue_t OBJECT_NOT_HEALTHY = returnvalue::makeCode(INTERFACE_ID, 1);
static constexpr ReturnValue_t INVALID_HEALTH_STATE = returnvalue::makeCode(INTERFACE_ID, 2);
static constexpr ReturnValue_t IS_EXTERNALLY_CONTROLLED = returnvalue::makeCode(INTERFACE_ID, 3);
static const ReturnValue_t OBJECT_NOT_HEALTHY = MAKE_RETURN_CODE(1);
static const ReturnValue_t INVALID_HEALTH_STATE = MAKE_RETURN_CODE(2);
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::SYSTEM_MANAGER_1;
//! P1: New Health, P2: Old Health
static const Event HEALTH_INFO = MAKE_EVENT(6, severity::INFO);
static const Event CHILD_CHANGED_HEALTH = MAKE_EVENT(7, severity::INFO);
static const Event CHILD_PROBLEMS = MAKE_EVENT(8, severity::LOW);
//! Assembly overwrites health information of children to keep satellite alive.
static const Event OVERWRITING_HEALTH = MAKE_EVENT(9, severity::LOW);
//! Someone starts a recovery of a component (typically power-cycle). No parameters.
static const Event TRYING_RECOVERY = MAKE_EVENT(10, severity::MEDIUM);
//! Recovery is ongoing. Comes twice during recovery.
//! P1: 0 for the first, 1 for the second event. P2: 0
static const Event RECOVERY_STEP = MAKE_EVENT(11, severity::MEDIUM);
//! Recovery was completed. Not necessarily successful. No parameters.
static const Event RECOVERY_DONE = MAKE_EVENT(12, severity::MEDIUM);
static const Event OVERWRITING_HEALTH =
MAKE_EVENT(9, severity::LOW); //!< Assembly overwrites health information of children to keep
//!< satellite alive.
static const Event TRYING_RECOVERY =
MAKE_EVENT(10, severity::MEDIUM); //!< Someone starts a recovery of a component (typically
//!< power-cycle). No parameters.
static const Event RECOVERY_STEP =
MAKE_EVENT(11, severity::MEDIUM); //!< Recovery is ongoing. Comes twice during recovery. P1:
//!< 0 for the first, 1 for the second event. P2: 0
static const Event RECOVERY_DONE = MAKE_EVENT(
12,
severity::MEDIUM); //!< Recovery was completed. Not necessarily successful. No parameters.
virtual ~HasHealthIF() {}
virtual MessageQueueId_t getCommandQueue() const = 0;

View File

@ -7,13 +7,11 @@
InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth)
: SystemObject(setObjectId),
commandQueue(QueueFactory::instance()->createMessageQueue(messageQueueDepth)),
poolManager(this, commandQueue),
internalErrorSid(setObjectId, InternalErrorDataset::ERROR_SET_ID),
internalErrorDataset(this) {
mutex = MutexFactory::instance()->createMutex();
auto mqArgs = MqArgs(setObjectId, static_cast<void *>(this));
commandQueue = QueueFactory::instance()->createMessageQueue(
messageQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
}
InternalErrorReporter::~InternalErrorReporter() { MutexFactory::instance()->deleteMutex(mutex); }
@ -38,14 +36,15 @@ ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) {
if ((newQueueHits > 0) or (newTmHits > 0) or (newStoreHits > 0)) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << "InternalErrorReporter::performOperation: Errors "
<< "occured: Queue | TM | Store : " << newQueueHits << " | " << newTmHits << " | "
<< newStoreHits << std::endl;
<< "occured!" << std::endl;
sif::debug << "Queue errors: " << newQueueHits << std::endl;
sif::debug << "TM errors: " << newTmHits << std::endl;
sif::debug << "Store errors: " << newStoreHits << std::endl;
#else
sif::printDebug(
"InternalErrorReporter::performOperation: Errors occured: Queue | TM | Store: %lu | %lu "
"| %lu\n",
static_cast<unsigned int>(newQueueHits), static_cast<unsigned int>(newTmHits),
static_cast<unsigned int>(newStoreHits));
sif::printDebug("InternalErrorReporter::performOperation: Errors occured!\n");
sif::printDebug("Queue errors: %lu\n", static_cast<unsigned int>(newQueueHits));
sif::printDebug("TM errors: %lu\n", static_cast<unsigned int>(newTmHits));
sif::printDebug("Store errors: %lu\n", static_cast<unsigned int>(newStoreHits));
#endif
}
}

View File

@ -34,7 +34,7 @@ class CommandMessageIF {
static const Command_t CMD_NONE = MAKE_COMMAND_ID(0);
static const Command_t REPLY_COMMAND_OK = MAKE_COMMAND_ID(1);
//! Reply indicating that the current command was rejected,
//! Parameter 1 should contain the error code
//! par1 should contain the error code
static const Command_t REPLY_REJECTED = MAKE_COMMAND_ID(2);
virtual ~CommandMessageIF(){};

View File

@ -19,33 +19,32 @@ class HasModesIF {
static const ReturnValue_t INVALID_SUBMODE = MAKE_RETURN_CODE(0x04);
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::SYSTEM_MANAGER;
//! An object announces changing the mode. p1: target mode. p2: target submode
static const Event CHANGING_MODE = MAKE_EVENT(0, severity::INFO);
//! An Object announces its mode; parameter1 is mode, parameter2 is submode
static const Event MODE_INFO = MAKE_EVENT(1, severity::INFO);
static const Event CHANGING_MODE =
MAKE_EVENT(0, severity::INFO); //!< An object announces changing the mode. p1: target mode.
//!< p2: target submode
static const Event MODE_INFO = MAKE_EVENT(
1,
severity::INFO); //!< An Object announces its mode; parameter1 is mode, parameter2 is submode
static const Event FALLBACK_FAILED = MAKE_EVENT(2, severity::HIGH);
static const Event MODE_TRANSITION_FAILED = MAKE_EVENT(3, severity::LOW);
static const Event CANT_KEEP_MODE = MAKE_EVENT(4, severity::HIGH);
//! Indicates a bug or configuration failure: Object is in a mode it should never be in.
static const Event OBJECT_IN_INVALID_MODE = MAKE_EVENT(5, severity::LOW);
//! The mode is changed, but for some reason, the change is forced, i.e. EXTERNAL_CONTROL ignored.
//! p1: target mode. p2: target submode
static const Event FORCING_MODE = MAKE_EVENT(6, severity::MEDIUM);
//! A mode command was rejected by the called object. Par1: called object id, Par2: return code.
static const Event MODE_CMD_REJECTED = MAKE_EVENT(7, severity::LOW);
static const Event OBJECT_IN_INVALID_MODE =
MAKE_EVENT(5, severity::LOW); //!< Indicates a bug or configuration failure: Object is in a
//!< mode it should never be in.
static const Event FORCING_MODE = MAKE_EVENT(
6, severity::MEDIUM); //!< The mode is changed, but for some reason, the change is forced,
//!< i.e. EXTERNAL_CONTROL ignored. p1: target mode. p2: target submode
static const Event MODE_CMD_REJECTED =
MAKE_EVENT(7, severity::LOW); //!< A mode command was rejected by the called object. Par1:
//!< called object id, Par2: return code.
//! 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
static constexpr Mode_t MODE_ON = 1;
//! The device is powered off. The only command accepted in this mode is a mode change to on.
static constexpr Mode_t MODE_OFF = 0;
static constexpr Mode_t MODE_INVALID = -1;
static constexpr Mode_t MODE_UNDEFINED = -2;
//! To avoid checks against magic number "0".
static const Submode_t SUBMODE_NONE = 0;
static const Mode_t MODE_ON =
1; //!< 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
static const Mode_t MODE_OFF = 0; //!< The device is powered off. The only command accepted in
//!< this mode is a mode change to on.
static const Submode_t SUBMODE_NONE = 0; //!< To avoid checks against magic number "0".
virtual ~HasModesIF() {}
virtual MessageQueueId_t getCommandQueue() const = 0;

View File

@ -24,13 +24,3 @@ void ModeMessage::setCantReachMode(CommandMessage* message, ReturnValue_t reason
message->setParameter(reason);
message->setParameter2(0);
}
void ModeMessage::setModeAnnounceMessage(CommandMessage& message, bool recursive) {
Command_t cmd;
if (recursive) {
cmd = CMD_MODE_ANNOUNCE_RECURSIVELY;
} else {
cmd = CMD_MODE_ANNOUNCE;
}
message.setCommand(cmd);
}

View File

@ -1,42 +1,43 @@
#ifndef FSFW_MODES_MODEMESSAGE_H_
#define FSFW_MODES_MODEMESSAGE_H_
#include "fsfw/ipc/CommandMessage.h"
#include "../ipc/CommandMessage.h"
typedef uint32_t Mode_t;
typedef uint8_t Submode_t;
class ModeMessage {
private:
ModeMessage();
public:
static const uint8_t MESSAGE_ID = messagetypes::MODE_COMMAND;
//!> Command to set the specified Mode, replies are: REPLY_MODE_REPLY,
//! REPLY_WRONG_MODE_REPLY, and REPLY_REJECTED; don't add any replies,
//! as this will break the subsystem mode machine!!
static const Command_t CMD_MODE_COMMAND = MAKE_COMMAND_ID(0x01);
//!> Command to set the specified Mode, regardless of external control flag, replies
//! are: REPLY_MODE_REPLY, REPLY_WRONG_MODE_REPLY, and REPLY_REJECTED; don't add any
//! replies, as this will break the subsystem mode machine!!
static const Command_t CMD_MODE_COMMAND_FORCED = MAKE_COMMAND_ID(0xF1);
//!> Reply to a CMD_MODE_COMMAND or CMD_MODE_READ
static const Command_t REPLY_MODE_REPLY = MAKE_COMMAND_ID(0x02);
//!> Unrequested info about the current mode (used for composites to
//! inform their container of a changed mode)
static const Command_t REPLY_MODE_INFO = MAKE_COMMAND_ID(0x03);
//!> Reply in case a mode command can't be executed. Par1: returnCode, Par2: 0
static const Command_t REPLY_CANT_REACH_MODE = MAKE_COMMAND_ID(0x04);
//!> Reply to a CMD_MODE_COMMAND, indicating that a mode was commanded
//! and a transition started but was aborted; the parameters contain
//! the mode that was reached
static const Command_t REPLY_WRONG_MODE_REPLY = MAKE_COMMAND_ID(0x05);
//!> Command to read the current mode and reply with a REPLY_MODE_REPLY
static const Command_t CMD_MODE_READ = MAKE_COMMAND_ID(0x06);
//!> Command to trigger an ModeInfo Event. This command does NOT have a reply.
static const Command_t CMD_MODE_ANNOUNCE = MAKE_COMMAND_ID(0x07);
//!> Command to trigger an ModeInfo Event and to send this command to
//! every child. This command does NOT have a reply.
static const Command_t CMD_MODE_ANNOUNCE_RECURSIVELY = MAKE_COMMAND_ID(0x08);
ModeMessage() = delete;
static const Command_t CMD_MODE_COMMAND =
MAKE_COMMAND_ID(0x01); //!> Command to set the specified Mode, replies are: REPLY_MODE_REPLY,
//! REPLY_WRONG_MODE_REPLY, and REPLY_REJECTED; don't add any replies,
//! as this will break the subsystem mode machine!!
static const Command_t CMD_MODE_COMMAND_FORCED = MAKE_COMMAND_ID(
0xF1); //!> Command to set the specified Mode, regardless of external control flag, replies
//! are: REPLY_MODE_REPLY, REPLY_WRONG_MODE_REPLY, and REPLY_REJECTED; don't add any
//! replies, as this will break the subsystem mode machine!!
static const Command_t REPLY_MODE_REPLY =
MAKE_COMMAND_ID(0x02); //!> Reply to a CMD_MODE_COMMAND or CMD_MODE_READ
static const Command_t REPLY_MODE_INFO =
MAKE_COMMAND_ID(0x03); //!> Unrequested info about the current mode (used for composites to
//! inform their container of a changed mode)
static const Command_t REPLY_CANT_REACH_MODE = MAKE_COMMAND_ID(
0x04); //!> Reply in case a mode command can't be executed. Par1: returnCode, Par2: 0
static const Command_t REPLY_WRONG_MODE_REPLY =
MAKE_COMMAND_ID(0x05); //!> Reply to a CMD_MODE_COMMAND, indicating that a mode was commanded
//! and a transition started but was aborted; the parameters contain
//! the mode that was reached
static const Command_t CMD_MODE_READ = MAKE_COMMAND_ID(
0x06); //!> Command to read the current mode and reply with a REPLY_MODE_REPLY
static const Command_t CMD_MODE_ANNOUNCE = MAKE_COMMAND_ID(
0x07); //!> Command to trigger an ModeInfo Event. This command does NOT have a reply.
static const Command_t CMD_MODE_ANNOUNCE_RECURSIVELY =
MAKE_COMMAND_ID(0x08); //!> Command to trigger an ModeInfo Event and to send this command to
//! every child. This command does NOT have a reply.
static Mode_t getMode(const CommandMessage* message);
static Submode_t getSubmode(const CommandMessage* message);
@ -44,7 +45,6 @@ class ModeMessage {
static void setModeMessage(CommandMessage* message, Command_t command, Mode_t mode,
Submode_t submode);
static void setModeAnnounceMessage(CommandMessage& message, bool recursive);
static void setCantReachMode(CommandMessage* message, ReturnValue_t reason);
static void clear(CommandMessage* message);
};

View File

@ -95,16 +95,13 @@ void ObjectManager::initialize() {
for (auto const& it : objectList) {
result = it.second->initialize();
if (result != returnvalue::OK) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
object_id_t var = it.first;
sif::error << "ObjectManager::initialize: Object 0x" << std::hex << std::setw(8)
<< std::setfill('0') << it.first << " failed to initialize with code 0x" << result
<< std::dec << std::setfill(' ') << std::endl;
#else
sif::printError(
"ObjectManager::initialize: Object 0x%08x failed to initialize with code 0x%04x\n", var,
it.first);
#endif
<< std::setfill('0') << var
<< " failed to "
"initialize with code 0x"
<< result << std::dec << std::setfill(' ') << std::endl;
#endif
errorCount++;
}

View File

@ -16,9 +16,7 @@ elseif(FSFW_OSAL MATCHES "host")
else()
message(
WARNING
"${MSG_PREFIX} The FSFW_OSAL variable was not set. Assuming host OS..")
message(WARNING "The OS_FSFW variable was not set. Assuming host OS..")
# Not set. Assumuing this is a host build, try to determine host OS
if(WIN32)
add_subdirectory(host)

View File

@ -274,8 +274,6 @@ ReturnValue_t TcpTmTcServer::handleTmSending(socket_t connSocket, bool& tmSent)
ConstStorageAccessor storeAccessor(storeId);
ReturnValue_t result = tmStore->getData(storeId, storeAccessor);
if (result != returnvalue::OK) {
// Invalid entry, pop FIFO
tmtcBridge->tmFifo->pop();
return result;
}
if (wiretappingEnabled) {

View File

@ -66,8 +66,7 @@ class HasParametersIF {
* @param newValues
* @param startAtIndex Linear index, runs left to right, top to bottom for
* matrix indexes.
* @return returnvalue::OK if parameter is valid and a set function of the parameter wrapper was
* called.
* @return
*/
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueIdentifier,
ParameterWrapper *parameterWrapper,

View File

@ -211,13 +211,9 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
if (data == nullptr) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "ParameterWrapper::copyFrom: Called on read-only variable or "
"data pointer not set"
<< std::endl;
sif::warning << "ParameterWrapper::copyFrom: Called on read-only variable!" << std::endl;
#else
sif::printWarning(
"ParameterWrapper::copyFrom: Called on read-only variable "
"or data pointer not set\n");
sif::printWarning("ParameterWrapper::copyFrom: Called on read-only variable!\n");
#endif
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
return READONLY;
@ -226,9 +222,9 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
if (from->readonlyData == nullptr) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "ParameterWrapper::copyFrom: Source not set" << std::endl;
sif::warning << "ParameterWrapper::copyFrom: Source not set!" << std::endl;
#else
sif::printWarning("ParameterWrapper::copyFrom: Source not set\n");
sif::printWarning("ParameterWrapper::copyFrom: Source not set!\n");
#endif
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
return SOURCE_NOT_SET;
@ -237,9 +233,9 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
if (type != from->type) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "ParameterWrapper::copyFrom: Datatype missmatch" << std::endl;
sif::warning << "ParameterWrapper::copyFrom: Datatype missmatch!" << std::endl;
#else
sif::printWarning("ParameterWrapper::copyFrom: Datatype missmatch\n");
sif::printWarning("ParameterWrapper::copyFrom: Datatype missmatch!\n");
#endif
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
return DATATYPE_MISSMATCH;
@ -249,9 +245,9 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
if (rows == 0 or columns == 0) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "ParameterWrapper::copyFrom: Columns or rows zero" << std::endl;
sif::warning << "ParameterWrapper::copyFrom: Columns or rows zero!" << std::endl;
#else
sif::printWarning("ParameterWrapper::copyFrom: Columns or rows zero\n");
sif::printWarning("ParameterWrapper::copyFrom: Columns or rows zero!\n");
#endif
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
return COLUMN_OR_ROWS_ZERO;

View File

@ -29,9 +29,9 @@ class PowerSwitchIF {
static const ReturnValue_t FUSE_ON = MAKE_RETURN_CODE(3);
static const ReturnValue_t FUSE_OFF = MAKE_RETURN_CODE(4);
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PCDU_2;
//!< Someone detected that a switch went off which shouldn't. Severity:
//!< Low, Parameter1: switchId1, Parameter2: switchId2
static const Event SWITCH_WENT_OFF = MAKE_EVENT(0, severity::LOW);
static const Event SWITCH_WENT_OFF = MAKE_EVENT(
0, severity::LOW); //!< Someone detected that a switch went off which shouldn't. Severity:
//!< Low, Parameter1: switchId1, Parameter2: switchId2
/**
* send a direct command to the Power Unit to enable/disable the specified switch.
*

View File

@ -3,7 +3,7 @@
#include <fsfw/ipc/QueueFactory.h>
#include <fsfw/power/PowerSwitchIF.h>
PowerSwitcherComponent::PowerSwitcherComponent(object_id_t objectId, PowerSwitchIF* pwrSwitcher,
PowerSwitcherComponent::PowerSwitcherComponent(object_id_t objectId, PowerSwitchIF *pwrSwitcher,
power::Switch_t pwrSwitch)
: SystemObject(objectId),
switcher(pwrSwitcher, pwrSwitch),
@ -54,7 +54,7 @@ ReturnValue_t PowerSwitcherComponent::initialize() {
MessageQueueId_t PowerSwitcherComponent::getCommandQueue() const { return queue->getId(); }
void PowerSwitcherComponent::getMode(Mode_t* mode, Submode_t* submode) {
void PowerSwitcherComponent::getMode(Mode_t *mode, Submode_t *submode) {
*mode = this->mode;
*submode = this->submode;
}
@ -65,7 +65,7 @@ ReturnValue_t PowerSwitcherComponent::setHealth(HealthState health) {
}
ReturnValue_t PowerSwitcherComponent::checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t* msToReachTheMode) {
uint32_t *msToReachTheMode) {
*msToReachTheMode = 5000;
if (mode != MODE_ON and mode != MODE_OFF) {
return TRANS_NOT_ALLOWED;
@ -105,15 +105,3 @@ void PowerSwitcherComponent::setMode(Mode_t newMode, Submode_t newSubmode) {
}
HasHealthIF::HealthState PowerSwitcherComponent::getHealth() { return healthHelper.getHealth(); }
const HasHealthIF* PowerSwitcherComponent::getOptHealthIF() const { return this; }
const HasModesIF& PowerSwitcherComponent::getModeIF() const { return *this; }
ReturnValue_t PowerSwitcherComponent::connectModeTreeParent(HasModeTreeChildrenIF& parent) {
return parent.registerChild(*this);
}
object_id_t PowerSwitcherComponent::getObjectId() const { return SystemObject::getObjectId(); }
ModeTreeChildIF& PowerSwitcherComponent::getModeTreeChildIF() { return *this; }

View File

@ -8,8 +8,6 @@
#include <fsfw/objectmanager/SystemObject.h>
#include <fsfw/power/PowerSwitcher.h>
#include <fsfw/power/definitions.h>
#include <fsfw/subsystem/ModeTreeChildIF.h>
#include <fsfw/subsystem/ModeTreeConnectionIF.h>
#include <fsfw/tasks/ExecutableObjectIF.h>
class PowerSwitchIF;
@ -26,17 +24,12 @@ class PowerSwitchIF;
*/
class PowerSwitcherComponent : public SystemObject,
public ExecutableObjectIF,
public ModeTreeChildIF,
public ModeTreeConnectionIF,
public HasModesIF,
public HasHealthIF {
public:
PowerSwitcherComponent(object_id_t objectId, PowerSwitchIF *pwrSwitcher,
power::Switch_t pwrSwitch);
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF &parent) override;
ModeTreeChildIF &getModeTreeChildIF() override;
private:
MessageQueueIF *queue = nullptr;
PowerSwitcher switcher;
@ -63,10 +56,6 @@ class PowerSwitcherComponent : public SystemObject,
ReturnValue_t setHealth(HealthState health) override;
HasHealthIF::HealthState getHealth() override;
object_id_t getObjectId() const override;
const HasHealthIF *getOptHealthIF() const override;
const HasModesIF &getModeIF() const override;
};
#endif /* _FSFW_POWER_POWERSWITCHERCOMPONENT_H_ */

View File

@ -20,7 +20,6 @@ ReturnValue_t CService200ModeCommanding::isValidSubservice(uint8_t subservice) {
case (Subservice::COMMAND_MODE_COMMAND):
case (Subservice::COMMAND_MODE_READ):
case (Subservice::COMMAND_MODE_ANNCOUNCE):
case (Subservice::COMMAND_MODE_ANNOUNCE_RECURSIVELY):
return returnvalue::OK;
default:
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
@ -54,26 +53,15 @@ ReturnValue_t CService200ModeCommanding::checkInterfaceAndAcquireMessageQueue(
ReturnValue_t CService200ModeCommanding::prepareCommand(CommandMessage *message, uint8_t subservice,
const uint8_t *tcData, size_t tcDataLen,
uint32_t *state, object_id_t objectId) {
ReturnValue_t result = returnvalue::OK;
if (subservice == Subservice::COMMAND_MODE_ANNCOUNCE or
subservice == Subservice::COMMAND_MODE_ANNOUNCE_RECURSIVELY) {
bool recursive = true;
if (subservice == Subservice::COMMAND_MODE_ANNCOUNCE) {
recursive = false;
}
ModeMessage::setModeAnnounceMessage(*message, recursive);
} else {
ModePacket modeCommandPacket;
ReturnValue_t result =
modeCommandPacket.deSerialize(&tcData, &tcDataLen, SerializeIF::Endianness::BIG);
if (result != returnvalue::OK) {
return result;
}
ModeMessage::setModeMessage(message, ModeMessage::CMD_MODE_COMMAND, modeCommandPacket.getMode(),
modeCommandPacket.getSubmode());
ModePacket modeCommandPacket;
ReturnValue_t result =
modeCommandPacket.deSerialize(&tcData, &tcDataLen, SerializeIF::Endianness::BIG);
if (result != returnvalue::OK) {
return result;
}
ModeMessage::setModeMessage(message, ModeMessage::CMD_MODE_COMMAND, modeCommandPacket.getMode(),
modeCommandPacket.getSubmode());
return result;
}

View File

@ -41,6 +41,8 @@ class Service11TelecommandScheduling final : public PusServiceBase {
static constexpr ReturnValue_t INVALID_TIME_WINDOW = returnvalue::makeCode(CLASS_ID, 2);
static constexpr ReturnValue_t TIMESHIFTING_NOT_POSSIBLE = returnvalue::makeCode(CLASS_ID, 3);
static constexpr ReturnValue_t INVALID_RELATIVE_TIME = returnvalue::makeCode(CLASS_ID, 4);
static constexpr ReturnValue_t CONTAINED_TC_TOO_SMALL = returnvalue::makeCode(CLASS_ID, 5);
static constexpr ReturnValue_t CONTAINED_TC_CRC_MISSMATCH = returnvalue::makeCode(CLASS_ID, 6);
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PUS_SERVICE_11;

View File

@ -6,6 +6,8 @@
#include "fsfw/serialize/SerializeAdapter.h"
#include "fsfw/serviceinterface.h"
#include "fsfw/tmtcservices/AcceptsTelecommandsIF.h"
#include "fsfw/tmtcpacket/pus/tc/PusTcIF.h"
#include "fsfw/globalfunctions/CRC.h"
static constexpr auto DEF_END = SerializeIF::Endianness::BIG;
@ -77,7 +79,7 @@ inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::performService
// NOTE: The iterator is increased in the loop here. Increasing the iterator as for-loop arg
// does not work in this case as we are deleting the current element here.
for (auto it = telecommandMap.begin(); it != telecommandMap.end();) {
if (it->first <= static_cast<uint32_t>(tNow.tv_sec)) {
if (it->first <= tNow.tv_sec) {
if (schedulingEnabled) {
// release tc
TmTcMessage releaseMsg(it->second.storeAddr);
@ -171,6 +173,14 @@ inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::doInsertActivi
return returnvalue::FAILED;
}
if (size < PusTcIF::MIN_SIZE) {
return CONTAINED_TC_TOO_SMALL;
}
if (CRC::crc16ccitt(data, size) != 0) {
return CONTAINED_TC_CRC_MISSMATCH;
}
// store currentPacket and receive the store address
store_address_t addr{};
if (tcStore->addData(&addr, data, size) != returnvalue::OK ||

View File

@ -1,7 +1,5 @@
#include "fsfw/pus/Service17Test.h"
#include <fsfw/serialize/SerializeElement.h>
#include "fsfw/FSFW.h"
#include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/objectmanager/SystemObject.h"
@ -33,15 +31,6 @@ ReturnValue_t Service17Test::handleRequest(uint8_t subservice) {
}
return tmHelper.storeAndSendTmPacket();
}
case Subservice::PING_WITH_DATA: {
SerializeElement<uint32_t> receivedDataLen = currentPacket.getUserDataLen();
ReturnValue_t result =
tmHelper.prepareTmPacket(Subservice::PING_WITH_DATA_REPORT_WITH_SIZE, receivedDataLen);
if (result != returnvalue::OK) {
return result;
}
return tmHelper.storeAndSendTmPacket();
}
default:
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
}

View File

@ -32,9 +32,6 @@ class Service17Test : public PusServiceBase {
CONNECTION_TEST_REPORT = 2,
//! [EXPORT] : [COMMAND] Trigger test reply and test event
EVENT_TRIGGER_TEST = 128,
PING_WITH_DATA = 129,
//! [EXPORT] : [COMMAND] Report which reports the sent user data size
PING_WITH_DATA_REPORT_WITH_SIZE = 130
};
explicit Service17Test(PsbParams params);

View File

@ -208,17 +208,17 @@ ReturnValue_t Service3Housekeeping::handleReply(const CommandMessage* reply,
ReturnValue_t error = returnvalue::FAILED;
HousekeepingMessage::getHkRequestFailureReply(reply, &error);
failureParameter2 = error;
return returnvalue::FAILED;
return CommandingServiceBase::EXECUTION_COMPLETE;
}
default:
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "Service3Housekeeping::handleReply: Invalid reply with "
<< "reply command " << command << std::endl;
<< "reply command " << command << "!" << std::endl;
#else
sif::printWarning(
"Service3Housekeeping::handleReply: Invalid reply with "
"reply command %hu\n",
"reply command %hu!\n",
command);
#endif
return CommandingServiceBase::INVALID_REPLY;
@ -248,28 +248,19 @@ void Service3Housekeeping::handleUnrequestedReply(CommandMessage* reply) {
case (HousekeepingMessage::HK_REQUEST_FAILURE): {
break;
}
case (CommandMessage::REPLY_REJECTED): {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "Service3Housekeeping::handleUnrequestedReply: Unexpected reply "
"rejected with error code"
<< reply->getParameter() << std::endl;
#else
#endif
break;
}
default: {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "Service3Housekeeping::handleUnrequestedReply: Invalid reply with reply "
"command "
<< command << "" << std::endl;
<< command << "!" << std::endl;
#else
sif::printWarning(
"Service3Housekeeping::handleUnrequestedReply: Invalid reply with "
"reply command %hu\n",
"reply command %hu!\n",
command);
#endif
break;
return;
}
}
@ -284,7 +275,6 @@ void Service3Housekeeping::handleUnrequestedReply(CommandMessage* reply) {
"Could not generate reply!\n");
#endif
}
CommandingServiceBase::handleUnrequestedReply(reply);
}
MessageQueueId_t Service3Housekeeping::getHkQueue() const { return commandQueue->getId(); }

View File

@ -13,10 +13,8 @@ Service5EventReporting::Service5EventReporting(PsbParams params, size_t maxNumbe
storeHelper(params.apid),
tmHelper(params.serviceId, storeHelper, sendHelper),
maxNumberReportsPerCycle(maxNumberReportsPerCycle) {
auto mqArgs = MqArgs(getObjectId(), static_cast<void*>(this));
psbParams.name = "PUS 5 Event Reporting";
eventQueue = QueueFactory::instance()->createMessageQueue(
messageQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
eventQueue = QueueFactory::instance()->createMessageQueue(messageQueueDepth);
}
Service5EventReporting::~Service5EventReporting() {
@ -40,6 +38,9 @@ ReturnValue_t Service5EventReporting::performService() {
}
}
}
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "Service5EventReporting::generateEventReport: Too many events" << std::endl;
#endif
return returnvalue::OK;
}

View File

@ -42,7 +42,7 @@
class Service5EventReporting : public PusServiceBase {
public:
Service5EventReporting(PsbParams params, size_t maxNumberReportsPerCycle = 10,
uint32_t messageQueueDepth = 20);
uint32_t messageQueueDepth = 10);
~Service5EventReporting() override;
/***

View File

@ -6,10 +6,10 @@
class Service9TimeManagement : public PusServiceBase {
public:
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PUS_SERVICE_9;
//!< Clock has been set. P1: New Uptime. P2: Old Uptime
static constexpr Event CLOCK_SET = MAKE_EVENT(0, severity::INFO);
//!< Clock could not be set. P1: Returncode.
static constexpr Event CLOCK_SET_FAILURE = MAKE_EVENT(1, severity::LOW);
static constexpr Event CLOCK_SET =
MAKE_EVENT(0, severity::INFO); //!< Clock has been set. P1: New Uptime. P2: Old Uptime
static constexpr Event CLOCK_SET_FAILURE =
MAKE_EVENT(1, severity::LOW); //!< Clock could not be set. P1: Returncode.
static constexpr uint8_t CLASS_ID = CLASS_ID::PUS_SERVICE_9;

View File

@ -1,9 +1,9 @@
#ifndef FSFW_PUS_SERVICEPACKETS_SERVICE200PACKETS_H_
#define FSFW_PUS_SERVICEPACKETS_SERVICE200PACKETS_H_
#include "fsfw/modes/ModeMessage.h"
#include "fsfw/serialize/SerialLinkedListAdapter.h"
#include "fsfw/serialize/SerializeIF.h"
#include "../../modes/ModeMessage.h"
#include "../../serialize/SerialLinkedListAdapter.h"
#include "../../serialize/SerializeIF.h"
/**
* @brief Subservice 1, 2, 3, 4, 5

View File

@ -1,4 +1,3 @@
target_sources(${LIB_FSFW_NAME} PRIVATE Subsystem.cpp SubsystemBase.cpp
helper.cpp)
target_sources(${LIB_FSFW_NAME} PRIVATE Subsystem.cpp SubsystemBase.cpp)
add_subdirectory(modes)

View File

@ -1,13 +0,0 @@
#ifndef FSFW_SUBSYSTEM_HASMODETREECHILDRENIF_H_
#define FSFW_SUBSYSTEM_HASMODETREECHILDRENIF_H_
#include "ModeTreeChildIF.h"
class HasModeTreeChildrenIF {
public:
virtual ~HasModeTreeChildrenIF() = default;
virtual ReturnValue_t registerChild(const ModeTreeChildIF& child) = 0;
virtual MessageQueueId_t getCommandQueue() const = 0;
};
#endif // FSFW_SUBSYSTEM_HASMODETREECHILDRENIF_H_

View File

@ -1,15 +0,0 @@
#ifndef FSFW_SUBSYSTEM_MODETREECHILDIF_H_
#define FSFW_SUBSYSTEM_MODETREECHILDIF_H_
#include <fsfw/health/HasHealthIF.h>
#include <fsfw/modes/HasModesIF.h>
class ModeTreeChildIF {
public:
virtual ~ModeTreeChildIF() = default;
virtual object_id_t getObjectId() const = 0;
virtual const HasHealthIF* getOptHealthIF() const = 0;
virtual const HasModesIF& getModeIF() const = 0;
};
#endif /* FSFW_SUBSYSTEM_MODETREECHILDIF_H_ */

View File

@ -1,13 +0,0 @@
#ifndef FSFW_SUBSYSTEM_MODES_MODETREECONNECTIONIF_H_
#define FSFW_SUBSYSTEM_MODES_MODETREECONNECTIONIF_H_
#include "fsfw/subsystem/HasModeTreeChildrenIF.h"
class ModeTreeConnectionIF {
public:
virtual ~ModeTreeConnectionIF() = default;
virtual ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF& parent) = 0;
virtual ModeTreeChildIF& getModeTreeChildIF() = 0;
};
#endif /* FSFW_SRC_FSFW_SUBSYSTEM_MODES_MODETREECONNECTIONIF_H_ */

View File

@ -9,9 +9,9 @@
#include "fsfw/serialize/SerialLinkedListAdapter.h"
#include "fsfw/serialize/SerializeElement.h"
Subsystem::Subsystem(object_id_t setObjectId, uint32_t maxNumberOfSequences,
Subsystem::Subsystem(object_id_t setObjectId, object_id_t parent, uint32_t maxNumberOfSequences,
uint32_t maxNumberOfTables)
: SubsystemBase(setObjectId, 0),
: SubsystemBase(setObjectId, parent, 0),
isInTransition(false),
childrenChangedHealth(false),
currentTargetTable(),
@ -36,13 +36,6 @@ ReturnValue_t Subsystem::checkSequence(HybridIterator<ModeListEntry> iter,
for (; iter.value != nullptr; ++iter) {
if (!existsModeTable(iter->getTableId())) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
using namespace std;
sif::warning << "Subsystem::checkSequence: "
<< "Object " << setfill('0') << hex << "0x" << setw(8) << getObjectId()
<< setw(0) << ": Mode table for mode ID "
<< "0x" << setw(8) << iter->getTableId() << " does not exist" << dec << endl;
#endif
return TABLE_DOES_NOT_EXIST;
} else {
ReturnValue_t result = checkTable(getTable(iter->getTableId()));

View File

@ -33,12 +33,8 @@ struct SequenceEntry : public TableSequenceBase {
};
/**
* @brief This class extends the SubsystemBase to perform the management of mode tables
* and mode sequences
* @brief TODO: documentation missing
* @details
* This class is able to use mode tables and sequences to command all its children into the
* right mode. Fallback sequences can be used to handle failed transitions or have a fallback
* in case a component can't keep its current mode.
*/
class Subsystem : public SubsystemBase, public HasModeSequenceIF {
public:
@ -66,7 +62,8 @@ class Subsystem : public SubsystemBase, public HasModeSequenceIF {
* @param maxNumberOfSequences
* @param maxNumberOfTables
*/
Subsystem(object_id_t setObjectId, uint32_t maxNumberOfSequences, uint32_t maxNumberOfTables);
Subsystem(object_id_t setObjectId, object_id_t parent, uint32_t maxNumberOfSequences,
uint32_t maxNumberOfTables);
virtual ~Subsystem();
ReturnValue_t addSequence(SequenceEntry sequence);

View File

@ -1,24 +1,50 @@
#include "fsfw/subsystem/SubsystemBase.h"
#include "fsfw/FSFW.h"
#include "fsfw/ipc/QueueFactory.h"
#include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/serviceinterface.h"
#include "fsfw/subsystem/helper.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
SubsystemBase::SubsystemBase(object_id_t setObjectId, Mode_t initialMode,
SubsystemBase::SubsystemBase(object_id_t setObjectId, object_id_t parent, Mode_t initialMode,
uint16_t commandQueueDepth)
: SystemObject(setObjectId),
mode(initialMode),
commandQueue(QueueFactory::instance()->createMessageQueue(commandQueueDepth,
CommandMessage::MAX_MESSAGE_SIZE)),
healthHelper(this, setObjectId),
modeHelper(this) {
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
commandQueue = QueueFactory::instance()->createMessageQueue(
commandQueueDepth, CommandMessage::MAX_MESSAGE_SIZE, &mqArgs);
}
modeHelper(this),
parentId(parent) {}
SubsystemBase::~SubsystemBase() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }
ReturnValue_t SubsystemBase::registerChild(object_id_t objectId) {
ChildInfo info;
HasModesIF* child = ObjectManager::instance()->get<HasModesIF>(objectId);
// This is a rather ugly hack to have the changedHealth info for all
// children available.
HasHealthIF* healthChild = ObjectManager::instance()->get<HasHealthIF>(objectId);
if (child == nullptr) {
if (healthChild == nullptr) {
return CHILD_DOESNT_HAVE_MODES;
} else {
info.commandQueue = healthChild->getCommandQueue();
info.mode = MODE_OFF;
}
} else {
info.commandQueue = child->getCommandQueue();
info.mode = -1; // intentional to force an initial command during system startup
}
info.submode = SUBMODE_NONE;
info.healthChanged = false;
auto resultPair = childrenMap.emplace(objectId, info);
if (not resultPair.second) {
return COULD_NOT_INSERT_CHILD;
}
return returnvalue::OK;
}
ReturnValue_t SubsystemBase::checkStateAgainstTable(HybridIterator<ModeListEntry> tableIter,
Submode_t targetSubmode) {
std::map<object_id_t, ChildInfo>::iterator childIter;
@ -58,8 +84,7 @@ void SubsystemBase::executeTable(HybridIterator<ModeListEntry> tableIter, Submod
if ((iter = childrenMap.find(object)) == childrenMap.end()) {
// illegal table entry, should only happen due to misconfigured mode table
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << std::hex << SystemObject::getObjectId() << ": invalid mode table entry"
<< std::endl;
sif::debug << std::hex << getObjectId() << ": invalid mode table entry" << std::endl;
#endif
continue;
}
@ -130,15 +155,36 @@ ReturnValue_t SubsystemBase::updateChildChangedHealth(MessageQueueId_t queue, bo
MessageQueueId_t SubsystemBase::getCommandQueue() const { return commandQueue->getId(); }
ReturnValue_t SubsystemBase::initialize() {
ReturnValue_t result = modeHelper.initialize();
MessageQueueId_t parentQueue = MessageQueueIF::NO_QUEUE;
ReturnValue_t result = SystemObject::initialize();
if (result != returnvalue::OK) {
return result;
}
result = healthHelper.initialize();
if (parentId != objects::NO_OBJECT) {
SubsystemBase* parent = ObjectManager::instance()->get<SubsystemBase>(parentId);
if (parent == nullptr) {
return returnvalue::FAILED;
}
parentQueue = parent->getCommandQueue();
parent->registerChild(getObjectId());
}
result = healthHelper.initialize(parentQueue);
if (result != returnvalue::OK) {
return result;
}
return SystemObject::initialize();
result = modeHelper.initialize(parentQueue);
if (result != returnvalue::OK) {
return result;
}
return returnvalue::OK;
}
ReturnValue_t SubsystemBase::performOperation(uint8_t opCode) {
@ -191,14 +237,8 @@ ReturnValue_t SubsystemBase::handleModeReply(CommandMessage* message) {
}
ReturnValue_t SubsystemBase::checkTable(HybridIterator<ModeListEntry> tableIter) {
for (; tableIter.value != nullptr; ++tableIter) {
for (; tableIter.value != NULL; ++tableIter) {
if (childrenMap.find(tableIter.value->getObject()) == childrenMap.end()) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
using namespace std;
sif::warning << "SubsystemBase::checkTable: Could not find Object " << setfill('0') << hex
<< "0x" << setw(8) << tableIter.value->getObject() << " in object " << setw(8)
<< setw(0) << "0x" << setw(8) << SystemObject::getObjectId() << dec << std::endl;
#endif
return TABLE_CONTAINS_INVALID_OBJECT_ID;
}
}
@ -283,33 +323,4 @@ ReturnValue_t SubsystemBase::setHealth(HealthState health) {
HasHealthIF::HealthState SubsystemBase::getHealth() { return healthHelper.getHealth(); }
ReturnValue_t SubsystemBase::connectModeTreeParent(HasModeTreeChildrenIF& parent) {
return modetree::connectModeTreeParent(parent, *this, healthHelper, modeHelper);
}
object_id_t SubsystemBase::getObjectId() const { return SystemObject::getObjectId(); }
void SubsystemBase::modeChanged() {}
ReturnValue_t SubsystemBase::registerChild(const ModeTreeChildIF& child) {
ChildInfo info;
const HasModesIF& modeChild = child.getModeIF();
// intentional to force an initial command during system startup
info.commandQueue = modeChild.getCommandQueue();
info.mode = HasModesIF::MODE_UNDEFINED;
info.submode = SUBMODE_NONE;
info.healthChanged = false;
auto resultPair = childrenMap.emplace(child.getObjectId(), info);
if (not resultPair.second) {
return COULD_NOT_INSERT_CHILD;
}
return returnvalue::OK;
}
const HasHealthIF* SubsystemBase::getOptHealthIF() const { return this; }
const HasModesIF& SubsystemBase::getModeIF() const { return *this; }
ModeTreeChildIF& SubsystemBase::getModeTreeChildIF() { return *this; }

View File

@ -3,35 +3,23 @@
#include <map>
#include "fsfw/container/HybridIterator.h"
#include "fsfw/health/HasHealthIF.h"
#include "fsfw/health/HealthHelper.h"
#include "fsfw/ipc/MessageQueueIF.h"
#include "fsfw/modes/HasModesIF.h"
#include "fsfw/objectmanager/SystemObject.h"
#include "fsfw/returnvalues/returnvalue.h"
#include "fsfw/subsystem/HasModeTreeChildrenIF.h"
#include "fsfw/subsystem/ModeTreeConnectionIF.h"
#include "fsfw/tasks/ExecutableObjectIF.h"
#include "../container/HybridIterator.h"
#include "../health/HasHealthIF.h"
#include "../health/HealthHelper.h"
#include "../ipc/MessageQueueIF.h"
#include "../modes/HasModesIF.h"
#include "../objectmanager/SystemObject.h"
#include "../returnvalues/returnvalue.h"
#include "../tasks/ExecutableObjectIF.h"
#include "modes/HasModeSequenceIF.h"
/**
* @defgroup subsystems Subsystem Objects
* All Subsystem and Assemblies can derive from this class. It contains helper classes to
* perform mode and health handling, which allows OBSW developers to build a mode tree for
* the whole satellite.
*
* Aside from setting up a mode tree and being able to executing mode tables, this class does not
* provide an implementation on what to do with the features. To build a mode tree, helper classes
* like the #AssemblyBase or the #Subsystem class extend and use the functionality of the base
* class.
* Contains all Subsystem and Assemblies
*/
class SubsystemBase : public SystemObject,
public HasModesIF,
public HasHealthIF,
public HasModeTreeChildrenIF,
public ModeTreeConnectionIF,
public ModeTreeChildIF,
public ExecutableObjectIF {
public:
static const uint8_t INTERFACE_ID = CLASS_ID::SUBSYSTEM_BASE;
@ -41,34 +29,32 @@ class SubsystemBase : public SystemObject,
static const ReturnValue_t COULD_NOT_INSERT_CHILD = MAKE_RETURN_CODE(0x04);
static const ReturnValue_t TABLE_CONTAINS_INVALID_OBJECT_ID = MAKE_RETURN_CODE(0x05);
SubsystemBase(object_id_t setObjectId, Mode_t initialMode = 0, uint16_t commandQueueDepth = 8);
SubsystemBase(object_id_t setObjectId, object_id_t parent, Mode_t initialMode = 0,
uint16_t commandQueueDepth = 8);
virtual ~SubsystemBase();
virtual MessageQueueId_t getCommandQueue() const override;
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF &parent) override;
ModeTreeChildIF &getModeTreeChildIF() override;
/**
* Function to register the child objects.
* Performs a checks if the child does implement HasHealthIF and/or HasModesIF
*
* Also adds them to the internal childrenMap.
* Also adds them to the internal childrenMap.
*
* @param objectId
* @return returnvalue::OK if successful
* CHILD_DOESNT_HAVE_MODES if Child is no HasHealthIF and no HasModesIF
* COULD_NOT_INSERT_CHILD If the Child could not be added to the ChildrenMap
* CHILD_DOESNT_HAVE_MODES if Child is no HasHealthIF and no HasModesIF
* COULD_NOT_INSERT_CHILD If the Child could not be added to the ChildrenMap
*/
ReturnValue_t registerChild(const ModeTreeChildIF &child) override;
ReturnValue_t registerChild(object_id_t objectId);
ReturnValue_t initialize() override;
virtual ReturnValue_t initialize() override;
ReturnValue_t performOperation(uint8_t opCode) override;
virtual ReturnValue_t performOperation(uint8_t opCode) override;
ReturnValue_t setHealth(HealthState health) override;
virtual ReturnValue_t setHealth(HealthState health) override;
HasHealthIF::HealthState getHealth() override;
virtual HasHealthIF::HealthState getHealth() override;
protected:
struct ChildInfo {
@ -95,6 +81,8 @@ class SubsystemBase : public SystemObject,
ModeHelper modeHelper;
const object_id_t parentId;
typedef std::map<object_id_t, ChildInfo> ChildrenMap;
ChildrenMap childrenMap;
@ -107,7 +95,6 @@ class SubsystemBase : public SystemObject,
Submode_t targetSubmode);
/**
* This function takes care of sending all according mode commands specified inside a mode table.
* We need to know the target Submode, as children are able to inherit the submode
* Still, we have a default for all child implementations which do not use submode inheritance
*/
@ -141,10 +128,6 @@ class SubsystemBase : public SystemObject,
virtual void getMode(Mode_t *mode, Submode_t *submode) override;
object_id_t getObjectId() const override;
const HasHealthIF *getOptHealthIF() const override;
const HasModesIF &getModeIF() const override;
virtual void setToExternalControl() override;
virtual void announceMode(bool recursive) override;

View File

@ -1,13 +0,0 @@
#include "helper.h"
ReturnValue_t modetree::connectModeTreeParent(HasModeTreeChildrenIF& parent,
const ModeTreeChildIF& child,
HealthHelper& healthHelper, ModeHelper& modeHelper) {
ReturnValue_t result = parent.registerChild(child);
if (result != returnvalue::OK) {
return result;
}
healthHelper.setParentQueue(parent.getCommandQueue());
modeHelper.setParentQueue(parent.getCommandQueue());
return returnvalue::OK;
}

View File

@ -1,14 +0,0 @@
#ifndef FSFW_SUBSYSTEM_HELPER_H_
#define FSFW_SUBSYSTEM_HELPER_H_
#include "HasModeTreeChildrenIF.h"
#include "fsfw/health/HealthHelper.h"
namespace modetree {
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF& parent, const ModeTreeChildIF& child,
HealthHelper& healthHelper, ModeHelper& modeHelper);
}
#endif /* FSFW_SRC_FSFW_SUBSYSTEM_HELPER_H_ */

View File

@ -4,13 +4,14 @@
AbstractTemperatureSensor::AbstractTemperatureSensor(object_id_t setObjectid,
ThermalModuleIF *thermalModule)
: SystemObject(setObjectid), healthHelper(this, setObjectid), parameterHelper(this) {
if (thermalModule != nullptr) {
: SystemObject(setObjectid),
commandQueue(NULL),
healthHelper(this, setObjectid),
parameterHelper(this) {
if (thermalModule != NULL) {
thermalModule->registerSensor(this);
}
auto mqArgs = MqArgs(setObjectid, static_cast<void *>(this));
commandQueue = QueueFactory::instance()->createMessageQueue(
3, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
commandQueue = QueueFactory::instance()->createMessageQueue();
}
AbstractTemperatureSensor::~AbstractTemperatureSensor() {

View File

@ -51,7 +51,7 @@ class AbstractTemperatureSensor : public HasHealthIF,
HasHealthIF::HealthState getHealth();
protected:
MessageQueueIF* commandQueue = nullptr;
MessageQueueIF* commandQueue;
HealthHelper healthHelper;
ParameterHelper parameterHelper;

View File

@ -12,9 +12,7 @@ Heater::Heater(uint32_t objectId, uint8_t switch0, uint8_t switch1)
switch1(switch1),
heaterOnCountdown(10800000) /*about two orbits*/,
parameterHelper(this) {
auto mqArgs = MqArgs(objectId, static_cast<void*>(this));
eventQueue = QueueFactory::instance()->createMessageQueue(
3, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
eventQueue = QueueFactory::instance()->createMessageQueue();
}
Heater::~Heater() { QueueFactory::instance()->deleteMessageQueue(eventQueue); }

View File

@ -13,9 +13,9 @@ class ThermalComponentIF : public HasParametersIF {
static const Event COMPONENT_TEMP_HIGH = MAKE_EVENT(2, severity::LOW);
static const Event COMPONENT_TEMP_OOL_LOW = MAKE_EVENT(3, severity::LOW);
static const Event COMPONENT_TEMP_OOL_HIGH = MAKE_EVENT(4, severity::LOW);
//!< Is thrown when a device should start-up, but the temperature is out
//!< of OP range. P1: thermalState of the component, P2: 0
static const Event TEMP_NOT_IN_OP_RANGE = MAKE_EVENT(5, severity::LOW);
static const Event TEMP_NOT_IN_OP_RANGE = MAKE_EVENT(
5, severity::LOW); //!< Is thrown when a device should start-up, but the temperature is out
//!< of OP range. P1: thermalState of the component, P2: 0
static const uint8_t INTERFACE_ID = CLASS_ID::THERMAL_COMPONENT_IF;
static const ReturnValue_t INVALID_TARGET_STATE = MAKE_RETURN_CODE(1);

View File

@ -246,20 +246,6 @@ ReturnValue_t CCSDSTime::convertFromASCII(Clock::TimeOfDay_t* to, const uint8_t*
return UNSUPPORTED_TIME_FORMAT;
}
ReturnValue_t CCSDSTime::convertToAsciiWithSecs(int8_t* to, const Clock::TimeOfDay_t* from,
uint8_t length) {
if (from == nullptr or to == nullptr) {
return returnvalue::FAILED;
}
int count = snprintf(reinterpret_cast<char*>(to), length,
"%4" SCNu32 "-%2" SCNu32 "-%2" SCNu32 "T%2" SCNu32 ":%2" SCNu32 ":%2" SCNu32,
from->year, from->month, from->day, from->hour, from->minute, from->second);
if (count >= length) {
return returnvalue::FAILED;
}
return returnvalue::OK;
}
ReturnValue_t CCSDSTime::checkCcs(const uint8_t* time, uint8_t length) {
const Ccs_mseconds* time_struct = reinterpret_cast<const Ccs_mseconds*>(time);

View File

@ -207,8 +207,7 @@ class CCSDSTime {
static ReturnValue_t convertFromASCII(Clock::TimeOfDay_t *to, uint8_t const *from,
uint8_t length);
static ReturnValue_t convertToAsciiWithSecs(int8_t *to, const Clock::TimeOfDay_t *from,
uint8_t length);
static uint32_t subsecondsToMicroseconds(uint16_t subseconds);
private:

View File

@ -1,11 +1,7 @@
#include "fsfw/timemanager/Countdown.h"
Countdown::Countdown(uint32_t initialTimeout, bool startImmediately) : timeout(initialTimeout) {
if (startImmediately) {
setTimeout(initialTimeout);
} else {
timeout = initialTimeout;
}
Countdown::Countdown(uint32_t initialTimeout) : timeout(initialTimeout) {
setTimeout(initialTimeout);
}
Countdown::~Countdown() {}

View File

@ -26,9 +26,8 @@ class Countdown {
* Otherwise a call to hasTimedOut might return True.
*
* @param initialTimeout Countdown duration in milliseconds
* @param startImmediately Set to false if countdown should not be started immediately
*/
Countdown(uint32_t initialTimeout = 0, bool startImmediately = true);
Countdown(uint32_t initialTimeout = 0);
~Countdown();
/**
* Call to set a new countdown duration.

View File

@ -33,47 +33,50 @@ class TmStoreBackendIF : public HasParametersIF {
static const ReturnValue_t INVALID_REQUEST = MAKE_RETURN_CODE(15);
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::MEMORY;
//! Initiating sending data to store failed. Low, par1:
//! returnCode, par2: integer (debug info)
static const Event STORE_SEND_WRITE_FAILED = MAKE_EVENT(0, severity::LOW);
//! Data was sent, but writing failed. Low, par1: returnCode, par2: 0
static const Event STORE_WRITE_FAILED = MAKE_EVENT(1, severity::LOW);
//! Initiating reading data from store failed. Low, par1: returnCode, par2: 0
static const Event STORE_SEND_READ_FAILED = MAKE_EVENT(2, severity::LOW);
//! Data was requested, but access failed. Low, par1: returnCode, par2: 0
static const Event STORE_READ_FAILED = MAKE_EVENT(3, severity::LOW);
//! An unexpected TM packet or data message occurred. Low, par1: 0, par2: integer (debug info)
static const Event UNEXPECTED_MSG = MAKE_EVENT(4, severity::LOW);
//! Storing data failed. May simply be a full store. Low, par1: returnCode,
//! par2: integer (sequence count of failed packet).
static const Event STORING_FAILED = MAKE_EVENT(5, severity::LOW);
//! Dumping retrieved data failed. Low, par1: returnCode,
//! par2: integer (sequence count of failed packet).
static const Event TM_DUMP_FAILED = MAKE_EVENT(6, severity::LOW);
//! Corrupted init data or read error. Low, par1: returnCode, par2: integer (debug info)
//! Store was not initialized. Starts empty. Info, parameters both zero.
static const Event STORE_INIT_FAILED = MAKE_EVENT(7, severity::LOW);
//! Data was read out, but it is inconsistent. Low par1:
//! Memory address of corruption, par2: integer (debug info)
static const Event STORE_INIT_EMPTY = MAKE_EVENT(8, severity::INFO);
static const Event STORE_CONTENT_CORRUPTED = MAKE_EVENT(9, severity::LOW);
//! Info event indicating the store will be initialized, either at boot or after IOB switch.
//! Info. pars: 0
static const Event STORE_INITIALIZE = MAKE_EVENT(10, severity::INFO);
//! Info event indicating the store was successfully initialized, either at boot or after
//! IOB switch. Info. pars: 0
static const Event INIT_DONE = MAKE_EVENT(11, severity::INFO);
//! Info event indicating that dumping finished successfully.
//! par1: Number of dumped packets. par2: APID/SSC (16bits each)
static const Event DUMP_FINISHED = MAKE_EVENT(12, severity::INFO);
//! Info event indicating that deletion finished successfully.
//! par1:Number of deleted packets. par2: APID/SSC (16bits each)
static const Event DELETION_FINISHED = MAKE_EVENT(13, severity::INFO);
//! Info event indicating that something went wrong during deletion. pars: 0
static const Event DELETION_FAILED = MAKE_EVENT(14, severity::LOW);
//! Info that the a auto catalog report failed
static const Event AUTO_CATALOGS_SENDING_FAILED = MAKE_EVENT(15, severity::INFO);
static const Event STORE_SEND_WRITE_FAILED =
MAKE_EVENT(0, severity::LOW); //!< Initiating sending data to store failed. Low, par1:
//!< returnCode, par2: integer (debug info)
static const Event STORE_WRITE_FAILED = MAKE_EVENT(
1, severity::LOW); //!< Data was sent, but writing failed. Low, par1: returnCode, par2: 0
static const Event STORE_SEND_READ_FAILED =
MAKE_EVENT(2, severity::LOW); //!< Initiating reading data from store failed. Low, par1:
//!< returnCode, par2: 0
static const Event STORE_READ_FAILED = MAKE_EVENT(
3, severity::LOW); //!< Data was requested, but access failed. Low, par1: returnCode, par2: 0
static const Event UNEXPECTED_MSG =
MAKE_EVENT(4, severity::LOW); //!< An unexpected TM packet or data message occurred. Low,
//!< par1: 0, par2: integer (debug info)
static const Event STORING_FAILED = MAKE_EVENT(
5, severity::LOW); //!< Storing data failed. May simply be a full store. Low, par1:
//!< returnCode, par2: integer (sequence count of failed packet).
static const Event TM_DUMP_FAILED =
MAKE_EVENT(6, severity::LOW); //!< Dumping retrieved data failed. Low, par1: returnCode,
//!< par2: integer (sequence count of failed packet).
static const Event STORE_INIT_FAILED =
MAKE_EVENT(7, severity::LOW); //!< Corrupted init data or read error. Low, par1: returnCode,
//!< par2: integer (debug info)
static const Event STORE_INIT_EMPTY = MAKE_EVENT(
8, severity::INFO); //!< Store was not initialized. Starts empty. Info, parameters both zero.
static const Event STORE_CONTENT_CORRUPTED =
MAKE_EVENT(9, severity::LOW); //!< Data was read out, but it is inconsistent. Low par1:
//!< Memory address of corruption, par2: integer (debug info)
static const Event STORE_INITIALIZE =
MAKE_EVENT(10, severity::INFO); //!< Info event indicating the store will be initialized,
//!< either at boot or after IOB switch. Info. pars: 0
static const Event INIT_DONE = MAKE_EVENT(
11, severity::INFO); //!< Info event indicating the store was successfully initialized,
//!< either at boot or after IOB switch. Info. pars: 0
static const Event DUMP_FINISHED = MAKE_EVENT(
12, severity::INFO); //!< Info event indicating that dumping finished successfully. par1:
//!< Number of dumped packets. par2: APID/SSC (16bits each)
static const Event DELETION_FINISHED = MAKE_EVENT(
13, severity::INFO); //!< Info event indicating that deletion finished successfully. par1:
//!< Number of deleted packets. par2: APID/SSC (16bits each)
static const Event DELETION_FAILED = MAKE_EVENT(
14,
severity::LOW); //!< Info event indicating that something went wrong during deletion. pars: 0
static const Event AUTO_CATALOGS_SENDING_FAILED =
MAKE_EVENT(15, severity::INFO); //!< Info that the a auto catalog report failed
virtual ~TmStoreBackendIF() {}

View File

@ -6,12 +6,47 @@
#include "fsfw/returnvalues/returnvalue.h"
#include "tmStorageConf.h"
class PusTmReader;
class SpacePacketReader;
class TmPacketMinimal;
class SpacePacketBase;
class TmStoreBackendIF;
class TmStoreFrontendIF {
public:
virtual TmStoreBackendIF* getBackend() const = 0;
/**
* What do I need to implement here?
* This is propably used by PUS Service 15 so we should propably check for messages..
* Provide base implementation?
* @param opCode
* @return
*/
virtual ReturnValue_t performOperation(uint8_t opCode) = 0;
/**
* Callback from the back-end to indicate a certain packet was received.
* front-end takes care of discarding/downloading the packet.
* @param packet Pointer to the newly received Space Packet.
* @param address Start address of the packet found
* @param isLastPacket Indicates if no more packets can be fetched.
* @return If more packets shall be fetched, returnvalue::OK must be returned.
* Any other code stops fetching packets.
*/
virtual ReturnValue_t packetRetrieved(TmPacketMinimal* packet, uint32_t address) = 0;
virtual void noMorePacketsInStore() = 0;
virtual void handleRetrievalFailed(ReturnValue_t errorCode, uint32_t parameter1 = 0,
uint32_t parameter2 = 0) = 0;
/**
* To get the queue where commands shall be sent.
* @return Id of command queue.
*/
virtual MessageQueueId_t getCommandQueue() const = 0;
virtual ReturnValue_t fetchPackets(ApidSsc start, ApidSsc end) = 0;
virtual ReturnValue_t deletePackets(ApidSsc upTo) = 0;
virtual ReturnValue_t checkPacket(SpacePacketBase* tmPacket) = 0;
virtual bool isEnabled() const = 0;
virtual void setEnabled(bool enabled) = 0;
virtual void resetDownlinkedPacketCount() = 0;
virtual ReturnValue_t setDumpTarget(object_id_t dumpTarget) = 0;
static const uint8_t INTERFACE_ID = CLASS_ID::TM_STORE_FRONTEND_IF;
static const ReturnValue_t BUSY = MAKE_RETURN_CODE(1);
static const ReturnValue_t LAST_PACKET_FOUND = MAKE_RETURN_CODE(2);
@ -22,38 +57,7 @@ class TmStoreFrontendIF {
static const ReturnValue_t ALL_DELETED = MAKE_RETURN_CODE(7);
static const ReturnValue_t INVALID_DATA = MAKE_RETURN_CODE(8);
static const ReturnValue_t NOT_READY = MAKE_RETURN_CODE(9);
virtual ~TmStoreFrontendIF() = default;
/**
* To get the queue where commands shall be sent.
* @return Id of command queue.
*/
virtual MessageQueueId_t getCommandQueue() const = 0;
virtual TmStoreBackendIF* getBackend() const = 0;
/**
* Callback from the back-end to indicate a certain packet was received.
* front-end takes care of discarding/downloading the packet.
* @param packet Pointer to the newly received Space Packet.
* @param address Start address of the packet found
* @param isLastPacket Indicates if no more packets can be fetched.
* @return If more packets shall be fetched, returnvalue::OK must be returned.
* Any other code stops fetching packets.
*/
virtual ReturnValue_t packetRetrieved(PusTmReader* packet, uint32_t address) = 0;
virtual void noMorePacketsInStore() = 0;
virtual void handleRetrievalFailed(ReturnValue_t errorCode, uint32_t parameter1 = 0,
uint32_t parameter2 = 0) = 0;
virtual ReturnValue_t fetchPackets(ApidSsc start, ApidSsc end) = 0;
virtual ReturnValue_t deletePackets(ApidSsc upTo) = 0;
virtual ReturnValue_t checkPacket(SpacePacketReader* tmPacket) = 0;
virtual bool isEnabled() const = 0;
virtual void setEnabled(bool enabled) = 0;
virtual void resetDownlinkedPacketCount() = 0;
virtual ReturnValue_t setDumpTarget(object_id_t dumpTarget) = 0;
virtual ~TmStoreFrontendIF() {}
};
#endif /* FSFW_TMTCSERVICES_TMSTOREFRONTENDIF_H_ */

View File

@ -1,14 +0,0 @@
#ifndef FSFW_SRC_FSFW_TMSTORAGE_TMSTOREBACKENDSIMPLEIF_H_
#define FSFW_SRC_FSFW_TMSTORAGE_TMSTOREBACKENDSIMPLEIF_H_
#include <fsfw/ipc/messageQueueDefinitions.h>
class TmStoreFrontendSimpleIF {
public:
virtual ~TmStoreFrontendSimpleIF() = default;
private:
virtual MessageQueueId_t getCommandQueue() const = 0;
};
#endif /* FSFW_SRC_FSFW_TMSTORAGE_TMSTOREBACKENDSIMPLEIF_H_ */

View File

@ -1,10 +1,6 @@
#ifndef FSFW_TMSTORAGE_TMSTOREPACKETS_H_
#define FSFW_TMSTORAGE_TMSTOREPACKETS_H_
#include <fsfw/tmtcpacket/pus/tm/PusTmReader.h>
#include <vector>
#include "fsfw/globalfunctions/timevalOperations.h"
#include "fsfw/serialize/SerialBufferAdapter.h"
#include "fsfw/serialize/SerialFixedArrayListAdapter.h"
@ -28,7 +24,7 @@ class ServiceSubservice : public SerialLinkedListAdapter<SerializeIF> {
class ApidSsc : public SerializeIF {
public:
ApidSsc() : apid(ccsds::LIMIT_APID), ssc(0) {}
ApidSsc() : apid(SpacePacketBase::LIMIT_APID), ssc(0) {}
ApidSsc(uint16_t apid, uint16_t ssc) : apid(apid), ssc(ssc) {}
uint16_t apid;
uint16_t ssc;
@ -66,59 +62,51 @@ class ChangeSelectionDefinition : public SerialLinkedListAdapter<SerializeIF> {
class TmPacketInformation : public SerializeIF {
public:
TmPacketInformation(PusTmReader* packet, size_t timestampLen) : rawTimestamp(timestampLen) {
setContent(packet);
}
TmPacketInformation(size_t timestampLen)
: apid(ccsds::LIMIT_APID),
TmPacketInformation(TmPacketMinimal* packet) { setContent(packet); }
TmPacketInformation()
: apid(SpacePacketBase::LIMIT_APID),
sourceSequenceCount(0),
serviceType(0),
serviceSubtype(0),
subCounter(0),
rawTimestamp(timestampLen) {}
subCounter(0) {}
void reset() {
apid = ccsds::LIMIT_APID;
apid = SpacePacketBase::LIMIT_APID;
sourceSequenceCount = 0;
serviceType = 0;
serviceSubtype = 0;
subCounter = 0;
memset(rawTimestamp.data(), 0, rawTimestamp.size());
memset(rawTimestamp, 0, sizeof(rawTimestamp));
}
void setContent(PusTmReader* packet) {
apid = packet->getApid();
sourceSequenceCount = packet->getSequenceCount();
void setContent(TmPacketMinimal* packet) {
apid = packet->getAPID();
sourceSequenceCount = packet->getPacketSequenceCount();
serviceType = packet->getService();
serviceSubtype = packet->getSubService();
subCounter = packet->getMessageTypeCounter();
memset(rawTimestamp.data(), 0, rawTimestamp.size());
// TODO: Fix all of this
// const uint8_t* pField = NULL;
// uint32_t size = 0;
// auto* timeReader = packet->getTimeReader();
// ReturnValue_t result = packet->getPacketTimeRaw(&pField, &size);
// if (result != returnvalue::OK) {
// return;
//}
// if (*pField == CCSDSTime::P_FIELD_CDS_SHORT && size <= TimeStamperIF::MISSION_TIMESTAMP_SIZE)
// {
// Shortcut to avoid converting CDS back and forth.
// TODO: Fix
// memcpy(rawTimestamp, pField, size);
// return;
// }
// timeval time = {0, 0};
// result = packet->getPacketTime(&time);
// if (result != returnvalue::OK) {
// return;
// }
//
// CCSDSTime::CDS_short cdsFormat;
// result = CCSDSTime::convertToCcsds(&cdsFormat, &time);
// if (result != returnvalue::OK) {
// return;
// }
// TODO: Fix
// memcpy(rawTimestamp, &cdsFormat, sizeof(cdsFormat));
subCounter = packet->getPacketSubcounter();
memset(rawTimestamp, 0, sizeof(rawTimestamp));
const uint8_t* pField = NULL;
uint32_t size = 0;
ReturnValue_t result = packet->getPacketTimeRaw(&pField, &size);
if (result != returnvalue::OK) {
return;
}
if (*pField == CCSDSTime::P_FIELD_CDS_SHORT && size <= TimeStamperIF::MISSION_TIMESTAMP_SIZE) {
// Shortcut to avoid converting CDS back and forth.
memcpy(rawTimestamp, pField, size);
return;
}
timeval time = {0, 0};
result = packet->getPacketTime(&time);
if (result != returnvalue::OK) {
return;
}
CCSDSTime::CDS_short cdsFormat;
result = CCSDSTime::convertToCcsds(&cdsFormat, &time);
if (result != returnvalue::OK) {
return;
}
memcpy(rawTimestamp, &cdsFormat, sizeof(cdsFormat));
}
void setContent(TmPacketInformation* content) {
apid = content->apid;
@ -126,10 +114,9 @@ class TmPacketInformation : public SerializeIF {
serviceType = content->serviceType;
serviceSubtype = content->serviceSubtype;
subCounter = content->subCounter;
// TODO: Fix
// memcpy(rawTimestamp, content->rawTimestamp, sizeof(rawTimestamp));
memcpy(rawTimestamp, content->rawTimestamp, sizeof(rawTimestamp));
}
bool isValid() const { return (apid < ccsds::LIMIT_APID) ? true : false; }
bool isValid() const { return (apid < SpacePacketBase::LIMIT_APID) ? true : false; }
static void reset(TmPacketInformation* packet) { packet->reset(); }
static bool isOlderThan(const TmPacketInformation* packet, const timeval* cmpTime) {
@ -229,7 +216,7 @@ class TmPacketInformation : public SerializeIF {
if (result != returnvalue::OK) {
return result;
}
SerialBufferAdapter<uint8_t> adapter(rawTimestamp.data(), rawTimestamp.size());
SerialBufferAdapter<uint8_t> adapter(rawTimestamp, sizeof(rawTimestamp));
return adapter.serialize(buffer, size, maxSize, streamEndianness);
}
@ -240,7 +227,7 @@ class TmPacketInformation : public SerializeIF {
size += SerializeAdapter::getSerializedSize(&serviceType);
size += SerializeAdapter::getSerializedSize(&serviceSubtype);
size += SerializeAdapter::getSerializedSize(&subCounter);
SerialBufferAdapter<uint8_t> adapter(rawTimestamp.data(), rawTimestamp.size());
SerialBufferAdapter<uint8_t> adapter(rawTimestamp, sizeof(rawTimestamp));
size += adapter.getSerializedSize();
return size;
};
@ -266,7 +253,7 @@ class TmPacketInformation : public SerializeIF {
if (result != returnvalue::OK) {
return result;
}
SerialBufferAdapter<uint8_t> adapter(rawTimestamp.data(), rawTimestamp.size());
SerialBufferAdapter<uint8_t> adapter(rawTimestamp, sizeof(rawTimestamp));
return adapter.deSerialize(buffer, size, streamEndianness);
}
@ -276,6 +263,6 @@ class TmPacketInformation : public SerializeIF {
uint8_t serviceType;
uint8_t serviceSubtype;
uint8_t subCounter;
std::vector<uint8_t> rawTimestamp;
uint8_t rawTimestamp[TimeStamperIF::MISSION_TIMESTAMP_SIZE];
};
#endif /* FSFW_TMSTORAGE_TMSTOREPACKETS_H_ */

View File

@ -27,10 +27,8 @@ CommandingServiceBase::CommandingServiceBase(object_id_t setObjectId, uint16_t a
verificationReporter(verificationReporter),
commandMap(numberOfParallelCommands),
name(name) {
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
size_t mqSz = MessageQueueMessage::MAX_MESSAGE_SIZE;
commandQueue = QueueFactory::instance()->createMessageQueue(queueDepth, mqSz, &mqArgs);
requestQueue = QueueFactory::instance()->createMessageQueue(queueDepth, mqSz, &mqArgs);
commandQueue = QueueFactory::instance()->createMessageQueue(queueDepth);
requestQueue = QueueFactory::instance()->createMessageQueue(queueDepth);
}
void CommandingServiceBase::setPacketSource(object_id_t packetSource_) {
@ -225,7 +223,7 @@ void CommandingServiceBase::handleReplyHandlerResult(ReturnValue_t result, Comma
// In case a new command is to be sent immediately, this is performed here.
// If no new command is sent, only analyse reply result by initializing
// sendResult as returnvalue::OK
// sendResult as RETURN_OK
ReturnValue_t sendResult = returnvalue::OK;
if (nextCommand->getCommand() != CommandMessage::CMD_NONE) {
sendResult = commandQueue->sendMessage(reply->getSender(), nextCommand);

View File

@ -27,8 +27,8 @@ ReturnValue_t PusServiceBase::performOperation(uint8_t opCode) {
ReturnValue_t result = performService();
if (result != returnvalue::OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "PusService " << static_cast<int>(psbParams.serviceId)
<< ": performService returned with " << static_cast<uint16_t>(result) << std::endl;
sif::error << "PusService " << psbParams.serviceId << ": performService returned with "
<< static_cast<uint16_t>(result) << std::endl;
#endif
return returnvalue::FAILED;
}

View File

@ -11,7 +11,7 @@ class SourceSequenceCounter {
SourceSequenceCounter(uint16_t initialSequenceCount = 0) : sequenceCount(initialSequenceCount) {}
void increment() { sequenceCount = (sequenceCount + 1) % (ccsds::LIMIT_SEQUENCE_COUNT); }
void decrement() { sequenceCount = (sequenceCount - 1) % (ccsds::LIMIT_SEQUENCE_COUNT); }
uint16_t get() { return this->sequenceCount; }
uint16_t get() const { return this->sequenceCount; }
void reset(uint16_t toValue = 0) { sequenceCount = toValue % (ccsds::LIMIT_SEQUENCE_COUNT); }
SourceSequenceCounter& operator++(int) {
this->increment();

View File

@ -16,9 +16,7 @@ TmTcBridge::TmTcBridge(const char* name, object_id_t objectId, object_id_t tcDes
tcDestination(tcDestination)
{
auto mqArgs = MqArgs(objectId, static_cast<void*>(this));
tmTcReceptionQueue = QueueFactory::instance()->createMessageQueue(
TMTC_RECEPTION_QUEUE_DEPTH, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
tmTcReceptionQueue = QueueFactory::instance()->createMessageQueue(TMTC_RECEPTION_QUEUE_DEPTH);
}
TmTcBridge::~TmTcBridge() { QueueFactory::instance()->deleteMessageQueue(tmTcReceptionQueue); }
@ -37,7 +35,7 @@ ReturnValue_t TmTcBridge::setNumberOfSentPacketsPerCycle(uint8_t sentPacketsPerC
}
}
ReturnValue_t TmTcBridge::setMaxNumberOfPacketsStored(unsigned int maxNumberOfPacketsStored) {
ReturnValue_t TmTcBridge::setMaxNumberOfPacketsStored(uint8_t maxNumberOfPacketsStored) {
if (maxNumberOfPacketsStored <= LIMIT_DOWNLINK_PACKETS_STORED) {
this->maxNumberOfPacketsStored = maxNumberOfPacketsStored;
return returnvalue::OK;
@ -173,18 +171,15 @@ ReturnValue_t TmTcBridge::storeDownlinkData(TmTcMessage* message) {
}
if (tmFifo->full()) {
if (warningSwitch) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "TmTcBridge::storeDownlinkData: TM downlink max. number "
"of stored packet IDs reached!"
<< std::endl;
sif::warning << "TmTcBridge::storeDownlinkData: TM downlink max. number "
"of stored packet IDs reached!"
<< std::endl;
#else
sif::printWarning(
"TmTcBridge::storeDownlinkData: TM downlink max. number "
"of stored packet IDs reached!\n");
sif::printWarning(
"TmTcBridge::storeDownlinkData: TM downlink max. number "
"of stored packet IDs reached!\n");
#endif
warningSwitch = false;
}
if (overwriteOld) {
tmFifo->retrieve(&storeId);
tmStore->deleteData(storeId);
@ -226,7 +221,6 @@ ReturnValue_t TmTcBridge::handleStoredTm() {
packetSentCounter++;
if (tmFifo->empty()) {
warningSwitch = true;
tmStored = false;
}
tmStore->deleteData(storeId);

View File

@ -17,7 +17,7 @@ class TmTcBridge : public AcceptsTelemetryIF,
public:
static constexpr uint8_t TMTC_RECEPTION_QUEUE_DEPTH = 20;
static constexpr uint8_t LIMIT_STORED_DATA_SENT_PER_CYCLE = 15;
static constexpr unsigned int LIMIT_DOWNLINK_PACKETS_STORED = 1000;
static constexpr uint8_t LIMIT_DOWNLINK_PACKETS_STORED = 200;
static constexpr uint8_t DEFAULT_STORED_DATA_SENT_PER_CYCLE = 5;
static constexpr uint8_t DEFAULT_DOWNLINK_PACKETS_STORED = 10;
@ -42,7 +42,7 @@ class TmTcBridge : public AcceptsTelemetryIF,
* @return -@c returnvalue::OK if value was set successfully
* -@c returnvalue::FAILED otherwise, stored value stays the same
*/
ReturnValue_t setMaxNumberOfPacketsStored(unsigned int maxNumberOfPacketsStored);
ReturnValue_t setMaxNumberOfPacketsStored(uint8_t maxNumberOfPacketsStored);
/**
* This will set up the bridge to overwrite old data in the FIFO.
@ -91,7 +91,6 @@ class TmTcBridge : public AcceptsTelemetryIF,
//! by default, so telemetry will be handled immediately.
bool communicationLinkUp = true;
bool tmStored = false;
bool warningSwitch = true;
bool overwriteOld = true;
uint8_t packetSentCounter = 0;
@ -153,7 +152,7 @@ class TmTcBridge : public AcceptsTelemetryIF,
*/
DynamicFIFO<store_address_t>* tmFifo = nullptr;
uint8_t sentPacketsPerCycle = DEFAULT_STORED_DATA_SENT_PER_CYCLE;
unsigned int maxNumberOfPacketsStored = DEFAULT_DOWNLINK_PACKETS_STORED;
uint8_t maxNumberOfPacketsStored = DEFAULT_DOWNLINK_PACKETS_STORED;
};
#endif /* FSFW_TMTCSERVICES_TMTCBRIDGE_H_ */

View File

@ -46,9 +46,9 @@ class GpioIF {
* an ouput or input gpio.
*
* @param gpioId A unique number which specifies the GPIO to read.
* @param gpioState State of GPIO will be written to this reference
* @param gpioState State of GPIO will be written to this pointer.
*/
virtual ReturnValue_t readGpio(gpioId_t gpioId, gpio::Levels& gpioState) = 0;
virtual ReturnValue_t readGpio(gpioId_t gpioId, int* gpioState) = 0;
};
#endif /* COMMON_GPIO_GPIOIF_H_ */

View File

@ -17,7 +17,7 @@ using gpioId_t = uint16_t;
namespace gpio {
enum class Levels : int { LOW = 0, HIGH = 1, FAILED = -1, NONE = 99 };
enum class Levels : int { LOW = 0, HIGH = 1, NONE = 99 };
enum class Direction : int { IN = 0, OUT = 1 };

View File

@ -252,8 +252,6 @@ ReturnValue_t GyroHandlerL3GD20H::initializeLocalDataPool(localpool::DataPool &l
localDataPoolMap.emplace(L3GD20H::ANG_VELOC_Y, new PoolEntry<float>({0.0}));
localDataPoolMap.emplace(L3GD20H::ANG_VELOC_Z, new PoolEntry<float>({0.0}));
localDataPoolMap.emplace(L3GD20H::TEMPERATURE, new PoolEntry<float>({0.0}));
poolManager.subscribeForRegularPeriodicPacket(
subdp::RegularHkPeriodicParams(dataset.getSid(), false, 10.0));
return returnvalue::OK;
}

View File

@ -195,7 +195,7 @@ ReturnValue_t MgmLIS3MDLHandler::scanForReply(const uint8_t *start, size_t len,
#endif
return DeviceHandlerIF::INVALID_DATA;
}
if (getMode() == _MODE_START_UP) {
if (mode == _MODE_START_UP) {
commandExecuted = true;
}
@ -224,7 +224,7 @@ ReturnValue_t MgmLIS3MDLHandler::scanForReply(const uint8_t *start, size_t len,
return DeviceHandlerIF::INVALID_DATA;
}
if (getMode() == _MODE_START_UP) {
if (mode == _MODE_START_UP) {
commandExecuted = true;
}
}
@ -371,16 +371,13 @@ float MgmLIS3MDLHandler::getSensitivityFactor(MGMLIS3MDL::Sensitivies sens) {
ReturnValue_t MgmLIS3MDLHandler::enableTemperatureSensor(const uint8_t *commandData,
size_t commandDataLen) {
if (commandData == nullptr) {
return INVALID_COMMAND_PARAMETER;
}
triggerEvent(CHANGE_OF_SETUP_PARAMETER);
uint32_t size = 2;
commandBuffer[0] = writeCommand(MGMLIS3MDL::CTRL_REG1);
if (commandDataLen > 1) {
return INVALID_NUMBER_OR_LENGTH_OF_PARAMETERS;
}
switch (commandData[0]) {
switch (*commandData) {
case (MGMLIS3MDL::ON): {
commandBuffer[1] = registers[0] | (1 << 7);
break;

View File

@ -169,7 +169,7 @@ ReturnValue_t MgmRM3100Handler::interpretDeviceReply(DeviceCommandId_t id, const
case (RM3100::CONFIGURE_CYCLE_COUNT):
case (RM3100::CONFIGURE_TMRC): {
// We can only check whether write was successful with read operation
if (getMode() == _MODE_START_UP) {
if (mode == _MODE_START_UP) {
commandExecuted = true;
}
break;
@ -192,7 +192,7 @@ ReturnValue_t MgmRM3100Handler::interpretDeviceReply(DeviceCommandId_t id, const
if (packet[1] == tmrcRegValue) {
commandExecuted = true;
// Reading TMRC was commanded. Trigger event to inform ground
if (getMode() != _MODE_START_UP) {
if (mode != _MODE_START_UP) {
triggerEvent(tmrcSet, tmrcRegValue, 0);
}
} else {
@ -211,7 +211,7 @@ ReturnValue_t MgmRM3100Handler::interpretDeviceReply(DeviceCommandId_t id, const
return DeviceHandlerIF::DEVICE_REPLY_INVALID;
}
// Reading TMRC was commanded. Trigger event to inform ground
if (getMode() != _MODE_START_UP) {
if (mode != _MODE_START_UP) {
uint32_t eventParam1 = (cycleCountX << 16) | cycleCountY;
triggerEvent(cycleCountersSet, eventParam1, cycleCountZ);
}

View File

@ -6,7 +6,7 @@
#include "fsfw/FSFW.h"
#include "fsfw/serviceinterface.h"
UnixFileGuard::UnixFileGuard(const std::string& device, int* fileDescriptor, int flags,
UnixFileGuard::UnixFileGuard(std::string device, int* fileDescriptor, int flags,
std::string diagnosticPrefix)
: fileDescriptor(fileDescriptor) {
if (fileDescriptor == nullptr) {

View File

@ -15,7 +15,7 @@ class UnixFileGuard {
static constexpr ReturnValue_t OPEN_FILE_FAILED = 1;
UnixFileGuard(const std::string& device, int* fileDescriptor, int flags,
UnixFileGuard(std::string device, int* fileDescriptor, int flags,
std::string diagnosticPrefix = "");
virtual ~UnixFileGuard();

View File

@ -1,27 +0,0 @@
#ifndef FSFW_HAL_SRC_FSFW_HAL_LINUX_GPIO_GPIO_H_
#define FSFW_HAL_SRC_FSFW_HAL_LINUX_GPIO_GPIO_H_
#include "fsfw_hal/common/gpio/GpioIF.h"
#include "fsfw_hal/common/gpio/gpioDefinitions.h"
/**
* @brief Additional abstraction layer for handling GPIOs.
*
* @author J. Meier
*/
class Gpio {
public:
Gpio(gpioId_t gpioId, GpioIF* gpioIF) : gpioId(gpioId), gpioIF(gpioIF) {
if (gpioIF == nullptr) {
sif::error << "Gpio::Gpio: Invalid GpioIF" << std::endl;
}
}
ReturnValue_t pullHigh() { return gpioIF->pullHigh(gpioId); }
ReturnValue_t pullLow() { return gpioIF->pullLow(gpioId); }
private:
gpioId_t gpioId = gpio::NO_GPIO;
GpioIF* gpioIF = nullptr;
};
#endif /* FSFW_HAL_SRC_FSFW_HAL_LINUX_GPIO_GPIO_H_ */

View File

@ -214,7 +214,7 @@ ReturnValue_t LinuxLibgpioIF::configureRegularGpio(gpioId_t gpioId, struct gpiod
}
ReturnValue_t LinuxLibgpioIF::pullHigh(gpioId_t gpioId) {
auto gpioMapIter = gpioMap.find(gpioId);
gpioMapIter = gpioMap.find(gpioId);
if (gpioMapIter == gpioMap.end()) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "LinuxLibgpioIF::pullHigh: Unknown GPIO ID " << gpioId << std::endl;
@ -244,7 +244,7 @@ ReturnValue_t LinuxLibgpioIF::pullHigh(gpioId_t gpioId) {
}
ReturnValue_t LinuxLibgpioIF::pullLow(gpioId_t gpioId) {
auto gpioMapIter = gpioMap.find(gpioId);
gpioMapIter = gpioMap.find(gpioId);
if (gpioMapIter == gpioMap.end()) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "LinuxLibgpioIF::pullLow: Unknown GPIO ID " << gpioId << std::endl;
@ -294,8 +294,8 @@ ReturnValue_t LinuxLibgpioIF::driveGpio(gpioId_t gpioId, GpiodRegularBase& regul
return returnvalue::OK;
}
ReturnValue_t LinuxLibgpioIF::readGpio(gpioId_t gpioId, gpio::Levels& gpioState) {
auto gpioMapIter = gpioMap.find(gpioId);
ReturnValue_t LinuxLibgpioIF::readGpio(gpioId_t gpioId, int* gpioState) {
gpioMapIter = gpioMap.find(gpioId);
if (gpioMapIter == gpioMap.end()) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "LinuxLibgpioIF::readGpio: Unknown GPIOD ID " << gpioId << std::endl;
@ -313,10 +313,7 @@ ReturnValue_t LinuxLibgpioIF::readGpio(gpioId_t gpioId, gpio::Levels& gpioState)
if (regularGpio == nullptr) {
return GPIO_TYPE_FAILURE;
}
gpioState = static_cast<gpio::Levels>(gpiod_line_get_value(regularGpio->lineHandle));
if (gpioState == gpio::Levels::FAILED) {
return GPIO_GET_VALUE_FAILED;
}
*gpioState = gpiod_line_get_value(regularGpio->lineHandle);
} else {
auto gpioCallback = dynamic_cast<GpioCallback*>(gpioMapIter->second);
if (gpioCallback->callback == nullptr) {
@ -377,7 +374,7 @@ ReturnValue_t LinuxLibgpioIF::checkForConflictsById(gpioId_t gpioIdToCheck,
gpio::GpioTypes expectedType,
GpioMap& mapToAdd) {
// Cross check with private map
auto gpioMapIter = gpioMap.find(gpioIdToCheck);
gpioMapIter = gpioMap.find(gpioIdToCheck);
if (gpioMapIter != gpioMap.end()) {
auto& gpioType = gpioMapIter->second->gpioType;
bool eraseDuplicateDifferentType = false;

View File

@ -25,8 +25,6 @@ class LinuxLibgpioIF : public GpioIF, public SystemObject {
static constexpr ReturnValue_t GPIO_INVALID_INSTANCE = returnvalue::makeCode(gpioRetvalId, 4);
static constexpr ReturnValue_t GPIO_DUPLICATE_DETECTED = returnvalue::makeCode(gpioRetvalId, 5);
static constexpr ReturnValue_t GPIO_INIT_FAILED = returnvalue::makeCode(gpioRetvalId, 6);
// Will be returned if getting the line value failed. Error type will be set to errno in this case
static constexpr ReturnValue_t GPIO_GET_VALUE_FAILED = returnvalue::makeCode(gpioRetvalId, 7);
LinuxLibgpioIF(object_id_t objectId);
virtual ~LinuxLibgpioIF();
@ -34,7 +32,7 @@ class LinuxLibgpioIF : public GpioIF, public SystemObject {
ReturnValue_t addGpios(GpioCookie* gpioCookie) override;
ReturnValue_t pullHigh(gpioId_t gpioId) override;
ReturnValue_t pullLow(gpioId_t gpioId) override;
ReturnValue_t readGpio(gpioId_t gpioId, gpio::Levels& gpioState) override;
ReturnValue_t readGpio(gpioId_t gpioId, int* gpioState) override;
private:
static const size_t MAX_CHIPNAME_LENGTH = 11;
@ -44,6 +42,7 @@ class LinuxLibgpioIF : public GpioIF, public SystemObject {
// Holds the information and configuration of all used GPIOs
GpioUnorderedMap gpioMap;
GpioUnorderedMapIter gpioMapIter;
/**
* @brief This functions drives line of a GPIO specified by the GPIO ID.

View File

@ -1,43 +0,0 @@
#pragma once
#include "fsfw/ipc/MutexIF.h"
#include "fsfw/returnvalues/returnvalue.h"
#include "fsfw_hal/common/gpio/GpioIF.h"
class ManualCsLockWrapper {
public:
ManualCsLockWrapper(MutexIF* lock, GpioIF* gpioIF, SpiCookie* cookie,
MutexIF::TimeoutType type = MutexIF::TimeoutType::BLOCKING,
uint32_t timeoutMs = 0)
: lock(lock), gpioIF(gpioIF), cookie(cookie), type(type), timeoutMs(timeoutMs) {
if (cookie == nullptr) {
// TODO: Error? Or maybe throw exception..
return;
}
cookie->setCsLockManual(true);
lockResult = lock->lockMutex(type, timeoutMs);
if (lockResult != returnvalue::OK) {
return;
}
gpioResult = gpioIF->pullLow(cookie->getChipSelectPin());
}
~ManualCsLockWrapper() {
if (gpioResult == returnvalue::OK) {
gpioIF->pullHigh(cookie->getChipSelectPin());
}
cookie->setCsLockManual(false);
if (lockResult == returnvalue::OK) {
lock->unlockMutex();
}
}
ReturnValue_t lockResult;
ReturnValue_t gpioResult;
private:
MutexIF* lock;
GpioIF* gpioIF;
SpiCookie* cookie;
MutexIF::TimeoutType type;
uint32_t timeoutMs = 0;
};

View File

@ -15,9 +15,19 @@
#include "fsfw_hal/linux/spi/SpiCookie.h"
#include "fsfw_hal/linux/utility.h"
SpiComIF::SpiComIF(object_id_t objectId, std::string devname, GpioIF& gpioComIF)
: SystemObject(objectId), gpioComIF(gpioComIF), dev(std::move(devname)) {
csMutex = MutexFactory::instance()->createMutex();
SpiComIF::SpiComIF(object_id_t objectId, GpioIF* gpioComIF)
: SystemObject(objectId), gpioComIF(gpioComIF) {
if (gpioComIF == nullptr) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "SpiComIF::SpiComIF: GPIO communication interface invalid!" << std::endl;
#else
sif::printError("SpiComIF::SpiComIF: GPIO communication interface invalid!\n");
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
}
spiMutex = MutexFactory::instance()->createMutex();
}
ReturnValue_t SpiComIF::initializeInterface(CookieIF* cookie) {
@ -65,7 +75,7 @@ ReturnValue_t SpiComIF::initializeInterface(CookieIF* cookie) {
/* Pull CS high in any case to be sure that device is inactive */
gpioId_t gpioId = spiCookie->getChipSelectPin();
if (gpioId != gpio::NO_GPIO) {
gpioComIF.pullHigh(gpioId);
gpioComIF->pullHigh(gpioId);
}
uint32_t spiSpeed = 0;
@ -75,7 +85,8 @@ ReturnValue_t SpiComIF::initializeInterface(CookieIF* cookie) {
spiCookie->getSpiParameters(spiMode, spiSpeed, &params);
int fileDescriptor = 0;
UnixFileGuard fileHelper(dev, &fileDescriptor, O_RDWR, "SpiComIF::initializeInterface");
UnixFileGuard fileHelper(spiCookie->getSpiDevice(), &fileDescriptor, O_RDWR,
"SpiComIF::initializeInterface");
if (fileHelper.getOpenResult() != returnvalue::OK) {
return fileHelper.getOpenResult();
}
@ -171,7 +182,8 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const
int retval = 0;
/* Prepare transfer */
int fileDescriptor = 0;
UnixFileGuard fileHelper(dev, &fileDescriptor, O_RDWR, "SpiComIF::sendMessage");
std::string device = spiCookie->getSpiDevice();
UnixFileGuard fileHelper(device, &fileDescriptor, O_RDWR, "SpiComIF::sendMessage");
if (fileHelper.getOpenResult() != returnvalue::OK) {
return OPENING_FILE_FAILED;
}
@ -184,28 +196,21 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const
bool fullDuplex = spiCookie->isFullDuplex();
gpioId_t gpioId = spiCookie->getChipSelectPin();
bool csLockManual = spiCookie->getCsLockManual();
MutexIF::TimeoutType csType;
dur_millis_t csTimeout = 0;
// Pull SPI CS low. For now, no support for active high given
if (gpioId != gpio::NO_GPIO and not csLockManual) {
spiCookie->getMutexParams(csType, csTimeout);
result = csMutex->lockMutex(csType, csTimeout);
/* Pull SPI CS low. For now, no support for active high given */
if (gpioId != gpio::NO_GPIO) {
result = spiMutex->lockMutex(timeoutType, timeoutMs);
if (result != returnvalue::OK) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "SpiComIF::sendMessage: Failed to lock mutex with code "
<< "0x" << std::hex << std::setfill('0') << std::setw(4) << result << std::dec
<< std::endl;
sif::error << "SpiComIF::sendMessage: Failed to lock mutex" << std::endl;
#else
sif::printError("SpiComIF::sendMessage: Failed to lock mutex with code %d\n", result);
sif::printError("SpiComIF::sendMessage: Failed to lock mutex\n");
#endif
#endif
return result;
}
updateLinePolarity(fileDescriptor);
result = gpioComIF.pullLow(gpioId);
result = gpioComIF->pullLow(gpioId);
if (result != returnvalue::OK) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
@ -216,8 +221,6 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const
#endif
return result;
}
} else {
updateLinePolarity(fileDescriptor);
}
/* Execute transfer */
@ -245,9 +248,9 @@ ReturnValue_t SpiComIF::performRegularSendOperation(SpiCookie* spiCookie, const
}
}
if (gpioId != gpio::NO_GPIO and not csLockManual) {
gpioComIF.pullHigh(gpioId);
result = csMutex->unlockMutex();
if (gpioId != gpio::NO_GPIO) {
gpioComIF->pullHigh(gpioId);
result = spiMutex->unlockMutex();
if (result != returnvalue::OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "SpiComIF::sendMessage: Failed to unlock mutex" << std::endl;
@ -275,8 +278,9 @@ ReturnValue_t SpiComIF::requestReceiveMessage(CookieIF* cookie, size_t requestLe
ReturnValue_t SpiComIF::performHalfDuplexReception(SpiCookie* spiCookie) {
ReturnValue_t result = returnvalue::OK;
std::string device = spiCookie->getSpiDevice();
int fileDescriptor = 0;
UnixFileGuard fileHelper(dev, &fileDescriptor, O_RDWR, "SpiComIF::requestReceiveMessage");
UnixFileGuard fileHelper(device, &fileDescriptor, O_RDWR, "SpiComIF::requestReceiveMessage");
if (fileHelper.getOpenResult() != returnvalue::OK) {
return OPENING_FILE_FAILED;
}
@ -288,26 +292,16 @@ ReturnValue_t SpiComIF::performHalfDuplexReception(SpiCookie* spiCookie) {
return result;
}
bool csLockManual = spiCookie->getCsLockManual();
gpioId_t gpioId = spiCookie->getChipSelectPin();
MutexIF::TimeoutType csType;
dur_millis_t csTimeout = 0;
if (gpioId != gpio::NO_GPIO and not csLockManual) {
spiCookie->getMutexParams(csType, csTimeout);
result = csMutex->lockMutex(csType, csTimeout);
if (gpioId != gpio::NO_GPIO) {
result = spiMutex->lockMutex(timeoutType, timeoutMs);
if (result != returnvalue::OK) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "SpiComIF::sendMessage: Failed to lock mutex with code "
<< "0x" << std::hex << std::setfill('0') << std::setw(4) << result << std::dec
<< std::endl;
#else
sif::printError("SpiComIF::sendMessage: Failed to lock mutex with code %d\n", result);
#endif
sif::error << "SpiComIF::getSendSuccess: Failed to lock mutex" << std::endl;
#endif
return result;
}
gpioComIF.pullLow(gpioId);
gpioComIF->pullLow(gpioId);
}
if (read(fileDescriptor, rxBuf, readSize) != static_cast<ssize_t>(readSize)) {
@ -321,9 +315,9 @@ ReturnValue_t SpiComIF::performHalfDuplexReception(SpiCookie* spiCookie) {
result = HALF_DUPLEX_TRANSFER_FAILED;
}
if (gpioId != gpio::NO_GPIO and not csLockManual) {
gpioComIF.pullHigh(gpioId);
result = csMutex->unlockMutex();
if (gpioId != gpio::NO_GPIO) {
gpioComIF->pullHigh(gpioId);
result = spiMutex->unlockMutex();
if (result != returnvalue::OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "SpiComIF::getSendSuccess: Failed to unlock mutex" << std::endl;
@ -352,7 +346,15 @@ ReturnValue_t SpiComIF::readReceivedMessage(CookieIF* cookie, uint8_t** buffer,
return returnvalue::OK;
}
MutexIF* SpiComIF::getCsMutex() { return csMutex; }
MutexIF* SpiComIF::getMutex(MutexIF::TimeoutType* timeoutType, uint32_t* timeoutMs) {
if (timeoutType != nullptr) {
*timeoutType = this->timeoutType;
}
if (timeoutMs != nullptr) {
*timeoutMs = this->timeoutMs;
}
return spiMutex;
}
void SpiComIF::performSpiWiretapping(SpiCookie* spiCookie) {
if (spiCookie == nullptr) {
@ -387,7 +389,7 @@ ReturnValue_t SpiComIF::getReadBuffer(address_t spiAddress, uint8_t** buffer) {
return returnvalue::OK;
}
GpioIF& SpiComIF::getGpioInterface() { return gpioComIF; }
GpioIF* SpiComIF::getGpioInterface() { return gpioComIF; }
void SpiComIF::setSpiSpeedAndMode(int spiFd, spi::SpiModes mode, uint32_t speed) {
int retval = ioctl(spiFd, SPI_IOC_WR_MODE, reinterpret_cast<uint8_t*>(&mode));
@ -399,27 +401,11 @@ void SpiComIF::setSpiSpeedAndMode(int spiFd, spi::SpiModes mode, uint32_t speed)
if (retval != 0) {
utility::handleIoctlError("SpiComIF::setSpiSpeedAndMode: Setting SPI speed failed");
}
}
void SpiComIF::getSpiSpeedAndMode(int spiFd, spi::SpiModes& mode, uint32_t& speed) const {
uint8_t tmpMode = 0;
int retval = ioctl(spiFd, SPI_IOC_RD_MODE, &tmpMode);
if (retval != 0) {
utility::handleIoctlError("SpiComIF::getSpiSpeedAndMode: Reading SPI mode failed");
}
mode = static_cast<spi::SpiModes>(tmpMode);
retval = ioctl(spiFd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
if (retval != 0) {
utility::handleIoctlError("SpiComIF::getSpiSpeedAndMode: Getting SPI speed failed");
}
}
const std::string& SpiComIF::getSpiDev() const { return dev; }
void SpiComIF::updateLinePolarity(int spiFd) {
// This updates the SPI clock default polarity. Only setting the mode does not update
// the line state, which can be an issue on mode switches because the clock line will
// switch the state after the chip select is pulled low
clockUpdateTransfer.len = 0;
int retval = ioctl(spiFd, SPI_IOC_MESSAGE(1), &clockUpdateTransfer);
retval = ioctl(spiFd, SPI_IOC_MESSAGE(1), &clockUpdateTransfer);
if (retval != 0) {
utility::handleIoctlError("SpiComIF::setSpiSpeedAndMode: Updating SPI default clock failed");
}

View File

@ -31,7 +31,7 @@ class SpiComIF : public DeviceCommunicationIF, public SystemObject {
static constexpr ReturnValue_t HALF_DUPLEX_TRANSFER_FAILED =
returnvalue::makeCode(spiRetvalId, 2);
SpiComIF(object_id_t objectId, std::string devname, GpioIF& gpioComIF);
SpiComIF(object_id_t objectId, GpioIF* gpioComIF);
ReturnValue_t initializeInterface(CookieIF* cookie) override;
ReturnValue_t sendMessage(CookieIF* cookie, const uint8_t* sendData, size_t sendLen) override;
@ -43,8 +43,7 @@ class SpiComIF : public DeviceCommunicationIF, public SystemObject {
* @brief This function returns the mutex which can be used to protect the spi bus when
* the chip select must be driven from outside of the com if.
*/
MutexIF* getCsMutex();
void setMutexParams(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs);
MutexIF* getMutex(MutexIF::TimeoutType* timeoutType = nullptr, uint32_t* timeoutMs = nullptr);
/**
* Perform a regular send operation using Linux iotcl. This is public so it can be used
@ -57,22 +56,8 @@ class SpiComIF : public DeviceCommunicationIF, public SystemObject {
ReturnValue_t performRegularSendOperation(SpiCookie* spiCookie, const uint8_t* sendData,
size_t sendLen);
GpioIF& getGpioInterface();
GpioIF* getGpioInterface();
void setSpiSpeedAndMode(int spiFd, spi::SpiModes mode, uint32_t speed);
void getSpiSpeedAndMode(int spiFd, spi::SpiModes& mode, uint32_t& speed) const;
/**
* This updates the SPI clock default polarity. Only setting the mode does not update
* the line state, which can be an issue on mode switches because the clock line will
* switch the state after the chip select is pulled low.
*
* It is recommended to call this function after #setSpiSpeedAndMode and after locking the
* CS mutex if the SPI bus has multiple SPI devices with different speed and SPI modes attached.
* @param spiFd
*/
void updateLinePolarity(int spiFd);
const std::string& getSpiDev() const;
void performSpiWiretapping(SpiCookie* spiCookie);
ReturnValue_t getReadBuffer(address_t spiAddress, uint8_t** buffer);
@ -83,15 +68,11 @@ class SpiComIF : public DeviceCommunicationIF, public SystemObject {
std::vector<uint8_t> replyBuffer;
};
GpioIF& gpioComIF;
std::string dev = "";
/**
* Protects the chip select operations. Lock when GPIO is pulled low, unlock after it was
* pulled high
*/
MutexIF* csMutex = nullptr;
// MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
// uint32_t timeoutMs = DEFAULT_MUTEX_TIMEOUT;
GpioIF* gpioComIF = nullptr;
MutexIF* spiMutex = nullptr;
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
uint32_t timeoutMs = 20;
spi_ioc_transfer clockUpdateTransfer = {};
using SpiDeviceMap = std::unordered_map<address_t, SpiInstance>;

View File

@ -1,25 +1,26 @@
#include "SpiCookie.h"
SpiCookie::SpiCookie(address_t spiAddress, gpioId_t chipSelect, const size_t maxSize,
SpiCookie::SpiCookie(address_t spiAddress, gpioId_t chipSelect, std::string spiDev,
const size_t maxSize, spi::SpiModes spiMode, uint32_t spiSpeed)
: SpiCookie(spi::SpiComIfModes::REGULAR, spiAddress, chipSelect, spiDev, maxSize, spiMode,
spiSpeed, nullptr, nullptr) {}
SpiCookie::SpiCookie(address_t spiAddress, std::string spiDev, const size_t maxSize,
spi::SpiModes spiMode, uint32_t spiSpeed)
: SpiCookie(spi::SpiComIfModes::REGULAR, spiAddress, chipSelect, maxSize, spiMode, spiSpeed,
nullptr, nullptr) {}
: SpiCookie(spiAddress, gpio::NO_GPIO, spiDev, maxSize, spiMode, spiSpeed) {}
SpiCookie::SpiCookie(address_t spiAddress, const size_t maxSize, spi::SpiModes spiMode,
uint32_t spiSpeed)
: SpiCookie(spiAddress, gpio::NO_GPIO, maxSize, spiMode, spiSpeed) {}
SpiCookie::SpiCookie(address_t spiAddress, gpioId_t chipSelect, const size_t maxSize,
spi::SpiModes spiMode, uint32_t spiSpeed,
spi::send_callback_function_t callback, void* args)
: SpiCookie(spi::SpiComIfModes::CALLBACK, spiAddress, chipSelect, maxSize, spiMode, spiSpeed,
callback, args) {}
SpiCookie::SpiCookie(spi::SpiComIfModes comIfMode, address_t spiAddress, gpioId_t chipSelect,
SpiCookie::SpiCookie(address_t spiAddress, gpioId_t chipSelect, std::string spiDev,
const size_t maxSize, spi::SpiModes spiMode, uint32_t spiSpeed,
spi::send_callback_function_t callback, void* args)
: SpiCookie(spi::SpiComIfModes::CALLBACK, spiAddress, chipSelect, spiDev, maxSize, spiMode,
spiSpeed, callback, args) {}
SpiCookie::SpiCookie(spi::SpiComIfModes comIfMode, address_t spiAddress, gpioId_t chipSelect,
std::string spiDev, const size_t maxSize, spi::SpiModes spiMode,
uint32_t spiSpeed, spi::send_callback_function_t callback, void* args)
: spiAddress(spiAddress),
chipSelectPin(chipSelect),
spiDevice(spiDev),
comIfMode(comIfMode),
maxSize(maxSize),
spiMode(spiMode),
@ -49,6 +50,8 @@ size_t SpiCookie::getMaxBufferSize() const { return maxSize; }
address_t SpiCookie::getSpiAddress() const { return spiAddress; }
std::string SpiCookie::getSpiDevice() const { return spiDevice; }
void SpiCookie::setThreeWireSpi(bool enable) { uncommonParameters.threeWireSpi = enable; }
void SpiCookie::setLsbFirst(bool enable) { uncommonParameters.lsbFirst = enable; }
@ -104,17 +107,3 @@ void SpiCookie::getCallback(spi::send_callback_function_t* callback, void** args
*callback = this->sendCallback;
*args = this->callbackArgs;
}
void SpiCookie::setCsLockManual(bool enable) { manualCsLock = enable; }
bool SpiCookie::getCsLockManual() const { return manualCsLock; }
void SpiCookie::getMutexParams(MutexIF::TimeoutType& csTimeoutType, dur_millis_t& csTimeout) const {
csTimeoutType = this->csTimeoutType;
csTimeout = this->csTimeout;
}
void SpiCookie::setMutexParams(MutexIF::TimeoutType csTimeoutType, dur_millis_t csTimeout) {
this->csTimeoutType = csTimeoutType;
this->csTimeout = csTimeout;
}

View File

@ -2,8 +2,6 @@
#define LINUX_SPI_SPICOOKIE_H_
#include <fsfw/devicehandlers/CookieIF.h>
#include <fsfw/ipc/MutexIF.h>
#include <fsfw/timemanager/clockDefinitions.h>
#include <linux/spi/spidev.h>
#include "../../common/gpio/gpioDefinitions.h"
@ -22,8 +20,6 @@
*/
class SpiCookie : public CookieIF {
public:
static constexpr dur_millis_t DEFAULT_MUTEX_TIMEOUT = 20;
/**
* Each SPI device will have a corresponding cookie. The cookie is used by the communication
* interface and contains device specific information like the largest expected size to be
@ -33,22 +29,23 @@ class SpiCookie : public CookieIF {
* @param spiDev
* @param maxSize
*/
SpiCookie(address_t spiAddress, gpioId_t chipSelect, const size_t maxSize, spi::SpiModes spiMode,
uint32_t spiSpeed);
SpiCookie(address_t spiAddress, gpioId_t chipSelect, std::string spiDev, const size_t maxSize,
spi::SpiModes spiMode, uint32_t spiSpeed);
/**
* Like constructor above, but without a dedicated GPIO CS. Can be used for hardware
* slave select or if CS logic is performed with decoders.
*/
SpiCookie(address_t spiAddress, const size_t maxReplySize, spi::SpiModes spiMode,
uint32_t spiSpeed);
SpiCookie(address_t spiAddress, std::string spiDev, const size_t maxReplySize,
spi::SpiModes spiMode, uint32_t spiSpeed);
/**
* Use the callback mode of the SPI communication interface. The user can pass the callback
* function here or by using the setter function #setCallbackMode
*/
SpiCookie(address_t spiAddress, gpioId_t chipSelect, const size_t maxSize, spi::SpiModes spiMode,
uint32_t spiSpeed, spi::send_callback_function_t callback, void* args);
SpiCookie(address_t spiAddress, gpioId_t chipSelect, std::string spiDev, const size_t maxSize,
spi::SpiModes spiMode, uint32_t spiSpeed, spi::send_callback_function_t callback,
void* args);
/**
* Get the callback function
@ -58,6 +55,7 @@ class SpiCookie : public CookieIF {
void getCallback(spi::send_callback_function_t* callback, void** args);
address_t getSpiAddress() const;
std::string getSpiDevice() const;
gpioId_t getChipSelectPin() const;
size_t getMaxBufferSize() const;
@ -141,42 +139,9 @@ class SpiCookie : public CookieIF {
*/
void activateCsDeselect(bool deselectCs, uint16_t delayUsecs);
void getMutexParams(MutexIF::TimeoutType& csTimeoutType, dur_millis_t& csTimeout) const;
void setMutexParams(MutexIF::TimeoutType csTimeoutType, dur_millis_t csTimeout);
void setCsLockManual(bool enable);
bool getCsLockManual() const;
spi_ioc_transfer* getTransferStructHandle();
private:
address_t spiAddress;
gpioId_t chipSelectPin;
spi::SpiComIfModes comIfMode;
// Required for regular mode
const size_t maxSize;
spi::SpiModes spiMode;
/**
* If this is set to true, the SPI ComIF will not perform any mutex locking for the
* CS mechanism. The user is responsible to locking and unlocking the mutex for the
* whole duration of the transfers.
*/
bool manualCsLock = false;
uint32_t spiSpeed;
bool halfDuplex = false;
MutexIF::TimeoutType csTimeoutType = MutexIF::TimeoutType::WAITING;
dur_millis_t csTimeout = DEFAULT_MUTEX_TIMEOUT;
// Required for callback mode
spi::send_callback_function_t sendCallback = nullptr;
void* callbackArgs = nullptr;
struct spi_ioc_transfer spiTransferStruct = {};
UncommonParameters uncommonParameters;
/**
* Internal constructor which initializes every field
* @param spiAddress
@ -189,8 +154,27 @@ class SpiCookie : public CookieIF {
* @param args
*/
SpiCookie(spi::SpiComIfModes comIfMode, address_t spiAddress, gpioId_t chipSelect,
const size_t maxSize, spi::SpiModes spiMode, uint32_t spiSpeed,
std::string spiDev, const size_t maxSize, spi::SpiModes spiMode, uint32_t spiSpeed,
spi::send_callback_function_t callback, void* args);
address_t spiAddress;
gpioId_t chipSelectPin;
std::string spiDevice;
spi::SpiComIfModes comIfMode;
// Required for regular mode
const size_t maxSize;
spi::SpiModes spiMode;
uint32_t spiSpeed;
bool halfDuplex = false;
// Required for callback mode
spi::send_callback_function_t sendCallback = nullptr;
void* callbackArgs = nullptr;
struct spi_ioc_transfer spiTransferStruct = {};
UncommonParameters uncommonParameters;
};
#endif /* LINUX_SPI_SPICOOKIE_H_ */

View File

@ -2,17 +2,19 @@
#include <fsfw/objectmanager/ObjectManager.h>
TestAssembly::TestAssembly(object_id_t objectId, object_id_t parentId, ModeTreeChildIF& testDevice0,
ModeTreeChildIF& testDevice1)
: AssemblyBase(objectId, parentId), deviceHandler0(testDevice0), deviceHandler1(testDevice1) {
TestAssembly::TestAssembly(object_id_t objectId, object_id_t parentId, object_id_t testDevice0,
object_id_t testDevice1)
: AssemblyBase(objectId, parentId),
deviceHandler0Id(testDevice0),
deviceHandler1Id(testDevice1) {
ModeListEntry newModeListEntry;
newModeListEntry.setObject(testDevice0.getObjectId());
newModeListEntry.setObject(testDevice0);
newModeListEntry.setMode(MODE_OFF);
newModeListEntry.setSubmode(SUBMODE_NONE);
commandTable.insert(newModeListEntry);
newModeListEntry.setObject(testDevice1.getObjectId());
newModeListEntry.setObject(testDevice1);
newModeListEntry.setMode(MODE_OFF);
newModeListEntry.setSubmode(SUBMODE_NONE);
@ -41,8 +43,8 @@ ReturnValue_t TestAssembly::commandChildren(Mode_t mode, Submode_t submode) {
commandTable[1].setMode(MODE_OFF);
commandTable[1].setSubmode(SUBMODE_NONE);
// We try to prefer 0 here but we try to switch to 1 even if it might fail
if (isDeviceAvailable(deviceHandler0.getObjectId())) {
if (childrenMap[deviceHandler0.getObjectId()].mode == MODE_ON) {
if (isDeviceAvailable(deviceHandler0Id)) {
if (childrenMap[deviceHandler0Id].mode == MODE_ON) {
commandTable[0].setMode(mode);
commandTable[0].setSubmode(SUBMODE_NONE);
} else {
@ -51,7 +53,7 @@ ReturnValue_t TestAssembly::commandChildren(Mode_t mode, Submode_t submode) {
result = NEED_SECOND_STEP;
}
} else {
if (childrenMap[deviceHandler1.getObjectId()].mode == MODE_ON) {
if (childrenMap[deviceHandler1Id].mode == MODE_ON) {
commandTable[1].setMode(mode);
commandTable[1].setSubmode(SUBMODE_NONE);
} else {
@ -62,7 +64,7 @@ ReturnValue_t TestAssembly::commandChildren(Mode_t mode, Submode_t submode) {
}
} else {
// Dual Mode Normal
if (childrenMap[deviceHandler0.getObjectId()].mode == MODE_ON) {
if (childrenMap[deviceHandler0Id].mode == MODE_ON) {
commandTable[0].setMode(mode);
commandTable[0].setSubmode(SUBMODE_NONE);
} else {
@ -70,7 +72,7 @@ ReturnValue_t TestAssembly::commandChildren(Mode_t mode, Submode_t submode) {
commandTable[0].setSubmode(SUBMODE_NONE);
result = NEED_SECOND_STEP;
}
if (childrenMap[deviceHandler1.getObjectId()].mode == MODE_ON) {
if (childrenMap[deviceHandler1Id].mode == MODE_ON) {
commandTable[1].setMode(mode);
commandTable[1].setSubmode(SUBMODE_NONE);
} else {
@ -87,7 +89,7 @@ ReturnValue_t TestAssembly::commandChildren(Mode_t mode, Submode_t submode) {
commandTable[1].setMode(MODE_OFF);
commandTable[1].setSubmode(SUBMODE_NONE);
// We try to prefer 0 here but we try to switch to 1 even if it might fail
if (isDeviceAvailable(deviceHandler0.getObjectId())) {
if (isDeviceAvailable(deviceHandler0Id)) {
commandTable[0].setMode(MODE_ON);
commandTable[0].setSubmode(SUBMODE_NONE);
} else {
@ -131,14 +133,23 @@ ReturnValue_t TestAssembly::initialize() {
if (result != returnvalue::OK) {
return result;
}
auto* handler0 = ObjectManager::instance()->get<TestDevice>(deviceHandler0.getObjectId());
auto* handler1 = ObjectManager::instance()->get<TestDevice>(deviceHandler1.getObjectId());
handler0 = ObjectManager::instance()->get<TestDevice>(deviceHandler0Id);
handler1 = ObjectManager::instance()->get<TestDevice>(deviceHandler1Id);
if ((handler0 == nullptr) or (handler1 == nullptr)) {
return returnvalue::FAILED;
}
handler0->connectModeTreeParent(*this);
handler1->connectModeTreeParent(*this);
handler0->setParentQueue(this->getCommandQueue());
handler1->setParentQueue(this->getCommandQueue());
result = registerChild(deviceHandler0Id);
if (result != returnvalue::OK) {
return result;
}
result = registerChild(deviceHandler1Id);
if (result != returnvalue::OK) {
return result;
}
return result;
}

View File

@ -7,8 +7,8 @@
class TestAssembly : public AssemblyBase {
public:
TestAssembly(object_id_t objectId, object_id_t parentId, ModeTreeChildIF& testDevice0,
ModeTreeChildIF& testDevice1);
TestAssembly(object_id_t objectId, object_id_t parentId, object_id_t testDevice0,
object_id_t testDevice1);
virtual ~TestAssembly();
ReturnValue_t initialize() override;
@ -41,8 +41,10 @@ class TestAssembly : public AssemblyBase {
private:
FixedArrayList<ModeListEntry, 2> commandTable;
ModeTreeChildIF& deviceHandler0;
ModeTreeChildIF& deviceHandler1;
object_id_t deviceHandler0Id = 0;
object_id_t deviceHandler1Id = 0;
TestDevice* handler0 = nullptr;
TestDevice* handler1 = nullptr;
bool isDeviceAvailable(object_id_t object);
};

View File

@ -4,8 +4,8 @@
#include <fsfw/objectmanager/ObjectManager.h>
#include <fsfw/serviceinterface/ServiceInterface.h>
TestController::TestController(object_id_t objectId, size_t commandQueueDepth)
: ExtendedControllerBase(objectId, commandQueueDepth) {}
TestController::TestController(object_id_t objectId, object_id_t parentId, size_t commandQueueDepth)
: ExtendedControllerBase(objectId, parentId, commandQueueDepth) {}
TestController::~TestController() {}

View File

@ -7,7 +7,7 @@
class TestController : public ExtendedControllerBase {
public:
TestController(object_id_t objectId, size_t commandQueueDepth = 10);
TestController(object_id_t objectId, object_id_t parentId, size_t commandQueueDepth = 10);
virtual ~TestController();
protected:

View File

@ -65,7 +65,7 @@ ReturnValue_t TestDevice::buildNormalDeviceCommand(DeviceCommandId_t* id) {
}
ReturnValue_t TestDevice::buildTransitionDeviceCommand(DeviceCommandId_t* id) {
if (getMode() == _MODE_TO_ON) {
if (mode == _MODE_TO_ON) {
if (fullInfoPrintout) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "TestDevice" << deviceIdx
@ -80,7 +80,7 @@ ReturnValue_t TestDevice::buildTransitionDeviceCommand(DeviceCommandId_t* id) {
#endif
}
}
if (getMode() == _MODE_TO_NORMAL) {
if (mode == _MODE_TO_NORMAL) {
if (fullInfoPrintout) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "TestDevice" << deviceIdx
@ -97,7 +97,7 @@ ReturnValue_t TestDevice::buildTransitionDeviceCommand(DeviceCommandId_t* id) {
setMode(MODE_NORMAL);
}
if (getMode() == _MODE_SHUT_DOWN) {
if (mode == _MODE_SHUT_DOWN) {
if (fullInfoPrintout) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "TestDevice" << deviceIdx
@ -118,7 +118,7 @@ ReturnValue_t TestDevice::buildTransitionDeviceCommand(DeviceCommandId_t* id) {
}
void TestDevice::doTransition(Mode_t modeFrom, Submode_t submodeFrom) {
if (getMode() == _MODE_TO_NORMAL) {
if (mode == _MODE_TO_NORMAL) {
if (fullInfoPrintout) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "TestDevice" << deviceIdx

View File

@ -269,7 +269,7 @@ TEST_CASE("DataSetTest", "[DataSetTest]") {
{
// PoolReadGuard rg(&sharedSet);
// CHECK(rg.getReadResult() == returnvalue::OK);
// CHECK(rg.getReadResult() == result::OK);
localSet.localPoolVarUint8.value = 5;
localSet.localPoolUint16Vec.value[0] = 1;
localSet.localPoolUint16Vec.value[1] = 2;

View File

@ -78,7 +78,7 @@ TEST_CASE("Command Executor", "[hal][linux]") {
REQUIRE(result != CommandExecutor::COMMAND_ERROR);
// This ensures that the tests do not block indefinitely
usleep(500);
REQUIRE(limitIdx < 50000);
REQUIRE(limitIdx < 500);
}
limitIdx = 0;
CHECK(bytesHaveBeenRead == true);

View File

@ -5,7 +5,7 @@
DeviceHandlerMock::DeviceHandlerMock(object_id_t objectId, object_id_t deviceCommunication,
CookieIF *comCookie, FailureIsolationBase *fdirInstance)
: DeviceHandlerBase(objectId, deviceCommunication, comCookie, fdirInstance) {
setMode(MODE_ON);
mode = MODE_ON;
}
DeviceHandlerMock::~DeviceHandlerMock() = default;

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