Compare commits

..

1 Commits

Author SHA1 Message Date
a46a66c35a Update and clean up HK and Local Pool Modules 2024-12-12 16:15:31 +01:00
33 changed files with 91 additions and 205 deletions

View File

@ -26,7 +26,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## Added ## Added
- FreeRTOS monotonic clock which is not subjected to time jumps of the system clock
- add CFDP subsystem ID - add CFDP subsystem ID
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/742 https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/742
- `PusTmZcWriter` now exposes API to set message counter field. - `PusTmZcWriter` now exposes API to set message counter field.
@ -35,20 +34,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## Changed ## Changed
- Complete overhaul of HK subsystem. Replaced local data pool manager by periodic HK - Complete refactoring of HK subsystem. Replaced local data pool manager by periodic HK
helper. The shared pool and the periodic HK generation are now distinct concepts. helper. The shared pool and the periodic HK generation are now distinct concepts.
- The local HK manager was replaced by a periodic HK helper which has reduced responsibilities.
It takes care of tracking the HK generation using a set specification provided by the user.n
However, it leaves serialization of the HK data completely to the developer. This removes a major
constraint on the format of the HK data, which was previously constrained to implementors of a
certain base class.
- The former set classes and pool objects are still available for HK set specification and
generation. The API has changed, but the general usage and their architecture has not.
- A new set of set classes and helper objects to specify HK sets and data which does not need to be
shared was added as well. The majority of datasets do not need to be shared anyway.
- The non-shared API retain the capability of appending of a validity blob for each piece of set
data at the end of the HK data. For both non-shared and shared data, this capability can be
specified in the constructor, and defaults to true.
- Improved File System Abstraction to be more in line with normal filesystems. - Improved File System Abstraction to be more in line with normal filesystems.
- CFDP implementation was improved, has now even less dependencies on other FSFW components - CFDP implementation was improved, has now even less dependencies on other FSFW components
and allows one inserted packet per state machine call. and allows one inserted packet per state machine call.

View File

@ -142,7 +142,7 @@ if(FSFW_BUILD_TESTS)
configure_file(unittests/testcfg/TestsConfig.h.in tests/TestsConfig.h) configure_file(unittests/testcfg/TestsConfig.h.in tests/TestsConfig.h)
project(${FSFW_TEST_TGT} CXX C) project(${FSFW_TEST_TGT} CXX C)
add_executable(${FSFW_TEST_TGT}) add_executable(${FSFW_TEST_TGT} unittests/datapool/testDataset.cpp)
if(IPO_SUPPORTED AND FSFW_ENABLE_IPO) if(IPO_SUPPORTED AND FSFW_ENABLE_IPO)
set_property(TARGET ${FSFW_TEST_TGT} PROPERTY INTERPROCEDURAL_OPTIMIZATION set_property(TARGET ${FSFW_TEST_TGT} PROPERTY INTERPROCEDURAL_OPTIMIZATION
TRUE) TRUE)

View File

