diff --git a/src/fsfw/datapool/LocalPoolObjectBase.cpp b/src/fsfw/datapool/LocalPoolObjectBase.cpp index e035a6cc..99d4196e 100644 --- a/src/fsfw/datapool/LocalPoolObjectBase.cpp +++ b/src/fsfw/datapool/LocalPoolObjectBase.cpp @@ -64,6 +64,10 @@ void PoolObjectBase::setReadWriteMode(pool_rwm_t newReadWriteMode) { this->readWriteMode = newReadWriteMode; } +[[nodiscard]] bool PoolObjectBase::isValid() const { return valid; } + +void PoolObjectBase::setValid(bool valid) { this->valid = valid; } + void PoolObjectBase::reportReadCommitError(const char* variableType, ReturnValue_t error, bool read, object_id_t objectId, id_t lpId) { #if FSFW_DISABLE_PRINTOUT == 0 diff --git a/src/fsfw/datapool/LocalPoolObjectBase.h b/src/fsfw/datapool/LocalPoolObjectBase.h index e50a429f..8d667957 100644 --- a/src/fsfw/datapool/LocalPoolObjectBase.h +++ b/src/fsfw/datapool/LocalPoolObjectBase.h @@ -27,6 +27,9 @@ class PoolObjectBase : public PoolVariableIF { [[nodiscard]] dp::id_t getDataPoolId() const override; void setDataPoolId(dp::id_t poolId); + [[nodiscard]] bool isValid() const; + void setValid(bool valid); + protected: /** * @brief To access the correct data pool entry on read and commit calls, @@ -40,6 +43,8 @@ class PoolObjectBase : public PoolVariableIF { */ ReadWriteMode_t readWriteMode = pool_rwm_t::VAR_READ_WRITE; + bool valid = false; + //! @brief Pointer to the class which manages the HK pool. dp::SharedPool* sharedPool = nullptr; @@ -47,4 +52,4 @@ class PoolObjectBase : public PoolVariableIF { object_id_t objectId, dp::id_t lpId); }; -} // namespace datapool \ No newline at end of file +} // namespace datapool diff --git a/src/fsfw/datapool/LocalPoolVector.h b/src/fsfw/datapool/LocalPoolVector.h index aed1731c..8946be64 100644 --- a/src/fsfw/datapool/LocalPoolVector.h +++ b/src/fsfw/datapool/LocalPoolVector.h @@ -216,6 +216,7 @@ class PoolVector : public PoolObjectBase { if (result != returnvalue::OK) { return result; } + this->valid = poolEntry->getValid(); std::memcpy(this->value, poolEntry->getDataPtr(), poolEntry->getByteSize()); return returnvalue::OK; } @@ -237,6 +238,7 @@ class PoolVector : public PoolObjectBase { if (result != returnvalue::OK) { return result; } + poolEntry->setValid(this->valid); std::memcpy(poolEntry->getDataPtr(), this->value, poolEntry->getByteSize()); return returnvalue::OK; } diff --git a/src/fsfw/datapool/PoolDataSetBase.cpp b/src/fsfw/datapool/PoolDataSetBase.cpp index 2996a496..eeecf698 100644 --- a/src/fsfw/datapool/PoolDataSetBase.cpp +++ b/src/fsfw/datapool/PoolDataSetBase.cpp @@ -1,8 +1,10 @@ #include "fsfw/datapool/PoolDataSetBase.h" +#include #include #include "fsfw/datapool/ReadCommitIFAttorney.h" +#include "fsfw/globalfunctions/bitutility.h" #include "fsfw/serviceinterface/ServiceInterface.h" PoolDataSetBase::PoolDataSetBase(PoolVariableIF** registeredVariablesArray, @@ -173,6 +175,51 @@ ReturnValue_t PoolDataSetBase::unlockDataPool() { return returnvalue::OK; } ReturnValue_t PoolDataSetBase::serialize(uint8_t** buffer, size_t* size, const size_t maxSize, SerializeIF::Endianness streamEndianness) const { ReturnValue_t result = returnvalue::FAILED; + const uint8_t validityMaskSize = std::ceil(static_cast(fillCount) / 8.0); + uint8_t* validityPtr = nullptr; +#if defined(_MSC_VER) || defined(__clang__) + // Use a std::vector here because MSVC will (rightly) not create a fixed size array + // with a non constant size specifier. The Apple compiler (LLVM) will not accept + // the initialization of a variable sized array + std::vector validityMask(validityMaskSize, 0); + validityPtr = validityMask.data(); +#else + uint8_t validityMask[validityMaskSize] = {}; + validityPtr = validityMask; +#endif + uint8_t validBufferIndex = 0; + uint8_t validBufferIndexBit = 0; + for (uint16_t count = 0; count < fillCount; count++) { + if (registeredVariables[count]->isValid()) { + /* Set bit at correct position */ + bitutil::set(validityPtr + validBufferIndex, validBufferIndexBit); + } + if (validBufferIndexBit == 7) { + validBufferIndex++; + validBufferIndexBit = 0; + } else { + validBufferIndexBit++; + } + + result = registeredVariables[count]->serialize(buffer, size, maxSize, streamEndianness); + if (result != returnvalue::OK) { + return result; + } + } + + if (*size + validityMaskSize > maxSize) { + return SerializeIF::BUFFER_TOO_SHORT; + } + // copy validity buffer to end + std::memcpy(*buffer, validityPtr, validityMaskSize); + *size += validityMaskSize; + return result; +} + +ReturnValue_t PoolDataSetBase::serializeWithValidityBlob( + uint8_t** buffer, size_t* size, const size_t maxSize, + SerializeIF::Endianness streamEndianness) const { + ReturnValue_t result = returnvalue::FAILED; for (uint16_t count = 0; count < fillCount; count++) { result = registeredVariables[count]->serialize(buffer, size, maxSize, streamEndianness); if (result != returnvalue::OK) { diff --git a/src/fsfw/datapool/PoolDataSetBase.h b/src/fsfw/datapool/PoolDataSetBase.h index b7da7d7d..22f1c9b0 100644 --- a/src/fsfw/datapool/PoolDataSetBase.h +++ b/src/fsfw/datapool/PoolDataSetBase.h @@ -122,6 +122,8 @@ class PoolDataSetBase : public PoolDataSetIF, public SerializeIF { ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, SerializeIF::Endianness streamEndianness) override; + ReturnValue_t serializeWithValidityBlob(uint8_t** buffer, size_t* size, const size_t maxSize, + SerializeIF::Endianness streamEndianness) const; /** * Can be used to individually protect every read and commit call. * @param protectEveryReadCommit diff --git a/src/fsfw/datapool/PoolEntry.cpp b/src/fsfw/datapool/PoolEntry.cpp index 85e265bf..9138a705 100644 --- a/src/fsfw/datapool/PoolEntry.cpp +++ b/src/fsfw/datapool/PoolEntry.cpp @@ -52,6 +52,16 @@ void* PoolEntry::getRawData() { return this->address; } +template +void PoolEntry::setValid(bool isValid) { + this->valid = isValid; +} + +template +bool PoolEntry::getValid() { + return valid; +} + template void PoolEntry::print() { const char* validString = nullptr; diff --git a/src/fsfw/datapool/PoolEntry.h b/src/fsfw/datapool/PoolEntry.h index 2c4cd2e1..aa51e096 100644 --- a/src/fsfw/datapool/PoolEntry.h +++ b/src/fsfw/datapool/PoolEntry.h @@ -105,6 +105,17 @@ class PoolEntry : public PoolEntryIF { */ void* getRawData(); + /** + * @brief This method allows to set the valid information + * of the pool entry. + */ + void setValid(bool isValid) override; + /** + * @brief This method allows to get the valid information + * of the pool entry. + */ + bool getValid() override; + /** * @brief This is a debug method that prints all values and the valid * information to the screen. It prints all array entries in a row. diff --git a/src/fsfw/datapool/PoolEntryIF.h b/src/fsfw/datapool/PoolEntryIF.h index affe68f1..32efe617 100644 --- a/src/fsfw/datapool/PoolEntryIF.h +++ b/src/fsfw/datapool/PoolEntryIF.h @@ -51,6 +51,15 @@ class PoolEntryIF { * Returns the type of the entry. */ virtual Type getType() = 0; + + /** + * @brief This method allows to set the valid information of the pool entry. + */ + virtual void setValid(bool isValid) = 0; + /** + * @brief This method allows to set the valid information of the pool entry. + */ + virtual bool getValid() = 0; }; #endif /* FSFW_DATAPOOL_POOLENTRYIF_H_ */ diff --git a/src/fsfw/datapool/PoolVariableIF.h b/src/fsfw/datapool/PoolVariableIF.h index a5a7ae14..d2ee7c33 100644 --- a/src/fsfw/datapool/PoolVariableIF.h +++ b/src/fsfw/datapool/PoolVariableIF.h @@ -47,6 +47,8 @@ class PoolVariableIF : public SerializeIF, public ReadCommitIF { * @brief This operation shall return the data pool id of the variable. */ virtual uint32_t getDataPoolId() const = 0; + + virtual bool isValid() const = 0; }; using pool_rwm_t = PoolVariableIF::ReadWriteMode_t; diff --git a/src/fsfw/datapool/SharedSetBase.cpp b/src/fsfw/datapool/SharedSetBase.cpp index 36482ec3..26f1ee02 100644 --- a/src/fsfw/datapool/SharedSetBase.cpp +++ b/src/fsfw/datapool/SharedSetBase.cpp @@ -112,6 +112,11 @@ ReturnValue_t SharedSetBase::serialize(uint8_t **buffer, size_t *size, size_t ma return SerializeIF::serialize(buffer, serLen, maxSize, streamEndianness); } +[[nodiscard]] ReturnValue_t SharedSetBase::serializeWithValidityBlob( + uint8_t **buffer, size_t *size, size_t maxSize, Endianness streamEndianness) const { + return base.serializeWithValidityBlob(buffer, size, maxSize, streamEndianness); +} + void SharedSetBase::setReportingEnabled(bool reportingEnabled) { this->reportingEnabled = reportingEnabled; } diff --git a/src/fsfw/datapool/SharedSetBase.h b/src/fsfw/datapool/SharedSetBase.h index 34ebd0f1..afa87e78 100644 --- a/src/fsfw/datapool/SharedSetBase.h +++ b/src/fsfw/datapool/SharedSetBase.h @@ -109,14 +109,18 @@ class SharedSetBase : public SerializeIF, public PoolDataSetIF { */ void setAllVariablesReadOnly(); - [[nodiscard]] ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, - Endianness streamEndianness) const override; + [[nodiscard]] virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, + Endianness streamEndianness) const override; [[nodiscard]] ReturnValue_t serialize(uint8_t* buffer, size_t& serLen, size_t maxSize, SerializeIF::Endianness streamEndianness) const override; - ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, - Endianness streamEndianness) override; + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) override; + + [[nodiscard]] virtual ReturnValue_t serializeWithValidityBlob(uint8_t** buffer, size_t* size, + size_t maxSize, + Endianness streamEndianness) const; [[nodiscard]] dp::sid_t getStructureId() const;