pool raw access adaptions

This commit is contained in:
Robin Müller 2020-05-17 23:54:56 +02:00
parent 1d28e1398e
commit d1b315c7df
2 changed files with 250 additions and 171 deletions

View File

@ -1,54 +1,76 @@
#include <framework/datapoolglob/GlobalDataPool.h> #include <framework/datapoolglob/GlobalDataPool.h>
#include <framework/datapool/PoolEntryIF.h>
#include <framework/datapool/PoolRawAccess.h> #include <framework/datapool/PoolRawAccess.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h> #include <framework/serviceinterface/ServiceInterfaceStream.h>
#include <framework/osal/Endiness.h> #include <framework/osal/Endiness.h>
PoolRawAccess::PoolRawAccess(uint32_t set_id, uint8_t setArrayEntry, PoolRawAccess::PoolRawAccess(uint32_t set_id, uint8_t setArrayEntry,
DataSetIF* data_set, ReadWriteMode_t setReadWriteMode) : DataSetIF* dataSet, ReadWriteMode_t setReadWriteMode) :
dataPoolId(set_id), arrayEntry(setArrayEntry), valid(false), type(Type::UNKNOWN_TYPE), typeSize( dataPoolId(set_id), arrayEntry(setArrayEntry), valid(false),
0), arraySize(0), sizeTillEnd(0), readWriteMode(setReadWriteMode) { type(Type::UNKNOWN_TYPE), typeSize(0), arraySize(0), sizeTillEnd(0),
readWriteMode(setReadWriteMode) {
memset(value, 0, sizeof(value)); memset(value, 0, sizeof(value));
if (data_set != NULL) { if (dataSet != nullptr) {
data_set->registerVariable(this); dataSet->registerVariable(this);
} }
} }
PoolRawAccess::~PoolRawAccess() { PoolRawAccess::~PoolRawAccess() {}
}
ReturnValue_t PoolRawAccess::read() { ReturnValue_t PoolRawAccess::read() {
PoolEntryIF* read_out = glob::dataPool.getRawData(dataPoolId); ReturnValue_t result = RETURN_FAILED;
if (read_out != NULL) { PoolEntryIF* readOut = glob::dataPool.getRawData(dataPoolId);
valid = read_out->getValid(); if (readOut != nullptr) {
if (read_out->getSize() > arrayEntry) { result = handleReadOut(readOut);
arraySize = read_out->getSize(); if(result == RETURN_OK) {
typeSize = read_out->getByteSize() / read_out->getSize(); return result;
type = read_out->getType(); }
} else {
result = READ_ENTRY_NON_EXISTENT;
}
handleReadError(result);
return result;
}
ReturnValue_t PoolRawAccess::handleReadOut(PoolEntryIF* readOut) {
ReturnValue_t result = RETURN_FAILED;
valid = readOut->getValid();
if (readOut->getSize() > arrayEntry) {
arraySize = readOut->getSize();
typeSize = readOut->getByteSize() / readOut->getSize();
type = readOut->getType();
if (typeSize <= sizeof(value)) { if (typeSize <= sizeof(value)) {
uint16_t arrayPosition = arrayEntry * typeSize; uint16_t arrayPosition = arrayEntry * typeSize;
sizeTillEnd = read_out->getByteSize() - arrayPosition; sizeTillEnd = readOut->getByteSize() - arrayPosition;
uint8_t* ptr = uint8_t* ptr = &((uint8_t*) readOut->getRawData())[arrayPosition];
&((uint8_t*) read_out->getRawData())[arrayPosition];
memcpy(value, ptr, typeSize); memcpy(value, ptr, typeSize);
return HasReturnvaluesIF::RETURN_OK; return RETURN_OK;
} else { } else {
//Error value type too large. result = READ_TYPE_TOO_LARGE;
} }
} else { } else {
//Error index requested too large //debug << "PoolRawAccess: Size: " << (int)read_out->getSize() << std::endl;
result = READ_INDEX_TOO_LARGE;
} }
} else { return result;
//Error entry does not exist.
} }
void PoolRawAccess::handleReadError(ReturnValue_t result) {
sif::error << "PoolRawAccess: read of DP Variable 0x" << std::hex << dataPoolId sif::error << "PoolRawAccess: read of DP Variable 0x" << std::hex << dataPoolId
<< std::dec << " failed." << std::endl; << std::dec << " failed, ";
if(result == READ_TYPE_TOO_LARGE) {
sif::error << "type too large." << std::endl;
}
else if(result == READ_INDEX_TOO_LARGE) {
sif::error << "index too large." << std::endl;
}
else if(result == READ_ENTRY_NON_EXISTENT) {
sif::error << "entry does not exist." << std::endl;
}
valid = INVALID; valid = INVALID;
typeSize = 0; typeSize = 0;
sizeTillEnd = 0; sizeTillEnd = 0;
memset(value, 0, sizeof(value)); memset(value, 0, sizeof(value));
return HasReturnvaluesIF::RETURN_FAILED;
} }
ReturnValue_t PoolRawAccess::commit() { ReturnValue_t PoolRawAccess::commit() {
@ -71,7 +93,9 @@ uint8_t* PoolRawAccess::getEntry() {
ReturnValue_t PoolRawAccess::getEntryEndianSafe(uint8_t* buffer, ReturnValue_t PoolRawAccess::getEntryEndianSafe(uint8_t* buffer,
uint32_t* writtenBytes, uint32_t max_size) { uint32_t* writtenBytes, uint32_t max_size) {
uint8_t* data_ptr = getEntry(); uint8_t* data_ptr = getEntry();
// debug << "PoolRawAccess::getEntry: Array position: " << index * size_of_type << " Size of T: " << (int)size_of_type << " ByteSize: " << byte_size << " Position: " << *size << std::endl; // debug << "PoolRawAccess::getEntry: Array position: " <<
// index * size_of_type << " Size of T: " << (int)size_of_type <<
// " ByteSize: " << byte_size << " Position: " << *size << std::endl;
if (typeSize == 0) if (typeSize == 0)
return DATA_POOL_ACCESS_FAILED; return DATA_POOL_ACCESS_FAILED;
if (typeSize > max_size) if (typeSize > max_size)
@ -89,6 +113,32 @@ ReturnValue_t PoolRawAccess::getEntryEndianSafe(uint8_t* buffer,
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t PoolRawAccess::serialize(uint8_t** buffer, size_t* size,
const size_t max_size, bool bigEndian) const {
if (typeSize + *size <= max_size) {
if (bigEndian) {
#ifndef BYTE_ORDER_SYSTEM
#error BYTE_ORDER_SYSTEM not defined
#elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN
for (uint8_t count = 0; count < typeSize; count++) {
(*buffer)[count] = value[typeSize - count - 1];
}
#elif BYTE_ORDER_SYSTEM == BIG_ENDIAN
memcpy(*buffer, value, typeSize);
#endif
} else {
memcpy(*buffer, value, typeSize);
}
*size += typeSize;
(*buffer) += typeSize;
return HasReturnvaluesIF::RETURN_OK;
} else {
return SerializeIF::BUFFER_TOO_SHORT;
}
}
Type PoolRawAccess::getType() { Type PoolRawAccess::getType() {
return type; return type;
} }
@ -145,29 +195,6 @@ uint16_t PoolRawAccess::getSizeTillEnd() const {
return sizeTillEnd; return sizeTillEnd;
} }
ReturnValue_t PoolRawAccess::serialize(uint8_t** buffer, size_t* size,
const size_t max_size, bool bigEndian) const {
if (typeSize + *size <= max_size) {
if (bigEndian) {
#ifndef BYTE_ORDER_SYSTEM
#error BYTE_ORDER_SYSTEM not defined
#elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN
for (uint8_t count = 0; count < typeSize; count++) {
(*buffer)[count] = value[typeSize - count - 1];
}
#elif BYTE_ORDER_SYSTEM == BIG_ENDIAN
memcpy(*buffer, value, typeSize);
#endif
} else {
memcpy(*buffer, value, typeSize);
}
*size += typeSize;
(*buffer) += typeSize;
return HasReturnvaluesIF::RETURN_OK;
} else {
return SerializeIF::BUFFER_TOO_SHORT;
}
}
size_t PoolRawAccess::getSerializedSize() const { size_t PoolRawAccess::getSerializedSize() const {
return typeSize; return typeSize;
@ -175,8 +202,9 @@ size_t PoolRawAccess::getSerializedSize() const {
ReturnValue_t PoolRawAccess::deSerialize(const uint8_t** buffer, size_t* size, ReturnValue_t PoolRawAccess::deSerialize(const uint8_t** buffer, size_t* size,
bool bigEndian) { bool bigEndian) {
// TODO: Needs to be tested!!!
if (*size >= typeSize) { if (*size >= typeSize) {
*size -= typeSize;
if (bigEndian) { if (bigEndian) {
#ifndef BYTE_ORDER_SYSTEM #ifndef BYTE_ORDER_SYSTEM
#error BYTE_ORDER_SYSTEM not defined #error BYTE_ORDER_SYSTEM not defined
@ -187,12 +215,14 @@ ReturnValue_t PoolRawAccess::deSerialize(const uint8_t** buffer, size_t* size,
#elif BYTE_ORDER_SYSTEM == BIG_ENDIAN #elif BYTE_ORDER_SYSTEM == BIG_ENDIAN
memcpy(value, *buffer, typeSize); memcpy(value, *buffer, typeSize);
#endif #endif
} else { }
else {
memcpy(value, *buffer, typeSize); memcpy(value, *buffer, typeSize);
} }
*buffer += typeSize; *buffer += typeSize;
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} else { }
else {
return SerializeIF::STREAM_TOO_SHORT; return SerializeIF::STREAM_TOO_SHORT;
} }
} }

View File

@ -2,36 +2,187 @@
#define POOLRAWACCESS_H_ #define POOLRAWACCESS_H_
#include <framework/datapool/DataSetIF.h> #include <framework/datapool/DataSetIF.h>
#include <framework/datapool/PoolEntryIF.h>
#include <framework/datapool/PoolVariableIF.h> #include <framework/datapool/PoolVariableIF.h>
#include <framework/globalfunctions/Type.h> #include <framework/globalfunctions/Type.h>
/** /**
* This class allows accessing Data Pool variables as raw bytes. * @brief This class allows accessing Data Pool variables as raw bytes.
* This is necessary to have an access method for HK data, as the PID's alone do not * @details
* provide a type information. * This is necessary to have an access method for HK data, as the PID's alone
* \ingroup data_pool * do not provide type information. Please note that the the raw pool access
* read() and commit() calls are not thread-safe.
*
* Please supply a data set and use the data set read(), commit() calls for
* thread-safe data pool access.
* @ingroup data_pool
*/ */
class PoolRawAccess: public PoolVariableIF { class PoolRawAccess: public PoolVariableIF, HasReturnvaluesIF {
public:
/**
* This constructor is used to access a data pool entry with a
* given ID if the target type is not known. A DataSet object is supplied
* and the data pool entry with the given ID is registered to that data set.
* Please note that a pool raw access buffer only has a buffer
* with a size of double. As such, for vector entries which have
* @param data_pool_id Target data pool entry ID
* @param arrayEntry
* @param data_set Dataset to register data pool entry to
* @param setReadWriteMode
* @param registerVectors If set to true, the constructor checks if
* there are multiple vector entries to registers
* and registers all of them recursively into the data_set
*
*/
PoolRawAccess(uint32_t data_pool_id, uint8_t arrayEntry,
DataSetIF* data_set, ReadWriteMode_t setReadWriteMode =
PoolVariableIF::VAR_READ);
/**
* @brief This operation returns a pointer to the entry fetched.
* @details Return pointer to the buffer containing the raw data
* Size and number of data can be retrieved by other means.
*/
uint8_t* getEntry();
/**
* @brief This operation returns the fetched entry from the data pool and
* flips the bytes, if necessary.
* @details It makes use of the getEntry call of this function, but additionally flips the
* bytes to big endian, which is the default for external communication (as House-
* keeping telemetry). To achieve this, the data is copied directly to the passed
* buffer, if it fits in the given max_size.
* @param buffer A pointer to a buffer to write to
* @param writtenBytes The number of bytes written is returned with this value.
* @param max_size The maximum size that the function may write to buffer.
* @return - @c RETURN_OK if entry could be acquired
* - @c RETURN_FAILED else.
*/
ReturnValue_t getEntryEndianSafe(uint8_t* buffer, uint32_t* size,
uint32_t max_size);
/**
* @brief Serialize raw pool entry into provided buffer directly
* @param buffer Provided buffer. Raw pool data will be copied here
* @param size [out] Increment provided size value by serialized size
* @param max_size Maximum allowed serialization size
* @param bigEndian Specify endianess
* @return - @c RETURN_OK if serialization was successfull
* - @c SerializeIF::BUFFER_TOO_SHORT if range check failed
*/
ReturnValue_t serialize(uint8_t** buffer, size_t* size,
const size_t max_size, bool bigEndian) const;
/**
* With this method, the content can be set from a big endian buffer safely.
* @param buffer Pointer to the data to set
* @param size Size of the data to write. Must fit this->size.
* @return - @c RETURN_OK on success
* - @c RETURN_FAILED on failure
*/
ReturnValue_t setEntryFromBigEndian(const uint8_t* buffer,
uint32_t setSize);
/**
* @brief This operation returns the type of the entry currently stored.
*/
Type getType();
/**
* @brief This operation returns the size of the entry currently stored.
*/
uint8_t getSizeOfType();
/**
*
* @return the size of the datapool array
*/
uint8_t getArraySize();
/**
* @brief This operation returns the data pool id of the variable.
*/
uint32_t getDataPoolId() const;
static const uint8_t INTERFACE_ID = CLASS_ID::POOL_RAW_ACCESS_CLASS;
static const ReturnValue_t INCORRECT_SIZE = MAKE_RETURN_CODE(0x01);
static const ReturnValue_t DATA_POOL_ACCESS_FAILED = MAKE_RETURN_CODE(0x02);
static const ReturnValue_t READ_TYPE_TOO_LARGE = MAKE_RETURN_CODE(0x03);
static const ReturnValue_t READ_INDEX_TOO_LARGE = MAKE_RETURN_CODE(0x04);
static const ReturnValue_t READ_ENTRY_NON_EXISTENT = MAKE_RETURN_CODE(0x05);
static const uint8_t RAW_MAX_SIZE = sizeof(double);
uint8_t value[RAW_MAX_SIZE];
/**
* @brief The classes destructor is empty. If commit() was not called, the local value is
* discarded and not written back to the data pool.
*/
~PoolRawAccess();
/**
* This method returns if the variable is read-write or read-only.
*/
ReadWriteMode_t getReadWriteMode() const;
/**
* @brief With this call, the valid information of the variable is returned.
*/
bool isValid() const;
void setValid(uint8_t valid);
/**
* Getter for the remaining size.
*/
uint16_t getSizeTillEnd() const;
size_t getSerializedSize() const;
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
bool bigEndian);
protected:
/**
* @brief This is a call to read the value from the global data pool.
* @details When executed, this operation tries to fetch the pool entry with matching
* data pool id from the global data pool and copies the value and the valid
* information to its local attributes. In case of a failure (wrong type or
* pool id not found), the variable is set to zero and invalid.
* The operation does NOT provide any mutual exclusive protection by itself !
* If reading from the data pool without information about the type is desired,
* initialize the raw pool access by supplying a data set and using the data set
* read function, which calls this read function.
* @return -@c RETURN_OK Read successfull
* -@c READ_TYPE_TOO_LARGE
* -@c READ_INDEX_TOO_LARGE
* -@c READ_ENTRY_NON_EXISTENT
*/
ReturnValue_t read();
/**
* @brief The commit call writes back the variable's value to the data pool.
* @details It checks type and size, as well as if the variable is writable. If so,
* the value is copied and the valid flag is automatically set to "valid".
* The operation does NOT provide any mutual exclusive protection by itself.
*
*/
ReturnValue_t commit();
ReturnValue_t handleReadOut(PoolEntryIF* read_out);
void handleReadError(ReturnValue_t result);
private: private:
/** /**
* \brief To access the correct data pool entry on read and commit calls, the data pool id * @brief To access the correct data pool entry on read and commit calls, the data pool id
* is stored. * is stored.
*/ */
uint32_t dataPoolId; uint32_t dataPoolId;
/** /**
* \brief The array entry that is fetched from the data pool. * @brief The array entry that is fetched from the data pool.
*/ */
uint8_t arrayEntry; uint8_t arrayEntry;
/** /**
* \brief The valid information as it was stored in the data pool is copied to this attribute. * @brief The valid information as it was stored in the data pool is copied to this attribute.
*/ */
uint8_t valid; uint8_t valid;
/** /**
* \brief This value contains the type of the data pool entry. * @brief This value contains the type of the data pool entry.
*/ */
Type type; Type type;
/** /**
* \brief This value contains the size of the data pool entry in bytes. * @brief This value contains the size of the data pool entry type in bytes.
*/ */
uint8_t typeSize; uint8_t typeSize;
/** /**
@ -43,111 +194,9 @@ private:
*/ */
uint16_t sizeTillEnd; uint16_t sizeTillEnd;
/** /**
* \brief The information whether the class is read-write or read-only is stored here. * @brief The information whether the class is read-write or read-only is stored here.
*/ */
ReadWriteMode_t readWriteMode; ReadWriteMode_t readWriteMode;
static const uint8_t RAW_MAX_SIZE = sizeof(double);
protected:
/**
* \brief This is a call to read the value from the global data pool.
* \details When executed, this operation tries to fetch the pool entry with matching
* data pool id from the global data pool and copies the value and the valid
* information to its local attributes. In case of a failure (wrong type or
* pool id not found), the variable is set to zero and invalid.
* The operation does NOT provide any mutual exclusive protection by itself.
*/
ReturnValue_t read();
/**
* \brief The commit call writes back the variable's value to the data pool.
* \details It checks type and size, as well as if the variable is writable. If so,
* the value is copied and the valid flag is automatically set to "valid".
* The operation does NOT provide any mutual exclusive protection by itself.
*
*/
ReturnValue_t commit();
public:
static const uint8_t INTERFACE_ID = CLASS_ID::POOL_RAW_ACCESS_CLASS;
static const ReturnValue_t INCORRECT_SIZE = MAKE_RETURN_CODE(0x01);
static const ReturnValue_t DATA_POOL_ACCESS_FAILED = MAKE_RETURN_CODE(0x02);
uint8_t value[RAW_MAX_SIZE];
PoolRawAccess(uint32_t data_pool_id, uint8_t arrayEntry,
DataSetIF* data_set, ReadWriteMode_t setReadWriteMode =
PoolVariableIF::VAR_READ);
/**
* \brief The classes destructor is empty. If commit() was not called, the local value is
* discarded and not written back to the data pool.
*/
~PoolRawAccess();
/**
* \brief This operation returns a pointer to the entry fetched.
* \details This means, it does not return a pointer to byte "index", but to the start byte of
* array entry "index". Example: If the original data pool array consists of an double
* array of size four, getEntry(1) returns &(this->value[8]).
*/
uint8_t* getEntry();
/**
* \brief This operation returns the fetched entry from the data pool and
* flips the bytes, if necessary.
* \details It makes use of the getEntry call of this function, but additionally flips the
* bytes to big endian, which is the default for external communication (as House-
* keeping telemetry). To achieve this, the data is copied directly to the passed
* buffer, if it fits in the given max_size.
* \param buffer A pointer to a buffer to write to
* \param writtenBytes The number of bytes written is returned with this value.
* \param max_size The maximum size that the function may write to buffer.
* \return - \c RETURN_OK if entry could be acquired
* - \c RETURN_FAILED else.
*/
ReturnValue_t getEntryEndianSafe(uint8_t* buffer, uint32_t* size,
uint32_t max_size);
/**
* With this method, the content can be set from a big endian buffer safely.
* @param buffer Pointer to the data to set
* @param size Size of the data to write. Must fit this->size.
* @return - \c RETURN_OK on success
* - \c RETURN_FAILED on failure
*/
ReturnValue_t setEntryFromBigEndian(const uint8_t* buffer,
uint32_t setSize);
/**
* \brief This operation returns the type of the entry currently stored.
*/
Type getType();
/**
* \brief This operation returns the size of the entry currently stored.
*/
uint8_t getSizeOfType();
/**
*
* @return the size of the datapool array
*/
uint8_t getArraySize();
/**
* \brief This operation returns the data pool id of the variable.
*/
uint32_t getDataPoolId() const;
/**
* This method returns if the variable is read-write or read-only.
*/
ReadWriteMode_t getReadWriteMode() const;
/**
* \brief With this call, the valid information of the variable is returned.
*/
bool isValid() const;
void setValid(uint8_t valid);
/**
* Getter for the remaining size.
*/
uint16_t getSizeTillEnd() const;
ReturnValue_t serialize(uint8_t** buffer, size_t* size,
const size_t max_size, bool bigEndian) const;
size_t getSerializedSize() const;
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
bool bigEndian);
}; };
#endif /* POOLRAWACCESS_H_ */ #endif /* POOLRAWACCESS_H_ */