@ -18,13 +18,13 @@ class MgmRM3100Handler : public DeviceHandlerBase {
static const uint8_t INTERFACE_ID = CLASS_ID::MGM_RM3100; static const uint8_t INTERFACE_ID = CLASS_ID::MGM_RM3100;
//! [EXPORT] : [COMMENT] P1: TMRC value which was set, P2: 0 //! [EXPORT] : [COMMENT] P1: TMRC value which was set, P2: 0
static constexpr Event tmrcSet = event::makeEvent<SUBSYSTEM_ID::MGM_RM3100, 0x00, severity::INFO>(); static constexpr Event tmrcSet = event::makeEvent(SUBSYSTEM_ID::MGM_RM3100, 0x00, severity::INFO);
//! [EXPORT] : [COMMENT] Cycle counter set. P1: First two bytes new Cycle Count X //! [EXPORT] : [COMMENT] Cycle counter set. P1: First two bytes new Cycle Count X
//! P1: Second two bytes new Cycle Count Y //! P1: Second two bytes new Cycle Count Y
//! P2: New cycle count Z //! P2: New cycle count Z
static constexpr Event cycleCountersSet = static constexpr Event cycleCountersSet =
event::makeEvent<SUBSYSTEM_ID::MGM_RM3100, 0x01, severity::INFO>(); event::makeEvent(SUBSYSTEM_ID::MGM_RM3100, 0x01, severity::INFO);
MgmRM3100Handler(object_id_t objectId, object_id_t deviceCommunication, CookieIF *comCookie, MgmRM3100Handler(object_id_t objectId, object_id_t deviceCommunication, CookieIF *comCookie,
uint32_t transitionDelay); uint32_t transitionDelay);

View File

@ -19,13 +19,13 @@ struct FsfwParams {
}; };
namespace events { namespace events {
static constexpr Event PDU_SEND_ERROR = event::makeEvent<SSID, 1, severity::LOW>(); static constexpr Event PDU_SEND_ERROR = event::makeEvent(SSID, 1, severity::LOW);
static constexpr Event SERIALIZATION_ERROR = event::makeEvent<SSID, 2, severity::LOW>(); static constexpr Event SERIALIZATION_ERROR = event::makeEvent(SSID, 2, severity::LOW);
static constexpr Event FILESTORE_ERROR = event::makeEvent<SSID, 3, severity::LOW>(); static constexpr Event FILESTORE_ERROR = event::makeEvent(SSID, 3, severity::LOW);
//! [EXPORT] : [COMMENT] P1: Transaction step ID, P2: 0 for source file name, 1 for dest file name //! [EXPORT] : [COMMENT] P1: Transaction step ID, P2: 0 for source file name, 1 for dest file name
static constexpr Event FILENAME_TOO_LARGE_ERROR = event::makeEvent<SSID, 4, severity::LOW>(); static constexpr Event FILENAME_TOO_LARGE_ERROR = event::makeEvent(SSID, 4, severity::LOW);
//! [EXPORT] : [COMMENT] CFDP request handling failed. P2: Returncode. //! [EXPORT] : [COMMENT] CFDP request handling failed. P2: Returncode.
static constexpr Event HANDLING_CFDP_REQUEST_FAILED = event::makeEvent<SSID, 5, severity::LOW>(); static constexpr Event HANDLING_CFDP_REQUEST_FAILED = event::makeEvent(SSID, 5, severity::LOW);
} // namespace events } // namespace events
static constexpr ReturnValue_t SOURCE_TRANSACTION_PENDING = returnvalue::makeCode(CID, 0); static constexpr ReturnValue_t SOURCE_TRANSACTION_PENDING = returnvalue::makeCode(CID, 0);

View File

@ -34,12 +34,11 @@ class ExtendedControllerBase : public ControllerBase,
ActionHelper actionHelper; ActionHelper actionHelper;
// Periodic HK methods, default method assumes that no shared pool is required. // Periodic HK methods, default method assumes that no shared pool is required.
datapool::SharedPool* getOptionalSharedPool() override = 0; virtual datapool::SharedPool* getOptionalSharedPool() override;
// Periodic HK abstract methods. // Periodic HK abstract methods.
ReturnValue_t serializeHkDataset(dp::sid_t structureId, uint8_t* buf, ReturnValue_t serializeHkDataset(dp::sid_t structureId, uint8_t* buf, size_t maxSize) = 0;
size_t maxSize) override = 0; ReturnValue_t specifyHkDatasets(std::vector<hk::SetSpecification>& setList) = 0;
ReturnValue_t specifyHkDatasets(std::vector<hk::SetSpecification>& setList) override = 0;
/** /**
* Implemented by child class. Handle all command messages which are * Implemented by child class. Handle all command messages which are

View File

@ -48,14 +48,6 @@ PoolObjectBase::PoolObjectBase(object_id_t poolOwner, id_t poolId, DataSetIF* da
return; return;
} }
sharedPool = hkOwner->getOptionalSharedPool(); sharedPool = hkOwner->getOptionalSharedPool();
if (sharedPool == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "PoolObjectBase: HK owner 0x" << std::hex << poolOwner << std::dec
<< "does not have a shared pool " << std::endl;
#else
sif::printError("PoolObjectBase: HK owner 0x%08x does not have a shared pool\n", poolOwner);
#endif
}
if (dataSet != nullptr) { if (dataSet != nullptr) {
dataSet->registerVariable(this); dataSet->registerVariable(this);

View File

@ -9,9 +9,9 @@
PoolDataSetBase::PoolDataSetBase(PoolVariableIF** registeredVariablesArray, PoolDataSetBase::PoolDataSetBase(PoolVariableIF** registeredVariablesArray,
const size_t maxFillCount, bool serializeWithValidityBlob) const size_t maxFillCount, bool serializeWithValidityBlob)
: serializeWithValidityBlob(serializeWithValidityBlob), : registeredVariables(registeredVariablesArray),
registeredVariables(registeredVariablesArray), maxFillCount(maxFillCount),
maxFillCount(maxFillCount) {} serializeWithValidityBlob(serializeWithValidityBlob) {}
PoolDataSetBase::~PoolDataSetBase() = default; PoolDataSetBase::~PoolDataSetBase() = default;
@ -251,9 +251,6 @@ size_t PoolDataSetBase::getSerializedSize() const {
for (uint16_t count = 0; count < fillCount; count++) { for (uint16_t count = 0; count < fillCount; count++) {
size += registeredVariables[count]->getSerializedSize(); size += registeredVariables[count]->getSerializedSize();
} }
if (serializeWithValidityBlob) {
size += std::ceil(static_cast<float>(fillCount) / 8.0);
}
return size; return size;
} }

View File

@ -139,8 +139,6 @@ class PoolDataSetBase : public PoolDataSetIF, public SerializeIF {
*/ */
void setChildrenValidity(bool valid); void setChildrenValidity(bool valid);
bool serializeWithValidityBlob = false;
protected: protected:
/** /**
* @brief The fill_count attribute ensures that the variables * @brief The fill_count attribute ensures that the variables
@ -168,6 +166,7 @@ class PoolDataSetBase : public PoolDataSetIF, public SerializeIF {
*/ */
PoolVariableIF** registeredVariables = nullptr; PoolVariableIF** registeredVariables = nullptr;
const size_t maxFillCount = 0; const size_t maxFillCount = 0;
bool serializeWithValidityBlob = false;
void setContainer(PoolVariableIF** variablesContainer); void setContainer(PoolVariableIF** variablesContainer);
PoolVariableIF** getContainer() const; PoolVariableIF** getContainer() const;

View File

@ -20,9 +20,9 @@ class PoolReadGuard {
if (readResult != returnvalue::OK) { if (readResult != returnvalue::OK) {
#if FSFW_VERBOSE_LEVEL == 1 #if FSFW_VERBOSE_LEVEL == 1
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "PoolReadGuard: Read failed!" << std::endl; sif::error << "PoolReadHelper: Read failed!" << std::endl;
#else #else
sif::printError("PoolReadGuard: Read failed!\n"); sif::printError("PoolReadHelper: Read failed!\n");
#endif /* FSFW_PRINT_VERBOSITY_LEVEL == 1 */ #endif /* FSFW_PRINT_VERBOSITY_LEVEL == 1 */
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
} }

View File

@ -210,7 +210,6 @@ inline ReturnValue_t PoolVariable<T>::readWithoutLock() {
} }
this->value = *(poolEntry->getDataPtr()); this->value = *(poolEntry->getDataPtr());
this->valid = poolEntry->getValid();
return returnvalue::OK; return returnvalue::OK;
} }
@ -242,7 +241,6 @@ ReturnValue_t PoolVariable<T>::commitWithoutLock() {
} }
*(poolEntry->getDataPtr()) = this->value; *(poolEntry->getDataPtr()) = this->value;
poolEntry->setValid(this->valid);
return returnvalue::OK; return returnvalue::OK;
} }

