Compare commits
3 Commits
refactor-p
...
7795fecfcb
Author | SHA1 | Date | |
---|---|---|---|
7795fecfcb | |||
9361af02c4
|
|||
842a3b1b03 |
14
CHANGELOG.md
14
CHANGELOG.md
@ -34,8 +34,20 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## Changed
|
||||
|
||||
- Complete refactoring of HK subsystem. Replaced local data pool manager by periodic HK
|
||||
- Complete overhaul of HK subsystem. Replaced local data pool manager by periodic HK
|
||||
helper. The shared pool and the periodic HK generation are now distinct concepts.
|
||||
- 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.
|
||||
- CFDP implementation was improved, has now even less dependencies on other FSFW components
|
||||
and allows one inserted packet per state machine call.
|
||||
|
@ -142,7 +142,7 @@ if(FSFW_BUILD_TESTS)
|
||||
configure_file(unittests/testcfg/TestsConfig.h.in tests/TestsConfig.h)
|
||||
|
||||
project(${FSFW_TEST_TGT} CXX C)
|
||||
add_executable(${FSFW_TEST_TGT} unittests/datapool/testDataset.cpp)
|
||||
add_executable(${FSFW_TEST_TGT})
|
||||
if(IPO_SUPPORTED AND FSFW_ENABLE_IPO)
|
||||
set_property(TARGET ${FSFW_TEST_TGT} PROPERTY INTERPROCEDURAL_OPTIMIZATION
|
||||
TRUE)
|
||||
|
@ -34,11 +34,12 @@ class ExtendedControllerBase : public ControllerBase,
|
||||
ActionHelper actionHelper;
|
||||
|
||||
// Periodic HK methods, default method assumes that no shared pool is required.
|
||||
virtual datapool::SharedPool* getOptionalSharedPool() override;
|
||||
datapool::SharedPool* getOptionalSharedPool() override = 0;
|
||||
|
||||
// Periodic HK abstract methods.
|
||||
ReturnValue_t serializeHkDataset(dp::sid_t structureId, uint8_t* buf, size_t maxSize) = 0;
|
||||
ReturnValue_t specifyHkDatasets(std::vector<hk::SetSpecification>& setList) = 0;
|
||||
ReturnValue_t serializeHkDataset(dp::sid_t structureId, uint8_t* buf,
|
||||
size_t maxSize) override = 0;
|
||||
ReturnValue_t specifyHkDatasets(std::vector<hk::SetSpecification>& setList) override = 0;
|
||||
|
||||
/**
|
||||
* Implemented by child class. Handle all command messages which are
|
||||
|
@ -48,6 +48,14 @@ PoolObjectBase::PoolObjectBase(object_id_t poolOwner, id_t poolId, DataSetIF* da
|
||||
return;
|
||||
}
|
||||
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) {
|
||||
dataSet->registerVariable(this);
|
||||
|
@ -9,9 +9,9 @@
|
||||
|
||||
PoolDataSetBase::PoolDataSetBase(PoolVariableIF** registeredVariablesArray,
|
||||
const size_t maxFillCount, bool serializeWithValidityBlob)
|
||||
: registeredVariables(registeredVariablesArray),
|
||||
maxFillCount(maxFillCount),
|
||||
serializeWithValidityBlob(serializeWithValidityBlob) {}
|
||||
: serializeWithValidityBlob(serializeWithValidityBlob),
|
||||
registeredVariables(registeredVariablesArray),
|
||||
maxFillCount(maxFillCount) {}
|
||||
|
||||
PoolDataSetBase::~PoolDataSetBase() = default;
|
||||
|
||||
@ -251,6 +251,9 @@ size_t PoolDataSetBase::getSerializedSize() const {
|
||||
for (uint16_t count = 0; count < fillCount; count++) {
|
||||
size += registeredVariables[count]->getSerializedSize();
|
||||
}
|
||||
if (serializeWithValidityBlob) {
|
||||
size += std::ceil(static_cast<float>(fillCount) / 8.0);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
|
@ -139,6 +139,8 @@ class PoolDataSetBase : public PoolDataSetIF, public SerializeIF {
|
||||
*/
|
||||
void setChildrenValidity(bool valid);
|
||||
|
||||
bool serializeWithValidityBlob = false;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief The fill_count attribute ensures that the variables
|
||||
@ -166,7 +168,6 @@ class PoolDataSetBase : public PoolDataSetIF, public SerializeIF {
|
||||
*/
|
||||
PoolVariableIF** registeredVariables = nullptr;
|
||||
const size_t maxFillCount = 0;
|
||||
bool serializeWithValidityBlob = false;
|
||||
|
||||
void setContainer(PoolVariableIF** variablesContainer);
|
||||
PoolVariableIF** getContainer() const;
|
||||
|
@ -20,9 +20,9 @@ class PoolReadGuard {
|
||||
if (readResult != returnvalue::OK) {
|
||||
#if FSFW_VERBOSE_LEVEL == 1
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "PoolReadHelper: Read failed!" << std::endl;
|
||||
sif::error << "PoolReadGuard: Read failed!" << std::endl;
|
||||
#else
|
||||
sif::printError("PoolReadHelper: Read failed!\n");
|
||||
sif::printError("PoolReadGuard: Read failed!\n");
|
||||
#endif /* FSFW_PRINT_VERBOSITY_LEVEL == 1 */
|
||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
using namespace dp;
|
||||
|
||||
SharedSet::SharedSet(dp::SharedPool& sharedPool, uint32_t setId, const size_t maxNumberOfVariables,
|
||||
bool serializeWithValídityBlob)
|
||||
bool serializeWithValidityBlob)
|
||||
: SharedSetBase(sharedPool, setId, nullptr, maxNumberOfVariables, serializeWithValidityBlob),
|
||||
poolVarList(maxNumberOfVariables) {
|
||||
this->setContainer(poolVarList.data());
|
||||
|
@ -105,9 +105,6 @@ ReturnValue_t SharedSetBase::deSerialize(const uint8_t **buffer, size_t *size,
|
||||
|
||||
ReturnValue_t SharedSetBase::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||
SerializeIF::Endianness streamEndianness) const {
|
||||
if (serializeWithValidityBlob) {
|
||||
return base.doSerializeWithValidityBlob(buffer, size, maxSize, streamEndianness);
|
||||
}
|
||||
return base.serialize(buffer, size, maxSize, streamEndianness);
|
||||
}
|
||||
|
||||
@ -143,10 +140,17 @@ void SharedSetBase::setAllVariablesReadOnly() {
|
||||
void SharedSetBase::printSet() { return; }
|
||||
|
||||
ReturnValue_t SharedSetBase::read(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
|
||||
return base.read(timeoutType, timeoutMs);
|
||||
lockDataPool(timeoutType, timeoutMs);
|
||||
ReturnValue_t result = base.read(timeoutType, timeoutMs);
|
||||
unlockDataPool();
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t SharedSetBase::commit(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
|
||||
return base.commit(timeoutType, timeoutMs);
|
||||
lockDataPool(timeoutType, timeoutMs);
|
||||
ReturnValue_t result = base.commit(timeoutType, timeoutMs);
|
||||
unlockDataPool();
|
||||
return result;
|
||||
}
|
||||
uint16_t SharedSetBase::getFillCount() const { return base.getFillCount(); }
|
||||
|
||||
@ -158,3 +162,8 @@ void SharedSetBase::setContainer(PoolVariableIF **variablesContainer) {
|
||||
return base.setContainer(variablesContainer);
|
||||
}
|
||||
PoolVariableIF **SharedSetBase::getContainer() const { return base.getContainer(); }
|
||||
|
||||
void SharedSetBase::updateValidityBlobSerialization(bool enable) {
|
||||
base.serializeWithValidityBlob = enable;
|
||||
}
|
||||
bool SharedSetBase::getValidityBlobSerialization() const { return base.serializeWithValidityBlob; }
|
||||
|
@ -159,11 +159,8 @@ class SharedSetBase : public SerializeIF, public PoolDataSetIF {
|
||||
*/
|
||||
void setChildrenValidity(bool valid);
|
||||
|
||||
/**
|
||||
* If the valid state of a dataset is always relevant to the whole
|
||||
* data set we can use this flag.
|
||||
*/
|
||||
bool serializeWithValidityBlob = false;
|
||||
void updateValidityBlobSerialization(bool enable);
|
||||
bool getValidityBlobSerialization() const;
|
||||
|
||||
protected:
|
||||
PoolDataSetBase base;
|
||||
|
@ -148,20 +148,24 @@ class FreshDeviceHandlerBase : public SystemObject,
|
||||
// System Object overrides.
|
||||
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
|
||||
* generate the packet is received, or periodic generation is necessary. The user should serialize the HK
|
||||
* set into the provided buffer, which will have the size specified in the set specification.
|
||||
* generate the packet is received, or periodic generation is necessary. The user should serialize
|
||||
* the HK set into the provided buffer, which will have the size specified in the set
|
||||
* 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;
|
||||
|
||||
/*
|
||||
* 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
|
||||
* not health, mode, action or housekeeping messages.
|
||||
@ -202,7 +206,6 @@ class FreshDeviceHandlerBase : public SystemObject,
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t performOperation(uint8_t opCode) override;
|
||||
ReturnValue_t initializeAfterTaskCreation() override;
|
||||
|
||||
/**
|
||||
* This calls the FDIR instance event trigger function.
|
||||
|
@ -1,9 +1,4 @@
|
||||
#ifndef FSFW_INC_FSFW_HOUSEKEEPING_H_
|
||||
#define FSFW_INC_FSFW_HOUSEKEEPING_H_
|
||||
#pragma once
|
||||
|
||||
#include "src/core/housekeeping/HousekeepingMessage.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_ */
|
||||
#include "fsfw/housekeeping/Dataset.h"
|
||||
#include "fsfw/housekeeping/DatasetElement.h"
|
@ -17,12 +17,6 @@ class Dataset : public SerializeIF {
|
||||
|
||||
[[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) {
|
||||
serializables.push_back(serializable);
|
||||
}
|
||||
@ -95,11 +89,20 @@ class Dataset : public SerializeIF {
|
||||
return SerializeIF::serialize(buffer, serSize, maxSize, streamEndianness);
|
||||
}
|
||||
|
||||
void setChildrenValidity(bool valid) {
|
||||
for (auto &serializable : serializables) {
|
||||
serializable.get().setValid(true);
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] size_t getSerializedSize() const override {
|
||||
size_t size = 0;
|
||||
for (auto &serializable : serializables) {
|
||||
size += serializable.get().getSerializedSize();
|
||||
}
|
||||
if (serializeWithValidityBlob) {
|
||||
size += std::ceil(static_cast<float>(serializables.size()) / 8.0);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ PeriodicHelper::PeriodicHelper(GeneratesPeriodicHkIF* owner, MessageQueueIF* que
|
||||
MessageQueueId_t hkDestQueue)
|
||||
: hkDestinationId(hkDestQueue) {
|
||||
if (owner == nullptr) {
|
||||
printWarningOrError(sif::OutputTypes::OUT_WARNING, "LocalDataPoolManager", returnvalue::FAILED,
|
||||
printWarningOrError(sif::OutputTypes::OUT_WARNING, "PeriodicHkHelper", returnvalue::FAILED,
|
||||
"Invalid supplied owner");
|
||||
return;
|
||||
}
|
||||
@ -200,11 +200,10 @@ void PeriodicHelper::performPeriodicHkGeneration(SetSpecification& setSpec, time
|
||||
if (result != returnvalue::OK) {
|
||||
// Configuration error
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "LocalDataPoolManager::performPeriodicHkOperation: HK generation failed."
|
||||
sif::warning << "hk::PeriodicHelper::performPeriodicHkOperation: HK generation failed."
|
||||
<< std::endl;
|
||||
#else
|
||||
sif::printWarning(
|
||||
"LocalDataPoolManager::performPeriodicHkOperation: HK generation failed.\n");
|
||||
sif::printWarning("hk::PeriodicHelper::performPeriodicHkOperation: HK generation failed.\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
@ -62,6 +62,7 @@ TEST_CASE("Pool Dataset Test", "[datapool]") {
|
||||
size_t serLen = 0;
|
||||
uint8_t* dataPtr = buf;
|
||||
dataset.serializeWithValidityBlob = true;
|
||||
CHECK(dataset.getSerializedSize() == 6);
|
||||
CHECK(dataset.serialize(&dataPtr, &serLen, sizeof(buf), SerializeIF::Endianness::NETWORK) ==
|
||||
returnvalue::OK);
|
||||
CHECK(buf[5] == 0b11000000);
|
||||
@ -70,7 +71,7 @@ TEST_CASE("Pool Dataset Test", "[datapool]") {
|
||||
SECTION("Larger Pool Dataset Serialization With Validity") {
|
||||
uint8_t buf[64]{};
|
||||
TestDatasetLarger datasetLarge;
|
||||
datasetLarge.setAllChildrenValidity(true);
|
||||
datasetLarge.setChildrenValidity(true);
|
||||
size_t serLen = 0;
|
||||
uint8_t* dataPtr = buf;
|
||||
datasetLarge.serializeWithValidityBlob = true;
|
||||
|
@ -23,6 +23,7 @@ TEST_CASE("DataSetTest", "[datapool]") {
|
||||
SECTION("BasicTest") {
|
||||
/* Test some basic functions */
|
||||
CHECK(localSet.getReportingEnabled() == false);
|
||||
CHECK(localSet.getSerializedSize() == 11);
|
||||
CHECK(localSet.getLocalPoolIdsSerializedSize() == 3 * sizeof(dp::id_t));
|
||||
CHECK(localSet.getStructureId() == lpool::testSid1);
|
||||
CHECK(localSet.getCreatorObjectId() == objects::TEST_LOCAL_POOL_OWNER_BASE);
|
||||
@ -156,7 +157,7 @@ TEST_CASE("DataSetTest", "[datapool]") {
|
||||
}
|
||||
|
||||
SECTION("Serialize with Validity Blob") {
|
||||
localSet.serializeWithValidityBlob = true;
|
||||
localSet.updateValidityBlobSerialization(true);
|
||||
CHECK(!localSet.localPoolVarUint8.isValid());
|
||||
CHECK(!localSet.localPoolUint16Vec.isValid());
|
||||
CHECK(!localSet.localPoolVarFloat.isValid());
|
||||
@ -168,6 +169,7 @@ TEST_CASE("DataSetTest", "[datapool]") {
|
||||
// Already reserve additional space for validity buffer, will be needed later
|
||||
uint8_t buffer[128]{};
|
||||
uint8_t* buffPtr = buffer;
|
||||
CHECK(localSet.getSerializedSize() == 12);
|
||||
CHECK(localSet.serialize(&buffPtr, &serSize, sizeof(buffer),
|
||||
SerializeIF::Endianness::MACHINE) == returnvalue::OK);
|
||||
CHECK(serSize == 12);
|
||||
|
Reference in New Issue
Block a user