View File

@ -3,7 +3,7 @@
using namespace dp; using namespace dp;
SharedSet::SharedSet(dp::SharedPool& sharedPool, uint32_t setId, const size_t maxNumberOfVariables, SharedSet::SharedSet(dp::SharedPool& sharedPool, uint32_t setId, const size_t maxNumberOfVariables,
bool serializeWithValidityBlob) bool serializeWithValídityBlob)
: SharedSetBase(sharedPool, setId, nullptr, maxNumberOfVariables, serializeWithValidityBlob), : SharedSetBase(sharedPool, setId, nullptr, maxNumberOfVariables, serializeWithValidityBlob),
poolVarList(maxNumberOfVariables) { poolVarList(maxNumberOfVariables) {
this->setContainer(poolVarList.data()); this->setContainer(poolVarList.data());

View File

@ -105,6 +105,9 @@ ReturnValue_t SharedSetBase::deSerialize(const uint8_t **buffer, size_t *size,
ReturnValue_t SharedSetBase::serialize(uint8_t **buffer, size_t *size, size_t maxSize, ReturnValue_t SharedSetBase::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
SerializeIF::Endianness streamEndianness) const { SerializeIF::Endianness streamEndianness) const {
if (serializeWithValidityBlob) {
return base.doSerializeWithValidityBlob(buffer, size, maxSize, streamEndianness);
}
return base.serialize(buffer, size, maxSize, streamEndianness); return base.serialize(buffer, size, maxSize, streamEndianness);
} }
@ -140,17 +143,10 @@ void SharedSetBase::setAllVariablesReadOnly() {
void SharedSetBase::printSet() { return; } void SharedSetBase::printSet() { return; }
ReturnValue_t SharedSetBase::read(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) { ReturnValue_t SharedSetBase::read(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
lockDataPool(timeoutType, timeoutMs); return base.read(timeoutType, timeoutMs);
ReturnValue_t result = base.read(timeoutType, timeoutMs);
unlockDataPool();
return result;
} }
ReturnValue_t SharedSetBase::commit(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) { ReturnValue_t SharedSetBase::commit(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
lockDataPool(timeoutType, timeoutMs); return base.commit(timeoutType, timeoutMs);
ReturnValue_t result = base.commit(timeoutType, timeoutMs);
unlockDataPool();
return result;
} }
uint16_t SharedSetBase::getFillCount() const { return base.getFillCount(); } uint16_t SharedSetBase::getFillCount() const { return base.getFillCount(); }
@ -162,8 +158,3 @@ void SharedSetBase::setContainer(PoolVariableIF **variablesContainer) {
return base.setContainer(variablesContainer); return base.setContainer(variablesContainer);
} }
PoolVariableIF **SharedSetBase::getContainer() const { return base.getContainer(); } PoolVariableIF **SharedSetBase::getContainer() const { return base.getContainer(); }
void SharedSetBase::updateValidityBlobSerialization(bool enable) {
base.serializeWithValidityBlob = enable;
}
bool SharedSetBase::getValidityBlobSerialization() const { return base.serializeWithValidityBlob; }

View File

@ -159,8 +159,11 @@ class SharedSetBase : public SerializeIF, public PoolDataSetIF {
*/ */
void setChildrenValidity(bool valid); void setChildrenValidity(bool valid);
void updateValidityBlobSerialization(bool enable); /**
bool getValidityBlobSerialization() const; * If the valid state of a dataset is always relevant to the whole
* data set we can use this flag.
*/
bool serializeWithValidityBlob = false;
protected: protected:
PoolDataSetBase base; PoolDataSetBase base;

View File

@ -190,6 +190,4 @@ ReturnValue_t FreshDeviceHandlerBase::getParameter(uint8_t domainId, uint8_t uni
return INVALID_DOMAIN_ID; return INVALID_DOMAIN_ID;
} }
datapool::SharedPool* FreshDeviceHandlerBase::getOptionalSharedPool() { return nullptr; } datapool::SharedPool* FreshDeviceHandlerBase::getOptionalSharedPool() { return nullptr; }
ModeHelper& FreshDeviceHandlerBase::getModeHelper() { return this->modeHelper; }

View File

@ -97,11 +97,6 @@ class FreshDeviceHandlerBase : public SystemObject,
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF& parent) override; ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF& parent) override;
ModeTreeChildIF& getModeTreeChildIF() override; ModeTreeChildIF& getModeTreeChildIF() override;
/**
* @brief Return an interface to the ModeHelper.
*/
ModeHelper& getModeHelper();
protected: protected:
ActionHelper actionHelper; ActionHelper actionHelper;
ModeHelper modeHelper; ModeHelper modeHelper;
@ -153,24 +148,20 @@ class FreshDeviceHandlerBase : public SystemObject,
// System Object overrides. // System Object overrides.
ReturnValue_t initialize() override; ReturnValue_t initialize() override;
// Default implementation assumes that no optional shared pool is required.
datapool::SharedPool* getOptionalSharedPool() override;
/** /**
* This function is implemented to serialize a housekeeping packet when a HK message to * This function is implemented to serialize a housekeeping packet when a HK message to
* generate the packet is received, or periodic generation is necessary. The user should serialize * generate the packet is received, or periodic generation is necessary. The user should serialize the HK
* the HK set into the provided buffer, which will have the size specified in the set * set into the provided buffer, which will have the size specified in the set specification.
* specification.
*/
ReturnValue_t serializeHkDataset(dp::sid_t structureId, uint8_t* buf,
size_t maxSize) override = 0;
/**
* This function is implemented by the user to specify the available housekeeping sets.
*/ */
ReturnValue_t serializeHkDataset(dp::sid_t structureId, uint8_t* buf, size_t maxSize) override = 0;
/**
* This function is implemented by the user to specify the available housekeeping sets.
*/
ReturnValue_t specifyHkDatasets(std::vector<hk::SetSpecification>& setList) override = 0; ReturnValue_t specifyHkDatasets(std::vector<hk::SetSpecification>& setList) override = 0;
/*
* If this device handler has an optional pool, return it. Otherwise, nullptr can be returned.
*/
datapool::SharedPool* getOptionalSharedPool() override = 0;
/** /**
* Implemented by child class. Handle all command messages which are * Implemented by child class. Handle all command messages which are
* not health, mode, action or housekeeping messages. * not health, mode, action or housekeeping messages.
@ -211,6 +202,7 @@ class FreshDeviceHandlerBase : public SystemObject,
* @return * @return
*/ */
virtual ReturnValue_t performOperation(uint8_t opCode) override; virtual ReturnValue_t performOperation(uint8_t opCode) override;
ReturnValue_t initializeAfterTaskCreation() override;
/** /**
* This calls the FDIR instance event trigger function. * This calls the FDIR instance event trigger function.

View File

@ -14,6 +14,8 @@ enum Severity : EventSeverity_t { INFO = 1, LOW = 2, MEDIUM = 3, HIGH = 4 };
} // namespace severity } // namespace severity
#define MAKE_EVENT(id, severity) (((severity) << 16) + (SUBSYSTEM_ID * 100) + (id))
typedef uint32_t Event; typedef uint32_t Event;
namespace event { namespace event {
@ -22,14 +24,11 @@ constexpr EventId_t getEventId(Event event) { return (event & 0xFFFF); }
constexpr EventSeverity_t getSeverity(Event event) { return ((event >> 16) & 0xFF); } constexpr EventSeverity_t getSeverity(Event event) { return ((event >> 16) & 0xFF); }
template<uint8_t subsystemId, UniqueEventId_t uniqueEventId, EventSeverity_t eventSeverity> constexpr Event makeEvent(uint8_t subsystemId, UniqueEventId_t uniqueEventId,
constexpr Event makeEvent() { EventSeverity_t eventSeverity) {
static_assert(uniqueEventId < 100, "The unique event ID must be smaller than 100!");
return (eventSeverity << 16) + (subsystemId * 100) + uniqueEventId; return (eventSeverity << 16) + (subsystemId * 100) + uniqueEventId;
} }
} // namespace event } // namespace event
#define MAKE_EVENT(id, severity) event::makeEvent<SUBSYSTEM_ID, id, severity>();
#endif /* EVENTOBJECT_EVENT_H_ */ #endif /* EVENTOBJECT_EVENT_H_ */

View File

@ -1,4 +1,9 @@
#pragma once #ifndef FSFW_INC_FSFW_HOUSEKEEPING_H_
#define FSFW_INC_FSFW_HOUSEKEEPING_H_
#include "fsfw/housekeeping/Dataset.h" #include "src/core/housekeeping/HousekeepingMessage.h"
#include "fsfw/housekeeping/DatasetElement.h" #include "src/core/housekeeping/HousekeepingPacketDownlink.h"
#include "src/core/housekeeping/HousekeepingSetPacket.h"
#include "src/core/housekeeping/HousekeepingSnapshot.h"
#endif /* FSFW_INC_FSFW_HOUSEKEEPING_H_ */

View File

@ -17,6 +17,12 @@ class Dataset : public SerializeIF {
[[nodiscard]] dp::structure_id_t getStructureId() const { return sid; } [[nodiscard]] dp::structure_id_t getStructureId() const { return sid; }
void setAllChildrenValidity(bool valid) {
for (auto &serializable : serializables) {
serializable.get().setValid(valid);
}
}
void addSerializable(const std::reference_wrapper<SerializableWithValidityIF> serializable) { void addSerializable(const std::reference_wrapper<SerializableWithValidityIF> serializable) {
serializables.push_back(serializable); serializables.push_back(serializable);
} }
@ -89,20 +95,11 @@ class Dataset : public SerializeIF {
return SerializeIF::serialize(buffer, serSize, maxSize, streamEndianness); return SerializeIF::serialize(buffer, serSize, maxSize, streamEndianness);
} }
void setChildrenValidity(bool valid) {
for (auto &serializable : serializables) {
serializable.get().setValid(valid);
}
}
[[nodiscard]] size_t getSerializedSize() const override { [[nodiscard]] size_t getSerializedSize() const override {
size_t size = 0; size_t size = 0;
for (auto &serializable : serializables) { for (auto &serializable : serializables) {
size += serializable.get().getSerializedSize(); size += serializable.get().getSerializedSize();
} }
if (serializeWithValidityBlob) {
size += std::ceil(static_cast<float>(serializables.size()) / 8.0);
}
return size; return size;
} }

View File

@ -17,7 +17,7 @@ PeriodicHelper::PeriodicHelper(GeneratesPeriodicHkIF* owner, MessageQueueIF* que
MessageQueueId_t hkDestQueue) MessageQueueId_t hkDestQueue)
: hkDestinationId(hkDestQueue) { : hkDestinationId(hkDestQueue) {
if (owner == nullptr) { if (owner == nullptr) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "PeriodicHkHelper", returnvalue::FAILED, printWarningOrError(sif::OutputTypes::OUT_WARNING, "LocalDataPoolManager", returnvalue::FAILED,
"Invalid supplied owner"); "Invalid supplied owner");
return; return;
} }
@ -200,10 +200,11 @@ void PeriodicHelper::performPeriodicHkGeneration(SetSpecification& setSpec, time
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
// Configuration error // Configuration error
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "hk::PeriodicHelper::performPeriodicHkOperation: HK generation failed." sif::warning << "LocalDataPoolManager::performPeriodicHkOperation: HK generation failed."
<< std::endl; << std::endl;
#else #else
sif::printWarning("hk::PeriodicHelper::performPeriodicHkOperation: HK generation failed.\n"); sif::printWarning(
"LocalDataPoolManager::performPeriodicHkOperation: HK generation failed.\n");
#endif #endif
return; return;
} }

View File

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

View File

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

View File

@ -5,7 +5,6 @@
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "fsfw/globalfunctions/timevalOperations.h" #include "fsfw/globalfunctions/timevalOperations.h"
#include "fsfw/serviceinterface/ServiceInterfacePrinter.h"
#include "fsfw/osal/freertos/Timekeeper.h" #include "fsfw/osal/freertos/Timekeeper.h"
#include "task.h" #include "task.h"
@ -48,8 +47,8 @@ ReturnValue_t Clock::getClock(timeval* time) {
} }
ReturnValue_t Clock::getClockMonotonic(timeval* time) { ReturnValue_t Clock::getClockMonotonic(timeval* time) {
*time = Timekeeper::instance()->getMonotonicClockOffset() + getUptime(); // TODO: I don't actually know if the timekeeper is monotonic..
return returnvalue::OK; return getClock_timeval(time);
} }
ReturnValue_t Clock::getUptime(timeval* uptime) { ReturnValue_t Clock::getUptime(timeval* uptime) {
@ -59,7 +58,7 @@ ReturnValue_t Clock::getUptime(timeval* uptime) {
} }
timeval Clock::getUptime() { timeval Clock::getUptime() {
TickType_t ticksSinceStart = Timekeeper::instance()->getTicks(); TickType_t ticksSinceStart = xTaskGetTickCount();
return Timekeeper::ticksToTimeval(ticksSinceStart); return Timekeeper::ticksToTimeval(ticksSinceStart);
} }

View File

@ -17,13 +17,7 @@ Timekeeper* Timekeeper::instance() {
return myinstance; return myinstance;
} }
void Timekeeper::setOffset(const timeval& offset) { void Timekeeper::setOffset(const timeval& offset) { this->offset = offset; }
if (not monotonicClockInitialized) {
this->monotonicClockOffset = offset;
monotonicClockInitialized = true;
}
this->offset = offset;
}
timeval Timekeeper::ticksToTimeval(TickType_t ticks) { timeval Timekeeper::ticksToTimeval(TickType_t ticks) {
timeval uptime; timeval uptime;
@ -39,7 +33,3 @@ timeval Timekeeper::ticksToTimeval(TickType_t ticks) {
} }
TickType_t Timekeeper::getTicks() { return xTaskGetTickCount(); } TickType_t Timekeeper::getTicks() { return xTaskGetTickCount(); }
const timeval Timekeeper::getMonotonicClockOffset() const {
return monotonicClockOffset;
}

View File

@ -18,14 +18,9 @@ class Timekeeper {
Timekeeper(); Timekeeper();
timeval offset; timeval offset;
// Set when offset is initialized the first time
timeval monotonicClockOffset;
bool monotonicClockInitialized = false;
static Timekeeper* myinstance; static Timekeeper* myinstance;
void setMonotonicClockOffset(const timeval& monotonicClockOffset);
public: public:
static Timekeeper* instance(); static Timekeeper* instance();
virtual ~Timekeeper(); virtual ~Timekeeper();
@ -39,7 +34,6 @@ class Timekeeper {
const timeval& getOffset() const; const timeval& getOffset() const;
void setOffset(const timeval& offset); void setOffset(const timeval& offset);
const timeval getMonotonicClockOffset() const;
}; };
#endif /* FRAMEWORK_OSAL_FREERTOS_TIMEKEEPER_H_ */ #endif /* FRAMEWORK_OSAL_FREERTOS_TIMEKEEPER_H_ */

View File

@ -49,7 +49,7 @@ class Service11TelecommandScheduling final : public PusServiceBase {
//! [EXPORT] : [COMMENT] Deletion of a TC from the map failed. //! [EXPORT] : [COMMENT] Deletion of a TC from the map failed.
//! P1: First 32 bit of request ID, P2. Last 32 bit of Request ID //! P1: First 32 bit of request ID, P2. Last 32 bit of Request ID
static constexpr Event TC_DELETION_FAILED = event::makeEvent<SUBSYSTEM_ID, 0, severity::MEDIUM>(); static constexpr Event TC_DELETION_FAILED = event::makeEvent(SUBSYSTEM_ID, 0, severity::MEDIUM);
// The types of PUS-11 subservices // The types of PUS-11 subservices
enum Subservice : uint8_t { enum Subservice : uint8_t {

View File

@ -53,17 +53,17 @@ void fsfwPrint(sif::PrintLevel printType, const char *fmt, va_list arg) {
#endif #endif
if (printType == sif::PrintLevel::INFO_LEVEL) { if (printType == sif::PrintLevel::INFO_LEVEL) {
len += sprintf(bufferPosition + len, "INFO "); len += sprintf(bufferPosition + len, "INFO");
} }
if (printType == sif::PrintLevel::DEBUG_LEVEL) { if (printType == sif::PrintLevel::DEBUG_LEVEL) {
len += sprintf(bufferPosition + len, "DEBUG "); len += sprintf(bufferPosition + len, "DEBUG");
} }
if (printType == sif::PrintLevel::WARNING_LEVEL) { if (printType == sif::PrintLevel::WARNING_LEVEL) {
len += sprintf(bufferPosition + len, "WARNING"); len += sprintf(bufferPosition + len, "WARNING");
} }
if (printType == sif::PrintLevel::ERROR_LEVEL) { if (printType == sif::PrintLevel::ERROR_LEVEL) {
len += sprintf(bufferPosition + len, "ERROR "); len += sprintf(bufferPosition + len, "ERROR");
} }
#if FSFW_COLORED_OUTPUT == 1 #if FSFW_COLORED_OUTPUT == 1
@ -75,7 +75,7 @@ void fsfwPrint(sif::PrintLevel printType, const char *fmt, va_list arg) {
/* /*
* Log current time to terminal if desired. * Log current time to terminal if desired.
*/ */
len += sprintf(bufferPosition + len, " | %02lu:%02lu:%02lu.%03lu | ", (unsigned long)now.hour, len += sprintf(bufferPosition + len, " | %lu:%02lu:%02lu.%03lu | ", (unsigned long)now.hour,
(unsigned long)now.minute, (unsigned long)now.second, (unsigned long)now.minute, (unsigned long)now.second,
(unsigned long)now.usecond / 1000); (unsigned long)now.usecond / 1000);

View File

@ -64,11 +64,6 @@ void SubsystemBase::executeTable(HybridIterator<ModeListEntry> tableIter, Submod
for (; tableIter.value != nullptr; ++tableIter) { for (; tableIter.value != nullptr; ++tableIter) {
object_id_t object = tableIter.value->getObject(); object_id_t object = tableIter.value->getObject();
// As default, the objectId in the commandTable is the same as the one in the childrenMap.
// The user has to specify otherwise if required.
object = commandObjectIdToChildrenMapObjectId(object);
if ((iter = childrenMap.find(object)) == childrenMap.end()) { if ((iter = childrenMap.find(object)) == childrenMap.end()) {
// illegal table entry, should only happen due to misconfigured mode table // illegal table entry, should only happen due to misconfigured mode table
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
@ -84,36 +79,22 @@ void SubsystemBase::executeTable(HybridIterator<ModeListEntry> tableIter, Submod
} }
if (healthHelper.healthTable->hasHealth(object)) { if (healthHelper.healthTable->hasHealth(object)) {
if (healthHelper.healthTable->isFaulty(object)) {
switch (healthHelper.healthTable->getHealth(object)) { ModeMessage::setModeMessage(&command, ModeMessage::CMD_MODE_COMMAND, HasModesIF::MODE_OFF,
case NEEDS_RECOVERY: SUBMODE_NONE);
case FAULTY: } else {
case PERMANENT_FAULTY: if (modeHelper.isForced()) {
ModeMessage::setModeMessage(&command, ModeMessage::CMD_MODE_COMMAND, HasModesIF::MODE_OFF, ModeMessage::setModeMessage(&command, ModeMessage::CMD_MODE_COMMAND_FORCED,
SUBMODE_NONE); tableIter.value->getMode(), submodeToCommand);
break; } else {
case HEALTHY: if (healthHelper.healthTable->isCommandable(object)) {
if (modeHelper.isForced()) {
ModeMessage::setModeMessage(&command, ModeMessage::CMD_MODE_COMMAND_FORCED,
tableIter.value->getMode(), submodeToCommand);
} else {
ModeMessage::setModeMessage(&command, ModeMessage::CMD_MODE_COMMAND, ModeMessage::setModeMessage(&command, ModeMessage::CMD_MODE_COMMAND,
tableIter.value->getMode(), submodeToCommand); tableIter.value->getMode(), submodeToCommand);
}
break;
case EXTERNAL_CONTROL:
if (modeHelper.isForced()) {
ModeMessage::setModeMessage(&command, ModeMessage::CMD_MODE_COMMAND_FORCED,
tableIter.value->getMode(), submodeToCommand);
} else { } else {
continue; continue;
} }
break; }
default:
// This never happens
break;
} }
} else { } else {
ModeMessage::setModeMessage(&command, ModeMessage::CMD_MODE_COMMAND, ModeMessage::setModeMessage(&command, ModeMessage::CMD_MODE_COMMAND,
tableIter.value->getMode(), submodeToCommand); tableIter.value->getMode(), submodeToCommand);
@ -124,11 +105,7 @@ void SubsystemBase::executeTable(HybridIterator<ModeListEntry> tableIter, Submod
continue; // don't send redundant mode commands (produces event spam), but still command if continue; // don't send redundant mode commands (produces event spam), but still command if
// mode is forced to reach lower levels // mode is forced to reach lower levels
} }
ReturnValue_t result = commandQueue->sendMessage(iter->second.commandQueue, &command);
// Get the messageQueueId if the receiver specified by the commandTable.
// This the same MessageQueueId as stored in the childrenMap if the commanded object is part of the childrenMap.
MessageQueueId_t commandedReceiver = ObjectManager::instance()->get<HasHealthIF>(tableIter->getObject())->getCommandQueue();
ReturnValue_t result = commandQueue->sendMessage(commandedReceiver, &command);
if (result == returnvalue::OK) { if (result == returnvalue::OK) {
++commandsOutstanding; ++commandsOutstanding;
} }
@ -362,7 +339,3 @@ ReturnValue_t SubsystemBase::registerChild(object_id_t childObjectId, MessageQue
} }
return returnvalue::OK; return returnvalue::OK;
} }
object_id_t SubsystemBase::commandObjectIdToChildrenMapObjectId(object_id_t commandId) {
return commandId;
}

View File

@ -153,15 +153,6 @@ class SubsystemBase : public SystemObject,
virtual void announceMode(bool recursive) override; virtual void announceMode(bool recursive) override;
virtual void modeChanged(); virtual void modeChanged();
/**
* @brief This converts the objectId of the object we want to send a mode command to into the
* objectId of the corresponding object in the childrenMap for the current mode command.
* As default implementation, this is the same objectId, and this functions returns it's input value
*
* It is up to the user to specify otherwise.
*/
virtual object_id_t commandObjectIdToChildrenMapObjectId(object_id_t commandId);
}; };
#endif /* FSFW_SUBSYSTEM_SUBSYSTEMBASE_H_ */ #endif /* FSFW_SUBSYSTEM_SUBSYSTEMBASE_H_ */

View File

@ -25,7 +25,7 @@ static constexpr ReturnValue_t INCORRECT_SECONDARY_HEADER = MAKE_RETURN_CODE(11)
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::TMTC_DISTRIBUTION; static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::TMTC_DISTRIBUTION;
//! P1: Returnvalue, P2: 0 for TM issues, 1 for TC issues //! P1: Returnvalue, P2: 0 for TM issues, 1 for TC issues
static constexpr Event HANDLE_PACKET_FAILED = event::makeEvent<SUBSYSTEM_ID, 0, severity::LOW>(); static constexpr Event HANDLE_PACKET_FAILED = event::makeEvent(SUBSYSTEM_ID, 0, severity::LOW);
}; // namespace tmtcdistrib }; // namespace tmtcdistrib
#endif // FSFW_TMTCPACKET_DEFINITIONS_H #endif // FSFW_TMTCPACKET_DEFINITIONS_H

View File

@ -142,7 +142,7 @@ class TemperatureSensor : public AbstractTemperatureSensor {
deltaTime = (uptime.tv_sec + uptime.tv_usec / 1000000.) - deltaTime = (uptime.tv_sec + uptime.tv_usec / 1000000.) -
(uptimeOfOldTemperature.tv_sec + uptimeOfOldTemperature.tv_usec / 1000000.); (uptimeOfOldTemperature.tv_sec + uptimeOfOldTemperature.tv_usec / 1000000.);
deltaTemp = oldTemperature - outputTemperature.value; deltaTemp = oldTemperature - outputTemperature;
if (deltaTemp < 0) { if (deltaTemp < 0) {
deltaTemp = -deltaTemp; deltaTemp = -deltaTemp;
} }
@ -160,13 +160,13 @@ class TemperatureSensor : public AbstractTemperatureSensor {
outputTemperature.setValid(PoolVariableIF::INVALID); outputTemperature.setValid(PoolVariableIF::INVALID);
outputTemperature = thermal::INVALID_TEMPERATURE; outputTemperature = thermal::INVALID_TEMPERATURE;
} else { } else {
oldTemperature = outputTemperature.value; oldTemperature = outputTemperature;
uptimeOfOldTemperature = uptime; uptimeOfOldTemperature = uptime;
} }
} }
public: public:
float getTemperature() { return outputTemperature.value; } float getTemperature() { return outputTemperature; }
bool isValid() { return outputTemperature.isValid(); } bool isValid() { return outputTemperature.isValid(); }

View File

@ -192,8 +192,6 @@ class Clock {
static MutexIF *timeMutex; static MutexIF *timeMutex;
static uint16_t leapSeconds; static uint16_t leapSeconds;
static bool leapSecondsSet; static bool leapSecondsSet;
static bool monotonicClockInitialized;
static timeval monotonicClockOffset;
}; };
#endif /* FSFW_TIMEMANAGER_CLOCK_H_ */ #endif /* FSFW_TIMEMANAGER_CLOCK_H_ */

View File

@ -62,7 +62,6 @@ TEST_CASE("Pool Dataset Test", "[datapool]") {
size_t serLen = 0; size_t serLen = 0;
uint8_t* dataPtr = buf; uint8_t* dataPtr = buf;
dataset.serializeWithValidityBlob = true; dataset.serializeWithValidityBlob = true;
CHECK(dataset.getSerializedSize() == 6);
CHECK(dataset.serialize(&dataPtr, &serLen, sizeof(buf), SerializeIF::Endianness::NETWORK) == CHECK(dataset.serialize(&dataPtr, &serLen, sizeof(buf), SerializeIF::Endianness::NETWORK) ==
returnvalue::OK); returnvalue::OK);
CHECK(buf[5] == 0b11000000); CHECK(buf[5] == 0b11000000);
@ -71,7 +70,7 @@ TEST_CASE("Pool Dataset Test", "[datapool]") {
SECTION("Larger Pool Dataset Serialization With Validity") { SECTION("Larger Pool Dataset Serialization With Validity") {
uint8_t buf[64]{}; uint8_t buf[64]{};
TestDatasetLarger datasetLarge; TestDatasetLarger datasetLarge;
datasetLarge.setChildrenValidity(true); datasetLarge.setAllChildrenValidity(true);
size_t serLen = 0; size_t serLen = 0;
uint8_t* dataPtr = buf; uint8_t* dataPtr = buf;
datasetLarge.serializeWithValidityBlob = true; datasetLarge.serializeWithValidityBlob = true;

View File

@ -23,7 +23,6 @@ TEST_CASE("DataSetTest", "[datapool]") {
SECTION("BasicTest") { SECTION("BasicTest") {
/* Test some basic functions */ /* Test some basic functions */
CHECK(localSet.getReportingEnabled() == false); CHECK(localSet.getReportingEnabled() == false);
CHECK(localSet.getSerializedSize() == 11);
CHECK(localSet.getLocalPoolIdsSerializedSize() == 3 * sizeof(dp::id_t)); CHECK(localSet.getLocalPoolIdsSerializedSize() == 3 * sizeof(dp::id_t));
CHECK(localSet.getStructureId() == lpool::testSid1); CHECK(localSet.getStructureId() == lpool::testSid1);
CHECK(localSet.getCreatorObjectId() == objects::TEST_LOCAL_POOL_OWNER_BASE); CHECK(localSet.getCreatorObjectId() == objects::TEST_LOCAL_POOL_OWNER_BASE);
@ -157,7 +156,7 @@ TEST_CASE("DataSetTest", "[datapool]") {
} }
SECTION("Serialize with Validity Blob") { SECTION("Serialize with Validity Blob") {
localSet.updateValidityBlobSerialization(true); localSet.serializeWithValidityBlob = true;
CHECK(!localSet.localPoolVarUint8.isValid()); CHECK(!localSet.localPoolVarUint8.isValid());
CHECK(!localSet.localPoolUint16Vec.isValid()); CHECK(!localSet.localPoolUint16Vec.isValid());
CHECK(!localSet.localPoolVarFloat.isValid()); CHECK(!localSet.localPoolVarFloat.isValid());
@ -169,7 +168,6 @@ TEST_CASE("DataSetTest", "[datapool]") {
// Already reserve additional space for validity buffer, will be needed later // Already reserve additional space for validity buffer, will be needed later
uint8_t buffer[128]{}; uint8_t buffer[128]{};
uint8_t* buffPtr = buffer; uint8_t* buffPtr = buffer;
CHECK(localSet.getSerializedSize() == 12);
CHECK(localSet.serialize(&buffPtr, &serSize, sizeof(buffer), CHECK(localSet.serialize(&buffPtr, &serSize, sizeof(buffer),
SerializeIF::Endianness::MACHINE) == returnvalue::OK); SerializeIF::Endianness::MACHINE) == returnvalue::OK);
CHECK(serSize == 12); CHECK(serSize == 12);